From e4454320b3cfffe926a487c33fbeb454366de2f8 Mon Sep 17 00:00:00 2001 From: Shih-wei Liao Date: Wed, 7 Apr 2010 12:21:42 -0700 Subject: libbcc Change-Id: Ieaa3ebd5a38f370752495549f8870b534eeedfc5 --- Android.mk | 39 + CMakeLists.txt | 1 + CREDITS.TXT | 5 + Makefile | 13 +- Makefile.config.in | 42 +- Makefile.rules | 127 +- README.txt | 3 +- Xcode/LLVM.xcodeproj/project.pbxproj | 3303 ------- Xcode/README.txt | 1 - autoconf/ExportMap.map | 3 + autoconf/configure.ac | 110 +- autoconf/m4/huge_val.m4 | 2 + bindings/ocaml/bitreader/bitreader_ocaml.c | 9 +- bindings/ocaml/bitreader/llvm_bitreader.ml | 5 +- bindings/ocaml/bitreader/llvm_bitreader.mli | 14 +- bindings/ocaml/bitwriter/bitwriter_ocaml.c | 15 + bindings/ocaml/bitwriter/llvm_bitwriter.ml | 7 + bindings/ocaml/bitwriter/llvm_bitwriter.mli | 12 + .../ocaml/executionengine/executionengine_ocaml.c | 49 +- .../ocaml/executionengine/llvm_executionengine.ml | 20 +- .../ocaml/executionengine/llvm_executionengine.mli | 109 +- bindings/ocaml/llvm/llvm.ml | 137 +- bindings/ocaml/llvm/llvm.mli | 355 +- bindings/ocaml/llvm/llvm_ocaml.c | 298 +- .../ocaml/transforms/scalar/llvm_scalar_opts.ml | 59 +- .../ocaml/transforms/scalar/llvm_scalar_opts.mli | 91 +- .../ocaml/transforms/scalar/scalar_opts_ocaml.c | 96 +- clear_tblgen_vars.mk | 2 + configure | 176 +- device/include/llvm/Config/AsmParsers.def | 29 + device/include/llvm/Config/AsmPrinters.def | 29 + device/include/llvm/Config/Disassemblers.def | 27 + device/include/llvm/Config/Targets.def | 28 + device/include/llvm/Config/config.h | 586 ++ docs/AliasAnalysis.html | 25 +- docs/BitCodeFormat.html | 2 +- docs/Bugpoint.html | 2 +- docs/CodeGenerator.html | 8 +- docs/CodingStandards.html | 6 +- docs/CommandGuide/FileCheck.pod | 2 +- docs/CommandGuide/Makefile | 6 +- docs/CommandGuide/bugpoint.pod | 6 +- docs/CommandGuide/index.html | 4 +- docs/CommandGuide/llc.pod | 4 +- docs/CommandGuide/lli.pod | 6 +- docs/CommandGuide/llvm-as.pod | 2 +- docs/CommandGuide/llvm-bcanalyzer.pod | 2 +- docs/CommandGuide/llvm-config.pod | 2 +- docs/CommandGuide/llvm-db.pod | 16 - docs/CommandGuide/llvm-dis.pod | 2 +- docs/CommandGuide/llvm-extract.pod | 10 +- docs/CommandGuide/llvm-link.pod | 2 +- docs/CommandGuide/llvm-nm.pod | 2 +- docs/CommandGuide/llvm-prof.pod | 2 +- docs/CommandGuide/llvm-ranlib.pod | 4 +- docs/CommandGuide/llvmc.pod | 4 +- docs/CommandGuide/tblgen.pod | 2 +- docs/CommandLine.html | 72 +- docs/CompilerDriver.html | 8 +- docs/CompilerWriterInfo.html | 2 +- docs/DeveloperPolicy.html | 4 +- docs/ExceptionHandling.html | 2 +- docs/ExtendingLLVM.html | 2 +- docs/FAQ.html | 4 +- docs/GCCFEBuildInstrs.html | 2 +- docs/GarbageCollection.html | 2 +- docs/GetElementPtr.html | 407 +- docs/GettingStarted.html | 28 +- docs/GettingStartedVS.html | 2 +- docs/HowToReleaseLLVM.html | 2 +- docs/HowToSubmitABug.html | 2 +- docs/LangRef.html | 254 +- docs/Lexicon.html | 2 +- docs/LinkTimeOptimization.html | 2 +- docs/Makefile | 24 +- docs/MakefileGuide.html | 6 +- docs/Packaging.html | 118 + docs/Passes.html | 77 +- docs/ProgrammersManual.html | 10 +- docs/Projects.html | 2 +- docs/ReleaseNotes.html | 16 +- docs/SourceLevelDebugging.html | 2 +- docs/SystemLibrary.html | 2 +- docs/TableGenFundamentals.html | 5 +- docs/TestingGuide.html | 27 +- docs/UsingLibraries.html | 2 +- docs/WritingAnLLVMBackend.html | 2 +- docs/WritingAnLLVMPass.html | 16 +- docs/index.html | 6 +- docs/tutorial/LangImpl1.html | 2 +- docs/tutorial/LangImpl2.html | 2 +- docs/tutorial/LangImpl3.html | 44 +- docs/tutorial/LangImpl4.html | 38 +- docs/tutorial/LangImpl5.html | 12 +- docs/tutorial/LangImpl6.html | 10 +- docs/tutorial/LangImpl7.html | 28 +- docs/tutorial/LangImpl8.html | 2 +- docs/tutorial/Makefile | 2 +- docs/tutorial/OCamlLangImpl1.html | 2 +- docs/tutorial/OCamlLangImpl2.html | 2 +- docs/tutorial/OCamlLangImpl3.html | 34 +- docs/tutorial/OCamlLangImpl4.html | 28 +- docs/tutorial/OCamlLangImpl5.html | 4 +- docs/tutorial/OCamlLangImpl6.html | 2 +- docs/tutorial/OCamlLangImpl7.html | 20 +- examples/Kaleidoscope/Chapter4/Makefile | 2 +- examples/Kaleidoscope/Chapter4/toy.cpp | 8 +- examples/Kaleidoscope/Chapter5/Makefile | 2 +- examples/Kaleidoscope/Chapter5/toy.cpp | 8 +- examples/Kaleidoscope/Chapter6/Makefile | 2 +- examples/Kaleidoscope/Chapter6/toy.cpp | 8 +- examples/Kaleidoscope/Chapter7/Makefile | 2 +- examples/Kaleidoscope/Chapter7/toy.cpp | 8 +- examples/Makefile | 7 +- host/include/llvm/Config/AsmParsers.def | 29 + host/include/llvm/Config/AsmPrinters.def | 29 + host/include/llvm/Config/Disassemblers.def | 29 + host/include/llvm/Config/Targets.def | 28 + host/include/llvm/Config/config.h | 583 ++ include/llvm-c/BitReader.h | 22 +- include/llvm-c/BitWriter.h | 13 +- include/llvm-c/Core.h | 206 +- include/llvm-c/ExecutionEngine.h | 23 + include/llvm/ADT/APFloat.h | 34 +- include/llvm/ADT/APInt.h | 28 + include/llvm/ADT/DeltaAlgorithm.h | 2 +- include/llvm/ADT/EquivalenceClasses.h | 2 +- include/llvm/ADT/ScopedHashTable.h | 69 +- include/llvm/ADT/SmallPtrSet.h | 2 +- include/llvm/ADT/StringRef.h | 16 +- include/llvm/ADT/Triple.h | 1 + include/llvm/Analysis/DebugInfo.h | 11 +- include/llvm/Analysis/Dominators.h | 48 +- include/llvm/Analysis/IVUsers.h | 110 +- include/llvm/Analysis/LoopInfo.h | 2 +- include/llvm/Analysis/MemoryDependenceAnalysis.h | 7 +- include/llvm/Analysis/PHITransAddr.h | 18 +- include/llvm/Analysis/Passes.h | 7 - include/llvm/Analysis/PostDominators.h | 4 + include/llvm/Analysis/ScalarEvolution.h | 23 +- include/llvm/Analysis/ScalarEvolutionExpander.h | 11 +- include/llvm/Analysis/ScalarEvolutionExpressions.h | 4 + include/llvm/Analysis/ValueTracking.h | 4 + include/llvm/Assembly/AsmAnnotationWriter.h | 21 +- include/llvm/Attributes.h | 29 +- include/llvm/Bitcode/LLVMBitCodes.h | 3 +- include/llvm/CodeGen/AsmPrinter.h | 9 +- include/llvm/CodeGen/DAGISelHeader.h | 135 - include/llvm/CodeGen/JITCodeEmitter.h | 2 +- include/llvm/CodeGen/LiveInterval.h | 12 +- include/llvm/CodeGen/LiveIntervalAnalysis.h | 14 +- include/llvm/CodeGen/LiveVariables.h | 11 + include/llvm/CodeGen/MachineBasicBlock.h | 5 - include/llvm/CodeGen/MachineCodeEmitter.h | 2 +- include/llvm/CodeGen/MachineFrameInfo.h | 16 +- include/llvm/CodeGen/MachineInstr.h | 49 +- include/llvm/CodeGen/MachineInstrBuilder.h | 2 +- include/llvm/CodeGen/MachineMemOperand.h | 11 +- include/llvm/CodeGen/MachineModuleInfo.h | 7 + include/llvm/CodeGen/MachineModuleInfoImpls.h | 35 +- include/llvm/CodeGen/MachineOperand.h | 11 +- include/llvm/CodeGen/MachineRegisterInfo.h | 8 + include/llvm/CodeGen/ObjectCodeEmitter.h | 2 +- include/llvm/CodeGen/Passes.h | 10 +- include/llvm/CodeGen/SelectionDAG.h | 51 +- include/llvm/CodeGen/SelectionDAGISel.h | 196 +- include/llvm/CodeGen/SelectionDAGNodes.h | 36 +- .../llvm/CodeGen/TargetLoweringObjectFileImpl.h | 207 + include/llvm/CompilerDriver/Common.td | 8 +- include/llvm/CompilerDriver/Main.inc | 2 +- include/llvm/CompilerDriver/Tool.h | 9 +- include/llvm/Constants.h | 56 +- include/llvm/DerivedTypes.h | 62 +- include/llvm/GlobalValue.h | 82 +- include/llvm/InstrTypes.h | 54 +- include/llvm/Instructions.h | 20 +- include/llvm/LinkAllPasses.h | 1 - include/llvm/MC/MCAssembler.h | 216 +- include/llvm/MC/MCCodeEmitter.h | 2 +- include/llvm/MC/MCContext.h | 10 +- include/llvm/MC/MCDirectives.h | 42 +- include/llvm/MC/MCExpr.h | 2 +- include/llvm/MC/MCFixup.h | 12 + include/llvm/MC/MCInstPrinter.h | 6 +- include/llvm/MC/MCStreamer.h | 48 +- include/llvm/Metadata.h | 7 +- include/llvm/Pass.h | 12 +- include/llvm/Support/CommandLine.h | 16 +- include/llvm/Support/Compiler.h | 4 +- include/llvm/Support/Dwarf.h | 1 - include/llvm/Support/FormattedStream.h | 4 +- include/llvm/Support/IRBuilder.h | 6 +- include/llvm/Support/Regex.h | 13 + include/llvm/Support/SourceMgr.h | 2 +- include/llvm/Support/TargetFolder.h | 4 +- include/llvm/System/DataTypes.h | 111 + include/llvm/System/Path.h | 2 +- include/llvm/Target/Mangler.h | 2 +- include/llvm/Target/Target.td | 7 - include/llvm/Target/TargetAsmBackend.h | 35 + include/llvm/Target/TargetAsmParser.h | 4 +- include/llvm/Target/TargetInstrInfo.h | 28 +- include/llvm/Target/TargetLowering.h | 11 +- include/llvm/Target/TargetLoweringObjectFile.h | 182 +- include/llvm/Target/TargetMachine.h | 43 +- include/llvm/Target/TargetOpcodes.h | 4 +- include/llvm/Target/TargetRegisterInfo.h | 11 + include/llvm/Target/TargetRegistry.h | 205 +- include/llvm/Target/TargetSelectionDAG.td | 3 +- include/llvm/Transforms/Scalar.h | 2 +- include/llvm/Transforms/Utils/BasicBlockUtils.h | 6 + include/llvm/Transforms/Utils/BuildLibCalls.h | 96 + include/llvm/Type.h | 78 +- include/llvm/Value.h | 1 + lib/Analysis/AliasAnalysisCounter.cpp | 2 +- lib/Analysis/AliasAnalysisEvaluator.cpp | 6 +- lib/Analysis/Android.mk | 69 + lib/Analysis/BasicAliasAnalysis.cpp | 4 +- lib/Analysis/CaptureTracking.cpp | 2 +- lib/Analysis/ConstantFolding.cpp | 57 +- lib/Analysis/DebugInfo.cpp | 9 +- lib/Analysis/IPA/Andersens.cpp | 2868 ------ lib/Analysis/IPA/CMakeLists.txt | 1 - lib/Analysis/IPA/GlobalsModRef.cpp | 4 +- lib/Analysis/IVUsers.cpp | 206 +- lib/Analysis/InlineCost.cpp | 4 +- lib/Analysis/InstructionSimplify.cpp | 33 +- lib/Analysis/MemoryDependenceAnalysis.cpp | 15 +- lib/Analysis/PHITransAddr.cpp | 60 +- lib/Analysis/PointerTracking.cpp | 2 +- lib/Analysis/ProfileInfo.cpp | 8 +- lib/Analysis/ScalarEvolution.cpp | 241 +- lib/Analysis/ScalarEvolutionAliasAnalysis.cpp | 8 +- lib/Analysis/ScalarEvolutionExpander.cpp | 400 +- lib/Analysis/ValueTracking.cpp | 153 +- lib/AsmParser/Android.mk | 28 + lib/AsmParser/LLLexer.cpp | 1 + lib/AsmParser/LLParser.cpp | 192 +- lib/AsmParser/LLParser.h | 5 + lib/AsmParser/LLToken.h | 1 + lib/Bitcode/Reader/Android.mk | 29 + lib/Bitcode/Reader/BitReader.cpp | 63 +- lib/Bitcode/Reader/BitcodeReader.cpp | 34 +- lib/Bitcode/Writer/BitWriter.cpp | 14 +- lib/Bitcode/Writer/BitcodeWriter.cpp | 61 +- lib/Bitcode/Writer/ValueEnumerator.cpp | 5 +- lib/CodeGen/Android.mk | 99 + lib/CodeGen/AsmPrinter/Android.mk | 31 + lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 43 +- lib/CodeGen/AsmPrinter/DIE.cpp | 1 + lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 17 +- lib/CodeGen/AsmPrinter/DwarfException.cpp | 232 +- lib/CodeGen/AsmPrinter/DwarfException.h | 5 +- lib/CodeGen/AsmPrinter/DwarfPrinter.cpp | 77 +- lib/CodeGen/AsmPrinter/DwarfPrinter.h | 12 +- lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp | 1 + lib/CodeGen/BranchFolding.cpp | 6 +- lib/CodeGen/CMakeLists.txt | 3 + lib/CodeGen/CalcSpillWeights.cpp | 5 +- lib/CodeGen/CodePlacementOpt.cpp | 17 +- lib/CodeGen/CriticalAntiDepBreaker.cpp | 4 + lib/CodeGen/DeadMachineInstructionElim.cpp | 42 +- lib/CodeGen/IntrinsicLowering.cpp | 4 +- lib/CodeGen/LLVMTargetMachine.cpp | 51 +- lib/CodeGen/LiveIntervalAnalysis.cpp | 142 +- lib/CodeGen/LiveVariables.cpp | 43 +- lib/CodeGen/MachineBasicBlock.cpp | 30 - lib/CodeGen/MachineCSE.cpp | 268 + lib/CodeGen/MachineFunction.cpp | 3 + lib/CodeGen/MachineInstr.cpp | 90 +- lib/CodeGen/MachineLICM.cpp | 45 +- lib/CodeGen/MachineModuleInfoImpls.cpp | 11 +- lib/CodeGen/MachineRegisterInfo.cpp | 13 + lib/CodeGen/MachineSink.cpp | 16 +- lib/CodeGen/OptimizePHIs.cpp | 189 + lib/CodeGen/PBQP/HeuristicSolver.h | 29 +- lib/CodeGen/PBQP/Heuristics/Briggs.h | 9 +- lib/CodeGen/PHIElimination.cpp | 41 +- lib/CodeGen/PHIElimination.h | 72 +- lib/CodeGen/Passes.cpp | 2 +- lib/CodeGen/PostRASchedulerList.cpp | 2 + lib/CodeGen/ProcessImplicitDefs.cpp | 5 +- lib/CodeGen/PrologEpilogInserter.cpp | 22 +- lib/CodeGen/PseudoSourceValue.cpp | 37 +- lib/CodeGen/RegAllocLinearScan.cpp | 4 - lib/CodeGen/RegAllocLocal.cpp | 33 +- lib/CodeGen/RegAllocPBQP.cpp | 6 +- lib/CodeGen/ScheduleDAGInstrs.cpp | 4 +- lib/CodeGen/SelectionDAG/Android.mk | 48 + lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 178 +- lib/CodeGen/SelectionDAG/FastISel.cpp | 28 + lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 51 + lib/CodeGen/SelectionDAG/InstrEmitter.h | 11 + lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 204 +- lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp | 17 +- lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 39 +- lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 8 +- lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp | 19 +- lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 154 +- lib/CodeGen/SelectionDAG/SDDbgValue.h | 67 + lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 16 +- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 320 +- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 171 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 1361 ++- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 72 +- lib/CodeGen/SimpleRegisterCoalescing.cpp | 68 +- lib/CodeGen/SjLjEHPrepare.cpp | 67 +- lib/CodeGen/StackProtector.cpp | 2 +- lib/CodeGen/TailDuplication.cpp | 33 +- lib/CodeGen/TargetInstrInfoImpl.cpp | 36 +- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 902 ++ lib/CodeGen/TwoAddressInstructionPass.cpp | 20 +- lib/CodeGen/VirtRegMap.cpp | 6 +- lib/CodeGen/VirtRegRewriter.cpp | 33 +- lib/CompilerDriver/Action.cpp | 15 +- lib/CompilerDriver/CompilationGraph.cpp | 5 +- lib/CompilerDriver/Main.cpp | 7 +- lib/CompilerDriver/Tool.cpp | 21 + lib/ExecutionEngine/ExecutionEngine.cpp | 12 +- lib/ExecutionEngine/ExecutionEngineBindings.cpp | 77 +- lib/ExecutionEngine/Interpreter/Execution.cpp | 28 +- lib/ExecutionEngine/JIT/Android.mk | 32 + lib/ExecutionEngine/JIT/JIT.cpp | 75 +- lib/ExecutionEngine/JIT/JIT.h | 4 + lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp | 6 +- lib/ExecutionEngine/JIT/JITEmitter.cpp | 444 +- lib/Linker/LinkModules.cpp | 2 +- lib/MC/Android.mk | 45 + lib/MC/CMakeLists.txt | 1 + lib/MC/MCAsmStreamer.cpp | 21 +- lib/MC/MCAssembler.cpp | 386 +- lib/MC/MCCodeEmitter.cpp | 12 + lib/MC/MCInstPrinter.cpp | 7 + lib/MC/MCMachOStreamer.cpp | 49 +- lib/MC/MCNullStreamer.cpp | 3 + lib/MC/MCParser/AsmParser.cpp | 38 +- lib/MC/MCSectionMachO.cpp | 1 + lib/MC/TargetAsmBackend.cpp | 19 + lib/Support/APFloat.cpp | 88 +- lib/Support/APInt.cpp | 10 +- lib/Support/Android.mk | 72 + lib/Support/CommandLine.cpp | 14 +- lib/Support/FormattedStream.cpp | 5 +- lib/Support/GraphWriter.cpp | 2 +- lib/Support/MemoryBuffer.cpp | 3 +- lib/Support/Regex.cpp | 76 + lib/Support/StringRef.cpp | 105 +- lib/Support/Triple.cpp | 9 + lib/Support/raw_ostream.cpp | 19 +- lib/System/Android.mk | 46 + lib/System/Unix/Host.inc | 1 + lib/System/Unix/Program.inc | 2 +- lib/System/Unix/Signals.inc | 11 +- lib/Target/ARM/ARMBaseInstrInfo.cpp | 24 +- lib/Target/ARM/ARMBaseInstrInfo.h | 6 +- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 119 +- lib/Target/ARM/ARMBaseRegisterInfo.h | 1 + lib/Target/ARM/ARMCodeEmitter.cpp | 101 +- lib/Target/ARM/ARMISelDAGToDAG.cpp | 7 +- lib/Target/ARM/ARMISelLowering.cpp | 188 +- lib/Target/ARM/ARMISelLowering.h | 6 +- lib/Target/ARM/ARMInstrFormats.td | 86 +- lib/Target/ARM/ARMInstrInfo.td | 1056 ++- lib/Target/ARM/ARMInstrNEON.td | 803 +- lib/Target/ARM/ARMInstrThumb.td | 128 +- lib/Target/ARM/ARMInstrThumb2.td | 818 +- lib/Target/ARM/ARMInstrVFP.td | 97 +- lib/Target/ARM/ARMJITInfo.cpp | 24 +- lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 18 +- lib/Target/ARM/ARMRelocations.h | 8 +- lib/Target/ARM/ARMSubtarget.cpp | 40 +- lib/Target/ARM/ARMSubtarget.h | 4 +- lib/Target/ARM/ARMTargetObjectFile.h | 4 +- lib/Target/ARM/Android.mk | 49 + lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp | 9 +- lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp | 6 + lib/Target/ARM/AsmPrinter/ARMInstPrinter.h | 1 + lib/Target/ARM/README.txt | 2 + lib/Target/ARM/TargetInfo/Android.mk | 24 + lib/Target/ARM/Thumb1RegisterInfo.cpp | 28 +- lib/Target/Alpha/AlphaCallingConv.td | 3 +- lib/Target/Alpha/AlphaISelDAGToDAG.cpp | 17 +- lib/Target/Alpha/AlphaISelLowering.cpp | 45 +- lib/Target/Alpha/AlphaInstrInfo.td | 6 +- lib/Target/Alpha/AlphaRegisterInfo.cpp | 7 +- lib/Target/Android.mk | 38 + lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp | 10 +- lib/Target/Blackfin/BlackfinISelLowering.cpp | 7 +- lib/Target/CBackend/CBackend.cpp | 256 +- lib/Target/CBackend/CTargetMachine.h | 3 +- lib/Target/CellSPU/SPU64InstrInfo.td | 8 +- lib/Target/CellSPU/SPUISelDAGToDAG.cpp | 129 +- lib/Target/CellSPU/SPUISelLowering.cpp | 26 +- lib/Target/CellSPU/SPUMCAsmInfo.cpp | 3 + lib/Target/CppBackend/CPPBackend.cpp | 41 +- lib/Target/CppBackend/CPPTargetMachine.h | 3 +- lib/Target/MBlaze/AsmPrinter/CMakeLists.txt | 9 + lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp | 302 + lib/Target/MBlaze/AsmPrinter/Makefile | 17 + lib/Target/MBlaze/CMakeLists.txt | 27 + lib/Target/MBlaze/MBlaze.h | 39 + lib/Target/MBlaze/MBlaze.td | 85 + lib/Target/MBlaze/MBlazeCallingConv.td | 26 + lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp | 75 + lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp | 339 + lib/Target/MBlaze/MBlazeISelLowering.cpp | 975 ++ lib/Target/MBlaze/MBlazeISelLowering.h | 149 + lib/Target/MBlaze/MBlazeInstrFPU.td | 223 + lib/Target/MBlaze/MBlazeInstrFSL.td | 153 + lib/Target/MBlaze/MBlazeInstrFormats.td | 246 + lib/Target/MBlaze/MBlazeInstrInfo.cpp | 222 + lib/Target/MBlaze/MBlazeInstrInfo.h | 242 + lib/Target/MBlaze/MBlazeInstrInfo.td | 672 ++ lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp | 109 + lib/Target/MBlaze/MBlazeIntrinsicInfo.h | 33 + lib/Target/MBlaze/MBlazeIntrinsics.td | 137 + lib/Target/MBlaze/MBlazeMCAsmInfo.cpp | 27 + lib/Target/MBlaze/MBlazeMCAsmInfo.h | 30 + lib/Target/MBlaze/MBlazeMachineFunction.h | 136 + lib/Target/MBlaze/MBlazeRegisterInfo.cpp | 421 + lib/Target/MBlaze/MBlazeRegisterInfo.h | 96 + lib/Target/MBlaze/MBlazeRegisterInfo.td | 186 + lib/Target/MBlaze/MBlazeSchedule.td | 63 + lib/Target/MBlaze/MBlazeSubtarget.cpp | 31 + lib/Target/MBlaze/MBlazeSubtarget.h | 79 + lib/Target/MBlaze/MBlazeTargetMachine.cpp | 66 + lib/Target/MBlaze/MBlazeTargetMachine.h | 69 + lib/Target/MBlaze/MBlazeTargetObjectFile.cpp | 88 + lib/Target/MBlaze/MBlazeTargetObjectFile.h | 41 + lib/Target/MBlaze/Makefile | 23 + lib/Target/MBlaze/TargetInfo/CMakeLists.txt | 7 + lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp | 19 + lib/Target/MBlaze/TargetInfo/Makefile | 15 + lib/Target/MSIL/MSILWriter.cpp | 18 +- lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp | 23 +- lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp | 23 +- lib/Target/MSP430/MSP430ISelDAGToDAG.cpp | 330 +- lib/Target/MSP430/MSP430ISelLowering.cpp | 31 +- lib/Target/MSP430/MSP430InstrInfo.td | 2 +- lib/Target/Mips/MipsISelDAGToDAG.cpp | 35 +- lib/Target/Mips/MipsISelLowering.cpp | 23 +- lib/Target/Mips/MipsInstrInfo.td | 11 +- lib/Target/Mips/MipsTargetObjectFile.h | 2 +- lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp | 27 +- lib/Target/PIC16/PIC16ABINames.h | 68 + lib/Target/PIC16/PIC16DebugInfo.cpp | 2 +- lib/Target/PIC16/PIC16ISelDAGToDAG.cpp | 10 - lib/Target/PIC16/PIC16ISelDAGToDAG.h | 4 +- lib/Target/PIC16/PIC16ISelLowering.cpp | 32 +- lib/Target/PIC16/PIC16MemSelOpt.cpp | 105 +- lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp | 299 + lib/Target/PIC16/PIC16Passes/PIC16Cloner.h | 83 + lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp | 26 +- lib/Target/PIC16/PIC16Passes/PIC16Overlay.h | 23 +- lib/Target/PIC16/PIC16TargetObjectFile.cpp | 6 +- lib/Target/PIC16/PIC16TargetObjectFile.h | 3 +- lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp | 3 +- lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp | 2 +- lib/Target/PowerPC/PPCCallingConv.td | 17 +- lib/Target/PowerPC/PPCHazardRecognizers.cpp | 2 +- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 12 - lib/Target/PowerPC/PPCISelLowering.cpp | 124 +- lib/Target/PowerPC/PPCInstr64Bit.td | 11 +- lib/Target/PowerPC/PPCInstrInfo.cpp | 94 +- lib/Target/PowerPC/PPCInstrInfo.td | 28 +- lib/Target/PowerPC/PPCRegisterInfo.cpp | 12 + lib/Target/PowerPC/PPCRegisterInfo.td | 12 +- lib/Target/PowerPC/PPCTargetMachine.cpp | 29 - lib/Target/PowerPC/PPCTargetMachine.h | 12 - lib/Target/PowerPC/README.txt | 19 +- lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp | 47 +- lib/Target/Sparc/README.txt | 1 + lib/Target/Sparc/SparcISelDAGToDAG.cpp | 16 +- lib/Target/Sparc/SparcISelLowering.cpp | 51 +- lib/Target/Sparc/SparcMachineFunctionInfo.h | 2 +- lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 59 +- lib/Target/SystemZ/SystemZISelLowering.cpp | 10 +- lib/Target/SystemZ/SystemZInstrFP.td | 2 +- lib/Target/SystemZ/SystemZInstrInfo.td | 2 +- lib/Target/SystemZ/SystemZMachineFunctionInfo.h | 3 +- lib/Target/TargetData.cpp | 2 +- lib/Target/TargetInstrInfo.cpp | 1 + lib/Target/TargetLoweringObjectFile.cpp | 844 +- lib/Target/X86/Android.mk | 47 + lib/Target/X86/AsmParser/X86AsmParser.cpp | 49 +- lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp | 7 +- lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h | 5 +- lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp | 78 +- lib/Target/X86/AsmPrinter/X86AsmPrinter.h | 3 +- lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp | 4 + lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h | 2 + lib/Target/X86/CMakeLists.txt | 1 + lib/Target/X86/README-SSE.txt | 8 +- lib/Target/X86/README.txt | 71 +- lib/Target/X86/TargetInfo/Android.mk | 24 + lib/Target/X86/X86.h | 19 +- lib/Target/X86/X86AsmBackend.cpp | 34 + lib/Target/X86/X86COFFMachineModuleInfo.cpp | 97 +- lib/Target/X86/X86COFFMachineModuleInfo.h | 27 +- lib/Target/X86/X86CodeEmitter.cpp | 387 +- lib/Target/X86/X86FastISel.cpp | 77 +- lib/Target/X86/X86FixupKinds.h | 25 + lib/Target/X86/X86FloatingPointRegKill.cpp | 2 +- lib/Target/X86/X86ISelDAGToDAG.cpp | 403 +- lib/Target/X86/X86ISelLowering.cpp | 512 +- lib/Target/X86/X86ISelLowering.h | 16 +- lib/Target/X86/X86Instr64bit.td | 79 +- lib/Target/X86/X86InstrFPStack.td | 2 +- lib/Target/X86/X86InstrFormats.td | 36 +- lib/Target/X86/X86InstrInfo.cpp | 110 +- lib/Target/X86/X86InstrInfo.h | 54 +- lib/Target/X86/X86InstrInfo.td | 420 +- lib/Target/X86/X86InstrMMX.td | 17 +- lib/Target/X86/X86InstrSSE.td | 427 +- lib/Target/X86/X86MCAsmInfo.cpp | 30 +- lib/Target/X86/X86MCAsmInfo.h | 5 - lib/Target/X86/X86MCCodeEmitter.cpp | 350 +- lib/Target/X86/X86MachineFunctionInfo.h | 15 - lib/Target/X86/X86RegisterInfo.cpp | 22 +- lib/Target/X86/X86RegisterInfo.h | 3 +- lib/Target/X86/X86RegisterInfo.td | 63 +- lib/Target/X86/X86Subtarget.h | 25 +- lib/Target/X86/X86TargetMachine.cpp | 43 +- lib/Target/X86/X86TargetMachine.h | 12 - lib/Target/X86/X86TargetObjectFile.cpp | 139 +- lib/Target/X86/X86TargetObjectFile.h | 42 +- lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp | 23 + lib/Target/XCore/XCoreISelDAGToDAG.cpp | 17 +- lib/Target/XCore/XCoreISelLowering.cpp | 81 +- lib/Target/XCore/XCoreISelLowering.h | 12 +- lib/Target/XCore/XCoreInstrInfo.cpp | 13 + lib/Target/XCore/XCoreInstrInfo.td | 38 +- lib/Target/XCore/XCoreTargetObjectFile.h | 3 +- lib/Transforms/Hello/Hello.cpp | 1 - lib/Transforms/IPO/ArgumentPromotion.cpp | 6 +- lib/Transforms/IPO/ConstantMerge.cpp | 41 +- lib/Transforms/IPO/DeadArgumentElimination.cpp | 4 +- lib/Transforms/IPO/DeadTypeElimination.cpp | 4 +- lib/Transforms/IPO/FunctionAttrs.cpp | 8 +- lib/Transforms/IPO/GlobalOpt.cpp | 178 +- lib/Transforms/IPO/Inliner.cpp | 25 +- lib/Transforms/IPO/StripSymbols.cpp | 9 + lib/Transforms/InstCombine/InstCombine.h | 24 +- lib/Transforms/InstCombine/InstCombineAddSub.cpp | 18 +- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 394 +- lib/Transforms/InstCombine/InstCombineCalls.cpp | 207 +- lib/Transforms/InstCombine/InstCombineCasts.cpp | 47 +- lib/Transforms/InstCombine/InstCombineCompares.cpp | 43 +- .../InstCombine/InstCombineLoadStoreAlloca.cpp | 30 +- .../InstCombine/InstCombineMulDivRem.cpp | 20 +- lib/Transforms/InstCombine/InstCombinePHI.cpp | 6 +- lib/Transforms/InstCombine/InstCombineSelect.cpp | 32 +- .../InstCombine/InstCombineSimplifyDemanded.cpp | 8 +- .../InstCombine/InstCombineVectorOps.cpp | 4 +- .../InstCombine/InstructionCombining.cpp | 14 +- lib/Transforms/Instrumentation/ProfilingUtils.cpp | 2 +- lib/Transforms/Scalar/ABCD.cpp | 4 +- lib/Transforms/Scalar/Android.mk | 55 + lib/Transforms/Scalar/CodeGenPrepare.cpp | 167 +- lib/Transforms/Scalar/DeadStoreElimination.cpp | 8 +- lib/Transforms/Scalar/GVN.cpp | 139 +- lib/Transforms/Scalar/IndVarSimplify.cpp | 208 +- lib/Transforms/Scalar/JumpThreading.cpp | 17 +- lib/Transforms/Scalar/LICM.cpp | 4 +- lib/Transforms/Scalar/LoopStrengthReduce.cpp | 5175 +++++----- lib/Transforms/Scalar/LoopUnswitch.cpp | 12 +- lib/Transforms/Scalar/MemCpyOptimizer.cpp | 2 +- lib/Transforms/Scalar/Reassociate.cpp | 34 +- lib/Transforms/Scalar/SCCP.cpp | 58 +- lib/Transforms/Scalar/ScalarReplAggregates.cpp | 39 +- lib/Transforms/Scalar/SimplifyLibCalls.cpp | 969 +- lib/Transforms/Utils/AddrModeMatcher.cpp | 8 +- lib/Transforms/Utils/Android.mk | 49 + lib/Transforms/Utils/BasicBlockUtils.cpp | 29 +- lib/Transforms/Utils/BreakCriticalEdges.cpp | 86 +- lib/Transforms/Utils/BuildLibCalls.cpp | 324 + lib/Transforms/Utils/CMakeLists.txt | 1 + lib/Transforms/Utils/Local.cpp | 15 +- lib/Transforms/Utils/LoopSimplify.cpp | 48 +- lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 12 +- lib/Transforms/Utils/SimplifyCFG.cpp | 12 +- lib/VMCore/Android.mk | 61 + lib/VMCore/AsmWriter.cpp | 66 +- lib/VMCore/Attributes.cpp | 9 +- lib/VMCore/ConstantFold.cpp | 154 +- lib/VMCore/Constants.cpp | 176 +- lib/VMCore/ConstantsContext.h | 15 + lib/VMCore/Core.cpp | 227 +- lib/VMCore/Function.cpp | 12 +- lib/VMCore/Globals.cpp | 4 +- lib/VMCore/IRBuilder.cpp | 2 +- lib/VMCore/InlineAsm.cpp | 2 +- lib/VMCore/Instructions.cpp | 173 +- lib/VMCore/LLVMContextImpl.h | 35 +- lib/VMCore/Makefile | 4 +- lib/VMCore/Metadata.cpp | 7 + lib/VMCore/Pass.cpp | 9 + lib/VMCore/PassManager.cpp | 33 +- lib/VMCore/Type.cpp | 207 +- lib/VMCore/TypesContext.h | 26 + lib/VMCore/Value.cpp | 12 +- lib/VMCore/ValueTypes.cpp | 7 +- lib/VMCore/Verifier.cpp | 145 +- llvm-device-build.mk | 52 + llvm-gen-intrinsics.mk | 18 + llvm-host-build.mk | 50 + projects/CMakeLists.txt | 2 +- projects/sample/configure | 1 + runtime/Makefile | 4 + runtime/libprofile/Makefile | 2 +- tblgen-rules.mk | 108 + test/Analysis/Andersens/2007-11-19-InlineAsm.ll | 8 - test/Analysis/Andersens/2008-03-19-External.ll | 12 - test/Analysis/Andersens/2008-04-07-Memcpy.ll | 14 - .../Andersens/2008-12-27-BuiltinWrongType.ll | 19 - test/Analysis/Andersens/basictest.ll | 28 - test/Analysis/Andersens/dg.exp | 4 - test/Analysis/Andersens/external.ll | 20 - test/Analysis/Andersens/modreftest.ll | 15 - test/Analysis/Andersens/modreftest2.ll | 14 - test/Analysis/Andersens/trivialtest.ll | 3 - test/Analysis/ScalarEvolution/trip-count10.ll | 76 + test/Archive/GNU.a | Bin 4210 -> 0 bytes test/Archive/IsNAN.o | Bin 2280 -> 0 bytes test/Archive/MacOSX.a | Bin 4166 -> 0 bytes test/Archive/SVR4.a | Bin 4214 -> 0 bytes test/Archive/xpg4.a | Bin 4214 -> 0 bytes test/Assembler/2010-01-06-UnionType.ll | 3 + test/Bindings/Ocaml/bitreader.ml | 16 +- test/Bindings/Ocaml/bitwriter.ml | 34 +- test/Bindings/Ocaml/executionengine.ml | 9 +- test/Bindings/Ocaml/scalar_opts.ml | 28 +- test/Bindings/Ocaml/vmcore.ml | 730 +- test/CodeGen/ARM/2010-03-04-eabi-fp-spill.ll | 65 + test/CodeGen/ARM/2010-03-04-stm-undef-addr.ll | 54 + test/CodeGen/ARM/arm-negative-stride.ll | 26 + test/CodeGen/ARM/armv4.ll | 13 + test/CodeGen/ARM/call.ll | 14 + test/CodeGen/ARM/lsr-code-insertion.ll | 4 +- test/CodeGen/ARM/neon_minmax.ll | 81 + test/CodeGen/ARM/remat.ll | 6 +- test/CodeGen/Alpha/add.ll | 3 +- test/CodeGen/Blackfin/promote-logic.ll | 3 +- test/CodeGen/CellSPU/bss.ll | 5 + test/CodeGen/Generic/2007-05-05-Personality.ll | 2 +- test/CodeGen/Generic/GC/argpromotion.ll | 2 +- test/CodeGen/Generic/debug-info.ll | 19 - test/CodeGen/MBlaze/brind.ll | 73 + test/CodeGen/MBlaze/callind.ll | 80 + test/CodeGen/MBlaze/cc.ll | 315 + test/CodeGen/MBlaze/dg.exp | 5 + test/CodeGen/MBlaze/div.ll | 75 + test/CodeGen/MBlaze/fpu.ll | 66 + test/CodeGen/MBlaze/fsl.ll | 323 + test/CodeGen/MBlaze/imm.ll | 70 + test/CodeGen/MBlaze/jumptable.ll | 79 + test/CodeGen/MBlaze/loop.ll | 47 + test/CodeGen/MBlaze/mul.ll | 51 + test/CodeGen/MBlaze/mul64.ll | 23 + test/CodeGen/MBlaze/select.ll | 15 + test/CodeGen/MBlaze/shift.ll | 117 + test/CodeGen/MSP430/AddrMode-bis-rx.ll | 6 +- test/CodeGen/MSP430/AddrMode-bis-xr.ll | 6 +- test/CodeGen/MSP430/AddrMode-mov-rx.ll | 6 +- test/CodeGen/MSP430/AddrMode-mov-xr.ll | 6 +- test/CodeGen/MSP430/Inst16mm.ll | 17 +- test/CodeGen/MSP430/Inst8rr.ll | 2 +- test/CodeGen/MSP430/bit.ll | 2 +- test/CodeGen/MSP430/setcc.ll | 44 +- test/CodeGen/PIC16/C16-11.ll | 5 +- test/CodeGen/PIC16/C16-15.ll | 2 +- .../PowerPC/2007-04-30-InlineAsmEarlyClobber.ll | 4 +- .../2009-08-17-inline-asm-addr-mode-breakage.ll | 6 +- test/CodeGen/PowerPC/2010-02-12-saveCR.ll | 30 + test/CodeGen/PowerPC/2010-02-26-FoldFloats.ll | 433 + test/CodeGen/PowerPC/Frames-alloca.ll | 2 +- test/CodeGen/PowerPC/LargeAbsoluteAddr.ll | 6 +- test/CodeGen/PowerPC/addc.ll | 25 +- test/CodeGen/PowerPC/indirectbr.ll | 14 +- test/CodeGen/PowerPC/lsr-postinc-pos.ll | 32 + test/CodeGen/PowerPC/mem_update.ll | 54 +- test/CodeGen/PowerPC/retaddr.ll | 2 +- test/CodeGen/Thumb2/2010-02-11-phi-cycle.ll | 76 + test/CodeGen/Thumb2/2010-02-24-BigStack.ll | 15 + test/CodeGen/Thumb2/cross-rc-coalescing-2.ll | 2 +- test/CodeGen/Thumb2/ldr-str-imm12.ll | 2 +- test/CodeGen/Thumb2/lsr-deficiency.ll | 18 +- test/CodeGen/Thumb2/thumb2-ifcvt1.ll | 12 +- test/CodeGen/Thumb2/thumb2-spill-q.ll | 4 +- test/CodeGen/Thumb2/thumb2-uxtb.ll | 20 +- test/CodeGen/X86/2005-01-17-CycleInDAG.ll | 2 +- test/CodeGen/X86/2006-05-11-InstrSched.ll | 4 +- test/CodeGen/X86/2006-10-07-ScalarSSEMiscompile.ll | 2 +- test/CodeGen/X86/2007-03-15-GEP-Idx-Sink.ll | 2 +- test/CodeGen/X86/2007-10-05-3AddrConvert.ll | 4 +- test/CodeGen/X86/2007-11-30-LoadFolding-Bug.ll | 2 +- test/CodeGen/X86/2008-02-22-ReMatBug.ll | 2 +- test/CodeGen/X86/2008-07-11-SpillerBug.ll | 4 +- test/CodeGen/X86/2008-08-05-SpillerBug.ll | 2 +- test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll | 133 +- test/CodeGen/X86/2009-07-16-LoadFoldingBug.ll | 102 - test/CodeGen/X86/2009-09-07-CoalescerBug.ll | 3 +- test/CodeGen/X86/2010-02-11-NonTemporal.ll | 22 + test/CodeGen/X86/2010-02-12-CoalescerBug-Impdef.ll | 260 + test/CodeGen/X86/2010-02-15-ImplicitDefBug.ll | 80 + test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll | 55 + test/CodeGen/X86/2010-02-23-DAGCombineBug.ll | 18 + test/CodeGen/X86/2010-02-23-DIV8rDefinesAX.ll | 20 + test/CodeGen/X86/2010-02-23-RematImplicitSubreg.ll | 49 + test/CodeGen/X86/2010-02-23-SingleDefPhiJoin.ll | 146 + test/CodeGen/X86/2010-03-04-Mul8Bug.ll | 25 + test/CodeGen/X86/2010-03-05-ConstantFoldCFG.ll | 42 + test/CodeGen/X86/2010-03-05-EFLAGS-Redef.ll | 49 + test/CodeGen/X86/addr-label-difference.ll | 10 +- test/CodeGen/X86/and-or-fold.ll | 28 +- test/CodeGen/X86/bswap-inline-asm.ll | 67 +- test/CodeGen/X86/code_placement_eh.ll | 45 + test/CodeGen/X86/crash.ll | 20 + test/CodeGen/X86/critical-edge-split.ll | 2 +- test/CodeGen/X86/dllexport.ll | 12 + test/CodeGen/X86/fastcall-correct-mangling.ll | 4 +- test/CodeGen/X86/full-lsr.ll | 9 +- test/CodeGen/X86/global-sections.ll | 3 +- test/CodeGen/X86/ins_subreg_coalesce-3.ll | 2 +- test/CodeGen/X86/iv-users-in-other-loops.ll | 8 +- test/CodeGen/X86/licm-symbol.ll | 39 + test/CodeGen/X86/loop-strength-reduce-2.ll | 19 +- test/CodeGen/X86/loop-strength-reduce-3.ll | 13 +- test/CodeGen/X86/loop-strength-reduce.ll | 13 +- test/CodeGen/X86/loop-strength-reduce4.ll | 18 +- test/CodeGen/X86/loop-strength-reduce8.ll | 8 +- test/CodeGen/X86/lsr-overflow.ll | 26 + test/CodeGen/X86/lsr-reuse-trunc.ll | 59 + test/CodeGen/X86/lsr-reuse.ll | 442 + test/CodeGen/X86/lsr-wrap.ll | 37 + test/CodeGen/X86/masked-iv-safe.ll | 6 +- test/CodeGen/X86/omit-label.ll | 57 - test/CodeGen/X86/pr1505b.ll | 4 +- test/CodeGen/X86/pr3495-2.ll | 6 +- test/CodeGen/X86/pr3495.ll | 3 +- test/CodeGen/X86/pre-split8.ll | 2 +- test/CodeGen/X86/pre-split9.ll | 2 +- test/CodeGen/X86/ptrtoint-constexpr.ll | 2 +- test/CodeGen/X86/scalar_widen_div.ll | 29 + test/CodeGen/X86/sse-minmax.ll | 610 +- test/CodeGen/X86/sse3.ll | 7 +- test/CodeGen/X86/stack-align.ll | 19 +- test/CodeGen/X86/stack-color-with-reg.ll | 2 +- test/CodeGen/X86/stdcall.ll | 16 + test/CodeGen/X86/store_op_load_fold.ll | 2 +- test/CodeGen/X86/store_op_load_fold2.ll | 24 +- test/CodeGen/X86/tailcall2.ll | 21 + test/CodeGen/X86/trunc-to-bool.ll | 21 +- test/CodeGen/X86/twoaddr-coalesce.ll | 2 +- test/CodeGen/X86/use-add-flags.ll | 12 +- test/CodeGen/X86/vec_cast.ll | 18 +- test/CodeGen/X86/vec_insert.ll | 4 +- test/CodeGen/X86/vec_shuffle-36.ll | 17 +- test/CodeGen/X86/vec_ss_load_fold.ll | 37 +- test/CodeGen/X86/xor-icmp.ll | 31 + test/CodeGen/XCore/2010-02-25-LSR-Crash.ll | 26 + test/CodeGen/XCore/switch.ll | 24 + test/CodeGen/XCore/switch_long.ll | 132 + test/DebugInfo/2009-02-27-licm.ll | 83 - test/DebugInfo/2009-03-03-cheapdse.ll | 80 - test/DebugInfo/2009-03-05-gvn.ll | 125 - test/DebugInfo/deaddebuglabel.ll | 62 - test/DebugInfo/funccall.ll | 147 - test/DebugInfo/globalGetElementPtr.ll | 264 - test/DebugInfo/inheritance.ll | 151 + test/ExecutionEngine/2010-01-15-UndefValue.ll | 4 +- test/Feature/alignment.ll | 4 + test/Feature/unions.ll | 12 + test/FrontendC++/2010-02-08-NamespaceVar.cpp | 16 - test/FrontendC++/2010-02-17-DbgArtificialArg.cpp | 14 + test/FrontendC/2003-12-14-ExternInlineSupport.c | 2 +- test/FrontendC/2007-02-16-WritableStrings.c | 2 +- test/FrontendC/2007-09-17-WeakRef.c | 2 +- test/FrontendC/2010-02-10-PointerName.c | 7 + test/FrontendC/2010-02-15-DbgStaticVar.c | 13 + test/FrontendC/2010-02-16-DbgVarScope.c | 30 + test/FrontendC/2010-02-18-Dbg-VectorType.c | 9 + test/FrontendC/2010-03-5-LexicalScope.c | 10 + .../FrontendObjC/2010-02-11-fwritable-stringsBug.m | 17 + test/FrontendObjC/2010-02-23-DbgInheritance.m | 9 + test/LLVMC/AppendCmdHook.td | 8 +- test/LLVMC/EnvParentheses.td | 4 +- test/LLVMC/ExternOptions.td | 2 +- test/LLVMC/ForwardAs.td | 4 +- test/LLVMC/ForwardTransformedValue.td | 2 +- test/LLVMC/ForwardValue.td | 6 +- test/LLVMC/HookWithArguments.td | 4 +- test/LLVMC/HookWithInFile.td | 2 +- test/LLVMC/Init.td | 2 +- test/LLVMC/MultiValuedOption.td | 2 +- test/LLVMC/MultiplePluginPriorities.td | 4 + test/LLVMC/NoActions.td | 2 +- test/LLVMC/OneOrMore.td | 2 +- test/LLVMC/OptionPreprocessor.td | 2 +- test/MC/AsmParser/X86/x86_32-bit_cat.s | 158 +- test/MC/AsmParser/X86/x86_32-encoding.s | 9866 +++++++++++++++++++- test/MC/AsmParser/X86/x86_32-new-encoder.s | 41 + test/MC/AsmParser/X86/x86_64-new-encoder.s | 26 + test/MC/AsmParser/X86/x86_instructions.s | 14 +- test/MC/AsmParser/X86/x86_operands.s | 20 +- test/MC/AsmParser/conditional_asm.s | 2 +- test/MC/Disassembler/simple-tests.txt | 29 + test/MC/MachO/Darwin/optimal_nop.s | 156 + test/Makefile | 4 +- test/Makefile.tests | 6 +- test/Other/2008-03-19-PassManager.ll | 58 - test/Other/constant-fold-gep.ll | 54 +- .../2006-03-07-DontMergeDiffSections.ll | 16 - test/Transforms/ConstantMerge/dont-merge.ll | 30 + test/Transforms/DeadStoreElimination/crash.ll | 14 + test/Transforms/GVN/2008-02-13-NewPHI.ll | 2 +- test/Transforms/GVN/2009-03-05-dbg.ll | 66 - test/Transforms/GVN/crash.ll | 22 +- test/Transforms/GVN/pre-load.ll | 27 + test/Transforms/GlobalOpt/2009-03-03-dbg.ll | 54 - test/Transforms/GlobalOpt/2009-03-05-dbg.ll | 119 +- .../GlobalOpt/2010-02-25-MallocPromote.ll | 18 + test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll | 27 + test/Transforms/GlobalOpt/ctor-list-opt-dbg.ll | 98 - .../IndVarSimplify/2003-09-12-MultiplePred.ll | 2 +- .../IndVarSimplify/2003-12-10-RemoveInstrCrash.ll | 2 +- test/Transforms/IndVarSimplify/2003-12-15-Crash.ll | 4 +- test/Transforms/IndVarSimplify/2005-11-18-Crash.ll | 2 +- .../IndVarSimplify/2006-12-10-BitCast.ll | 2 +- .../IndVarSimplify/2009-05-24-useafterfree.ll | 4 +- test/Transforms/IndVarSimplify/addrec-gep.ll | 2 +- test/Transforms/IndVarSimplify/avoid-i0.ll | 4 +- test/Transforms/IndVarSimplify/max-pointer.ll | 4 +- .../InstCombine/2006-12-08-ICmp-Combining.ll | 18 - .../2009-01-19-fmod-constant-float-specials.ll | 3 +- test/Transforms/InstCombine/2010-03-03-ExtElim.ll | 18 + test/Transforms/InstCombine/JavaCompare.ll | 2 +- test/Transforms/InstCombine/and2.ll | 6 +- test/Transforms/InstCombine/bswap-fold.ll | 6 + .../InstCombine/constant-fold-ptr-casts.ll | 18 - test/Transforms/InstCombine/crash.ll | 15 + test/Transforms/InstCombine/fcmp-select.ll | 53 + test/Transforms/InstCombine/fcmp-special.ll | 155 + test/Transforms/InstCombine/icmp.ll | 12 +- test/Transforms/InstCombine/load-cmp.ll | 8 +- test/Transforms/InstCombine/memset_chk.ll | 18 + test/Transforms/InstCombine/multi-use-or.ll | 2 +- test/Transforms/InstCombine/objsize.ll | 87 +- test/Transforms/InstCombine/or.ll | 20 +- test/Transforms/InstCombine/phi.ll | 40 + test/Transforms/InstCombine/ptr-int-cast.ll | 18 +- test/Transforms/InstCombine/strcpy_chk.ll | 12 + test/Transforms/InstCombine/vec_narrow.ll | 2 +- test/Transforms/InstCombine/vector-casts.ll | 16 + test/Transforms/InstCombine/xor2.ll | 8 +- test/Transforms/JumpThreading/crash.ll | 11 + test/Transforms/JumpThreading/or-undef.ll | 69 + .../LoopDeletion/simplify-then-delete.ll | 65 + .../LoopIndexSplit/SplitValue-2007-08-24-dbg.ll | 71 - .../LoopStrengthReduce/2008-08-06-CmpStride.ll | 5 +- .../change-compare-stride-trickiness-0.ll | 13 +- .../change-compare-stride-trickiness-1.ll | 4 +- .../Transforms/LoopStrengthReduce/count-to-zero.ll | 2 +- .../LoopStrengthReduce/invariant_value_first.ll | 2 +- .../invariant_value_first_arg.ll | 2 +- .../LoopStrengthReduce/nonlinear-postinc.ll | 44 + .../LoopStrengthReduce/ops_after_indvar.ll | 2 +- .../LoopStrengthReduce/quadradic-exit-value.ll | 2 +- .../Transforms/LoopStrengthReduce/remove_indvar.ll | 2 + .../use_postinc_value_outside_loop.ll | 2 +- test/Transforms/Reassociate/crash.ll | 15 +- test/Transforms/SCCP/retvalue-undef.ll | 32 + test/Transforms/ScalarRepl/2009-03-17-CleanUp.ll | 3961 -------- .../SimplifyCFG/2009-06-15-InvokeCrash.ll | 14 +- test/Transforms/SimplifyLibCalls/strcpy_chk.ll | 12 - test/Unit/lit.cfg | 9 +- test/Unit/lit.site.cfg.in | 2 + test/lib/llvm.exp | 15 +- test/lit.cfg | 8 +- test/site.exp.in | 2 - tools/Makefile | 27 +- tools/bugpoint/CrashDebugger.cpp | 2 +- tools/bugpoint/ExtractFunction.cpp | 2 +- tools/llc/llc.cpp | 14 +- tools/llvm-config/CMakeLists.txt | 2 - tools/llvm-config/Makefile | 4 +- tools/llvm-extract/llvm-extract.cpp | 52 +- tools/llvm-mc/llvm-mc.cpp | 4 +- tools/llvm-shlib/Makefile | 60 + tools/llvmc/doc/LLVMC-Reference.rst | 26 +- .../example/mcc16/plugins/PIC16Base/PIC16Base.td | 42 +- tools/llvmc/plugins/Base/Base.td.in | 146 +- tools/llvmc/plugins/Clang/Clang.td | 37 +- tools/opt/opt.cpp | 3 +- unittests/ADT/APFloatTest.cpp | 36 + unittests/ADT/StringMapTest.cpp | 1 + unittests/ExecutionEngine/JIT/JITTest.cpp | 50 + unittests/ExecutionEngine/JIT/MultiJITTest.cpp | 164 + unittests/Makefile.unittest | 11 +- unittests/Support/AllocatorTest.cpp | 2 +- unittests/Support/RegexTest.cpp | 29 + unittests/VMCore/DerivedTypesTest.cpp | 10 +- unittests/VMCore/MetadataTest.cpp | 29 +- unittests/VMCore/VerifierTest.cpp | 44 + utils/GenLibDeps.pl | 2 + utils/TableGen/Android.mk | 46 + utils/TableGen/AsmMatcherEmitter.cpp | 62 +- utils/TableGen/AsmWriterEmitter.cpp | 44 + utils/TableGen/AsmWriterEmitter.h | 1 + utils/TableGen/CMakeLists.txt | 4 + utils/TableGen/CodeGenDAGPatterns.cpp | 346 +- utils/TableGen/CodeGenDAGPatterns.h | 47 +- utils/TableGen/CodeGenInstruction.cpp | 3 +- utils/TableGen/CodeGenInstruction.h | 2 +- utils/TableGen/DAGISelEmitter.cpp | 1967 +--- utils/TableGen/DAGISelEmitter.h | 16 - utils/TableGen/DAGISelMatcher.cpp | 402 + utils/TableGen/DAGISelMatcher.h | 1112 +++ utils/TableGen/DAGISelMatcherEmitter.cpp | 779 ++ utils/TableGen/DAGISelMatcherGen.cpp | 882 ++ utils/TableGen/DAGISelMatcherOpt.cpp | 509 + utils/TableGen/InstrEnumEmitter.cpp | 2 +- utils/TableGen/LLVMCConfigurationEmitter.cpp | 444 +- utils/TableGen/Record.h | 4 + utils/TableGen/X86RecognizableInstr.cpp | 107 +- utils/buildit/GNUmakefile | 4 +- utils/git/find-rev | 50 + .../lit/lit/ExampleTests/LLVM.InTree/test/site.exp | 2 - .../ExampleTests/LLVM.OutOfTree/obj/test/site.exp | 2 - utils/lit/lit/TestFormats.py | 7 +- utils/lit/lit/TestRunner.py | 18 + utils/lit/lit/TestingConfig.py | 9 +- utils/llvm.grm | 1 + utils/vim/llvm.vim | 5 +- utils/vim/tablegen.vim | 2 +- utils/vim/vimrc | 31 +- 936 files changed, 52992 insertions(+), 27943 deletions(-) create mode 100644 Android.mk delete mode 100644 Xcode/LLVM.xcodeproj/project.pbxproj delete mode 100644 Xcode/README.txt create mode 100644 clear_tblgen_vars.mk create mode 100644 device/include/llvm/Config/AsmParsers.def create mode 100644 device/include/llvm/Config/AsmPrinters.def create mode 100644 device/include/llvm/Config/Disassemblers.def create mode 100644 device/include/llvm/Config/Targets.def create mode 100644 device/include/llvm/Config/config.h delete mode 100644 docs/CommandGuide/llvm-db.pod create mode 100644 docs/Packaging.html create mode 100644 host/include/llvm/Config/AsmParsers.def create mode 100644 host/include/llvm/Config/AsmPrinters.def create mode 100644 host/include/llvm/Config/Disassemblers.def create mode 100644 host/include/llvm/Config/Targets.def create mode 100644 host/include/llvm/Config/config.h delete mode 100644 include/llvm/CodeGen/DAGISelHeader.h create mode 100644 include/llvm/CodeGen/TargetLoweringObjectFileImpl.h create mode 100644 include/llvm/System/DataTypes.h create mode 100644 include/llvm/Target/TargetAsmBackend.h create mode 100644 include/llvm/Transforms/Utils/BuildLibCalls.h create mode 100644 lib/Analysis/Android.mk delete mode 100644 lib/Analysis/IPA/Andersens.cpp create mode 100644 lib/AsmParser/Android.mk create mode 100644 lib/Bitcode/Reader/Android.mk create mode 100644 lib/CodeGen/Android.mk create mode 100644 lib/CodeGen/AsmPrinter/Android.mk create mode 100644 lib/CodeGen/MachineCSE.cpp create mode 100644 lib/CodeGen/OptimizePHIs.cpp create mode 100644 lib/CodeGen/SelectionDAG/Android.mk create mode 100644 lib/CodeGen/SelectionDAG/SDDbgValue.h create mode 100644 lib/CodeGen/TargetLoweringObjectFileImpl.cpp create mode 100644 lib/ExecutionEngine/JIT/Android.mk create mode 100644 lib/MC/Android.mk create mode 100644 lib/MC/TargetAsmBackend.cpp create mode 100644 lib/Support/Android.mk create mode 100644 lib/System/Android.mk create mode 100644 lib/Target/ARM/Android.mk create mode 100644 lib/Target/ARM/TargetInfo/Android.mk create mode 100644 lib/Target/Android.mk create mode 100644 lib/Target/MBlaze/AsmPrinter/CMakeLists.txt create mode 100644 lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp create mode 100644 lib/Target/MBlaze/AsmPrinter/Makefile create mode 100644 lib/Target/MBlaze/CMakeLists.txt create mode 100644 lib/Target/MBlaze/MBlaze.h create mode 100644 lib/Target/MBlaze/MBlaze.td create mode 100644 lib/Target/MBlaze/MBlazeCallingConv.td create mode 100644 lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp create mode 100644 lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp create mode 100644 lib/Target/MBlaze/MBlazeISelLowering.cpp create mode 100644 lib/Target/MBlaze/MBlazeISelLowering.h create mode 100644 lib/Target/MBlaze/MBlazeInstrFPU.td create mode 100644 lib/Target/MBlaze/MBlazeInstrFSL.td create mode 100644 lib/Target/MBlaze/MBlazeInstrFormats.td create mode 100644 lib/Target/MBlaze/MBlazeInstrInfo.cpp create mode 100644 lib/Target/MBlaze/MBlazeInstrInfo.h create mode 100644 lib/Target/MBlaze/MBlazeInstrInfo.td create mode 100644 lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp create mode 100644 lib/Target/MBlaze/MBlazeIntrinsicInfo.h create mode 100644 lib/Target/MBlaze/MBlazeIntrinsics.td create mode 100644 lib/Target/MBlaze/MBlazeMCAsmInfo.cpp create mode 100644 lib/Target/MBlaze/MBlazeMCAsmInfo.h create mode 100644 lib/Target/MBlaze/MBlazeMachineFunction.h create mode 100644 lib/Target/MBlaze/MBlazeRegisterInfo.cpp create mode 100644 lib/Target/MBlaze/MBlazeRegisterInfo.h create mode 100644 lib/Target/MBlaze/MBlazeRegisterInfo.td create mode 100644 lib/Target/MBlaze/MBlazeSchedule.td create mode 100644 lib/Target/MBlaze/MBlazeSubtarget.cpp create mode 100644 lib/Target/MBlaze/MBlazeSubtarget.h create mode 100644 lib/Target/MBlaze/MBlazeTargetMachine.cpp create mode 100644 lib/Target/MBlaze/MBlazeTargetMachine.h create mode 100644 lib/Target/MBlaze/MBlazeTargetObjectFile.cpp create mode 100644 lib/Target/MBlaze/MBlazeTargetObjectFile.h create mode 100644 lib/Target/MBlaze/Makefile create mode 100644 lib/Target/MBlaze/TargetInfo/CMakeLists.txt create mode 100644 lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp create mode 100644 lib/Target/MBlaze/TargetInfo/Makefile create mode 100644 lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp create mode 100644 lib/Target/PIC16/PIC16Passes/PIC16Cloner.h create mode 100644 lib/Target/X86/Android.mk create mode 100644 lib/Target/X86/TargetInfo/Android.mk create mode 100644 lib/Target/X86/X86AsmBackend.cpp create mode 100644 lib/Target/X86/X86FixupKinds.h create mode 100644 lib/Transforms/Scalar/Android.mk create mode 100644 lib/Transforms/Utils/Android.mk create mode 100644 lib/Transforms/Utils/BuildLibCalls.cpp create mode 100644 lib/VMCore/Android.mk create mode 100644 llvm-device-build.mk create mode 100644 llvm-gen-intrinsics.mk create mode 100644 llvm-host-build.mk create mode 100644 tblgen-rules.mk delete mode 100644 test/Analysis/Andersens/2007-11-19-InlineAsm.ll delete mode 100644 test/Analysis/Andersens/2008-03-19-External.ll delete mode 100644 test/Analysis/Andersens/2008-04-07-Memcpy.ll delete mode 100644 test/Analysis/Andersens/2008-12-27-BuiltinWrongType.ll delete mode 100644 test/Analysis/Andersens/basictest.ll delete mode 100644 test/Analysis/Andersens/dg.exp delete mode 100644 test/Analysis/Andersens/external.ll delete mode 100644 test/Analysis/Andersens/modreftest.ll delete mode 100644 test/Analysis/Andersens/modreftest2.ll delete mode 100644 test/Analysis/Andersens/trivialtest.ll create mode 100644 test/Analysis/ScalarEvolution/trip-count10.ll delete mode 100644 test/Archive/GNU.a delete mode 100644 test/Archive/IsNAN.o delete mode 100644 test/Archive/MacOSX.a delete mode 100644 test/Archive/SVR4.a delete mode 100644 test/Archive/xpg4.a create mode 100644 test/Assembler/2010-01-06-UnionType.ll create mode 100644 test/CodeGen/ARM/2010-03-04-eabi-fp-spill.ll create mode 100644 test/CodeGen/ARM/2010-03-04-stm-undef-addr.ll create mode 100644 test/CodeGen/ARM/armv4.ll create mode 100644 test/CodeGen/ARM/neon_minmax.ll create mode 100644 test/CodeGen/CellSPU/bss.ll delete mode 100644 test/CodeGen/Generic/debug-info.ll create mode 100644 test/CodeGen/MBlaze/brind.ll create mode 100644 test/CodeGen/MBlaze/callind.ll create mode 100644 test/CodeGen/MBlaze/cc.ll create mode 100644 test/CodeGen/MBlaze/dg.exp create mode 100644 test/CodeGen/MBlaze/div.ll create mode 100644 test/CodeGen/MBlaze/fpu.ll create mode 100644 test/CodeGen/MBlaze/fsl.ll create mode 100644 test/CodeGen/MBlaze/imm.ll create mode 100644 test/CodeGen/MBlaze/jumptable.ll create mode 100644 test/CodeGen/MBlaze/loop.ll create mode 100644 test/CodeGen/MBlaze/mul.ll create mode 100644 test/CodeGen/MBlaze/mul64.ll create mode 100644 test/CodeGen/MBlaze/select.ll create mode 100644 test/CodeGen/MBlaze/shift.ll create mode 100644 test/CodeGen/PowerPC/2010-02-12-saveCR.ll create mode 100644 test/CodeGen/PowerPC/2010-02-26-FoldFloats.ll create mode 100644 test/CodeGen/PowerPC/lsr-postinc-pos.ll create mode 100644 test/CodeGen/Thumb2/2010-02-11-phi-cycle.ll create mode 100644 test/CodeGen/Thumb2/2010-02-24-BigStack.ll delete mode 100644 test/CodeGen/X86/2009-07-16-LoadFoldingBug.ll create mode 100644 test/CodeGen/X86/2010-02-11-NonTemporal.ll create mode 100644 test/CodeGen/X86/2010-02-12-CoalescerBug-Impdef.ll create mode 100644 test/CodeGen/X86/2010-02-15-ImplicitDefBug.ll create mode 100644 test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll create mode 100644 test/CodeGen/X86/2010-02-23-DAGCombineBug.ll create mode 100644 test/CodeGen/X86/2010-02-23-DIV8rDefinesAX.ll create mode 100644 test/CodeGen/X86/2010-02-23-RematImplicitSubreg.ll create mode 100644 test/CodeGen/X86/2010-02-23-SingleDefPhiJoin.ll create mode 100644 test/CodeGen/X86/2010-03-04-Mul8Bug.ll create mode 100644 test/CodeGen/X86/2010-03-05-ConstantFoldCFG.ll create mode 100644 test/CodeGen/X86/2010-03-05-EFLAGS-Redef.ll create mode 100644 test/CodeGen/X86/code_placement_eh.ll create mode 100644 test/CodeGen/X86/crash.ll create mode 100644 test/CodeGen/X86/dllexport.ll create mode 100644 test/CodeGen/X86/licm-symbol.ll create mode 100644 test/CodeGen/X86/lsr-overflow.ll create mode 100644 test/CodeGen/X86/lsr-reuse-trunc.ll create mode 100644 test/CodeGen/X86/lsr-reuse.ll create mode 100644 test/CodeGen/X86/lsr-wrap.ll delete mode 100644 test/CodeGen/X86/omit-label.ll create mode 100644 test/CodeGen/X86/stdcall.ll create mode 100644 test/CodeGen/XCore/2010-02-25-LSR-Crash.ll create mode 100644 test/CodeGen/XCore/switch.ll create mode 100644 test/CodeGen/XCore/switch_long.ll delete mode 100644 test/DebugInfo/2009-02-27-licm.ll delete mode 100644 test/DebugInfo/2009-03-03-cheapdse.ll delete mode 100644 test/DebugInfo/2009-03-05-gvn.ll delete mode 100644 test/DebugInfo/deaddebuglabel.ll delete mode 100644 test/DebugInfo/funccall.ll delete mode 100644 test/DebugInfo/globalGetElementPtr.ll create mode 100644 test/DebugInfo/inheritance.ll create mode 100644 test/Feature/unions.ll delete mode 100644 test/FrontendC++/2010-02-08-NamespaceVar.cpp create mode 100644 test/FrontendC++/2010-02-17-DbgArtificialArg.cpp create mode 100644 test/FrontendC/2010-02-10-PointerName.c create mode 100644 test/FrontendC/2010-02-15-DbgStaticVar.c create mode 100644 test/FrontendC/2010-02-16-DbgVarScope.c create mode 100644 test/FrontendC/2010-02-18-Dbg-VectorType.c create mode 100644 test/FrontendC/2010-03-5-LexicalScope.c create mode 100644 test/FrontendObjC/2010-02-11-fwritable-stringsBug.m create mode 100644 test/FrontendObjC/2010-02-23-DbgInheritance.m create mode 100644 test/MC/AsmParser/X86/x86_32-new-encoder.s create mode 100644 test/MC/AsmParser/X86/x86_64-new-encoder.s create mode 100644 test/MC/MachO/Darwin/optimal_nop.s delete mode 100644 test/Other/2008-03-19-PassManager.ll delete mode 100644 test/Transforms/ConstantMerge/2006-03-07-DontMergeDiffSections.ll create mode 100644 test/Transforms/ConstantMerge/dont-merge.ll delete mode 100644 test/Transforms/GVN/2009-03-05-dbg.ll delete mode 100644 test/Transforms/GlobalOpt/2009-03-03-dbg.ll create mode 100644 test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll create mode 100644 test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll delete mode 100644 test/Transforms/GlobalOpt/ctor-list-opt-dbg.ll delete mode 100644 test/Transforms/InstCombine/2006-12-08-ICmp-Combining.ll create mode 100644 test/Transforms/InstCombine/2010-03-03-ExtElim.ll delete mode 100644 test/Transforms/InstCombine/constant-fold-ptr-casts.ll create mode 100644 test/Transforms/InstCombine/fcmp-select.ll create mode 100644 test/Transforms/InstCombine/fcmp-special.ll create mode 100644 test/Transforms/InstCombine/memset_chk.ll create mode 100644 test/Transforms/InstCombine/strcpy_chk.ll create mode 100644 test/Transforms/JumpThreading/or-undef.ll create mode 100644 test/Transforms/LoopDeletion/simplify-then-delete.ll delete mode 100644 test/Transforms/LoopIndexSplit/SplitValue-2007-08-24-dbg.ll create mode 100644 test/Transforms/LoopStrengthReduce/nonlinear-postinc.ll create mode 100644 test/Transforms/SCCP/retvalue-undef.ll delete mode 100644 test/Transforms/ScalarRepl/2009-03-17-CleanUp.ll delete mode 100644 test/Transforms/SimplifyLibCalls/strcpy_chk.ll create mode 100644 tools/llvm-shlib/Makefile create mode 100644 unittests/ExecutionEngine/JIT/MultiJITTest.cpp create mode 100644 unittests/VMCore/VerifierTest.cpp create mode 100644 utils/TableGen/Android.mk create mode 100644 utils/TableGen/DAGISelMatcher.cpp create mode 100644 utils/TableGen/DAGISelMatcher.h create mode 100644 utils/TableGen/DAGISelMatcherEmitter.cpp create mode 100644 utils/TableGen/DAGISelMatcherGen.cpp create mode 100644 utils/TableGen/DAGISelMatcherOpt.cpp create mode 100755 utils/git/find-rev diff --git a/Android.mk b/Android.mk new file mode 100644 index 0000000000..9c065f68c6 --- /dev/null +++ b/Android.mk @@ -0,0 +1,39 @@ +LOCAL_PATH := $(call my-dir) +LLVM_ROOT_PATH := $(LOCAL_PATH) +include $(CLEAR_VARS) + +# Only use this on the device or emulator. +ifeq ($(TARGET_SIMULATOR),true) +$(error LLVM not suitable for the simulator! $(LOCAL_PATH)) +endif + +subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \ + lib/System \ + lib/Support \ + utils/TableGen \ + lib/VMCore \ + lib/Bitcode/Reader \ + lib/Analysis \ + lib/Transforms/Utils \ + lib/Transforms/Scalar \ + lib/CodeGen \ + lib/CodeGen/SelectionDAG \ + lib/CodeGen/AsmPrinter \ + lib/Target \ + lib/Target/ARM \ + lib/Target/ARM/TargetInfo \ + lib/Target/X86 \ + lib/Target/X86/TargetInfo \ + lib/ExecutionEngine/JIT \ + lib/MC \ + )) + +TBLGEN := $(HOST_OUT_EXECUTABLES)/tblgen$(HOST_EXECUTABLE_SUFFIX) + +CLEAR_TBLGEN_VARS := $(LOCAL_PATH)/clear_tblgen_vars.mk +LLVM_HOST_BUILD_MK := $(LOCAL_PATH)/llvm-host-build.mk +LLVM_DEVICE_BUILD_MK := $(LOCAL_PATH)/llvm-device-build.mk +LLVM_GEN_INTRINSICS_MK := $(LOCAL_PATH)/llvm-gen-intrinsics.mk +LLVM_TBLGEN_RULES_MK := $(LOCAL_PATH)/tblgen-rules.mk + +include $(subdirs) diff --git a/CMakeLists.txt b/CMakeLists.txt index 216e0f6c65..96e06082fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ set(LLVM_ALL_TARGETS CellSPU CppBackend Mips + MBlaze MSIL MSP430 PIC16 diff --git a/CREDITS.TXT b/CREDITS.TXT index f6467abfc0..e58b85fdbd 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -335,3 +335,8 @@ D: Bunches of stuff N: Bob Wilson E: bob.wilson@acm.org D: Advanced SIMD (NEON) support in the ARM backend + +N: Wesley Peck +E: peckw@wesleypeck.com +W: http://wesleypeck.com/ +D: MicroBlaze backend diff --git a/Makefile b/Makefile index 319bdcd0fb..f5a9b336e3 100644 --- a/Makefile +++ b/Makefile @@ -30,8 +30,8 @@ ifeq ($(BUILD_DIRS_ONLY),1) DIRS := lib/System lib/Support utils OPTIONAL_DIRS := else - DIRS := lib/System lib/Support utils lib/VMCore lib tools/llvm-config \ - tools runtime docs unittests + DIRS := lib/System lib/Support utils lib/VMCore lib tools/llvm-shlib \ + tools/llvm-config tools runtime docs unittests OPTIONAL_DIRS := projects bindings endif @@ -43,12 +43,9 @@ EXTRA_DIST := test unittests llvm.spec include win32 Xcode include $(LEVEL)/Makefile.config -# llvm-gcc4 doesn't need runtime libs. llvm-gcc4 is the only supported one. -# FIXME: Remove runtime entirely once we have an understanding of where -# libprofile etc should go. -#ifeq ($(LLVMGCC_MAJVERS),4) -# DIRS := $(filter-out runtime, $(DIRS)) -#endif +ifneq ($(ENABLE_SHARED),1) + DIRS := $(filter-out tools/llvm-shlib, $(DIRS)) +endif ifeq ($(MAKECMDGOALS),libs-only) DIRS := $(filter-out tools runtime docs, $(DIRS)) diff --git a/Makefile.config.in b/Makefile.config.in index 2cc69dcf4c..1b61f0908a 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -76,14 +76,14 @@ endif LLVMMAKE := $(LLVM_SRC_ROOT)/make -PROJ_bindir := $(DESTDIR)$(PROJ_prefix)/bin -PROJ_libdir := $(DESTDIR)$(PROJ_prefix)/lib -PROJ_datadir := $(DESTDIR)$(PROJ_prefix)/share -PROJ_docsdir := $(DESTDIR)$(PROJ_prefix)/docs/llvm -PROJ_etcdir := $(DESTDIR)$(PROJ_prefix)/etc/llvm -PROJ_includedir := $(DESTDIR)$(PROJ_prefix)/include -PROJ_infodir := $(DESTDIR)$(PROJ_prefix)/info -PROJ_mandir := $(DESTDIR)$(PROJ_prefix)/share/man +PROJ_bindir := $(PROJ_prefix)/bin +PROJ_libdir := $(PROJ_prefix)/lib +PROJ_datadir := $(PROJ_prefix)/share +PROJ_docsdir := $(PROJ_prefix)/docs/llvm +PROJ_etcdir := $(PROJ_prefix)/etc/llvm +PROJ_includedir := $(PROJ_prefix)/include +PROJ_infodir := $(PROJ_prefix)/info +PROJ_mandir := $(PROJ_prefix)/share/man # Determine if we're on a unix type operating system LLVM_ON_UNIX:=@LLVM_ON_UNIX@ @@ -183,25 +183,21 @@ TARGETS_TO_BUILD=@TARGETS_TO_BUILD@ # want to override the value set by configure. LLVMGCCDIR := @LLVMGCCDIR@ -# Determine the target for which LLVM should generate code. -ifeq (@LLVMGCC_MAJVERS@,3) -LLVMGCCARCH := @target@/3.4-llvm -else -LLVMGCCARCH := @target@/@LLVMGCC_VERSION@ -endif - -# Determine the path where the library executables are -LLVMGCCLIBEXEC := @LLVMGCCLIBEXEC@ - # Full pathnames of LLVM C/C++ front-end 'cc1' and 'cc1plus' binaries: LLVMGCC := @LLVMGCC@ LLVMGXX := @LLVMGXX@ LLVMCC1 := @LLVMCC1@ LLVMCC1PLUS := @LLVMCC1PLUS@ -LLVMGCC_VERSION := @LLVMGCC_VERSION@ -LLVMGCC_MAJVERS := @LLVMGCC_MAJVERS@ LLVMGCC_LANGS := @LLVMGCC_LANGS@ +# Information on Clang, if configured. +CLANGPATH := @CLANGPATH@ +CLANGXXPATH := @CLANGXXPATH@ +ENABLE_BUILT_CLANG := @ENABLE_BUILT_CLANG@ + +# The LLVM capable compiler to use. +LLVMCC_OPTION := @LLVMCC_OPTION@ + # Path to directory where object files should be stored during a build. # Set OBJ_ROOT to "." if you do not want to use a separate place for # object files. @@ -266,6 +262,9 @@ ENABLE_THREADS := @ENABLE_THREADS@ # Do we want to build with position independent code? ENABLE_PIC := @ENABLE_PIC@ +# Do we want to build a shared library and link the tools with it? +ENABLE_SHARED := @ENABLE_SHARED@ + # Use -fvisibility-inlines-hidden? ENABLE_VISIBILITY_INLINES_HIDDEN := @ENABLE_VISIBILITY_INLINES_HIDDEN@ @@ -276,6 +275,9 @@ ENABLE_VISIBILITY_INLINES_HIDDEN := @ENABLE_VISIBILITY_INLINES_HIDDEN@ # Enable JIT for this platform TARGET_HAS_JIT = @TARGET_HAS_JIT@ +# Environment variable to set to change the runtime shared library search path. +SHLIBPATH_VAR = @SHLIBPATH_VAR@ + # Shared library extension for host platform. SHLIBEXT = @SHLIBEXT@ diff --git a/Makefile.rules b/Makefile.rules index 761cc812be..fcddd50c3a 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -493,7 +493,27 @@ ExmplDir := $(PROJ_OBJ_ROOT)/$(BuildMode)/examples LLVMLibDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/lib LLVMToolDir := $(LLVM_OBJ_ROOT)/$(BuildMode)/bin LLVMExmplDir:= $(LLVM_OBJ_ROOT)/$(BuildMode)/examples -CFERuntimeLibDir := $(LLVMGCCDIR)/lib + +#-------------------------------------------------------------------- +# LLVM Capable Compiler +#-------------------------------------------------------------------- + +ifeq ($(LLVMCC_OPTION),llvm-gcc) + LLVMCC := $(LLVMGCC) + LLVMCXX := $(LLVMGXX) +else + ifeq ($(LLVMCC_OPTION),clang) + ifneq ($(CLANGPATH),) + LLVMCC := $(CLANGPATH) + LLVMCXX := $(CLANGXXPATH) + else + ifeq ($(ENABLE_BUILT_CLANG),1) + LLVMCC := $(LLVMToolDir)/clang + LLVMCXX := $(LLVMToolDir)/clang++ + endif + endif + endif +endif #-------------------------------------------------------------------- # Full Paths To Compiled Tools and Utilities @@ -529,16 +549,6 @@ endif ifndef LBUGPOINT LBUGPOINT := $(LLVMToolDir)/bugpoint$(EXEEXT) endif -ifndef LUPGRADE -LUPGRADE := $(LLVMToolDir)/llvm-upgrade$(EXEEXT) -endif -ifeq ($(LLVMGCC_MAJVERS),3) -LLVMGCCWITHPATH := PATH="$(LLVMToolDir):$(PATH)" $(LLVMGCC) -LLVMGXXWITHPATH := PATH="$(LLVMToolDir):$(PATH)" $(LLVMGXX) -else -LLVMGCCWITHPATH := $(LLVMGCC) -LLVMGXXWITHPATH := $(LLVMGXX) -endif #-------------------------------------------------------------------- # Adjust to user's request @@ -613,11 +623,12 @@ endif ifneq ($(HOST_OS),Darwin) ifneq ($(DARWIN_MAJVERS),4) ifdef TOOLNAME -ifdef EXAMPLE_TOOL - LD.Flags += $(RPATH) -Wl,$(ExmplDir) $(RDYNAMIC) -else - LD.Flags += $(RPATH) -Wl,$(ToolDir) $(RDYNAMIC) -endif + LD.Flags += $(RPATH) -Wl,'$$ORIGIN/../lib' + ifdef EXAMPLE_TOOL + LD.Flags += $(RPATH) -Wl,$(ExmplDir) $(RDYNAMIC) + else + LD.Flags += $(RPATH) -Wl,$(ToolDir) $(RDYNAMIC) + endif endif endif endif @@ -710,14 +721,12 @@ else $(TargetCommonOpts) $(CompileCommonOpts) $(LD.Flags) $(Strip) endif -BCCompile.C = $(LLVMGCCWITHPATH) $(CPP.Flags) $(C.Flags) $(CFLAGS) \ - $(CPPFLAGS) \ +BCCompile.C = $(LLVMCC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) Preprocess.C = $(CC) $(CPP.Flags) $(C.Flags) $(CPPFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) -E -BCCompile.CXX = $(LLVMGXXWITHPATH) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ - $(CPPFLAGS) \ +BCCompile.CXX = $(LLVMCXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) ProgInstall = $(INSTALL) $(Install.StripFlag) -m 0755 @@ -772,7 +781,7 @@ ObjectsBC := $(BaseNameSources:%=$(ObjDir)/%.bc) # in the file so they get built before dependencies #--------------------------------------------------------- -$(PROJ_bindir) $(PROJ_libdir) $(PROJ_includedir) $(PROJ_etcdir):: +$(DESTDIR)$(PROJ_bindir) $(DESTDIR)$(PROJ_libdir) $(DESTDIR)$(PROJ_includedir) $(DESTDIR)$(PROJ_etcdir):: $(Verb) $(MKDIR) $@ # To create other directories, as needed, and timestamp their creation @@ -895,22 +904,22 @@ install-local:: uninstall-local:: $(Echo) UnInstall circumvented with NO_INSTALL else -install-local:: $(PROJ_etcdir) $(CONFIG_FILES) - $(Echo) Installing Configuration Files To $(PROJ_etcdir) +install-local:: $(DESTDIR)$(PROJ_etcdir) $(CONFIG_FILES) + $(Echo) Installing Configuration Files To $(DESTDIR)$(PROJ_etcdir) $(Verb)for file in $(CONFIG_FILES); do \ if test -f $(PROJ_OBJ_DIR)/$${file} ; then \ - $(DataInstall) $(PROJ_OBJ_DIR)/$${file} $(PROJ_etcdir) ; \ + $(DataInstall) $(PROJ_OBJ_DIR)/$${file} $(DESTDIR)$(PROJ_etcdir) ; \ elif test -f $(PROJ_SRC_DIR)/$${file} ; then \ - $(DataInstall) $(PROJ_SRC_DIR)/$${file} $(PROJ_etcdir) ; \ + $(DataInstall) $(PROJ_SRC_DIR)/$${file} $(DESTDIR)$(PROJ_etcdir) ; \ else \ $(ECHO) Error: cannot find config file $${file}. ; \ fi \ done uninstall-local:: - $(Echo) Uninstalling Configuration Files From $(PROJ_etcdir) + $(Echo) Uninstalling Configuration Files From $(DESTDIR)$(PROJ_etcdir) $(Verb)for file in $(CONFIG_FILES); do \ - $(RM) -f $(PROJ_etcdir)/$${file} ; \ + $(RM) -f $(DESTDIR)$(PROJ_etcdir)/$${file} ; \ done endif @@ -952,11 +961,16 @@ $(LLVM_CONFIG): $(ToolDir)/$(strip $(TOOLNAME))$(EXEEXT): $(LLVM_CONFIG) +ifeq ($(ENABLE_SHARED), 1) +LLVMLibsOptions += -lLLVM-$(LLVMVersion) +LLVMLibsPaths += $(LibDir)/libLLVM-$(LLVMVersion)$(SHLIBEXT) +else LLVMLibsOptions += $(shell $(LLVM_CONFIG) --libs $(LINK_COMPONENTS)) LLVMLibsPaths += $(LLVM_CONFIG) \ $(shell $(LLVM_CONFIG) --libfiles $(LINK_COMPONENTS)) endif endif +endif ############################################################################### # Library Build Rules: Four ways to build a library @@ -971,12 +985,12 @@ endif #--------------------------------------------------------- ifdef MODULE_NAME -ifeq ($(strip $(LLVMGCC)),) -$(warning Modules require llvm-gcc but no llvm-gcc is available ****) +ifeq ($(strip $(LLVMCC)),) +$(warning Modules require LLVM capable compiler but none is available ****) else Module := $(LibDir)/$(MODULE_NAME).bc -LinkModule := $(LLVMLD) -L$(CFERuntimeLibDir) -r +LinkModule := $(LLVMLD) -r ifdef EXPORTED_SYMBOL_FILE @@ -997,7 +1011,7 @@ endif ifdef BYTECODE_DESTINATION ModuleDestDir := $(BYTECODE_DESTINATION) else -ModuleDestDir := $(PROJ_libdir) +ModuleDestDir := $(DESTDIR)$(PROJ_libdir) endif ifdef NO_INSTALL @@ -1076,17 +1090,17 @@ install-local:: uninstall-local:: $(Echo) Uninstall circumvented with NO_INSTALL else -DestSharedLib = $(PROJ_libdir)/lib$(LIBRARYNAME)$(SHLIBEXT) +DestSharedLib = $(DESTDIR)$(PROJ_libdir)/lib$(LIBRARYNAME)$(SHLIBEXT) install-local:: $(DestSharedLib) -$(DestSharedLib): $(LibName.SO) $(PROJ_libdir) +$(DestSharedLib): $(LibName.SO) $(DESTDIR)$(PROJ_libdir) $(Echo) Installing $(BuildMode) Shared Library $(DestSharedLib) $(Verb) $(INSTALL) $(LibName.SO) $(DestSharedLib) uninstall-local:: $(Echo) Uninstalling $(BuildMode) Shared Library $(DestSharedLib) - -$(Verb) $(RM) -f $(PROJ_libdir)/lib$(LIBRARYNAME).* + -$(Verb) $(RM) -f $(DESTDIR)$(PROJ_libdir)/lib$(LIBRARYNAME).* endif endif @@ -1097,15 +1111,14 @@ endif # targets for building them. #--------------------------------------------------------- ifdef BYTECODE_LIBRARY -ifeq ($(strip $(LLVMGCC)),) -$(warning Bytecode libraries require llvm-gcc which could not be found ****) +ifeq ($(strip $(LLVMCC)),) +$(warning Bytecode libraries require LLVM capable compiler but none is available ****) else all-local:: $(LibName.BCA) ifdef EXPORTED_SYMBOL_FILE -BCLinkLib = $(LLVMLD) -L$(CFERuntimeLibDir) \ - -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) +BCLinkLib = $(LLVMLD) -internalize-public-api-file=$(EXPORTED_SYMBOL_FILE) $(LibName.BCA): $(ObjectsBC) $(LibDir)/.dir $(LLVMLD) \ $(LLVMToolDir)/llvm-ar @@ -1131,7 +1144,7 @@ endif ifdef BYTECODE_DESTINATION BytecodeDestDir := $(BYTECODE_DESTINATION) else -BytecodeDestDir := $(PROJ_libdir) +BytecodeDestDir := $(DESTDIR)$(PROJ_libdir) endif DestBytecodeLib = $(BytecodeDestDir)/lib$(LIBRARYNAME).bca @@ -1162,11 +1175,13 @@ endif # If neither BUILD_ARCHIVE or LOADABLE_MODULE are specified, default to # building an archive. #--------------------------------------------------------- +ifndef NO_BUILD_ARCHIVE ifndef BUILD_ARCHIVE ifndef LOADABLE_MODULE BUILD_ARCHIVE = 1 endif endif +endif #--------------------------------------------------------- # Archive Library Targets: @@ -1194,13 +1209,13 @@ install-local:: uninstall-local:: $(Echo) Uninstall circumvented with NO_INSTALL else -DestArchiveLib := $(PROJ_libdir)/lib$(LIBRARYNAME).a +DestArchiveLib := $(DESTDIR)$(PROJ_libdir)/lib$(LIBRARYNAME).a install-local:: $(DestArchiveLib) -$(DestArchiveLib): $(LibName.A) $(PROJ_libdir) +$(DestArchiveLib): $(LibName.A) $(DESTDIR)$(PROJ_libdir) $(Echo) Installing $(BuildMode) Archive Library $(DestArchiveLib) - $(Verb) $(MKDIR) $(PROJ_libdir) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_libdir) $(Verb) $(INSTALL) $(LibName.A) $(DestArchiveLib) uninstall-local:: @@ -1300,11 +1315,11 @@ install-local:: uninstall-local:: $(Echo) Uninstall circumvented with NO_INSTALL else -DestTool = $(PROJ_bindir)/$(TOOLEXENAME) +DestTool = $(DESTDIR)$(PROJ_bindir)/$(TOOLEXENAME) install-local:: $(DestTool) -$(DestTool): $(ToolBuildPath) $(PROJ_bindir) +$(DestTool): $(ToolBuildPath) $(DESTDIR)$(PROJ_bindir) $(Echo) Installing $(BuildMode) $(DestTool) $(Verb) $(ProgInstall) $(ToolBuildPath) $(DestTool) @@ -1382,19 +1397,19 @@ BC_DEPEND_OPTIONS = -MMD -MP -MF "$(ObjDir)/$*.bc.d.tmp" \ BC_DEPEND_MOVEFILE = then $(MV) -f "$(ObjDir)/$*.bc.d.tmp" "$(ObjDir)/$*.bc.d"; \ else $(RM) "$(ObjDir)/$*.bc.d.tmp"; exit 1; fi -$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGXX) +$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) $(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)" $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ $< -o $(ObjDir)/$*.ll -S -emit-llvm ; \ $(BC_DEPEND_MOVEFILE) -$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGXX) +$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) $(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)" $(Verb) if $(BCCompile.CXX) $(BC_DEPEND_OPTIONS) \ $< -o $(ObjDir)/$*.ll -S -emit-llvm ; \ $(BC_DEPEND_MOVEFILE) -$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGCC) +$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) $(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)" $(Verb) if $(BCCompile.C) $(BC_DEPEND_OPTIONS) \ $< -o $(ObjDir)/$*.ll -S -emit-llvm ; \ @@ -1415,15 +1430,15 @@ $(ObjDir)/%.o: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(Echo) "Compiling $*.c for $(BuildMode) build" $(PIC_FLAG) $(Compile.C) $< -o $@ -$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGXX) +$(ObjDir)/%.ll: %.cpp $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) $(Echo) "Compiling $*.cpp for $(BuildMode) build (bytecode)" $(BCCompile.CXX) $< -o $@ -S -emit-llvm -$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGXX) +$(ObjDir)/%.ll: %.cc $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCXX) $(Echo) "Compiling $*.cc for $(BuildMode) build (bytecode)" $(BCCompile.CXX) $< -o $@ -S -emit-llvm -$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMGCC) +$(ObjDir)/%.ll: %.c $(ObjDir)/.dir $(BUILT_SOURCES) $(LLVMCC) $(Echo) "Compiling $*.c for $(BuildMode) build (bytecode)" $(BCCompile.C) $< -o $@ -S -emit-llvm @@ -1949,25 +1964,25 @@ uninstall-local:: else install-local:: $(Echo) Installing include files - $(Verb) $(MKDIR) $(PROJ_includedir) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir) $(Verb) if test -d "$(PROJ_SRC_ROOT)/include" ; then \ cd $(PROJ_SRC_ROOT)/include && \ for hdr in `find . -type f '!' '(' -name '*~' \ -o -name '.#*' -o -name '*.in' ')' -print | grep -v CVS | \ grep -v .svn` ; do \ - instdir=`dirname "$(PROJ_includedir)/$$hdr"` ; \ + instdir=`dirname "$(DESTDIR)$(PROJ_includedir)/$$hdr"` ; \ if test \! -d "$$instdir" ; then \ $(EchoCmd) Making install directory $$instdir ; \ $(MKDIR) $$instdir ;\ fi ; \ - $(DataInstall) $$hdr $(PROJ_includedir)/$$hdr ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ done ; \ fi ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) $(Verb) if test -d "$(PROJ_OBJ_ROOT)/include" ; then \ cd $(PROJ_OBJ_ROOT)/include && \ for hdr in `find . -type f -print | grep -v CVS` ; do \ - $(DataInstall) $$hdr $(PROJ_includedir)/$$hdr ; \ + $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ done ; \ fi endif @@ -1979,10 +1994,10 @@ uninstall-local:: $(RM) -f `find . -path '*/Internal' -prune -o '(' -type f \ '!' '(' -name '*~' -o -name '.#*' \ -o -name '*.in' ')' -print ')' | \ - grep -v CVS | sed 's#^#$(PROJ_includedir)/#'` ; \ + grep -v CVS | sed 's#^#$(DESTDIR)$(PROJ_includedir)/#'` ; \ cd $(PROJ_SRC_ROOT)/include && \ $(RM) -f `find . -path '*/Internal' -prune -o '(' -type f -name '*.in' \ - -print ')' | sed 's#\.in$$##;s#^#$(PROJ_includedir)/#'` ; \ + -print ')' | sed 's#\.in$$##;s#^#$(DESTDIR)$(PROJ_includedir)/#'` ; \ fi endif endif diff --git a/README.txt b/README.txt index 6c2dbb0ad4..2ebe271b8e 100644 --- a/README.txt +++ b/README.txt @@ -11,4 +11,5 @@ the license agreement found in LICENSE.txt. Please see the HTML documentation provided in docs/index.html for further assistance with LLVM. - +If you're writing a package for LLVM, see docs/Packaging.html for our +suggestions. diff --git a/Xcode/LLVM.xcodeproj/project.pbxproj b/Xcode/LLVM.xcodeproj/project.pbxproj deleted file mode 100644 index e2f40f4cba..0000000000 --- a/Xcode/LLVM.xcodeproj/project.pbxproj +++ /dev/null @@ -1,3303 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 42; - objects = { - -/* Begin PBXAggregateTarget section */ - CF0329BC08D1BE8E0030FD33 /* LLVM full llc */ = { - isa = PBXAggregateTarget; - buildConfigurationList = CF0329C708D1BEC40030FD33 /* Build configuration list for PBXAggregateTarget "LLVM full llc" */; - buildPhases = ( - ); - dependencies = ( - CF0329BE08D1BE970030FD33 /* PBXTargetDependency */, - CF0329C008D1BE9B0030FD33 /* PBXTargetDependency */, - ); - name = "LLVM full llc"; - productName = "LLVM full llc"; - }; - CFDF86D00ADE820000D40A3D /* LLVM full llc release */ = { - isa = PBXAggregateTarget; - buildConfigurationList = CFDF86D50ADE820000D40A3D /* Build configuration list for PBXAggregateTarget "LLVM full llc release" */; - buildPhases = ( - ); - dependencies = ( - CFDF86DA0ADE822100D40A3D /* PBXTargetDependency */, - CFDF86DC0ADE822100D40A3D /* PBXTargetDependency */, - ); - name = "LLVM full llc release"; - productName = "LLVM full llc"; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXContainerItemProxy section */ - CF0329BD08D1BE970030FD33 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = CF0329B608D1BE110030FD33; - remoteInfo = "LLVM lib"; - }; - CF0329BF08D1BE9B0030FD33 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = CF0329BB08D1BE5D0030FD33; - remoteInfo = "LLVM llc"; - }; - CFDF86D90ADE822100D40A3D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = CFDF86BD0ADE819D00D40A3D; - remoteInfo = "LLVM lib release"; - }; - CFDF86DB0ADE822100D40A3D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = CFDF86C60ADE81D000D40A3D; - remoteInfo = "LLVM llc release"; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 354CF6D10CD299440059AF3E /* DeserializeAPInt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeserializeAPInt.cpp; sourceTree = ""; }; - 354CF6D20CD2994D0059AF3E /* SerializeAPInt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SerializeAPInt.cpp; sourceTree = ""; }; - 35A9CDED0CD0F6AF008ABC1D /* Deserialize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deserialize.h; sourceTree = ""; }; - 35A9CDEE0CD0F6AF008ABC1D /* Serialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Serialization.h; sourceTree = ""; }; - 35A9CDEF0CD0F6AF008ABC1D /* Serialize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Serialize.h; sourceTree = ""; }; - 35A9CDF00CD0F6D5008ABC1D /* Deserialize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Deserialize.cpp; sourceTree = ""; }; - 35A9CDF10CD0F6E1008ABC1D /* Serialize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Serialize.cpp; sourceTree = ""; }; - 35E98A830CBC2ED300C5CDC1 /* DenseSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DenseSet.h; sourceTree = ""; }; - 35E98A840CBC2ED300C5CDC1 /* ImmutableMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImmutableMap.h; sourceTree = ""; }; - 35E98A850CBC2ED300C5CDC1 /* ImmutableSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImmutableSet.h; sourceTree = ""; }; - 754221420D171DFC00DDB61B /* MachineLICM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MachineLICM.cpp; sourceTree = ""; }; - 84115FFE0B66D87400E1293E /* TargetMachOWriterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetMachOWriterInfo.cpp; sourceTree = ""; }; - 84115FFF0B66D89B00E1293E /* PPCMachOWriterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PPCMachOWriterInfo.cpp; sourceTree = ""; }; - 841160000B66D8AC00E1293E /* PPCMachOWriterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PPCMachOWriterInfo.h; sourceTree = ""; }; - 8443EF210B66B62D00959964 /* TargetMachOWriterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetMachOWriterInfo.h; sourceTree = ""; }; - 9F4B0E5E0D0E02580061F270 /* bitreader_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bitreader_ocaml.c; sourceTree = ""; }; - 9F4B0E5F0D0E02580061F270 /* llvm_bitreader.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_bitreader.ml; sourceTree = ""; }; - 9F4B0E600D0E02580061F270 /* llvm_bitreader.mli */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_bitreader.mli; sourceTree = ""; }; - 9F4B0E8C0D0E05ED0061F270 /* BitReader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitReader.cpp; sourceTree = ""; }; - 9F4B0E8D0D0E05ED0061F270 /* DeserializeAPFloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DeserializeAPFloat.cpp; sourceTree = ""; }; - 9F502ADB0D1D8CA3007939DF /* executionengine_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = executionengine_ocaml.c; sourceTree = ""; }; - 9F502ADC0D1D8CA3007939DF /* llvm_executionengine.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_executionengine.ml; sourceTree = ""; }; - 9F502ADD0D1D8CA3007939DF /* llvm_executionengine.mli */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_executionengine.mli; sourceTree = ""; }; - 9F502AEC0D1D8CF8007939DF /* executionengine.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = executionengine.ml; sourceTree = ""; }; - 9F502B090D1D8D8D007939DF /* ExecutionEngineBindings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutionEngineBindings.cpp; sourceTree = ""; }; - 9F5B90CB0D0CE87100CDFDEA /* StringPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringPool.cpp; sourceTree = ""; }; - 9F5B90CE0D0CE89300CDFDEA /* AlignOf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlignOf.h; sourceTree = ""; }; - 9F5B90CF0D0CE89300CDFDEA /* Registry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Registry.h; sourceTree = ""; }; - 9F5B90D00D0CE89300CDFDEA /* StringPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringPool.h; sourceTree = ""; }; - 9F5B90E70D0DF19100CDFDEA /* BitReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitReader.h; sourceTree = ""; }; - 9F68EB010C77AD02004AA152 /* LoopPass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LoopPass.cpp; sourceTree = ""; }; - 9F68EB020C77AD02004AA152 /* MemoryDependenceAnalysis.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryDependenceAnalysis.cpp; sourceTree = ""; }; - 9F68EB060C77AD2C004AA152 /* BitcodeReader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BitcodeReader.cpp; sourceTree = ""; }; - 9F68EB070C77AD2C004AA152 /* BitcodeReader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BitcodeReader.h; sourceTree = ""; }; - 9F68EB120C77AD2C004AA152 /* BitcodeWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BitcodeWriter.cpp; sourceTree = ""; }; - 9F68EB130C77AD2C004AA152 /* BitcodeWriterPass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BitcodeWriterPass.cpp; sourceTree = ""; }; - 9F68EB250C77AD2C004AA152 /* ValueEnumerator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ValueEnumerator.cpp; sourceTree = ""; }; - 9F68EB260C77AD2C004AA152 /* ValueEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ValueEnumerator.h; sourceTree = ""; }; - 9F6B2CC00D0F6E56000F00FD /* bitreader.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bitreader.ml; sourceTree = ""; }; - 9F70401A0D8D732400FD06FF /* llvm_scalar_opts.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = llvm_scalar_opts.ml; path = transforms/scalar/llvm_scalar_opts.ml; sourceTree = ""; }; - 9F70401B0D8D732400FD06FF /* llvm_scalar_opts.mli */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = llvm_scalar_opts.mli; path = transforms/scalar/llvm_scalar_opts.mli; sourceTree = ""; }; - 9F70401E0D8D735E00FD06FF /* scalar_opts_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = scalar_opts_ocaml.c; path = transforms/scalar/scalar_opts_ocaml.c; sourceTree = ""; }; - 9F7793460C73BC2000551F9C /* CodeGenPrepare.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenPrepare.cpp; sourceTree = ""; }; - 9F7793470C73BC2000551F9C /* GVN.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GVN.cpp; sourceTree = ""; }; - 9F7793480C73BC2000551F9C /* GVNPRE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GVNPRE.cpp; sourceTree = ""; }; - 9F7793490C73BC2000551F9C /* LoopIndexSplit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoopIndexSplit.cpp; sourceTree = ""; }; - 9F77934A0C73BC2000551F9C /* LoopRotation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LoopRotation.cpp; sourceTree = ""; }; - 9F7793500C73BD1500551F9C /* ELFWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELFWriter.h; sourceTree = ""; }; - 9F7793510C73BD1500551F9C /* IfConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IfConversion.cpp; sourceTree = ""; }; - 9F7793520C73BD1500551F9C /* LowerSubregs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LowerSubregs.cpp; sourceTree = ""; }; - 9F7793530C73BD1500551F9C /* MachOWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachOWriter.h; sourceTree = ""; }; - 9F7793540C73BD1500551F9C /* PostRASchedulerList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PostRASchedulerList.cpp; sourceTree = ""; }; - 9F7793550C73BD1500551F9C /* RegAllocBigBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegAllocBigBlock.cpp; sourceTree = ""; }; - 9F7793560C73BD1500551F9C /* RegisterScavenging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterScavenging.cpp; sourceTree = ""; }; - 9F7793570C73BD1500551F9C /* SimpleRegisterCoalescing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimpleRegisterCoalescing.cpp; sourceTree = ""; }; - 9F7793770C73C48A00551F9C /* StripDeadPrototypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StripDeadPrototypes.cpp; sourceTree = ""; }; - 9F7793780C73C49A00551F9C /* BasicInliner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BasicInliner.cpp; sourceTree = ""; }; - 9F7793790C73C49A00551F9C /* CloneLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CloneLoop.cpp; sourceTree = ""; }; - 9F77937A0C73C49A00551F9C /* InlineCost.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InlineCost.cpp; sourceTree = ""; }; - 9F77937B0C73C4F400551F9C /* AutoUpgrade.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AutoUpgrade.cpp; path = ../lib/VMCore/AutoUpgrade.cpp; sourceTree = SOURCE_ROOT; }; - 9F77937C0C73C4F400551F9C /* ConstantFold.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConstantFold.cpp; path = ../lib/VMCore/ConstantFold.cpp; sourceTree = SOURCE_ROOT; }; - 9F77937D0C73C4F400551F9C /* ConstantFold.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ConstantFold.h; path = ../lib/VMCore/ConstantFold.h; sourceTree = SOURCE_ROOT; }; - 9F77937E0C73C53000551F9C /* ParameterAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParameterAttributes.h; sourceTree = ""; }; - 9F7793800C73C54C00551F9C /* Archive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Archive.h; sourceTree = ""; }; - 9F7793810C73C54C00551F9C /* BitCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitCodes.h; sourceTree = ""; }; - 9F7793820C73C54C00551F9C /* BitstreamReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitstreamReader.h; sourceTree = ""; }; - 9F7793830C73C54C00551F9C /* BitstreamWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitstreamWriter.h; sourceTree = ""; }; - 9F7793840C73C54C00551F9C /* LLVMBitCodes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLVMBitCodes.h; sourceTree = ""; }; - 9F7793850C73C54C00551F9C /* ReaderWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderWriter.h; sourceTree = ""; }; - 9F7793860C73C57100551F9C /* CallingConvLower.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallingConvLower.h; sourceTree = ""; }; - 9F7793870C73C57100551F9C /* ELFRelocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELFRelocation.h; sourceTree = ""; }; - 9F7793880C73C57100551F9C /* FileWriters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileWriters.h; sourceTree = ""; }; - 9F7793890C73C57100551F9C /* MachORelocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachORelocation.h; sourceTree = ""; }; - 9F77938A0C73C57100551F9C /* RegisterScavenging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterScavenging.h; sourceTree = ""; }; - 9F7794140C73CB6100551F9C /* Mips.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Mips.h; sourceTree = ""; }; - 9F7794150C73CB6100551F9C /* Mips.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Mips.td; sourceTree = ""; }; - 9F7794160C73CB6100551F9C /* MipsAsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MipsAsmPrinter.cpp; sourceTree = ""; }; - 9F7794170C73CB6100551F9C /* MipsCallingConv.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MipsCallingConv.td; sourceTree = ""; }; - 9F7794180C73CB6100551F9C /* MipsInstrFormats.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MipsInstrFormats.td; sourceTree = ""; }; - 9F7794190C73CB6100551F9C /* MipsInstrInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MipsInstrInfo.cpp; sourceTree = ""; }; - 9F77941A0C73CB6100551F9C /* MipsInstrInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MipsInstrInfo.h; sourceTree = ""; }; - 9F77941B0C73CB6100551F9C /* MipsInstrInfo.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MipsInstrInfo.td; sourceTree = ""; }; - 9F77941C0C73CB6100551F9C /* MipsISelDAGToDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MipsISelDAGToDAG.cpp; sourceTree = ""; }; - 9F77941D0C73CB6100551F9C /* MipsISelLowering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MipsISelLowering.cpp; sourceTree = ""; }; - 9F77941E0C73CB6100551F9C /* MipsISelLowering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MipsISelLowering.h; sourceTree = ""; }; - 9F77941F0C73CB6100551F9C /* MipsMachineFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MipsMachineFunction.h; sourceTree = ""; }; - 9F7794200C73CB6100551F9C /* MipsRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MipsRegisterInfo.cpp; sourceTree = ""; }; - 9F7794210C73CB6100551F9C /* MipsRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MipsRegisterInfo.h; sourceTree = ""; }; - 9F7794220C73CB6100551F9C /* MipsRegisterInfo.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = MipsRegisterInfo.td; sourceTree = ""; }; - 9F7794230C73CB6100551F9C /* MipsSubtarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MipsSubtarget.cpp; sourceTree = ""; }; - 9F7794240C73CB6100551F9C /* MipsSubtarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MipsSubtarget.h; sourceTree = ""; }; - 9F7794250C73CB6100551F9C /* MipsTargetAsmInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MipsTargetAsmInfo.cpp; sourceTree = ""; }; - 9F7794260C73CB6100551F9C /* MipsTargetAsmInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MipsTargetAsmInfo.h; sourceTree = ""; }; - 9F7794270C73CB6100551F9C /* MipsTargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MipsTargetMachine.cpp; sourceTree = ""; }; - 9F7794280C73CB6100551F9C /* MipsTargetMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MipsTargetMachine.h; sourceTree = ""; }; - 9F77942F0C73CB7900551F9C /* MSILWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MSILWriter.cpp; sourceTree = ""; }; - 9F7794300C73CB7900551F9C /* MSILWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MSILWriter.h; sourceTree = ""; }; - 9F7794880C73D51000551F9C /* MemoryBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryBuffer.h; sourceTree = ""; }; - 9F7794890C73D51000551F9C /* Streams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Streams.h; sourceTree = ""; }; - 9F7C23E50CB81C2100498408 /* Analysis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Analysis.h; sourceTree = ""; }; - 9F7C23E60CB81C2B00498408 /* Analysis.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Analysis.cpp; sourceTree = ""; }; - 9F7C240C0CB81ECD00498408 /* analysis_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = analysis_ocaml.c; sourceTree = ""; }; - 9F7C240D0CB81ECD00498408 /* llvm_analysis.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_analysis.ml; sourceTree = ""; }; - 9F7C240E0CB81ECD00498408 /* llvm_analysis.mli */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_analysis.mli; sourceTree = ""; }; - 9F7C2C4F0CB9496C00498408 /* analysis.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = analysis.ml; sourceTree = ""; }; - 9F7C2C520CB9496C00498408 /* bitwriter.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = bitwriter.ml; sourceTree = ""; }; - 9F7C2C5D0CB9496C00498408 /* vmcore.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = vmcore.ml; sourceTree = ""; }; - 9FA638D90C77B184007F12AE /* AutoUpgrade.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AutoUpgrade.h; sourceTree = ""; }; - 9FA638DA0C77B184007F12AE /* GlobalAlias.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GlobalAlias.h; sourceTree = ""; }; - 9FA638DB0C77B1AB007F12AE /* APInt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = APInt.h; sourceTree = ""; }; - 9FA638DC0C77B1AB007F12AE /* APSInt.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = APSInt.h; sourceTree = ""; }; - 9FA638DD0C77B1AB007F12AE /* BitVector.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BitVector.h; sourceTree = ""; }; - 9FA638E00C77B1AB007F12AE /* IndexedMap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IndexedMap.h; sourceTree = ""; }; - 9FA638E20C77B1AB007F12AE /* SmallPtrSet.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SmallPtrSet.h; sourceTree = ""; }; - 9FA638E30C77B1AB007F12AE /* SmallSet.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SmallSet.h; sourceTree = ""; }; - 9FA638E40C77B1AB007F12AE /* StringMap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StringMap.h; sourceTree = ""; }; - 9FA638E50C77B203007F12AE /* LoopPass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LoopPass.h; sourceTree = ""; }; - 9FA638E60C77B203007F12AE /* MemoryDependenceAnalysis.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MemoryDependenceAnalysis.h; sourceTree = ""; }; - 9FA638E70C77B222007F12AE /* Disassembler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Disassembler.h; sourceTree = ""; }; - 9FA638E80C77B231007F12AE /* TargetELFWriterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetELFWriterInfo.h; sourceTree = ""; }; - 9FA638EA0C77B252007F12AE /* InlinerPass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InlinerPass.h; sourceTree = ""; }; - 9FA638EB0C77B26B007F12AE /* BasicInliner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BasicInliner.h; sourceTree = ""; }; - 9FA638EC0C77B26B007F12AE /* InlineCost.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InlineCost.h; sourceTree = ""; }; - 9FD3E5710CA0116100E54D15 /* bitwriter_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = bitwriter_ocaml.c; sourceTree = ""; }; - 9FD3E5720CA0116100E54D15 /* llvm_bitwriter.ml */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llvm_bitwriter.ml; sourceTree = ""; }; - 9FD3E5730CA0116100E54D15 /* llvm_bitwriter.mli */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llvm_bitwriter.mli; sourceTree = ""; }; - 9FD3E57B0CA0116100E54D15 /* llvm.ml */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llvm.ml; sourceTree = ""; }; - 9FD3E57C0CA0116100E54D15 /* llvm.mli */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llvm.mli; sourceTree = ""; }; - 9FD3E57D0CA0116100E54D15 /* llvm_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; path = llvm_ocaml.c; sourceTree = ""; }; - 9FD3E58D0CA0125F00E54D15 /* BitWriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BitWriter.h; sourceTree = ""; }; - 9FD3E58E0CA0125F00E54D15 /* Core.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Core.h; sourceTree = ""; }; - 9FD3E5900CA0129D00E54D15 /* Core.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Core.cpp; path = ../lib/VMCore/Core.cpp; sourceTree = SOURCE_ROOT; }; - 9FD3E5920CA012B300E54D15 /* BitWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BitWriter.cpp; sourceTree = ""; }; - 9FE25D900CAB166D005383FC /* APFloat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APFloat.h; sourceTree = ""; }; - 9FE25D910CAB166D005383FC /* SparseBitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SparseBitVector.h; sourceTree = ""; }; - 9FE25D920CAB169F005383FC /* RegisterCoalescer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterCoalescer.h; sourceTree = ""; }; - 9FE25D940CAB16FB005383FC /* RegisterCoalescer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterCoalescer.cpp; sourceTree = ""; }; - 9FE25D950CAB1724005383FC /* APFloat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = APFloat.cpp; sourceTree = ""; }; - 9FE25D960CAB1759005383FC /* TargetCallingConv.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TargetCallingConv.td; sourceTree = ""; }; - 9FE4508B0C77A77000C4FEA4 /* ARMCodeEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ARMCodeEmitter.cpp; sourceTree = ""; }; - 9FE4508C0C77A77000C4FEA4 /* ARMGenAsmWriter.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = ARMGenAsmWriter.inc; sourceTree = ""; }; - 9FE4508D0C77A77000C4FEA4 /* ARMGenDAGISel.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = ARMGenDAGISel.inc; sourceTree = ""; }; - 9FE4508E0C77A77100C4FEA4 /* ARMGenInstrInfo.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = ARMGenInstrInfo.inc; sourceTree = ""; }; - 9FE4508F0C77A77100C4FEA4 /* ARMGenInstrNames.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = ARMGenInstrNames.inc; sourceTree = ""; }; - 9FE450900C77A77100C4FEA4 /* ARMGenRegisterInfo.h.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = ARMGenRegisterInfo.h.inc; sourceTree = ""; }; - 9FE450910C77A77100C4FEA4 /* ARMGenRegisterInfo.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = ARMGenRegisterInfo.inc; sourceTree = ""; }; - 9FE450920C77A77100C4FEA4 /* ARMGenRegisterNames.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = ARMGenRegisterNames.inc; sourceTree = ""; }; - 9FE450930C77A77100C4FEA4 /* ARMGenSubtarget.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = ARMGenSubtarget.inc; sourceTree = ""; }; - 9FE450940C77A77100C4FEA4 /* ARMJITInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ARMJITInfo.cpp; sourceTree = ""; }; - 9FE450950C77A77100C4FEA4 /* ARMJITInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ARMJITInfo.h; sourceTree = ""; }; - 9FE450960C77A77100C4FEA4 /* ARMRelocations.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ARMRelocations.h; sourceTree = ""; }; - 9FE450970C77A77100C4FEA4 /* README-Thumb.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "README-Thumb.txt"; sourceTree = ""; }; - 9FE450980C77A77100C4FEA4 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; - 9FE4509A0C77A79C00C4FEA4 /* PPCCallingConv.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = PPCCallingConv.td; sourceTree = ""; }; - 9FE4509B0C77A79C00C4FEA4 /* PPCGenCallingConv.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = PPCGenCallingConv.inc; sourceTree = ""; }; - 9FE4509C0C77A7BC00C4FEA4 /* README-MMX.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "README-MMX.txt"; sourceTree = ""; }; - 9FE4509D0C77A7BC00C4FEA4 /* X86CallingConv.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = X86CallingConv.td; sourceTree = ""; }; - 9FE4509F0C77A7BC00C4FEA4 /* X86ELFWriterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86ELFWriterInfo.cpp; sourceTree = ""; }; - 9FE450A00C77A7BC00C4FEA4 /* X86ELFWriterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86ELFWriterInfo.h; sourceTree = ""; }; - 9FE450A10C77A7BC00C4FEA4 /* X86GenCallingConv.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; path = X86GenCallingConv.inc; sourceTree = ""; }; - 9FE450A20C77A7BC00C4FEA4 /* X86InstrFormats.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = X86InstrFormats.td; sourceTree = ""; }; - 9FE450A50C77AAF000C4FEA4 /* Disassembler.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Disassembler.cpp; sourceTree = ""; }; - 9FE450A60C77AB3200C4FEA4 /* APInt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = APInt.cpp; sourceTree = ""; }; - 9FE450A70C77AB3200C4FEA4 /* ConstantRange.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantRange.cpp; sourceTree = ""; }; - 9FE450A80C77AB3200C4FEA4 /* MemoryBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryBuffer.cpp; sourceTree = ""; }; - 9FE450A90C77AB3200C4FEA4 /* SmallPtrSet.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SmallPtrSet.cpp; sourceTree = ""; }; - 9FE450AA0C77AB3200C4FEA4 /* StringMap.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StringMap.cpp; sourceTree = ""; }; - 9FE450AB0C77AB6100C4FEA4 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; - 9FE450AC0C77AB6E00C4FEA4 /* CallingConvLower.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CallingConvLower.cpp; sourceTree = ""; }; - 9FE450DF0C77ABE400C4FEA4 /* Archive.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Archive.cpp; sourceTree = ""; }; - 9FE450E00C77ABE400C4FEA4 /* ArchiveInternals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ArchiveInternals.h; sourceTree = ""; }; - 9FE450E10C77ABE400C4FEA4 /* ArchiveReader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ArchiveReader.cpp; sourceTree = ""; }; - 9FE450E20C77ABE400C4FEA4 /* ArchiveWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ArchiveWriter.cpp; sourceTree = ""; }; - 9FEB8C550D1CD1E200EE46BC /* ExecutionEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionEngine.h; sourceTree = ""; }; - 9FEDD5F10D8D73AB009F6DF1 /* Scalar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Scalar.h; sourceTree = ""; }; - 9FEDD5F70D8D797D009F6DF1 /* Scalar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Scalar.cpp; sourceTree = ""; }; - 9FEDD6140D8D7C3B009F6DF1 /* scalar_opts.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = scalar_opts.ml; sourceTree = ""; }; - 9FEDD6B60D8D83D0009F6DF1 /* Target.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Target.cpp; sourceTree = ""; }; - 9FEDD6B80D8D83EC009F6DF1 /* Target.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Target.h; sourceTree = ""; }; - 9FEDD6BB0D8D8408009F6DF1 /* lto.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lto.h; sourceTree = ""; }; - 9FEDD6BD0D8D8426009F6DF1 /* target.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = target.ml; sourceTree = ""; }; - 9FEDD6C10D8D844E009F6DF1 /* llvm_target.ml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_target.ml; sourceTree = ""; }; - 9FEDD6C20D8D844E009F6DF1 /* llvm_target.mli */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = llvm_target.mli; sourceTree = ""; }; - 9FEDD6C40D8D844E009F6DF1 /* target_ocaml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = target_ocaml.c; sourceTree = ""; }; - CF1ACC9709C9DE4400D3C5EB /* IntrinsicInst.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IntrinsicInst.cpp; path = ../lib/VMCore/IntrinsicInst.cpp; sourceTree = ""; }; - CF26835B09178F5500C5F253 /* TargetInstrItineraries.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetInstrItineraries.h; sourceTree = ""; }; - CF32AF5C0AEE6A4E00D24CD4 /* LLVMTargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LLVMTargetMachine.cpp; sourceTree = ""; }; - CF33BE160AF62B4200E93805 /* SmallString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmallString.h; sourceTree = ""; }; - CF341DAD0AB07A8B0099B064 /* AlphaTargetAsmInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlphaTargetAsmInfo.h; sourceTree = ""; }; - CF341DAE0AB07A8B0099B064 /* AlphaTargetAsmInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaTargetAsmInfo.cpp; sourceTree = ""; }; - CF341E010AB080220099B064 /* PPCTargetAsmInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCTargetAsmInfo.h; sourceTree = ""; }; - CF341E020AB080220099B064 /* PPCTargetAsmInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCTargetAsmInfo.cpp; sourceTree = ""; }; - CF341E220AB0814B0099B064 /* SparcTargetAsmInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SparcTargetAsmInfo.h; sourceTree = ""; }; - CF341E230AB0814B0099B064 /* SparcTargetAsmInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SparcTargetAsmInfo.cpp; sourceTree = ""; }; - CF341E320AB082D60099B064 /* X86TargetAsmInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86TargetAsmInfo.h; sourceTree = ""; }; - CF341E330AB082D60099B064 /* X86TargetAsmInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = X86TargetAsmInfo.cpp; sourceTree = ""; }; - CF42B6BF0AF24F5300D5D47C /* FoldingSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FoldingSet.h; sourceTree = ""; }; - CF42B6C40AF2512000D5D47C /* FoldingSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FoldingSet.cpp; sourceTree = ""; }; - CF47BD380AAF40BC00A8B13E /* TargetAsmInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TargetAsmInfo.h; sourceTree = ""; }; - CF47BD860AAF487E00A8B13E /* TargetAsmInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TargetAsmInfo.cpp; sourceTree = ""; }; - CF490D14090541D30072DB1C /* TargetSchedule.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TargetSchedule.td; sourceTree = ""; }; - CF490D15090541D30072DB1C /* TargetSelectionDAG.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TargetSelectionDAG.td; sourceTree = ""; }; - CF490E2F0907BBF80072DB1C /* SubtargetEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubtargetEmitter.h; sourceTree = ""; }; - CF490E300907BBF80072DB1C /* SubtargetEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SubtargetEmitter.cpp; sourceTree = ""; }; - CF4F27E60A7B6E23004359F6 /* MachinePassRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachinePassRegistry.h; sourceTree = ""; }; - CF4F27F60A7B6FA3004359F6 /* MachinePassRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MachinePassRegistry.cpp; sourceTree = ""; }; - CF65223409CA39B800C4B521 /* Intrinsics.gen */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Intrinsics.gen; sourceTree = ""; }; - CF6527D909D1A53400C4B521 /* MachineLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachineLocation.h; sourceTree = ""; }; - CF6527FA09D1BA3800C4B521 /* DelaySlotFiller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DelaySlotFiller.cpp; path = ../lib/Target/Sparc/DelaySlotFiller.cpp; sourceTree = SOURCE_ROOT; }; - CF6527FB09D1BA3800C4B521 /* FPMover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FPMover.cpp; path = ../lib/Target/Sparc/FPMover.cpp; sourceTree = SOURCE_ROOT; }; - CF6527FC09D1BA3800C4B521 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; name = Makefile; path = ../lib/Target/Sparc/Makefile; sourceTree = SOURCE_ROOT; }; - CF6527FD09D1BA3800C4B521 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = ../lib/Target/Sparc/README.txt; sourceTree = SOURCE_ROOT; }; - CF6527FE09D1BA3800C4B521 /* Sparc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Sparc.h; path = ../lib/Target/Sparc/Sparc.h; sourceTree = SOURCE_ROOT; }; - CF6527FF09D1BA3800C4B521 /* Sparc.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = Sparc.td; path = ../lib/Target/Sparc/Sparc.td; sourceTree = SOURCE_ROOT; }; - CF65280009D1BA3800C4B521 /* SparcAsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SparcAsmPrinter.cpp; path = ../lib/Target/Sparc/SparcAsmPrinter.cpp; sourceTree = SOURCE_ROOT; }; - CF65280109D1BA3800C4B521 /* SparcGenAsmWriter.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = SparcGenAsmWriter.inc; path = ../lib/Target/Sparc/SparcGenAsmWriter.inc; sourceTree = SOURCE_ROOT; }; - CF65280209D1BA3800C4B521 /* SparcGenDAGISel.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = SparcGenDAGISel.inc; path = ../lib/Target/Sparc/SparcGenDAGISel.inc; sourceTree = SOURCE_ROOT; }; - CF65280309D1BA3800C4B521 /* SparcGenInstrInfo.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = SparcGenInstrInfo.inc; path = ../lib/Target/Sparc/SparcGenInstrInfo.inc; sourceTree = SOURCE_ROOT; }; - CF65280409D1BA3800C4B521 /* SparcGenInstrNames.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = SparcGenInstrNames.inc; path = ../lib/Target/Sparc/SparcGenInstrNames.inc; sourceTree = SOURCE_ROOT; }; - CF65280509D1BA3800C4B521 /* SparcGenRegisterInfo.h.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = SparcGenRegisterInfo.h.inc; path = ../lib/Target/Sparc/SparcGenRegisterInfo.h.inc; sourceTree = SOURCE_ROOT; }; - CF65280609D1BA3800C4B521 /* SparcGenRegisterInfo.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = SparcGenRegisterInfo.inc; path = ../lib/Target/Sparc/SparcGenRegisterInfo.inc; sourceTree = SOURCE_ROOT; }; - CF65280709D1BA3800C4B521 /* SparcGenRegisterNames.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = SparcGenRegisterNames.inc; path = ../lib/Target/Sparc/SparcGenRegisterNames.inc; sourceTree = SOURCE_ROOT; }; - CF65280809D1BA3800C4B521 /* SparcGenSubtarget.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = SparcGenSubtarget.inc; path = ../lib/Target/Sparc/SparcGenSubtarget.inc; sourceTree = SOURCE_ROOT; }; - CF65280909D1BA3800C4B521 /* SparcInstrFormats.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SparcInstrFormats.td; path = ../lib/Target/Sparc/SparcInstrFormats.td; sourceTree = SOURCE_ROOT; }; - CF65280A09D1BA3800C4B521 /* SparcInstrInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SparcInstrInfo.cpp; path = ../lib/Target/Sparc/SparcInstrInfo.cpp; sourceTree = SOURCE_ROOT; }; - CF65280B09D1BA3800C4B521 /* SparcInstrInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SparcInstrInfo.h; path = ../lib/Target/Sparc/SparcInstrInfo.h; sourceTree = SOURCE_ROOT; }; - CF65280C09D1BA3800C4B521 /* SparcInstrInfo.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SparcInstrInfo.td; path = ../lib/Target/Sparc/SparcInstrInfo.td; sourceTree = SOURCE_ROOT; }; - CF65280D09D1BA3800C4B521 /* SparcISelDAGToDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SparcISelDAGToDAG.cpp; path = ../lib/Target/Sparc/SparcISelDAGToDAG.cpp; sourceTree = SOURCE_ROOT; }; - CF65280E09D1BA3800C4B521 /* SparcRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SparcRegisterInfo.cpp; path = ../lib/Target/Sparc/SparcRegisterInfo.cpp; sourceTree = SOURCE_ROOT; }; - CF65280F09D1BA3800C4B521 /* SparcRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SparcRegisterInfo.h; path = ../lib/Target/Sparc/SparcRegisterInfo.h; sourceTree = SOURCE_ROOT; }; - CF65281009D1BA3800C4B521 /* SparcRegisterInfo.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = SparcRegisterInfo.td; path = ../lib/Target/Sparc/SparcRegisterInfo.td; sourceTree = SOURCE_ROOT; }; - CF65281109D1BA3800C4B521 /* SparcSubtarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SparcSubtarget.cpp; path = ../lib/Target/Sparc/SparcSubtarget.cpp; sourceTree = SOURCE_ROOT; }; - CF65281209D1BA3800C4B521 /* SparcSubtarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SparcSubtarget.h; path = ../lib/Target/Sparc/SparcSubtarget.h; sourceTree = SOURCE_ROOT; }; - CF65281309D1BA3800C4B521 /* SparcTargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SparcTargetMachine.cpp; path = ../lib/Target/Sparc/SparcTargetMachine.cpp; sourceTree = SOURCE_ROOT; }; - CF65281409D1BA3800C4B521 /* SparcTargetMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SparcTargetMachine.h; path = ../lib/Target/Sparc/SparcTargetMachine.h; sourceTree = SOURCE_ROOT; }; - CF6529A6095B21A8007F884E /* MachineModuleInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MachineModuleInfo.cpp; sourceTree = ""; }; - CF6B5AFD095C82C300D1EA42 /* DAGCombiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DAGCombiner.cpp; sourceTree = ""; }; - CF6F487109505E1500BC9E82 /* MachineModuleInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachineModuleInfo.h; sourceTree = ""; }; - CF71B60F0AC45EDA0007F57C /* SmallVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SmallVector.h; sourceTree = ""; }; - CF73C0A2098A4FDF00627152 /* InlineAsm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineAsm.h; sourceTree = ""; }; - CF73C0A3098A4FDF00627152 /* TypeSymbolTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeSymbolTable.h; sourceTree = ""; }; - CF73C0A4098A4FDF00627152 /* ValueSymbolTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueSymbolTable.h; sourceTree = ""; }; - CF73C0A5098A507300627152 /* ConstantFolding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantFolding.h; sourceTree = ""; }; - CF73C0A9098A50FD00627152 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; - CF73C0AD098A519400627152 /* DataTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataTypes.h; sourceTree = ""; }; - CF73C0AE098A51AD00627152 /* Alarm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Alarm.h; sourceTree = ""; }; - CF73C0AF098A51DD00627152 /* RSProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSProfiling.h; sourceTree = ""; }; - CF73C0B0098A523C00627152 /* ConstantFolding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantFolding.cpp; sourceTree = ""; }; - CF73C0B7098A546000627152 /* RSProfiling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RSProfiling.cpp; sourceTree = ""; }; - CF73C0B8098A546000627152 /* RSProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSProfiling.h; sourceTree = ""; }; - CF73C0B9098A546000627152 /* Reg2Mem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Reg2Mem.cpp; sourceTree = ""; }; - CF73C0BD098A551F00627152 /* InlineAsm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InlineAsm.cpp; path = ../lib/VMCore/InlineAsm.cpp; sourceTree = SOURCE_ROOT; }; - CF73C0BE098A551F00627152 /* TypeSymbolTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TypeSymbolTable.cpp; path = ../lib/VMCore/TypeSymbolTable.cpp; sourceTree = SOURCE_ROOT; }; - CF73C0BF098A551F00627152 /* ValueSymbolTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueSymbolTable.cpp; path = ../lib/VMCore/ValueSymbolTable.cpp; sourceTree = SOURCE_ROOT; }; - CF79495D09B326D4005ADFCA /* Dwarf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Dwarf.cpp; sourceTree = ""; }; - CF7FFA1F0985081C008B0087 /* ScheduleDAGList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScheduleDAGList.cpp; sourceTree = ""; }; - CF7FFA2109850864008B0087 /* ScheduleDAG.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScheduleDAG.h; sourceTree = ""; }; - CF8D62FA09C2226F006017BA /* Intrinsics.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Intrinsics.td; sourceTree = ""; }; - CF8E00490989162500DA2399 /* Dwarf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Dwarf.h; sourceTree = ""; }; - CF8F1B410B64F6D100BB4199 /* RuntimeLibcalls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RuntimeLibcalls.h; sourceTree = ""; }; - CF8F1B420B64F70B00BB4199 /* PassManagers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassManagers.h; sourceTree = ""; }; - CF8F1B430B64F74400BB4199 /* Allocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Allocator.h; sourceTree = ""; }; - CF8F1B440B64F74400BB4199 /* Compiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Compiler.h; sourceTree = ""; }; - CF8F1B460B64F74400BB4199 /* ManagedStatic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ManagedStatic.h; sourceTree = ""; }; - CF8F1B470B64F74400BB4199 /* OutputBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OutputBuffer.h; sourceTree = ""; }; - CF8F1B490B64F7AB00BB4199 /* LinkTimeOptimizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkTimeOptimizer.h; sourceTree = ""; }; - CF8F1B4D0B64F80700BB4199 /* AliasDebugger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AliasDebugger.cpp; sourceTree = ""; }; - CF8F1B500B64F86A00BB4199 /* ManagedStatic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ManagedStatic.cpp; sourceTree = ""; }; - CF8F1B510B64F86A00BB4199 /* Streams.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Streams.cpp; sourceTree = ""; }; - CF8F1B530B64F8C000BB4199 /* IncludeFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IncludeFile.cpp; sourceTree = ""; }; - CF8F1B540B64F90F00BB4199 /* AlphaBranchSelector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaBranchSelector.cpp; sourceTree = ""; }; - CF8F1B550B64F90F00BB4199 /* AlphaLLRP.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaLLRP.cpp; sourceTree = ""; }; - CF8F1B560B64F98900BB4199 /* CBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CBackend.cpp; sourceTree = ""; }; - CF8F1B570B64F9AC00BB4199 /* PPCPredicates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCPredicates.cpp; sourceTree = ""; }; - CF8F1B580B64F9AC00BB4199 /* PPCPredicates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCPredicates.h; sourceTree = ""; }; - CF8F1B590B64F9E100BB4199 /* X86COFF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86COFF.h; sourceTree = ""; }; - CF8F1B5B0B64FA2F00BB4199 /* PredicateSimplifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PredicateSimplifier.cpp; sourceTree = ""; }; - CF8F1B5C0B64FA7300BB4199 /* PassManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PassManager.cpp; path = ../lib/VMCore/PassManager.cpp; sourceTree = SOURCE_ROOT; }; - CF8F1B680B64FADA00BB4199 /* llvm-upgrade.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "llvm-upgrade.cpp"; sourceTree = ""; }; - CF8F1B720B64FADA00BB4199 /* UpgradeInternals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UpgradeInternals.h; sourceTree = ""; }; - CF8F1B750B64FADA00BB4199 /* UpgradeLexer.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; path = UpgradeLexer.l; sourceTree = ""; }; - CF8F1B7C0B64FADA00BB4199 /* UpgradeParser.y */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.yacc; path = UpgradeParser.y; sourceTree = ""; }; - CF8F1B7F0B64FADA00BB4199 /* CppWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CppWriter.cpp; sourceTree = ""; }; - CF8F1B800B64FADA00BB4199 /* CppWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CppWriter.h; sourceTree = ""; }; - CF8F1B870B64FADA00BB4199 /* llvm2cpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = llvm2cpp.cpp; sourceTree = ""; }; - CF8F1B950B64FB5000BB4199 /* ConfigLexer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConfigLexer.cpp; sourceTree = ""; }; - CF8F1B9D0B64FB7F00BB4199 /* lto-c.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "lto-c.cpp"; sourceTree = ""; }; - CF8F1B9E0B64FB7F00BB4199 /* lto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lto.cpp; sourceTree = ""; }; - CF8F1BAC0B64FB8000BB4199 /* AnalysisWrappers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AnalysisWrappers.cpp; sourceTree = ""; }; - CF8F1BB70B64FB8000BB4199 /* GraphPrinters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphPrinters.cpp; sourceTree = ""; }; - CF8F1BB90B64FB8000BB4199 /* opt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = opt.cpp; sourceTree = ""; }; - CF8F1BBA0B64FB8000BB4199 /* PrintSCC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PrintSCC.cpp; sourceTree = ""; }; - CF8F1BC90B64FBD500BB4199 /* CodeGenIntrinsics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeGenIntrinsics.h; sourceTree = ""; }; - CF8F1BD10B64FC8A00BB4199 /* ARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARM.h; sourceTree = ""; }; - CF8F1BD20B64FC8A00BB4199 /* ARM.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ARM.td; sourceTree = ""; }; - CF8F1BD30B64FC8A00BB4199 /* ARMAddressingModes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMAddressingModes.h; sourceTree = ""; }; - CF8F1BD40B64FC8A00BB4199 /* ARMAsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMAsmPrinter.cpp; sourceTree = ""; }; - CF8F1BD50B64FC8A00BB4199 /* ARMConstantIslandPass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMConstantIslandPass.cpp; sourceTree = ""; }; - CF8F1BD60B64FC8A00BB4199 /* ARMConstantPoolValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMConstantPoolValue.cpp; sourceTree = ""; }; - CF8F1BD70B64FC8A00BB4199 /* ARMConstantPoolValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMConstantPoolValue.h; sourceTree = ""; }; - CF8F1BD80B64FC8A00BB4199 /* ARMFrameInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMFrameInfo.h; sourceTree = ""; }; - CF8F1BD90B64FC8A00BB4199 /* ARMInstrInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMInstrInfo.cpp; sourceTree = ""; }; - CF8F1BDA0B64FC8A00BB4199 /* ARMInstrInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMInstrInfo.h; sourceTree = ""; }; - CF8F1BDB0B64FC8A00BB4199 /* ARMInstrInfo.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ARMInstrInfo.td; sourceTree = ""; }; - CF8F1BDC0B64FC8A00BB4199 /* ARMInstrThumb.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ARMInstrThumb.td; sourceTree = ""; }; - CF8F1BDD0B64FC8A00BB4199 /* ARMInstrVFP.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ARMInstrVFP.td; sourceTree = ""; }; - CF8F1BDE0B64FC8A00BB4199 /* ARMISelDAGToDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMISelDAGToDAG.cpp; sourceTree = ""; }; - CF8F1BDF0B64FC8A00BB4199 /* ARMISelLowering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMISelLowering.cpp; sourceTree = ""; }; - CF8F1BE00B64FC8A00BB4199 /* ARMISelLowering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMISelLowering.h; sourceTree = ""; }; - CF8F1BE10B64FC8A00BB4199 /* ARMLoadStoreOptimizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMLoadStoreOptimizer.cpp; sourceTree = ""; }; - CF8F1BE20B64FC8A00BB4199 /* ARMMachineFunctionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMMachineFunctionInfo.h; sourceTree = ""; }; - CF8F1BE30B64FC8A00BB4199 /* ARMRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMRegisterInfo.cpp; sourceTree = ""; }; - CF8F1BE40B64FC8A00BB4199 /* ARMRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMRegisterInfo.h; sourceTree = ""; }; - CF8F1BE50B64FC8A00BB4199 /* ARMRegisterInfo.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ARMRegisterInfo.td; sourceTree = ""; }; - CF8F1BE60B64FC8A00BB4199 /* ARMSubtarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMSubtarget.cpp; sourceTree = ""; }; - CF8F1BE70B64FC8A00BB4199 /* ARMSubtarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMSubtarget.h; sourceTree = ""; }; - CF8F1BE80B64FC8A00BB4199 /* ARMTargetAsmInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMTargetAsmInfo.cpp; sourceTree = ""; }; - CF8F1BE90B64FC8A00BB4199 /* ARMTargetAsmInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMTargetAsmInfo.h; sourceTree = ""; }; - CF8F1BEA0B64FC8A00BB4199 /* ARMTargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMTargetMachine.cpp; sourceTree = ""; }; - CF8F1BEB0B64FC8A00BB4199 /* ARMTargetMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMTargetMachine.h; sourceTree = ""; }; - CF9720260A9F39B9002CEEDD /* LinkAllPasses.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkAllPasses.h; sourceTree = ""; }; - CF9720270A9F39B9002CEEDD /* LinkTimeOptimizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkTimeOptimizer.h; sourceTree = ""; }; - CF9720340A9F3A41002CEEDD /* IncludeFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IncludeFile.h; sourceTree = ""; }; - CF9720350A9F3ADC002CEEDD /* MachOWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MachOWriter.cpp; sourceTree = ""; }; - CF9720370A9F3B1C002CEEDD /* TargetLowering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TargetLowering.cpp; sourceTree = ""; }; - CF97208A0A9F3C6F002CEEDD /* LCSSA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LCSSA.cpp; sourceTree = ""; }; - CF97208B0A9F3C6F002CEEDD /* LowerAllocations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LowerAllocations.cpp; sourceTree = ""; }; - CF97208C0A9F3C6F002CEEDD /* LowerInvoke.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LowerInvoke.cpp; sourceTree = ""; }; - CF97208E0A9F3C6F002CEEDD /* LowerSwitch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LowerSwitch.cpp; sourceTree = ""; }; - CF97208F0A9F3C6F002CEEDD /* Mem2Reg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mem2Reg.cpp; sourceTree = ""; }; - CF9720900A9F3CA2002CEEDD /* ValueTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueTypes.cpp; path = ../lib/VMCore/ValueTypes.cpp; sourceTree = SOURCE_ROOT; }; - CF9720910A9F3CC7002CEEDD /* FindBugs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FindBugs.cpp; sourceTree = ""; }; - CF9720920A9F3CC7002CEEDD /* ToolRunner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ToolRunner.cpp; sourceTree = ""; }; - CF9720930A9F3CC7002CEEDD /* ToolRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToolRunner.h; sourceTree = ""; }; - CF9720970A9F3D4D002CEEDD /* IntrinsicEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IntrinsicEmitter.cpp; sourceTree = ""; }; - CF9720980A9F3D4D002CEEDD /* IntrinsicEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntrinsicEmitter.h; sourceTree = ""; }; - CF9BCD0808C74DE0001E7011 /* SubtargetFeature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SubtargetFeature.h; sourceTree = ""; }; - CF9BCD1508C75070001E7011 /* SubtargetFeature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SubtargetFeature.cpp; sourceTree = ""; }; - CFA702BB0A6FA85F0006009A /* AlphaGenAsmWriter.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenAsmWriter.inc; sourceTree = ""; }; - CFA702BC0A6FA85F0006009A /* AlphaGenCodeEmitter.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenCodeEmitter.inc; sourceTree = ""; }; - CFA702BD0A6FA85F0006009A /* AlphaGenDAGISel.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenDAGISel.inc; sourceTree = ""; }; - CFA702BE0A6FA85F0006009A /* AlphaGenInstrInfo.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenInstrInfo.inc; sourceTree = ""; }; - CFA702BF0A6FA85F0006009A /* AlphaGenInstrNames.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenInstrNames.inc; sourceTree = ""; }; - CFA702C00A6FA85F0006009A /* AlphaGenRegisterInfo.h.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenRegisterInfo.h.inc; sourceTree = ""; }; - CFA702C10A6FA85F0006009A /* AlphaGenRegisterInfo.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenRegisterInfo.inc; sourceTree = ""; }; - CFA702C20A6FA85F0006009A /* AlphaGenRegisterNames.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenRegisterNames.inc; sourceTree = ""; }; - CFA702C30A6FA85F0006009A /* AlphaGenSubtarget.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = AlphaGenSubtarget.inc; sourceTree = ""; }; - CFA702CB0A6FA8AD0006009A /* PPCGenAsmWriter.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = PPCGenAsmWriter.inc; sourceTree = ""; }; - CFA702CC0A6FA8AD0006009A /* PPCGenCodeEmitter.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = PPCGenCodeEmitter.inc; sourceTree = ""; }; - CFA702CD0A6FA8AD0006009A /* PPCGenDAGISel.inc */ = {isa = PBXFileReference; explicitFileType = sourcecode.pascal; fileEncoding = 4; path = PPCGenDAGISel.inc; sourceTree = ""; }; - CFA702CE0A6FA8AD0006009A /* PPCGenInstrInfo.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = PPCGenInstrInfo.inc; sourceTree = ""; }; - CFA702CF0A6FA8AD0006009A /* PPCGenInstrNames.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = PPCGenInstrNames.inc; sourceTree = ""; }; - CFA702D00A6FA8AD0006009A /* PPCGenRegisterInfo.h.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = PPCGenRegisterInfo.h.inc; sourceTree = ""; }; - CFA702D10A6FA8AD0006009A /* PPCGenRegisterInfo.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = PPCGenRegisterInfo.inc; sourceTree = ""; }; - CFA702D20A6FA8AD0006009A /* PPCGenRegisterNames.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = PPCGenRegisterNames.inc; sourceTree = ""; }; - CFA702D30A6FA8AD0006009A /* PPCGenSubtarget.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = PPCGenSubtarget.inc; sourceTree = ""; }; - CFA702D40A6FA8DD0006009A /* X86GenAsmWriter.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = X86GenAsmWriter.inc; sourceTree = ""; }; - CFA702D50A6FA8DD0006009A /* X86GenAsmWriter1.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = X86GenAsmWriter1.inc; sourceTree = ""; }; - CFA702D60A6FA8DD0006009A /* X86GenDAGISel.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = X86GenDAGISel.inc; sourceTree = ""; }; - CFA702D70A6FA8DD0006009A /* X86GenInstrInfo.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = X86GenInstrInfo.inc; sourceTree = ""; }; - CFA702D80A6FA8DD0006009A /* X86GenInstrNames.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = X86GenInstrNames.inc; sourceTree = ""; }; - CFA702D90A6FA8DD0006009A /* X86GenRegisterInfo.h.inc */ = {isa = PBXFileReference; fileEncoding = 4; languageSpecificationIdentifier = c.cpp; lastKnownFileType = sourcecode.pascal; path = X86GenRegisterInfo.h.inc; sourceTree = ""; }; - CFA702DA0A6FA8DD0006009A /* X86GenRegisterInfo.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = X86GenRegisterInfo.inc; sourceTree = ""; }; - CFA702DB0A6FA8DD0006009A /* X86GenRegisterNames.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = X86GenRegisterNames.inc; sourceTree = ""; }; - CFA702DC0A6FA8DD0006009A /* X86GenSubtarget.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = X86GenSubtarget.inc; sourceTree = ""; }; - CFABD0A20B09E342003EB061 /* PPCMachineFunctionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCMachineFunctionInfo.h; sourceTree = ""; }; - CFBD8B1A090E76540020B107 /* AlphaISelDAGToDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaISelDAGToDAG.cpp; sourceTree = ""; }; - CFBD8B1B090E76540020B107 /* AlphaISelLowering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaISelLowering.cpp; sourceTree = ""; }; - CFBD8B1C090E76540020B107 /* AlphaISelLowering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlphaISelLowering.h; sourceTree = ""; }; - CFBD8B1D090E76540020B107 /* AlphaSubtarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaSubtarget.cpp; sourceTree = ""; }; - CFBD8B1E090E76540020B107 /* AlphaSubtarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlphaSubtarget.h; sourceTree = ""; }; - CFC244570959DEF2009F8C47 /* DwarfWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DwarfWriter.cpp; sourceTree = ""; }; - CFC244BB0959F24C009F8C47 /* X86ISelDAGToDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = X86ISelDAGToDAG.cpp; sourceTree = ""; }; - CFC244BC0959F24C009F8C47 /* X86ISelLowering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = X86ISelLowering.cpp; sourceTree = ""; }; - CFC244BD0959F24C009F8C47 /* X86ISelLowering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86ISelLowering.h; sourceTree = ""; }; - CFD7E4F30A798FC3000C7379 /* LinkAllCodegenComponents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkAllCodegenComponents.h; sourceTree = ""; }; - CFD99AA80AFE827B0068D19C /* LICENSE.TXT */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE.TXT; path = ../LICENSE.TXT; sourceTree = SOURCE_ROOT; }; - CFD99AAD0AFE827B0068D19C /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = README.txt; path = ../README.txt; sourceTree = SOURCE_ROOT; }; - CFD99AB70AFE848A0068D19C /* Allocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Allocator.cpp; sourceTree = ""; }; - CFD99ABA0AFE84D70068D19C /* IncludeFile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IncludeFile.cpp; sourceTree = ""; }; - CFD99ABB0AFE84EF0068D19C /* Alarm.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = Alarm.inc; sourceTree = ""; }; - CFD99ABE0AFE857A0068D19C /* README-X86-64.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "README-X86-64.txt"; sourceTree = ""; }; - CFD99ADA0AFE87650068D19C /* lto.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lto.cpp; path = lto/lto.cpp; sourceTree = ""; }; - CFD99ADB0AFE87870068D19C /* AnalysisWrappers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnalysisWrappers.cpp; path = opt/AnalysisWrappers.cpp; sourceTree = ""; }; - CFD99ADC0AFE87870068D19C /* GraphPrinters.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GraphPrinters.cpp; path = opt/GraphPrinters.cpp; sourceTree = ""; }; - CFD99ADD0AFE87870068D19C /* opt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = opt.cpp; path = opt/opt.cpp; sourceTree = ""; }; - CFD99ADE0AFE87870068D19C /* PrintSCC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PrintSCC.cpp; path = opt/PrintSCC.cpp; sourceTree = ""; }; - CFE21C780A80CC0600D3E908 /* RegAllocRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegAllocRegistry.h; sourceTree = ""; }; - CFE21C7B0A80CC1C00D3E908 /* SchedulerRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SchedulerRegistry.h; sourceTree = ""; }; - CFE420FB0A66F67300AB4BF6 /* MachineJumpTableInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachineJumpTableInfo.h; sourceTree = ""; }; - CFE420FC0A66F67300AB4BF6 /* ValueTypes.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ValueTypes.td; sourceTree = ""; }; - CFE420FD0A66F67300AB4BF6 /* Interpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Interpreter.h; sourceTree = ""; }; - CFE420FE0A66F67300AB4BF6 /* JIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JIT.h; sourceTree = ""; }; - CFE420FF0A66F67300AB4BF6 /* IntrinsicsPowerPC.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IntrinsicsPowerPC.td; sourceTree = ""; }; - CFE421000A66F67300AB4BF6 /* IntrinsicsX86.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IntrinsicsX86.td; sourceTree = ""; }; - CFE421010A66F67300AB4BF6 /* LinkAllVMCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkAllVMCore.h; sourceTree = ""; }; - CFE421060A66F86D00AB4BF6 /* ScheduleDAGRRList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScheduleDAGRRList.cpp; sourceTree = ""; }; - CFE421070A66F8DC00AB4BF6 /* GraphWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GraphWriter.cpp; sourceTree = ""; }; - CFE421090A66F93300AB4BF6 /* Alarm.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Alarm.cpp; sourceTree = ""; }; - CFE4210A0A66F93300AB4BF6 /* Alarm.inc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; path = Alarm.inc; sourceTree = ""; }; - CFE4210B0A66F96400AB4BF6 /* AlphaSchedule.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AlphaSchedule.td; sourceTree = ""; }; - CFE421140A66FA2D00AB4BF6 /* PPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPC.h; sourceTree = ""; }; - CFE421150A66FA2D00AB4BF6 /* PPC.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPC.td; sourceTree = ""; }; - CFE421160A66FA2D00AB4BF6 /* PPCAsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCAsmPrinter.cpp; sourceTree = ""; }; - CFE421170A66FA2D00AB4BF6 /* PPCBranchSelector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCBranchSelector.cpp; sourceTree = ""; }; - CFE421180A66FA2D00AB4BF6 /* PPCCodeEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCCodeEmitter.cpp; sourceTree = ""; }; - CFE421190A66FA2D00AB4BF6 /* PPCFrameInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCFrameInfo.h; sourceTree = ""; }; - CFE4211A0A66FA2D00AB4BF6 /* PPCHazardRecognizers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCHazardRecognizers.cpp; sourceTree = ""; }; - CFE4211B0A66FA2D00AB4BF6 /* PPCHazardRecognizers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCHazardRecognizers.h; sourceTree = ""; }; - CFE4211C0A66FA2D00AB4BF6 /* PPCInstr64Bit.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCInstr64Bit.td; sourceTree = ""; }; - CFE4211D0A66FA2D00AB4BF6 /* PPCInstrAltivec.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCInstrAltivec.td; sourceTree = ""; }; - CFE4211E0A66FA2D00AB4BF6 /* PPCInstrBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCInstrBuilder.h; sourceTree = ""; }; - CFE4211F0A66FA2D00AB4BF6 /* PPCInstrFormats.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCInstrFormats.td; sourceTree = ""; }; - CFE421200A66FA2D00AB4BF6 /* PPCInstrInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCInstrInfo.cpp; sourceTree = ""; }; - CFE421210A66FA2D00AB4BF6 /* PPCInstrInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCInstrInfo.h; sourceTree = ""; }; - CFE421220A66FA2D00AB4BF6 /* PPCInstrInfo.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCInstrInfo.td; sourceTree = ""; }; - CFE421230A66FA2D00AB4BF6 /* PPCISelDAGToDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCISelDAGToDAG.cpp; sourceTree = ""; }; - CFE421240A66FA2D00AB4BF6 /* PPCISelLowering.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCISelLowering.cpp; sourceTree = ""; }; - CFE421250A66FA2D00AB4BF6 /* PPCISelLowering.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCISelLowering.h; sourceTree = ""; }; - CFE421260A66FA2D00AB4BF6 /* PPCJITInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCJITInfo.cpp; sourceTree = ""; }; - CFE421270A66FA2D00AB4BF6 /* PPCJITInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCJITInfo.h; sourceTree = ""; }; - CFE421280A66FA2D00AB4BF6 /* PPCPerfectShuffle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCPerfectShuffle.h; sourceTree = ""; }; - CFE421290A66FA2D00AB4BF6 /* PPCRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCRegisterInfo.cpp; sourceTree = ""; }; - CFE4212A0A66FA2D00AB4BF6 /* PPCRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCRegisterInfo.h; sourceTree = ""; }; - CFE4212B0A66FA2D00AB4BF6 /* PPCRegisterInfo.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCRegisterInfo.td; sourceTree = ""; }; - CFE4212C0A66FA2D00AB4BF6 /* PPCRelocations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCRelocations.h; sourceTree = ""; }; - CFE4212D0A66FA2D00AB4BF6 /* PPCSchedule.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCSchedule.td; sourceTree = ""; }; - CFE4212E0A66FA2D00AB4BF6 /* PPCScheduleG3.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCScheduleG3.td; sourceTree = ""; }; - CFE4212F0A66FA2D00AB4BF6 /* PPCScheduleG4.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCScheduleG4.td; sourceTree = ""; }; - CFE421300A66FA2D00AB4BF6 /* PPCScheduleG4Plus.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCScheduleG4Plus.td; sourceTree = ""; }; - CFE421310A66FA2D00AB4BF6 /* PPCScheduleG5.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PPCScheduleG5.td; sourceTree = ""; }; - CFE421320A66FA2E00AB4BF6 /* PPCSubtarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCSubtarget.cpp; sourceTree = ""; }; - CFE421330A66FA2E00AB4BF6 /* PPCSubtarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCSubtarget.h; sourceTree = ""; }; - CFE421340A66FA2E00AB4BF6 /* PPCTargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPCTargetMachine.cpp; sourceTree = ""; }; - CFE421350A66FA2E00AB4BF6 /* PPCTargetMachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPCTargetMachine.h; sourceTree = ""; }; - CFE421360A66FA2E00AB4BF6 /* README_ALTIVEC.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README_ALTIVEC.txt; sourceTree = ""; }; - CFE421370A66FA2E00AB4BF6 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; - CFE421380A66FA8000AB4BF6 /* README-FPStack.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "README-FPStack.txt"; sourceTree = ""; }; - CFE421390A66FA8000AB4BF6 /* README-SSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "README-SSE.txt"; sourceTree = ""; }; - CFE4213A0A66FA8000AB4BF6 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; - CFE4213B0A66FA8000AB4BF6 /* X86MachineFunctionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = X86MachineFunctionInfo.h; sourceTree = ""; }; - CFE4213D0A66FAE100AB4BF6 /* Hello.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Hello.cpp; sourceTree = ""; }; - CFE4213F0A66FB5E00AB4BF6 /* IndMemRemoval.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndMemRemoval.cpp; sourceTree = ""; }; - CFF0DE6309BF6C360031957F /* X86InstrFPStack.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = X86InstrFPStack.td; sourceTree = ""; }; - CFF0DE6409BF6C360031957F /* X86InstrMMX.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = X86InstrMMX.td; sourceTree = ""; }; - CFF0DE6509BF6C360031957F /* X86InstrSSE.td */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = X86InstrSSE.td; sourceTree = ""; }; - CFF8B434097C605F0047F72A /* UniqueVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniqueVector.h; sourceTree = ""; }; - DE4DA0390911476D0012D44B /* LoopSimplify.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = LoopSimplify.cpp; path = ../lib/Transforms/Utils/LoopSimplify.cpp; sourceTree = SOURCE_ROOT; }; - DE4DA03C091147920012D44B /* LiveInterval.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = LiveInterval.h; path = ../include/llvm/CodeGen/LiveInterval.h; sourceTree = SOURCE_ROOT; }; - DE4DA03D091147920012D44B /* LiveIntervalAnalysis.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = LiveIntervalAnalysis.h; path = ../include/llvm/CodeGen/LiveIntervalAnalysis.h; sourceTree = SOURCE_ROOT; }; - DE4DA065091148520012D44B /* SubtargetEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = SubtargetEmitter.cpp; path = ../utils/TableGen/SubtargetEmitter.cpp; sourceTree = SOURCE_ROOT; }; - DE4DA066091148520012D44B /* SubtargetEmitter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SubtargetEmitter.h; path = ../utils/TableGen/SubtargetEmitter.h; sourceTree = SOURCE_ROOT; }; - DE66EC5B08ABE86900323D32 /* AsmWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = AsmWriter.cpp; path = ../lib/VMCore/AsmWriter.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC5C08ABE86A00323D32 /* BasicBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = BasicBlock.cpp; path = ../lib/VMCore/BasicBlock.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6008ABE86A00323D32 /* Constants.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Constants.cpp; path = ../lib/VMCore/Constants.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6108ABE86A00323D32 /* Dominators.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Dominators.cpp; path = ../lib/VMCore/Dominators.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6208ABE86A00323D32 /* Function.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Function.cpp; path = ../lib/VMCore/Function.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6308ABE86A00323D32 /* Globals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Globals.cpp; path = ../lib/VMCore/Globals.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6408ABE86A00323D32 /* Instruction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Instruction.cpp; path = ../lib/VMCore/Instruction.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6508ABE86A00323D32 /* Instructions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Instructions.cpp; path = ../lib/VMCore/Instructions.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6608ABE86A00323D32 /* LeakDetector.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = LeakDetector.cpp; path = ../lib/VMCore/LeakDetector.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6708ABE86A00323D32 /* Mangler.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Mangler.cpp; path = ../lib/VMCore/Mangler.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6808ABE86A00323D32 /* Module.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Module.cpp; path = ../lib/VMCore/Module.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6908ABE86A00323D32 /* ModuleProvider.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleProvider.cpp; path = ../lib/VMCore/ModuleProvider.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6A08ABE86A00323D32 /* Pass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Pass.cpp; path = ../lib/VMCore/Pass.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6D08ABE86A00323D32 /* SymbolTableListTraitsImpl.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SymbolTableListTraitsImpl.h; path = ../lib/VMCore/SymbolTableListTraitsImpl.h; sourceTree = SOURCE_ROOT; }; - DE66EC6E08ABE86A00323D32 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Type.cpp; path = ../lib/VMCore/Type.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC6F08ABE86A00323D32 /* Value.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Value.cpp; path = ../lib/VMCore/Value.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC7008ABE86A00323D32 /* Verifier.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Verifier.cpp; path = ../lib/VMCore/Verifier.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC8E08ABEAF000323D32 /* llvmAsmParser.y */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.yacc; name = llvmAsmParser.y; path = ../lib/AsmParser/llvmAsmParser.y; sourceTree = SOURCE_ROOT; }; - DE66EC8F08ABEAF000323D32 /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Parser.cpp; path = ../lib/AsmParser/Parser.cpp; sourceTree = SOURCE_ROOT; }; - DE66EC9008ABEAF000323D32 /* ParserInternals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ParserInternals.h; path = ../lib/AsmParser/ParserInternals.h; sourceTree = SOURCE_ROOT; }; - DE66ECBE08ABEC0700323D32 /* AliasAnalysis.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AliasAnalysis.cpp; sourceTree = ""; }; - DE66ECBF08ABEC0700323D32 /* AliasAnalysisCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AliasAnalysisCounter.cpp; sourceTree = ""; }; - DE66ECC008ABEC0700323D32 /* AliasAnalysisEvaluator.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AliasAnalysisEvaluator.cpp; sourceTree = ""; }; - DE66ECC108ABEC0700323D32 /* AliasSetTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AliasSetTracker.cpp; sourceTree = ""; }; - DE66ECC208ABEC0700323D32 /* BasicAliasAnalysis.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BasicAliasAnalysis.cpp; sourceTree = ""; }; - DE66ECC308ABEC0700323D32 /* CFGPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CFGPrinter.cpp; sourceTree = ""; }; - DE66ED1708ABEC0800323D32 /* InstCount.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = InstCount.cpp; sourceTree = ""; }; - DE66ED1808ABEC0800323D32 /* Interval.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Interval.cpp; sourceTree = ""; }; - DE66ED1908ABEC0800323D32 /* IntervalPartition.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IntervalPartition.cpp; sourceTree = ""; }; - DE66ED1B08ABEC0800323D32 /* Andersens.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Andersens.cpp; sourceTree = ""; }; - DE66ED1C08ABEC0800323D32 /* CallGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CallGraph.cpp; sourceTree = ""; }; - DE66ED1D08ABEC0800323D32 /* CallGraphSCCPass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CallGraphSCCPass.cpp; sourceTree = ""; }; - DE66ED2F08ABEC0800323D32 /* FindUsedTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FindUsedTypes.cpp; sourceTree = ""; }; - DE66ED3008ABEC0800323D32 /* GlobalsModRef.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GlobalsModRef.cpp; sourceTree = ""; }; - DE66ED3308ABEC0800323D32 /* LoadValueNumbering.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LoadValueNumbering.cpp; sourceTree = ""; }; - DE66ED3408ABEC0800323D32 /* LoopInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LoopInfo.cpp; sourceTree = ""; }; - DE66ED3608ABEC0800323D32 /* PostDominators.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PostDominators.cpp; sourceTree = ""; }; - DE66ED3708ABEC0800323D32 /* ProfileInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ProfileInfo.cpp; sourceTree = ""; }; - DE66ED3808ABEC0800323D32 /* ProfileInfoLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ProfileInfoLoader.cpp; sourceTree = ""; }; - DE66ED3908ABEC0800323D32 /* ProfileInfoLoaderPass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ProfileInfoLoaderPass.cpp; sourceTree = ""; }; - DE66ED3A08ABEC0800323D32 /* ScalarEvolution.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ScalarEvolution.cpp; sourceTree = ""; }; - DE66ED3B08ABEC0800323D32 /* ScalarEvolutionExpander.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ScalarEvolutionExpander.cpp; sourceTree = ""; }; - DE66ED3C08ABEC0800323D32 /* Trace.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Trace.cpp; sourceTree = ""; }; - DE66ED3D08ABEC0800323D32 /* ValueNumbering.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ValueNumbering.cpp; sourceTree = ""; }; - DE66ED3F08ABEC2A00323D32 /* AsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AsmPrinter.cpp; sourceTree = ""; }; - DE66ED4008ABEC2A00323D32 /* BranchFolding.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BranchFolding.cpp; sourceTree = ""; }; - DE66ED6F08ABEC2B00323D32 /* ELFWriter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ELFWriter.cpp; sourceTree = ""; }; - DE66ED7008ABEC2B00323D32 /* IntrinsicLowering.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IntrinsicLowering.cpp; sourceTree = ""; }; - DE66ED7108ABEC2B00323D32 /* LiveInterval.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiveInterval.cpp; sourceTree = ""; }; - DE66ED7308ABEC2B00323D32 /* LiveIntervalAnalysis.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiveIntervalAnalysis.cpp; sourceTree = ""; }; - DE66ED7508ABEC2B00323D32 /* LiveVariables.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiveVariables.cpp; sourceTree = ""; }; - DE66ED7608ABEC2B00323D32 /* MachineBasicBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachineBasicBlock.cpp; sourceTree = ""; }; - DE66ED7808ABEC2B00323D32 /* MachineFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachineFunction.cpp; sourceTree = ""; }; - DE66ED7908ABEC2B00323D32 /* MachineInstr.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MachineInstr.cpp; sourceTree = ""; }; - DE66ED7B08ABEC2B00323D32 /* Passes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Passes.cpp; sourceTree = ""; }; - DE66ED7C08ABEC2B00323D32 /* PHIElimination.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PHIElimination.cpp; sourceTree = ""; }; - DE66ED7D08ABEC2B00323D32 /* PhysRegTracker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PhysRegTracker.h; sourceTree = ""; }; - DE66ED7E08ABEC2B00323D32 /* PrologEpilogInserter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PrologEpilogInserter.cpp; sourceTree = ""; }; - DE66ED8008ABEC2B00323D32 /* RegAllocLinearScan.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RegAllocLinearScan.cpp; sourceTree = ""; }; - DE66ED8108ABEC2B00323D32 /* RegAllocLocal.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RegAllocLocal.cpp; sourceTree = ""; }; - DE66ED8208ABEC2B00323D32 /* RegAllocSimple.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RegAllocSimple.cpp; sourceTree = ""; }; - DE66ED9008ABEC2B00323D32 /* LegalizeDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LegalizeDAG.cpp; sourceTree = ""; }; - DE66ED9208ABEC2B00323D32 /* SelectionDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionDAG.cpp; sourceTree = ""; }; - DE66ED9308ABEC2B00323D32 /* SelectionDAGISel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionDAGISel.cpp; sourceTree = ""; }; - DE66ED9408ABEC2B00323D32 /* SelectionDAGPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SelectionDAGPrinter.cpp; sourceTree = ""; }; - DE66ED9508ABEC2B00323D32 /* TwoAddressInstructionPass.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TwoAddressInstructionPass.cpp; sourceTree = ""; }; - DE66ED9608ABEC2B00323D32 /* UnreachableBlockElim.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = UnreachableBlockElim.cpp; sourceTree = ""; }; - DE66ED9808ABEC2B00323D32 /* VirtRegMap.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = VirtRegMap.cpp; sourceTree = ""; }; - DE66ED9908ABEC2B00323D32 /* VirtRegMap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = VirtRegMap.h; sourceTree = ""; }; - DE66EDB108ABEC7300323D32 /* Debugger.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Debugger.cpp; sourceTree = ""; }; - DE66EDB508ABEC7300323D32 /* ProgramInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ProgramInfo.cpp; sourceTree = ""; }; - DE66EDB608ABEC7300323D32 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; - DE66EDB708ABEC7300323D32 /* RuntimeInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RuntimeInfo.cpp; sourceTree = ""; }; - DE66EDB808ABEC7300323D32 /* SourceFile.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SourceFile.cpp; sourceTree = ""; }; - DE66EDB908ABEC7300323D32 /* SourceLanguage-CFamily.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "SourceLanguage-CFamily.cpp"; sourceTree = ""; }; - DE66EDBA08ABEC7300323D32 /* SourceLanguage-CPlusPlus.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "SourceLanguage-CPlusPlus.cpp"; sourceTree = ""; }; - DE66EDBB08ABEC7300323D32 /* SourceLanguage-Unknown.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "SourceLanguage-Unknown.cpp"; sourceTree = ""; }; - DE66EDBC08ABEC7300323D32 /* SourceLanguage.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SourceLanguage.cpp; sourceTree = ""; }; - DE66EDC408ABEC9000323D32 /* ExecutionEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutionEngine.cpp; sourceTree = ""; }; - DE66EDCE08ABEC9000323D32 /* Execution.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Execution.cpp; sourceTree = ""; }; - DE66EDCF08ABEC9000323D32 /* ExternalFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ExternalFunctions.cpp; sourceTree = ""; }; - DE66EDD008ABEC9000323D32 /* Interpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Interpreter.cpp; sourceTree = ""; }; - DE66EDD108ABEC9000323D32 /* Interpreter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Interpreter.h; sourceTree = ""; }; - DE66EDDE08ABEC9100323D32 /* Intercept.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Intercept.cpp; sourceTree = ""; }; - DE66EDDF08ABEC9100323D32 /* JIT.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JIT.cpp; sourceTree = ""; }; - DE66EDE008ABEC9100323D32 /* JIT.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JIT.h; sourceTree = ""; }; - DE66EDE108ABEC9100323D32 /* JITEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JITEmitter.cpp; sourceTree = ""; }; - DE66EDE308ABEC9100323D32 /* TargetSelect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetSelect.cpp; sourceTree = ""; }; - DE66EDF608ABEDD300323D32 /* LinkArchives.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LinkArchives.cpp; sourceTree = ""; }; - DE66EDF708ABEDD300323D32 /* Linker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Linker.cpp; sourceTree = ""; }; - DE66EDF808ABEDD300323D32 /* LinkItems.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LinkItems.cpp; sourceTree = ""; }; - DE66EDF908ABEDD300323D32 /* LinkModules.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LinkModules.cpp; sourceTree = ""; }; - DE66EDFC08ABEDE600323D32 /* Annotation.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Annotation.cpp; sourceTree = ""; }; - DE66EE1D08ABEDE600323D32 /* CommandLine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CommandLine.cpp; sourceTree = ""; }; - DE66EE3D08ABEDE600323D32 /* Debug.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Debug.cpp; sourceTree = ""; }; - DE66EE3E08ABEDE600323D32 /* FileUtilities.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FileUtilities.cpp; sourceTree = ""; }; - DE66EE3F08ABEDE600323D32 /* IsInf.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IsInf.cpp; sourceTree = ""; }; - DE66EE4008ABEDE600323D32 /* IsNAN.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IsNAN.cpp; sourceTree = ""; }; - DE66EE4208ABEDE600323D32 /* PluginLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PluginLoader.cpp; sourceTree = ""; }; - DE66EE4308ABEDE600323D32 /* SlowOperationInformer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SlowOperationInformer.cpp; sourceTree = ""; }; - DE66EE4408ABEDE600323D32 /* Statistic.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Statistic.cpp; sourceTree = ""; }; - DE66EE4508ABEDE700323D32 /* StringExtras.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StringExtras.cpp; sourceTree = ""; }; - DE66EE4608ABEDE700323D32 /* SystemUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SystemUtils.cpp; sourceTree = ""; }; - DE66EE4708ABEDE700323D32 /* Timer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Timer.cpp; sourceTree = ""; }; - DE66EE6008ABEE3400323D32 /* DynamicLibrary.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLibrary.cpp; sourceTree = ""; }; - DE66EE6108ABEE3400323D32 /* LICENSE.TXT */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = LICENSE.TXT; sourceTree = ""; }; - DE66EE6508ABEE3400323D32 /* MappedFile.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MappedFile.cpp; sourceTree = ""; }; - DE66EE6608ABEE3400323D32 /* Memory.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Memory.cpp; sourceTree = ""; }; - DE66EE6708ABEE3400323D32 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = ""; }; - DE66EE6808ABEE3400323D32 /* Path.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Path.cpp; sourceTree = ""; }; - DE66EE6908ABEE3400323D32 /* Process.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Process.cpp; sourceTree = ""; }; - DE66EE6A08ABEE3400323D32 /* Program.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Program.cpp; sourceTree = ""; }; - DE66EE6B08ABEE3400323D32 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; - DE66EE7C08ABEE3400323D32 /* Signals.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Signals.cpp; sourceTree = ""; }; - DE66EE7D08ABEE3400323D32 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = ""; }; - DE66EE7F08ABEE3500323D32 /* MappedFile.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = MappedFile.inc; sourceTree = ""; }; - DE66EE8008ABEE3500323D32 /* Memory.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Memory.inc; sourceTree = ""; }; - DE66EE8108ABEE3500323D32 /* Mutex.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Mutex.inc; sourceTree = ""; }; - DE66EE8208ABEE3500323D32 /* Path.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Path.inc; sourceTree = ""; }; - DE66EE8308ABEE3500323D32 /* Process.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Process.inc; sourceTree = ""; }; - DE66EE8408ABEE3500323D32 /* Program.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Program.inc; sourceTree = ""; }; - DE66EE8508ABEE3500323D32 /* README.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; - DE66EE8608ABEE3500323D32 /* Signals.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Signals.inc; sourceTree = ""; }; - DE66EE8908ABEE3500323D32 /* TimeValue.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = TimeValue.inc; sourceTree = ""; }; - DE66EE8A08ABEE3500323D32 /* Unix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Unix.h; sourceTree = ""; }; - DE66EE8C08ABEE3500323D32 /* DynamicLibrary.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = DynamicLibrary.inc; sourceTree = ""; }; - DE66EE8D08ABEE3500323D32 /* MappedFile.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = MappedFile.inc; sourceTree = ""; }; - DE66EE8E08ABEE3500323D32 /* Memory.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Memory.inc; sourceTree = ""; }; - DE66EE8F08ABEE3500323D32 /* Mutex.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Mutex.inc; sourceTree = ""; }; - DE66EE9008ABEE3500323D32 /* Path.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Path.inc; sourceTree = ""; }; - DE66EE9108ABEE3500323D32 /* Process.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Process.inc; sourceTree = ""; }; - DE66EE9208ABEE3500323D32 /* Program.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Program.inc; sourceTree = ""; }; - DE66EE9308ABEE3500323D32 /* Signals.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Signals.inc; sourceTree = ""; }; - DE66EE9408ABEE3500323D32 /* TimeValue.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = TimeValue.inc; sourceTree = ""; }; - DE66EE9508ABEE3500323D32 /* Win32.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Win32.h; sourceTree = ""; }; - DE66EE9808ABEE5E00323D32 /* Alpha.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Alpha.h; sourceTree = ""; }; - DE66EE9908ABEE5E00323D32 /* Alpha.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Alpha.td; sourceTree = ""; }; - DE66EE9A08ABEE5E00323D32 /* AlphaAsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaAsmPrinter.cpp; sourceTree = ""; }; - DE66EE9B08ABEE5E00323D32 /* AlphaCodeEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaCodeEmitter.cpp; sourceTree = ""; }; - DE66EEA308ABEE5E00323D32 /* AlphaInstrFormats.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = AlphaInstrFormats.td; sourceTree = ""; }; - DE66EEA408ABEE5E00323D32 /* AlphaInstrInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaInstrInfo.cpp; sourceTree = ""; }; - DE66EEA508ABEE5E00323D32 /* AlphaInstrInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AlphaInstrInfo.h; sourceTree = ""; }; - DE66EEA608ABEE5E00323D32 /* AlphaInstrInfo.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = AlphaInstrInfo.td; sourceTree = ""; }; - DE66EEA908ABEE5E00323D32 /* AlphaJITInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaJITInfo.cpp; sourceTree = ""; }; - DE66EEAA08ABEE5E00323D32 /* AlphaJITInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AlphaJITInfo.h; sourceTree = ""; }; - DE66EEAB08ABEE5E00323D32 /* AlphaRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaRegisterInfo.cpp; sourceTree = ""; }; - DE66EEAC08ABEE5E00323D32 /* AlphaRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AlphaRegisterInfo.h; sourceTree = ""; }; - DE66EEAD08ABEE5E00323D32 /* AlphaRegisterInfo.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = AlphaRegisterInfo.td; sourceTree = ""; }; - DE66EEAE08ABEE5E00323D32 /* AlphaRelocations.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AlphaRelocations.h; sourceTree = ""; }; - DE66EEAF08ABEE5E00323D32 /* AlphaTargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AlphaTargetMachine.cpp; sourceTree = ""; }; - DE66EEB008ABEE5E00323D32 /* AlphaTargetMachine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AlphaTargetMachine.h; sourceTree = ""; }; - DE66EECA08ABEE5E00323D32 /* CTargetMachine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CTargetMachine.h; sourceTree = ""; }; - DE66EF0E08ABEE5E00323D32 /* README */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = README; sourceTree = ""; }; - DE66EF1008ABEE5E00323D32 /* TargetRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetRegisterInfo.cpp; sourceTree = ""; }; - DE66F08A08ABEE6000323D32 /* Target.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Target.td; sourceTree = ""; }; - DE66F08B08ABEE6000323D32 /* TargetData.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetData.cpp; sourceTree = ""; }; - DE66F08C08ABEE6000323D32 /* TargetFrameInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetFrameInfo.cpp; sourceTree = ""; }; - DE66F08D08ABEE6000323D32 /* TargetInstrInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetInstrInfo.cpp; sourceTree = ""; }; - DE66F08F08ABEE6000323D32 /* TargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetMachine.cpp; sourceTree = ""; }; - DE66F09008ABEE6000323D32 /* TargetMachineRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetMachineRegistry.cpp; sourceTree = ""; }; - DE66F09208ABEE6000323D32 /* TargetSubtarget.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TargetSubtarget.cpp; sourceTree = ""; }; - DE66F0BC08ABEE6000323D32 /* X86.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86.h; sourceTree = ""; }; - DE66F0BD08ABEE6000323D32 /* X86.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = X86.td; sourceTree = ""; }; - DE66F0BE08ABEE6000323D32 /* X86AsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86AsmPrinter.cpp; sourceTree = ""; }; - DE66F0BF08ABEE6000323D32 /* X86AsmPrinter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86AsmPrinter.h; sourceTree = ""; }; - DE66F0C008ABEE6000323D32 /* X86ATTAsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86ATTAsmPrinter.cpp; sourceTree = ""; }; - DE66F0C108ABEE6000323D32 /* X86ATTAsmPrinter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86ATTAsmPrinter.h; sourceTree = ""; }; - DE66F0C208ABEE6000323D32 /* X86CodeEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86CodeEmitter.cpp; sourceTree = ""; }; - DE66F0C408ABEE6000323D32 /* X86FloatingPoint.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86FloatingPoint.cpp; sourceTree = ""; }; - DE66F0CC08ABEE6000323D32 /* X86InstrBuilder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86InstrBuilder.h; sourceTree = ""; }; - DE66F0CD08ABEE6000323D32 /* X86InstrInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86InstrInfo.cpp; sourceTree = ""; }; - DE66F0CE08ABEE6000323D32 /* X86InstrInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86InstrInfo.h; sourceTree = ""; }; - DE66F0CF08ABEE6100323D32 /* X86InstrInfo.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = X86InstrInfo.td; sourceTree = ""; }; - DE66F0D008ABEE6100323D32 /* X86IntelAsmPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86IntelAsmPrinter.cpp; sourceTree = ""; }; - DE66F0D108ABEE6100323D32 /* X86IntelAsmPrinter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86IntelAsmPrinter.h; sourceTree = ""; }; - DE66F0D508ABEE6100323D32 /* X86JITInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86JITInfo.cpp; sourceTree = ""; }; - DE66F0D608ABEE6100323D32 /* X86JITInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86JITInfo.h; sourceTree = ""; }; - DE66F0D808ABEE6100323D32 /* X86RegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86RegisterInfo.cpp; sourceTree = ""; }; - DE66F0D908ABEE6100323D32 /* X86RegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86RegisterInfo.h; sourceTree = ""; }; - DE66F0DA08ABEE6100323D32 /* X86RegisterInfo.td */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = X86RegisterInfo.td; sourceTree = ""; }; - DE66F0DB08ABEE6100323D32 /* X86Relocations.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86Relocations.h; sourceTree = ""; }; - DE66F0DC08ABEE6100323D32 /* X86Subtarget.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86Subtarget.cpp; sourceTree = ""; }; - DE66F0DD08ABEE6100323D32 /* X86Subtarget.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86Subtarget.h; sourceTree = ""; }; - DE66F0DE08ABEE6100323D32 /* X86TargetMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = X86TargetMachine.cpp; sourceTree = ""; }; - DE66F0DF08ABEE6100323D32 /* X86TargetMachine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = X86TargetMachine.h; sourceTree = ""; }; - DE66F0EF08ABEFB300323D32 /* BlockProfiling.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BlockProfiling.cpp; sourceTree = ""; }; - DE66F0FE08ABEFB300323D32 /* EdgeProfiling.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = EdgeProfiling.cpp; sourceTree = ""; }; - DE66F11B08ABEFB300323D32 /* ProfilingUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ProfilingUtils.cpp; sourceTree = ""; }; - DE66F11C08ABEFB300323D32 /* ProfilingUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ProfilingUtils.h; sourceTree = ""; }; - DE66F12008ABEFB300323D32 /* ArgumentPromotion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ArgumentPromotion.cpp; sourceTree = ""; }; - DE66F12108ABEFB300323D32 /* ConstantMerge.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantMerge.cpp; sourceTree = ""; }; - DE66F12208ABEFB300323D32 /* DeadArgumentElimination.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DeadArgumentElimination.cpp; sourceTree = ""; }; - DE66F12308ABEFB300323D32 /* DeadTypeElimination.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DeadTypeElimination.cpp; sourceTree = ""; }; - DE66F14C08ABEFB400323D32 /* GlobalDCE.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GlobalDCE.cpp; sourceTree = ""; }; - DE66F14D08ABEFB400323D32 /* GlobalOpt.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GlobalOpt.cpp; sourceTree = ""; }; - DE66F14E08ABEFB400323D32 /* Inliner.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Inliner.cpp; sourceTree = ""; }; - DE66F15008ABEFB400323D32 /* InlineSimple.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = InlineSimple.cpp; sourceTree = ""; }; - DE66F15108ABEFB400323D32 /* Internalize.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Internalize.cpp; sourceTree = ""; }; - DE66F15208ABEFB400323D32 /* IPConstantPropagation.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IPConstantPropagation.cpp; sourceTree = ""; }; - DE66F15308ABEFB400323D32 /* LoopExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LoopExtractor.cpp; sourceTree = ""; }; - DE66F15408ABEFB400323D32 /* LowerSetJmp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LowerSetJmp.cpp; sourceTree = ""; }; - DE66F15608ABEFB400323D32 /* PruneEH.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PruneEH.cpp; sourceTree = ""; }; - DE66F15708ABEFB400323D32 /* RaiseAllocations.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RaiseAllocations.cpp; sourceTree = ""; }; - DE66F15808ABEFB400323D32 /* SimplifyLibCalls.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SimplifyLibCalls.cpp; sourceTree = ""; }; - DE66F15908ABEFB400323D32 /* StripSymbols.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = StripSymbols.cpp; sourceTree = ""; }; - DE66F15E08ABEFB400323D32 /* ADCE.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ADCE.cpp; sourceTree = ""; }; - DE66F15F08ABEFB400323D32 /* BasicBlockPlacement.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BasicBlockPlacement.cpp; sourceTree = ""; }; - DE66F16008ABEFB400323D32 /* CondPropagate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CondPropagate.cpp; sourceTree = ""; }; - DE66F16108ABEFB400323D32 /* ConstantProp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantProp.cpp; sourceTree = ""; }; - DE66F16308ABEFB400323D32 /* DCE.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DCE.cpp; sourceTree = ""; }; - DE66F16408ABEFB400323D32 /* DeadStoreElimination.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DeadStoreElimination.cpp; sourceTree = ""; }; - DE66F1A308ABEFB400323D32 /* GCSE.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GCSE.cpp; sourceTree = ""; }; - DE66F1A408ABEFB400323D32 /* IndVarSimplify.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IndVarSimplify.cpp; sourceTree = ""; }; - DE66F1A508ABEFB400323D32 /* InstructionCombining.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = InstructionCombining.cpp; sourceTree = ""; }; - DE66F1A608ABEFB400323D32 /* LICM.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LICM.cpp; sourceTree = ""; }; - DE66F1A808ABEFB400323D32 /* LoopStrengthReduce.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LoopStrengthReduce.cpp; sourceTree = ""; }; - DE66F1A908ABEFB400323D32 /* LoopUnroll.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LoopUnroll.cpp; sourceTree = ""; }; - DE66F1AA08ABEFB400323D32 /* LoopUnswitch.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LoopUnswitch.cpp; sourceTree = ""; }; - DE66F1B508ABEFB400323D32 /* Reassociate.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Reassociate.cpp; sourceTree = ""; }; - DE66F1B608ABEFB400323D32 /* ScalarReplAggregates.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ScalarReplAggregates.cpp; sourceTree = ""; }; - DE66F1B708ABEFB400323D32 /* SCCP.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SCCP.cpp; sourceTree = ""; }; - DE66F1B808ABEFB400323D32 /* SimplifyCFG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SimplifyCFG.cpp; sourceTree = ""; }; - DE66F1B908ABEFB400323D32 /* TailDuplication.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TailDuplication.cpp; sourceTree = ""; }; - DE66F1BA08ABEFB400323D32 /* TailRecursionElimination.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TailRecursionElimination.cpp; sourceTree = ""; }; - DE66F1BE08ABEFB400323D32 /* BasicBlockUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BasicBlockUtils.cpp; sourceTree = ""; }; - DE66F1BF08ABEFB400323D32 /* BreakCriticalEdges.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BreakCriticalEdges.cpp; sourceTree = ""; }; - DE66F1C008ABEFB400323D32 /* CloneFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CloneFunction.cpp; sourceTree = ""; }; - DE66F1C108ABEFB400323D32 /* CloneModule.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CloneModule.cpp; sourceTree = ""; }; - DE66F1C208ABEFB400323D32 /* CloneTrace.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CloneTrace.cpp; sourceTree = ""; }; - DE66F1C308ABEFB400323D32 /* CodeExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CodeExtractor.cpp; sourceTree = ""; }; - DE66F1E008ABEFB400323D32 /* DemoteRegToStack.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DemoteRegToStack.cpp; sourceTree = ""; }; - DE66F1E108ABEFB400323D32 /* InlineFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = InlineFunction.cpp; sourceTree = ""; }; - DE66F1E208ABEFB400323D32 /* Local.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Local.cpp; sourceTree = ""; }; - DE66F1E408ABEFB400323D32 /* PromoteMemoryToRegister.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PromoteMemoryToRegister.cpp; sourceTree = ""; }; - DE66F1E508ABEFB400323D32 /* SimplifyCFG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = SimplifyCFG.cpp; sourceTree = ""; }; - DE66F1E608ABEFB400323D32 /* UnifyFunctionExitNodes.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = UnifyFunctionExitNodes.cpp; sourceTree = ""; }; - DE66F1E708ABEFB400323D32 /* ValueMapper.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ValueMapper.cpp; sourceTree = ""; }; - DE66F1EA08ABF03100323D32 /* AbstractTypeUser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AbstractTypeUser.h; sourceTree = ""; }; - DE66F1EE08ABF03100323D32 /* DenseMap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DenseMap.h; sourceTree = ""; }; - DE66F1EF08ABF03100323D32 /* DepthFirstIterator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DepthFirstIterator.h; sourceTree = ""; }; - DE66F1F008ABF03100323D32 /* EquivalenceClasses.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = EquivalenceClasses.h; sourceTree = ""; }; - DE66F1F108ABF03100323D32 /* GraphTraits.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GraphTraits.h; sourceTree = ""; }; - DE66F1F308ABF03100323D32 /* hash_map.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = hash_map.in; sourceTree = ""; }; - DE66F1F508ABF03100323D32 /* hash_set.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = hash_set.in; sourceTree = ""; }; - DE66F1F608ABF03100323D32 /* HashExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = HashExtras.h; sourceTree = ""; }; - DE66F1F708ABF03100323D32 /* ilist */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ilist; sourceTree = ""; }; - DE66F1F908ABF03100323D32 /* iterator.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = iterator.in; sourceTree = ""; }; - DE66F1FA08ABF03100323D32 /* PostOrderIterator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PostOrderIterator.h; sourceTree = ""; }; - DE66F1FB08ABF03100323D32 /* SCCIterator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SCCIterator.h; sourceTree = ""; }; - DE66F1FC08ABF03100323D32 /* SetOperations.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SetOperations.h; sourceTree = ""; }; - DE66F1FD08ABF03100323D32 /* SetVector.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SetVector.h; sourceTree = ""; }; - DE66F1FE08ABF03100323D32 /* Statistic.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Statistic.h; sourceTree = ""; }; - DE66F1FF08ABF03100323D32 /* STLExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = STLExtras.h; sourceTree = ""; }; - DE66F20008ABF03100323D32 /* StringExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StringExtras.h; sourceTree = ""; }; - DE66F20108ABF03100323D32 /* Tree.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Tree.h; sourceTree = ""; }; - DE66F20208ABF03100323D32 /* VectorExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = VectorExtras.h; sourceTree = ""; }; - DE66F20408ABF03100323D32 /* AliasAnalysis.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AliasAnalysis.h; sourceTree = ""; }; - DE66F20508ABF03100323D32 /* AliasSetTracker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AliasSetTracker.h; sourceTree = ""; }; - DE66F20608ABF03100323D32 /* CallGraph.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CallGraph.h; sourceTree = ""; }; - DE66F20708ABF03100323D32 /* CFGPrinter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CFGPrinter.h; sourceTree = ""; }; - DE66F20808ABF03100323D32 /* ConstantsScanner.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ConstantsScanner.h; sourceTree = ""; }; - DE66F20F08ABF03100323D32 /* Dominators.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Dominators.h; sourceTree = ""; }; - DE66F21208ABF03100323D32 /* FindUsedTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FindUsedTypes.h; sourceTree = ""; }; - DE66F21308ABF03100323D32 /* Interval.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Interval.h; sourceTree = ""; }; - DE66F21408ABF03100323D32 /* IntervalIterator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IntervalIterator.h; sourceTree = ""; }; - DE66F21508ABF03100323D32 /* IntervalPartition.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IntervalPartition.h; sourceTree = ""; }; - DE66F21608ABF03100323D32 /* LoadValueNumbering.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LoadValueNumbering.h; sourceTree = ""; }; - DE66F21708ABF03100323D32 /* LoopInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LoopInfo.h; sourceTree = ""; }; - DE66F21808ABF03100323D32 /* Passes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Passes.h; sourceTree = ""; }; - DE66F21908ABF03100323D32 /* PostDominators.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PostDominators.h; sourceTree = ""; }; - DE66F21A08ABF03100323D32 /* ProfileInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ProfileInfo.h; sourceTree = ""; }; - DE66F21B08ABF03100323D32 /* ProfileInfoLoader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ProfileInfoLoader.h; sourceTree = ""; }; - DE66F21C08ABF03100323D32 /* ProfileInfoTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ProfileInfoTypes.h; sourceTree = ""; }; - DE66F21D08ABF03100323D32 /* ScalarEvolution.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScalarEvolution.h; sourceTree = ""; }; - DE66F21E08ABF03100323D32 /* ScalarEvolutionExpander.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScalarEvolutionExpander.h; sourceTree = ""; }; - DE66F21F08ABF03100323D32 /* ScalarEvolutionExpressions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ScalarEvolutionExpressions.h; sourceTree = ""; }; - DE66F22008ABF03100323D32 /* Trace.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Trace.h; sourceTree = ""; }; - DE66F22108ABF03100323D32 /* ValueNumbering.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ValueNumbering.h; sourceTree = ""; }; - DE66F22208ABF03100323D32 /* Verifier.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Verifier.h; sourceTree = ""; }; - DE66F22308ABF03100323D32 /* Argument.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Argument.h; sourceTree = ""; }; - DE66F22508ABF03100323D32 /* AsmAnnotationWriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AsmAnnotationWriter.h; sourceTree = ""; }; - DE66F22708ABF03100323D32 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Parser.h; sourceTree = ""; }; - DE66F22808ABF03100323D32 /* PrintModulePass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PrintModulePass.h; sourceTree = ""; }; - DE66F22908ABF03100323D32 /* Writer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Writer.h; sourceTree = ""; }; - DE66F22A08ABF03100323D32 /* BasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BasicBlock.h; sourceTree = ""; }; - DE66F23308ABF03100323D32 /* CallGraphSCCPass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CallGraphSCCPass.h; sourceTree = ""; }; - DE66F23408ABF03100323D32 /* CallingConv.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CallingConv.h; sourceTree = ""; }; - DE66F23608ABF03100323D32 /* AsmPrinter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AsmPrinter.h; sourceTree = ""; }; - DE66F23908ABF03100323D32 /* IntrinsicLowering.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IntrinsicLowering.h; sourceTree = ""; }; - DE66F23A08ABF03100323D32 /* LiveVariables.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LiveVariables.h; sourceTree = ""; }; - DE66F23B08ABF03100323D32 /* MachineBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineBasicBlock.h; sourceTree = ""; }; - DE66F23C08ABF03100323D32 /* MachineCodeEmitter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineCodeEmitter.h; sourceTree = ""; }; - DE66F23D08ABF03100323D32 /* MachineConstantPool.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineConstantPool.h; sourceTree = ""; }; - DE66F23E08ABF03100323D32 /* MachineFrameInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineFrameInfo.h; sourceTree = ""; }; - DE66F23F08ABF03100323D32 /* MachineFunction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineFunction.h; sourceTree = ""; }; - DE66F24008ABF03100323D32 /* MachineFunctionPass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineFunctionPass.h; sourceTree = ""; }; - DE66F24108ABF03100323D32 /* MachineInstr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineInstr.h; sourceTree = ""; }; - DE66F24208ABF03100323D32 /* MachineInstrBuilder.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineInstrBuilder.h; sourceTree = ""; }; - DE66F24308ABF03100323D32 /* MachineRelocation.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MachineRelocation.h; sourceTree = ""; }; - DE66F24408ABF03100323D32 /* Passes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Passes.h; sourceTree = ""; }; - DE66F24508ABF03100323D32 /* SchedGraphCommon.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SchedGraphCommon.h; sourceTree = ""; }; - DE66F24608ABF03100323D32 /* SelectionDAG.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SelectionDAG.h; sourceTree = ""; }; - DE66F24708ABF03100323D32 /* SelectionDAGISel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SelectionDAGISel.h; sourceTree = ""; }; - DE66F24808ABF03100323D32 /* SelectionDAGNodes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SelectionDAGNodes.h; sourceTree = ""; }; - DE66F24B08ABF03100323D32 /* ValueTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ValueTypes.h; sourceTree = ""; }; - DE66F24E08ABF03100323D32 /* alloca.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = alloca.h; sourceTree = ""; }; - DE66F25008ABF03100323D32 /* config.h.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = config.h.in; sourceTree = ""; }; - DE66F25108ABF03100323D32 /* Constant.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Constant.h; sourceTree = ""; }; - DE66F25208ABF03100323D32 /* Constants.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Constants.h; sourceTree = ""; }; - DE66F25408ABF03100323D32 /* Debugger.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Debugger.h; sourceTree = ""; }; - DE66F25508ABF03100323D32 /* InferiorProcess.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InferiorProcess.h; sourceTree = ""; }; - DE66F25608ABF03100323D32 /* ProgramInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ProgramInfo.h; sourceTree = ""; }; - DE66F25708ABF03100323D32 /* RuntimeInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RuntimeInfo.h; sourceTree = ""; }; - DE66F25808ABF03100323D32 /* SourceFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SourceFile.h; sourceTree = ""; }; - DE66F25908ABF03100323D32 /* SourceLanguage.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SourceLanguage.h; sourceTree = ""; }; - DE66F25A08ABF03100323D32 /* DerivedTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DerivedTypes.h; sourceTree = ""; }; - DE66F25C08ABF03100323D32 /* ExecutionEngine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ExecutionEngine.h; sourceTree = ""; }; - DE66F25D08ABF03100323D32 /* GenericValue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GenericValue.h; sourceTree = ""; }; - DE66F25E08ABF03100323D32 /* Function.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Function.h; sourceTree = ""; }; - DE66F25F08ABF03100323D32 /* GlobalValue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GlobalValue.h; sourceTree = ""; }; - DE66F26008ABF03100323D32 /* GlobalVariable.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GlobalVariable.h; sourceTree = ""; }; - DE66F26108ABF03100323D32 /* InstrTypes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InstrTypes.h; sourceTree = ""; }; - DE66F26208ABF03100323D32 /* Instruction.def */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = Instruction.def; sourceTree = ""; }; - DE66F26308ABF03100323D32 /* Instruction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Instruction.h; sourceTree = ""; }; - DE66F26408ABF03100323D32 /* Instructions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Instructions.h; sourceTree = ""; }; - DE66F26508ABF03100323D32 /* IntrinsicInst.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IntrinsicInst.h; sourceTree = ""; }; - DE66F26608ABF03100323D32 /* Intrinsics.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Intrinsics.h; sourceTree = ""; }; - DE66F26708ABF03100323D32 /* Linker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Linker.h; sourceTree = ""; }; - DE66F26808ABF03100323D32 /* Module.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Module.h; sourceTree = ""; }; - DE66F26908ABF03200323D32 /* ModuleProvider.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ModuleProvider.h; sourceTree = ""; }; - DE66F26A08ABF03200323D32 /* Pass.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Pass.h; sourceTree = ""; }; - DE66F26B08ABF03200323D32 /* PassAnalysisSupport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PassAnalysisSupport.h; sourceTree = ""; }; - DE66F26C08ABF03200323D32 /* PassManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PassManager.h; sourceTree = ""; }; - DE66F26D08ABF03200323D32 /* PassSupport.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PassSupport.h; sourceTree = ""; }; - DE66F27008ABF03200323D32 /* AIXDataTypesFix.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AIXDataTypesFix.h; sourceTree = ""; }; - DE66F27108ABF03200323D32 /* Annotation.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Annotation.h; sourceTree = ""; }; - DE66F27208ABF03200323D32 /* CallSite.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CallSite.h; sourceTree = ""; }; - DE66F27308ABF03200323D32 /* Casting.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Casting.h; sourceTree = ""; }; - DE66F27408ABF03200323D32 /* CFG.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CFG.h; sourceTree = ""; }; - DE66F27508ABF03200323D32 /* CommandLine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CommandLine.h; sourceTree = ""; }; - DE66F27708ABF03200323D32 /* ConstantRange.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ConstantRange.h; sourceTree = ""; }; - DE66F27908ABF03200323D32 /* DataTypes.h.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = DataTypes.h.in; sourceTree = ""; }; - DE66F27A08ABF03200323D32 /* Debug.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Debug.h; sourceTree = ""; }; - DE66F27B08ABF03200323D32 /* DOTGraphTraits.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DOTGraphTraits.h; sourceTree = ""; }; - DE66F27C08ABF03200323D32 /* DynamicLinker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DynamicLinker.h; sourceTree = ""; }; - DE66F27D08ABF03200323D32 /* ELF.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ELF.h; sourceTree = ""; }; - DE66F27E08ABF03200323D32 /* FileUtilities.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FileUtilities.h; sourceTree = ""; }; - DE66F27F08ABF03200323D32 /* GetElementPtrTypeIterator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GetElementPtrTypeIterator.h; sourceTree = ""; }; - DE66F28008ABF03200323D32 /* GraphWriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GraphWriter.h; sourceTree = ""; }; - DE66F28108ABF03200323D32 /* InstIterator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InstIterator.h; sourceTree = ""; }; - DE66F28208ABF03200323D32 /* InstVisitor.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InstVisitor.h; sourceTree = ""; }; - DE66F28308ABF03200323D32 /* LeakDetector.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = LeakDetector.h; sourceTree = ""; }; - DE66F28408ABF03200323D32 /* Mangler.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Mangler.h; sourceTree = ""; }; - DE66F28508ABF03200323D32 /* MathExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MathExtras.h; sourceTree = ""; }; - DE66F28608ABF03200323D32 /* MutexGuard.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MutexGuard.h; sourceTree = ""; }; - DE66F28708ABF03200323D32 /* PassNameParser.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PassNameParser.h; sourceTree = ""; }; - DE66F28808ABF03200323D32 /* PatternMatch.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PatternMatch.h; sourceTree = ""; }; - DE66F28908ABF03200323D32 /* PluginLoader.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PluginLoader.h; sourceTree = ""; }; - DE66F28A08ABF03200323D32 /* SlowOperationInformer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SlowOperationInformer.h; sourceTree = ""; }; - DE66F28B08ABF03200323D32 /* StableBasicBlockNumbering.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = StableBasicBlockNumbering.h; sourceTree = ""; }; - DE66F28C08ABF03200323D32 /* SystemUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SystemUtils.h; sourceTree = ""; }; - DE66F28E08ABF03200323D32 /* Timer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Timer.h; sourceTree = ""; }; - DE66F29008ABF03200323D32 /* type_traits.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = type_traits.h; sourceTree = ""; }; - DE66F29308ABF03200323D32 /* SymbolTableListTraits.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = SymbolTableListTraits.h; sourceTree = ""; }; - DE66F29508ABF03200323D32 /* DynamicLibrary.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DynamicLibrary.h; sourceTree = ""; }; - DE66F29608ABF03200323D32 /* LICENSE.TXT */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = LICENSE.TXT; sourceTree = ""; }; - DE66F29708ABF03200323D32 /* MappedFile.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MappedFile.h; sourceTree = ""; }; - DE66F29808ABF03200323D32 /* Memory.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Memory.h; sourceTree = ""; }; - DE66F29908ABF03200323D32 /* Mutex.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Mutex.h; sourceTree = ""; }; - DE66F29A08ABF03200323D32 /* Path.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Path.h; sourceTree = ""; }; - DE66F29B08ABF03200323D32 /* Process.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Process.h; sourceTree = ""; }; - DE66F29C08ABF03200323D32 /* Program.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Program.h; sourceTree = ""; }; - DE66F29D08ABF03200323D32 /* Signals.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Signals.h; sourceTree = ""; }; - DE66F29E08ABF03200323D32 /* TimeValue.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TimeValue.h; sourceTree = ""; }; - DE66F2A008ABF03200323D32 /* TargetRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetRegisterInfo.h; sourceTree = ""; }; - DE66F2A108ABF03200323D32 /* TargetData.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetData.h; sourceTree = ""; }; - DE66F2A208ABF03200323D32 /* TargetFrameInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetFrameInfo.h; sourceTree = ""; }; - DE66F2A308ABF03200323D32 /* TargetInstrInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetInstrInfo.h; sourceTree = ""; }; - DE66F2A408ABF03200323D32 /* TargetJITInfo.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetJITInfo.h; sourceTree = ""; }; - DE66F2A508ABF03200323D32 /* TargetLowering.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetLowering.h; sourceTree = ""; }; - DE66F2A608ABF03200323D32 /* TargetMachine.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetMachine.h; sourceTree = ""; }; - DE66F2A708ABF03200323D32 /* TargetMachineRegistry.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetMachineRegistry.h; sourceTree = ""; }; - DE66F2A808ABF03200323D32 /* TargetOptions.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetOptions.h; sourceTree = ""; }; - DE66F2AA08ABF03200323D32 /* TargetSubtarget.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TargetSubtarget.h; sourceTree = ""; }; - DE66F2AC08ABF03200323D32 /* Instrumentation.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Instrumentation.h; sourceTree = ""; }; - DE66F2AD08ABF03200323D32 /* IPO.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = IPO.h; sourceTree = ""; }; - DE66F2AF08ABF03200323D32 /* Scalar.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Scalar.h; sourceTree = ""; }; - DE66F2B108ABF03200323D32 /* BasicBlockUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BasicBlockUtils.h; sourceTree = ""; }; - DE66F2B208ABF03200323D32 /* Cloning.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Cloning.h; sourceTree = ""; }; - DE66F2B308ABF03200323D32 /* FunctionUtils.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FunctionUtils.h; sourceTree = ""; }; - DE66F2B408ABF03200323D32 /* Local.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Local.h; sourceTree = ""; }; - DE66F2B508ABF03200323D32 /* PromoteMemToReg.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PromoteMemToReg.h; sourceTree = ""; }; - DE66F2B608ABF03200323D32 /* UnifyFunctionExitNodes.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = UnifyFunctionExitNodes.h; sourceTree = ""; }; - DE66F2B708ABF03200323D32 /* Type.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Type.h; sourceTree = ""; }; - DE66F2B808ABF03200323D32 /* Use.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Use.h; sourceTree = ""; }; - DE66F2B908ABF03200323D32 /* User.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = User.h; sourceTree = ""; }; - DE66F2BA08ABF03200323D32 /* Value.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Value.h; sourceTree = ""; }; - DE66F2CC08ABF14400323D32 /* BugDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = BugDriver.cpp; sourceTree = ""; }; - DE66F2CD08ABF14400323D32 /* BugDriver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = BugDriver.h; sourceTree = ""; }; - DE66F2CE08ABF14400323D32 /* bugpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = bugpoint.cpp; sourceTree = ""; }; - DE66F2CF08ABF14400323D32 /* CrashDebugger.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CrashDebugger.cpp; sourceTree = ""; }; - DE66F2E208ABF14400323D32 /* ExecutionDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutionDriver.cpp; sourceTree = ""; }; - DE66F2E308ABF14400323D32 /* ExtractFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ExtractFunction.cpp; sourceTree = ""; }; - DE66F2E408ABF14400323D32 /* ListReducer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ListReducer.h; sourceTree = ""; }; - DE66F2E608ABF14400323D32 /* Miscompilation.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Miscompilation.cpp; sourceTree = ""; }; - DE66F2E708ABF14400323D32 /* OptimizerDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = OptimizerDriver.cpp; sourceTree = ""; }; - DE66F2E808ABF14400323D32 /* TestPasses.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TestPasses.cpp; sourceTree = ""; }; - DE66F30008ABF14400323D32 /* llc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = llc.cpp; path = llc/llc.cpp; sourceTree = ""; }; - DE66F30708ABF14400323D32 /* lli.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = lli.cpp; path = lli/lli.cpp; sourceTree = ""; }; - DE66F30E08ABF14400323D32 /* llvm-ar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-ar.cpp"; path = "llvm-ar/llvm-ar.cpp"; sourceTree = ""; }; - DE66F31508ABF14400323D32 /* llvm-as.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-as.cpp"; path = "llvm-as/llvm-as.cpp"; sourceTree = ""; }; - DE66F31C08ABF14400323D32 /* llvm-bcanalyzer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-bcanalyzer.cpp"; path = "llvm-bcanalyzer/llvm-bcanalyzer.cpp"; sourceTree = ""; }; - DE66F31F08ABF14400323D32 /* CLICommand.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLICommand.h; sourceTree = ""; }; - DE66F32008ABF14400323D32 /* CLIDebugger.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CLIDebugger.cpp; sourceTree = ""; }; - DE66F32108ABF14400323D32 /* CLIDebugger.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CLIDebugger.h; sourceTree = ""; }; - DE66F32208ABF14400323D32 /* Commands.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Commands.cpp; sourceTree = ""; }; - DE66F32B08ABF14400323D32 /* llvm-db.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "llvm-db.cpp"; sourceTree = ""; }; - DE66F33208ABF14400323D32 /* llvm-dis.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-dis.cpp"; path = "llvm-dis/llvm-dis.cpp"; sourceTree = ""; }; - DE66F33908ABF14400323D32 /* llvm-extract.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-extract.cpp"; path = "llvm-extract/llvm-extract.cpp"; sourceTree = ""; }; - DE66F34208ABF14400323D32 /* llvm-ld.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = "llvm-ld.cpp"; sourceTree = ""; }; - DE66F34408ABF14400323D32 /* Optimize.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Optimize.cpp; sourceTree = ""; }; - DE66F34A08ABF14400323D32 /* llvm-link.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-link.cpp"; path = "llvm-link/llvm-link.cpp"; sourceTree = ""; }; - DE66F35108ABF14400323D32 /* llvm-nm.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-nm.cpp"; path = "llvm-nm/llvm-nm.cpp"; sourceTree = ""; }; - DE66F35808ABF14500323D32 /* llvm-prof.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-prof.cpp"; path = "llvm-prof/llvm-prof.cpp"; sourceTree = ""; }; - DE66F35F08ABF14500323D32 /* llvm-ranlib.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = "llvm-ranlib.cpp"; path = "llvm-ranlib/llvm-ranlib.cpp"; sourceTree = ""; }; - DE66F36908ABF14500323D32 /* c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = c; sourceTree = ""; }; - DE66F36A08ABF14500323D32 /* CompilerDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CompilerDriver.cpp; sourceTree = ""; }; - DE66F36B08ABF14500323D32 /* CompilerDriver.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CompilerDriver.h; sourceTree = ""; }; - DE66F36D08ABF14500323D32 /* ConfigLexer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ConfigLexer.h; sourceTree = ""; }; - DE66F36E08ABF14500323D32 /* ConfigLexer.l */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.lex; path = ConfigLexer.l; sourceTree = ""; }; - DE66F36F08ABF14500323D32 /* Configuration.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Configuration.cpp; sourceTree = ""; }; - DE66F37008ABF14500323D32 /* Configuration.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Configuration.h; sourceTree = ""; }; - DE66F37108ABF14500323D32 /* cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = cpp; sourceTree = ""; }; - DE66F37D08ABF14500323D32 /* ll */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = ll; sourceTree = ""; }; - DE66F37E08ABF14500323D32 /* llvmc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = llvmc.cpp; sourceTree = ""; }; - DE66F38C08ABF35300323D32 /* CREDITS.TXT */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = CREDITS.TXT; path = ../CREDITS.TXT; sourceTree = SOURCE_ROOT; }; - DE66F38F08ABF35C00323D32 /* AliasAnalysis.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = AliasAnalysis.html; sourceTree = ""; }; - DE66F39008ABF35C00323D32 /* Bugpoint.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = Bugpoint.html; sourceTree = ""; }; - DE66F39208ABF35C00323D32 /* GCCFEBuildInstrs.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = GCCFEBuildInstrs.html; sourceTree = ""; }; - DE66F39308ABF35C00323D32 /* CodeGenerator.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = CodeGenerator.html; sourceTree = ""; }; - DE66F39408ABF35C00323D32 /* CodingStandards.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = CodingStandards.html; sourceTree = ""; }; - DE66F39808ABF35C00323D32 /* bugpoint.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = bugpoint.pod; sourceTree = ""; }; - DE66F39E08ABF35C00323D32 /* index.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = index.html; sourceTree = ""; }; - DE66F39F08ABF35C00323D32 /* llc.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llc.pod; sourceTree = ""; }; - DE66F3A008ABF35C00323D32 /* lli.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = lli.pod; sourceTree = ""; }; - DE66F3A108ABF35C00323D32 /* llvm-ar.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-ar.pod"; sourceTree = ""; }; - DE66F3A208ABF35C00323D32 /* llvm-as.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-as.pod"; sourceTree = ""; }; - DE66F3A308ABF35C00323D32 /* llvm-bcanalyzer.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-bcanalyzer.pod"; sourceTree = ""; }; - DE66F3A408ABF35C00323D32 /* llvm-db.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-db.pod"; sourceTree = ""; }; - DE66F3A508ABF35C00323D32 /* llvm-dis.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-dis.pod"; sourceTree = ""; }; - DE66F3A608ABF35C00323D32 /* llvm-extract.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-extract.pod"; sourceTree = ""; }; - DE66F3A708ABF35C00323D32 /* llvm-ld.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-ld.pod"; sourceTree = ""; }; - DE66F3A808ABF35C00323D32 /* llvm-link.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-link.pod"; sourceTree = ""; }; - DE66F3A908ABF35C00323D32 /* llvm-nm.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-nm.pod"; sourceTree = ""; }; - DE66F3AA08ABF35C00323D32 /* llvm-prof.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-prof.pod"; sourceTree = ""; }; - DE66F3AB08ABF35C00323D32 /* llvm-ranlib.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = "llvm-ranlib.pod"; sourceTree = ""; }; - DE66F3AC08ABF35C00323D32 /* llvmc.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llvmc.pod; sourceTree = ""; }; - DE66F3AD08ABF35C00323D32 /* llvmgcc.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llvmgcc.pod; sourceTree = ""; }; - DE66F3AE08ABF35C00323D32 /* llvmgxx.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llvmgxx.pod; sourceTree = ""; }; - DE66F3AF08ABF35C00323D32 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - DE66F3B408ABF35D00323D32 /* manpage.css */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = manpage.css; sourceTree = ""; }; - DE66F3B508ABF35D00323D32 /* opt.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = opt.pod; sourceTree = ""; }; - DE66F3B808ABF35D00323D32 /* stkrc.pod */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = stkrc.pod; sourceTree = ""; }; - DE66F3B908ABF35D00323D32 /* CommandLine.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = CommandLine.html; sourceTree = ""; }; - DE66F3BA08ABF35D00323D32 /* CompilerDriver.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = CompilerDriver.html; sourceTree = ""; }; - DE66F3BB08ABF35D00323D32 /* CompilerWriterInfo.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = CompilerWriterInfo.html; sourceTree = ""; }; - DE66F3BD08ABF35D00323D32 /* doxygen.cfg.in */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = doxygen.cfg.in; sourceTree = ""; }; - DE66F3BE08ABF35D00323D32 /* doxygen.css */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = doxygen.css; sourceTree = ""; }; - DE66F3BF08ABF35D00323D32 /* doxygen.footer */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = doxygen.footer; sourceTree = ""; }; - DE66F3C008ABF35D00323D32 /* doxygen.header */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = doxygen.header; sourceTree = ""; }; - DE66F3C108ABF35D00323D32 /* doxygen.intro */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = doxygen.intro; sourceTree = ""; }; - DE66F3C208ABF35D00323D32 /* ExtendingLLVM.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = ExtendingLLVM.html; sourceTree = ""; }; - DE66F3C308ABF35D00323D32 /* FAQ.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = FAQ.html; sourceTree = ""; }; - DE66F3C408ABF35D00323D32 /* GarbageCollection.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = GarbageCollection.html; sourceTree = ""; }; - DE66F3C508ABF35D00323D32 /* GettingStarted.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = GettingStarted.html; sourceTree = ""; }; - DE66F3C608ABF35D00323D32 /* GettingStartedVS.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = GettingStartedVS.html; sourceTree = ""; }; - DE66F3E408ABF35D00323D32 /* HowToSubmitABug.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = HowToSubmitABug.html; sourceTree = ""; }; - DE66F3E608ABF35D00323D32 /* Debugging.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = Debugging.gif; sourceTree = ""; }; - DE66F3E708ABF35D00323D32 /* libdeps.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = libdeps.gif; sourceTree = ""; }; - DE66F3E808ABF35D00323D32 /* lines.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = lines.gif; sourceTree = ""; }; - DE66F3E908ABF35D00323D32 /* objdeps.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = objdeps.gif; sourceTree = ""; }; - DE66F3EA08ABF35D00323D32 /* venusflytrap.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = venusflytrap.jpg; sourceTree = ""; }; - DE66F3EB08ABF35D00323D32 /* index.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = index.html; sourceTree = ""; }; - DE66F3EC08ABF35D00323D32 /* LangRef.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = LangRef.html; sourceTree = ""; }; - DE66F3ED08ABF35D00323D32 /* Lexicon.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = Lexicon.html; sourceTree = ""; }; - DE66F3EE08ABF35D00323D32 /* llvm.css */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = llvm.css; sourceTree = ""; }; - DE66F3F108ABF35D00323D32 /* MakefileGuide.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = MakefileGuide.html; sourceTree = ""; }; - DE66F3F208ABF35D00323D32 /* ProgrammersManual.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = ProgrammersManual.html; sourceTree = ""; }; - DE66F3F308ABF35D00323D32 /* Projects.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = Projects.html; sourceTree = ""; }; - DE66F3F408ABF35D00323D32 /* ReleaseNotes.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = ReleaseNotes.html; sourceTree = ""; }; - DE66F3F508ABF35D00323D32 /* SourceLevelDebugging.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = SourceLevelDebugging.html; sourceTree = ""; }; - DE66F3F708ABF35D00323D32 /* SystemLibrary.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = SystemLibrary.html; sourceTree = ""; }; - DE66F3F808ABF35D00323D32 /* TableGenFundamentals.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = TableGenFundamentals.html; sourceTree = ""; }; - DE66F3F908ABF35D00323D32 /* TestingGuide.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = TestingGuide.html; sourceTree = ""; }; - DE66F3FA08ABF35D00323D32 /* UsingLibraries.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = UsingLibraries.html; sourceTree = ""; }; - DE66F3FB08ABF35D00323D32 /* WritingAnLLVMBackend.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = WritingAnLLVMBackend.html; sourceTree = ""; }; - DE66F3FC08ABF35D00323D32 /* WritingAnLLVMPass.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = WritingAnLLVMPass.html; sourceTree = ""; }; - DE66F40E08ABF37000323D32 /* fibonacci.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = fibonacci.cpp; path = Fibonacci/fibonacci.cpp; sourceTree = ""; }; - DE66F41508ABF37000323D32 /* HowToUseJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = HowToUseJIT.cpp; path = HowToUseJIT/HowToUseJIT.cpp; sourceTree = ""; }; - DE66F41E08ABF37000323D32 /* ModuleMaker.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ModuleMaker.cpp; path = ModuleMaker/ModuleMaker.cpp; sourceTree = ""; }; - DE66F42608ABF37000323D32 /* ParallelJIT.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ParallelJIT.cpp; path = ParallelJIT/ParallelJIT.cpp; sourceTree = ""; }; - DE694D9F08B51E0C0039C106 /* ScheduleDAG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ScheduleDAG.cpp; sourceTree = ""; }; - DE81704008CFB44D0093BDEF /* fpcmp.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = fpcmp.cpp; path = fpcmp/fpcmp.cpp; sourceTree = ""; }; - DE81704F08CFB44D0093BDEF /* NightlyTest.gnuplot */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = NightlyTest.gnuplot; sourceTree = ""; }; - DE81705108CFB44D0093BDEF /* NightlyTestTemplate.html */ = {isa = PBXFileReference; explicitFileType = text.html.documentation; fileEncoding = 30; path = NightlyTestTemplate.html; sourceTree = ""; }; - DE81705908CFB44D0093BDEF /* AsmWriterEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = AsmWriterEmitter.cpp; sourceTree = ""; }; - DE81705A08CFB44D0093BDEF /* AsmWriterEmitter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = AsmWriterEmitter.h; sourceTree = ""; }; - DE81705B08CFB44D0093BDEF /* CodeEmitterGen.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CodeEmitterGen.cpp; sourceTree = ""; }; - DE81705C08CFB44D0093BDEF /* CodeEmitterGen.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CodeEmitterGen.h; sourceTree = ""; }; - DE81705D08CFB44D0093BDEF /* CodeGenInstruction.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CodeGenInstruction.h; sourceTree = ""; }; - DE81705E08CFB44D0093BDEF /* CodeGenRegisters.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CodeGenRegisters.h; sourceTree = ""; }; - DE81705F08CFB44D0093BDEF /* CodeGenTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CodeGenTarget.cpp; sourceTree = ""; }; - DE81706008CFB44D0093BDEF /* CodeGenTarget.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CodeGenTarget.h; sourceTree = ""; }; - DE81706708CFB44D0093BDEF /* DAGISelEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DAGISelEmitter.cpp; sourceTree = ""; }; - DE81706808CFB44D0093BDEF /* DAGISelEmitter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DAGISelEmitter.h; sourceTree = ""; }; - DE81708908CFB44D0093BDEF /* InstrInfoEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = InstrInfoEmitter.cpp; sourceTree = ""; }; - DE81708A08CFB44D0093BDEF /* InstrInfoEmitter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InstrInfoEmitter.h; sourceTree = ""; }; - DE81708E08CFB44D0093BDEF /* Record.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Record.cpp; sourceTree = ""; }; - DE81708F08CFB44D0093BDEF /* Record.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Record.h; sourceTree = ""; }; - DE81709008CFB44D0093BDEF /* RegisterInfoEmitter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RegisterInfoEmitter.cpp; sourceTree = ""; }; - DE81709108CFB44D0093BDEF /* RegisterInfoEmitter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RegisterInfoEmitter.h; sourceTree = ""; }; - DE8170AA08CFB44D0093BDEF /* TableGen.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TableGen.cpp; sourceTree = ""; }; - DE8170AB08CFB44D0093BDEF /* TableGenBackend.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = TableGenBackend.cpp; sourceTree = ""; }; - DE8170AC08CFB44D0093BDEF /* TableGenBackend.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TableGenBackend.h; sourceTree = ""; }; - DEFAB19D0959E9A100E0AB42 /* DwarfWriter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = DwarfWriter.h; path = ../include/llvm/CodeGen/DwarfWriter.h; sourceTree = SOURCE_ROOT; }; - F22627320DAE34D10008F441 /* index.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = index.html; sourceTree = ""; }; - F22627330DAE34D20008F441 /* JITTutorial1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = JITTutorial1.html; sourceTree = ""; }; - F22627340DAE34D20008F441 /* JITTutorial2-1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "JITTutorial2-1.png"; sourceTree = ""; }; - F22627350DAE34D20008F441 /* JITTutorial2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = JITTutorial2.html; sourceTree = ""; }; - F22627360DAE34D20008F441 /* LangImpl1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LangImpl1.html; sourceTree = ""; }; - F22627370DAE34D20008F441 /* LangImpl2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LangImpl2.html; sourceTree = ""; }; - F22627380DAE34D20008F441 /* LangImpl3.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LangImpl3.html; sourceTree = ""; }; - F22627390DAE34D20008F441 /* LangImpl4.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LangImpl4.html; sourceTree = ""; }; - F226273A0DAE34D20008F441 /* LangImpl5-cfg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "LangImpl5-cfg.png"; sourceTree = ""; }; - F226273B0DAE34D20008F441 /* LangImpl5.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LangImpl5.html; sourceTree = ""; }; - F226273C0DAE34D20008F441 /* LangImpl6.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LangImpl6.html; sourceTree = ""; }; - F226273D0DAE34D20008F441 /* LangImpl7.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LangImpl7.html; sourceTree = ""; }; - F226273E0DAE34D20008F441 /* LangImpl8.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LangImpl8.html; sourceTree = ""; }; - F226273F0DAE34D20008F441 /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = ""; }; - F22627400DAE34D20008F441 /* OCamlLangImpl1.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = OCamlLangImpl1.html; sourceTree = ""; }; - F22627410DAE34D20008F441 /* OCamlLangImpl2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = OCamlLangImpl2.html; sourceTree = ""; }; - F22627420DAE34D20008F441 /* OCamlLangImpl3.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = OCamlLangImpl3.html; sourceTree = ""; }; - F22627430DAE34D20008F441 /* OCamlLangImpl4.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = OCamlLangImpl4.html; sourceTree = ""; }; - F22627440DAE34D20008F441 /* OCamlLangImpl5.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = OCamlLangImpl5.html; sourceTree = ""; }; - F22627450DAE34D20008F441 /* OCamlLangImpl6.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = OCamlLangImpl6.html; sourceTree = ""; }; - F22627460DAE34D20008F441 /* OCamlLangImpl7.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = OCamlLangImpl7.html; sourceTree = ""; }; - F22761DF0DAD09CD003D8065 /* BrainF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BrainF.cpp; path = BrainF/BrainF.cpp; sourceTree = ""; }; - F22761E00DAD09CD003D8065 /* BrainF.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BrainF.h; path = BrainF/BrainF.h; sourceTree = ""; }; - F22761E10DAD09CD003D8065 /* BrainFDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BrainFDriver.cpp; path = BrainF/BrainFDriver.cpp; sourceTree = ""; }; - F27C8CE90DAD2EF900A33844 /* IRBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IRBuilder.h; sourceTree = ""; }; - F27C8CFF0DAD307700A33844 /* ShadowStackCollector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowStackCollector.cpp; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXGroup section */ - 08FB7794FE84155DC02AAC07 /* LLVM */ = { - isa = PBXGroup; - children = ( - DE66F1E908ABF03100323D32 /* include/llvm */, - CF8F1B480B64F7AB00BB4199 /* include/llvm-c */, - DE66ECBD08ABEC0700323D32 /* lib/Analysis */, - 9FE450DE0C77ABE400C4FEA4 /* lib/Archive */, - DE66EC8808ABEAC900323D32 /* lib/AsmParser */, - 9F68EB030C77AD2C004AA152 /* lib/Bitcode */, - DE66ED3E08ABEC2A00323D32 /* lib/CodeGen */, - DE66ED9A08ABEC7200323D32 /* lib/Debugger */, - DE66EDBF08ABEC8F00323D32 /* lib/ExecutionEngine */, - DE66EDEB08ABEDD300323D32 /* lib/Linker */, - DE66EDFB08ABEDE600323D32 /* lib/Support */, - DE66EE4908ABEE3400323D32 /* lib/System */, - DE66EE9608ABEE5D00323D32 /* lib/Target */, - DE66F0E108ABEFB300323D32 /* lib/Transforms */, - DE66EC7508ABE8EF00323D32 /* lib/VMCore */, - DE66F2BD08ABF14400323D32 /* tools */, - DE816FAC08CFB44C0093BDEF /* utils */, - DE66F38D08ABF35C00323D32 /* docs */, - 9FD3E56D0CA0116100E54D15 /* bindings */, - 9F7C2B690CB9496B00498408 /* test */, - DE66F3FD08ABF37000323D32 /* examples */, - DE66F38C08ABF35300323D32 /* CREDITS.TXT */, - CFD99AA80AFE827B0068D19C /* LICENSE.TXT */, - CFD99AAD0AFE827B0068D19C /* README.txt */, - 721CA1750D0B44D200D5004F /* Products */, - ); - name = LLVM; - sourceTree = ""; - }; - 721CA1750D0B44D200D5004F /* Products */ = { - isa = PBXGroup; - children = ( - ); - name = Products; - sourceTree = ""; - }; - 9F4B0E5D0D0E02580061F270 /* bitreader */ = { - isa = PBXGroup; - children = ( - 9F4B0E5E0D0E02580061F270 /* bitreader_ocaml.c */, - 9F4B0E5F0D0E02580061F270 /* llvm_bitreader.ml */, - 9F4B0E600D0E02580061F270 /* llvm_bitreader.mli */, - ); - path = bitreader; - sourceTree = ""; - }; - 9F502ACD0D1D8CA3007939DF /* executionengine */ = { - isa = PBXGroup; - children = ( - 9F502ADB0D1D8CA3007939DF /* executionengine_ocaml.c */, - 9F502ADC0D1D8CA3007939DF /* llvm_executionengine.ml */, - 9F502ADD0D1D8CA3007939DF /* llvm_executionengine.mli */, - ); - path = executionengine; - sourceTree = ""; - }; - 9F68EB030C77AD2C004AA152 /* lib/Bitcode */ = { - isa = PBXGroup; - children = ( - 9F68EB050C77AD2C004AA152 /* Reader */, - 9F68EB110C77AD2C004AA152 /* Writer */, - ); - name = lib/Bitcode; - path = ../lib/Bitcode; - sourceTree = SOURCE_ROOT; - }; - 9F68EB050C77AD2C004AA152 /* Reader */ = { - isa = PBXGroup; - children = ( - 35A9CDF00CD0F6D5008ABC1D /* Deserialize.cpp */, - 9F4B0E8D0D0E05ED0061F270 /* DeserializeAPFloat.cpp */, - 354CF6D10CD299440059AF3E /* DeserializeAPInt.cpp */, - 9F68EB060C77AD2C004AA152 /* BitcodeReader.cpp */, - 9F68EB070C77AD2C004AA152 /* BitcodeReader.h */, - 9F4B0E8C0D0E05ED0061F270 /* BitReader.cpp */, - ); - path = Reader; - sourceTree = ""; - }; - 9F68EB110C77AD2C004AA152 /* Writer */ = { - isa = PBXGroup; - children = ( - 354CF6D20CD2994D0059AF3E /* SerializeAPInt.cpp */, - 9FD3E5920CA012B300E54D15 /* BitWriter.cpp */, - 9F68EB120C77AD2C004AA152 /* BitcodeWriter.cpp */, - 9F68EB130C77AD2C004AA152 /* BitcodeWriterPass.cpp */, - 9F68EB250C77AD2C004AA152 /* ValueEnumerator.cpp */, - 9F68EB260C77AD2C004AA152 /* ValueEnumerator.h */, - 35A9CDF10CD0F6E1008ABC1D /* Serialize.cpp */, - ); - path = Writer; - sourceTree = ""; - }; - 9F7040170D8D72FF00FD06FF /* transforms */ = { - isa = PBXGroup; - children = ( - 9F7040190D8D730A00FD06FF /* scalar */, - ); - name = transforms; - sourceTree = ""; - }; - 9F7040190D8D730A00FD06FF /* scalar */ = { - isa = PBXGroup; - children = ( - 9F70401A0D8D732400FD06FF /* llvm_scalar_opts.ml */, - 9F70401B0D8D732400FD06FF /* llvm_scalar_opts.mli */, - 9F70401E0D8D735E00FD06FF /* scalar_opts_ocaml.c */, - ); - name = scalar; - sourceTree = ""; - }; - 9F77937F0C73C54C00551F9C /* Bitcode */ = { - isa = PBXGroup; - children = ( - 9F7793800C73C54C00551F9C /* Archive.h */, - 9F7793810C73C54C00551F9C /* BitCodes.h */, - 9F7793820C73C54C00551F9C /* BitstreamReader.h */, - 9F7793830C73C54C00551F9C /* BitstreamWriter.h */, - 9F7793840C73C54C00551F9C /* LLVMBitCodes.h */, - 9F7793850C73C54C00551F9C /* ReaderWriter.h */, - 35A9CDEE0CD0F6AF008ABC1D /* Serialization.h */, - 35A9CDEF0CD0F6AF008ABC1D /* Serialize.h */, - 35A9CDED0CD0F6AF008ABC1D /* Deserialize.h */, - ); - path = Bitcode; - sourceTree = ""; - }; - 9F7794120C73CB6100551F9C /* Mips */ = { - isa = PBXGroup; - children = ( - 9F7794140C73CB6100551F9C /* Mips.h */, - 9F7794150C73CB6100551F9C /* Mips.td */, - 9F7794160C73CB6100551F9C /* MipsAsmPrinter.cpp */, - 9F7794170C73CB6100551F9C /* MipsCallingConv.td */, - 9F7794180C73CB6100551F9C /* MipsInstrFormats.td */, - 9F7794190C73CB6100551F9C /* MipsInstrInfo.cpp */, - 9F77941A0C73CB6100551F9C /* MipsInstrInfo.h */, - 9F77941B0C73CB6100551F9C /* MipsInstrInfo.td */, - 9F77941C0C73CB6100551F9C /* MipsISelDAGToDAG.cpp */, - 9F77941D0C73CB6100551F9C /* MipsISelLowering.cpp */, - 9F77941E0C73CB6100551F9C /* MipsISelLowering.h */, - 9F77941F0C73CB6100551F9C /* MipsMachineFunction.h */, - 9F7794200C73CB6100551F9C /* MipsRegisterInfo.cpp */, - 9F7794210C73CB6100551F9C /* MipsRegisterInfo.h */, - 9F7794220C73CB6100551F9C /* MipsRegisterInfo.td */, - 9F7794230C73CB6100551F9C /* MipsSubtarget.cpp */, - 9F7794240C73CB6100551F9C /* MipsSubtarget.h */, - 9F7794250C73CB6100551F9C /* MipsTargetAsmInfo.cpp */, - 9F7794260C73CB6100551F9C /* MipsTargetAsmInfo.h */, - 9F7794270C73CB6100551F9C /* MipsTargetMachine.cpp */, - 9F7794280C73CB6100551F9C /* MipsTargetMachine.h */, - ); - path = Mips; - sourceTree = ""; - }; - 9F7794290C73CB7900551F9C /* MSIL */ = { - isa = PBXGroup; - children = ( - 9F77942F0C73CB7900551F9C /* MSILWriter.cpp */, - 9F7794300C73CB7900551F9C /* MSILWriter.h */, - ); - path = MSIL; - sourceTree = ""; - }; - 9F7C240B0CB81ECD00498408 /* analysis */ = { - isa = PBXGroup; - children = ( - 9F7C240C0CB81ECD00498408 /* analysis_ocaml.c */, - 9F7C240D0CB81ECD00498408 /* llvm_analysis.ml */, - 9F7C240E0CB81ECD00498408 /* llvm_analysis.mli */, - ); - path = analysis; - sourceTree = ""; - }; - 9F7C2B690CB9496B00498408 /* test */ = { - isa = PBXGroup; - children = ( - 9F7C2C4B0CB9496C00498408 /* Bindings */, - ); - name = test; - path = ../test; - sourceTree = SOURCE_ROOT; - }; - 9F7C2C4B0CB9496C00498408 /* Bindings */ = { - isa = PBXGroup; - children = ( - 9F7C2C4C0CB9496C00498408 /* Ocaml */, - ); - path = Bindings; - sourceTree = ""; - }; - 9F7C2C4C0CB9496C00498408 /* Ocaml */ = { - isa = PBXGroup; - children = ( - 9F7C2C4F0CB9496C00498408 /* analysis.ml */, - 9F6B2CC00D0F6E56000F00FD /* bitreader.ml */, - 9F7C2C520CB9496C00498408 /* bitwriter.ml */, - 9F502AEC0D1D8CF8007939DF /* executionengine.ml */, - 9FEDD6140D8D7C3B009F6DF1 /* scalar_opts.ml */, - 9FEDD6BD0D8D8426009F6DF1 /* target.ml */, - 9F7C2C5D0CB9496C00498408 /* vmcore.ml */, - ); - path = Ocaml; - sourceTree = ""; - }; - 9FA638E90C77B252007F12AE /* IPO */ = { - isa = PBXGroup; - children = ( - 9FA638EA0C77B252007F12AE /* InlinerPass.h */, - ); - path = IPO; - sourceTree = ""; - }; - 9FD3E56D0CA0116100E54D15 /* bindings */ = { - isa = PBXGroup; - children = ( - 9FD3E56F0CA0116100E54D15 /* ocaml */, - ); - name = bindings; - path = ../bindings; - sourceTree = SOURCE_ROOT; - }; - 9FD3E56F0CA0116100E54D15 /* ocaml */ = { - isa = PBXGroup; - children = ( - 9F502ACD0D1D8CA3007939DF /* executionengine */, - 9F7C240B0CB81ECD00498408 /* analysis */, - 9F4B0E5D0D0E02580061F270 /* bitreader */, - 9FD3E5700CA0116100E54D15 /* bitwriter */, - 9FD3E57A0CA0116100E54D15 /* llvm */, - 9FEDD6C00D8D844E009F6DF1 /* target */, - 9F7040170D8D72FF00FD06FF /* transforms */, - ); - path = ocaml; - sourceTree = ""; - }; - 9FD3E5700CA0116100E54D15 /* bitwriter */ = { - isa = PBXGroup; - children = ( - 9FD3E5710CA0116100E54D15 /* bitwriter_ocaml.c */, - 9FD3E5720CA0116100E54D15 /* llvm_bitwriter.ml */, - 9FD3E5730CA0116100E54D15 /* llvm_bitwriter.mli */, - ); - path = bitwriter; - sourceTree = ""; - }; - 9FD3E57A0CA0116100E54D15 /* llvm */ = { - isa = PBXGroup; - children = ( - 9FD3E57B0CA0116100E54D15 /* llvm.ml */, - 9FD3E57C0CA0116100E54D15 /* llvm.mli */, - 9FD3E57D0CA0116100E54D15 /* llvm_ocaml.c */, - ); - path = llvm; - sourceTree = ""; - }; - 9FE450DE0C77ABE400C4FEA4 /* lib/Archive */ = { - isa = PBXGroup; - children = ( - 9FE450DF0C77ABE400C4FEA4 /* Archive.cpp */, - 9FE450E00C77ABE400C4FEA4 /* ArchiveInternals.h */, - 9FE450E10C77ABE400C4FEA4 /* ArchiveReader.cpp */, - 9FE450E20C77ABE400C4FEA4 /* ArchiveWriter.cpp */, - ); - name = lib/Archive; - path = ../lib/Archive; - sourceTree = SOURCE_ROOT; - }; - 9FEDD5F00D8D73AB009F6DF1 /* Transforms */ = { - isa = PBXGroup; - children = ( - 9FEDD5F10D8D73AB009F6DF1 /* Scalar.h */, - ); - path = Transforms; - sourceTree = ""; - }; - 9FEDD6C00D8D844E009F6DF1 /* target */ = { - isa = PBXGroup; - children = ( - 9FEDD6C10D8D844E009F6DF1 /* llvm_target.ml */, - 9FEDD6C20D8D844E009F6DF1 /* llvm_target.mli */, - 9FEDD6C40D8D844E009F6DF1 /* target_ocaml.c */, - ); - path = target; - sourceTree = ""; - }; - CF8F1B480B64F7AB00BB4199 /* include/llvm-c */ = { - isa = PBXGroup; - children = ( - 9F7C23E50CB81C2100498408 /* Analysis.h */, - 9F5B90E70D0DF19100CDFDEA /* BitReader.h */, - 9FD3E58D0CA0125F00E54D15 /* BitWriter.h */, - 9FD3E58E0CA0125F00E54D15 /* Core.h */, - 9FEB8C550D1CD1E200EE46BC /* ExecutionEngine.h */, - CF8F1B490B64F7AB00BB4199 /* LinkTimeOptimizer.h */, - 9FEDD6BB0D8D8408009F6DF1 /* lto.h */, - 9FEDD6B80D8D83EC009F6DF1 /* Target.h */, - 9FEDD5F00D8D73AB009F6DF1 /* Transforms */, - ); - name = "include/llvm-c"; - path = "../include/llvm-c"; - sourceTree = SOURCE_ROOT; - }; - CF8F1B5E0B64FADA00BB4199 /* llvm-upgrade */ = { - isa = PBXGroup; - children = ( - CF8F1B680B64FADA00BB4199 /* llvm-upgrade.cpp */, - CF8F1B720B64FADA00BB4199 /* UpgradeInternals.h */, - CF8F1B750B64FADA00BB4199 /* UpgradeLexer.l */, - CF8F1B7C0B64FADA00BB4199 /* UpgradeParser.y */, - ); - path = "llvm-upgrade"; - sourceTree = ""; - }; - CF8F1B7E0B64FADA00BB4199 /* llvm2cpp */ = { - isa = PBXGroup; - children = ( - CF8F1B7F0B64FADA00BB4199 /* CppWriter.cpp */, - CF8F1B800B64FADA00BB4199 /* CppWriter.h */, - CF8F1B870B64FADA00BB4199 /* llvm2cpp.cpp */, - ); - path = llvm2cpp; - sourceTree = ""; - }; - CF8F1B960B64FB7F00BB4199 /* lto */ = { - isa = PBXGroup; - children = ( - CF8F1B9D0B64FB7F00BB4199 /* lto-c.cpp */, - CF8F1B9E0B64FB7F00BB4199 /* lto.cpp */, - ); - path = lto; - sourceTree = ""; - }; - CF8F1BAB0B64FB8000BB4199 /* opt */ = { - isa = PBXGroup; - children = ( - CF8F1BAC0B64FB8000BB4199 /* AnalysisWrappers.cpp */, - CF8F1BB70B64FB8000BB4199 /* GraphPrinters.cpp */, - CF8F1BB90B64FB8000BB4199 /* opt.cpp */, - CF8F1BBA0B64FB8000BB4199 /* PrintSCC.cpp */, - ); - path = opt; - sourceTree = ""; - }; - CF8F1BCF0B64FC8A00BB4199 /* ARM */ = { - isa = PBXGroup; - children = ( - 9FE4508B0C77A77000C4FEA4 /* ARMCodeEmitter.cpp */, - 9FE4508C0C77A77000C4FEA4 /* ARMGenAsmWriter.inc */, - 9FE4508D0C77A77000C4FEA4 /* ARMGenDAGISel.inc */, - 9FE4508E0C77A77100C4FEA4 /* ARMGenInstrInfo.inc */, - 9FE4508F0C77A77100C4FEA4 /* ARMGenInstrNames.inc */, - 9FE450900C77A77100C4FEA4 /* ARMGenRegisterInfo.h.inc */, - 9FE450910C77A77100C4FEA4 /* ARMGenRegisterInfo.inc */, - 9FE450920C77A77100C4FEA4 /* ARMGenRegisterNames.inc */, - 9FE450930C77A77100C4FEA4 /* ARMGenSubtarget.inc */, - 9FE450940C77A77100C4FEA4 /* ARMJITInfo.cpp */, - 9FE450950C77A77100C4FEA4 /* ARMJITInfo.h */, - 9FE450960C77A77100C4FEA4 /* ARMRelocations.h */, - 9FE450970C77A77100C4FEA4 /* README-Thumb.txt */, - 9FE450980C77A77100C4FEA4 /* README.txt */, - CF8F1BD10B64FC8A00BB4199 /* ARM.h */, - CF8F1BD20B64FC8A00BB4199 /* ARM.td */, - CF8F1BD30B64FC8A00BB4199 /* ARMAddressingModes.h */, - CF8F1BD40B64FC8A00BB4199 /* ARMAsmPrinter.cpp */, - CF8F1BD50B64FC8A00BB4199 /* ARMConstantIslandPass.cpp */, - CF8F1BD60B64FC8A00BB4199 /* ARMConstantPoolValue.cpp */, - CF8F1BD70B64FC8A00BB4199 /* ARMConstantPoolValue.h */, - CF8F1BD80B64FC8A00BB4199 /* ARMFrameInfo.h */, - CF8F1BD90B64FC8A00BB4199 /* ARMInstrInfo.cpp */, - CF8F1BDA0B64FC8A00BB4199 /* ARMInstrInfo.h */, - CF8F1BDB0B64FC8A00BB4199 /* ARMInstrInfo.td */, - CF8F1BDC0B64FC8A00BB4199 /* ARMInstrThumb.td */, - CF8F1BDD0B64FC8A00BB4199 /* ARMInstrVFP.td */, - CF8F1BDE0B64FC8A00BB4199 /* ARMISelDAGToDAG.cpp */, - CF8F1BDF0B64FC8A00BB4199 /* ARMISelLowering.cpp */, - CF8F1BE00B64FC8A00BB4199 /* ARMISelLowering.h */, - CF8F1BE10B64FC8A00BB4199 /* ARMLoadStoreOptimizer.cpp */, - CF8F1BE20B64FC8A00BB4199 /* ARMMachineFunctionInfo.h */, - CF8F1BE30B64FC8A00BB4199 /* ARMRegisterInfo.cpp */, - CF8F1BE40B64FC8A00BB4199 /* ARMRegisterInfo.h */, - CF8F1BE50B64FC8A00BB4199 /* ARMRegisterInfo.td */, - CF8F1BE60B64FC8A00BB4199 /* ARMSubtarget.cpp */, - CF8F1BE70B64FC8A00BB4199 /* ARMSubtarget.h */, - CF8F1BE80B64FC8A00BB4199 /* ARMTargetAsmInfo.cpp */, - CF8F1BE90B64FC8A00BB4199 /* ARMTargetAsmInfo.h */, - CF8F1BEA0B64FC8A00BB4199 /* ARMTargetMachine.cpp */, - CF8F1BEB0B64FC8A00BB4199 /* ARMTargetMachine.h */, - ); - path = ARM; - sourceTree = ""; - }; - CFD99ADF0AFE878F0068D19C /* opt */ = { - isa = PBXGroup; - children = ( - CFD99ADB0AFE87870068D19C /* AnalysisWrappers.cpp */, - CFD99ADC0AFE87870068D19C /* GraphPrinters.cpp */, - CFD99ADD0AFE87870068D19C /* opt.cpp */, - CFD99ADE0AFE87870068D19C /* PrintSCC.cpp */, - ); - name = opt; - sourceTree = ""; - }; - CFE4213C0A66FAE100AB4BF6 /* Hello */ = { - isa = PBXGroup; - children = ( - CFE4213D0A66FAE100AB4BF6 /* Hello.cpp */, - ); - path = Hello; - sourceTree = ""; - }; - DE66EC7508ABE8EF00323D32 /* lib/VMCore */ = { - isa = PBXGroup; - children = ( - DE66EC5B08ABE86900323D32 /* AsmWriter.cpp */, - 9F77937B0C73C4F400551F9C /* AutoUpgrade.cpp */, - DE66EC5C08ABE86A00323D32 /* BasicBlock.cpp */, - 9F77937C0C73C4F400551F9C /* ConstantFold.cpp */, - 9F77937D0C73C4F400551F9C /* ConstantFold.h */, - DE66EC6008ABE86A00323D32 /* Constants.cpp */, - 9FD3E5900CA0129D00E54D15 /* Core.cpp */, - DE66EC6108ABE86A00323D32 /* Dominators.cpp */, - DE66EC6208ABE86A00323D32 /* Function.cpp */, - DE66EC6308ABE86A00323D32 /* Globals.cpp */, - CF73C0BD098A551F00627152 /* InlineAsm.cpp */, - DE66EC6408ABE86A00323D32 /* Instruction.cpp */, - DE66EC6508ABE86A00323D32 /* Instructions.cpp */, - CF1ACC9709C9DE4400D3C5EB /* IntrinsicInst.cpp */, - DE66EC6608ABE86A00323D32 /* LeakDetector.cpp */, - DE66EC6708ABE86A00323D32 /* Mangler.cpp */, - DE66EC6808ABE86A00323D32 /* Module.cpp */, - DE66EC6908ABE86A00323D32 /* ModuleProvider.cpp */, - DE66EC6A08ABE86A00323D32 /* Pass.cpp */, - CF8F1B5C0B64FA7300BB4199 /* PassManager.cpp */, - DE66EC6D08ABE86A00323D32 /* SymbolTableListTraitsImpl.h */, - DE66EC6E08ABE86A00323D32 /* Type.cpp */, - CF73C0BE098A551F00627152 /* TypeSymbolTable.cpp */, - DE66EC6F08ABE86A00323D32 /* Value.cpp */, - CF73C0BF098A551F00627152 /* ValueSymbolTable.cpp */, - CF9720900A9F3CA2002CEEDD /* ValueTypes.cpp */, - DE66EC7008ABE86A00323D32 /* Verifier.cpp */, - ); - name = lib/VMCore; - sourceTree = ""; - }; - DE66EC8808ABEAC900323D32 /* lib/AsmParser */ = { - isa = PBXGroup; - children = ( - DE66EC8E08ABEAF000323D32 /* llvmAsmParser.y */, - DE66EC8F08ABEAF000323D32 /* Parser.cpp */, - DE66EC9008ABEAF000323D32 /* ParserInternals.h */, - ); - name = lib/AsmParser; - sourceTree = ""; - }; - DE66ECBD08ABEC0700323D32 /* lib/Analysis */ = { - isa = PBXGroup; - children = ( - DE66ED1A08ABEC0800323D32 /* IPA */, - DE66ECBE08ABEC0700323D32 /* AliasAnalysis.cpp */, - DE66ECBF08ABEC0700323D32 /* AliasAnalysisCounter.cpp */, - DE66ECC008ABEC0700323D32 /* AliasAnalysisEvaluator.cpp */, - CF8F1B4D0B64F80700BB4199 /* AliasDebugger.cpp */, - DE66ECC108ABEC0700323D32 /* AliasSetTracker.cpp */, - 9F7C23E60CB81C2B00498408 /* Analysis.cpp */, - DE66ECC208ABEC0700323D32 /* BasicAliasAnalysis.cpp */, - DE66ECC308ABEC0700323D32 /* CFGPrinter.cpp */, - CF73C0B0098A523C00627152 /* ConstantFolding.cpp */, - DE66ED1708ABEC0800323D32 /* InstCount.cpp */, - DE66ED1808ABEC0800323D32 /* Interval.cpp */, - DE66ED1908ABEC0800323D32 /* IntervalPartition.cpp */, - DE66ED3308ABEC0800323D32 /* LoadValueNumbering.cpp */, - DE66ED3408ABEC0800323D32 /* LoopInfo.cpp */, - 9F68EB010C77AD02004AA152 /* LoopPass.cpp */, - 9F68EB020C77AD02004AA152 /* MemoryDependenceAnalysis.cpp */, - DE66ED3608ABEC0800323D32 /* PostDominators.cpp */, - DE66ED3708ABEC0800323D32 /* ProfileInfo.cpp */, - DE66ED3808ABEC0800323D32 /* ProfileInfoLoader.cpp */, - DE66ED3908ABEC0800323D32 /* ProfileInfoLoaderPass.cpp */, - DE66ED3A08ABEC0800323D32 /* ScalarEvolution.cpp */, - DE66ED3B08ABEC0800323D32 /* ScalarEvolutionExpander.cpp */, - DE66ED3C08ABEC0800323D32 /* Trace.cpp */, - DE66ED3D08ABEC0800323D32 /* ValueNumbering.cpp */, - ); - name = lib/Analysis; - path = ../lib/Analysis; - sourceTree = SOURCE_ROOT; - }; - DE66ED1A08ABEC0800323D32 /* IPA */ = { - isa = PBXGroup; - children = ( - DE66ED1B08ABEC0800323D32 /* Andersens.cpp */, - DE66ED1C08ABEC0800323D32 /* CallGraph.cpp */, - DE66ED1D08ABEC0800323D32 /* CallGraphSCCPass.cpp */, - DE66ED2F08ABEC0800323D32 /* FindUsedTypes.cpp */, - DE66ED3008ABEC0800323D32 /* GlobalsModRef.cpp */, - ); - path = IPA; - sourceTree = ""; - }; - DE66ED3E08ABEC2A00323D32 /* lib/CodeGen */ = { - isa = PBXGroup; - children = ( - F27C8CFF0DAD307700A33844 /* ShadowStackCollector.cpp */, - 754221420D171DFC00DDB61B /* MachineLICM.cpp */, - 9FE450AB0C77AB6100C4FEA4 /* README.txt */, - DE66ED8308ABEC2B00323D32 /* SelectionDAG */, - DE66ED3F08ABEC2A00323D32 /* AsmPrinter.cpp */, - DE66ED4008ABEC2A00323D32 /* BranchFolding.cpp */, - CFC244570959DEF2009F8C47 /* DwarfWriter.cpp */, - 9F7793500C73BD1500551F9C /* ELFWriter.h */, - DE66ED6F08ABEC2B00323D32 /* ELFWriter.cpp */, - 9F7793510C73BD1500551F9C /* IfConversion.cpp */, - DE66ED7008ABEC2B00323D32 /* IntrinsicLowering.cpp */, - DE66ED7108ABEC2B00323D32 /* LiveInterval.cpp */, - DE66ED7308ABEC2B00323D32 /* LiveIntervalAnalysis.cpp */, - DE66ED7508ABEC2B00323D32 /* LiveVariables.cpp */, - CF32AF5C0AEE6A4E00D24CD4 /* LLVMTargetMachine.cpp */, - 9F7793520C73BD1500551F9C /* LowerSubregs.cpp */, - DE66ED7608ABEC2B00323D32 /* MachineBasicBlock.cpp */, - CF6529A6095B21A8007F884E /* MachineModuleInfo.cpp */, - DE66ED7808ABEC2B00323D32 /* MachineFunction.cpp */, - DE66ED7908ABEC2B00323D32 /* MachineInstr.cpp */, - CF4F27F60A7B6FA3004359F6 /* MachinePassRegistry.cpp */, - 9F7793530C73BD1500551F9C /* MachOWriter.h */, - CF9720350A9F3ADC002CEEDD /* MachOWriter.cpp */, - DE66ED7B08ABEC2B00323D32 /* Passes.cpp */, - DE66ED7C08ABEC2B00323D32 /* PHIElimination.cpp */, - 9F7793540C73BD1500551F9C /* PostRASchedulerList.cpp */, - DE66ED7D08ABEC2B00323D32 /* PhysRegTracker.h */, - DE66ED7E08ABEC2B00323D32 /* PrologEpilogInserter.cpp */, - 9F7793550C73BD1500551F9C /* RegAllocBigBlock.cpp */, - DE66ED8008ABEC2B00323D32 /* RegAllocLinearScan.cpp */, - DE66ED8108ABEC2B00323D32 /* RegAllocLocal.cpp */, - 9FE25D940CAB16FB005383FC /* RegisterCoalescer.cpp */, - 9F7793560C73BD1500551F9C /* RegisterScavenging.cpp */, - DE66ED8208ABEC2B00323D32 /* RegAllocSimple.cpp */, - 9F7793570C73BD1500551F9C /* SimpleRegisterCoalescing.cpp */, - DE66ED9508ABEC2B00323D32 /* TwoAddressInstructionPass.cpp */, - DE66ED9608ABEC2B00323D32 /* UnreachableBlockElim.cpp */, - DE66ED9808ABEC2B00323D32 /* VirtRegMap.cpp */, - DE66ED9908ABEC2B00323D32 /* VirtRegMap.h */, - ); - name = lib/CodeGen; - path = ../lib/CodeGen; - sourceTree = SOURCE_ROOT; - }; - DE66ED8308ABEC2B00323D32 /* SelectionDAG */ = { - isa = PBXGroup; - children = ( - 9FE450AC0C77AB6E00C4FEA4 /* CallingConvLower.cpp */, - CF6B5AFD095C82C300D1EA42 /* DAGCombiner.cpp */, - DE66ED9008ABEC2B00323D32 /* LegalizeDAG.cpp */, - CF7FFA1F0985081C008B0087 /* ScheduleDAGList.cpp */, - DE694D9F08B51E0C0039C106 /* ScheduleDAG.cpp */, - DE66ED9208ABEC2B00323D32 /* SelectionDAG.cpp */, - DE66ED9308ABEC2B00323D32 /* SelectionDAGISel.cpp */, - DE66ED9408ABEC2B00323D32 /* SelectionDAGPrinter.cpp */, - CFE421060A66F86D00AB4BF6 /* ScheduleDAGRRList.cpp */, - CF9720370A9F3B1C002CEEDD /* TargetLowering.cpp */, - ); - path = SelectionDAG; - sourceTree = ""; - }; - DE66ED9A08ABEC7200323D32 /* lib/Debugger */ = { - isa = PBXGroup; - children = ( - DE66EDB108ABEC7300323D32 /* Debugger.cpp */, - DE66EDB508ABEC7300323D32 /* ProgramInfo.cpp */, - DE66EDB608ABEC7300323D32 /* README.txt */, - DE66EDB708ABEC7300323D32 /* RuntimeInfo.cpp */, - DE66EDB808ABEC7300323D32 /* SourceFile.cpp */, - DE66EDB908ABEC7300323D32 /* SourceLanguage-CFamily.cpp */, - DE66EDBA08ABEC7300323D32 /* SourceLanguage-CPlusPlus.cpp */, - DE66EDBB08ABEC7300323D32 /* SourceLanguage-Unknown.cpp */, - DE66EDBC08ABEC7300323D32 /* SourceLanguage.cpp */, - ); - name = lib/Debugger; - path = ../lib/Debugger; - sourceTree = SOURCE_ROOT; - }; - DE66EDBF08ABEC8F00323D32 /* lib/ExecutionEngine */ = { - isa = PBXGroup; - children = ( - DE66EDC508ABEC9000323D32 /* Interpreter */, - DE66EDD308ABEC9000323D32 /* JIT */, - DE66EDC408ABEC9000323D32 /* ExecutionEngine.cpp */, - 9F502B090D1D8D8D007939DF /* ExecutionEngineBindings.cpp */, - ); - name = lib/ExecutionEngine; - path = ../lib/ExecutionEngine; - sourceTree = SOURCE_ROOT; - }; - DE66EDC508ABEC9000323D32 /* Interpreter */ = { - isa = PBXGroup; - children = ( - DE66EDCE08ABEC9000323D32 /* Execution.cpp */, - DE66EDCF08ABEC9000323D32 /* ExternalFunctions.cpp */, - DE66EDD008ABEC9000323D32 /* Interpreter.cpp */, - DE66EDD108ABEC9000323D32 /* Interpreter.h */, - ); - path = Interpreter; - sourceTree = ""; - }; - DE66EDD308ABEC9000323D32 /* JIT */ = { - isa = PBXGroup; - children = ( - DE66EDDE08ABEC9100323D32 /* Intercept.cpp */, - DE66EDDF08ABEC9100323D32 /* JIT.cpp */, - DE66EDE008ABEC9100323D32 /* JIT.h */, - DE66EDE108ABEC9100323D32 /* JITEmitter.cpp */, - DE66EDE308ABEC9100323D32 /* TargetSelect.cpp */, - ); - path = JIT; - sourceTree = ""; - }; - DE66EDEB08ABEDD300323D32 /* lib/Linker */ = { - isa = PBXGroup; - children = ( - DE66EDF608ABEDD300323D32 /* LinkArchives.cpp */, - DE66EDF708ABEDD300323D32 /* Linker.cpp */, - DE66EDF808ABEDD300323D32 /* LinkItems.cpp */, - DE66EDF908ABEDD300323D32 /* LinkModules.cpp */, - ); - name = lib/Linker; - path = ../lib/Linker; - sourceTree = SOURCE_ROOT; - }; - DE66EDFB08ABEDE600323D32 /* lib/Support */ = { - isa = PBXGroup; - children = ( - 9FE25D950CAB1724005383FC /* APFloat.cpp */, - 9FE450A60C77AB3200C4FEA4 /* APInt.cpp */, - 9FE450A70C77AB3200C4FEA4 /* ConstantRange.cpp */, - 9FE450A80C77AB3200C4FEA4 /* MemoryBuffer.cpp */, - 9FE450A90C77AB3200C4FEA4 /* SmallPtrSet.cpp */, - 9FE450AA0C77AB3200C4FEA4 /* StringMap.cpp */, - CFD99AB70AFE848A0068D19C /* Allocator.cpp */, - DE66EDFC08ABEDE600323D32 /* Annotation.cpp */, - DE66EE1D08ABEDE600323D32 /* CommandLine.cpp */, - DE66EE3D08ABEDE600323D32 /* Debug.cpp */, - CF79495D09B326D4005ADFCA /* Dwarf.cpp */, - DE66EE3E08ABEDE600323D32 /* FileUtilities.cpp */, - CF42B6C40AF2512000D5D47C /* FoldingSet.cpp */, - CFE421070A66F8DC00AB4BF6 /* GraphWriter.cpp */, - DE66EE3F08ABEDE600323D32 /* IsInf.cpp */, - DE66EE4008ABEDE600323D32 /* IsNAN.cpp */, - CF8F1B500B64F86A00BB4199 /* ManagedStatic.cpp */, - DE66EE4208ABEDE600323D32 /* PluginLoader.cpp */, - DE66EE4308ABEDE600323D32 /* SlowOperationInformer.cpp */, - DE66EE4408ABEDE600323D32 /* Statistic.cpp */, - CF8F1B510B64F86A00BB4199 /* Streams.cpp */, - DE66EE4508ABEDE700323D32 /* StringExtras.cpp */, - 9F5B90CB0D0CE87100CDFDEA /* StringPool.cpp */, - DE66EE4608ABEDE700323D32 /* SystemUtils.cpp */, - DE66EE4708ABEDE700323D32 /* Timer.cpp */, - ); - name = lib/Support; - path = ../lib/Support; - sourceTree = SOURCE_ROOT; - }; - DE66EE4908ABEE3400323D32 /* lib/System */ = { - isa = PBXGroup; - children = ( - 9FE450A50C77AAF000C4FEA4 /* Disassembler.cpp */, - DE66EE7E08ABEE3500323D32 /* Unix */, - DE66EE8B08ABEE3500323D32 /* Win32 */, - CFE421090A66F93300AB4BF6 /* Alarm.cpp */, - DE66EE6008ABEE3400323D32 /* DynamicLibrary.cpp */, - CF8F1B530B64F8C000BB4199 /* IncludeFile.cpp */, - DE66EE6108ABEE3400323D32 /* LICENSE.TXT */, - CFD99ABA0AFE84D70068D19C /* IncludeFile.cpp */, - DE66EE6508ABEE3400323D32 /* MappedFile.cpp */, - DE66EE6608ABEE3400323D32 /* Memory.cpp */, - DE66EE6708ABEE3400323D32 /* Mutex.cpp */, - DE66EE6808ABEE3400323D32 /* Path.cpp */, - DE66EE6908ABEE3400323D32 /* Process.cpp */, - DE66EE6A08ABEE3400323D32 /* Program.cpp */, - DE66EE6B08ABEE3400323D32 /* README.txt */, - DE66EE7C08ABEE3400323D32 /* Signals.cpp */, - DE66EE7D08ABEE3400323D32 /* TimeValue.cpp */, - ); - name = lib/System; - path = ../lib/System; - sourceTree = SOURCE_ROOT; - }; - DE66EE7E08ABEE3500323D32 /* Unix */ = { - isa = PBXGroup; - children = ( - CFD99ABB0AFE84EF0068D19C /* Alarm.inc */, - DE66EE7F08ABEE3500323D32 /* MappedFile.inc */, - DE66EE8008ABEE3500323D32 /* Memory.inc */, - DE66EE8108ABEE3500323D32 /* Mutex.inc */, - DE66EE8208ABEE3500323D32 /* Path.inc */, - DE66EE8308ABEE3500323D32 /* Process.inc */, - DE66EE8408ABEE3500323D32 /* Program.inc */, - DE66EE8508ABEE3500323D32 /* README.txt */, - DE66EE8608ABEE3500323D32 /* Signals.inc */, - DE66EE8908ABEE3500323D32 /* TimeValue.inc */, - DE66EE8A08ABEE3500323D32 /* Unix.h */, - ); - path = Unix; - sourceTree = ""; - }; - DE66EE8B08ABEE3500323D32 /* Win32 */ = { - isa = PBXGroup; - children = ( - CFE4210A0A66F93300AB4BF6 /* Alarm.inc */, - DE66EE8C08ABEE3500323D32 /* DynamicLibrary.inc */, - DE66EE8D08ABEE3500323D32 /* MappedFile.inc */, - DE66EE8E08ABEE3500323D32 /* Memory.inc */, - DE66EE8F08ABEE3500323D32 /* Mutex.inc */, - DE66EE9008ABEE3500323D32 /* Path.inc */, - DE66EE9108ABEE3500323D32 /* Process.inc */, - DE66EE9208ABEE3500323D32 /* Program.inc */, - DE66EE9308ABEE3500323D32 /* Signals.inc */, - DE66EE9408ABEE3500323D32 /* TimeValue.inc */, - DE66EE9508ABEE3500323D32 /* Win32.h */, - ); - path = Win32; - sourceTree = ""; - }; - DE66EE9608ABEE5D00323D32 /* lib/Target */ = { - isa = PBXGroup; - children = ( - 9F7794290C73CB7900551F9C /* MSIL */, - DE66EE9708ABEE5D00323D32 /* Alpha */, - CF8F1BCF0B64FC8A00BB4199 /* ARM */, - DE66EEC908ABEE5E00323D32 /* CBackend */, - 9F7794120C73CB6100551F9C /* Mips */, - DE66EF1108ABEE5E00323D32 /* PowerPC */, - DE66EF7008ABEE5F00323D32 /* Sparc */, - DE66F09308ABEE6000323D32 /* X86 */, - DE66EF1008ABEE5E00323D32 /* TargetRegisterInfo.cpp */, - CF9BCD1508C75070001E7011 /* SubtargetFeature.cpp */, - 9FEDD6B60D8D83D0009F6DF1 /* Target.cpp */, - DE66F08A08ABEE6000323D32 /* Target.td */, - CF47BD860AAF487E00A8B13E /* TargetAsmInfo.cpp */, - 9FE25D960CAB1759005383FC /* TargetCallingConv.td */, - DE66F08B08ABEE6000323D32 /* TargetData.cpp */, - DE66F08C08ABEE6000323D32 /* TargetFrameInfo.cpp */, - DE66F08D08ABEE6000323D32 /* TargetInstrInfo.cpp */, - DE66F08F08ABEE6000323D32 /* TargetMachine.cpp */, - DE66F09008ABEE6000323D32 /* TargetMachineRegistry.cpp */, - 84115FFE0B66D87400E1293E /* TargetMachOWriterInfo.cpp */, - CF490D14090541D30072DB1C /* TargetSchedule.td */, - CF490D15090541D30072DB1C /* TargetSelectionDAG.td */, - DE66F09208ABEE6000323D32 /* TargetSubtarget.cpp */, - ); - name = lib/Target; - path = ../lib/Target; - sourceTree = SOURCE_ROOT; - }; - DE66EE9708ABEE5D00323D32 /* Alpha */ = { - isa = PBXGroup; - children = ( - DE66EE9808ABEE5E00323D32 /* Alpha.h */, - DE66EE9908ABEE5E00323D32 /* Alpha.td */, - DE66EE9A08ABEE5E00323D32 /* AlphaAsmPrinter.cpp */, - CF8F1B540B64F90F00BB4199 /* AlphaBranchSelector.cpp */, - DE66EE9B08ABEE5E00323D32 /* AlphaCodeEmitter.cpp */, - CFA702BB0A6FA85F0006009A /* AlphaGenAsmWriter.inc */, - CFA702BC0A6FA85F0006009A /* AlphaGenCodeEmitter.inc */, - CFA702BD0A6FA85F0006009A /* AlphaGenDAGISel.inc */, - CFA702BE0A6FA85F0006009A /* AlphaGenInstrInfo.inc */, - CFA702BF0A6FA85F0006009A /* AlphaGenInstrNames.inc */, - CFA702C00A6FA85F0006009A /* AlphaGenRegisterInfo.h.inc */, - CFA702C10A6FA85F0006009A /* AlphaGenRegisterInfo.inc */, - CFA702C20A6FA85F0006009A /* AlphaGenRegisterNames.inc */, - CFA702C30A6FA85F0006009A /* AlphaGenSubtarget.inc */, - DE66EEA308ABEE5E00323D32 /* AlphaInstrFormats.td */, - DE66EEA408ABEE5E00323D32 /* AlphaInstrInfo.cpp */, - DE66EEA508ABEE5E00323D32 /* AlphaInstrInfo.h */, - DE66EEA608ABEE5E00323D32 /* AlphaInstrInfo.td */, - CFBD8B1A090E76540020B107 /* AlphaISelDAGToDAG.cpp */, - CFBD8B1B090E76540020B107 /* AlphaISelLowering.cpp */, - CFBD8B1C090E76540020B107 /* AlphaISelLowering.h */, - DE66EEA908ABEE5E00323D32 /* AlphaJITInfo.cpp */, - DE66EEAA08ABEE5E00323D32 /* AlphaJITInfo.h */, - CF8F1B550B64F90F00BB4199 /* AlphaLLRP.cpp */, - DE66EEAB08ABEE5E00323D32 /* AlphaRegisterInfo.cpp */, - DE66EEAC08ABEE5E00323D32 /* AlphaRegisterInfo.h */, - DE66EEAD08ABEE5E00323D32 /* AlphaRegisterInfo.td */, - DE66EEAE08ABEE5E00323D32 /* AlphaRelocations.h */, - CFE4210B0A66F96400AB4BF6 /* AlphaSchedule.td */, - CFBD8B1D090E76540020B107 /* AlphaSubtarget.cpp */, - CFBD8B1E090E76540020B107 /* AlphaSubtarget.h */, - CF341DAE0AB07A8B0099B064 /* AlphaTargetAsmInfo.cpp */, - CF341DAD0AB07A8B0099B064 /* AlphaTargetAsmInfo.h */, - DE66EEAF08ABEE5E00323D32 /* AlphaTargetMachine.cpp */, - DE66EEB008ABEE5E00323D32 /* AlphaTargetMachine.h */, - ); - path = Alpha; - sourceTree = ""; - }; - DE66EEC908ABEE5E00323D32 /* CBackend */ = { - isa = PBXGroup; - children = ( - CF8F1B560B64F98900BB4199 /* CBackend.cpp */, - DE66EECA08ABEE5E00323D32 /* CTargetMachine.h */, - ); - path = CBackend; - sourceTree = ""; - }; - DE66EF1108ABEE5E00323D32 /* PowerPC */ = { - isa = PBXGroup; - children = ( - 9FE4509A0C77A79C00C4FEA4 /* PPCCallingConv.td */, - 9FE4509B0C77A79C00C4FEA4 /* PPCGenCallingConv.inc */, - 841160000B66D8AC00E1293E /* PPCMachOWriterInfo.h */, - 84115FFF0B66D89B00E1293E /* PPCMachOWriterInfo.cpp */, - CFA702CB0A6FA8AD0006009A /* PPCGenAsmWriter.inc */, - CFA702CC0A6FA8AD0006009A /* PPCGenCodeEmitter.inc */, - CFA702CD0A6FA8AD0006009A /* PPCGenDAGISel.inc */, - CFA702CE0A6FA8AD0006009A /* PPCGenInstrInfo.inc */, - CFA702CF0A6FA8AD0006009A /* PPCGenInstrNames.inc */, - CFA702D00A6FA8AD0006009A /* PPCGenRegisterInfo.h.inc */, - CFA702D10A6FA8AD0006009A /* PPCGenRegisterInfo.inc */, - CFA702D20A6FA8AD0006009A /* PPCGenRegisterNames.inc */, - CFA702D30A6FA8AD0006009A /* PPCGenSubtarget.inc */, - CFE421140A66FA2D00AB4BF6 /* PPC.h */, - CFE421150A66FA2D00AB4BF6 /* PPC.td */, - CFE421160A66FA2D00AB4BF6 /* PPCAsmPrinter.cpp */, - CFE421170A66FA2D00AB4BF6 /* PPCBranchSelector.cpp */, - CFE421180A66FA2D00AB4BF6 /* PPCCodeEmitter.cpp */, - CFE421190A66FA2D00AB4BF6 /* PPCFrameInfo.h */, - CFE4211A0A66FA2D00AB4BF6 /* PPCHazardRecognizers.cpp */, - CFE4211B0A66FA2D00AB4BF6 /* PPCHazardRecognizers.h */, - CFE4211C0A66FA2D00AB4BF6 /* PPCInstr64Bit.td */, - CFE4211D0A66FA2D00AB4BF6 /* PPCInstrAltivec.td */, - CFE4211E0A66FA2D00AB4BF6 /* PPCInstrBuilder.h */, - CFE4211F0A66FA2D00AB4BF6 /* PPCInstrFormats.td */, - CFE421200A66FA2D00AB4BF6 /* PPCInstrInfo.cpp */, - CFE421210A66FA2D00AB4BF6 /* PPCInstrInfo.h */, - CFE421220A66FA2D00AB4BF6 /* PPCInstrInfo.td */, - CFE421230A66FA2D00AB4BF6 /* PPCISelDAGToDAG.cpp */, - CFE421240A66FA2D00AB4BF6 /* PPCISelLowering.cpp */, - CFE421250A66FA2D00AB4BF6 /* PPCISelLowering.h */, - CFE421260A66FA2D00AB4BF6 /* PPCJITInfo.cpp */, - CFE421270A66FA2D00AB4BF6 /* PPCJITInfo.h */, - CFABD0A20B09E342003EB061 /* PPCMachineFunctionInfo.h */, - CFE421280A66FA2D00AB4BF6 /* PPCPerfectShuffle.h */, - CF8F1B570B64F9AC00BB4199 /* PPCPredicates.cpp */, - CF8F1B580B64F9AC00BB4199 /* PPCPredicates.h */, - CFE421290A66FA2D00AB4BF6 /* PPCRegisterInfo.cpp */, - CFE4212A0A66FA2D00AB4BF6 /* PPCRegisterInfo.h */, - CFE4212B0A66FA2D00AB4BF6 /* PPCRegisterInfo.td */, - CFE4212C0A66FA2D00AB4BF6 /* PPCRelocations.h */, - CFE4212D0A66FA2D00AB4BF6 /* PPCSchedule.td */, - CFE4212E0A66FA2D00AB4BF6 /* PPCScheduleG3.td */, - CFE4212F0A66FA2D00AB4BF6 /* PPCScheduleG4.td */, - CFE421300A66FA2D00AB4BF6 /* PPCScheduleG4Plus.td */, - CFE421310A66FA2D00AB4BF6 /* PPCScheduleG5.td */, - CFE421320A66FA2E00AB4BF6 /* PPCSubtarget.cpp */, - CFE421330A66FA2E00AB4BF6 /* PPCSubtarget.h */, - CF341E020AB080220099B064 /* PPCTargetAsmInfo.cpp */, - CF341E010AB080220099B064 /* PPCTargetAsmInfo.h */, - CFE421340A66FA2E00AB4BF6 /* PPCTargetMachine.cpp */, - CFE421350A66FA2E00AB4BF6 /* PPCTargetMachine.h */, - CFE421360A66FA2E00AB4BF6 /* README_ALTIVEC.txt */, - CFE421370A66FA2E00AB4BF6 /* README.txt */, - ); - path = PowerPC; - sourceTree = ""; - }; - DE66EF7008ABEE5F00323D32 /* Sparc */ = { - isa = PBXGroup; - children = ( - CF65280109D1BA3800C4B521 /* SparcGenAsmWriter.inc */, - CF65280209D1BA3800C4B521 /* SparcGenDAGISel.inc */, - CF65280309D1BA3800C4B521 /* SparcGenInstrInfo.inc */, - CF65280409D1BA3800C4B521 /* SparcGenInstrNames.inc */, - CF65280509D1BA3800C4B521 /* SparcGenRegisterInfo.h.inc */, - CF65280609D1BA3800C4B521 /* SparcGenRegisterInfo.inc */, - CF65280709D1BA3800C4B521 /* SparcGenRegisterNames.inc */, - CF65280809D1BA3800C4B521 /* SparcGenSubtarget.inc */, - CF6527FA09D1BA3800C4B521 /* DelaySlotFiller.cpp */, - CF6527FB09D1BA3800C4B521 /* FPMover.cpp */, - CF6527FC09D1BA3800C4B521 /* Makefile */, - CF6527FD09D1BA3800C4B521 /* README.txt */, - CF6527FE09D1BA3800C4B521 /* Sparc.h */, - CF6527FF09D1BA3800C4B521 /* Sparc.td */, - CF65280009D1BA3800C4B521 /* SparcAsmPrinter.cpp */, - CF65280909D1BA3800C4B521 /* SparcInstrFormats.td */, - CF65280A09D1BA3800C4B521 /* SparcInstrInfo.cpp */, - CF65280B09D1BA3800C4B521 /* SparcInstrInfo.h */, - CF65280C09D1BA3800C4B521 /* SparcInstrInfo.td */, - CF65280D09D1BA3800C4B521 /* SparcISelDAGToDAG.cpp */, - CF65280E09D1BA3800C4B521 /* SparcRegisterInfo.cpp */, - CF65280F09D1BA3800C4B521 /* SparcRegisterInfo.h */, - CF65281009D1BA3800C4B521 /* SparcRegisterInfo.td */, - CF65281109D1BA3800C4B521 /* SparcSubtarget.cpp */, - CF65281209D1BA3800C4B521 /* SparcSubtarget.h */, - CF341E230AB0814B0099B064 /* SparcTargetAsmInfo.cpp */, - CF341E220AB0814B0099B064 /* SparcTargetAsmInfo.h */, - CF65281309D1BA3800C4B521 /* SparcTargetMachine.cpp */, - CF65281409D1BA3800C4B521 /* SparcTargetMachine.h */, - ); - path = Sparc; - sourceTree = ""; - }; - DE66F09308ABEE6000323D32 /* X86 */ = { - isa = PBXGroup; - children = ( - 9FE4509C0C77A7BC00C4FEA4 /* README-MMX.txt */, - 9FE4509D0C77A7BC00C4FEA4 /* X86CallingConv.td */, - 9FE4509F0C77A7BC00C4FEA4 /* X86ELFWriterInfo.cpp */, - 9FE450A00C77A7BC00C4FEA4 /* X86ELFWriterInfo.h */, - 9FE450A10C77A7BC00C4FEA4 /* X86GenCallingConv.inc */, - 9FE450A20C77A7BC00C4FEA4 /* X86InstrFormats.td */, - CFA702D40A6FA8DD0006009A /* X86GenAsmWriter.inc */, - CFA702D50A6FA8DD0006009A /* X86GenAsmWriter1.inc */, - CFA702D60A6FA8DD0006009A /* X86GenDAGISel.inc */, - CFA702D70A6FA8DD0006009A /* X86GenInstrInfo.inc */, - CFA702D80A6FA8DD0006009A /* X86GenInstrNames.inc */, - CFA702D90A6FA8DD0006009A /* X86GenRegisterInfo.h.inc */, - CFA702DA0A6FA8DD0006009A /* X86GenRegisterInfo.inc */, - CFA702DB0A6FA8DD0006009A /* X86GenRegisterNames.inc */, - CFA702DC0A6FA8DD0006009A /* X86GenSubtarget.inc */, - CFE421380A66FA8000AB4BF6 /* README-FPStack.txt */, - CFE421390A66FA8000AB4BF6 /* README-SSE.txt */, - CFD99ABE0AFE857A0068D19C /* README-X86-64.txt */, - CFE4213A0A66FA8000AB4BF6 /* README.txt */, - CFF0DE6309BF6C360031957F /* X86InstrFPStack.td */, - CFF0DE6409BF6C360031957F /* X86InstrMMX.td */, - CFF0DE6509BF6C360031957F /* X86InstrSSE.td */, - DE66F0BC08ABEE6000323D32 /* X86.h */, - DE66F0BD08ABEE6000323D32 /* X86.td */, - DE66F0BE08ABEE6000323D32 /* X86AsmPrinter.cpp */, - DE66F0BF08ABEE6000323D32 /* X86AsmPrinter.h */, - DE66F0C008ABEE6000323D32 /* X86ATTAsmPrinter.cpp */, - DE66F0C108ABEE6000323D32 /* X86ATTAsmPrinter.h */, - DE66F0C208ABEE6000323D32 /* X86CodeEmitter.cpp */, - CF8F1B590B64F9E100BB4199 /* X86COFF.h */, - DE66F0C408ABEE6000323D32 /* X86FloatingPoint.cpp */, - DE66F0CC08ABEE6000323D32 /* X86InstrBuilder.h */, - DE66F0CD08ABEE6000323D32 /* X86InstrInfo.cpp */, - DE66F0CE08ABEE6000323D32 /* X86InstrInfo.h */, - DE66F0CF08ABEE6100323D32 /* X86InstrInfo.td */, - DE66F0D008ABEE6100323D32 /* X86IntelAsmPrinter.cpp */, - DE66F0D108ABEE6100323D32 /* X86IntelAsmPrinter.h */, - DE66F0D508ABEE6100323D32 /* X86JITInfo.cpp */, - DE66F0D608ABEE6100323D32 /* X86JITInfo.h */, - CFE4213B0A66FA8000AB4BF6 /* X86MachineFunctionInfo.h */, - DE66F0D808ABEE6100323D32 /* X86RegisterInfo.cpp */, - DE66F0D908ABEE6100323D32 /* X86RegisterInfo.h */, - DE66F0DA08ABEE6100323D32 /* X86RegisterInfo.td */, - DE66F0DB08ABEE6100323D32 /* X86Relocations.h */, - CFC244BB0959F24C009F8C47 /* X86ISelDAGToDAG.cpp */, - CFC244BC0959F24C009F8C47 /* X86ISelLowering.cpp */, - CFC244BD0959F24C009F8C47 /* X86ISelLowering.h */, - DE66F0DC08ABEE6100323D32 /* X86Subtarget.cpp */, - DE66F0DD08ABEE6100323D32 /* X86Subtarget.h */, - CF341E330AB082D60099B064 /* X86TargetAsmInfo.cpp */, - CF341E320AB082D60099B064 /* X86TargetAsmInfo.h */, - DE66F0DE08ABEE6100323D32 /* X86TargetMachine.cpp */, - DE66F0DF08ABEE6100323D32 /* X86TargetMachine.h */, - ); - path = X86; - sourceTree = ""; - }; - DE66F0E108ABEFB300323D32 /* lib/Transforms */ = { - isa = PBXGroup; - children = ( - DE66F0EE08ABEFB300323D32 /* Instrumentation */, - CFE4213C0A66FAE100AB4BF6 /* Hello */, - DE66F11F08ABEFB300323D32 /* IPO */, - DE66F15C08ABEFB400323D32 /* Scalar */, - DE66F1BD08ABEFB400323D32 /* Utils */, - ); - name = lib/Transforms; - path = ../lib/Transforms; - sourceTree = SOURCE_ROOT; - }; - DE66F0EE08ABEFB300323D32 /* Instrumentation */ = { - isa = PBXGroup; - children = ( - DE66F0EF08ABEFB300323D32 /* BlockProfiling.cpp */, - DE66F0FE08ABEFB300323D32 /* EdgeProfiling.cpp */, - DE66F11B08ABEFB300323D32 /* ProfilingUtils.cpp */, - DE66F11C08ABEFB300323D32 /* ProfilingUtils.h */, - CF73C0B7098A546000627152 /* RSProfiling.cpp */, - CF73C0B8098A546000627152 /* RSProfiling.h */, - ); - path = Instrumentation; - sourceTree = ""; - }; - DE66F11F08ABEFB300323D32 /* IPO */ = { - isa = PBXGroup; - children = ( - 9F7793770C73C48A00551F9C /* StripDeadPrototypes.cpp */, - DE66F12008ABEFB300323D32 /* ArgumentPromotion.cpp */, - DE66F12108ABEFB300323D32 /* ConstantMerge.cpp */, - DE66F12208ABEFB300323D32 /* DeadArgumentElimination.cpp */, - DE66F12308ABEFB300323D32 /* DeadTypeElimination.cpp */, - DE66F14C08ABEFB400323D32 /* GlobalDCE.cpp */, - DE66F14D08ABEFB400323D32 /* GlobalOpt.cpp */, - CFE4213F0A66FB5E00AB4BF6 /* IndMemRemoval.cpp */, - DE66F14E08ABEFB400323D32 /* Inliner.cpp */, - DE66F15008ABEFB400323D32 /* InlineSimple.cpp */, - DE66F15108ABEFB400323D32 /* Internalize.cpp */, - DE66F15208ABEFB400323D32 /* IPConstantPropagation.cpp */, - DE66F15308ABEFB400323D32 /* LoopExtractor.cpp */, - DE66F15408ABEFB400323D32 /* LowerSetJmp.cpp */, - DE66F15608ABEFB400323D32 /* PruneEH.cpp */, - DE66F15708ABEFB400323D32 /* RaiseAllocations.cpp */, - DE66F15808ABEFB400323D32 /* SimplifyLibCalls.cpp */, - DE66F15908ABEFB400323D32 /* StripSymbols.cpp */, - ); - path = IPO; - sourceTree = ""; - }; - DE66F15C08ABEFB400323D32 /* Scalar */ = { - isa = PBXGroup; - children = ( - DE66F15E08ABEFB400323D32 /* ADCE.cpp */, - DE66F15F08ABEFB400323D32 /* BasicBlockPlacement.cpp */, - 9F7793460C73BC2000551F9C /* CodeGenPrepare.cpp */, - DE66F16008ABEFB400323D32 /* CondPropagate.cpp */, - DE66F16108ABEFB400323D32 /* ConstantProp.cpp */, - DE66F16308ABEFB400323D32 /* DCE.cpp */, - DE66F16408ABEFB400323D32 /* DeadStoreElimination.cpp */, - DE66F1A308ABEFB400323D32 /* GCSE.cpp */, - 9F7793470C73BC2000551F9C /* GVN.cpp */, - 9F7793480C73BC2000551F9C /* GVNPRE.cpp */, - DE66F1A408ABEFB400323D32 /* IndVarSimplify.cpp */, - DE66F1A508ABEFB400323D32 /* InstructionCombining.cpp */, - DE66F1A608ABEFB400323D32 /* LICM.cpp */, - 9F77934A0C73BC2000551F9C /* LoopRotation.cpp */, - 9F7793490C73BC2000551F9C /* LoopIndexSplit.cpp */, - DE66F1A808ABEFB400323D32 /* LoopStrengthReduce.cpp */, - DE66F1A908ABEFB400323D32 /* LoopUnroll.cpp */, - DE66F1AA08ABEFB400323D32 /* LoopUnswitch.cpp */, - CF8F1B5B0B64FA2F00BB4199 /* PredicateSimplifier.cpp */, - DE66F1B508ABEFB400323D32 /* Reassociate.cpp */, - CF73C0B9098A546000627152 /* Reg2Mem.cpp */, - 9FEDD5F70D8D797D009F6DF1 /* Scalar.cpp */, - DE66F1B608ABEFB400323D32 /* ScalarReplAggregates.cpp */, - DE66F1B708ABEFB400323D32 /* SCCP.cpp */, - DE66F1B808ABEFB400323D32 /* SimplifyCFG.cpp */, - DE66F1B908ABEFB400323D32 /* TailDuplication.cpp */, - DE66F1BA08ABEFB400323D32 /* TailRecursionElimination.cpp */, - ); - path = Scalar; - sourceTree = ""; - }; - DE66F1BD08ABEFB400323D32 /* Utils */ = { - isa = PBXGroup; - children = ( - DE66F1BE08ABEFB400323D32 /* BasicBlockUtils.cpp */, - 9F7793780C73C49A00551F9C /* BasicInliner.cpp */, - DE66F1BF08ABEFB400323D32 /* BreakCriticalEdges.cpp */, - DE66F1C008ABEFB400323D32 /* CloneFunction.cpp */, - 9F7793790C73C49A00551F9C /* CloneLoop.cpp */, - DE66F1C108ABEFB400323D32 /* CloneModule.cpp */, - DE66F1C208ABEFB400323D32 /* CloneTrace.cpp */, - DE66F1C308ABEFB400323D32 /* CodeExtractor.cpp */, - DE66F1E008ABEFB400323D32 /* DemoteRegToStack.cpp */, - 9F77937A0C73C49A00551F9C /* InlineCost.cpp */, - DE66F1E108ABEFB400323D32 /* InlineFunction.cpp */, - CF97208A0A9F3C6F002CEEDD /* LCSSA.cpp */, - DE66F1E208ABEFB400323D32 /* Local.cpp */, - DE4DA0390911476D0012D44B /* LoopSimplify.cpp */, - CF97208B0A9F3C6F002CEEDD /* LowerAllocations.cpp */, - CF97208C0A9F3C6F002CEEDD /* LowerInvoke.cpp */, - CF97208E0A9F3C6F002CEEDD /* LowerSwitch.cpp */, - CF97208F0A9F3C6F002CEEDD /* Mem2Reg.cpp */, - DE66F1E408ABEFB400323D32 /* PromoteMemoryToRegister.cpp */, - DE66F1E508ABEFB400323D32 /* SimplifyCFG.cpp */, - DE66F1E608ABEFB400323D32 /* UnifyFunctionExitNodes.cpp */, - DE66F1E708ABEFB400323D32 /* ValueMapper.cpp */, - ); - path = Utils; - sourceTree = ""; - }; - DE66F1E908ABF03100323D32 /* include/llvm */ = { - isa = PBXGroup; - children = ( - DE66F1EB08ABF03100323D32 /* ADT */, - DE66F20308ABF03100323D32 /* Analysis */, - DE66F22408ABF03100323D32 /* Assembly */, - 9F77937F0C73C54C00551F9C /* Bitcode */, - DE66F23508ABF03100323D32 /* CodeGen */, - DE66F24C08ABF03100323D32 /* Config */, - DE66F25308ABF03100323D32 /* Debugger */, - DE66F25B08ABF03100323D32 /* ExecutionEngine */, - DE66F26E08ABF03200323D32 /* Support */, - DE66F29408ABF03200323D32 /* System */, - DE66F29F08ABF03200323D32 /* Target */, - DE66F2AB08ABF03200323D32 /* Transforms */, - DE66F1EA08ABF03100323D32 /* AbstractTypeUser.h */, - DE66F22308ABF03100323D32 /* Argument.h */, - 9FA638D90C77B184007F12AE /* AutoUpgrade.h */, - DE66F22A08ABF03100323D32 /* BasicBlock.h */, - DE66F23308ABF03100323D32 /* CallGraphSCCPass.h */, - DE66F23408ABF03100323D32 /* CallingConv.h */, - DE66F25108ABF03100323D32 /* Constant.h */, - DE66F25208ABF03100323D32 /* Constants.h */, - DE66F25A08ABF03100323D32 /* DerivedTypes.h */, - DE66F25E08ABF03100323D32 /* Function.h */, - 9FA638DA0C77B184007F12AE /* GlobalAlias.h */, - DE66F25F08ABF03100323D32 /* GlobalValue.h */, - DE66F26008ABF03100323D32 /* GlobalVariable.h */, - CF73C0A2098A4FDF00627152 /* InlineAsm.h */, - DE66F26108ABF03100323D32 /* InstrTypes.h */, - DE66F26208ABF03100323D32 /* Instruction.def */, - DE66F26308ABF03100323D32 /* Instruction.h */, - DE66F26408ABF03100323D32 /* Instructions.h */, - DE66F26508ABF03100323D32 /* IntrinsicInst.h */, - DE66F26608ABF03100323D32 /* Intrinsics.h */, - CF65223409CA39B800C4B521 /* Intrinsics.gen */, - CFE420FF0A66F67300AB4BF6 /* IntrinsicsPowerPC.td */, - CFE421000A66F67300AB4BF6 /* IntrinsicsX86.td */, - CF8D62FA09C2226F006017BA /* Intrinsics.td */, - CF9720260A9F39B9002CEEDD /* LinkAllPasses.h */, - CFE421010A66F67300AB4BF6 /* LinkAllVMCore.h */, - CF9720270A9F39B9002CEEDD /* LinkTimeOptimizer.h */, - DE66F26708ABF03100323D32 /* Linker.h */, - DE66F26808ABF03100323D32 /* Module.h */, - DE66F26908ABF03200323D32 /* ModuleProvider.h */, - 9F77937E0C73C53000551F9C /* ParameterAttributes.h */, - DE66F26A08ABF03200323D32 /* Pass.h */, - DE66F26B08ABF03200323D32 /* PassAnalysisSupport.h */, - DE66F26C08ABF03200323D32 /* PassManager.h */, - CF8F1B420B64F70B00BB4199 /* PassManagers.h */, - DE66F26D08ABF03200323D32 /* PassSupport.h */, - DE66F29308ABF03200323D32 /* SymbolTableListTraits.h */, - DE66F2B708ABF03200323D32 /* Type.h */, - CF73C0A3098A4FDF00627152 /* TypeSymbolTable.h */, - DE66F2B808ABF03200323D32 /* Use.h */, - DE66F2B908ABF03200323D32 /* User.h */, - DE66F2BA08ABF03200323D32 /* Value.h */, - CF73C0A4098A4FDF00627152 /* ValueSymbolTable.h */, - ); - name = include/llvm; - path = ../include/llvm; - sourceTree = SOURCE_ROOT; - }; - DE66F1EB08ABF03100323D32 /* ADT */ = { - isa = PBXGroup; - children = ( - 35E98A830CBC2ED300C5CDC1 /* DenseSet.h */, - 35E98A840CBC2ED300C5CDC1 /* ImmutableMap.h */, - 35E98A850CBC2ED300C5CDC1 /* ImmutableSet.h */, - 9FA638DD0C77B1AB007F12AE /* BitVector.h */, - DE66F1EE08ABF03100323D32 /* DenseMap.h */, - DE66F1EF08ABF03100323D32 /* DepthFirstIterator.h */, - DE66F1F008ABF03100323D32 /* EquivalenceClasses.h */, - CF42B6BF0AF24F5300D5D47C /* FoldingSet.h */, - CF42B6BF0AF24F5300D5D47C /* FoldingSet.h */, - DE66F1F108ABF03100323D32 /* GraphTraits.h */, - DE66F1F308ABF03100323D32 /* hash_map.in */, - DE66F1F508ABF03100323D32 /* hash_set.in */, - DE66F1F608ABF03100323D32 /* HashExtras.h */, - DE66F1F708ABF03100323D32 /* ilist */, - 9FA638E00C77B1AB007F12AE /* IndexedMap.h */, - 9FE25D900CAB166D005383FC /* APFloat.h */, - 9FA638DB0C77B1AB007F12AE /* APInt.h */, - 9FA638DC0C77B1AB007F12AE /* APSInt.h */, - DE66F1F908ABF03100323D32 /* iterator.in */, - DE66F1FA08ABF03100323D32 /* PostOrderIterator.h */, - DE66F1FB08ABF03100323D32 /* SCCIterator.h */, - DE66F1FC08ABF03100323D32 /* SetOperations.h */, - DE66F1FD08ABF03100323D32 /* SetVector.h */, - 9FA638E20C77B1AB007F12AE /* SmallPtrSet.h */, - 9FA638E30C77B1AB007F12AE /* SmallSet.h */, - CF33BE160AF62B4200E93805 /* SmallString.h */, - CF71B60F0AC45EDA0007F57C /* SmallVector.h */, - 9FE25D910CAB166D005383FC /* SparseBitVector.h */, - 9FA638E40C77B1AB007F12AE /* StringMap.h */, - DE66F1FE08ABF03100323D32 /* Statistic.h */, - DE66F1FF08ABF03100323D32 /* STLExtras.h */, - DE66F20008ABF03100323D32 /* StringExtras.h */, - DE66F20108ABF03100323D32 /* Tree.h */, - CFF8B434097C605F0047F72A /* UniqueVector.h */, - DE66F20208ABF03100323D32 /* VectorExtras.h */, - ); - path = ADT; - sourceTree = ""; - }; - DE66F20308ABF03100323D32 /* Analysis */ = { - isa = PBXGroup; - children = ( - 9FA638E50C77B203007F12AE /* LoopPass.h */, - 9FA638E60C77B203007F12AE /* MemoryDependenceAnalysis.h */, - DE66F20408ABF03100323D32 /* AliasAnalysis.h */, - DE66F20508ABF03100323D32 /* AliasSetTracker.h */, - DE66F20608ABF03100323D32 /* CallGraph.h */, - DE66F20708ABF03100323D32 /* CFGPrinter.h */, - CF73C0A5098A507300627152 /* ConstantFolding.h */, - DE66F20808ABF03100323D32 /* ConstantsScanner.h */, - DE66F20F08ABF03100323D32 /* Dominators.h */, - DE66F21208ABF03100323D32 /* FindUsedTypes.h */, - DE66F21308ABF03100323D32 /* Interval.h */, - DE66F21408ABF03100323D32 /* IntervalIterator.h */, - DE66F21508ABF03100323D32 /* IntervalPartition.h */, - DE66F21608ABF03100323D32 /* LoadValueNumbering.h */, - DE66F21708ABF03100323D32 /* LoopInfo.h */, - DE66F21808ABF03100323D32 /* Passes.h */, - DE66F21908ABF03100323D32 /* PostDominators.h */, - DE66F21A08ABF03100323D32 /* ProfileInfo.h */, - DE66F21B08ABF03100323D32 /* ProfileInfoLoader.h */, - DE66F21C08ABF03100323D32 /* ProfileInfoTypes.h */, - DE66F21D08ABF03100323D32 /* ScalarEvolution.h */, - DE66F21E08ABF03100323D32 /* ScalarEvolutionExpander.h */, - DE66F21F08ABF03100323D32 /* ScalarEvolutionExpressions.h */, - DE66F22008ABF03100323D32 /* Trace.h */, - DE66F22108ABF03100323D32 /* ValueNumbering.h */, - DE66F22208ABF03100323D32 /* Verifier.h */, - ); - path = Analysis; - sourceTree = ""; - }; - DE66F22408ABF03100323D32 /* Assembly */ = { - isa = PBXGroup; - children = ( - DE66F22508ABF03100323D32 /* AsmAnnotationWriter.h */, - DE66F22708ABF03100323D32 /* Parser.h */, - DE66F22808ABF03100323D32 /* PrintModulePass.h */, - DE66F22908ABF03100323D32 /* Writer.h */, - ); - path = Assembly; - sourceTree = ""; - }; - DE66F23508ABF03100323D32 /* CodeGen */ = { - isa = PBXGroup; - children = ( - DE66F23608ABF03100323D32 /* AsmPrinter.h */, - 9F7793860C73C57100551F9C /* CallingConvLower.h */, - DEFAB19D0959E9A100E0AB42 /* DwarfWriter.h */, - 9F7793870C73C57100551F9C /* ELFRelocation.h */, - 9F7793880C73C57100551F9C /* FileWriters.h */, - DE66F23908ABF03100323D32 /* IntrinsicLowering.h */, - CFD7E4F30A798FC3000C7379 /* LinkAllCodegenComponents.h */, - DE4DA03C091147920012D44B /* LiveInterval.h */, - DE4DA03D091147920012D44B /* LiveIntervalAnalysis.h */, - DE66F23A08ABF03100323D32 /* LiveVariables.h */, - DE66F23B08ABF03100323D32 /* MachineBasicBlock.h */, - DE66F23C08ABF03100323D32 /* MachineCodeEmitter.h */, - DE66F23D08ABF03100323D32 /* MachineConstantPool.h */, - CF6F487109505E1500BC9E82 /* MachineModuleInfo.h */, - DE66F23E08ABF03100323D32 /* MachineFrameInfo.h */, - DE66F23F08ABF03100323D32 /* MachineFunction.h */, - DE66F24008ABF03100323D32 /* MachineFunctionPass.h */, - DE66F24108ABF03100323D32 /* MachineInstr.h */, - DE66F24208ABF03100323D32 /* MachineInstrBuilder.h */, - CFE420FB0A66F67300AB4BF6 /* MachineJumpTableInfo.h */, - CF6527D909D1A53400C4B521 /* MachineLocation.h */, - CF4F27E60A7B6E23004359F6 /* MachinePassRegistry.h */, - DE66F24308ABF03100323D32 /* MachineRelocation.h */, - 9F7793890C73C57100551F9C /* MachORelocation.h */, - DE66F24408ABF03100323D32 /* Passes.h */, - CFE21C780A80CC0600D3E908 /* RegAllocRegistry.h */, - 9FE25D920CAB169F005383FC /* RegisterCoalescer.h */, - 9F77938A0C73C57100551F9C /* RegisterScavenging.h */, - CF8F1B410B64F6D100BB4199 /* RuntimeLibcalls.h */, - DE66F24508ABF03100323D32 /* SchedGraphCommon.h */, - CF7FFA2109850864008B0087 /* ScheduleDAG.h */, - CFE21C7B0A80CC1C00D3E908 /* SchedulerRegistry.h */, - DE66F24608ABF03100323D32 /* SelectionDAG.h */, - DE66F24708ABF03100323D32 /* SelectionDAGISel.h */, - DE66F24808ABF03100323D32 /* SelectionDAGNodes.h */, - DE66F24B08ABF03100323D32 /* ValueTypes.h */, - CFE420FC0A66F67300AB4BF6 /* ValueTypes.td */, - ); - path = CodeGen; - sourceTree = ""; - }; - DE66F24C08ABF03100323D32 /* Config */ = { - isa = PBXGroup; - children = ( - DE66F24E08ABF03100323D32 /* alloca.h */, - CF73C0A9098A50FD00627152 /* config.h */, - DE66F25008ABF03100323D32 /* config.h.in */, - ); - path = Config; - sourceTree = ""; - }; - DE66F25308ABF03100323D32 /* Debugger */ = { - isa = PBXGroup; - children = ( - DE66F25408ABF03100323D32 /* Debugger.h */, - DE66F25508ABF03100323D32 /* InferiorProcess.h */, - DE66F25608ABF03100323D32 /* ProgramInfo.h */, - DE66F25708ABF03100323D32 /* RuntimeInfo.h */, - DE66F25808ABF03100323D32 /* SourceFile.h */, - DE66F25908ABF03100323D32 /* SourceLanguage.h */, - ); - path = Debugger; - sourceTree = ""; - }; - DE66F25B08ABF03100323D32 /* ExecutionEngine */ = { - isa = PBXGroup; - children = ( - DE66F25C08ABF03100323D32 /* ExecutionEngine.h */, - DE66F25D08ABF03100323D32 /* GenericValue.h */, - CFE420FD0A66F67300AB4BF6 /* Interpreter.h */, - CFE420FE0A66F67300AB4BF6 /* JIT.h */, - ); - path = ExecutionEngine; - sourceTree = ""; - }; - DE66F26E08ABF03200323D32 /* Support */ = { - isa = PBXGroup; - children = ( - F27C8CE90DAD2EF900A33844 /* IRBuilder.h */, - DE66F27008ABF03200323D32 /* AIXDataTypesFix.h */, - 9F5B90CE0D0CE89300CDFDEA /* AlignOf.h */, - CF8F1B430B64F74400BB4199 /* Allocator.h */, - DE66F27108ABF03200323D32 /* Annotation.h */, - DE66F27208ABF03200323D32 /* CallSite.h */, - DE66F27308ABF03200323D32 /* Casting.h */, - DE66F27408ABF03200323D32 /* CFG.h */, - DE66F27508ABF03200323D32 /* CommandLine.h */, - CF8F1B440B64F74400BB4199 /* Compiler.h */, - DE66F27708ABF03200323D32 /* ConstantRange.h */, - CF73C0AD098A519400627152 /* DataTypes.h */, - DE66F27908ABF03200323D32 /* DataTypes.h.in */, - DE66F27A08ABF03200323D32 /* Debug.h */, - DE66F27B08ABF03200323D32 /* DOTGraphTraits.h */, - DE66F27C08ABF03200323D32 /* DynamicLinker.h */, - DE66F27D08ABF03200323D32 /* ELF.h */, - CF8E00490989162500DA2399 /* Dwarf.h */, - DE66F27E08ABF03200323D32 /* FileUtilities.h */, - DE66F27F08ABF03200323D32 /* GetElementPtrTypeIterator.h */, - DE66F28008ABF03200323D32 /* GraphWriter.h */, - DE66F28108ABF03200323D32 /* InstIterator.h */, - DE66F28208ABF03200323D32 /* InstVisitor.h */, - DE66F28308ABF03200323D32 /* LeakDetector.h */, - CF8F1B460B64F74400BB4199 /* ManagedStatic.h */, - DE66F28408ABF03200323D32 /* Mangler.h */, - DE66F28508ABF03200323D32 /* MathExtras.h */, - 9F7794880C73D51000551F9C /* MemoryBuffer.h */, - DE66F28608ABF03200323D32 /* MutexGuard.h */, - CF8F1B470B64F74400BB4199 /* OutputBuffer.h */, - DE66F28708ABF03200323D32 /* PassNameParser.h */, - DE66F28808ABF03200323D32 /* PatternMatch.h */, - DE66F28908ABF03200323D32 /* PluginLoader.h */, - 9F5B90CF0D0CE89300CDFDEA /* Registry.h */, - DE66F28A08ABF03200323D32 /* SlowOperationInformer.h */, - DE66F28B08ABF03200323D32 /* StableBasicBlockNumbering.h */, - 9F7794890C73D51000551F9C /* Streams.h */, - 9F5B90D00D0CE89300CDFDEA /* StringPool.h */, - DE66F28C08ABF03200323D32 /* SystemUtils.h */, - DE66F28E08ABF03200323D32 /* Timer.h */, - DE66F29008ABF03200323D32 /* type_traits.h */, - ); - path = Support; - sourceTree = ""; - }; - DE66F29408ABF03200323D32 /* System */ = { - isa = PBXGroup; - children = ( - CF73C0AE098A51AD00627152 /* Alarm.h */, - 9FA638E70C77B222007F12AE /* Disassembler.h */, - DE66F29508ABF03200323D32 /* DynamicLibrary.h */, - CF9720340A9F3A41002CEEDD /* IncludeFile.h */, - DE66F29608ABF03200323D32 /* LICENSE.TXT */, - DE66F29708ABF03200323D32 /* MappedFile.h */, - DE66F29808ABF03200323D32 /* Memory.h */, - DE66F29908ABF03200323D32 /* Mutex.h */, - DE66F29A08ABF03200323D32 /* Path.h */, - DE66F29B08ABF03200323D32 /* Process.h */, - DE66F29C08ABF03200323D32 /* Program.h */, - DE66F29D08ABF03200323D32 /* Signals.h */, - DE66F29E08ABF03200323D32 /* TimeValue.h */, - ); - path = System; - sourceTree = ""; - }; - DE66F29F08ABF03200323D32 /* Target */ = { - isa = PBXGroup; - children = ( - DE66F2A008ABF03200323D32 /* TargetRegisterInfo.h */, - CF9BCD0808C74DE0001E7011 /* SubtargetFeature.h */, - CF47BD380AAF40BC00A8B13E /* TargetAsmInfo.h */, - DE66F2A108ABF03200323D32 /* TargetData.h */, - 9FA638E80C77B231007F12AE /* TargetELFWriterInfo.h */, - DE66F2A208ABF03200323D32 /* TargetFrameInfo.h */, - DE66F2A308ABF03200323D32 /* TargetInstrInfo.h */, - CF26835B09178F5500C5F253 /* TargetInstrItineraries.h */, - DE66F2A408ABF03200323D32 /* TargetJITInfo.h */, - DE66F2A508ABF03200323D32 /* TargetLowering.h */, - DE66F2A608ABF03200323D32 /* TargetMachine.h */, - DE66F2A708ABF03200323D32 /* TargetMachineRegistry.h */, - 8443EF210B66B62D00959964 /* TargetMachOWriterInfo.h */, - DE66F2A808ABF03200323D32 /* TargetOptions.h */, - DE66F2AA08ABF03200323D32 /* TargetSubtarget.h */, - ); - path = Target; - sourceTree = ""; - }; - DE66F2AB08ABF03200323D32 /* Transforms */ = { - isa = PBXGroup; - children = ( - DE66F2AC08ABF03200323D32 /* Instrumentation.h */, - 9FA638E90C77B252007F12AE /* IPO */, - DE66F2AD08ABF03200323D32 /* IPO.h */, - CF73C0AF098A51DD00627152 /* RSProfiling.h */, - DE66F2AF08ABF03200323D32 /* Scalar.h */, - DE66F2B008ABF03200323D32 /* Utils */, - ); - path = Transforms; - sourceTree = ""; - }; - DE66F2B008ABF03200323D32 /* Utils */ = { - isa = PBXGroup; - children = ( - DE66F2B108ABF03200323D32 /* BasicBlockUtils.h */, - 9FA638EB0C77B26B007F12AE /* BasicInliner.h */, - DE66F2B208ABF03200323D32 /* Cloning.h */, - DE66F2B308ABF03200323D32 /* FunctionUtils.h */, - 9FA638EC0C77B26B007F12AE /* InlineCost.h */, - DE66F2B408ABF03200323D32 /* Local.h */, - DE66F2B508ABF03200323D32 /* PromoteMemToReg.h */, - DE66F2B608ABF03200323D32 /* UnifyFunctionExitNodes.h */, - ); - path = Utils; - sourceTree = ""; - }; - DE66F2BD08ABF14400323D32 /* tools */ = { - isa = PBXGroup; - children = ( - CFD99ADF0AFE878F0068D19C /* opt */, - DE66F2CB08ABF14400323D32 /* bugpoint */, - DE66F2F008ABF14400323D32 /* gccld */, - DE66F31E08ABF14400323D32 /* llvm-db */, - DE66F33B08ABF14400323D32 /* llvm-ld */, - DE66F36808ABF14500323D32 /* llvmc */, - CF8F1B5E0B64FADA00BB4199 /* llvm-upgrade */, - CF8F1B7E0B64FADA00BB4199 /* llvm2cpp */, - CFD99ADA0AFE87650068D19C /* lto.cpp */, - DE66F30008ABF14400323D32 /* llc.cpp */, - DE66F30708ABF14400323D32 /* lli.cpp */, - DE66F30E08ABF14400323D32 /* llvm-ar.cpp */, - DE66F31508ABF14400323D32 /* llvm-as.cpp */, - DE66F31C08ABF14400323D32 /* llvm-bcanalyzer.cpp */, - DE66F33208ABF14400323D32 /* llvm-dis.cpp */, - DE66F33908ABF14400323D32 /* llvm-extract.cpp */, - DE66F34A08ABF14400323D32 /* llvm-link.cpp */, - DE66F35108ABF14400323D32 /* llvm-nm.cpp */, - DE66F35808ABF14500323D32 /* llvm-prof.cpp */, - DE66F35F08ABF14500323D32 /* llvm-ranlib.cpp */, - CF8F1B960B64FB7F00BB4199 /* lto */, - CF8F1BAB0B64FB8000BB4199 /* opt */, - ); - name = tools; - path = ../tools; - sourceTree = SOURCE_ROOT; - }; - DE66F2CB08ABF14400323D32 /* bugpoint */ = { - isa = PBXGroup; - children = ( - DE66F2CC08ABF14400323D32 /* BugDriver.cpp */, - DE66F2CD08ABF14400323D32 /* BugDriver.h */, - DE66F2CE08ABF14400323D32 /* bugpoint.cpp */, - DE66F2CF08ABF14400323D32 /* CrashDebugger.cpp */, - DE66F2E208ABF14400323D32 /* ExecutionDriver.cpp */, - DE66F2E308ABF14400323D32 /* ExtractFunction.cpp */, - CF9720910A9F3CC7002CEEDD /* FindBugs.cpp */, - DE66F2E408ABF14400323D32 /* ListReducer.h */, - DE66F2E608ABF14400323D32 /* Miscompilation.cpp */, - DE66F2E708ABF14400323D32 /* OptimizerDriver.cpp */, - DE66F2E808ABF14400323D32 /* TestPasses.cpp */, - CF9720920A9F3CC7002CEEDD /* ToolRunner.cpp */, - CF9720930A9F3CC7002CEEDD /* ToolRunner.h */, - ); - path = bugpoint; - sourceTree = ""; - }; - DE66F2F008ABF14400323D32 /* gccld */ = { - isa = PBXGroup; - children = ( - ); - path = gccld; - sourceTree = ""; - }; - DE66F31E08ABF14400323D32 /* llvm-db */ = { - isa = PBXGroup; - children = ( - DE66F31F08ABF14400323D32 /* CLICommand.h */, - DE66F32008ABF14400323D32 /* CLIDebugger.cpp */, - DE66F32108ABF14400323D32 /* CLIDebugger.h */, - DE66F32208ABF14400323D32 /* Commands.cpp */, - DE66F32B08ABF14400323D32 /* llvm-db.cpp */, - ); - path = "llvm-db"; - sourceTree = ""; - }; - DE66F33B08ABF14400323D32 /* llvm-ld */ = { - isa = PBXGroup; - children = ( - DE66F34208ABF14400323D32 /* llvm-ld.cpp */, - DE66F34408ABF14400323D32 /* Optimize.cpp */, - ); - path = "llvm-ld"; - sourceTree = ""; - }; - DE66F36808ABF14500323D32 /* llvmc */ = { - isa = PBXGroup; - children = ( - DE66F36908ABF14500323D32 /* c */, - DE66F36A08ABF14500323D32 /* CompilerDriver.cpp */, - DE66F36B08ABF14500323D32 /* CompilerDriver.h */, - CF8F1B950B64FB5000BB4199 /* ConfigLexer.cpp */, - DE66F36D08ABF14500323D32 /* ConfigLexer.h */, - DE66F36E08ABF14500323D32 /* ConfigLexer.l */, - DE66F36F08ABF14500323D32 /* Configuration.cpp */, - DE66F37008ABF14500323D32 /* Configuration.h */, - DE66F37108ABF14500323D32 /* cpp */, - DE66F37D08ABF14500323D32 /* ll */, - DE66F37E08ABF14500323D32 /* llvmc.cpp */, - ); - path = llvmc; - sourceTree = ""; - }; - DE66F38D08ABF35C00323D32 /* docs */ = { - isa = PBXGroup; - children = ( - F22627310DAE34D10008F441 /* tutorial */, - DE66F38F08ABF35C00323D32 /* AliasAnalysis.html */, - DE66F39008ABF35C00323D32 /* Bugpoint.html */, - DE66F39208ABF35C00323D32 /* GCCFEBuildInstrs.html */, - DE66F39308ABF35C00323D32 /* CodeGenerator.html */, - DE66F39408ABF35C00323D32 /* CodingStandards.html */, - DE66F39508ABF35C00323D32 /* CommandGuide */, - DE66F3B908ABF35D00323D32 /* CommandLine.html */, - DE66F3BA08ABF35D00323D32 /* CompilerDriver.html */, - DE66F3BB08ABF35D00323D32 /* CompilerWriterInfo.html */, - DE66F3BD08ABF35D00323D32 /* doxygen.cfg.in */, - DE66F3BE08ABF35D00323D32 /* doxygen.css */, - DE66F3BF08ABF35D00323D32 /* doxygen.footer */, - DE66F3C008ABF35D00323D32 /* doxygen.header */, - DE66F3C108ABF35D00323D32 /* doxygen.intro */, - DE66F3C208ABF35D00323D32 /* ExtendingLLVM.html */, - DE66F3C308ABF35D00323D32 /* FAQ.html */, - DE66F3C408ABF35D00323D32 /* GarbageCollection.html */, - DE66F3C508ABF35D00323D32 /* GettingStarted.html */, - DE66F3C608ABF35D00323D32 /* GettingStartedVS.html */, - DE66F3E408ABF35D00323D32 /* HowToSubmitABug.html */, - DE66F3E508ABF35D00323D32 /* img */, - DE66F3EB08ABF35D00323D32 /* index.html */, - DE66F3EC08ABF35D00323D32 /* LangRef.html */, - DE66F3ED08ABF35D00323D32 /* Lexicon.html */, - DE66F3EE08ABF35D00323D32 /* llvm.css */, - DE66F3F108ABF35D00323D32 /* MakefileGuide.html */, - DE66F3F208ABF35D00323D32 /* ProgrammersManual.html */, - DE66F3F308ABF35D00323D32 /* Projects.html */, - DE66F3F408ABF35D00323D32 /* ReleaseNotes.html */, - DE66F3F508ABF35D00323D32 /* SourceLevelDebugging.html */, - DE66F3F708ABF35D00323D32 /* SystemLibrary.html */, - DE66F3F808ABF35D00323D32 /* TableGenFundamentals.html */, - DE66F3F908ABF35D00323D32 /* TestingGuide.html */, - DE66F3FA08ABF35D00323D32 /* UsingLibraries.html */, - DE66F3FB08ABF35D00323D32 /* WritingAnLLVMBackend.html */, - DE66F3FC08ABF35D00323D32 /* WritingAnLLVMPass.html */, - ); - name = docs; - path = ../docs; - sourceTree = SOURCE_ROOT; - }; - DE66F39508ABF35C00323D32 /* CommandGuide */ = { - isa = PBXGroup; - children = ( - DE66F39808ABF35C00323D32 /* bugpoint.pod */, - DE66F39E08ABF35C00323D32 /* index.html */, - DE66F39F08ABF35C00323D32 /* llc.pod */, - DE66F3A008ABF35C00323D32 /* lli.pod */, - DE66F3A108ABF35C00323D32 /* llvm-ar.pod */, - DE66F3A208ABF35C00323D32 /* llvm-as.pod */, - DE66F3A308ABF35C00323D32 /* llvm-bcanalyzer.pod */, - DE66F3A408ABF35C00323D32 /* llvm-db.pod */, - DE66F3A508ABF35C00323D32 /* llvm-dis.pod */, - DE66F3A608ABF35C00323D32 /* llvm-extract.pod */, - DE66F3A708ABF35C00323D32 /* llvm-ld.pod */, - DE66F3A808ABF35C00323D32 /* llvm-link.pod */, - DE66F3A908ABF35C00323D32 /* llvm-nm.pod */, - DE66F3AA08ABF35C00323D32 /* llvm-prof.pod */, - DE66F3AB08ABF35C00323D32 /* llvm-ranlib.pod */, - DE66F3AC08ABF35C00323D32 /* llvmc.pod */, - DE66F3AD08ABF35C00323D32 /* llvmgcc.pod */, - DE66F3AE08ABF35C00323D32 /* llvmgxx.pod */, - DE66F3AF08ABF35C00323D32 /* Makefile */, - DE66F3B408ABF35D00323D32 /* manpage.css */, - DE66F3B508ABF35D00323D32 /* opt.pod */, - DE66F3B808ABF35D00323D32 /* stkrc.pod */, - ); - path = CommandGuide; - sourceTree = ""; - }; - DE66F3E508ABF35D00323D32 /* img */ = { - isa = PBXGroup; - children = ( - DE66F3E608ABF35D00323D32 /* Debugging.gif */, - DE66F3E708ABF35D00323D32 /* libdeps.gif */, - DE66F3E808ABF35D00323D32 /* lines.gif */, - DE66F3E908ABF35D00323D32 /* objdeps.gif */, - DE66F3EA08ABF35D00323D32 /* venusflytrap.jpg */, - ); - path = img; - sourceTree = ""; - }; - DE66F3FD08ABF37000323D32 /* examples */ = { - isa = PBXGroup; - children = ( - F22761DF0DAD09CD003D8065 /* BrainF.cpp */, - F22761E00DAD09CD003D8065 /* BrainF.h */, - F22761E10DAD09CD003D8065 /* BrainFDriver.cpp */, - DE66F40E08ABF37000323D32 /* fibonacci.cpp */, - DE66F41508ABF37000323D32 /* HowToUseJIT.cpp */, - DE66F41E08ABF37000323D32 /* ModuleMaker.cpp */, - DE66F42608ABF37000323D32 /* ParallelJIT.cpp */, - ); - name = examples; - path = ../examples; - sourceTree = SOURCE_ROOT; - }; - DE816FAC08CFB44C0093BDEF /* utils */ = { - isa = PBXGroup; - children = ( - DE81705708CFB44D0093BDEF /* TableGen */, - DE81704008CFB44D0093BDEF /* fpcmp.cpp */, - DE81704F08CFB44D0093BDEF /* NightlyTest.gnuplot */, - DE81705108CFB44D0093BDEF /* NightlyTestTemplate.html */, - ); - name = utils; - path = ../utils; - sourceTree = SOURCE_ROOT; - }; - DE81705708CFB44D0093BDEF /* TableGen */ = { - isa = PBXGroup; - children = ( - DE81705908CFB44D0093BDEF /* AsmWriterEmitter.cpp */, - DE81705A08CFB44D0093BDEF /* AsmWriterEmitter.h */, - DE81705B08CFB44D0093BDEF /* CodeEmitterGen.cpp */, - DE81705C08CFB44D0093BDEF /* CodeEmitterGen.h */, - DE81705D08CFB44D0093BDEF /* CodeGenInstruction.h */, - CF8F1BC90B64FBD500BB4199 /* CodeGenIntrinsics.h */, - DE81705E08CFB44D0093BDEF /* CodeGenRegisters.h */, - DE81705F08CFB44D0093BDEF /* CodeGenTarget.cpp */, - DE81706008CFB44D0093BDEF /* CodeGenTarget.h */, - DE81706708CFB44D0093BDEF /* DAGISelEmitter.cpp */, - DE81706808CFB44D0093BDEF /* DAGISelEmitter.h */, - CF9720970A9F3D4D002CEEDD /* IntrinsicEmitter.cpp */, - CF9720980A9F3D4D002CEEDD /* IntrinsicEmitter.h */, - DE81708908CFB44D0093BDEF /* InstrInfoEmitter.cpp */, - DE81708A08CFB44D0093BDEF /* InstrInfoEmitter.h */, - DE81708E08CFB44D0093BDEF /* Record.cpp */, - DE81708F08CFB44D0093BDEF /* Record.h */, - DE81709008CFB44D0093BDEF /* RegisterInfoEmitter.cpp */, - DE81709108CFB44D0093BDEF /* RegisterInfoEmitter.h */, - DE4DA065091148520012D44B /* SubtargetEmitter.cpp */, - DE4DA066091148520012D44B /* SubtargetEmitter.h */, - DE8170AA08CFB44D0093BDEF /* TableGen.cpp */, - DE8170AB08CFB44D0093BDEF /* TableGenBackend.cpp */, - DE8170AC08CFB44D0093BDEF /* TableGenBackend.h */, - CF490E300907BBF80072DB1C /* SubtargetEmitter.cpp */, - CF490E2F0907BBF80072DB1C /* SubtargetEmitter.h */, - ); - path = TableGen; - sourceTree = ""; - }; - F22627310DAE34D10008F441 /* tutorial */ = { - isa = PBXGroup; - children = ( - F22627320DAE34D10008F441 /* index.html */, - F22627330DAE34D20008F441 /* JITTutorial1.html */, - F22627340DAE34D20008F441 /* JITTutorial2-1.png */, - F22627350DAE34D20008F441 /* JITTutorial2.html */, - F22627360DAE34D20008F441 /* LangImpl1.html */, - F22627370DAE34D20008F441 /* LangImpl2.html */, - F22627380DAE34D20008F441 /* LangImpl3.html */, - F22627390DAE34D20008F441 /* LangImpl4.html */, - F226273A0DAE34D20008F441 /* LangImpl5-cfg.png */, - F226273B0DAE34D20008F441 /* LangImpl5.html */, - F226273C0DAE34D20008F441 /* LangImpl6.html */, - F226273D0DAE34D20008F441 /* LangImpl7.html */, - F226273E0DAE34D20008F441 /* LangImpl8.html */, - F226273F0DAE34D20008F441 /* Makefile */, - F22627400DAE34D20008F441 /* OCamlLangImpl1.html */, - F22627410DAE34D20008F441 /* OCamlLangImpl2.html */, - F22627420DAE34D20008F441 /* OCamlLangImpl3.html */, - F22627430DAE34D20008F441 /* OCamlLangImpl4.html */, - F22627440DAE34D20008F441 /* OCamlLangImpl5.html */, - F22627450DAE34D20008F441 /* OCamlLangImpl6.html */, - F22627460DAE34D20008F441 /* OCamlLangImpl7.html */, - ); - path = tutorial; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXLegacyTarget section */ - CF0329B608D1BE110030FD33 /* LLVM lib */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "$(ACTION) -j 2"; - buildConfigurationList = CF0329B708D1BE530030FD33 /* Build configuration list for PBXLegacyTarget "LLVM lib" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/make; - buildWorkingDirectory = "$(SRCROOT)/../lib"; - dependencies = ( - ); - name = "LLVM lib"; - passBuildSettingsInEnvironment = 0; - productName = "LLVM lib"; - }; - CF0329BB08D1BE5D0030FD33 /* LLVM llc */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "$(ACTION) -j 2"; - buildConfigurationList = CF0329C308D1BEC40030FD33 /* Build configuration list for PBXLegacyTarget "LLVM llc" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/make; - buildWorkingDirectory = "$(SRCROOT)/../tools/llc"; - dependencies = ( - ); - name = "LLVM llc"; - passBuildSettingsInEnvironment = 0; - productName = "LLVM llc"; - }; - CF490E830907CDAB0072DB1C /* LLVM TableGen */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "$(ACTION) -j 2"; - buildConfigurationList = CF490E840907CDAB0072DB1C /* Build configuration list for PBXLegacyTarget "LLVM TableGen" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/make; - buildWorkingDirectory = "${SRCROOT}/../utils/TableGen"; - dependencies = ( - ); - name = "LLVM TableGen"; - passBuildSettingsInEnvironment = 0; - productName = "LLVM llc"; - }; - CFDF86BD0ADE819D00D40A3D /* LLVM lib release */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "$(ACTION) -j 2 ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1"; - buildConfigurationList = CFDF86BE0ADE819D00D40A3D /* Build configuration list for PBXLegacyTarget "LLVM lib release" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/make; - buildWorkingDirectory = "$(SRCROOT)/../lib"; - dependencies = ( - ); - name = "LLVM lib release"; - passBuildSettingsInEnvironment = 0; - productName = "LLVM lib"; - }; - CFDF86C60ADE81D000D40A3D /* LLVM llc release */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "$(ACTION) -j 2 ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1"; - buildConfigurationList = CFDF86C70ADE81D000D40A3D /* Build configuration list for PBXLegacyTarget "LLVM llc release" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/make; - buildWorkingDirectory = "$(SRCROOT)/../tools/llc"; - dependencies = ( - ); - name = "LLVM llc release"; - passBuildSettingsInEnvironment = 0; - productName = "LLVM llc"; - }; - D28A88AD04BDD90700651E21 /* LLVM */ = { - isa = PBXLegacyTarget; - buildArgumentsString = "$(ACTION) -j 2"; - buildConfigurationList = DE66EC4C08ABE78900323D32 /* Build configuration list for PBXLegacyTarget "LLVM" */; - buildPhases = ( - ); - buildToolPath = /usr/bin/make; - buildWorkingDirectory = "$(SRCROOT)/../"; - dependencies = ( - ); - name = LLVM; - passBuildSettingsInEnvironment = 0; - productName = LLVM; - }; -/* End PBXLegacyTarget section */ - -/* Begin PBXProject section */ - 08FB7793FE84155DC02AAC07 /* Project object */ = { - isa = PBXProject; - buildConfigurationList = DE66EC5008ABE78900323D32 /* Build configuration list for PBXProject "LLVM" */; - compatibilityVersion = "Xcode 2.4"; - hasScannedForEncodings = 1; - mainGroup = 08FB7794FE84155DC02AAC07 /* LLVM */; - productRefGroup = 721CA1750D0B44D200D5004F /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - D28A88AD04BDD90700651E21 /* LLVM */, - CF0329B608D1BE110030FD33 /* LLVM lib */, - CF0329BB08D1BE5D0030FD33 /* LLVM llc */, - CF0329BC08D1BE8E0030FD33 /* LLVM full llc */, - CF490E830907CDAB0072DB1C /* LLVM TableGen */, - CFDF86BD0ADE819D00D40A3D /* LLVM lib release */, - CFDF86C60ADE81D000D40A3D /* LLVM llc release */, - CFDF86D00ADE820000D40A3D /* LLVM full llc release */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXTargetDependency section */ - CF0329BE08D1BE970030FD33 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = CF0329B608D1BE110030FD33 /* LLVM lib */; - targetProxy = CF0329BD08D1BE970030FD33 /* PBXContainerItemProxy */; - }; - CF0329C008D1BE9B0030FD33 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = CF0329BB08D1BE5D0030FD33 /* LLVM llc */; - targetProxy = CF0329BF08D1BE9B0030FD33 /* PBXContainerItemProxy */; - }; - CFDF86DA0ADE822100D40A3D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = CFDF86BD0ADE819D00D40A3D /* LLVM lib release */; - targetProxy = CFDF86D90ADE822100D40A3D /* PBXContainerItemProxy */; - }; - CFDF86DC0ADE822100D40A3D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = CFDF86C60ADE81D000D40A3D /* LLVM llc release */; - targetProxy = CFDF86DB0ADE822100D40A3D /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - CF0329B808D1BE530030FD33 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM lib"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Debug; - }; - CF0329B908D1BE530030FD33 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM lib"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Release; - }; - CF0329C408D1BEC40030FD33 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Debug; - }; - CF0329C508D1BEC40030FD33 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Release; - }; - CF0329C808D1BEC40030FD33 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM full llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Debug; - }; - CF0329C908D1BEC40030FD33 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM full llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Release; - }; - CF490E850907CDAB0072DB1C /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM TableGen"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Debug; - }; - CF490E860907CDAB0072DB1C /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Release; - }; - CFDF86BF0ADE819D00D40A3D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM lib"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Debug; - }; - CFDF86C00ADE819D00D40A3D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM lib"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Release; - }; - CFDF86C80ADE81D000D40A3D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Debug; - }; - CFDF86C90ADE81D000D40A3D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Release; - }; - CFDF86D60ADE820000D40A3D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM full llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Debug; - }; - CFDF86D70ADE820000D40A3D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = NO; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - OTHER_REZFLAGS = ""; - PRODUCT_NAME = "LLVM full llc"; - SECTORDER_FLAGS = ""; - WARNING_CFLAGS = ( - "-Wmost", - "-Wno-four-char-constants", - "-Wno-unknown-pragmas", - ); - }; - name = Release; - }; - DE66EC4D08ABE78900323D32 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = NO; - DEBUGGING_SYMBOLS = YES; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_FIX_AND_CONTINUE = YES; - GCC_GENERATE_DEBUGGING_SYMBOLS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - OPTIMIZATION_CFLAGS = "-O0"; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - PRODUCT_NAME = LLVM; - ZERO_LINK = YES; - }; - name = Debug; - }; - DE66EC4E08ABE78900323D32 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - COPY_PHASE_STRIP = YES; - ENABLE_OPTIMIZED = 1; - GCC_ENABLE_FIX_AND_CONTINUE = NO; - OTHER_CFLAGS = ""; - OTHER_LDFLAGS = ""; - PRODUCT_NAME = LLVM; - ZERO_LINK = NO; - }; - name = Release; - }; - DE66EC5108ABE78900323D32 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - DEBUG_INFORMATION_FORMAT = dwarf; - GCC_OPTIMIZATION_LEVEL = 0; - USER_HEADER_SEARCH_PATHS = "../include/**"; - }; - name = Debug; - }; - DE66EC5208ABE78900323D32 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - DEBUG_INFORMATION_FORMAT = dwarf; - USER_HEADER_SEARCH_PATHS = "../include/**"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - CF0329B708D1BE530030FD33 /* Build configuration list for PBXLegacyTarget "LLVM lib" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CF0329B808D1BE530030FD33 /* Debug */, - CF0329B908D1BE530030FD33 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - CF0329C308D1BEC40030FD33 /* Build configuration list for PBXLegacyTarget "LLVM llc" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CF0329C408D1BEC40030FD33 /* Debug */, - CF0329C508D1BEC40030FD33 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - CF0329C708D1BEC40030FD33 /* Build configuration list for PBXAggregateTarget "LLVM full llc" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CF0329C808D1BEC40030FD33 /* Debug */, - CF0329C908D1BEC40030FD33 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - CF490E840907CDAB0072DB1C /* Build configuration list for PBXLegacyTarget "LLVM TableGen" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CF490E850907CDAB0072DB1C /* Debug */, - CF490E860907CDAB0072DB1C /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - CFDF86BE0ADE819D00D40A3D /* Build configuration list for PBXLegacyTarget "LLVM lib release" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CFDF86BF0ADE819D00D40A3D /* Debug */, - CFDF86C00ADE819D00D40A3D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - CFDF86C70ADE81D000D40A3D /* Build configuration list for PBXLegacyTarget "LLVM llc release" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CFDF86C80ADE81D000D40A3D /* Debug */, - CFDF86C90ADE81D000D40A3D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - CFDF86D50ADE820000D40A3D /* Build configuration list for PBXAggregateTarget "LLVM full llc release" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CFDF86D60ADE820000D40A3D /* Debug */, - CFDF86D70ADE820000D40A3D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - DE66EC4C08ABE78900323D32 /* Build configuration list for PBXLegacyTarget "LLVM" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DE66EC4D08ABE78900323D32 /* Debug */, - DE66EC4E08ABE78900323D32 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - DE66EC5008ABE78900323D32 /* Build configuration list for PBXProject "LLVM" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - DE66EC5108ABE78900323D32 /* Debug */, - DE66EC5208ABE78900323D32 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; -/* End XCConfigurationList section */ - }; - rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; -} diff --git a/Xcode/README.txt b/Xcode/README.txt deleted file mode 100644 index 614cd67472..0000000000 --- a/Xcode/README.txt +++ /dev/null @@ -1 +0,0 @@ -Xcode project files for LLVM, for Xcode 2.1 diff --git a/autoconf/ExportMap.map b/autoconf/ExportMap.map index 43e310e053..17b185fed9 100644 --- a/autoconf/ExportMap.map +++ b/autoconf/ExportMap.map @@ -1,4 +1,7 @@ { global: main; + __progname; + environ; + local: *; }; diff --git a/autoconf/configure.ac b/autoconf/configure.ac index 40f77d828e..a5cb788b2a 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -80,6 +80,7 @@ do llvm-tv) AC_CONFIG_SUBDIRS([projects/llvm-tv]) ;; llvm-poolalloc) AC_CONFIG_SUBDIRS([projects/llvm-poolalloc]) ;; poolalloc) AC_CONFIG_SUBDIRS([projects/poolalloc]) ;; + safecode) AC_CONFIG_SUBDIRS([projects/safecode]) ;; llvm-kernel) AC_CONFIG_SUBDIRS([projects/llvm-kernel]) ;; *) AC_MSG_WARN([Unknown project (${i}) won't be configured automatically]) @@ -184,7 +185,7 @@ AC_CACHE_CHECK([type of operating system we're going to host on], llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" llvm_cv_os_type="Haiku" - llvm_cv_platform_type="Unix" ;; + llvm_cv_platform_type="Unix" ;; *-unknown-eabi*) llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" @@ -236,7 +237,7 @@ AC_CACHE_CHECK([type of operating system we're going to target], *-*-mingw*) llvm_cv_target_os_type="MingW" ;; *-*-haiku*) - llvm_cv_target_os_type="Haiku" ;; + llvm_cv_target_os_type="Haiku" ;; *-unknown-eabi*) llvm_cv_target_os_type="Freestanding" ;; *) @@ -291,6 +292,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], msp430-*) llvm_cv_target_arch="MSP430" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;; bfin-*) llvm_cv_target_arch="Blackfin" ;; + mblaze-*) llvm_cv_target_arch="MBlaze" ;; *) llvm_cv_target_arch="Unknown" ;; esac]) @@ -427,6 +429,7 @@ else MSP430) AC_SUBST(TARGET_HAS_JIT,0) ;; SystemZ) AC_SUBST(TARGET_HAS_JIT,0) ;; Blackfin) AC_SUBST(TARGET_HAS_JIT,0) ;; + MBlaze) AC_SUBST(TARGET_HAS_JIT,0) ;; *) AC_SUBST(TARGET_HAS_JIT,0) ;; esac fi @@ -470,6 +473,18 @@ esac AC_DEFINE_UNQUOTED([ENABLE_PIC],$ENABLE_PIC, [Define if position independent code is enabled]) +dnl Allow building a shared library and linking tools against it. +AC_ARG_ENABLE(shared, + AS_HELP_STRING([--enable-shared], + [Build a shared library and link tools against it (default is NO)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(ENABLE_SHARED,[1]) ;; + no) AC_SUBST(ENABLE_SHARED,[0]) ;; + default) AC_SUBST(ENABLE_SHARED,[0]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-shared. Use "yes" or "no"]) ;; +esac + dnl Allow specific targets to be specified for building (or not) TARGETS_TO_BUILD="" AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], @@ -481,7 +496,7 @@ if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend MBlaze" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -500,6 +515,7 @@ case "$enableval" in cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; msil) TARGETS_TO_BUILD="MSIL $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; host) case "$llvm_cv_target_arch" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -508,6 +524,7 @@ case "$enableval" in Alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; PIC16) TARGETS_TO_BUILD="PIC16 $TARGETS_TO_BUILD" ;; XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; @@ -612,6 +629,56 @@ if test -n "$LLVMGXX" && test -z "$LLVMGCC"; then AC_MSG_ERROR([Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is used]); fi +dnl Allow a specific Clang compiler to be used with this LLVM config. +AC_ARG_WITH(clang, + AS_HELP_STRING([--with-clang], + [Specify location of clang compiler (default is --with-built-clang)]), + [],[with_clang=default]) + +dnl Enable use of the built Clang. +AC_ARG_WITH(built-clang, + AS_HELP_STRING([--with-built-clang], + [Use the compiled Clang as the LLVM compiler (default=check)]), + [],[with_built_clang=check]) + +dnl Select the Clang compiler option. +dnl +dnl If --with-clang is given, always honor that; otherwise honor +dnl --with-built-clang, or check if we have the clang sources. +AC_MSG_CHECKING([clang compiler]) +WITH_CLANGPATH="" +WITH_BUILT_CLANG=0 +if test "$with_clang" != "default"; then + WITH_CLANGPATH="$with_clang" + if ! test -x "$WITH_CLANGPATH"; then + AC_MSG_ERROR([invalid --with-clang, path does not specify an executable]) + fi +elif test "$with_built_clang" = "yes"; then + WITH_BUILT_CLANG=1 +elif test "$with_built_clang" = "no"; then + WITH_BUILT_CLANG=0 +else + if test "$with_built_clang" != "check"; then + AC_MSG_ERROR([invalid value for --with-built-clang.]) + fi + + if test -f ${srcdir}/tools/clang/README.txt; then + WITH_BUILT_CLANG=1 + fi +fi + +if ! test -z "$WITH_CLANGPATH"; then + AC_MSG_RESULT([$WITH_CLANGPATH]) + WITH_CLANGXXPATH=`"$WITH_CLANGPATH" --print-prog-name=clang++` +elif test "$WITH_BUILT_CLANG" = "1"; then + AC_MSG_RESULT([built]) +else + AC_MSG_RESULT([none]) +fi +AC_SUBST(CLANGPATH,$WITH_CLANGPATH) +AC_SUBST(CLANGXXPATH,$WITH_CLANGXXPATH) +AC_SUBST(ENABLE_BUILT_CLANG,$WITH_BUILT_CLANG) + dnl Override the option to use for optimized builds. AC_ARG_WITH(optimize-option, AS_HELP_STRING([--with-optimize-option], @@ -946,6 +1013,29 @@ else AC_SUBST(LLVMGXXCOMMAND,$LLVMGXXCOMMAND) fi +dnl Select the LLVM capable compiler to use, we default to using llvm-gcc if +dnl found, otherwise clang if available. +AC_ARG_WITH(llvmcc, + AS_HELP_STRING([--with-llvmcc=], + [Choose the LLVM capable compiler to use (llvm-gcc, clang, or none; default=check)]), + [],[with_llvmcc=check]) +AC_MSG_CHECKING([LLVM capable compiler]) +if test "$with_llvmcc" != "check"; then + if (test "$with_llvmcc" != "llvm-gcc" && + test "$with_llvmcc" != "clang" && + test "$with_llvmcc" != "none"); then + AC_MSG_ERROR([invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'.]) + fi + WITH_LLVMCC="$with_llvmcc" +elif test -n "$LLVMGCC"; then + WITH_LLVMCC=llvm-gcc +elif test -n "$WITH_CLANGPATH" || test "$WITH_BUILT_CLANG" -ne "0"; then + WITH_LLVMCC=clang +else + WITH_LLVMCC=none +fi +AC_MSG_RESULT([$WITH_LLVMCC]) +AC_SUBST(LLVMCC_OPTION,$WITH_LLVMCC) AC_MSG_CHECKING([tool compatibility]) @@ -994,7 +1084,7 @@ fi dnl Tool compatibility is okay if we make it here. AC_MSG_RESULT([ok]) -dnl Check optional compiler flags. +dnl Check optional compiler flags. AC_MSG_CHECKING([optional compiler flags]) CXX_FLAG_CHECK(NO_VARIADIC_MACROS, [-Wno-variadic-macros]) CXX_FLAG_CHECK(NO_MISSING_FIELD_INITIALIZERS, [-Wno-missing-field-initializers]) @@ -1250,12 +1340,6 @@ if test "$llvm_cv_llvmgcc_sanity" = "yes" ; then AC_SUBST(LLVMCC1PLUS,$llvmcc1pluspath) llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'` AC_SUBST(LLVMGCCDIR,$llvmgccdir) - llvmgcclibexec=`echo "$llvmcc1path" | sed 's,/cc1,,'` - AC_SUBST(LLVMGCCLIBEXEC,$llvmgcclibexec) - llvmgccversion=[`"$LLVMGCC" -dumpversion 2>&1 | sed 's/^\([0-9.]*\).*/\1/'`] - llvmgccmajvers=[`echo $llvmgccversion | sed 's/^\([0-9]\).*/\1/'`] - AC_SUBST(LLVMGCC_VERSION,$llvmgccversion) - AC_SUBST(LLVMGCC_MAJVERS,$llvmgccmajvers) llvmgcclangs=[`"$LLVMGCC" -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'`] AC_SUBST(LLVMGCC_LANGS,$llvmgcclangs) AC_MSG_RESULT([ok]) @@ -1265,6 +1349,10 @@ dnl Propagate the shared library extension that the libltdl checks did to dnl the Makefiles so we can use it there too AC_SUBST(SHLIBEXT,$libltdl_cv_shlibext) +dnl Propagate the run-time library path variable that the libltdl +dnl checks found to the Makefiles so we can use it there too +AC_SUBST(SHLIBPATH_VAR,$libltdl_cv_shlibpath_var) + # Translate the various configuration directories and other basic # information into substitutions that will end up in Makefile.config.in # that these configured values can be used by the makefiles @@ -1275,7 +1363,7 @@ eval LLVM_PREFIX="${prefix}"; eval LLVM_BINDIR="${prefix}/bin"; eval LLVM_LIBDIR="${prefix}/lib"; eval LLVM_DATADIR="${prefix}/share/llvm"; -eval LLVM_DOCSDIR="${prefix}/docs/llvm"; +eval LLVM_DOCSDIR="${prefix}/share/doc/llvm"; eval LLVM_ETCDIR="${prefix}/etc/llvm"; eval LLVM_INCLUDEDIR="${prefix}/include"; eval LLVM_INFODIR="${prefix}/info"; diff --git a/autoconf/m4/huge_val.m4 b/autoconf/m4/huge_val.m4 index fd94c11c86..5fffbfc8d3 100644 --- a/autoconf/m4/huge_val.m4 +++ b/autoconf/m4/huge_val.m4 @@ -5,6 +5,7 @@ AC_DEFUN([AC_HUGE_VAL_CHECK],[ AC_CACHE_CHECK([for HUGE_VAL sanity], [ac_cv_huge_val_sanity],[ AC_LANG_PUSH([C++]) + ac_save_CXXFLAGS=$CXXFLAGS CXXFLAGS=-pedantic AC_RUN_IFELSE( AC_LANG_PROGRAM( @@ -12,6 +13,7 @@ AC_DEFUN([AC_HUGE_VAL_CHECK],[ [double x = HUGE_VAL; return x != x; ]), [ac_cv_huge_val_sanity=yes],[ac_cv_huge_val_sanity=no], [ac_cv_huge_val_sanity=yes]) + CXXFLAGS=$ac_save_CXXFLAGS AC_LANG_POP([C++]) ]) AC_SUBST(HUGE_VAL_SANITY,$ac_cv_huge_val_sanity) diff --git a/bindings/ocaml/bitreader/bitreader_ocaml.c b/bindings/ocaml/bitreader/bitreader_ocaml.c index 5fd9f854d9..ef72ce213d 100644 --- a/bindings/ocaml/bitreader/bitreader_ocaml.c +++ b/bindings/ocaml/bitreader/bitreader_ocaml.c @@ -46,17 +46,16 @@ static void llvm_raise(value Prototype, char *Message) { /*===-- Modules -----------------------------------------------------------===*/ /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ -CAMLprim value llvm_get_module_provider(LLVMContextRef C, - LLVMMemoryBufferRef MemBuf) { +CAMLprim value llvm_get_module(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { CAMLparam0(); CAMLlocal2(Variant, MessageVal); char *Message; - LLVMModuleProviderRef MP; - if (LLVMGetBitcodeModuleProviderInContext(C, MemBuf, &MP, &Message)) + LLVMModuleRef M; + if (LLVMGetBitcodeModuleInContext(C, MemBuf, &M, &Message)) llvm_raise(llvm_bitreader_error_exn, Message); - CAMLreturn((value) MemBuf); + CAMLreturn((value) M); } /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ diff --git a/bindings/ocaml/bitreader/llvm_bitreader.ml b/bindings/ocaml/bitreader/llvm_bitreader.ml index 88587cbe1e..8b9d01d8fb 100644 --- a/bindings/ocaml/bitreader/llvm_bitreader.ml +++ b/bindings/ocaml/bitreader/llvm_bitreader.ml @@ -13,9 +13,8 @@ exception Error of string external register_exns : exn -> unit = "llvm_register_bitreader_exns" let _ = register_exns (Error "") -external get_module_provider : Llvm.llcontext -> Llvm.llmemorybuffer -> - Llvm.llmoduleprovider - = "llvm_get_module_provider" +external get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_get_module" external parse_bitcode : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule = "llvm_parse_bitcode" diff --git a/bindings/ocaml/bitreader/llvm_bitreader.mli b/bindings/ocaml/bitreader/llvm_bitreader.mli index 5648b35fee..5e2240974a 100644 --- a/bindings/ocaml/bitreader/llvm_bitreader.mli +++ b/bindings/ocaml/bitreader/llvm_bitreader.mli @@ -14,14 +14,12 @@ exception Error of string -(** [get_module_provider context mb] reads the bitcode for a new - module provider [m] from the memory buffer [mb] in the context [context]. - Returns [m] if successful, or raises [Error msg] otherwise, where [msg] is a - description of the error encountered. See the function - [llvm::getBitcodeModuleProvider]. *) -external get_module_provider : Llvm.llcontext -> Llvm.llmemorybuffer -> - Llvm.llmoduleprovider - = "llvm_get_module_provider" +(** [get_module context mb] reads the bitcode for a new module [m] from the + memory buffer [mb] in the context [context]. Returns [m] if successful, or + raises [Error msg] otherwise, where [msg] is a description of the error + encountered. See the function [llvm::getBitcodeModule]. *) +external get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_get_module" (** [parse_bitcode context mb] parses the bitcode for a new module [m] from the memory buffer [mb] in the context [context]. Returns [m] if successful, or diff --git a/bindings/ocaml/bitwriter/bitwriter_ocaml.c b/bindings/ocaml/bitwriter/bitwriter_ocaml.c index 41aca259ca..53c93cbdfe 100644 --- a/bindings/ocaml/bitwriter/bitwriter_ocaml.c +++ b/bindings/ocaml/bitwriter/bitwriter_ocaml.c @@ -28,3 +28,18 @@ CAMLprim value llvm_write_bitcode_file(value M, value Path) { int res = LLVMWriteBitcodeToFile((LLVMModuleRef) M, String_val(Path)); return Val_bool(res == 0); } + +/* ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool */ +CAMLprim value llvm_write_bitcode_to_fd(value U, value M, value FD) { + int Unbuffered; + int res; + + if (U == Val_int(0)) { + Unbuffered = 0; + } else { + Unbuffered = Bool_val(Field(U,0)); + } + + res = LLVMWriteBitcodeToFD((LLVMModuleRef) M, Int_val(FD), 0, Unbuffered); + return Val_bool(res == 0); +} diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.ml b/bindings/ocaml/bitwriter/llvm_bitwriter.ml index 7b45c53dbf..3e69a3cc8f 100644 --- a/bindings/ocaml/bitwriter/llvm_bitwriter.ml +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.ml @@ -16,3 +16,10 @@ (* Writes the bitcode for module the given path. Returns true if successful. *) external write_bitcode_file : Llvm.llmodule -> string -> bool = "llvm_write_bitcode_file" + +external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule + -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" + +let output_bitcode ?unbuffered channel m = + write_bitcode_to_fd ?unbuffered m (Unix.descr_of_out_channel channel) diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.mli b/bindings/ocaml/bitwriter/llvm_bitwriter.mli index 2f782a1d9f..ea9a87600a 100644 --- a/bindings/ocaml/bitwriter/llvm_bitwriter.mli +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.mli @@ -16,3 +16,15 @@ [path]. Returns [true] if successful, [false] otherwise. *) external write_bitcode_file : Llvm.llmodule -> string -> bool = "llvm_write_bitcode_file" + +(** [write_bitcode_to_fd ~unbuffered fd m] writes the bitcode for module + [m] to the channel [c]. If [unbuffered] is [true], after every write the fd + will be flushed. Returns [true] if successful, [false] otherwise. *) +external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule + -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" + +(** [output_bitcode ~unbuffered c m] writes the bitcode for module [m] + to the channel [c]. If [unbuffered] is [true], after every write the fd + will be flushed. Returns [true] if successful, [false] otherwise. *) +val output_bitcode : ?unbuffered:bool -> out_channel -> Llvm.llmodule -> bool diff --git a/bindings/ocaml/executionengine/executionengine_ocaml.c b/bindings/ocaml/executionengine/executionengine_ocaml.c index 072d583bf8..5b1e32efef 100644 --- a/bindings/ocaml/executionengine/executionengine_ocaml.c +++ b/bindings/ocaml/executionengine/executionengine_ocaml.c @@ -91,7 +91,7 @@ CAMLprim value llvm_genericvalue_of_float(LLVMTypeRef Ty, value N) { } /* 'a -> t */ -CAMLprim value llvm_genericvalue_of_value(value V) { +CAMLprim value llvm_genericvalue_of_pointer(value V) { CAMLparam1(V); CAMLreturn(alloc_generic_value(LLVMCreateGenericValueOfPointer(Op_val(V)))); } @@ -130,7 +130,7 @@ CAMLprim value llvm_genericvalue_as_float(LLVMTypeRef Ty, value GenVal) { } /* t -> 'a */ -CAMLprim value llvm_genericvalue_as_value(value GenVal) { +CAMLprim value llvm_genericvalue_as_pointer(value GenVal) { return Val_op(LLVMGenericValueToPointer(Genericvalue_val(GenVal))); } @@ -168,41 +168,31 @@ CAMLprim value llvm_genericvalue_as_nativeint(value GenVal) { /*--... Operations on execution engines ....................................--*/ -/* llmoduleprovider -> ExecutionEngine.t */ -CAMLprim LLVMExecutionEngineRef llvm_ee_create(LLVMModuleProviderRef MP) { +/* llmodule -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef llvm_ee_create(LLVMModuleRef M) { LLVMExecutionEngineRef Interp; char *Error; - if (LLVMCreateExecutionEngine(&Interp, MP, &Error)) + if (LLVMCreateExecutionEngineForModule(&Interp, M, &Error)) llvm_raise(llvm_ee_error_exn, Error); return Interp; } -/* llmoduleprovider -> ExecutionEngine.t */ +/* llmodule -> ExecutionEngine.t */ CAMLprim LLVMExecutionEngineRef -llvm_ee_create_interpreter(LLVMModuleProviderRef MP) { +llvm_ee_create_interpreter(LLVMModuleRef M) { LLVMExecutionEngineRef Interp; char *Error; - if (LLVMCreateInterpreter(&Interp, MP, &Error)) + if (LLVMCreateInterpreterForModule(&Interp, M, &Error)) llvm_raise(llvm_ee_error_exn, Error); return Interp; } -/* llmoduleprovider -> ExecutionEngine.t */ +/* llmodule -> int -> ExecutionEngine.t */ CAMLprim LLVMExecutionEngineRef -llvm_ee_create_jit(LLVMModuleProviderRef MP) { +llvm_ee_create_jit(LLVMModuleRef M, value OptLevel) { LLVMExecutionEngineRef JIT; char *Error; - if (LLVMCreateJITCompiler(&JIT, MP, 3, &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return JIT; -} - -/* llmoduleprovider -> ExecutionEngine.t */ -CAMLprim LLVMExecutionEngineRef -llvm_ee_create_fast_jit(LLVMModuleProviderRef MP) { - LLVMExecutionEngineRef JIT; - char *Error; - if (LLVMCreateJITCompiler(&JIT, MP, 0, &Error)) + if (LLVMCreateJITCompilerForModule(&JIT, M, Int_val(OptLevel), &Error)) llvm_raise(llvm_ee_error_exn, Error); return JIT; } @@ -213,19 +203,18 @@ CAMLprim value llvm_ee_dispose(LLVMExecutionEngineRef EE) { return Val_unit; } -/* llmoduleprovider -> ExecutionEngine.t -> unit */ -CAMLprim value llvm_ee_add_mp(LLVMModuleProviderRef MP, - LLVMExecutionEngineRef EE) { - LLVMAddModuleProvider(EE, MP); +/* llmodule -> ExecutionEngine.t -> unit */ +CAMLprim value llvm_ee_add_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { + LLVMAddModule(EE, M); return Val_unit; } -/* llmoduleprovider -> ExecutionEngine.t -> llmodule */ -CAMLprim LLVMModuleRef llvm_ee_remove_mp(LLVMModuleProviderRef MP, - LLVMExecutionEngineRef EE) { +/* llmodule -> ExecutionEngine.t -> llmodule */ +CAMLprim LLVMModuleRef llvm_ee_remove_module(LLVMModuleRef M, + LLVMExecutionEngineRef EE) { LLVMModuleRef RemovedModule; char *Error; - if (LLVMRemoveModuleProvider(EE, MP, &RemovedModule, &Error)) + if (LLVMRemoveModule(EE, M, &RemovedModule, &Error)) llvm_raise(llvm_ee_error_exn, Error); return RemovedModule; } @@ -237,7 +226,7 @@ CAMLprim value llvm_ee_find_function(value Name, LLVMExecutionEngineRef EE) { LLVMValueRef Found; if (LLVMFindFunction(EE, String_val(Name), &Found)) CAMLreturn(Val_unit); - Option = alloc(1, 1); + Option = alloc(1, 0); Field(Option, 0) = Val_op(Found); CAMLreturn(Option); } diff --git a/bindings/ocaml/executionengine/llvm_executionengine.ml b/bindings/ocaml/executionengine/llvm_executionengine.ml index c9e8f18b22..a8535b2464 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.ml +++ b/bindings/ocaml/executionengine/llvm_executionengine.ml @@ -20,7 +20,7 @@ module GenericValue = struct external of_float: Llvm.lltype -> float -> t = "llvm_genericvalue_of_float" external of_pointer: 'a -> t - = "llvm_genericvalue_of_value" + = "llvm_genericvalue_of_pointer" external of_int32: Llvm.lltype -> int32 -> t = "llvm_genericvalue_of_int32" external of_int: Llvm.lltype -> int -> t @@ -33,7 +33,7 @@ module GenericValue = struct external as_float: Llvm.lltype -> t -> float = "llvm_genericvalue_as_float" external as_pointer: t -> 'a - = "llvm_genericvalue_as_value" + = "llvm_genericvalue_as_pointer" external as_int32: t -> int32 = "llvm_genericvalue_as_int32" external as_int: t -> int @@ -56,20 +56,18 @@ module ExecutionEngine = struct call into LLVM. *) let _ = register_exns (Error "") - external create: Llvm.llmoduleprovider -> t + external create: Llvm.llmodule -> t = "llvm_ee_create" - external create_interpreter: Llvm.llmoduleprovider -> t + external create_interpreter: Llvm.llmodule -> t = "llvm_ee_create_interpreter" - external create_jit: Llvm.llmoduleprovider -> t + external create_jit: Llvm.llmodule -> int -> t = "llvm_ee_create_jit" - external create_fast_jit: Llvm.llmoduleprovider -> t - = "llvm_ee_create_fast_jit" external dispose: t -> unit = "llvm_ee_dispose" - external add_module_provider: Llvm.llmoduleprovider -> t -> unit - = "llvm_ee_add_mp" - external remove_module_provider: Llvm.llmoduleprovider -> t -> Llvm.llmodule - = "llvm_ee_remove_mp" + external add_module: Llvm.llmodule -> t -> unit + = "llvm_ee_add_module" + external remove_module: Llvm.llmodule -> t -> Llvm.llmodule + = "llvm_ee_remove_module" external find_function: string -> t -> Llvm.llvalue option = "llvm_ee_find_function" external run_function: Llvm.llvalue -> GenericValue.t array -> t -> diff --git a/bindings/ocaml/executionengine/llvm_executionengine.mli b/bindings/ocaml/executionengine/llvm_executionengine.mli index 6c2fdfb786..ce25f9d0ae 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.mli +++ b/bindings/ocaml/executionengine/llvm_executionengine.mli @@ -25,57 +25,58 @@ module GenericValue: sig (** [of_float fpty n] boxes the float [n] in a float-valued generic value according to the floating point type [fpty]. See the fields [llvm::GenericValue::DoubleVal] and [llvm::GenericValue::FloatVal]. *) - val of_float: Llvm.lltype -> float -> t + external of_float : Llvm.lltype -> float -> t = "llvm_genericvalue_of_float" (** [of_pointer v] boxes the pointer value [v] in a generic value. See the field [llvm::GenericValue::PointerVal]. *) - val of_pointer: 'a -> t + external of_pointer : 'a -> t = "llvm_genericvalue_of_pointer" (** [of_int32 n w] boxes the int32 [i] in a generic value with the bitwidth [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int32: Llvm.lltype -> int32 -> t + external of_int32 : Llvm.lltype -> int32 -> t = "llvm_genericvalue_of_int32" (** [of_int n w] boxes the int [i] in a generic value with the bitwidth [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int: Llvm.lltype -> int -> t + external of_int : Llvm.lltype -> int -> t = "llvm_genericvalue_of_int" (** [of_natint n w] boxes the native int [i] in a generic value with the bitwidth [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_nativeint: Llvm.lltype -> nativeint -> t - + external of_nativeint : Llvm.lltype -> nativeint -> t + = "llvm_genericvalue_of_nativeint" + (** [of_int64 n w] boxes the int64 [i] in a generic value with the bitwidth [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int64: Llvm.lltype -> int64 -> t - + external of_int64 : Llvm.lltype -> int64 -> t = "llvm_genericvalue_of_int64" + (** [as_float fpty gv] unboxes the floating point-valued generic value [gv] of floating point type [fpty]. See the fields [llvm::GenericValue::DoubleVal] and [llvm::GenericValue::FloatVal]. *) - val as_float: Llvm.lltype -> t -> float + external as_float : Llvm.lltype -> t -> float = "llvm_genericvalue_as_float" (** [as_pointer gv] unboxes the pointer-valued generic value [gv]. See the field [llvm::GenericValue::PointerVal]. *) - val as_pointer: t -> 'a + external as_pointer : t -> 'a = "llvm_genericvalue_as_pointer" (** [as_int32 gv] unboxes the integer-valued generic value [gv] as an [int32]. Is invalid if [gv] has a bitwidth greater than 32 bits. See the field [llvm::GenericValue::IntVal]. *) - val as_int32: t -> int32 + external as_int32 : t -> int32 = "llvm_genericvalue_as_int32" (** [as_int gv] unboxes the integer-valued generic value [gv] as an [int]. Is invalid if [gv] has a bitwidth greater than the host bit width (but the most significant bit may be lost). See the field [llvm::GenericValue::IntVal]. *) - val as_int: t -> int + external as_int : t -> int = "llvm_genericvalue_as_int" (** [as_natint gv] unboxes the integer-valued generic value [gv] as a [nativeint]. Is invalid if [gv] has a bitwidth greater than [nativeint]. See the field [llvm::GenericValue::IntVal]. *) - val as_nativeint: t -> nativeint + external as_nativeint : t -> nativeint = "llvm_genericvalue_as_nativeint" (** [as_int64 gv] returns the integer-valued generic value [gv] as an [int64]. Is invalid if [gv] has a bitwidth greater than [int64]. See the field [llvm::GenericValue::IntVal]. *) - val as_int64: t -> int64 + external as_int64 : t -> int64 = "llvm_genericvalue_as_int64" end @@ -85,81 +86,77 @@ module ExecutionEngine: sig invoking a static compiler and generating a native executable. *) type t - (** [create mp] creates a new execution engine, taking ownership of the - module provider [mp] if successful. Creates a JIT if possible, else falls - back to an interpreter. Raises [Error msg] if an error occurrs. The - execution engine is not garbage collected and must be destroyed with - [dispose ee]. See the function [llvm::EngineBuilder::create]. *) - val create: Llvm.llmoduleprovider -> t - - (** [create_interpreter mp] creates a new interpreter, taking ownership of the - module provider [mp] if successful. Raises [Error msg] if an error - occurrs. The execution engine is not garbage collected and must be - destroyed with [dispose ee]. + (** [create m] creates a new execution engine, taking ownership of the + module [m] if successful. Creates a JIT if possible, else falls back to an + interpreter. Raises [Error msg] if an error occurrs. The execution engine + is not garbage collected and must be destroyed with [dispose ee]. See the function [llvm::EngineBuilder::create]. *) - val create_interpreter: Llvm.llmoduleprovider -> t + external create : Llvm.llmodule -> t = "llvm_ee_create" - (** [create_jit mp] creates a new JIT (just-in-time compiler), taking - ownership of the module provider [mp] if successful. This function creates - a JIT which favors code quality over compilation speed. Raises [Error msg] - if an error occurrs. The execution engine is not garbage collected and - must be destroyed with [dispose ee]. + (** [create_interpreter m] creates a new interpreter, taking ownership of the + module [m] if successful. Raises [Error msg] if an error occurrs. The + execution engine is not garbage collected and must be destroyed with + [dispose ee]. See the function [llvm::EngineBuilder::create]. *) - val create_jit: Llvm.llmoduleprovider -> t + external create_interpreter : Llvm.llmodule -> t = "llvm_ee_create_interpreter" - (** [create_fast_jit mp] creates a new JIT (just-in-time compiler) which - favors compilation speed over code quality. It takes ownership of the - module provider [mp] if successful. Raises [Error msg] if an error - occurrs. The execution engine is not garbage collected and must be - destroyed with [dispose ee]. + (** [create_jit m optlevel] creates a new JIT (just-in-time compiler), taking + ownership of the module [m] if successful with the desired optimization + level [optlevel]. Raises [Error msg] if an error occurrs. The execution + engine is not garbage collected and must be destroyed with [dispose ee]. See the function [llvm::EngineBuilder::create]. *) - val create_fast_jit: Llvm.llmoduleprovider -> t - + external create_jit : Llvm.llmodule -> int -> t = "llvm_ee_create_jit" + (** [dispose ee] releases the memory used by the execution engine and must be invoked to avoid memory leaks. *) - val dispose: t -> unit + external dispose : t -> unit = "llvm_ee_dispose" - (** [add_module_provider mp ee] adds the module provider [mp] to the execution - engine [ee]. *) - val add_module_provider: Llvm.llmoduleprovider -> t -> unit + (** [add_module m ee] adds the module [m] to the execution engine [ee]. *) + external add_module : Llvm.llmodule -> t -> unit = "llvm_ee_add_module" - (** [remove_module_provider mp ee] removes the module provider [mp] from the - execution engine [ee], disposing of [mp] and the module referenced by - [mp]. Raises [Error msg] if an error occurs. *) - val remove_module_provider: Llvm.llmoduleprovider -> t -> Llvm.llmodule + (** [remove_module m ee] removes the module [m] from the execution engine + [ee], disposing of [m] and the module referenced by [mp]. Raises + [Error msg] if an error occurs. *) + external remove_module : Llvm.llmodule -> t -> Llvm.llmodule + = "llvm_ee_remove_module" (** [find_function n ee] finds the function named [n] defined in any of the modules owned by the execution engine [ee]. Returns [None] if the function is not found and [Some f] otherwise. *) - val find_function: string -> t -> Llvm.llvalue option + external find_function : string -> t -> Llvm.llvalue option + = "llvm_ee_find_function" (** [run_function f args ee] synchronously executes the function [f] with the arguments [args], which must be compatible with the parameter types. *) - val run_function: Llvm.llvalue -> GenericValue.t array -> t -> - GenericValue.t + external run_function : Llvm.llvalue -> GenericValue.t array -> t -> + GenericValue.t + = "llvm_ee_run_function" (** [run_static_ctors ee] executes the static constructors of each module in the execution engine [ee]. *) - val run_static_ctors: t -> unit + external run_static_ctors : t -> unit = "llvm_ee_run_static_ctors" (** [run_static_dtors ee] executes the static destructors of each module in the execution engine [ee]. *) - val run_static_dtors: t -> unit + external run_static_dtors : t -> unit = "llvm_ee_run_static_dtors" (** [run_function_as_main f args env ee] executes the function [f] as a main function, passing it [argv] and [argc] according to the string array [args], and [envp] as specified by the array [env]. Returns the integer return value of the function. *) - val run_function_as_main: Llvm.llvalue -> string array -> - (string * string) array -> t -> int + external run_function_as_main : Llvm.llvalue -> string array -> + (string * string) array -> t -> int + = "llvm_ee_run_function_as_main" (** [free_machine_code f ee] releases the memory in the execution engine [ee] used to store the machine code for the function [f]. *) - val free_machine_code: Llvm.llvalue -> t -> unit + external free_machine_code : Llvm.llvalue -> t -> unit + = "llvm_ee_free_machine_code" (** [target_data ee] is the target data owned by the execution engine [ee]. *) - val target_data: t -> Llvm_target.TargetData.t + external target_data : t -> Llvm_target.TargetData.t + = "LLVMGetExecutionEngineTargetData" end external initialize_native_target : unit -> bool diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index 7e4acbff47..e801c49471 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -13,9 +13,9 @@ type llmodule type lltype type lltypehandle type llvalue +type lluse type llbasicblock type llbuilder -type llmoduleprovider type llmemorybuffer module TypeKind = struct @@ -35,6 +35,7 @@ module TypeKind = struct | Opaque | Vector | Metadata + | Union end module Linkage = struct @@ -89,11 +90,13 @@ module Attribute = struct | Optsize | Ssp | Sspreq + | Alignment | Nocapture | Noredzone | Noimplicitfloat | Naked | Inlinehint + | Stackalignment end module Icmp = struct @@ -147,6 +150,7 @@ type ('a, 'b) llrev_pos = external create_context : unit -> llcontext = "llvm_create_context" external dispose_context : llcontext -> unit = "llvm_dispose_context" external global_context : unit -> llcontext = "llvm_global_context" +external mdkind_id : llcontext -> string -> int = "llvm_mdkind_id" (*===-- Modules -----------------------------------------------------------===*) external create_module : llcontext -> string -> llmodule = "llvm_create_module" @@ -163,6 +167,8 @@ external define_type_name : string -> lltype -> llmodule -> bool = "llvm_add_type_name" external delete_type_name : string -> llmodule -> unit = "llvm_delete_type_name" +external type_by_name : llmodule -> string -> lltype option + = "llvm_type_by_name" external dump_module : llmodule -> unit = "llvm_dump_module" (*===-- Types -------------------------------------------------------------===*) @@ -198,9 +204,15 @@ external param_types : lltype -> lltype array = "llvm_param_types" external struct_type : llcontext -> lltype array -> lltype = "llvm_struct_type" external packed_struct_type : llcontext -> lltype array -> lltype = "llvm_packed_struct_type" -external element_types : lltype -> lltype array = "llvm_element_types" +external struct_element_types : lltype -> lltype array + = "llvm_struct_element_types" external is_packed : lltype -> bool = "llvm_is_packed" +(*--... Operations on union types ..........................................--*) +external union_type : llcontext -> lltype array -> lltype = "llvm_union_type" +external union_element_types : lltype -> lltype array + = "llvm_union_element_types" + (*--... Operations on pointer, vector, and array types .....................--*) external array_type : lltype -> int -> lltype = "llvm_array_type" external pointer_type : lltype -> lltype = "llvm_pointer_type" @@ -229,15 +241,63 @@ external type_of : llvalue -> lltype = "llvm_type_of" external value_name : llvalue -> string = "llvm_value_name" external set_value_name : string -> llvalue -> unit = "llvm_set_value_name" external dump_value : llvalue -> unit = "llvm_dump_value" +external replace_all_uses_with : llvalue -> llvalue -> unit + = "LLVMReplaceAllUsesWith" + +(*--... Operations on uses .................................................--*) +external use_begin : llvalue -> lluse option = "llvm_use_begin" +external use_succ : lluse -> lluse option = "llvm_use_succ" +external user : lluse -> llvalue = "llvm_user" +external used_value : lluse -> llvalue = "llvm_used_value" + +let iter_uses f v = + let rec aux = function + | None -> () + | Some u -> + f u; + aux (use_succ u) + in + aux (use_begin v) + +let fold_left_uses f init v = + let rec aux init u = + match u with + | None -> init + | Some u -> aux (f init u) (use_succ u) + in + aux init (use_begin v) + +let fold_right_uses f v init = + let rec aux u init = + match u with + | None -> init + | Some u -> f u (aux (use_succ u) init) + in + aux (use_begin v) init + + +(*--... Operations on users ................................................--*) +external operand : llvalue -> int -> llvalue = "llvm_operand" (*--... Operations on constants of (mostly) any type .......................--*) external is_constant : llvalue -> bool = "llvm_is_constant" external const_null : lltype -> llvalue = "LLVMConstNull" external const_all_ones : (*int|vec*)lltype -> llvalue = "LLVMConstAllOnes" +external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull" external undef : lltype -> llvalue = "LLVMGetUndef" external is_null : llvalue -> bool = "llvm_is_null" external is_undef : llvalue -> bool = "llvm_is_undef" +(*--... Operations on instructions .........................................--*) +external has_metadata : llvalue -> bool = "llvm_has_metadata" +external metadata : llvalue -> int -> llvalue option = "llvm_metadata" +external set_metadata : llvalue -> int -> llvalue -> unit = "llvm_set_metadata" +external clear_metadata : llvalue -> int -> unit = "llvm_clear_metadata" + +(*--... Operations on metadata .......,.....................................--*) +external mdstring : llcontext -> string -> llvalue = "llvm_mdstring" +external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode" + (*--... Operations on scalar constants .....................................--*) external const_int : lltype -> int -> llvalue = "llvm_const_int" external const_of_int64 : lltype -> Int64.t -> bool -> llvalue @@ -257,19 +317,27 @@ external const_struct : llcontext -> llvalue array -> llvalue external const_packed_struct : llcontext -> llvalue array -> llvalue = "llvm_const_packed_struct" external const_vector : llvalue array -> llvalue = "llvm_const_vector" +external const_union : lltype -> llvalue -> llvalue = "LLVMConstUnion" (*--... Constant expressions ...............................................--*) external align_of : lltype -> llvalue = "LLVMAlignOf" external size_of : lltype -> llvalue = "LLVMSizeOf" external const_neg : llvalue -> llvalue = "LLVMConstNeg" +external const_nsw_neg : llvalue -> llvalue = "LLVMConstNSWNeg" +external const_nuw_neg : llvalue -> llvalue = "LLVMConstNUWNeg" external const_fneg : llvalue -> llvalue = "LLVMConstFNeg" external const_not : llvalue -> llvalue = "LLVMConstNot" external const_add : llvalue -> llvalue -> llvalue = "LLVMConstAdd" external const_nsw_add : llvalue -> llvalue -> llvalue = "LLVMConstNSWAdd" +external const_nuw_add : llvalue -> llvalue -> llvalue = "LLVMConstNUWAdd" external const_fadd : llvalue -> llvalue -> llvalue = "LLVMConstFAdd" external const_sub : llvalue -> llvalue -> llvalue = "LLVMConstSub" +external const_nsw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNSWSub" +external const_nuw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNUWSub" external const_fsub : llvalue -> llvalue -> llvalue = "LLVMConstFSub" external const_mul : llvalue -> llvalue -> llvalue = "LLVMConstMul" +external const_nsw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNSWMul" +external const_nuw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNUWMul" external const_fmul : llvalue -> llvalue -> llvalue = "LLVMConstFMul" external const_udiv : llvalue -> llvalue -> llvalue = "LLVMConstUDiv" external const_sdiv : llvalue -> llvalue -> llvalue = "LLVMConstSDiv" @@ -325,6 +393,10 @@ external const_extractvalue : llvalue -> int array -> llvalue = "llvm_const_extractvalue" external const_insertvalue : llvalue -> llvalue -> int array -> llvalue = "llvm_const_insertvalue" +external const_inline_asm : lltype -> string -> string -> bool -> bool -> + llvalue + = "llvm_const_inline_asm" +external block_address : llvalue -> llbasicblock -> llvalue = "LLVMBlockAddress" (*--... Operations on global variables, functions, and aliases (globals) ...--*) external global_parent : llvalue -> llmodule = "LLVMGetGlobalParent" @@ -344,8 +416,14 @@ external set_global_constant : bool -> llvalue -> unit (*--... Operations on global variables .....................................--*) external declare_global : lltype -> string -> llmodule -> llvalue = "llvm_declare_global" +external declare_qualified_global : lltype -> string -> int -> llmodule -> + llvalue + = "llvm_declare_qualified_global" external define_global : string -> llvalue -> llmodule -> llvalue = "llvm_define_global" +external define_qualified_global : string -> llvalue -> int -> llmodule -> + llvalue + = "llvm_define_qualified_global" external lookup_global : string -> llmodule -> llvalue option = "llvm_lookup_global" external delete_global : llvalue -> unit = "llvm_delete_global" @@ -403,6 +481,10 @@ let rec fold_right_global_range f i e init = let fold_right_globals f m init = fold_right_global_range f (global_end m) (At_start m) init +(*--... Operations on aliases ..............................................--*) +external add_alias : llmodule -> lltype -> llvalue -> string -> llvalue + = "llvm_add_alias" + (*--... Operations on functions ............................................--*) external declare_function : string -> lltype -> llmodule -> llvalue = "llvm_declare_function" @@ -680,6 +762,17 @@ let position_before i = position_builder (Before i) let position_at_end bb = position_builder (At_end bb) +(*--... Metadata ...........................................................--*) +external set_current_debug_location : llbuilder -> llvalue -> unit + = "llvm_set_current_debug_location" +external clear_current_debug_location : llbuilder -> unit + = "llvm_clear_current_debug_location" +external current_debug_location : llbuilder -> llvalue option + = "llvm_current_debug_location" +external set_inst_debug_location : llbuilder -> llvalue -> unit + = "llvm_set_inst_debug_location" + + (*--... Terminators ........................................................--*) external build_ret_void : llbuilder -> llvalue = "llvm_build_ret_void" external build_ret : llvalue -> llbuilder -> llvalue = "llvm_build_ret" @@ -692,6 +785,10 @@ external build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue = "llvm_build_switch" external add_case : llvalue -> llvalue -> llbasicblock -> unit = "llvm_add_case" +external build_indirect_br : llvalue -> int -> llbuilder -> llvalue + = "llvm_build_indirect_br" +external add_destination : llvalue -> llbasicblock -> unit + = "llvm_add_destination" external build_invoke : llvalue -> llvalue array -> llbasicblock -> llbasicblock -> string -> llbuilder -> llvalue = "llvm_build_invoke_bc" "llvm_build_invoke_nat" @@ -703,14 +800,24 @@ external build_add : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_add" external build_nsw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_nsw_add" +external build_nuw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_add" external build_fadd : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_fadd" external build_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_sub" +external build_nsw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_sub" +external build_nuw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_sub" external build_fsub : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_fsub" external build_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_mul" +external build_nsw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_mul" +external build_nuw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_mul" external build_fmul : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_fmul" external build_udiv : llvalue -> llvalue -> string -> llbuilder -> llvalue @@ -741,19 +848,20 @@ external build_xor : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_xor" external build_neg : llvalue -> string -> llbuilder -> llvalue = "llvm_build_neg" +external build_nsw_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_neg" +external build_nuw_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_neg" +external build_fneg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fneg" external build_not : llvalue -> string -> llbuilder -> llvalue = "llvm_build_not" (*--... Memory .............................................................--*) -external build_malloc : lltype -> string -> llbuilder -> llvalue - = "llvm_build_malloc" -external build_array_malloc : lltype -> llvalue -> string -> llbuilder -> - llvalue = "llvm_build_array_malloc" external build_alloca : lltype -> string -> llbuilder -> llvalue = "llvm_build_alloca" external build_array_alloca : lltype -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_array_alloca" -external build_free : llvalue -> llbuilder -> llvalue = "llvm_build_free" external build_load : llvalue -> string -> llbuilder -> llvalue = "llvm_build_load" external build_store : llvalue -> llvalue -> llbuilder -> llvalue @@ -841,14 +949,6 @@ external build_is_not_null : llvalue -> string -> llbuilder -> llvalue external build_ptrdiff : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_ptrdiff" -(*===-- Module providers --------------------------------------------------===*) - -module ModuleProvider = struct - external create : llmodule -> llmoduleprovider - = "LLVMCreateModuleProviderForExistingModule" - external dispose : llmoduleprovider -> unit = "llvm_dispose_module_provider" -end - (*===-- Memory buffers ----------------------------------------------------===*) @@ -865,7 +965,7 @@ module PassManager = struct type 'a t type any = [ `Module | `Function ] external create : unit -> [ `Module ] t = "llvm_passmanager_create" - external create_function : llmoduleprovider -> [ `Function ] t + external create_function : llmodule -> [ `Function ] t = "LLVMCreateFunctionPassManager" external run_module : llmodule -> [ `Module ] t -> bool = "llvm_passmanager_run_module" @@ -897,11 +997,14 @@ let rec string_of_lltype ty = | TypeKind.Pointer -> (string_of_lltype (element_type ty)) ^ "*" | TypeKind.Struct -> let s = "{ " ^ (concat2 ", " ( - Array.map string_of_lltype (element_types ty) + Array.map string_of_lltype (struct_element_types ty) )) ^ " }" in if is_packed ty then "<" ^ s ^ ">" else s + | TypeKind.Union -> "union { " ^ (concat2 ", " ( + Array.map string_of_lltype (union_element_types ty) + )) ^ " }" | TypeKind.Array -> "[" ^ (string_of_int (array_length ty)) ^ " x " ^ (string_of_lltype (element_type ty)) ^ "]" | TypeKind.Vector -> "<" ^ (string_of_int (vector_size ty)) ^ diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index bcdcb2ce11..4b0c06da03 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -39,6 +39,9 @@ type lltypehandle This type covers a wide range of subclasses. *) type llvalue +(** Used to store users and usees of values. See the [llvm::Use] class. *) +type lluse + (** A basic block in LLVM IR. See the [llvm::BasicBlock] class. *) type llbasicblock @@ -46,10 +49,6 @@ type llbasicblock class. *) type llbuilder -(** Used to provide a module to JIT or interpreter. - See the [llvm::ModuleProvider] class. *) -type llmoduleprovider - (** Used to efficiently handle large buffers of read-only binary data. See the [llvm::MemoryBuffer] class. *) type llmemorybuffer @@ -73,6 +72,7 @@ module TypeKind : sig | Opaque | Vector | Metadata + | Union end (** The linkage of a global value, accessed with {!linkage} and @@ -139,11 +139,13 @@ module Attribute : sig | Optsize | Ssp | Sspreq + | Alignment | Nocapture | Noredzone | Noimplicitfloat | Naked | Inlinehint + | Stackalignment end (** The predicate for an integer comparison ([icmp]) instruction. @@ -220,6 +222,11 @@ external dispose_context : llcontext -> unit = "llvm_dispose_context" (** See the function [llvm::getGlobalContext]. *) external global_context : unit -> llcontext = "llvm_global_context" +(** [mdkind_id context name] returns the MDKind ID that corresponds to the + name [name] in the context [context]. See the function + [llvm::LLVMContext::getMDKindID]. *) +external mdkind_id : llcontext -> string -> int = "llvm_mdkind_id" + (** {6 Modules} *) @@ -268,6 +275,11 @@ external define_type_name : string -> lltype -> llmodule -> bool external delete_type_name : string -> llmodule -> unit = "llvm_delete_type_name" +(** [type_by_name m n] returns the type in the module [m] named [n], or [None] + if it does not exist. See the method [llvm::Module::getTypeByName]. *) +external type_by_name : llmodule -> string -> lltype option + = "llvm_type_by_name" + (** [dump_module m] prints the .ll representation of the module [m] to standard error. See the method [llvm::Module::dump]. *) external dump_module : llmodule -> unit = "llvm_dump_module" @@ -381,15 +393,29 @@ external struct_type : llcontext -> lltype array -> lltype external packed_struct_type : llcontext -> lltype array -> lltype = "llvm_packed_struct_type" -(** [element_types sty] returns the constituent types of the struct type [sty]. - See the method [llvm::StructType::getElementType]. *) -external element_types : lltype -> lltype array = "llvm_element_types" +(** [struct_element_types sty] returns the constituent types of the struct type + [sty]. See the method [llvm::StructType::getElementType]. *) +external struct_element_types : lltype -> lltype array + = "llvm_struct_element_types" (** [is_packed sty] returns [true] if the structure type [sty] is packed, [false] otherwise. See the method [llvm::StructType::isPacked]. *) external is_packed : lltype -> bool = "llvm_is_packed" +(** {7 Operations on union types} *) + +(** [union_type context tys] returns the union type in the context [context] + containing the types in the array [tys]. See the method + [llvm::UnionType::get] *) +external union_type : llcontext -> lltype array -> lltype = "llvm_union_type" + +(** [union_element_types uty] returns the constituent types of the union type + [uty]. See the method [llvm::UnionType::getElementType]. *) +external union_element_types : lltype -> lltype array + = "llvm_union_element_types" + + (** {7 Operations on pointer, vector, and array types} *) (** [array_type ty n] returns the array type containing [n] elements of type @@ -482,6 +508,50 @@ external set_value_name : string -> llvalue -> unit = "llvm_set_value_name" error. See the method [llvm::Value::dump]. *) external dump_value : llvalue -> unit = "llvm_dump_value" +(** [replace_all_uses_with old new] replaces all uses of the value [old] + * with the value [new]. See the method [llvm::Value::replaceAllUsesWith]. *) +external replace_all_uses_with : llvalue -> llvalue -> unit + = "LLVMReplaceAllUsesWith" + + +(* {6 Uses} *) + +(** [use_begin v] returns the first position in the use list for the value [v]. + [use_begin] and [use_succ] can e used to iterate over the use list in order. + See the method [llvm::Value::use_begin]. *) +external use_begin : llvalue -> lluse option = "llvm_use_begin" + +(** [use_succ u] returns the use list position succeeding [u]. + See the method [llvm::use_value_iterator::operator++]. *) +external use_succ : lluse -> lluse option = "llvm_use_succ" + +(** [user u] returns the user of the use [u]. + See the method [llvm::Use::getUser]. *) +external user : lluse -> llvalue = "llvm_user" + +(** [used_value u] returns the usee of the use [u]. + See the method [llvm::Use::getUsedValue]. *) +external used_value : lluse -> llvalue = "llvm_used_value" + +(** [iter_uses f v] applies function [f] to each of the users of the value [v] + in order. Tail recursive. *) +val iter_uses : (lluse -> unit) -> llvalue -> unit + +(** [fold_left_uses f init v] is [f (... (f init u1) ...) uN] where + [u1,...,uN] are the users of the value [v]. Tail recursive. *) +val fold_left_uses : ('a -> lluse -> 'a) -> 'a -> llvalue -> 'a + +(** [fold_right_uses f v init] is [f u1 (... (f uN init) ...)] where + [u1,...,uN] are the users of the value [v]. Not tail recursive. *) +val fold_right_uses : (lluse -> 'a -> 'a) -> llvalue -> 'a -> 'a + + +(* {6 Users} *) + +(** [operand v i] returns the operand at index [i] for the value [v]. See the + method [llvm::User::getOperand]. *) +external operand : llvalue -> int -> llvalue = "llvm_operand" + (** {7 Operations on constants of (mostly) any type} *) @@ -497,6 +567,10 @@ external const_null : lltype -> llvalue = "LLVMConstNull" [ty]. See the method [llvm::Constant::getAllOnesValue]. *) external const_all_ones : (*int|vec*)lltype -> llvalue = "LLVMConstAllOnes" +(** [const_pointer_null ty] returns the constant null (zero) pointer of the type + [ty]. See the method [llvm::ConstantPointerNull::get]. *) +external const_pointer_null : lltype -> llvalue = "LLVMConstPointerNull" + (** [undef ty] returns the undefined value of the type [ty]. See the method [llvm::UndefValue::get]. *) external undef : lltype -> llvalue = "LLVMGetUndef" @@ -510,6 +584,39 @@ external is_null : llvalue -> bool = "llvm_is_null" external is_undef : llvalue -> bool = "llvm_is_undef" +(** {7 Operations on instructions} *) + +(** [has_metadata i] returns whether or not the instruction [i] has any + metadata attached to it. See the function + [llvm::Instruction::hasMetadata]. *) +external has_metadata : llvalue -> bool = "llvm_has_metadata" + +(** [metadata i kind] optionally returns the metadata associated with the + kind [kind] in the instruction [i] See the function + [llvm::Instruction::getMetadata]. *) +external metadata : llvalue -> int -> llvalue option = "llvm_metadata" + +(** [set_metadata i kind md] sets the metadata [md] of kind [kind] in the + instruction [i]. See the function [llvm::Instruction::setMetadata]. *) +external set_metadata : llvalue -> int -> llvalue -> unit = "llvm_set_metadata" + +(** [clear_metadata i kind] clears the metadata of kind [kind] in the + instruction [i]. See the function [llvm::Instruction::setMetadata]. *) +external clear_metadata : llvalue -> int -> unit = "llvm_clear_metadata" + + +(** {7 Operations on metadata} *) + +(** [mdstring c s] returns the MDString of the string [s] in the context [c]. + See the method [llvm::MDNode::get]. *) +external mdstring : llcontext -> string -> llvalue = "llvm_mdstring" + +(** [mdnode c elts] returns the MDNode containing the values [elts] in the + context [c]. + See the method [llvm::MDNode::get]. *) +external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode" + + (** {7 Operations on scalar constants} *) (** [const_int ty i] returns the integer constant of type [ty] and value [i]. @@ -577,6 +684,10 @@ external const_packed_struct : llcontext -> llvalue array -> llvalue values [elts]. See the method [llvm::ConstantVector::get]. *) external const_vector : llvalue array -> llvalue = "llvm_const_vector" +(** [const_union ty v] returns the union constant of type [union_type tys] and + containing the value [v]. See the method [llvm::ConstantUnion::get]. *) +external const_union : lltype -> llvalue -> llvalue = "LLVMConstUnion" + (** {7 Constant expressions} *) @@ -596,6 +707,16 @@ external size_of : lltype -> llvalue = "LLVMSizeOf" See the method [llvm::ConstantExpr::getNeg]. *) external const_neg : llvalue -> llvalue = "LLVMConstNeg" +(** [const_nsw_neg c] returns the arithmetic negation of the constant [c] with + no signed wrapping. The result is undefined if the negation overflows. + See the method [llvm::ConstantExpr::getNSWNeg]. *) +external const_nsw_neg : llvalue -> llvalue = "LLVMConstNSWNeg" + +(** [const_nuw_neg c] returns the arithmetic negation of the constant [c] with + no unsigned wrapping. The result is undefined if the negation overflows. + See the method [llvm::ConstantExpr::getNUWNeg]. *) +external const_nuw_neg : llvalue -> llvalue = "LLVMConstNUWNeg" + (** [const_fneg c] returns the arithmetic negation of the constant float [c]. See the method [llvm::ConstantExpr::getFNeg]. *) external const_fneg : llvalue -> llvalue = "LLVMConstFNeg" @@ -613,6 +734,11 @@ external const_add : llvalue -> llvalue -> llvalue = "LLVMConstAdd" See the method [llvm::ConstantExpr::getNSWAdd]. *) external const_nsw_add : llvalue -> llvalue -> llvalue = "LLVMConstNSWAdd" +(** [const_nuw_add c1 c2] returns the constant sum of two constants with no + unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWAdd]. *) +external const_nuw_add : llvalue -> llvalue -> llvalue = "LLVMConstNUWAdd" + (** [const_fadd c1 c2] returns the constant sum of two constant floats. See the method [llvm::ConstantExpr::getFAdd]. *) external const_fadd : llvalue -> llvalue -> llvalue = "LLVMConstFAdd" @@ -621,6 +747,16 @@ external const_fadd : llvalue -> llvalue -> llvalue = "LLVMConstFAdd" constants. See the method [llvm::ConstantExpr::getSub]. *) external const_sub : llvalue -> llvalue -> llvalue = "LLVMConstSub" +(** [const_nsw_sub c1 c2] returns the constant difference of two constants with + no signed wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWSub]. *) +external const_nsw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNSWSub" + +(** [const_nuw_sub c1 c2] returns the constant difference of two constants with + no unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWSub]. *) +external const_nuw_sub : llvalue -> llvalue -> llvalue = "LLVMConstNUWSub" + (** [const_fsub c1 c2] returns the constant difference, [c1 - c2], of two constant floats. See the method [llvm::ConstantExpr::getFSub]. *) external const_fsub : llvalue -> llvalue -> llvalue = "LLVMConstFSub" @@ -629,6 +765,16 @@ external const_fsub : llvalue -> llvalue -> llvalue = "LLVMConstFSub" See the method [llvm::ConstantExpr::getMul]. *) external const_mul : llvalue -> llvalue -> llvalue = "LLVMConstMul" +(** [const_nsw_mul c1 c2] returns the constant product of two constants with + no signed wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWMul]. *) +external const_nsw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNSWMul" + +(** [const_nuw_mul c1 c2] returns the constant product of two constants with + no unsigned wrapping. The result is undefined if the sum overflows. + See the method [llvm::ConstantExpr::getNSWMul]. *) +external const_nuw_mul : llvalue -> llvalue -> llvalue = "LLVMConstNUWMul" + (** [const_fmul c1 c2] returns the constant product of two constants floats. See the method [llvm::ConstantExpr::getFMul]. *) external const_fmul : llvalue -> llvalue -> llvalue = "LLVMConstFMul" @@ -858,6 +1004,16 @@ external const_extractvalue : llvalue -> int array -> llvalue external const_insertvalue : llvalue -> llvalue -> int array -> llvalue = "llvm_const_insertvalue" +(** [const_inline_asm ty asm con side align] inserts a inline assembly string. + See the method [llvm::InlineAsm::get]. *) +external const_inline_asm : lltype -> string -> string -> bool -> bool -> + llvalue + = "llvm_const_inline_asm" + +(** [block_address f bb] returns the address of the basic block [bb] in the + function [f]. See the method [llvm::BasicBlock::get]. *) +external block_address : llvalue -> llbasicblock -> llvalue = "LLVMBlockAddress" + (** {7 Operations on global variables, functions, and aliases (globals)} *) @@ -907,19 +1063,36 @@ external set_alignment : int -> llvalue -> unit = "llvm_set_alignment" (** {7 Operations on global variables} *) (** [declare_global ty name m] returns a new global variable of type [ty] and - with name [name] in module [m]. If such a global variable already exists, - it is returned. If the type of the existing global differs, then a bitcast - to [ty] is returned. *) + with name [name] in module [m] in the default address space (0). If such a + global variable already exists, it is returned. If the type of the existing + global differs, then a bitcast to [ty] is returned. *) external declare_global : lltype -> string -> llmodule -> llvalue = "llvm_declare_global" +(** [declare_qualified_global ty name addrspace m] returns a new global variable + of type [ty] and with name [name] in module [m] in the address space + [addrspace]. If such a global variable already exists, it is returned. If + the type of the existing global differs, then a bitcast to [ty] is + returned. *) +external declare_qualified_global : lltype -> string -> int -> llmodule -> + llvalue + = "llvm_declare_qualified_global" + (** [define_global name init m] returns a new global with name [name] and - initializer [init] in module [m]. If the named global already exists, it is - renamed. + initializer [init] in module [m] in the default address space (0). If the + named global already exists, it is renamed. See the constructor of [llvm::GlobalVariable]. *) external define_global : string -> llvalue -> llmodule -> llvalue = "llvm_define_global" +(** [define_qualified_global name init addrspace m] returns a new global with + name [name] and initializer [init] in module [m] in the address space + [addrspace]. If the named global already exists, it is renamed. + See the constructor of [llvm::GlobalVariable]. *) +external define_qualified_global : string -> llvalue -> int -> llmodule -> + llvalue + = "llvm_define_qualified_global" + (** [lookup_global name m] returns [Some g] if a global variable with name [name] exists in module [m]. If no such global exists, returns [None]. See the [llvm::GlobalVariable] constructor. *) @@ -1008,6 +1181,15 @@ external is_thread_local : llvalue -> bool = "llvm_is_thread_local" external set_thread_local : bool -> llvalue -> unit = "llvm_set_thread_local" +(** {7 Operations on aliases} *) + +(** [add_alias m t a n] inserts an alias in the module [m] with the type [t] and + the aliasee [a] with the name [n]. + See the constructor for [llvm::GlobalAlias]. *) +external add_alias : llmodule -> lltype -> llvalue -> string -> llvalue + = "llvm_add_alias" + + (** {7 Operations on functions} *) (** [declare_function name ty m] returns a new function of type [ty] and @@ -1397,6 +1579,30 @@ external insertion_block : llbuilder -> llbasicblock = "llvm_insertion_block" external insert_into_builder : llvalue -> string -> llbuilder -> unit = "llvm_insert_into_builder" +(** {7 Metadata} *) + +(** [set_current_debug_location b md] sets the current debug location [md] in + the builder [b]. + See the method [llvm::IRBuilder::SetDebugLocation]. *) +external set_current_debug_location : llbuilder -> llvalue -> unit + = "llvm_set_current_debug_location" + +(** [clear_current_debug_location b] clears the current debug location in the + builder [b]. *) +external clear_current_debug_location : llbuilder -> unit + = "llvm_clear_current_debug_location" + +(** [current_debug_location b] returns the current debug location, or None + if none is currently set. + See the method [llvm::IRBuilder::GetDebugLocation]. *) +external current_debug_location : llbuilder -> llvalue option + = "llvm_current_debug_location" + +(** [set_inst_debug_location b i] sets the current debug location of the builder + [b] to the instruction [i]. + See the method [llvm::IRBuilder::SetInstDebugLocation]. *) +external set_inst_debug_location : llbuilder -> llvalue -> unit + = "llvm_set_inst_debug_location" (** {7 Terminators} *) @@ -1420,13 +1626,13 @@ external build_aggregate_ret : llvalue array -> llbuilder -> llvalue = "llvm_build_aggregate_ret" (** [build_br bb b] creates a - [b %bb] + [br %bb] instruction at the position specified by the instruction builder [b]. See the method [llvm::LLVMBuilder::CreateBr]. *) external build_br : llbasicblock -> llbuilder -> llvalue = "llvm_build_br" (** [build_cond_br cond tbb fbb b] creates a - [b %cond, %tbb, %fbb] + [br %cond, %tbb, %fbb] instruction at the position specified by the instruction builder [b]. See the method [llvm::LLVMBuilder::CreateCondBr]. *) external build_cond_br : llvalue -> llbasicblock -> llbasicblock -> llbuilder -> @@ -1446,6 +1652,20 @@ external build_switch : llvalue -> llbasicblock -> int -> llbuilder -> llvalue external add_case : llvalue -> llvalue -> llbasicblock -> unit = "llvm_add_case" +(** [build_indirect_br addr count b] creates a + [indirectbr %addr] + instruction at the position specified by the instruction builder [b] with + space reserved for [count] destinations. + See the method [llvm::LLVMBuilder::CreateIndirectBr]. *) +external build_indirect_br : llvalue -> int -> llbuilder -> llvalue + = "llvm_build_indirect_br" + +(** [add_destination br bb] adds the basic block [bb] as a possible branch + location for the indirectbr instruction [br]. + See the method [llvm::IndirectBrInst::addDestination]. **) +external add_destination : llvalue -> llbasicblock -> unit + = "llvm_add_destination" + (** [build_invoke fn args tobb unwindbb name b] creates an [%name = invoke %fn(args) to %tobb unwind %unwindbb] instruction at the position specified by the instruction builder [b]. @@ -1476,13 +1696,20 @@ external build_unreachable : llbuilder -> llvalue = "llvm_build_unreachable" external build_add : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_add" -(** [build_nswadd x y name b] creates a +(** [build_nsw_add x y name b] creates a [%name = nsw add %x, %y] instruction at the position specified by the instruction builder [b]. See the method [llvm::LLVMBuilder::CreateNSWAdd]. *) external build_nsw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_nsw_add" +(** [build_nuw_add x y name b] creates a + [%name = nuw add %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWAdd]. *) +external build_nuw_add : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_add" + (** [build_fadd x y name b] creates a [%name = fadd %x, %y] instruction at the position specified by the instruction builder [b]. @@ -1497,6 +1724,20 @@ external build_fadd : llvalue -> llvalue -> string -> llbuilder -> llvalue external build_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_sub" +(** [build_nsw_sub x y name b] creates a + [%name = nsw sub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNSWSub]. *) +external build_nsw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_sub" + +(** [build_nuw_sub x y name b] creates a + [%name = nuw sub %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWSub]. *) +external build_nuw_sub : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_sub" + (** [build_fsub x y name b] creates a [%name = fsub %x, %y] instruction at the position specified by the instruction builder [b]. @@ -1511,6 +1752,20 @@ external build_fsub : llvalue -> llvalue -> string -> llbuilder -> llvalue external build_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_mul" +(** [build_nsw_mul x y name b] creates a + [%name = nsw mul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNSWMul]. *) +external build_nsw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_mul" + +(** [build_nuw_mul x y name b] creates a + [%name = nuw mul %x, %y] + instruction at the position specified by the instruction builder [b]. + See the method [llvm::LLVMBuilder::CreateNUWMul]. *) +external build_nuw_mul : llvalue -> llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_mul" + (** [build_fmul x y name b] creates a [%name = fmul %x, %y] instruction at the position specified by the instruction builder [b]. @@ -1617,6 +1872,30 @@ external build_xor : llvalue -> llvalue -> string -> llbuilder -> llvalue external build_neg : llvalue -> string -> llbuilder -> llvalue = "llvm_build_neg" +(** [build_nsw_neg x name b] creates a + [%name = nsw sub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateNeg]. *) +external build_nsw_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nsw_neg" + +(** [build_nuw_neg x name b] creates a + [%name = nuw sub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateNeg]. *) +external build_nuw_neg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_nuw_neg" + +(** [build_fneg x name b] creates a + [%name = fsub 0, %x] + instruction at the position specified by the instruction builder [b]. + [-0.0] is used for floating point types to compute the correct sign. + See the method [llvm::LLVMBuilder::CreateFNeg]. *) +external build_fneg : llvalue -> string -> llbuilder -> llvalue + = "llvm_build_fneg" + (** [build_xor x name b] creates a [%name = xor %x, -1] instruction at the position specified by the instruction builder [b]. @@ -1628,20 +1907,6 @@ external build_not : llvalue -> string -> llbuilder -> llvalue (** {7 Memory} *) -(** [build_malloc ty name b] creates a - [%name = malloc %ty] - instruction at the position specified by the instruction builder [b]. - See the method [llvm::LLVMBuilder::CreateAlloca]. *) -external build_malloc : lltype -> string -> llbuilder -> llvalue - = "llvm_build_malloc" - -(** [build_array_malloc ty n name b] creates a - [%name = malloc %ty, %n] - instruction at the position specified by the instruction builder [b]. - See the method [llvm::LLVMBuilder::CreateMalloc]. *) -external build_array_malloc : lltype -> llvalue -> string -> llbuilder -> - llvalue = "llvm_build_array_malloc" - (** [build_alloca ty name b] creates a [%name = alloca %ty] instruction at the position specified by the instruction builder [b]. @@ -1656,12 +1921,6 @@ external build_alloca : lltype -> string -> llbuilder -> llvalue external build_array_alloca : lltype -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_array_alloca" -(** [build_free v b] creates a - [free %v] - instruction at the position specified by the instruction builder [b]. - See the method [llvm::LLVMBuilder::CreateFree]. *) -external build_free : llvalue -> llbuilder -> llvalue = "llvm_build_free" - (** [build_load v name b] creates a [%name = load %v] instruction at the position specified by the instruction builder [b]. @@ -1938,20 +2197,6 @@ external build_is_not_null : llvalue -> string -> llbuilder -> llvalue external build_ptrdiff : llvalue -> llvalue -> string -> llbuilder -> llvalue = "llvm_build_ptrdiff" -(** {6 Module providers} *) - -module ModuleProvider : sig - (** [create_module_provider m] encapsulates [m] in a module provider and takes - ownership of the module. See the constructor - [llvm::ExistingModuleProvider::ExistingModuleProvider]. *) - external create : llmodule -> llmoduleprovider - = "LLVMCreateModuleProviderForExistingModule" - - (** [dispose_module_provider mp] destroys the module provider [mp] as well as - the contained module. *) - external dispose : llmoduleprovider -> unit = "llvm_dispose_module_provider" -end - (** {6 Memory buffers} *) @@ -1983,12 +2228,12 @@ module PassManager : sig See the constructor of [llvm::PassManager]. *) external create : unit -> [ `Module ] t = "llvm_passmanager_create" - (** [PassManager.create_function mp] constructs a new function-by-function - pass pipeline over the module provider [mp]. It does not take ownership of - [mp]. This type of pipeline is suitable for code generation and JIT - compilation tasks. + (** [PassManager.create_function m] constructs a new function-by-function + pass pipeline over the module [m]. It does not take ownership of [m]. + This type of pipeline is suitable for code generation and JIT compilation + tasks. See the constructor of [llvm::FunctionPassManager]. *) - external create_function : llmoduleprovider -> [ `Function ] t + external create_function : llmodule -> [ `Function ] t = "LLVMCreateFunctionPassManager" (** [run_module m pm] initializes, executes on the module [m], and finalizes @@ -2018,7 +2263,7 @@ module PassManager : sig external finalize : [ `Function ] t -> bool = "llvm_passmanager_finalize" (** Frees the memory of a pass pipeline. For function pipelines, does not free - the module provider. + the module. See the destructor of [llvm::BasePassManager]. *) external dispose : [< any ] t -> unit = "llvm_passmanager_dispose" end diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index 8fdcac5c19..d526a05a51 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -110,6 +110,13 @@ CAMLprim LLVMContextRef llvm_global_context(value Unit) { return LLVMGetGlobalContext(); } +/* llcontext -> string -> int */ +CAMLprim value llvm_mdkind_id(LLVMContextRef C, value Name) { + unsigned MDKindID = LLVMGetMDKindIDInContext(C, String_val(Name), + caml_string_length(Name)); + return Val_int(MDKindID); +} + /*===-- Modules -----------------------------------------------------------===*/ /* llcontext -> string -> llmodule */ @@ -157,6 +164,18 @@ CAMLprim value llvm_delete_type_name(value Name, LLVMModuleRef M) { return Val_unit; } +/* llmodule -> string -> lltype option */ +CAMLprim value llvm_type_by_name(LLVMModuleRef M, value Name) { + CAMLparam1(Name); + LLVMTypeRef T; + if ((T = LLVMGetTypeByName(M, String_val(Name)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) T; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + /* llmodule -> unit */ CAMLprim value llvm_dump_module(LLVMModuleRef M) { LLVMDumpModule(M); @@ -283,7 +302,7 @@ CAMLprim LLVMTypeRef llvm_packed_struct_type(LLVMContextRef C, } /* lltype -> lltype array */ -CAMLprim value llvm_element_types(LLVMTypeRef StructTy) { +CAMLprim value llvm_struct_element_types(LLVMTypeRef StructTy) { value Tys = alloc(LLVMCountStructElementTypes(StructTy), 0); LLVMGetStructElementTypes(StructTy, (LLVMTypeRef *) Tys); return Tys; @@ -294,6 +313,21 @@ CAMLprim value llvm_is_packed(LLVMTypeRef StructTy) { return Val_bool(LLVMIsPackedStruct(StructTy)); } +/*--... Operations on union types ..........................................--*/ + +/* llcontext -> lltype array -> lltype */ +CAMLprim LLVMTypeRef llvm_union_type(LLVMContextRef C, value ElementTypes) { + return LLVMUnionTypeInContext(C, (LLVMTypeRef *) ElementTypes, + Wosize_val(ElementTypes)); +} + +/* lltype -> lltype array */ +CAMLprim value llvm_union_element_types(LLVMTypeRef UnionTy) { + value Tys = alloc(LLVMCountUnionElementTypes(UnionTy), 0); + LLVMGetUnionElementTypes(UnionTy, (LLVMTypeRef *) Tys); + return Tys; +} + /*--... Operations on array, pointer, and vector types .....................--*/ /* lltype -> int -> lltype */ @@ -406,6 +440,13 @@ CAMLprim value llvm_dump_value(LLVMValueRef Val) { return Val_unit; } +/*--... Operations on users ................................................--*/ + +/* llvalue -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_operand(LLVMValueRef V, value I) { + return LLVMGetOperand(V, Int_val(I)); +} + /*--... Operations on constants of (mostly) any type .......................--*/ /* llvalue -> bool */ @@ -423,6 +464,52 @@ CAMLprim value llvm_is_undef(LLVMValueRef Val) { return Val_bool(LLVMIsUndef(Val)); } +/*--... Operations on instructions .........................................--*/ + +/* llvalue -> bool */ +CAMLprim value llvm_has_metadata(LLVMValueRef Val) { + return Val_bool(LLVMHasMetadata(Val)); +} + +/* llvalue -> int -> llvalue option */ +CAMLprim value llvm_metadata(LLVMValueRef Val, value MDKindID) { + CAMLparam1(MDKindID); + LLVMValueRef MD; + if ((MD = LLVMGetMetadata(Val, Int_val(MDKindID)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) MD; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llvalue -> int -> llvalue -> unit */ +CAMLprim value llvm_set_metadata(LLVMValueRef Val, value MDKindID, + LLVMValueRef MD) { + LLVMSetMetadata(Val, Int_val(MDKindID), MD); + return Val_unit; +} + +/* llvalue -> int -> unit */ +CAMLprim value llvm_clear_metadata(LLVMValueRef Val, value MDKindID) { + LLVMSetMetadata(Val, Int_val(MDKindID), NULL); + return Val_unit; +} + + +/*--... Operations on metadata .............................................--*/ + +/* llcontext -> string -> llvalue */ +CAMLprim LLVMValueRef llvm_mdstring(LLVMContextRef C, value S) { + return LLVMMDStringInContext(C, String_val(S), caml_string_length(S)); +} + +/* llcontext -> llvalue array -> llvalue */ +CAMLprim LLVMValueRef llvm_mdnode(LLVMContextRef C, value ElementVals) { + return LLVMMDNodeInContext(C, (LLVMValueRef*) Op_val(ElementVals), + Wosize_val(ElementVals)); +} + /*--... Operations on scalar constants .....................................--*/ /* lltype -> int -> llvalue */ @@ -561,6 +648,14 @@ CAMLprim LLVMValueRef llvm_const_insertvalue(LLVMValueRef Aggregate, CAMLreturnT(LLVMValueRef, result); } +/* lltype -> string -> string -> bool -> bool -> llvalue */ +CAMLprim LLVMValueRef llvm_const_inline_asm(LLVMTypeRef Ty, value Asm, + value Constraints, value HasSideEffects, + value IsAlignStack) { + return LLVMConstInlineAsm(Ty, String_val(Asm), String_val(Constraints), + Bool_val(HasSideEffects), Bool_val(IsAlignStack)); +} + /*--... Operations on global variables, functions, and aliases (globals) ...--*/ /* llvalue -> bool */ @@ -612,6 +707,42 @@ CAMLprim value llvm_set_alignment(value Bytes, LLVMValueRef Global) { return Val_unit; } +/*--... Operations on uses .................................................--*/ + +/* llvalue -> lluse option */ +CAMLprim value llvm_use_begin(LLVMValueRef Val) { + CAMLparam0(); + LLVMUseRef First; + if ((First = LLVMGetFirstUse(Val))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) First; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* lluse -> lluse option */ +CAMLprim value llvm_use_succ(LLVMUseRef U) { + CAMLparam0(); + LLVMUseRef Next; + if ((Next = LLVMGetNextUse(U))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) Next; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* lluse -> llvalue */ +CAMLprim LLVMValueRef llvm_user(LLVMUseRef UR) { + return LLVMGetUser(UR); +} + +/* lluse -> llvalue */ +CAMLprim LLVMValueRef llvm_used_value(LLVMUseRef UR) { + return LLVMGetUsedValue(UR); +} + /*--... Operations on global variables .....................................--*/ DEFINE_ITERATORS(global, Global, LLVMModuleRef, LLVMValueRef, @@ -629,6 +760,20 @@ CAMLprim LLVMValueRef llvm_declare_global(LLVMTypeRef Ty, value Name, return LLVMAddGlobal(M, Ty, String_val(Name)); } +/* lltype -> string -> int -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_declare_qualified_global(LLVMTypeRef Ty, value Name, + value AddressSpace, + LLVMModuleRef M) { + LLVMValueRef GlobalVar; + if ((GlobalVar = LLVMGetNamedGlobal(M, String_val(Name)))) { + if (LLVMGetElementType(LLVMTypeOf(GlobalVar)) != Ty) + return LLVMConstBitCast(GlobalVar, + LLVMPointerType(Ty, Int_val(AddressSpace))); + return GlobalVar; + } + return LLVMAddGlobal(M, Ty, String_val(Name)); +} + /* string -> llmodule -> llvalue option */ CAMLprim value llvm_lookup_global(value Name, LLVMModuleRef M) { CAMLparam1(Name); @@ -650,6 +795,19 @@ CAMLprim LLVMValueRef llvm_define_global(value Name, LLVMValueRef Initializer, return GlobalVar; } +/* string -> llvalue -> int -> llmodule -> llvalue */ +CAMLprim LLVMValueRef llvm_define_qualified_global(value Name, + LLVMValueRef Initializer, + value AddressSpace, + LLVMModuleRef M) { + LLVMValueRef GlobalVar = LLVMAddGlobalInAddressSpace(M, + LLVMTypeOf(Initializer), + String_val(Name), + Int_val(AddressSpace)); + LLVMSetInitializer(GlobalVar, Initializer); + return GlobalVar; +} + /* llvalue -> unit */ CAMLprim value llvm_delete_global(LLVMValueRef GlobalVar) { LLVMDeleteGlobal(GlobalVar); @@ -692,6 +850,13 @@ CAMLprim value llvm_set_global_constant(value Flag, LLVMValueRef GlobalVar) { return Val_unit; } +/*--... Operations on aliases ..............................................--*/ + +CAMLprim LLVMValueRef llvm_add_alias(LLVMModuleRef M, LLVMTypeRef Ty, + LLVMValueRef Aliasee, value Name) { + return LLVMAddAlias(M, Ty, Aliasee, String_val(Name)); +} + /*--... Operations on functions ............................................--*/ DEFINE_ITERATORS(function, Function, LLVMModuleRef, LLVMValueRef, @@ -978,7 +1143,7 @@ CAMLprim value llvm_position_builder(value Pos, value B) { } /* llbuilder -> llbasicblock */ -CAMLprim LLVMBasicBlockRef llvm_insertion_block(LLVMBuilderRef B) { +CAMLprim LLVMBasicBlockRef llvm_insertion_block(value B) { LLVMBasicBlockRef InsertBlock = LLVMGetInsertBlock(Builder_val(B)); if (!InsertBlock) raise_not_found(); @@ -986,12 +1151,44 @@ CAMLprim LLVMBasicBlockRef llvm_insertion_block(LLVMBuilderRef B) { } /* llvalue -> string -> llbuilder -> unit */ -CAMLprim value llvm_insert_into_builder(LLVMValueRef I, value Name, - LLVMBuilderRef B) { - LLVMInsertIntoBuilderWithName(B, I, String_val(Name)); +CAMLprim value llvm_insert_into_builder(LLVMValueRef I, value Name, value B) { + LLVMInsertIntoBuilderWithName(Builder_val(B), I, String_val(Name)); + return Val_unit; +} + +/*--... Metadata ...........................................................--*/ + +/* llbuilder -> llvalue -> unit */ +CAMLprim value llvm_set_current_debug_location(value B, LLVMValueRef V) { + LLVMSetCurrentDebugLocation(Builder_val(B), V); return Val_unit; } +/* llbuilder -> unit */ +CAMLprim value llvm_clear_current_debug_location(value B) { + LLVMSetCurrentDebugLocation(Builder_val(B), NULL); + return Val_unit; +} + +/* llbuilder -> llvalue option */ +CAMLprim value llvm_current_debug_location(value B) { + CAMLparam0(); + LLVMValueRef L; + if ((L = LLVMGetCurrentDebugLocation(Builder_val(B)))) { + value Option = alloc(1, 0); + Field(Option, 0) = (value) L; + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llbuilder -> llvalue -> unit */ +CAMLprim value llvm_set_inst_debug_location(value B, LLVMValueRef V) { + LLVMSetInstDebugLocation(Builder_val(B), V); + return Val_unit; +} + + /*--... Terminators ........................................................--*/ /* llbuilder -> llvalue */ @@ -1031,13 +1228,27 @@ CAMLprim LLVMValueRef llvm_build_switch(LLVMValueRef Of, return LLVMBuildSwitch(Builder_val(B), Of, Else, Int_val(EstimatedCount)); } -CAMLprim value llvm_add_case(LLVMValueRef Switch, - LLVMValueRef OnVal, +/* llvalue -> llvalue -> llbasicblock -> unit */ +CAMLprim value llvm_add_case(LLVMValueRef Switch, LLVMValueRef OnVal, LLVMBasicBlockRef Dest) { LLVMAddCase(Switch, OnVal, Dest); return Val_unit; } +/* llvalue -> llbasicblock -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_indirect_br(LLVMValueRef Addr, + value EstimatedDests, + value B) { + return LLVMBuildIndirectBr(Builder_val(B), Addr, EstimatedDests); +} + +/* llvalue -> llvalue -> llbasicblock -> unit */ +CAMLprim value llvm_add_destination(LLVMValueRef IndirectBr, + LLVMBasicBlockRef Dest) { + LLVMAddDestination(IndirectBr, Dest); + return Val_unit; +} + /* llvalue -> llvalue array -> llbasicblock -> llbasicblock -> string -> llbuilder -> llvalue */ CAMLprim LLVMValueRef llvm_build_invoke_nat(LLVMValueRef Fn, value Args, @@ -1081,6 +1292,12 @@ CAMLprim LLVMValueRef llvm_build_nsw_add(LLVMValueRef LHS, LLVMValueRef RHS, return LLVMBuildNSWAdd(Builder_val(B), LHS, RHS, String_val(Name)); } +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_add(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWAdd(Builder_val(B), LHS, RHS, String_val(Name)); +} + /* llvalue -> llvalue -> string -> llbuilder -> llvalue */ CAMLprim LLVMValueRef llvm_build_fadd(LLVMValueRef LHS, LLVMValueRef RHS, value Name, value B) { @@ -1093,6 +1310,18 @@ CAMLprim LLVMValueRef llvm_build_sub(LLVMValueRef LHS, LLVMValueRef RHS, return LLVMBuildSub(Builder_val(B), LHS, RHS, String_val(Name)); } +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_sub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNSWSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_sub(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWSub(Builder_val(B), LHS, RHS, String_val(Name)); +} + /* llvalue -> llvalue -> string -> llbuilder -> llvalue */ CAMLprim LLVMValueRef llvm_build_fsub(LLVMValueRef LHS, LLVMValueRef RHS, value Name, value B) { @@ -1105,6 +1334,18 @@ CAMLprim LLVMValueRef llvm_build_mul(LLVMValueRef LHS, LLVMValueRef RHS, return LLVMBuildMul(Builder_val(B), LHS, RHS, String_val(Name)); } +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nsw_mul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNSWMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + +/* llvalue -> llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_mul(LLVMValueRef LHS, LLVMValueRef RHS, + value Name, value B) { + return LLVMBuildNUWMul(Builder_val(B), LHS, RHS, String_val(Name)); +} + /* llvalue -> llvalue -> string -> llbuilder -> llvalue */ CAMLprim LLVMValueRef llvm_build_fmul(LLVMValueRef LHS, LLVMValueRef RHS, value Name, value B) { @@ -1196,25 +1437,31 @@ CAMLprim LLVMValueRef llvm_build_neg(LLVMValueRef X, } /* llvalue -> string -> llbuilder -> llvalue */ -CAMLprim LLVMValueRef llvm_build_not(LLVMValueRef X, - value Name, value B) { - return LLVMBuildNot(Builder_val(B), X, String_val(Name)); +CAMLprim LLVMValueRef llvm_build_nsw_neg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNSWNeg(Builder_val(B), X, String_val(Name)); } -/*--... Memory .............................................................--*/ +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_nuw_neg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNUWNeg(Builder_val(B), X, String_val(Name)); +} -/* lltype -> string -> llbuilder -> llvalue */ -CAMLprim LLVMValueRef llvm_build_malloc(LLVMTypeRef Ty, - value Name, value B) { - return LLVMBuildMalloc(Builder_val(B), Ty, String_val(Name)); +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_fneg(LLVMValueRef X, + value Name, value B) { + return LLVMBuildFNeg(Builder_val(B), X, String_val(Name)); } -/* lltype -> llvalue -> string -> llbuilder -> llvalue */ -CAMLprim LLVMValueRef llvm_build_array_malloc(LLVMTypeRef Ty, LLVMValueRef Size, - value Name, value B) { - return LLVMBuildArrayMalloc(Builder_val(B), Ty, Size, String_val(Name)); +/* llvalue -> string -> llbuilder -> llvalue */ +CAMLprim LLVMValueRef llvm_build_not(LLVMValueRef X, + value Name, value B) { + return LLVMBuildNot(Builder_val(B), X, String_val(Name)); } +/*--... Memory .............................................................--*/ + /* lltype -> string -> llbuilder -> llvalue */ CAMLprim LLVMValueRef llvm_build_alloca(LLVMTypeRef Ty, value Name, value B) { @@ -1227,11 +1474,6 @@ CAMLprim LLVMValueRef llvm_build_array_alloca(LLVMTypeRef Ty, LLVMValueRef Size, return LLVMBuildArrayAlloca(Builder_val(B), Ty, Size, String_val(Name)); } -/* llvalue -> llbuilder -> llvalue */ -CAMLprim LLVMValueRef llvm_build_free(LLVMValueRef Pointer, value B) { - return LLVMBuildFree(Builder_val(B), Pointer); -} - /* llvalue -> string -> llbuilder -> llvalue */ CAMLprim LLVMValueRef llvm_build_load(LLVMValueRef Pointer, value Name, value B) { @@ -1510,14 +1752,6 @@ CAMLprim LLVMValueRef llvm_build_ptrdiff(LLVMValueRef LHS, LLVMValueRef RHS, return LLVMBuildPtrDiff(Builder_val(B), LHS, RHS, String_val(Name)); } -/*===-- Module Providers --------------------------------------------------===*/ - -/* llmoduleprovider -> unit */ -CAMLprim value llvm_dispose_module_provider(LLVMModuleProviderRef MP) { - LLVMDisposeModuleProvider(MP); - return Val_unit; -} - /*===-- Memory buffers ----------------------------------------------------===*/ diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml index b4563b716a..5699152b5a 100644 --- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml +++ b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml @@ -10,9 +10,38 @@ external add_constant_propagation : [ unit = "llvm_add_constant_propagation" -external add_instruction_combining : [ unit - = "llvm_add_instruction_combining" +external add_sccp : [ unit + = "llvm_add_sccp" +external add_dead_store_elimination : [ unit + = "llvm_add_dead_store_elimination" +external add_aggressive_dce : [ unit + = "llvm_add_aggressive_dce" +external +add_scalar_repl_aggregation : [ unit + = "llvm_add_scalar_repl_aggregation" +external add_ind_var_simplification : [ unit + = "llvm_add_ind_var_simplification" +external +add_instruction_combination : [ unit + = "llvm_add_instruction_combination" +external add_licm : [ unit + = "llvm_add_licm" +external add_loop_unswitch : [ unit + = "llvm_add_loop_unswitch" +external add_loop_unroll : [ unit + = "llvm_add_loop_unroll" +external add_loop_rotation : [ unit + = "llvm_add_loop_rotation" +external add_loop_index_split : [ unit + = "llvm_add_loop_index_split" external add_memory_to_register_promotion : [ unit @@ -21,12 +50,26 @@ external add_memory_to_register_demotion : [ unit = "llvm_add_memory_to_register_demotion" -external add_reassociation : [ unit +external add_reassociation : [ unit = "llvm_add_reassociation" -external add_gvn : [ unit - = "llvm_add_gvn" +external add_jump_threading : [ unit + = "llvm_add_jump_threading" external add_cfg_simplification : [ unit = "llvm_add_cfg_simplification" +external +add_tail_call_elimination : [ unit + = "llvm_add_tail_call_elimination" +external add_gvn : [ unit + = "llvm_add_gvn" +external add_memcpy_opt : [ unit + = "llvm_add_memcpy_opt" +external add_loop_deletion : [ unit + = "llvm_add_loop_deletion" +external +add_lib_call_simplification : [ unit + = "llvm_add_lib_call_simplification" diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli index 6fcce0432d..9f95fbce9f 100644 --- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli +++ b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli @@ -17,10 +17,59 @@ external add_constant_propagation : [ unit = "llvm_add_constant_propagation" +(** See the [llvm::createSCCPPass] function. *) +external add_sccp : [ unit + = "llvm_add_sccp" + +(** See [llvm::createDeadStoreEliminationPass] function. *) +external add_dead_store_elimination : [ unit + = "llvm_add_dead_store_elimination" + +(** See The [llvm::createAggressiveDCEPass] function. *) +external add_aggressive_dce : [ unit + = "llvm_add_aggressive_dce" + +(** See the [llvm::createScalarReplAggregatesPass] function. *) +external +add_scalar_repl_aggregation : [ unit + = "llvm_add_scalar_repl_aggregation" + +(** See the [llvm::createIndVarSimplifyPass] function. *) +external add_ind_var_simplification : [ unit + = "llvm_add_ind_var_simplification" + (** See the [llvm::createInstructionCombiningPass] function. *) -external add_instruction_combining : [ unit - = "llvm_add_instruction_combining" +external +add_instruction_combination : [ unit + = "llvm_add_instruction_combination" + +(** See the [llvm::createLICMPass] function. *) +external add_licm : [ unit + = "llvm_add_licm" + +(** See the [llvm::createLoopUnswitchPass] function. *) +external add_loop_unswitch : [ unit + = "llvm_add_loop_unswitch" + +(** See the [llvm::createLoopUnrollPass] function. *) +external add_loop_unroll : [ unit + = "llvm_add_loop_unroll" + +(** See the [llvm::createLoopRotatePass] function. *) +external add_loop_rotation : [ unit + = "llvm_add_loop_rotation" + +(** See the [llvm::createLoopIndexSplitPass] function. *) +external add_loop_index_split : [ unit + = "llvm_add_loop_index_split" (** See the [llvm::createPromoteMemoryToRegisterPass] function. *) external @@ -35,16 +84,40 @@ add_memory_to_register_demotion : [ unit +external add_reassociation : [ unit = "llvm_add_reassociation" -(** See the [llvm::createGVNPass] function. *) -external add_gvn : [ unit - = "llvm_add_gvn" +(** See the [llvm::createJumpThreadingPass] function. *) +external add_jump_threading : [ unit + = "llvm_add_jump_threading" (** See the [llvm::createCFGSimplificationPass] function. *) external add_cfg_simplification : [ unit = "llvm_add_cfg_simplification" + +(** See the [llvm::createTailCallEliminationPass] function. *) +external +add_tail_call_elimination : [ unit + = "llvm_add_tail_call_elimination" + +(** See the [llvm::createGVNPass] function. *) +external add_gvn : [ unit + = "llvm_add_gvn" + +(** See the [llvm::createMemCpyOptPass] function. *) +external add_memcpy_opt : [ unit + = "llvm_add_memcpy_opt" + +(** See the [llvm::createLoopDeletionPass] function. *) +external add_loop_deletion : [ unit + = "llvm_add_loop_deletion" + +(** See the [llvm::createSimplifyLibCallsPass] function. *) +external +add_lib_call_simplification : [ unit + = "llvm_add_lib_call_simplification" diff --git a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c index 87c1060984..c20bdde575 100644 --- a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c +++ b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c @@ -26,11 +26,71 @@ CAMLprim value llvm_add_constant_propagation(LLVMPassManagerRef PM) { } /* [ unit */ -CAMLprim value llvm_add_instruction_combining(LLVMPassManagerRef PM) { +CAMLprim value llvm_add_sccp(LLVMPassManagerRef PM) { + LLVMAddSCCPPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_dead_store_elimination(LLVMPassManagerRef PM) { + LLVMAddDeadStoreEliminationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_aggressive_dce(LLVMPassManagerRef PM) { + LLVMAddAggressiveDCEPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_scalar_repl_aggregation(LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_ind_var_simplification(LLVMPassManagerRef PM) { + LLVMAddIndVarSimplifyPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_instruction_combination(LLVMPassManagerRef PM) { LLVMAddInstructionCombiningPass(PM); return Val_unit; } +/* [ unit */ +CAMLprim value llvm_add_licm(LLVMPassManagerRef PM) { + LLVMAddLICMPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) { + LLVMAddLoopUnrollPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_unroll(LLVMPassManagerRef PM) { + LLVMAddLoopUnrollPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_rotation(LLVMPassManagerRef PM) { + LLVMAddLoopRotatePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_index_split(LLVMPassManagerRef PM) { + LLVMAddLoopIndexSplitPass(PM); + return Val_unit; +} + /* [ unit */ CAMLprim value llvm_add_memory_to_register_promotion(LLVMPassManagerRef PM) { LLVMAddPromoteMemoryToRegisterPass(PM); @@ -50,8 +110,8 @@ CAMLprim value llvm_add_reassociation(LLVMPassManagerRef PM) { } /* [ unit */ -CAMLprim value llvm_add_gvn(LLVMPassManagerRef PM) { - LLVMAddGVNPass(PM); +CAMLprim value llvm_add_jump_threading(LLVMPassManagerRef PM) { + LLVMAddJumpThreadingPass(PM); return Val_unit; } @@ -60,3 +120,33 @@ CAMLprim value llvm_add_cfg_simplification(LLVMPassManagerRef PM) { LLVMAddCFGSimplificationPass(PM); return Val_unit; } + +/* [ unit */ +CAMLprim value llvm_add_tail_call_elimination(LLVMPassManagerRef PM) { + LLVMAddTailCallEliminationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_gvn(LLVMPassManagerRef PM) { + LLVMAddGVNPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_memcpy_opt(LLVMPassManagerRef PM) { + LLVMAddMemCpyOptPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) { + LLVMAddLoopDeletionPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_lib_call_simplification(LLVMPassManagerRef PM) { + LLVMAddSimplifyLibCallsPass(PM); + return Val_unit; +} diff --git a/clear_tblgen_vars.mk b/clear_tblgen_vars.mk new file mode 100644 index 0000000000..6c9623e427 --- /dev/null +++ b/clear_tblgen_vars.mk @@ -0,0 +1,2 @@ +TBLGEN_TABLES := +TBLGEN_TD_DIR := diff --git a/configure b/configure index 88050f310c..2b597a12db 100755 --- a/configure +++ b/configure @@ -689,12 +689,16 @@ TARGET_HAS_JIT ENABLE_DOXYGEN ENABLE_THREADS ENABLE_PIC +ENABLE_SHARED TARGETS_TO_BUILD LLVM_ENUM_TARGETS LLVM_ENUM_ASM_PRINTERS LLVM_ENUM_ASM_PARSERS LLVM_ENUM_DISASSEMBLERS ENABLE_CBE_PRINTF_A +CLANGPATH +CLANGXXPATH +ENABLE_BUILT_CLANG OPTIMIZE_OPTION EXTRA_OPTIONS BINUTILS_INCDIR @@ -754,6 +758,7 @@ LLVMGCCCOMMAND LLVMGXXCOMMAND LLVMGCC LLVMGXX +LLVMCC_OPTION NO_VARIADIC_MACROS NO_MISSING_FIELD_INITIALIZERS USE_UDIS86 @@ -764,11 +769,9 @@ MMAP_FILE LLVMCC1 LLVMCC1PLUS LLVMGCCDIR -LLVMGCCLIBEXEC -LLVMGCC_VERSION -LLVMGCC_MAJVERS LLVMGCC_LANGS SHLIBEXT +SHLIBPATH_VAR LLVM_PREFIX LLVM_BINDIR LLVM_LIBDIR @@ -810,6 +813,7 @@ projects/llvm-java projects/llvm-tv projects/llvm-poolalloc projects/poolalloc +projects/safecode projects/llvm-kernel' # Initialize some variables set by options. @@ -1401,6 +1405,8 @@ Optional Features: --enable-threads Use threads if available (default is YES) --enable-pic Build LLVM with Position Independent Code (default is YES) + --enable-shared Build a shared library and link tools against it + (default is NO) --enable-targets Build specific host targets: all or target1,target2,... Valid targets are: host, x86, x86_64, sparc, powerpc, alpha, arm, mips, spu, @@ -1426,6 +1432,10 @@ Optional Packages: searches PATH) --with-llvmgxx Specify location of llvm-g++ driver (default searches PATH) + --with-clang Specify location of clang compiler (default is + --with-built-clang) + --with-built-clang Use the compiled Clang as the LLVM compiler + (default=check) --with-optimize-option Select the compiler options to use for optimized builds --with-extra-options Specify additional options to compile LLVM with @@ -1442,6 +1452,8 @@ Optional Packages: --with-binutils-include Specify path to binutils/include/ containing plugin-api.h file for gold plugin. --with-tclinclude directory where tcl headers are + --with-llvmcc= Choose the LLVM capable compiler to use (llvm-gcc, + clang, or none; default=check) --with-udis86= Use udis86 external x86 disassembler library --with-oprofile= Tell OProfile >= 0.9.4 how to symbolize JIT output @@ -1967,6 +1979,8 @@ do llvm-poolalloc) subdirs="$subdirs projects/llvm-poolalloc" ;; poolalloc) subdirs="$subdirs projects/poolalloc" + ;; + safecode) subdirs="$subdirs projects/safecode" ;; llvm-kernel) subdirs="$subdirs projects/llvm-kernel" ;; @@ -2320,6 +2334,7 @@ else msp430-*) llvm_cv_target_arch="MSP430" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;; bfin-*) llvm_cv_target_arch="Blackfin" ;; + mblaze-*) llvm_cv_target_arch="MBlaze" ;; *) llvm_cv_target_arch="Unknown" ;; esac fi @@ -4784,6 +4799,8 @@ else SystemZ) TARGET_HAS_JIT=0 ;; Blackfin) TARGET_HAS_JIT=0 + ;; + MBlaze) TARGET_HAS_JIT=0 ;; *) TARGET_HAS_JIT=0 ;; @@ -4857,6 +4874,25 @@ cat >>confdefs.h <<_ACEOF _ACEOF +# Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then + enableval=$enable_shared; +else + enableval=default +fi + +case "$enableval" in + yes) ENABLE_SHARED=1 + ;; + no) ENABLE_SHARED=0 + ;; + default) ENABLE_SHARED=0 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-shared. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-shared. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + TARGETS_TO_BUILD="" # Check whether --enable-targets was given. if test "${enable_targets+set}" = set; then @@ -4869,7 +4905,7 @@ if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend MSIL CppBackend MBlaze" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -4888,6 +4924,7 @@ case "$enableval" in cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; msil) TARGETS_TO_BUILD="MSIL $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; + mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; host) case "$llvm_cv_target_arch" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -4896,6 +4933,7 @@ case "$enableval" in Alpha) TARGETS_TO_BUILD="Alpha $TARGETS_TO_BUILD" ;; ARM) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;; Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;; + MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; PIC16) TARGETS_TO_BUILD="PIC16 $TARGETS_TO_BUILD" ;; XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; @@ -5029,6 +5067,69 @@ echo "$as_me: error: Invalid llvm-gcc. Use --with-llvmgcc when --with-llvmgxx is fi +# Check whether --with-clang was given. +if test "${with_clang+set}" = set; then + withval=$with_clang; +else + with_clang=default +fi + + + +# Check whether --with-built-clang was given. +if test "${with_built_clang+set}" = set; then + withval=$with_built_clang; +else + with_built_clang=check +fi + + +{ echo "$as_me:$LINENO: checking clang compiler" >&5 +echo $ECHO_N "checking clang compiler... $ECHO_C" >&6; } +WITH_CLANGPATH="" +WITH_BUILT_CLANG=0 +if test "$with_clang" != "default"; then + WITH_CLANGPATH="$with_clang" + if ! test -x "$WITH_CLANGPATH"; then + { { echo "$as_me:$LINENO: error: invalid --with-clang, path does not specify an executable" >&5 +echo "$as_me: error: invalid --with-clang, path does not specify an executable" >&2;} + { (exit 1); exit 1; }; } + fi +elif test "$with_built_clang" = "yes"; then + WITH_BUILT_CLANG=1 +elif test "$with_built_clang" = "no"; then + WITH_BUILT_CLANG=0 +else + if test "$with_built_clang" != "check"; then + { { echo "$as_me:$LINENO: error: invalid value for --with-built-clang." >&5 +echo "$as_me: error: invalid value for --with-built-clang." >&2;} + { (exit 1); exit 1; }; } + fi + + if test -f ${srcdir}/tools/clang/README.txt; then + WITH_BUILT_CLANG=1 + fi +fi + +if ! test -z "$WITH_CLANGPATH"; then + { echo "$as_me:$LINENO: result: $WITH_CLANGPATH" >&5 +echo "${ECHO_T}$WITH_CLANGPATH" >&6; } + WITH_CLANGXXPATH=`"$WITH_CLANGPATH" --print-prog-name=clang++` +elif test "$WITH_BUILT_CLANG" = "1"; then + { echo "$as_me:$LINENO: result: built" >&5 +echo "${ECHO_T}built" >&6; } +else + { echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6; } +fi +CLANGPATH=$WITH_CLANGPATH + +CLANGXXPATH=$WITH_CLANGXXPATH + +ENABLE_BUILT_CLANG=$WITH_BUILT_CLANG + + + # Check whether --with-optimize-option was given. if test "${with_optimize_option+set}" = set; then withval=$with_optimize_option; @@ -11035,7 +11136,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <&5 +echo $ECHO_N "checking LLVM capable compiler... $ECHO_C" >&6; } +if test "$with_llvmcc" != "check"; then + if (test "$with_llvmcc" != "llvm-gcc" && + test "$with_llvmcc" != "clang" && + test "$with_llvmcc" != "none"); then + { { echo "$as_me:$LINENO: error: invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'." >&5 +echo "$as_me: error: invalid value for --with-llvmcc, expected 'llvm-gcc', 'clang', or 'none'." >&2;} + { (exit 1); exit 1; }; } + fi + WITH_LLVMCC="$with_llvmcc" +elif test -n "$LLVMGCC"; then + WITH_LLVMCC=llvm-gcc +elif test -n "$WITH_CLANGPATH" || test "$WITH_BUILT_CLANG" -ne "0"; then + WITH_LLVMCC=clang +else + WITH_LLVMCC=none +fi +{ echo "$as_me:$LINENO: result: $WITH_LLVMCC" >&5 +echo "${ECHO_T}$WITH_LLVMCC" >&6; } +LLVMCC_OPTION=$WITH_LLVMCC + + { echo "$as_me:$LINENO: checking tool compatibility" >&5 echo $ECHO_N "checking tool compatibility... $ECHO_C" >&6; } @@ -16413,6 +16544,7 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + ac_save_CXXFLAGS=$CXXFLAGS CXXFLAGS=-pedantic if test "$cross_compiling" = yes; then ac_cv_huge_val_sanity=yes @@ -16465,6 +16597,7 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$a fi + CXXFLAGS=$ac_save_CXXFLAGS ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -19576,15 +19709,6 @@ echo $ECHO_N "checking llvm-gcc component support... $ECHO_C" >&6; } llvmgccdir=`echo "$llvmcc1path" | sed 's,/libexec/.*,,'` LLVMGCCDIR=$llvmgccdir - llvmgcclibexec=`echo "$llvmcc1path" | sed 's,/cc1,,'` - LLVMGCCLIBEXEC=$llvmgcclibexec - - llvmgccversion=`"$LLVMGCC" -dumpversion 2>&1 | sed 's/^\([0-9.]*\).*/\1/'` - llvmgccmajvers=`echo $llvmgccversion | sed 's/^\([0-9]\).*/\1/'` - LLVMGCC_VERSION=$llvmgccversion - - LLVMGCC_MAJVERS=$llvmgccmajvers - llvmgcclangs=`"$LLVMGCC" -v --help 2>&1 | grep '^Configured with:' | sed 's/^.*--enable-languages=\([^ ]*\).*/\1/'` LLVMGCC_LANGS=$llvmgcclangs @@ -19595,6 +19719,9 @@ fi SHLIBEXT=$libltdl_cv_shlibext +SHLIBPATH_VAR=$libltdl_cv_shlibpath_var + + # Translate the various configuration directories and other basic # information into substitutions that will end up in Makefile.config.in # that these configured values can be used by the makefiles @@ -19605,7 +19732,7 @@ eval LLVM_PREFIX="${prefix}"; eval LLVM_BINDIR="${prefix}/bin"; eval LLVM_LIBDIR="${prefix}/lib"; eval LLVM_DATADIR="${prefix}/share/llvm"; -eval LLVM_DOCSDIR="${prefix}/docs/llvm"; +eval LLVM_DOCSDIR="${prefix}/share/doc/llvm"; eval LLVM_ETCDIR="${prefix}/etc/llvm"; eval LLVM_INCLUDEDIR="${prefix}/include"; eval LLVM_INFODIR="${prefix}/info"; @@ -20652,16 +20779,16 @@ TARGET_HAS_JIT!$TARGET_HAS_JIT$ac_delim ENABLE_DOXYGEN!$ENABLE_DOXYGEN$ac_delim ENABLE_THREADS!$ENABLE_THREADS$ac_delim ENABLE_PIC!$ENABLE_PIC$ac_delim +ENABLE_SHARED!$ENABLE_SHARED$ac_delim TARGETS_TO_BUILD!$TARGETS_TO_BUILD$ac_delim LLVM_ENUM_TARGETS!$LLVM_ENUM_TARGETS$ac_delim LLVM_ENUM_ASM_PRINTERS!$LLVM_ENUM_ASM_PRINTERS$ac_delim LLVM_ENUM_ASM_PARSERS!$LLVM_ENUM_ASM_PARSERS$ac_delim LLVM_ENUM_DISASSEMBLERS!$LLVM_ENUM_DISASSEMBLERS$ac_delim ENABLE_CBE_PRINTF_A!$ENABLE_CBE_PRINTF_A$ac_delim -OPTIMIZE_OPTION!$OPTIMIZE_OPTION$ac_delim -EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim -BINUTILS_INCDIR!$BINUTILS_INCDIR$ac_delim -ENABLE_LLVMC_DYNAMIC!$ENABLE_LLVMC_DYNAMIC$ac_delim +CLANGPATH!$CLANGPATH$ac_delim +CLANGXXPATH!$CLANGXXPATH$ac_delim +ENABLE_BUILT_CLANG!$ENABLE_BUILT_CLANG$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -20703,6 +20830,10 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +OPTIMIZE_OPTION!$OPTIMIZE_OPTION$ac_delim +EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim +BINUTILS_INCDIR!$BINUTILS_INCDIR$ac_delim +ENABLE_LLVMC_DYNAMIC!$ENABLE_LLVMC_DYNAMIC$ac_delim ENABLE_LLVMC_DYNAMIC_PLUGINS!$ENABLE_LLVMC_DYNAMIC_PLUGINS$ac_delim CXX!$CXX$ac_delim CXXFLAGS!$CXXFLAGS$ac_delim @@ -20758,6 +20889,7 @@ LLVMGCCCOMMAND!$LLVMGCCCOMMAND$ac_delim LLVMGXXCOMMAND!$LLVMGXXCOMMAND$ac_delim LLVMGCC!$LLVMGCC$ac_delim LLVMGXX!$LLVMGXX$ac_delim +LLVMCC_OPTION!$LLVMCC_OPTION$ac_delim NO_VARIADIC_MACROS!$NO_VARIADIC_MACROS$ac_delim NO_MISSING_FIELD_INITIALIZERS!$NO_MISSING_FIELD_INITIALIZERS$ac_delim USE_UDIS86!$USE_UDIS86$ac_delim @@ -20768,11 +20900,9 @@ MMAP_FILE!$MMAP_FILE$ac_delim LLVMCC1!$LLVMCC1$ac_delim LLVMCC1PLUS!$LLVMCC1PLUS$ac_delim LLVMGCCDIR!$LLVMGCCDIR$ac_delim -LLVMGCCLIBEXEC!$LLVMGCCLIBEXEC$ac_delim -LLVMGCC_VERSION!$LLVMGCC_VERSION$ac_delim -LLVMGCC_MAJVERS!$LLVMGCC_MAJVERS$ac_delim LLVMGCC_LANGS!$LLVMGCC_LANGS$ac_delim SHLIBEXT!$SHLIBEXT$ac_delim +SHLIBPATH_VAR!$SHLIBPATH_VAR$ac_delim LLVM_PREFIX!$LLVM_PREFIX$ac_delim LLVM_BINDIR!$LLVM_BINDIR$ac_delim LLVM_LIBDIR!$LLVM_LIBDIR$ac_delim @@ -20793,7 +20923,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 88; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 91; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/device/include/llvm/Config/AsmParsers.def b/device/include/llvm/Config/AsmParsers.def new file mode 100644 index 0000000000..d0093514a2 --- /dev/null +++ b/device/include/llvm/Config/AsmParsers.def @@ -0,0 +1,29 @@ +//===- llvm/Config/AsmParsers.def - LLVM Assembly Parsers -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language parsers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PARSER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly parsers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASM_PARSER +# error Please define the macro LLVM_ASM_PARSER(TargetName) +#endif + +LLVM_ASM_PARSER(ARM) + +#undef LLVM_ASM_PARSER diff --git a/device/include/llvm/Config/AsmPrinters.def b/device/include/llvm/Config/AsmPrinters.def new file mode 100644 index 0000000000..6706bd3072 --- /dev/null +++ b/device/include/llvm/Config/AsmPrinters.def @@ -0,0 +1,29 @@ +//===- llvm/Config/AsmPrinters.def - LLVM Assembly Printers -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language printers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PRINTER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly printers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASM_PRINTER +# error Please define the macro LLVM_ASM_PRINTER(TargetName) +#endif + +LLVM_ASM_PRINTER(ARM) + +#undef LLVM_ASM_PRINTER diff --git a/device/include/llvm/Config/Disassemblers.def b/device/include/llvm/Config/Disassemblers.def new file mode 100644 index 0000000000..7221c15257 --- /dev/null +++ b/device/include/llvm/Config/Disassemblers.def @@ -0,0 +1,27 @@ +//===- llvm/Config/Disassemblers.def - LLVM Assembly Parsers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates all of the assembly-language parsers +// supported by this build of LLVM. Clients of this file should define +// the LLVM_ASM_PARSER macro to be a function-like macro with a +// single parameter (the name of the target whose assembly can be +// generated); including this file will then enumerate all of the +// targets with assembly parsers. +// +// The set of targets supported by LLVM is generated at configuration +// time, at which point this header is generated. Do not modify this +// header directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DISASSEMBLER +# error Please define the macro LLVM_DISASSEMBLER(TargetName) +#endif + +#undef LLVM_DISASSEMBLER diff --git a/device/include/llvm/Config/Targets.def b/device/include/llvm/Config/Targets.def new file mode 100644 index 0000000000..c50df96905 --- /dev/null +++ b/device/include/llvm/Config/Targets.def @@ -0,0 +1,28 @@ +/*===- llvm/Config/Targets.def - LLVM Target Architectures ------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file enumerates all of the target architectures supported by *| +|* this build of LLVM. Clients of this file should define the *| +|* LLVM_TARGET macro to be a function-like macro with a single *| +|* parameter (the name of the target); including this file will then *| +|* enumerate all of the targets. *| +|* *| +|* The set of targets supported by LLVM is generated at configuration *| +|* time, at which point this header is generated. Do not modify this *| +|* header directly. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_TARGET +# error Please define the macro LLVM_TARGET(TargetName) +#endif + +LLVM_TARGET(ARM) + +#undef LLVM_TARGET diff --git a/device/include/llvm/Config/config.h b/device/include/llvm/Config/config.h new file mode 100644 index 0000000000..d8128de76c --- /dev/null +++ b/device/include/llvm/Config/config.h @@ -0,0 +1,586 @@ +/* include/llvm/Config/config.h. Generated from config.h.in by configure. */ +/* include/llvm/Config/config.h.in. Generated from autoconf/configure.ac by autoheader. */ + +/* 32 bit multilib directory. */ +#define CXX_INCLUDE_32BIT_DIR "" + +/* 64 bit multilib directory. */ +#define CXX_INCLUDE_64BIT_DIR "" + +/* Arch the libstdc++ headers. */ +#define CXX_INCLUDE_ARCH "" + +/* Directory with the libstdc++ headers. */ +#define CXX_INCLUDE_ROOT "" + +/* Directories clang will search for headers */ +#define C_INCLUDE_DIRS "" + +/* Define if CBE is enabled for printf %a output */ +#define ENABLE_CBE_PRINTF_A 1 + +/* Define if position independent code is enabled */ +#define ENABLE_PIC 0 + +/* Define if threads enabled */ +#define ENABLE_THREADS 0 + +/* Define to 1 if you have the `argz_append' function. */ +#define HAVE_ARGZ_APPEND 1 + +/* Define to 1 if you have the `argz_create_sep' function. */ +#define HAVE_ARGZ_CREATE_SEP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARGZ_H 1 + +/* Define to 1 if you have the `argz_insert' function. */ +#define HAVE_ARGZ_INSERT 1 + +/* Define to 1 if you have the `argz_next' function. */ +#define HAVE_ARGZ_NEXT 1 + +/* Define to 1 if you have the `argz_stringify' function. */ +#define HAVE_ARGZ_STRINGIFY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ASSERT_H 1 + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the `bcopy' function. */ +/* #undef HAVE_BCOPY */ + +/* Define to 1 if you have the `ceilf' function. */ +#define HAVE_CEILF 1 + +/* Define if the neat program is available */ +/* #undef HAVE_CIRCO */ + +/* Define to 1 if you have the `closedir' function. */ +#define HAVE_CLOSEDIR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CTYPE_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#define HAVE_DIRENT_H 1 + +/* Define if you have the GNU dld library. */ +/* #undef HAVE_DLD */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLD_H */ + +/* Define to 1 if you have the `dlerror' function. */ +#define HAVE_DLERROR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define if dlopen() is available on this platform. */ +#define HAVE_DLOPEN 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DL_H */ + +/* Define if the dot program is available */ +/* #undef HAVE_DOT */ + +/* Define if the dotty program is available */ +/* #undef HAVE_DOTTY */ + +/* Define if you have the _dyld_func_lookup function. */ +/* #undef HAVE_DYLD */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ERRNO_H 1 + +/* Define to 1 if the system has the type `error_t'. */ +#define HAVE_ERROR_T 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_EXECINFO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define if the neat program is available */ +/* #undef HAVE_FDP */ + +/* Define if libffi is available on this platform. */ +/* #undef HAVE_FFI_CALL */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FFI_FFI_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_FFI_H */ + +/* Set to 1 if the finite function is found in */ +/* #undef HAVE_FINITE_IN_IEEEFP_H */ + +/* Define to 1 if you have the `floorf' function. */ +#define HAVE_FLOORF 1 + +/* Define to 1 if you have the `fmodf' function. */ +#define HAVE_FMODF 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the `getrusage' function. */ +#define HAVE_GETRUSAGE 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define if the Graphviz program is available */ +/* #undef HAVE_GRAPHVIZ */ + +/* Define if the gv program is available */ +/* #undef HAVE_GV */ + +/* Define to 1 if you have the `index' function. */ +/* #undef HAVE_INDEX */ + +/* Define to 1 if the system has the type `int64_t'. */ +#define HAVE_INT64_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `isatty' function. */ +#define HAVE_ISATTY 1 + +/* Set to 1 if the isinf function is found in */ +#define HAVE_ISINF_IN_CMATH 1 + +/* Set to 1 if the isinf function is found in */ +#define HAVE_ISINF_IN_MATH_H 1 + +/* Set to 1 if the isnan function is found in */ +#define HAVE_ISNAN_IN_CMATH 1 + +/* Set to 1 if the isnan function is found in */ +#define HAVE_ISNAN_IN_MATH_H 1 + +/* Define if you have the libdl library or equivalent. */ +#define HAVE_LIBDL 1 + +/* Define to 1 if you have the `imagehlp' library (-limagehlp). */ +/* #undef HAVE_LIBIMAGEHLP */ + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `psapi' library (-lpsapi). */ +/* #undef HAVE_LIBPSAPI */ + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#define HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `udis86' library (-ludis86). */ +/* #undef HAVE_LIBUDIS86 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define if you can use -Wl,-export-dynamic. */ +#define HAVE_LINK_EXPORT_DYNAMIC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LINK_H 1 + +/* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add + the current directory to the dynamic linker search path. */ +#define HAVE_LINK_R 1 + +/* Define to 1 if you have the `longjmp' function. */ +#define HAVE_LONGJMP 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACH_MACH_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MACH_O_DYLD_H */ + +/* Define if mallinfo() is available on this platform. */ +#define HAVE_MALLINFO 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MALLOC_MALLOC_H */ + +/* Define to 1 if you have the `malloc_zone_statistics' function. */ +/* #undef HAVE_MALLOC_ZONE_STATISTICS */ + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkdtemp' function. */ +/* #undef HAVE_MKDTEMP */ + +/* Define to 1 if you have the `mkstemp' function. */ +#define HAVE_MKSTEMP 1 + +/* Define to 1 if you have the `mktemp' function. */ +#define HAVE_MKTEMP 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if + it uses MAP_ANON */ +#define HAVE_MMAP_ANONYMOUS 1 + +/* Define if mmap() can map files into memory */ +#define HAVE_MMAP_FILE + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the `nearbyintf' function. */ +#define HAVE_NEARBYINTF 1 + +/* Define if the neat program is available */ +/* #undef HAVE_NEATO */ + +/* Define to 1 if you have the `opendir' function. */ +#define HAVE_OPENDIR 1 + +/* Define to 1 if you have the `powf' function. */ +#define HAVE_POWF 1 + +/* Define if libtool can extract symbol lists from object files. */ +#define HAVE_PRELOADED_SYMBOLS 1 + +/* Define to have the %a format string */ +#define HAVE_PRINTF_A 1 + +/* Have pthread_getspecific */ +/* #undef HAVE_PTHREAD_GETSPECIFIC */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_PTHREAD_H */ + +/* Have pthread_mutex_lock */ +/* #undef HAVE_PTHREAD_MUTEX_LOCK */ + +/* Have pthread_rwlock_init */ +/* #undef HAVE_PTHREAD_RWLOCK_INIT */ + +/* Define to 1 if srand48/lrand48/drand48 exist in */ +#define HAVE_RAND48 1 + +/* Define to 1 if you have the `readdir' function. */ +#define HAVE_READDIR 1 + +/* Define to 1 if you have the `realpath' function. */ +#define HAVE_REALPATH 1 + +/* Define to 1 if you have the `rindex' function. */ +/* #undef HAVE_RINDEX */ + +/* Define to 1 if you have the `rintf' function. */ +#define HAVE_RINTF 1 + +/* Define to 1 if you have the `round' function. */ +#define HAVE_ROUND 1 + +/* Define to 1 if you have the `roundf' function. */ +#define HAVE_ROUNDF 1 + +/* Define to 1 if you have the `sbrk' function. */ +#define HAVE_SBRK 1 + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `setjmp' function. */ +#define HAVE_SETJMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SETJMP_H 1 + +/* Define to 1 if you have the `setrlimit' function. */ +#define HAVE_SETRLIMIT 1 + +/* Define if you have the shl_load function. */ +/* #undef HAVE_SHL_LOAD */ + +/* Define to 1 if you have the `siglongjmp' function. */ +#define HAVE_SIGLONGJMP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SIGNAL_H 1 + +/* Define to 1 if you have the `sigsetjmp' function. */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDIO_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Set to 1 if the std::isinf function is found in */ +/* #undef HAVE_STD_ISINF_IN_CMATH */ + +/* Set to 1 if the std::isnan function is found in */ +#define HAVE_STD_ISNAN_IN_CMATH 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strcmp' function. */ +#define HAVE_STRCMP 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the `strerror_s' function. */ +/* #undef HAVE_STRERROR_S */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strtof' function. */ +#define HAVE_STRTOF 1 + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +#define HAVE_STRTOQ 1 + +/* Define to 1 if you have the `sysconf' function. */ +#define HAVE_SYSCONF 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_DL_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#define HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define if the neat program is available */ +/* #undef HAVE_TWOPI */ + +/* Define to 1 if the system has the type `uint64_t'. */ +#define HAVE_UINT64_T 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if the system has the type `u_int64_t'. */ +/* #undef HAVE_U_INT64_T */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_WINDOWS_H */ + +/* Define to 1 if you have the `__dso_handle' function. */ +#define HAVE___DSO_HANDLE 1 + +/* Installation directory for binary executables */ +#define LLVM_BINDIR "/usr/local/google/llvm/bin" + +/* Time at which LLVM was configured */ +#define LLVM_CONFIGTIME "Fri Feb 26 12:17:10 CST 2010" + +/* Installation directory for data files */ +#define LLVM_DATADIR "/usr/local/google/llvm/share/llvm" + +/* Installation directory for documentation */ +#define LLVM_DOCSDIR "/usr/local/google/llvm/docs/llvm" + +/* Installation directory for config files */ +#define LLVM_ETCDIR "/usr/local/google/llvm/etc/llvm" + +/* Host triple we were built on */ +#define LLVM_HOSTTRIPLE "x86_64-unknown-linux-gnu" + +/* Installation directory for include files */ +#define LLVM_INCLUDEDIR "/usr/local/google/llvm/include" + +/* Installation directory for .info files */ +#define LLVM_INFODIR "/usr/local/google/llvm/info" + +/* Installation directory for libraries */ +#define LLVM_LIBDIR "/usr/local/google/llvm/lib" + +/* Installation directory for man pages */ +#define LLVM_MANDIR "/usr/local/google/llvm/man" + +/* Build multithreading support into LLVM */ +/* #undef LLVM_MULTITHREADED */ + +/* LLVM architecture name for the native architecture, if available */ +#define LLVM_NATIVE_ARCH ARMTarget + +/* Define if this is Unixish platform */ +#define LLVM_ON_UNIX 1 + +/* Define if this is Win32ish platform */ +/* #undef LLVM_ON_WIN32 */ + +/* Define to path to circo program if found or 'echo circo' otherwise */ +/* #undef LLVM_PATH_CIRCO */ + +/* Define to path to dot program if found or 'echo dot' otherwise */ +/* #undef LLVM_PATH_DOT */ + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +/* #undef LLVM_PATH_DOTTY */ + +/* Define to path to fdp program if found or 'echo fdp' otherwise */ +/* #undef LLVM_PATH_FDP */ + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +/* #undef LLVM_PATH_GRAPHVIZ */ + +/* Define to path to gv program if found or 'echo gv' otherwise */ +/* #undef LLVM_PATH_GV */ + +/* Define to path to neato program if found or 'echo neato' otherwise */ +/* #undef LLVM_PATH_NEATO */ + +/* Define to path to twopi program if found or 'echo twopi' otherwise */ +/* #undef LLVM_PATH_TWOPI */ + +/* Installation prefix directory */ +#define LLVM_PREFIX "/usr/local/google/llvm" + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +/* #undef LTDL_DLOPEN_DEPLIBS */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LTDL_OBJDIR ".libs/" + +/* Define to the name of the environment variable that determines the dynamic + library search path. */ +#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH" + +/* Define to the extension used for shared libraries, say, ".so". */ +#define LTDL_SHLIB_EXT ".so" + +/* Define to the system default library search path. */ +#define LTDL_SYSSEARCHPATH "/lib:/usr/lib:/usr/local/lib:/lib:/usr/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib32:/usr/lib32:/usr/local/lib32:/usr/x86_64-pc-linux-gnu/lib:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4:/usr/lib/gcc/x86_64-pc-linux-gnu/4.3.4/32:/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2:/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/32" + +/* Define if /dev/zero should be used when mapping RWX memory, or undefine if + its not necessary */ +/* #undef NEED_DEV_ZERO_FOR_MMAP */ + +/* Define if dlsym() requires a leading underscore in symbol names. */ +/* #undef NEED_USCORE */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "llvmbugs@cs.uiuc.edu" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "llvm" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "llvm 2.7svn" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "-llvm-" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.7svn" + +/* Define as the return type of signal handlers (`int' or `void'). */ +#define RETSIGTYPE void + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +/* #undef STAT_MACROS_BROKEN */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +#define TIME_WITH_SYS_TIME 1 + +/* Define to 1 if your declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define if we have the oprofile JIT-support library */ +#define USE_OPROFILE 0 + +/* Define if use udis86 library */ +#define USE_UDIS86 0 + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to a type to use for `error_t' if it is not otherwise available. */ +/* #undef error_t */ + +/* Define to `int' if does not define. */ +/* #undef pid_t */ + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ diff --git a/docs/AliasAnalysis.html b/docs/AliasAnalysis.html index 74b593c65f..6edd9f57af 100644 --- a/docs/AliasAnalysis.html +++ b/docs/AliasAnalysis.html @@ -403,7 +403,7 @@ implementing, you just override the interfaces you can improve.

href="#basic-aa">basicaa and no-aa passes) every alias analysis pass chains to another alias analysis implementation (for example, the user can specify "-basicaa -ds-aa --anders-aa -licm" to get the maximum benefit from the three alias +-licm" to get the maximum benefit from both alias analyses). The alias analysis class automatically takes care of most of this for methods that you don't override. For methods that you do override, in code paths that return a conservative MayAlias or Mod/Ref result, simply return @@ -703,25 +703,6 @@ loads and stores to be eliminated.

non-address taken globals), but is very quick analysis.

- - - -
- -

The -anders-aa pass implements the well-known "Andersen's algorithm" -for interprocedural alias analysis. This algorithm is a subset-based, -flow-insensitive, context-insensitive, and field-insensitive alias analysis that -is widely believed to be fairly precise. Unfortunately, this algorithm is also -O(N3). The LLVM implementation currently does not implement any of -the refinements (such as "online cycle elimination" or "offline variable -substitution") to improve its efficiency, so it can be quite slow in common -cases. -

- -
-
The -steens-aa pass @@ -855,7 +836,7 @@ pointer.

These passes are useful for evaluating the various alias analysis -implementations. You can use them with commands like 'opt -anders-aa -ds-aa +implementations. You can use them with commands like 'opt -ds-aa -aa-eval foo.bc -disable-output -stats'.

@@ -949,7 +930,7 @@ analysis directly.

Chris Lattner
LLVM Compiler Infrastructure
- Last modified: $Date: 2009-11-22 08:01:44 -0800 (Sun, 22 Nov 2009) $ + Last modified: $Date: 2010-03-02 03:24:17 +0800 (二, 02 3月 2010) $ diff --git a/docs/BitCodeFormat.html b/docs/BitCodeFormat.html index 2284b3e39a..de2e65a60e 100644 --- a/docs/BitCodeFormat.html +++ b/docs/BitCodeFormat.html @@ -1157,7 +1157,7 @@ fields of FUNCTION records.

src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"> Chris Lattner
The LLVM Compiler Infrastructure
-Last modified: $Date: 2010-01-20 09:53:51 -0800 (Wed, 20 Jan 2010) $ +Last modified: $Date: 2010-01-21 01:53:51 +0800 (四, 21 1月 2010) $ diff --git a/docs/Bugpoint.html b/docs/Bugpoint.html index 8d1400b781..6a381b3a8a 100644 --- a/docs/Bugpoint.html +++ b/docs/Bugpoint.html @@ -243,7 +243,7 @@ non-obvious ways. Here are some hints and tips:

Chris Lattner
LLVM Compiler Infrastructure
- Last modified: $Date: 2009-10-12 11:12:47 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2009-10-13 02:12:47 +0800 (二, 13 10月 2009) $ diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html index b446eebc55..5baa4a7259 100644 --- a/docs/CodeGenerator.html +++ b/docs/CodeGenerator.html @@ -1041,9 +1041,9 @@ ret

-%t1 = add float %W, %X
-%t2 = mul float %t1, %Y
-%t3 = add float %t2, %Z
+%t1 = fadd float %W, %X
+%t2 = fmul float %t1, %Y
+%t3 = fadd float %t2, %Z
 
@@ -2116,7 +2116,7 @@ MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory Chris Lattner
The LLVM Compiler Infrastructure
- Last modified: $Date: 2010-01-11 10:53:47 -0800 (Mon, 11 Jan 2010) $ + Last modified: $Date: 2010-03-02 09:11:08 +0800 (二, 02 3月 2010) $ diff --git a/docs/CodingStandards.html b/docs/CodingStandards.html index 8f8f890462..601c5ec528 100644 --- a/docs/CodingStandards.html +++ b/docs/CodingStandards.html @@ -194,9 +194,9 @@ something sane goes a long ways towards avoiding writing documentation.

Method information

Methods defined in a class (as well as any global functions) should also be -documented properly. A quick note about what it does any a description of the +documented properly. A quick note about what it does and a description of the borderline behaviour is all that is necessary here (unless something -particularly tricky or insideous is going on). The hope is that people can +particularly tricky or insidious is going on). The hope is that people can figure out how to use your interfaces without reading the code itself... that is the goal metric.

@@ -1346,7 +1346,7 @@ something.

Chris Lattner
LLVM Compiler Infrastructure
- Last modified: $Date: 2009-10-12 07:46:08 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2010-02-27 04:18:32 +0800 (六, 27 2月 2010) $ diff --git a/docs/CommandGuide/FileCheck.pod b/docs/CommandGuide/FileCheck.pod index 32516ad87b..433979a871 100644 --- a/docs/CommandGuide/FileCheck.pod +++ b/docs/CommandGuide/FileCheck.pod @@ -25,7 +25,7 @@ match. The file to verify is always read from standard input. =over -=item B<--help> +=item B<-help> Print a summary of command line options. diff --git a/docs/CommandGuide/Makefile b/docs/CommandGuide/Makefile index 3b65183107..2c2d0760e7 100644 --- a/docs/CommandGuide/Makefile +++ b/docs/CommandGuide/Makefile @@ -77,9 +77,9 @@ EXTRA_DIST := $(POD) index.html clean-local:: $(Verb) $(RM) -f pod2htm*.*~~ $(HTML) $(MAN) $(PS) -HTML_DIR := $(PROJ_docsdir)/html/CommandGuide -MAN_DIR := $(PROJ_mandir)/man1 -PS_DIR := $(PROJ_docsdir)/ps +HTML_DIR := $(DESTDIR)$(PROJ_docsdir)/html/CommandGuide +MAN_DIR := $(DESTDIR)$(PROJ_mandir)/man1 +PS_DIR := $(DESTDIR)$(PROJ_docsdir)/ps install-local:: $(HTML) $(INSTALL_MANS) $(PS) $(Echo) Installing HTML CommandGuide Documentation diff --git a/docs/CommandGuide/bugpoint.pod b/docs/CommandGuide/bugpoint.pod index 204ea4d3d3..7afeea1aba 100644 --- a/docs/CommandGuide/bugpoint.pod +++ b/docs/CommandGuide/bugpoint.pod @@ -85,7 +85,7 @@ mis-management. Continually randomize the specified passes and run them on the test program until a bug is found or the user kills B. -=item B<--help> +=item B<-help> Print a summary of command line options. @@ -99,9 +99,9 @@ it runs, to come from that file. Load the dynamic object F into B itself. This object should register new optimization passes. Once loaded, the object will add new command line options to enable various optimizations. To see the new complete list of -optimizations, use the B<--help> and B<--load> options together; for example: +optimizations, use the B<-help> and B<--load> options together; for example: - bugpoint --load myNewPass.so --help + bugpoint --load myNewPass.so -help =item B<--mlimit> F diff --git a/docs/CommandGuide/index.html b/docs/CommandGuide/index.html index 88bb87c5df..0bdba7ea5d 100644 --- a/docs/CommandGuide/index.html +++ b/docs/CommandGuide/index.html @@ -17,7 +17,7 @@ for all of the LLVM tools. These pages describe how to use the LLVM commands and what their options are. Note that these pages do not describe all of the options available for all tools. To get a complete listing, pass the ---help (general options) or --help-hidden (general+debugging +-help (general options) or -help-hidden (general+debugging options) arguments to the tool you are interested in.

@@ -148,7 +148,7 @@ options) arguments to the tool you are interested in.

src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"> LLVM Compiler Infrastructure
- Last modified: $Date: 2009-10-18 20:54:13 -0700 (Sun, 18 Oct 2009) $ + Last modified: $Date: 2010-02-18 22:08:13 +0800 (四, 18 2月 2010) $ diff --git a/docs/CommandGuide/llc.pod b/docs/CommandGuide/llc.pod index 8adfb682be..ac24aab4ff 100644 --- a/docs/CommandGuide/llc.pod +++ b/docs/CommandGuide/llc.pod @@ -38,7 +38,7 @@ Other B options are as follows: =over -=item B<--help> +=item B<-help> Print a summary of command line options. @@ -56,7 +56,7 @@ string. =item B<-march>=I Specify the architecture for which to generate assembly, overriding the target -encoded in the input file. See the output of B for a list of +encoded in the input file. See the output of B for a list of valid architectures. By default this is inferred from the target triple or autodetected to the current architecture. diff --git a/docs/CommandGuide/lli.pod b/docs/CommandGuide/lli.pod index e9fdf74fe5..6d1e1c65d4 100644 --- a/docs/CommandGuide/lli.pod +++ b/docs/CommandGuide/lli.pod @@ -73,7 +73,7 @@ architecture which is not compatible with the current system. =item B<-march>=I Specify the architecture for which to generate assembly, overriding the target -encoded in the bitcode file. See the output of B for a list of +encoded in the bitcode file. See the output of B for a list of valid architectures. By default this is inferred from the target triple or autodetected to the current architecture. @@ -170,7 +170,7 @@ Instruction schedulers available (before register allocation): =item B<-regalloc>=I -Register allocator to use: (default = linearscan) +Register allocator to use (default=linearscan) =bigblock: Big-block register allocator =linearscan: linear scan register allocator =local - local register allocator @@ -186,7 +186,7 @@ Choose relocation model from: =item B<-spiller> -Spiller to use: (default: local) +Spiller to use (default=local) =simple: simple spiller =local: local spiller diff --git a/docs/CommandGuide/llvm-as.pod b/docs/CommandGuide/llvm-as.pod index 045a9245b6..185c009698 100644 --- a/docs/CommandGuide/llvm-as.pod +++ b/docs/CommandGuide/llvm-as.pod @@ -50,7 +50,7 @@ Enable binary output on terminals. Normally, B will refuse to write raw bitcode output if the output stream is a terminal. With this option, B will write raw bitcode regardless of the output device. -=item B<--help> +=item B<-help> Print a summary of command line options. diff --git a/docs/CommandGuide/llvm-bcanalyzer.pod b/docs/CommandGuide/llvm-bcanalyzer.pod index f60b513822..b0bc0cddba 100644 --- a/docs/CommandGuide/llvm-bcanalyzer.pod +++ b/docs/CommandGuide/llvm-bcanalyzer.pod @@ -43,7 +43,7 @@ Causes B to verify the module produced by reading the bitcode. This ensures that the statistics generated are based on a consistent module. -=item B<--help> +=item B<-help> Print a summary of command line options. diff --git a/docs/CommandGuide/llvm-config.pod b/docs/CommandGuide/llvm-config.pod index 06f10de221..4e38dae3df 100644 --- a/docs/CommandGuide/llvm-config.pod +++ b/docs/CommandGuide/llvm-config.pod @@ -30,7 +30,7 @@ To link against the JIT: Print the version number of LLVM. -=item B<--help> +=item B<-help> Print a summary of B arguments. diff --git a/docs/CommandGuide/llvm-db.pod b/docs/CommandGuide/llvm-db.pod deleted file mode 100644 index 132417685c..0000000000 --- a/docs/CommandGuide/llvm-db.pod +++ /dev/null @@ -1,16 +0,0 @@ -=pod - -=head1 NAME - -llvm-db - LLVM debugger (alpha) - -=head1 SYNOPSIS - -Details coming soon. Please see -L in the meantime. - -=head1 AUTHORS - -Maintained by the LLVM Team (L). - -=cut diff --git a/docs/CommandGuide/llvm-dis.pod b/docs/CommandGuide/llvm-dis.pod index 2b83290c9b..5b2f4ef4e9 100644 --- a/docs/CommandGuide/llvm-dis.pod +++ b/docs/CommandGuide/llvm-dis.pod @@ -33,7 +33,7 @@ Enable binary output on terminals. Normally, B will refuse to write raw bitcode output if the output stream is a terminal. With this option, B will write raw bitcode regardless of the output device. -=item B<--help> +=item B<-help> Print a summary of command line options. diff --git a/docs/CommandGuide/llvm-extract.pod b/docs/CommandGuide/llvm-extract.pod index b62e8ae312..d4baab7399 100644 --- a/docs/CommandGuide/llvm-extract.pod +++ b/docs/CommandGuide/llvm-extract.pod @@ -34,9 +34,15 @@ B will write raw bitcode regardless of the output device. =item B<--func> I -Extract the function named I from the LLVM bitcode. +Extract the function named I from the LLVM bitcode. May be +specified multiple times to extract multiple functions at once. -=item B<--help> +=item B<--glob> I + +Extract the global variable named I from the LLVM bitcode. May be +specified multiple times to extract multiple global variables at once. + +=item B<-help> Print a summary of command line options. diff --git a/docs/CommandGuide/llvm-link.pod b/docs/CommandGuide/llvm-link.pod index e1a1267c52..8d06cc9d9d 100644 --- a/docs/CommandGuide/llvm-link.pod +++ b/docs/CommandGuide/llvm-link.pod @@ -51,7 +51,7 @@ Write output in LLVM intermediate language (instead of bitcode). If specified, B prints a human-readable version of the output bitcode file to standard error. -=item B<--help> +=item B<-help> Print a summary of command line options. diff --git a/docs/CommandGuide/llvm-nm.pod b/docs/CommandGuide/llvm-nm.pod index 995ac08139..a580d3f5ca 100644 --- a/docs/CommandGuide/llvm-nm.pod +++ b/docs/CommandGuide/llvm-nm.pod @@ -77,7 +77,7 @@ Use POSIX.2 output format. Alias for B<--format=posix>. Use BSD output format. Alias for B<--format=bsd>. -=item B<--help> +=item B<-help> Print a summary of command-line options and their meanings. diff --git a/docs/CommandGuide/llvm-prof.pod b/docs/CommandGuide/llvm-prof.pod index 381387d7db..9541b05dca 100644 --- a/docs/CommandGuide/llvm-prof.pod +++ b/docs/CommandGuide/llvm-prof.pod @@ -18,7 +18,7 @@ where the program hotspots are. This program is often used in conjunction with the F script. This script automatically instruments a program, runs it with the JIT, then runs B to format a report. To get more information about -F, execute it with the B<--help> option. +F, execute it with the B<-help> option. =head1 OPTIONS diff --git a/docs/CommandGuide/llvm-ranlib.pod b/docs/CommandGuide/llvm-ranlib.pod index 130edb0771..53cd34bbb5 100644 --- a/docs/CommandGuide/llvm-ranlib.pod +++ b/docs/CommandGuide/llvm-ranlib.pod @@ -6,7 +6,7 @@ llvm-ranlib - Generate index for LLVM archive =head1 SYNOPSIS -B [--version] [--help] +B [--version] [-help] =head1 DESCRIPTION @@ -30,7 +30,7 @@ Specifies the archive-file to which the symbol table is added or updated. Print the version of B and exit without building a symbol table. -=item F<--help> +=item F<-help> Print usage help for B and exit without building a symbol table. diff --git a/docs/CommandGuide/llvmc.pod b/docs/CommandGuide/llvmc.pod index e5e0651161..d237ca4c14 100644 --- a/docs/CommandGuide/llvmc.pod +++ b/docs/CommandGuide/llvmc.pod @@ -77,11 +77,11 @@ Store temporary files in the given directory. This directory is deleted on exit unless I<--save-temps> is specified. If I<--save-temps=obj> is also specified, I<--temp-dir> is given the precedence. -=item B<--help> +=item B<-help> Print a summary of command-line options and exit. -=item B<--help-hidden> +=item B<-help-hidden> Print a summary of command-line options and exit. Print help even for options intended for developers. diff --git a/docs/CommandGuide/tblgen.pod b/docs/CommandGuide/tblgen.pod index c8244af5ce..d127492a91 100644 --- a/docs/CommandGuide/tblgen.pod +++ b/docs/CommandGuide/tblgen.pod @@ -26,7 +26,7 @@ to read as input. =over -=item B<--help> +=item B<-help> Print a summary of command line options. diff --git a/docs/CommandLine.html b/docs/CommandLine.html index 38421c72f8..d477609361 100644 --- a/docs/CommandLine.html +++ b/docs/CommandLine.html @@ -44,7 +44,7 @@
  • Option Modifiers
      -
    • Hiding an option from --help +
    • Hiding an option from -help output
    • Controlling the number of occurrences required and allowed
    • @@ -161,7 +161,7 @@ you declare it. Custom parsers are no problem.
    • Labor Saving: The CommandLine library cuts down on the amount of grunt work that you, the user, have to do. For example, it automatically provides a ---help option that shows the available command line options for your +-help option that shows the available command line options for your tool. Additionally, it does most of the basic correctness checking for you.
    • @@ -239,14 +239,14 @@ href="#list">"cl::list template), and tell the CommandLine library that the data type that we are parsing is a string.

      The second and third parameters (which are optional) are used to specify what -to output for the "--help" option. In this case, we get a line that +to output for the "-help" option. In this case, we get a line that looks like this:

       USAGE: compiler [options]
       
       OPTIONS:
      -  -help             - display available options (--help-hidden for more)
      +  -help             - display available options (-help-hidden for more)
         -o <filename>     - Specify output filename
       
      @@ -308,14 +308,14 @@ the CommandLine library will automatically issue an error if the argument is not specified, which shifts all of the command line option verification code out of your application into the library. This is just one example of how using flags can alter the default behaviour of the library, on a per-option basis. By -adding one of the declarations above, the --help option synopsis is now +adding one of the declarations above, the -help option synopsis is now extended to:

       USAGE: compiler [options] <input file>
       
       OPTIONS:
      -  -help             - display available options (--help-hidden for more)
      +  -help             - display available options (-help-hidden for more)
         -o <filename>     - Specify output filename
       
      @@ -346,8 +346,8 @@ declaring options of boolean type like this:

      ("Force", "Quiet", and "Quiet2") to recognize these options. Note that the "-q" option is specified with the "cl::Hidden" flag. This modifier prevents it -from being shown by the standard "--help" output (note that it is still -shown in the "--help-hidden" output).

      +from being shown by the standard "-help" output (note that it is still +shown in the "-help-hidden" output).

      The CommandLine library uses a different parser for different data types. For example, in the string case, the argument passed @@ -372,7 +372,7 @@ href="#doubleparser">double, and int parsers work like you would expect, using the 'strtol' and 'strtod' C library calls to parse the string value into the specified data type.

      -

      With the declarations above, "compiler --help" emits this:

      +

      With the declarations above, "compiler -help" emits this:

       USAGE: compiler [options] <input file>
      @@ -381,10 +381,10 @@ OPTIONS:
         -f     - Enable binary output on terminals
         -o     - Override output filename
         -quiet - Don't print informational messages
      -  -help  - display available options (--help-hidden for more)
      +  -help  - display available options (-help-hidden for more)
       
      -

      and "compiler --help-hidden" prints this:

      +

      and "compiler -help-hidden" prints this:

       USAGE: compiler [options] <input file>
      @@ -394,7 +394,7 @@ OPTIONS:
         -o     - Override output filename
         -q     - Don't print informational messages
         -quiet - Don't print informational messages
      -  -help  - display available options (--help-hidden for more)
      +  -help  - display available options (-help-hidden for more)
       

      This brief example has shown you how to use the 'cl::aliasopt modifier) whenever it is specified. Because aliases do not hold state, the only thing the program has to query is the Quiet variable now. Another nice feature of aliases is that they automatically hide themselves from the -help output -(although, again, they are still visible in the --help-hidden +(although, again, they are still visible in the -help-hidden output).

      Now the application code can simply use:

      @@ -531,7 +531,7 @@ OPTIONS: -O2 - Enable default optimizations -O3 - Enable expensive optimizations -f - Enable binary output on terminals - -help - display available options (--help-hidden for more) + -help - display available options (-help-hidden for more) -o <filename> - Specify output filename -quiet - Don't print informational messages @@ -599,7 +599,7 @@ enum DebugLev {

      This definition defines an enumerated command line variable of type "enum DebugLev", which works exactly the same way as before. The difference here is just the interface exposed to the user of your program and the help output by -the "--help" option:

      +the "-help" option:

       USAGE: compiler [options] <input file>
      @@ -615,7 +615,7 @@ OPTIONS:
           =quick      - enable quick debug information
           =detailed   - enable detailed debug information
         -f            - Enable binary output on terminals
      -  -help         - display available options (--help-hidden for more)
      +  -help         - display available options (-help-hidden for more)
         -o <filename> - Specify output filename
         -quiet        - Don't print informational messages
       
      @@ -706,7 +706,7 @@ checking we have to do.

      Instead of collecting sets of options in a list, it is also possible to -gather information for enum values in a bit vector. The represention used by +gather information for enum values in a bit vector. The representation used by the cl::bits class is an unsigned integer. An enum value is represented by a 0/1 in the enum's ordinal value bit position. 1 indicating that the enum was specified, 0 otherwise. As each @@ -794,7 +794,7 @@ USAGE: compiler [options] <input file> OPTIONS: ... - -help - display available options (--help-hidden for more) + -help - display available options (-help-hidden for more) -o <filename> - Specify output filename

      @@ -835,14 +835,14 @@ Using the CommandLine library, this would be specified as:

      cl::opt<string> Filename(cl::Positional, cl::desc("<input file>"), cl::init("-")); -

      Given these two option declarations, the --help output for our grep +

      Given these two option declarations, the -help output for our grep replacement would look like this:

       USAGE: spiffygrep [options] <regular expression> <input file>
       
       OPTIONS:
      -  -help - display available options (--help-hidden for more)
      +  -help - display available options (-help-hidden for more)
       

      ... and the resultant program could be used just like the standard @@ -872,7 +872,7 @@ Note that the system grep has the same problem:

         $ spiffygrep '-foo' test.txt
      -  Unknown command line argument '-foo'.  Try: spiffygrep --help'
      +  Unknown command line argument '-foo'.  Try: spiffygrep -help'
       
         $ grep '-foo' test.txt
         grep: illegal option -- f
      @@ -986,7 +986,7 @@ shell itself.  Using the CommandLine library, we would specify this as:

      USAGE: spiffysh [options] <input script> <program arguments>... OPTIONS: - -help - display available options (--help-hidden for more) + -help - display available options (-help-hidden for more) -x - Enable trace output
      @@ -1098,11 +1098,11 @@ This option is specified in simple double quotes:
    • The cl::desc attribute specifies a -description for the option to be shown in the --help output for the +description for the option to be shown in the -help output for the program.
    • The cl::value_desc attribute -specifies a string that can be used to fine tune the --help output for +specifies a string that can be used to fine tune the -help output for a command line option. Look here for an example.
    • @@ -1130,7 +1130,7 @@ the string-to-value mapping to be used by the generic parser. It takes a clEnumValEnd terminated list of (option, value, description) triplets that specify the option name, the value mapped to, and the description shown in the ---help for the tool. Because the generic parser is used most +-help for the tool. Because the generic parser is used most frequently with enum values, two macros are often useful:
        @@ -1175,13 +1175,13 @@ obviously).

        Option modifiers are the flags and expressions that you pass into the constructors for cl::opt and cl::list. These modifiers give you the ability to -tweak how options are parsed and how --help output is generated to fit +tweak how options are parsed and how -help output is generated to fit your application well.

        These options fall into five main categories:

          -
        1. Hiding an option from --help output
        2. +
        3. Hiding an option from -help output
        4. Controlling the number of occurrences required and allowed
        5. Controlling whether or not a value must be @@ -1200,14 +1200,14 @@ usually shouldn't have to worry about these.

          The cl::NotHidden, cl::Hidden, and cl::ReallyHidden modifiers are used to control whether or not an option -appears in the --help and --help-hidden output for the +appears in the -help and -help-hidden output for the compiled program:

            @@ -1219,8 +1219,8 @@ in both help listings.
          • The cl::Hidden modifier (which is the default for cl::alias options) indicates that -the option should not appear in the --help output, but should appear in -the --help-hidden output.
          • +the option should not appear in the -help output, but should appear in +the -help-hidden output.
          • The cl::ReallyHidden modifier indicates that the option should not appear in any help output.
          • @@ -1508,7 +1508,7 @@ available.

            The cl::ParseCommandLineOptions function requires two parameters (argc and argv), but may also take an optional third parameter which holds additional extra text to emit when the ---help option is invoked, and a fourth boolean parameter that enables +-help option is invoked, and a fourth boolean parameter that enables response files.

          @@ -1535,7 +1535,7 @@ does.

          not be available, it can't just look in argv[0]), the name of the environment variable to examine, the optional additional extra text to emit when the ---help option is invoked, and the boolean +-help option is invoked, and the boolean switch that controls whether response files should be read.

          @@ -1689,7 +1689,7 @@ the conversion from string to data.

          The cl::extrahelp class is a nontemplated class that allows extra -help text to be printed out for the --help option.

          +help text to be printed out for the -help option.

           namespace cl {
          @@ -1906,7 +1906,7 @@ MFS("max-file-size", cl::desc("Maximum file si
           
           
           OPTIONS:
          -  -help                 - display available options (--help-hidden for more)
          +  -help                 - display available options (-help-hidden for more)
             ...
             -max-file-size=<size> - Maximum file size to accept
           
          @@ -1972,7 +1972,7 @@ tutorial.

          Chris Lattner
          LLVM Compiler Infrastructure
          - Last modified: $Date: 2009-10-12 07:46:08 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2010-02-27 04:18:32 +0800 (六, 27 2月 2010) $ diff --git a/docs/CompilerDriver.html b/docs/CompilerDriver.html index c4e618bb4a..db82889423 100644 --- a/docs/CompilerDriver.html +++ b/docs/CompilerDriver.html @@ -132,7 +132,7 @@ directory with the compilation graph description in Graphviz format (identical to the file used by the --view-graph option). The -o option can be used to set the output file name. Hidden option, useful for debugging LLVMC plugins.
        6. -
        7. --help, --help-hidden, --version - These options have +
        8. -help, -help-hidden, --version - These options have their standard meaning.
    @@ -325,7 +325,7 @@ aliased option name. Usage example: Possible option properties:

      -
    • help - help string associated with this option. Used for --help +
    • help - help string associated with this option. Used for -help output.
    • required - this option must be specified exactly once (or, in case of the list options without the multi_val property, at least @@ -338,7 +338,7 @@ it is synonymous with requiredmulti_val. Incompatible with required and one_or_more.
    • hidden - the description of this option will not appear in -the --help output (but will appear in the --help-hidden +the -help output (but will appear in the -help-hidden output).
    • really_hidden - the option will not be mentioned in any help output.
    • @@ -748,7 +748,7 @@ the Base plugin behav Mikhail Glushenkov
      LLVM Compiler Infrastructure
      -Last modified: $Date: 2009-12-23 04:49:51 -0800 (Wed, 23 Dec 2009) $ +Last modified: $Date: 2010-02-18 22:08:13 +0800 (四, 18 2月 2010) $ diff --git a/docs/CompilerWriterInfo.html b/docs/CompilerWriterInfo.html index efeddc07c7..397bd5db16 100644 --- a/docs/CompilerWriterInfo.html +++ b/docs/CompilerWriterInfo.html @@ -256,7 +256,7 @@ processors. Misha Brukman
      LLVM Compiler Infrastructure
      - Last modified: $Date: 2008-12-11 09:34:48 -0800 (Thu, 11 Dec 2008) $ + Last modified: $Date: 2008-12-12 01:34:48 +0800 (五, 12 12月 2008) $ diff --git a/docs/DeveloperPolicy.html b/docs/DeveloperPolicy.html index 98172cc7ec..f6ccdd0c90 100644 --- a/docs/DeveloperPolicy.html +++ b/docs/DeveloperPolicy.html @@ -520,7 +520,7 @@ Changes

      We intend to keep LLVM perpetually open source and to use a liberal open source license. The current license is the University of - llinois/NCSA Open Source License, which boils down to this:

      + Illinois/NCSA Open Source License, which boils down to this:

      • You can freely distribute LLVM.
      • @@ -601,7 +601,7 @@ Changes Written by the LLVM Oversight Group
        The LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-10-10 14:37:16 -0700 (Sat, 10 Oct 2009) $ + Last modified: $Date: 2010-02-27 04:18:32 +0800 (六, 27 2月 2010) $ diff --git a/docs/ExceptionHandling.html b/docs/ExceptionHandling.html index 4267215529..f427f7d55b 100644 --- a/docs/ExceptionHandling.html +++ b/docs/ExceptionHandling.html @@ -599,7 +599,7 @@ Chris Lattner
        LLVM Compiler Infrastructure
        - Last modified: $Date: 2010-01-27 17:45:32 -0800 (Wed, 27 Jan 2010) $ + Last modified: $Date: 2010-01-28 09:45:32 +0800 (四, 28 1月 2010) $ diff --git a/docs/ExtendingLLVM.html b/docs/ExtendingLLVM.html index 925816a653..e937e42be6 100644 --- a/docs/ExtendingLLVM.html +++ b/docs/ExtendingLLVM.html @@ -384,7 +384,7 @@ void calcTypeName(const Type *Ty, The LLVM Compiler Infrastructure
        - Last modified: $Date: 2008-12-11 10:23:24 -0800 (Thu, 11 Dec 2008) $ + Last modified: $Date: 2008-12-12 02:23:24 +0800 (五, 12 12月 2008) $ diff --git a/docs/FAQ.html b/docs/FAQ.html index 8d8ddb333b..c693bc55c4 100644 --- a/docs/FAQ.html +++ b/docs/FAQ.html @@ -437,7 +437,7 @@ Stop.

        The GNUmakefile in the top-level directory of LLVM-GCC is a special Makefile used by Apple to invoke the build_gcc script after - setting up a special environment. This has the unforunate side-effect that + setting up a special environment. This has the unfortunate side-effect that trying to build LLVM-GCC with srcdir == objdir in a "non-Apple way" invokes the GNUmakefile instead of Makefile. Because the environment isn't set up correctly to do this, the build fails.

        @@ -931,7 +931,7 @@ F.i: src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"> LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-10-12 07:46:08 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2010-02-26 07:41:41 +0800 (五, 26 2月 2010) $ diff --git a/docs/GCCFEBuildInstrs.html b/docs/GCCFEBuildInstrs.html index 08844ec173..36ab9fce97 100644 --- a/docs/GCCFEBuildInstrs.html +++ b/docs/GCCFEBuildInstrs.html @@ -272,7 +272,7 @@ More information is available in the FAQ. src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"> LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-07-05 05:01:44 -0700 (Sun, 05 Jul 2009) $ + Last modified: $Date: 2009-07-05 20:01:44 +0800 (日, 05 7月 2009) $ diff --git a/docs/GarbageCollection.html b/docs/GarbageCollection.html index ab43f6e469..b93d845124 100644 --- a/docs/GarbageCollection.html +++ b/docs/GarbageCollection.html @@ -1380,7 +1380,7 @@ Fergus Henderson. International Symposium on Memory Management 2002.

        Chris Lattner
        LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-08-05 08:42:44 -0700 (Wed, 05 Aug 2009) $ + Last modified: $Date: 2009-08-05 23:42:44 +0800 (三, 05 8月 2009) $ diff --git a/docs/GetElementPtr.html b/docs/GetElementPtr.html index 32c1bce18d..37dcd781fd 100644 --- a/docs/GetElementPtr.html +++ b/docs/GetElementPtr.html @@ -17,7 +17,7 @@
        1. Introduction
        2. -
        3. The Questions +
        4. Address Computation
          1. Why is the extra 0 index required?
          2. What is dereferenced by GEP?
          3. @@ -25,6 +25,30 @@ subsequent ones?
          4. Why don't GEP x,0,0,1 and GEP x,1 alias?
          5. Why do GEP x,1,0,0 and GEP x,1 alias?
          6. +
          7. Can GEP index into vector elements? +
          8. Can GEP index into unions? +
          9. What effect do address spaces have on GEPs? +
          10. How is GEP different from ptrtoint, arithmetic, and inttoptr?
          11. +
          12. I'm writing a backend for a target which needs custom lowering for GEP. How do I do this? +
          13. How does VLA addressing work with GEPs? +
        5. +
        6. Rules +
            +
          1. What happens if an array index is out of bounds? +
          2. Can array indices be negative? +
          3. Can I compare two values computed with GEPs? +
          4. Can I do GEP with a different pointer type than the type of the underlying object? +
          5. Can I cast an object's address to integer and add it to null? +
          6. Can I compute the distance between two objects, and add that value to one address to compute the other address? +
          7. Can I do type-based alias analysis on LLVM IR? +
          8. What happens if a GEP computation overflows? +
          9. How can I tell if my front-end is following the rules? +
        7. +
        8. Rationale +
            +
          1. Why is GEP designed this way?
          2. +
          3. Why do struct member indices always use i32?
          4. +
          5. What's an uglygep?
        9. Summary
        @@ -37,9 +61,10 @@ +

        This document seeks to dispel the mystery and confusion surrounding LLVM's - GetElementPtr (GEP) instruction. Questions about the wiley GEP instruction are + GetElementPtr (GEP) instruction. Questions about the wily GEP instruction are probably the most frequently occurring questions once a developer gets down to coding with LLVM. Here we lay out the sources of confusion and show that the GEP instruction is really quite simple. @@ -47,22 +72,14 @@

        - +

        When people are first confronted with the GEP instruction, they tend to relate it to known concepts from other programming paradigms, most notably C - array indexing and field selection. However, GEP is a little different and - this leads to the following questions; all of which are answered in the - following sections.

        -
          -
        1. What is the first index of the GEP instruction? -
        2. -
        3. Why is the extra 0 index required?
        4. -
        5. What is dereferenced by GEP?
        6. -
        7. Why don't GEP x,0,0,1 and GEP x,1 alias?
        8. -
        9. Why do GEP x,1,0,0 and GEP x,1 alias?
        10. -
        + array indexing and field selection. GEP closely resembles C array indexing + and field selection, however it's is a little different and this leads to + the following questions.

        @@ -85,7 +102,7 @@ X = &Foo->F;

        it is natural to think that there is only one index, the selection of the field F. However, in this example, Foo is a pointer. That - pointer must be indexed explicitly in LLVM. C, on the other hand, indexs + pointer must be indexed explicitly in LLVM. C, on the other hand, indices through it transparently. To arrive at the same address location as the C code, you would provide the GEP instruction with two index operands. The first operand indexes through the pointer; the second operand indexes the @@ -155,7 +172,7 @@ entry:

        -%MyVar = unintialized global i32
        +%MyVar = uninitialized global i32
         ...
         %idx1 = getelementptr i32* %MyVar, i64 0
         %idx2 = getelementptr i32* %MyVar, i64 1
        @@ -210,7 +227,7 @@ idx3 = (char*) &MyVar + 8
           field of the structure %MyStruct. When people first look at it, they 
           wonder why the i64 0 index is needed. However, a closer inspection 
           of how globals and GEPs work reveals the need. Becoming aware of the following
        -  facts will dispell the confusion:

        + facts will dispel the confusion:

        1. The type of %MyStruct is not { float*, i32 } but rather { float*, i32 }*. That is, %MyStruct is a @@ -297,8 +314,8 @@ idx3 = (char*) &MyVar + 8
           %MyVar = global { [10 x i32 ] }
          -%idx1 = getlementptr { [10 x i32 ] }* %MyVar, i64 0, i32 0, i64 1
          -%idx2 = getlementptr { [10 x i32 ] }* %MyVar, i64 1
          +%idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 0, i32 0, i64 1
          +%idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1
           
          @@ -326,8 +343,8 @@ idx3 = (char*) &MyVar + 8
           %MyVar = global { [10 x i32 ] }
          -%idx1 = getlementptr { [10 x i32 ] }* %MyVar, i64 1, i32 0, i64 0
          -%idx2 = getlementptr { [10 x i32 ] }* %MyVar, i64 1
          +%idx1 = getelementptr { [10 x i32 ] }* %MyVar, i64 1, i32 0, i64 0
          +%idx2 = getelementptr { [10 x i32 ] }* %MyVar, i64 1
           
          @@ -336,6 +353,352 @@ idx3 = (char*) &MyVar + 8 MyVar+40 but its type is { [10 x i32] }*.

        + + + +
        +

        This hasn't always been forcefully disallowed, though it's not recommended. + It leads to awkward special cases in the optimizers, and fundamental + inconsistency in the IR. In the future, it will probably be outright + disallowed.

        + +
        + + + + +
        +

        Unknown.

        + +
        + + + + +
        +

        None, except that the address space qualifier on the first operand pointer + type always matches the address space qualifier on the result type.

        + +
        + + + + +
        +

        It's very similar; there are only subtle differences.

        + +

        With ptrtoint, you have to pick an integer type. One approach is to pick i64; + this is safe on everything LLVM supports (LLVM internally assumes pointers + are never wider than 64 bits in many places), and the optimizer will actually + narrow the i64 arithmetic down to the actual pointer size on targets which + don't support 64-bit arithmetic in most cases. However, there are some cases + where it doesn't do this. With GEP you can avoid this problem. + +

        Also, GEP carries additional pointer aliasing rules. It's invalid to take a + GEP from one object, address into a different separately allocated + object, and dereference it. IR producers (front-ends) must follow this rule, + and consumers (optimizers, specifically alias analysis) benefit from being + able to rely on it. See the Rules section for more + information.

        + +

        And, GEP is more concise in common cases.

        + +

        However, for the underlying integer computation implied, there + is no difference.

        + +
        + + + + +
        +

        You don't. The integer computation implied by a GEP is target-independent. + Typically what you'll need to do is make your backend pattern-match + expressions trees involving ADD, MUL, etc., which are what GEP is lowered + into. This has the advantage of letting your code work correctly in more + cases.

        + +

        GEP does use target-dependent parameters for the size and layout of data + types, which targets can customize.

        + +

        If you require support for addressing units which are not 8 bits, you'll + need to fix a lot of code in the backend, with GEP lowering being only a + small piece of the overall picture.

        + +
        + + + + +
        +

        GEPs don't natively support VLAs. LLVM's type system is entirely static, + and GEP address computations are guided by an LLVM type.

        + +

        VLA indices can be implemented as linearized indices. For example, an + expression like X[a][b][c], must be effectively lowered into a form + like X[a*m+b*n+c], so that it appears to the GEP as a single-dimensional + array reference.

        + +

        This means if you want to write an analysis which understands array + indices and you want to support VLAs, your code will have to be + prepared to reverse-engineer the linearization. One way to solve this + problem is to use the ScalarEvolution library, which always presents + VLA and non-VLA indexing in the same manner.

        +
        + + + + + + + + +
        +

        There are two senses in which an array index can be out of bounds.

        + +

        First, there's the array type which comes from the (static) type of + the first operand to the GEP. Indices greater than the number of elements + in the corresponding static array type are valid. There is no problem with + out of bounds indices in this sense. Indexing into an array only depends + on the size of the array element, not the number of elements.

        + +

        A common example of how this is used is arrays where the size is not known. + It's common to use array types with zero length to represent these. The + fact that the static type says there are zero elements is irrelevant; it's + perfectly valid to compute arbitrary element indices, as the computation + only depends on the size of the array element, not the number of + elements. Note that zero-sized arrays are not a special case here.

        + +

        This sense is unconnected with inbounds keyword. The + inbounds keyword is designed to describe low-level pointer + arithmetic overflow conditions, rather than high-level array + indexing rules. + +

        Analysis passes which wish to understand array indexing should not + assume that the static array type bounds are respected.

        + +

        The second sense of being out of bounds is computing an address that's + beyond the actual underlying allocated object.

        + +

        With the inbounds keyword, the result value of the GEP is + undefined if the address is outside the actual underlying allocated + object and not the address one-past-the-end.

        + +

        Without the inbounds keyword, there are no restrictions + on computing out-of-bounds addresses. Obviously, performing a load or + a store requires an address of allocated and sufficiently aligned + memory. But the GEP itself is only concerned with computing addresses.

        + +
        + + + +
        +

        Yes. This is basically a special case of array indices being out + of bounds.

        + +
        + + + +
        +

        Yes. If both addresses are within the same allocated object, or + one-past-the-end, you'll get the comparison result you expect. If either + is outside of it, integer arithmetic wrapping may occur, so the + comparison may not be meaningful.

        + +
        + + + +
        +

        Yes. There are no restrictions on bitcasting a pointer value to an arbitrary + pointer type. The types in a GEP serve only to define the parameters for the + underlying integer computation. They need not correspond with the actual + type of the underlying object.

        + +

        Furthermore, loads and stores don't have to use the same types as the type + of the underlying object. Types in this context serve only to specify + memory size and alignment. Beyond that there are merely a hint to the + optimizer indicating how the value will likely be used.

        + +
        + + + +
        +

        You can compute an address that way, but if you use GEP to do the add, + you can't use that pointer to actually access the object, unless the + object is managed outside of LLVM.

        + +

        The underlying integer computation is sufficiently defined; null has a + defined value -- zero -- and you can add whatever value you want to it.

        + +

        However, it's invalid to access (load from or store to) an LLVM-aware + object with such a pointer. This includes GlobalVariables, Allocas, and + objects pointed to by noalias pointers.

        + +

        If you really need this functionality, you can do the arithmetic with + explicit integer instructions, and use inttoptr to convert the result to + an address. Most of GEP's special aliasing rules do not apply to pointers + computed from ptrtoint, arithmetic, and inttoptr sequences.

        + +
        + + + +
        +

        As with arithmetic on null, You can use GEP to compute an address that + way, but you can't use that pointer to actually access the object if you + do, unless the object is managed outside of LLVM.

        + +

        Also as above, ptrtoint and inttoptr provide an alternative way to do this + which do not have this restriction.

        + +
        + + + +
        +

        You can't do type-based alias analysis using LLVM's built-in type system, + because LLVM has no restrictions on mixing types in addressing, loads or + stores.

        + +

        It would be possible to add special annotations to the IR, probably using + metadata, to describe a different type system (such as the C type system), + and do type-based aliasing on top of that. This is a much bigger + undertaking though.

        + +
        + + + + +
        +

        If the GEP has the inbounds keyword, the result value is + undefined.

        + +

        Otherwise, the result value is the result from evaluating the implied + two's complement integer computation. However, since there's no + guarantee of where an object will be allocated in the address space, + such values have limited meaning.

        + +
        + + + + +
        +

        There is currently no checker for the getelementptr rules. Currently, + the only way to do this is to manually check each place in your front-end + where GetElementPtr operators are created.

        + +

        It's not possible to write a checker which could find all rule + violations statically. It would be possible to write a checker which + works by instrumenting the code with dynamic checks though. Alternatively, + it would be possible to write a static checker which catches a subset of + possible problems. However, no such checker exists today.

        + +
        + + + + + + + + +
        +

        The design of GEP has the following goals, in rough unofficial + order of priority:

        +
          +
        • Support C, C-like languages, and languages which can be + conceptually lowered into C (this covers a lot).
        • +
        • Support optimizations such as those that are common in + C compilers.
        • +
        • Provide a consistent method for computing addresses so that + address computations don't need to be a part of load and + store instructions in the IR.
        • +
        • Support non-C-like languages, to the extent that it doesn't + interfere with other goals.
        • +
        • Minimize target-specific information in the IR.
        • +
        +
        + + + +
        +

        The specific type i32 is probably just a historical artifact, however it's + wide enough for all practical purposes, so there's been no need to change it. + It doesn't necessarily imply i32 address arithmetic; it's just an identifier + which identifies a field in a struct. Requiring that all struct indices be + the same reduces the range of possibilities for cases where two GEPs are + effectively the same but have distinct operand types.

        + +
        + + + + +
        +

        Some LLVM optimizers operate on GEPs by internally lowering them into + more primitive integer expressions, which allows them to be combined + with other integer expressions and/or split into multiple separate + integer expressions. If they've made non-trivial changes, translating + back into LLVM IR can involve reverse-engineering the structure of + the addressing in order to fit it into the static type of the original + first operand. It isn't always possibly to fully reconstruct this + structure; sometimes the underlying addressing doesn't correspond with + the static type at all. In such cases the optimizer instead will emit + a GEP with the base pointer casted to a simple address-unit pointer, + using the name "uglygep". This isn't pretty, but it's just as + valid, and it's sufficient to preserve the pointer aliasing guarantees + that GEP provides.

        + +
        + @@ -365,7 +728,7 @@ idx3 = (char*) &MyVar + 8 Valid HTML 4.01 The LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-10-12 07:46:08 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2010-02-26 02:16:03 +0800 (五, 26 2月 2010) $ diff --git a/docs/GettingStarted.html b/docs/GettingStarted.html index 8d865d6f7a..42005b2731 100644 --- a/docs/GettingStarted.html +++ b/docs/GettingStarted.html @@ -256,13 +256,13 @@ software you will need.

        Cygwin/Win32 x861,8, 11 - GCC 3.4.X, binutils 2.15 + GCC 3.4.X, binutils 2.20 MinGW/Win32 x861,6, 8, 10 - GCC 3.4.X, binutils 2.15 + GCC 3.4.X, binutils 2.20 @@ -318,12 +318,8 @@ up
      • The GCC-based C/C++ frontend does not build
      • The port is done using the MSYS shell.
      • Native code generation exists but is not complete.
      • -
      • Binutils up to post-2.17 has bug in bfd/cofflink.c - preventing LLVM from building correctly. Several workarounds have been - introduced into LLVM build system, but the bug can occur anytime in the - future. We highly recommend that you rebuild your current binutils with the - patch from - Binutils bugzilla, if it wasn't already applied.
      • +
      • Binutils 2.20 or later is required to build the assembler + generated by LLVM properly.
      • XCode 2.5 and gcc 4.0.1 (Apple Build 5370) will trip internal LLVM assert messages when compiled for Release at optimization levels greater than 0 (i.e., "-O1" and higher). @@ -1197,10 +1193,16 @@ $ ./hello.bc
      • -This allows you to execute LLVM bitcode files directly. Thanks to Jack -Cummings for pointing this out! +This allows you to execute LLVM bitcode files directly. On Debian, you +can also use this command instead of the 'echo' command above:

        +
        +
        +$ sudo update-binfmts --install llvm /path/to/lli --magic 'BC'
        +
        +
        + @@ -1367,7 +1369,7 @@ end to compile.

        The tools directory contains the executables built out of the libraries above, which form the main part of the user interface. You can -always get help for a tool by typing tool_name --help. The +always get help for a tool by typing tool_name -help. The following is a brief introduction to the most important tools. More detailed information is in the Command Guide.

        @@ -1438,7 +1440,7 @@ information is in the Command Guide.

        opt
        opt reads LLVM bitcode, applies a series of LLVM to LLVM transformations (which are specified on the command line), and then outputs - the resultant bitcode. The 'opt --help' command is a good way to + the resultant bitcode. The 'opt -help' command is a good way to get a list of the program transformations available in LLVM.
        opt can also be used to run a specific analysis on an input LLVM bitcode file and print out the results. It is primarily useful for @@ -1671,7 +1673,7 @@ out:

        Chris Lattner
        Reid Spencer
        The LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-12-17 09:18:11 -0800 (Thu, 17 Dec 2009) $ + Last modified: $Date: 2010-02-18 22:08:13 +0800 (四, 18 2月 2010) $ diff --git a/docs/GettingStartedVS.html b/docs/GettingStartedVS.html index 33ed206f19..07aed2590b 100644 --- a/docs/GettingStartedVS.html +++ b/docs/GettingStartedVS.html @@ -411,7 +411,7 @@ out:

        Jeff Cohen
        The LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-08-05 08:42:44 -0700 (Wed, 05 Aug 2009) $ + Last modified: $Date: 2009-08-05 23:42:44 +0800 (三, 05 8月 2009) $ diff --git a/docs/HowToReleaseLLVM.html b/docs/HowToReleaseLLVM.html index f2c1b0278f..fed604f465 100644 --- a/docs/HowToReleaseLLVM.html +++ b/docs/HowToReleaseLLVM.html @@ -518,7 +518,7 @@ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XX \ src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"> The LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-10-12 07:46:08 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2009-10-12 22:46:08 +0800 (一, 12 10月 2009) $ diff --git a/docs/HowToSubmitABug.html b/docs/HowToSubmitABug.html index 7923956c32..97568f20d6 100644 --- a/docs/HowToSubmitABug.html +++ b/docs/HowToSubmitABug.html @@ -348,7 +348,7 @@ the following:

        Chris Lattner
        The LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-10-12 07:46:08 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2009-10-12 22:46:08 +0800 (一, 12 10月 2009) $ diff --git a/docs/LangRef.html b/docs/LangRef.html index eea369d082..6a965cee80 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -66,12 +66,17 @@
      • Derived Types
          -
        1. Array Type
        2. +
        3. Aggregate Types +
            +
          1. Array Type
          2. +
          3. Structure Type
          4. +
          5. Packed Structure Type
          6. +
          7. Union Type
          8. +
          9. Vector Type
          10. +
          +
        4. Function Type
        5. Pointer Type
        6. -
        7. Structure Type
        8. -
        9. Packed Structure Type
        10. -
        11. Vector Type
        12. Opaque Type
      • @@ -843,7 +848,7 @@ define i32 @main() { ; i32()*
        -

        LLVM function definitions consist of the "define" keyord, an +

        LLVM function definitions consist of the "define" keyword, an optional linkage type, an optional visibility style, an optional calling convention, a return type, an optional @@ -1078,6 +1083,11 @@ define void @f() optsize { ... }

        +
        alignstack(<n>)
        +
        This attribute indicates that, when emitting the prologue and epilogue, + the backend should forcibly align the stack pointer. Specify the + desired alignment, which must be a power of two, in parentheses. +
        alwaysinline
        This attribute indicates that the inliner should attempt to inline this function into callers whenever possible, ignoring any active inlining size @@ -1267,7 +1277,7 @@ target datalayout = "layout specification"
        • E - big endian
        • -
        • p:32:64:64 - 32-bit pointers with 64-bit alignment
        • +
        • p:64:64:64 - 64-bit pointers with 64-bit alignment
        • i1:8:8 - i1 is 8-bit (byte) aligned
        • i8:8:8 - i8 is 8-bit (byte) aligned
        • i16:16:16 - i16 is 16-bit aligned
        • @@ -1399,6 +1409,7 @@ Classifications pointer, vector, structure, + union, array, label, metadata. @@ -1413,12 +1424,12 @@ Classifications derived - integer, - array, + array, function, pointer, structure, packed structure, + union, vector, opaque. @@ -1556,6 +1567,21 @@ Classifications possible to have a two dimensional array, using an array as the element type of another array.

          + + + + + + +
          + +

          Aggregate Types are a subset of derived types that can contain multiple + member types. Arrays, + structs, vectors and + unions are aggregate types.

          + +
          + @@ -1624,9 +1650,9 @@ Classifications
          Overview:

          The function type can be thought of as a function signature. It consists of a return type and a list of formal parameter types. The return type of a - function type is a scalar type, a void type, or a struct type. If the return - type is a struct type then all struct elements must be of first class types, - and the struct must have at least one element.

          + function type is a scalar type, a void type, a struct type, or a union + type. If the return type is a struct type then all struct elements must be + of first class types, and the struct must have at least one element.

          Syntax:
          @@ -1638,7 +1664,7 @@ Classifications 
              which indicates that the function takes a variable number of arguments.
              Variable argument functions can access their arguments with
              the variable argument handling intrinsic
          -   functions.  '<returntype>' is a any type except
          +   functions.  '<returntype>' is any type except
              label.

          Examples:
          @@ -1648,12 +1674,11 @@ Classifications function taking an i32, returning an i32 - float (i16 signext, i32 *) * + float (i16, i32 *) * Pointer to a function that takes - an i16 that should be sign extended and a - pointer to i32, returning - float. + an i16 and a pointer to i32, + returning float. i32 (i8*, ...) @@ -1748,16 +1773,66 @@ Classifications + + + +
          + +
          Overview:
          +

          A union type describes an object with size and alignment suitable for + an object of any one of a given set of types (also known as an "untagged" + union). It is similar in concept and usage to a + struct, except that all members of the union + have an offset of zero. The elements of a union may be any type that has a + size. Unions must have at least one member - empty unions are not allowed. +

          + +

          The size of the union as a whole will be the size of its largest member, + and the alignment requirements of the union as a whole will be the largest + alignment requirement of any member.

          + +

          Union members are accessed using 'load and + 'store' by getting a pointer to a field with + the 'getelementptr' instruction. + Since all members are at offset zero, the getelementptr instruction does + not affect the address, only the type of the resulting pointer.

          + +
          Syntax:
          +
          +  union { <type list> }
          +
          + +
          Examples:
          + + + + + + + + +
          union { i32, i32*, float }A union of three types: an i32, a pointer to + an i32, and a float.
          + union { float, i32 (i32) * }A union, where the first element is a float and the + second element is a pointer to a + function that takes an i32, returning + an i32.
          + +
          +
          Overview:
          -

          As in many languages, the pointer type represents a pointer or reference to - another object, which must live in memory. Pointer types may have an optional - address space attribute defining the target-specific numbered address space - where the pointed-to object resides. The default address space is zero.

          +

          The pointer type is used to specify memory locations. + Pointers are commonly used to reference objects in memory.

          + +

          Pointer types may have an optional address space attribute defining the + numbered address space where the pointed-to object resides. The default + address space is number zero. The semantics of non-zero address + spaces are target-specific.

          Note that LLVM does not permit pointers to void (void*) nor does it permit pointers to labels (label*). Use i8* instead.

          @@ -1986,6 +2061,14 @@ Classifications
          the number and types of elements must match those specified by the type.
        +
        Union constants
        +
        Union constants are represented with notation similar to a structure with + a single element - that is, a single typed element surrounded + by braces ({})). For example: "{ i32 4 }". The + union type can be initialized with a single-element + struct as long as the type of the struct element matches the type of + one of the union members.
        +
        Array constants
        Array constants are represented with notation similar to array type definitions (a comma separated list of elements, surrounded by square @@ -2004,7 +2087,8 @@ Classifications
        Zero initialization
        The string 'zeroinitializer' can be used to zero initialize a - value to zero of any type, including scalar and aggregate types. + value to zero of any type, including scalar and + aggregate types. This is often used to avoid having to print large zero initializers (e.g. for large arrays) and is always exactly equivalent to using explicit zero initializers.
        @@ -2436,6 +2520,23 @@ call void asm alignstack "eieio", ""() metadata nodes, which can be looked up in the module symbol table. For example: "!foo = metadata !{!4, !3}". +

        Metadata can be used as function arguments. Here llvm.dbg.value + function is using two metadata arguments. + +

        +
        +       call void @llvm.dbg.value(metadata !24, i64 0, metadata !25)
        +     
        +

        + +

        Metadata can be attached with an instruction. Here metadata !21 is + attached with add instruction using !dbg identifier. + +

        +
        +      %indvar.next = add i64 %indvar, 1, !dbg !21
        +    
        +

        @@ -2803,9 +2904,10 @@ IfUnequal: function to be invoked.
      • 'function args': argument list whose types match the function - signature argument types. If the function signature indicates the - function accepts a variable number of arguments, the extra arguments can - be specified.
      • + signature argument types and parameter attributes. All arguments must be + of first class type. If the function + signature indicates the function accepts a variable number of arguments, + the extra arguments can be specified.
      • 'normal label': the label reached when the called function executes a 'ret' instruction.
      • @@ -3840,7 +3942,8 @@ Instruction
        -

        LLVM supports several instructions for working with aggregate values.

        +

        LLVM supports several instructions for working with + aggregate values.

        @@ -3857,14 +3960,14 @@ Instruction
        Overview:
        -

        The 'extractvalue' instruction extracts the value of a struct field - or array element from an aggregate value.

        +

        The 'extractvalue' instruction extracts the value of a member field + from an aggregate value.

        Arguments:

        The first operand of an 'extractvalue' instruction is a value - of struct or array type. The - operands are constant indices to specify which value to extract in a similar - manner as indices in a + of struct, union or + array type. The operands are constant indices to + specify which value to extract in a similar manner as indices in a 'getelementptr' instruction.

        Semantics:
        @@ -3891,16 +3994,15 @@ Instruction
        Overview:
        -

        The 'insertvalue' instruction inserts a value into a struct field or - array element in an aggregate.

        - +

        The 'insertvalue' instruction inserts a value into a member field + in an aggregate value.

        Arguments:

        The first operand of an 'insertvalue' instruction is a value - of struct or array type. The - second operand is a first-class value to insert. The following operands are - constant indices indicating the position at which to insert the value in a - similar manner as indices in a + of struct, union or + array type. The second operand is a first-class + value to insert. The following operands are constant indices indicating + the position at which to insert the value in a similar manner as indices in a 'getelementptr' instruction. The value to insert must have the same type as the value identified by the indices.

        @@ -3992,8 +4094,9 @@ Instruction
        Syntax:
        -  <result> = load <ty>* <pointer>[, align <alignment>]
        -  <result> = volatile load <ty>* <pointer>[, align <alignment>]
        +  <result> = load <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
        +  <result> = volatile load <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
        +  !<index> = !{ i32 1 }
         
        Overview:
        @@ -4006,16 +4109,24 @@ Instruction marked as volatile, then the optimizer is not allowed to modify the number or order of execution of this load with other volatile load and store - instructions.

        + instructions.

        -

        The optional constant "align" argument specifies the alignment of the +

        The optional constant align argument specifies the alignment of the operation (that is, the alignment of the memory address). A value of 0 or an - omitted "align" argument means that the operation has the preferential + omitted align argument means that the operation has the preferential alignment for the target. It is the responsibility of the code emitter to ensure that the alignment information is correct. Overestimating the - alignment results in an undefined behavior. Underestimating the alignment may + alignment results in undefined behavior. Underestimating the alignment may produce less efficient code. An alignment of 1 is always safe.

        +

        The optional !nontemporal metadata must reference a single + metatadata name <index> corresponding to a metadata node with + one i32 entry of value 1. The existence of + the !nontemporal metatadata on the instruction tells the optimizer + and code generator that this load is not expected to be reused in the cache. + The code generator may select special instructions to save cache bandwidth, + such as the MOVNT instruction on x86.

        +
        Semantics:

        The location of memory pointed to is loaded. If the value being loaded is of scalar type then the number of bytes read does not exceed the minimum number @@ -4042,8 +4153,8 @@ Instruction

        Syntax:
        -  store <ty> <value>, <ty>* <pointer>[, align <alignment>]                   ; yields {void}
        -  volatile store <ty> <value>, <ty>* <pointer>[, align <alignment>]          ; yields {void}
        +  store <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !]                   ; yields {void}
        +  volatile store <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !]          ; yields {void}
         
        Overview:
        @@ -4068,6 +4179,15 @@ Instruction alignment results in an undefined behavior. Underestimating the alignment may produce less efficient code. An alignment of 1 is always safe.

        +

        The optional !nontemporal metadata must reference a single metatadata + name corresponding to a metadata node with one i32 entry of + value 1. The existence of the !nontemporal metatadata on the + instruction tells the optimizer and code generator that this load is + not expected to be reused in the cache. The code generator may + select special instructions to save cache bandwidth, such as the + MOVNT instruction on x86.

        + +
        Semantics:

        The contents of memory are updated to contain '<value>' at the location specified by the '<pointer>' operand. If @@ -4102,8 +4222,8 @@ Instruction

        Overview:

        The 'getelementptr' instruction is used to get the address of a - subelement of an aggregate data structure. It performs address calculation - only and does not access memory.

        + subelement of an aggregate data structure. + It performs address calculation only and does not access memory.

        Arguments:

        The first argument is always a pointer, and forms the basis of the @@ -4113,15 +4233,15 @@ Instruction indexes the pointer value given as the first argument, the second index indexes a value of the type pointed to (not necessarily the value directly pointed to, since the first index can be non-zero), etc. The first type - indexed into must be a pointer value, subsequent types can be arrays, vectors - and structs. Note that subsequent types being indexed into can never be - pointers, since that would require loading the pointer before continuing - calculation.

        + indexed into must be a pointer value, subsequent types can be arrays, + vectors, structs and unions. Note that subsequent types being indexed into + can never be pointers, since that would require loading the pointer before + continuing calculation.

        The type of each index argument depends on the type it is indexing into. - When indexing into a (optionally packed) structure, only i32 integer - constants are allowed. When indexing into an array, pointer or - vector, integers of any width are allowed, and they are not required to be + When indexing into a (optionally packed) structure or union, only i32 + integer constants are allowed. When indexing into an array, pointer + or vector, integers of any width are allowed, and they are not required to be constant.

        For example, let's consider a C code fragment and how it gets compiled to @@ -4861,7 +4981,7 @@ entry: op1 is equal to op2.

      • ogt: yields true if both operands are not a QNAN and - op1 is greather than op2.
      • + op1 is greater than op2.
      • oge: yields true if both operands are not a QNAN and op1 is greater than or equal to op2.
      • @@ -5037,7 +5157,7 @@ Loop: ; Infinite loop that counts from 0 on up...
      • The call is in tail position (ret immediately follows call and ret uses value of call or is void).
      • Option -tailcallopt is enabled, - or llvm::PerformTailCallOpt is true.
      • + or llvm::GuaranteedTailCallOpt is true.
      • Platform specific constraints are met.
      @@ -5068,10 +5188,10 @@ Loop: ; Infinite loop that counts from 0 on up... to function value.
    • 'function args': argument list whose types match the function - signature argument types. All arguments must be of - first class type. If the function signature - indicates the function accepts a variable number of arguments, the extra - arguments can be specified.
    • + signature argument types and parameter attributes. All arguments must be + of first class type. If the function + signature indicates the function accepts a variable number of arguments, + the extra arguments can be specified.
    • The optional function attributes list. Only 'noreturn', 'nounwind', 'readonly' and @@ -5106,7 +5226,7 @@ Loop: ; Infinite loop that counts from 0 on up... standard C99 library as being the C99 library functions, and may perform optimizations or generate code for them under that assumption. This is something we'd like to change in the future to provide better support for -freestanding environments and non-C-based langauges.

      +freestanding environments and non-C-based languages.

      @@ -5662,7 +5782,7 @@ LLVM.

      Semantics:

      This intrinsic does not modify the behavior of the program. Backends that do - not support this intrinisic may ignore it.

      + not support this intrinsic may ignore it.

      @@ -5742,7 +5862,7 @@ LLVM.

      number of bytes to copy, and the fourth argument is the alignment of the source and destination locations.

      -

      If the call to this intrinisic has an alignment value that is not 0 or 1, +

      If the call to this intrinsic has an alignment value that is not 0 or 1, then the caller guarantees that both the source and destination pointers are aligned to that boundary.

      @@ -5792,7 +5912,7 @@ LLVM.

      number of bytes to copy, and the fourth argument is the alignment of the source and destination locations.

      -

      If the call to this intrinisic has an alignment value that is not 0 or 1, +

      If the call to this intrinsic has an alignment value that is not 0 or 1, then the caller guarantees that the source and destination pointers are aligned to that boundary.

      @@ -5840,7 +5960,7 @@ LLVM.

      specifying the number of bytes to fill, and the fourth argument is the known alignment of destination location.

      -

      If the call to this intrinisic has an alignment value that is not 0 or 1, +

      If the call to this intrinsic has an alignment value that is not 0 or 1, then the caller guarantees that the destination pointer is aligned to that boundary.

      @@ -6611,7 +6731,7 @@ LLVM.

      Arguments:

      The llvm.memory.barrier intrinsic requires five boolean arguments. The first four arguments enables a specific barrier as listed below. The - fith argument specifies that the barrier applies to io or device or uncached + fifth argument specifies that the barrier applies to io or device or uncached memory.

        @@ -7350,7 +7470,7 @@ LLVM.

        Chris Lattner
        The LLVM Compiler Infrastructure
        - Last modified: $Date: 2010-02-05 17:16:28 -0800 (Fri, 05 Feb 2010) $ + Last modified: $Date: 2010-03-05 07:44:48 +0800 (五, 05 3月 2010) $ diff --git a/docs/Lexicon.html b/docs/Lexicon.html index 398be762dc..d8c0ba59ca 100644 --- a/docs/Lexicon.html +++ b/docs/Lexicon.html @@ -255,7 +255,7 @@ href="http://www.program-transformation.org/Transform/BURG">BURG tool. src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01">The LLVM Team
        The LLVM Compiler Infrastructure
        -Last modified: $Date: 2008-12-14 00:01:51 -0800 (Sun, 14 Dec 2008) $ +Last modified: $Date: 2008-12-14 16:01:51 +0800 (日, 14 12月 2008) $ diff --git a/docs/LinkTimeOptimization.html b/docs/LinkTimeOptimization.html index 90460d0882..7c2f986ff1 100644 --- a/docs/LinkTimeOptimization.html +++ b/docs/LinkTimeOptimization.html @@ -382,7 +382,7 @@ of the native object files.

        Devang Patel and Nick Kledzik
        LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-10-12 07:46:08 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2009-10-12 22:46:08 +0800 (一, 12 10月 2009) $ diff --git a/docs/Makefile b/docs/Makefile index 5bfa6c3cfb..8f7d6171d3 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -48,11 +48,11 @@ generated:: doxygen ocamldoc install-html: $(PROJ_OBJ_DIR)/html.tar.gz $(Echo) Installing HTML documentation - $(Verb) $(MKDIR) $(PROJ_docsdir)/html - $(Verb) $(MKDIR) $(PROJ_docsdir)/html/img - $(Verb) $(DataInstall) $(HTML) $(PROJ_docsdir)/html - $(Verb) $(DataInstall) $(IMAGES) $(PROJ_docsdir)/html/img - $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(PROJ_docsdir) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/img + $(Verb) $(DataInstall) $(HTML) $(DESTDIR)$(PROJ_docsdir)/html + $(Verb) $(DataInstall) $(IMAGES) $(DESTDIR)$(PROJ_docsdir)/html/img + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/html.tar.gz $(DESTDIR)$(PROJ_docsdir) $(PROJ_OBJ_DIR)/html.tar.gz: $(HTML) $(Echo) Packaging HTML documentation @@ -63,11 +63,11 @@ $(PROJ_OBJ_DIR)/html.tar.gz: $(HTML) install-doxygen: doxygen $(Echo) Installing doxygen documentation - $(Verb) $(MKDIR) $(PROJ_docsdir)/html/doxygen - $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(PROJ_docsdir) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/html/doxygen + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/doxygen.tar.gz $(DESTDIR)$(PROJ_docsdir) $(Verb) cd $(PROJ_OBJ_DIR)/doxygen && \ $(FIND) . -type f -exec \ - $(DataInstall) {} $(PROJ_docsdir)/html/doxygen \; + $(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/html/doxygen \; doxygen: regendoc $(PROJ_OBJ_DIR)/doxygen.tar.gz @@ -94,11 +94,11 @@ $(LLVM_SRC_ROOT)/docs/userloc.html: install-ocamldoc: ocamldoc $(Echo) Installing ocamldoc documentation - $(Verb) $(MKDIR) $(PROJ_docsdir)/ocamldoc/html - $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_docsdir) + $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_docsdir)/ocamldoc/html + $(Verb) $(DataInstall) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(DESTDIR)$(PROJ_docsdir) $(Verb) cd $(PROJ_OBJ_DIR)/ocamldoc && \ $(FIND) . -type f -exec \ - $(DataInstall) {} $(PROJ_docsdir)/ocamldoc/html \; + $(DataInstall) {} $(DESTDIR)$(PROJ_docsdir)/ocamldoc/html \; ocamldoc: regen-ocamldoc $(Echo) Packaging ocamldoc documentation @@ -120,4 +120,4 @@ regen-ocamldoc: uninstall-local:: $(Echo) Uninstalling Documentation - $(Verb) $(RM) -rf $(PROJ_docsdir) + $(Verb) $(RM) -rf $(DESTDIR)$(PROJ_docsdir) diff --git a/docs/MakefileGuide.html b/docs/MakefileGuide.html index 6c06c9f933..37b0d019e6 100644 --- a/docs/MakefileGuide.html +++ b/docs/MakefileGuide.html @@ -818,6 +818,10 @@ mklib by the configure script and always located in the
        LLVMAS(defaulted)
        Specifies the path to the llvm-as tool.
        +
        LLVMCC
        +
        Specifies the path to the LLVM capable compiler.
        +
        LLVMCXX
        +
        Specifies the path to the LLVM C++ capable compiler.
        LLVMGCC(defaulted)
        Specifies the path to the LLVM version of the GCC 'C' Compiler
        LLVMGXX(defaulted)
        @@ -1021,7 +1025,7 @@ Reid Spencer
        The LLVM Compiler Infrastructure
        - Last modified: $Date: 2009-10-12 07:46:08 -0700 (Mon, 12 Oct 2009) $ + Last modified: $Date: 2010-02-23 18:00:53 +0800 (二, 23 2月 2010) $ diff --git a/docs/Packaging.html b/docs/Packaging.html new file mode 100644 index 0000000000..883e755804 --- /dev/null +++ b/docs/Packaging.html @@ -0,0 +1,118 @@ + + + + Advice on Packaging LLVM + + + + +
        Advice on Packaging LLVM
        +
          +
        1. Overview
        2. +
        3. Compile Flags
        4. +
        5. C++ Features
        6. +
        7. Shared Library
        8. +
        9. Dependencies
        10. +
        + + + + +
        + +

        LLVM sets certain default configure options to make sure our developers don't +break things for constrained platforms. These settings are not optimal for most +desktop systems, and we hope that packagers (e.g., Redhat, Debian, MacPorts, +etc.) will tweak them. This document lists settings we suggest you tweak. +

        + +

        LLVM's API changes with each release, so users are likely to want, for +example, both LLVM-2.6 and LLVM-2.7 installed at the same time to support apps +developed against each. +

        +
        + + + + +
        + +

        LLVM runs much more quickly when it's optimized and assertions are removed. +However, such a build is currently incompatible with users who build without +defining NDEBUG, and the lack of assertions makes it hard to debug problems in +user code. We recommend allowing users to install both optimized and debug +versions of LLVM in parallel. The following configure flags are relevant: +

        + +
        +
        --disable-assertions
        Builds LLVM with NDEBUG + defined. Changes the LLVM ABI. Also available by setting + DISABLE_ASSERTIONS=0|1 in make's environment. This defaults + to enabled regardless of the optimization setting, but it slows things + down.
        + +
        --enable-debug-symbols
        Builds LLVM with -g. + Also available by setting DEBUG_SYMBOLS=0|1 in make's + environment. This defaults to disabled when optimizing, so you should turn it + back on to let users debug their programs.
        + +
        --enable-optimized
        (For svn checkouts) Builds LLVM with + -O2 and, by default, turns off debug symbols. Also available by + setting ENABLE_OPTIMIZED=0|1 in make's environment. This + defaults to enabled when not in a checkout.
        +
        +
        + + + + +
        + +
        +
        RTTI
        LLVM disables RTTI by default. Add REQUIRES_RTTI=1 + to your environment while running make to re-enable it. This will + allow users to build with RTTI enabled and still inherit from LLVM + classes.
        +
        +
        + + + + +
        + +

        Configure with --enable-shared to build +libLLVM-major.minor.(so|dylib) and link the tools +against it. This saves lots of binary size at the cost of some startup time. +

        +
        + + + + +
        + +
        +
        --enable-libffi
        Depend on libffi to allow the LLVM +interpreter to call external functions.
        +
        --with-oprofile
        Depend on libopagent +(>=version 0.9.4) to let the LLVM JIT tell oprofile about function addresses and +line numbers.
        +
        +
        + + +
        +
        + Valid CSS + Valid HTML 4.01 + The LLVM Compiler Infrastructure
        + Last modified: $Date: 2010-02-27 06:25:06 +0800 (六, 27 2月 2010) $ +
        + + diff --git a/docs/Passes.html b/docs/Passes.html index c366808c1d..a0b233711b 100644 --- a/docs/Passes.html +++ b/docs/Passes.html @@ -75,7 +75,6 @@ perl -e '$/ = undef; for (split(/\n/, <>)) { s:^ *///? ?::; print "

        \n" if ! ANALYSIS PASSES OptionName -aa-evalExhaustive Alias Analysis Precision Evaluator --anders-aaAndersen's Interprocedural Alias Analysis -basicaaBasic Alias Analysis (default AA impl) -basiccgBasic CallGraph Construction -codegenprepareOptimize for code generation @@ -202,80 +201,6 @@ perl -e '$/ = undef; for (split(/\n/, <>)) { s:^ *///? ?::; print "

        \n" if ! Spadini, and Wojciech Stryjewski.

        - - -
        -

        - This is an implementation of Andersen's interprocedural alias - analysis -

        - -

        - In pointer analysis terms, this is a subset-based, flow-insensitive, - field-sensitive, and context-insensitive algorithm pointer algorithm. -

        - -

        - This algorithm is implemented as three stages: -

        - -
          -
        1. Object identification.
        2. -
        3. Inclusion constraint identification.
        4. -
        5. Offline constraint graph optimization.
        6. -
        7. Inclusion constraint solving.
        8. -
        - -

        - The object identification stage identifies all of the memory objects in the - program, which includes globals, heap allocated objects, and stack allocated - objects. -

        - -

        - The inclusion constraint identification stage finds all inclusion constraints - in the program by scanning the program, looking for pointer assignments and - other statements that effect the points-to graph. For a statement like - A = B, this statement is processed to - indicate that A can point to anything that B can point - to. Constraints can handle copies, loads, and stores, and address taking. -

        - -

        - The offline constraint graph optimization portion includes offline variable - substitution algorithms intended to computer pointer and location - equivalences. Pointer equivalences are those pointers that will have the - same points-to sets, and location equivalences are those variables that - always appear together in points-to sets. -

        - -

        - The inclusion constraint solving phase iteratively propagates the inclusion - constraints until a fixed point is reached. This is an O(n³) - algorithm. -

        - -

        - Function constraints are handled as if they were structs with X - fields. Thus, an access to argument X of function Y is - an access to node index getNode(Y) + X. - This representation allows handling of indirect calls without any issues. To - wit, an indirect call Y(a,b) is - equivalent to *(Y + 1) = a, *(Y + 2) = - b. The return node for a function F is always - located at getNode(F) + CallReturnPos. The arguments - start at getNode(F) + CallArgPos. -

        - -

        - Please keep in mind that the current andersen's pass has many known - problems and bugs. It should be considered "research quality". -

        - -
        -
        -

        ilists have another speciality that must be considered. To be a good +

        ilists have another specialty that must be considered. To be a good citizen in the C++ ecosystem, it needs to support the standard container operations, such as begin and end iterators, etc. Also, the operator-- must work correctly on the end iterator in the @@ -2999,9 +2999,9 @@ the lib/VMCore directory.

        +

        Also, -anders-aa was removed

        +
        @@ -467,6 +469,10 @@ href="http://llvm.org/viewvc/llvm-project?view=rev&revision=85295">defaults to compiling eagerly to avoid a race condition in the lazy JIT. Clients that still want the lazy JIT can switch it on by calling ExecutionEngine::DisableLazyCompilation(false). +
      • It is now possible to create more than one JIT instance in the same process. +These JITs can generate machine code in parallel, +although you +still have to obey the other threading restrictions.
      @@ -637,6 +643,13 @@ Clients must replace calls to
    • FIXME: Debug info has been totally redone. Add pointers to new APIs. Substantial caveats about compatibility of .ll and .bc files.
    • +
    • The llvm/Support/DataTypes.h header has moved +to llvm/System/DataTypes.h.
    • + +
    • The isInteger, isIntOrIntVector, isFloatingPoint, +isFPOrFPVector and isFPOrFPVector methods have been renamed +isIntegerTy, isIntOrIntVectorTy, isFloatingPointTy, +isFPOrFPVectorTy and isFPOrFPVectorTy respectively.
    @@ -722,7 +735,6 @@ href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVMdev list.

    experimental.
  • The llc "-filetype=asm" (the default) is the only supported value for this option. The ELF writer is experimental.
  • -
  • The implementation of Andersen's Alias Analysis has many known bugs.
  • @@ -985,7 +997,7 @@ lists.

    src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"> LLVM Compiler Infrastructure
    - Last modified: $Date: 2010-02-09 20:09:52 -0800 (Tue, 09 Feb 2010) $ + Last modified: $Date: 2010-03-02 03:29:17 +0800 (二, 02 3月 2010) $ diff --git a/docs/SourceLevelDebugging.html b/docs/SourceLevelDebugging.html index e1c78a9d37..231ce5445b 100644 --- a/docs/SourceLevelDebugging.html +++ b/docs/SourceLevelDebugging.html @@ -1738,7 +1738,7 @@ enum Trees { Chris Lattner
    LLVM Compiler Infrastructure
    - Last modified: $Date: 2010-01-11 14:53:48 -0800 (Mon, 11 Jan 2010) $ + Last modified: $Date: 2010-01-12 06:53:48 +0800 (二, 12 1月 2010) $ diff --git a/docs/SystemLibrary.html b/docs/SystemLibrary.html index c438ee7862..52d9b21294 100644 --- a/docs/SystemLibrary.html +++ b/docs/SystemLibrary.html @@ -313,7 +313,7 @@ Reid Spencer
    LLVM Compiler Infrastructure
    - Last modified: $Date: 2009-07-17 14:11:24 -0700 (Fri, 17 Jul 2009) $ + Last modified: $Date: 2009-07-18 05:11:24 +0800 (六, 18 7月 2009) $ diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html index 05d519907e..fd93fc31b7 100644 --- a/docs/TableGenFundamentals.html +++ b/docs/TableGenFundamentals.html @@ -155,7 +155,6 @@ file prints this (at the time of this writing):

    bit hasCtrlDep = 0; bit isNotDuplicable = 0; bit hasSideEffects = 0; - bit mayHaveSideEffects = 0; bit neverHasSideEffects = 0; InstrItinClass Itinerary = NoItinerary; string Constraints = ""; @@ -189,7 +188,7 @@ backend, and is only shown as an example.

    As you can see, a lot of information is needed for every instruction supported by the code generator, and specifying it all manually would be -unmaintainble, prone to bugs, and tiring to do in the first place. Because we +unmaintainable, prone to bugs, and tiring to do in the first place. Because we are using TableGen, all of the information was derived from the following definition:

    @@ -798,7 +797,7 @@ This should highlight the APIs in TableGen/Record.h.

    Chris Lattner
    LLVM Compiler Infrastructure
    - Last modified: $Date: 2010-01-05 11:11:42 -0800 (Tue, 05 Jan 2010) $ + Last modified: $Date: 2010-02-28 07:47:46 +0800 (日, 28 2月 2010) $ diff --git a/docs/TestingGuide.html b/docs/TestingGuide.html index d776afe9b9..f1584c3ea8 100644 --- a/docs/TestingGuide.html +++ b/docs/TestingGuide.html @@ -693,8 +693,6 @@ that FileCheck is not actually line-oriented when it matches, this allows you to define two separate CHECK lines that match on the same line.

    - - @@ -761,12 +759,6 @@ substitutions
    The full path to the llvm-gxx executable as specified in the configured LLVM environment
    -
    llvmgcc_version (%llvmgcc_version)
    -
    The full version number of the llvm-gcc executable.
    - -
    llvmgccmajvers (%llvmgccmajvers)
    -
    The major version number of the llvm-gcc executable.
    -
    gccpath
    The full path to the C compiler used to build LLVM. Note that this might not be gcc.
    @@ -824,22 +816,20 @@ substitutions

    Sometimes it is necessary to mark a test case as "expected fail" or XFAIL. - You can easily mark a test as XFAIL just by including XFAIL: on a + You can easily mark a test as XFAIL just by including XFAIL: on a line near the top of the file. This signals that the test case should succeed if the test fails. Such test cases are counted separately by DejaGnu. To specify an expected fail, use the XFAIL keyword in the comments of the test program followed by a colon and one or more regular expressions (separated by - a comma). The regular expressions allow you to XFAIL the test conditionally - by host platform. The regular expressions following the : are matched against - the target triplet or llvmgcc version number for the host machine. If there is - a match, the test is expected to fail. If not, the test is expected to - succeed. To XFAIL everywhere just specify XFAIL: *. When matching - the llvm-gcc version, you can specify the major (e.g. 3) or full version - (i.e. 3.4) number. Here is an example of an XFAIL line:

    + a comma). The regular expressions allow you to XFAIL the test conditionally by + host platform. The regular expressions following the : are matched against the + target triplet for the host machine. If there is a match, the test is expected + to fail. If not, the test is expected to succeed. To XFAIL everywhere just + specify XFAIL: *. Here is an example of an XFAIL line:

    -; XFAIL: darwin,sun,llvmgcc4
    +; XFAIL: darwin,sun
     
    @@ -1145,7 +1135,6 @@ example reports that can do fancy stuff.

    - @@ -1217,7 +1206,7 @@ know. Thanks!

    John T. Criswell, Reid Spencer, and Tanya Lattner
    The LLVM Compiler Infrastructure
    - Last modified: $Date: 2009-09-27 01:01:44 -0700 (Sun, 27 Sep 2009) $ + Last modified: $Date: 2010-02-27 05:23:59 +0800 (六, 27 2月 2010) $ diff --git a/docs/UsingLibraries.html b/docs/UsingLibraries.html index cf5333c01e..47e459c5b4 100644 --- a/docs/UsingLibraries.html +++ b/docs/UsingLibraries.html @@ -432,7 +432,7 @@ Reid Spencer The LLVM Compiler Infrastructure -
    Last modified: $Date: 2009-07-23 17:30:09 -0700 (Thu, 23 Jul 2009) $ +
    Last modified: $Date: 2009-07-24 08:30:09 +0800 (五, 24 7月 2009) $ - Constraints.push_back(Constraint(Constraint::Copy, - getReturnNode(RI.getParent()->getParent()), - getNode(RI.getOperand(0)))); -} - -void Andersens::visitLoadInst(LoadInst &LI) { - if (isa(LI.getType())) - // P1 = load P2 --> - Constraints.push_back(Constraint(Constraint::Load, getNodeValue(LI), - getNode(LI.getOperand(0)))); -} - -void Andersens::visitStoreInst(StoreInst &SI) { - if (isa(SI.getOperand(0)->getType())) - // store P1, P2 --> - Constraints.push_back(Constraint(Constraint::Store, - getNode(SI.getOperand(1)), - getNode(SI.getOperand(0)))); -} - -void Andersens::visitGetElementPtrInst(GetElementPtrInst &GEP) { - // P1 = getelementptr P2, ... --> - Constraints.push_back(Constraint(Constraint::Copy, getNodeValue(GEP), - getNode(GEP.getOperand(0)))); -} - -void Andersens::visitPHINode(PHINode &PN) { - if (isa(PN.getType())) { - unsigned PNN = getNodeValue(PN); - for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) - // P1 = phi P2, P3 --> , , ... - Constraints.push_back(Constraint(Constraint::Copy, PNN, - getNode(PN.getIncomingValue(i)))); - } -} - -void Andersens::visitCastInst(CastInst &CI) { - Value *Op = CI.getOperand(0); - if (isa(CI.getType())) { - if (isa(Op->getType())) { - // P1 = cast P2 --> - Constraints.push_back(Constraint(Constraint::Copy, getNodeValue(CI), - getNode(CI.getOperand(0)))); - } else { - // P1 = cast int --> -#if 0 - Constraints.push_back(Constraint(Constraint::Copy, getNodeValue(CI), - UniversalSet)); -#else - getNodeValue(CI); -#endif - } - } else if (isa(Op->getType())) { - // int = cast P1 --> -#if 0 - Constraints.push_back(Constraint(Constraint::Copy, - UniversalSet, - getNode(CI.getOperand(0)))); -#else - getNode(CI.getOperand(0)); -#endif - } -} - -void Andersens::visitSelectInst(SelectInst &SI) { - if (isa(SI.getType())) { - unsigned SIN = getNodeValue(SI); - // P1 = select C, P2, P3 ---> , - Constraints.push_back(Constraint(Constraint::Copy, SIN, - getNode(SI.getOperand(1)))); - Constraints.push_back(Constraint(Constraint::Copy, SIN, - getNode(SI.getOperand(2)))); - } -} - -void Andersens::visitVAArg(VAArgInst &I) { - llvm_unreachable("vaarg not handled yet!"); -} - -/// AddConstraintsForCall - Add constraints for a call with actual arguments -/// specified by CS to the function specified by F. Note that the types of -/// arguments might not match up in the case where this is an indirect call and -/// the function pointer has been casted. If this is the case, do something -/// reasonable. -void Andersens::AddConstraintsForCall(CallSite CS, Function *F) { - Value *CallValue = CS.getCalledValue(); - bool IsDeref = F == NULL; - - // If this is a call to an external function, try to handle it directly to get - // some taste of context sensitivity. - if (F && F->isDeclaration() && AddConstraintsForExternalCall(CS, F)) - return; - - if (isa(CS.getType())) { - unsigned CSN = getNode(CS.getInstruction()); - if (!F || isa(F->getFunctionType()->getReturnType())) { - if (IsDeref) - Constraints.push_back(Constraint(Constraint::Load, CSN, - getNode(CallValue), CallReturnPos)); - else - Constraints.push_back(Constraint(Constraint::Copy, CSN, - getNode(CallValue) + CallReturnPos)); - } else { - // If the function returns a non-pointer value, handle this just like we - // treat a nonpointer cast to pointer. - Constraints.push_back(Constraint(Constraint::Copy, CSN, - UniversalSet)); - } - } else if (F && isa(F->getFunctionType()->getReturnType())) { -#if FULL_UNIVERSAL - Constraints.push_back(Constraint(Constraint::Copy, - UniversalSet, - getNode(CallValue) + CallReturnPos)); -#else - Constraints.push_back(Constraint(Constraint::Copy, - getNode(CallValue) + CallReturnPos, - UniversalSet)); -#endif - - - } - - CallSite::arg_iterator ArgI = CS.arg_begin(), ArgE = CS.arg_end(); - bool external = !F || F->isDeclaration(); - if (F) { - // Direct Call - Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end(); - for (; AI != AE && ArgI != ArgE; ++AI, ++ArgI) - { -#if !FULL_UNIVERSAL - if (external && isa((*ArgI)->getType())) - { - // Add constraint that ArgI can now point to anything due to - // escaping, as can everything it points to. The second portion of - // this should be taken care of by universal = *universal - Constraints.push_back(Constraint(Constraint::Copy, - getNode(*ArgI), - UniversalSet)); - } -#endif - if (isa(AI->getType())) { - if (isa((*ArgI)->getType())) { - // Copy the actual argument into the formal argument. - Constraints.push_back(Constraint(Constraint::Copy, getNode(AI), - getNode(*ArgI))); - } else { - Constraints.push_back(Constraint(Constraint::Copy, getNode(AI), - UniversalSet)); - } - } else if (isa((*ArgI)->getType())) { -#if FULL_UNIVERSAL - Constraints.push_back(Constraint(Constraint::Copy, - UniversalSet, - getNode(*ArgI))); -#else - Constraints.push_back(Constraint(Constraint::Copy, - getNode(*ArgI), - UniversalSet)); -#endif - } - } - } else { - //Indirect Call - unsigned ArgPos = CallFirstArgPos; - for (; ArgI != ArgE; ++ArgI) { - if (isa((*ArgI)->getType())) { - // Copy the actual argument into the formal argument. - Constraints.push_back(Constraint(Constraint::Store, - getNode(CallValue), - getNode(*ArgI), ArgPos++)); - } else { - Constraints.push_back(Constraint(Constraint::Store, - getNode (CallValue), - UniversalSet, ArgPos++)); - } - } - } - // Copy all pointers passed through the varargs section to the varargs node. - if (F && F->getFunctionType()->isVarArg()) - for (; ArgI != ArgE; ++ArgI) - if (isa((*ArgI)->getType())) - Constraints.push_back(Constraint(Constraint::Copy, getVarargNode(F), - getNode(*ArgI))); - // If more arguments are passed in than we track, just drop them on the floor. -} - -void Andersens::visitCallSite(CallSite CS) { - if (isa(CS.getType())) - getNodeValue(*CS.getInstruction()); - - if (Function *F = CS.getCalledFunction()) { - AddConstraintsForCall(CS, F); - } else { - AddConstraintsForCall(CS, NULL); - } -} - -//===----------------------------------------------------------------------===// -// Constraint Solving Phase -//===----------------------------------------------------------------------===// - -/// intersects - Return true if the points-to set of this node intersects -/// with the points-to set of the specified node. -bool Andersens::Node::intersects(Node *N) const { - return PointsTo->intersects(N->PointsTo); -} - -/// intersectsIgnoring - Return true if the points-to set of this node -/// intersects with the points-to set of the specified node on any nodes -/// except for the specified node to ignore. -bool Andersens::Node::intersectsIgnoring(Node *N, unsigned Ignoring) const { - // TODO: If we are only going to call this with the same value for Ignoring, - // we should move the special values out of the points-to bitmap. - bool WeHadIt = PointsTo->test(Ignoring); - bool NHadIt = N->PointsTo->test(Ignoring); - bool Result = false; - if (WeHadIt) - PointsTo->reset(Ignoring); - if (NHadIt) - N->PointsTo->reset(Ignoring); - Result = PointsTo->intersects(N->PointsTo); - if (WeHadIt) - PointsTo->set(Ignoring); - if (NHadIt) - N->PointsTo->set(Ignoring); - return Result; -} - - -/// Clump together address taken variables so that the points-to sets use up -/// less space and can be operated on faster. - -void Andersens::ClumpAddressTaken() { -#undef DEBUG_TYPE -#define DEBUG_TYPE "anders-aa-renumber" - std::vector Translate; - std::vector NewGraphNodes; - - Translate.resize(GraphNodes.size()); - unsigned NewPos = 0; - - for (unsigned i = 0; i < Constraints.size(); ++i) { - Constraint &C = Constraints[i]; - if (C.Type == Constraint::AddressOf) { - GraphNodes[C.Src].AddressTaken = true; - } - } - for (unsigned i = 0; i < NumberSpecialNodes; ++i) { - unsigned Pos = NewPos++; - Translate[i] = Pos; - NewGraphNodes.push_back(GraphNodes[i]); - DEBUG(dbgs() << "Renumbering node " << i << " to node " << Pos << "\n"); - } - - // I believe this ends up being faster than making two vectors and splicing - // them. - for (unsigned i = NumberSpecialNodes; i < GraphNodes.size(); ++i) { - if (GraphNodes[i].AddressTaken) { - unsigned Pos = NewPos++; - Translate[i] = Pos; - NewGraphNodes.push_back(GraphNodes[i]); - DEBUG(dbgs() << "Renumbering node " << i << " to node " << Pos << "\n"); - } - } - - for (unsigned i = NumberSpecialNodes; i < GraphNodes.size(); ++i) { - if (!GraphNodes[i].AddressTaken) { - unsigned Pos = NewPos++; - Translate[i] = Pos; - NewGraphNodes.push_back(GraphNodes[i]); - DEBUG(dbgs() << "Renumbering node " << i << " to node " << Pos << "\n"); - } - } - - for (DenseMap::iterator Iter = ValueNodes.begin(); - Iter != ValueNodes.end(); - ++Iter) - Iter->second = Translate[Iter->second]; - - for (DenseMap::iterator Iter = ObjectNodes.begin(); - Iter != ObjectNodes.end(); - ++Iter) - Iter->second = Translate[Iter->second]; - - for (DenseMap::iterator Iter = ReturnNodes.begin(); - Iter != ReturnNodes.end(); - ++Iter) - Iter->second = Translate[Iter->second]; - - for (DenseMap::iterator Iter = VarargNodes.begin(); - Iter != VarargNodes.end(); - ++Iter) - Iter->second = Translate[Iter->second]; - - for (unsigned i = 0; i < Constraints.size(); ++i) { - Constraint &C = Constraints[i]; - C.Src = Translate[C.Src]; - C.Dest = Translate[C.Dest]; - } - - GraphNodes.swap(NewGraphNodes); -#undef DEBUG_TYPE -#define DEBUG_TYPE "anders-aa" -} - -/// The technique used here is described in "Exploiting Pointer and Location -/// Equivalence to Optimize Pointer Analysis. In the 14th International Static -/// Analysis Symposium (SAS), August 2007." It is known as the "HVN" algorithm, -/// and is equivalent to value numbering the collapsed constraint graph without -/// evaluating unions. This is used as a pre-pass to HU in order to resolve -/// first order pointer dereferences and speed up/reduce memory usage of HU. -/// Running both is equivalent to HRU without the iteration -/// HVN in more detail: -/// Imagine the set of constraints was simply straight line code with no loops -/// (we eliminate cycles, so there are no loops), such as: -/// E = &D -/// E = &C -/// E = F -/// F = G -/// G = F -/// Applying value numbering to this code tells us: -/// G == F == E -/// -/// For HVN, this is as far as it goes. We assign new value numbers to every -/// "address node", and every "reference node". -/// To get the optimal result for this, we use a DFS + SCC (since all nodes in a -/// cycle must have the same value number since the = operation is really -/// inclusion, not overwrite), and value number nodes we receive points-to sets -/// before we value our own node. -/// The advantage of HU over HVN is that HU considers the inclusion property, so -/// that if you have -/// E = &D -/// E = &C -/// E = F -/// F = G -/// F = &D -/// G = F -/// HU will determine that G == F == E. HVN will not, because it cannot prove -/// that the points to information ends up being the same because they all -/// receive &D from E anyway. - -void Andersens::HVN() { - DEBUG(dbgs() << "Beginning HVN\n"); - // Build a predecessor graph. This is like our constraint graph with the - // edges going in the opposite direction, and there are edges for all the - // constraints, instead of just copy constraints. We also build implicit - // edges for constraints are implied but not explicit. I.E for the constraint - // a = &b, we add implicit edges *a = b. This helps us capture more cycles - for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { - Constraint &C = Constraints[i]; - if (C.Type == Constraint::AddressOf) { - GraphNodes[C.Src].AddressTaken = true; - GraphNodes[C.Src].Direct = false; - - // Dest = &src edge - unsigned AdrNode = C.Src + FirstAdrNode; - if (!GraphNodes[C.Dest].PredEdges) - GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; - GraphNodes[C.Dest].PredEdges->set(AdrNode); - - // *Dest = src edge - unsigned RefNode = C.Dest + FirstRefNode; - if (!GraphNodes[RefNode].ImplicitPredEdges) - GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>; - GraphNodes[RefNode].ImplicitPredEdges->set(C.Src); - } else if (C.Type == Constraint::Load) { - if (C.Offset == 0) { - // dest = *src edge - if (!GraphNodes[C.Dest].PredEdges) - GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; - GraphNodes[C.Dest].PredEdges->set(C.Src + FirstRefNode); - } else { - GraphNodes[C.Dest].Direct = false; - } - } else if (C.Type == Constraint::Store) { - if (C.Offset == 0) { - // *dest = src edge - unsigned RefNode = C.Dest + FirstRefNode; - if (!GraphNodes[RefNode].PredEdges) - GraphNodes[RefNode].PredEdges = new SparseBitVector<>; - GraphNodes[RefNode].PredEdges->set(C.Src); - } - } else { - // Dest = Src edge and *Dest = *Src edge - if (!GraphNodes[C.Dest].PredEdges) - GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; - GraphNodes[C.Dest].PredEdges->set(C.Src); - unsigned RefNode = C.Dest + FirstRefNode; - if (!GraphNodes[RefNode].ImplicitPredEdges) - GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>; - GraphNodes[RefNode].ImplicitPredEdges->set(C.Src + FirstRefNode); - } - } - PEClass = 1; - // Do SCC finding first to condense our predecessor graph - DFSNumber = 0; - Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0); - Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false); - Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false); - - for (unsigned i = 0; i < FirstRefNode; ++i) { - unsigned Node = VSSCCRep[i]; - if (!Node2Visited[Node]) - HVNValNum(Node); - } - for (BitVectorMap::iterator Iter = Set2PEClass.begin(); - Iter != Set2PEClass.end(); - ++Iter) - delete Iter->first; - Set2PEClass.clear(); - Node2DFS.clear(); - Node2Deleted.clear(); - Node2Visited.clear(); - DEBUG(dbgs() << "Finished HVN\n"); - -} - -/// This is the workhorse of HVN value numbering. We combine SCC finding at the -/// same time because it's easy. -void Andersens::HVNValNum(unsigned NodeIndex) { - unsigned MyDFS = DFSNumber++; - Node *N = &GraphNodes[NodeIndex]; - Node2Visited[NodeIndex] = true; - Node2DFS[NodeIndex] = MyDFS; - - // First process all our explicit edges - if (N->PredEdges) - for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); - Iter != N->PredEdges->end(); - ++Iter) { - unsigned j = VSSCCRep[*Iter]; - if (!Node2Deleted[j]) { - if (!Node2Visited[j]) - HVNValNum(j); - if (Node2DFS[NodeIndex] > Node2DFS[j]) - Node2DFS[NodeIndex] = Node2DFS[j]; - } - } - - // Now process all the implicit edges - if (N->ImplicitPredEdges) - for (SparseBitVector<>::iterator Iter = N->ImplicitPredEdges->begin(); - Iter != N->ImplicitPredEdges->end(); - ++Iter) { - unsigned j = VSSCCRep[*Iter]; - if (!Node2Deleted[j]) { - if (!Node2Visited[j]) - HVNValNum(j); - if (Node2DFS[NodeIndex] > Node2DFS[j]) - Node2DFS[NodeIndex] = Node2DFS[j]; - } - } - - // See if we found any cycles - if (MyDFS == Node2DFS[NodeIndex]) { - while (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS) { - unsigned CycleNodeIndex = SCCStack.top(); - Node *CycleNode = &GraphNodes[CycleNodeIndex]; - VSSCCRep[CycleNodeIndex] = NodeIndex; - // Unify the nodes - N->Direct &= CycleNode->Direct; - - if (CycleNode->PredEdges) { - if (!N->PredEdges) - N->PredEdges = new SparseBitVector<>; - *(N->PredEdges) |= CycleNode->PredEdges; - delete CycleNode->PredEdges; - CycleNode->PredEdges = NULL; - } - if (CycleNode->ImplicitPredEdges) { - if (!N->ImplicitPredEdges) - N->ImplicitPredEdges = new SparseBitVector<>; - *(N->ImplicitPredEdges) |= CycleNode->ImplicitPredEdges; - delete CycleNode->ImplicitPredEdges; - CycleNode->ImplicitPredEdges = NULL; - } - - SCCStack.pop(); - } - - Node2Deleted[NodeIndex] = true; - - if (!N->Direct) { - GraphNodes[NodeIndex].PointerEquivLabel = PEClass++; - return; - } - - // Collect labels of successor nodes - bool AllSame = true; - unsigned First = ~0; - SparseBitVector<> *Labels = new SparseBitVector<>; - bool Used = false; - - if (N->PredEdges) - for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); - Iter != N->PredEdges->end(); - ++Iter) { - unsigned j = VSSCCRep[*Iter]; - unsigned Label = GraphNodes[j].PointerEquivLabel; - // Ignore labels that are equal to us or non-pointers - if (j == NodeIndex || Label == 0) - continue; - if (First == (unsigned)~0) - First = Label; - else if (First != Label) - AllSame = false; - Labels->set(Label); - } - - // We either have a non-pointer, a copy of an existing node, or a new node. - // Assign the appropriate pointer equivalence label. - if (Labels->empty()) { - GraphNodes[NodeIndex].PointerEquivLabel = 0; - } else if (AllSame) { - GraphNodes[NodeIndex].PointerEquivLabel = First; - } else { - GraphNodes[NodeIndex].PointerEquivLabel = Set2PEClass[Labels]; - if (GraphNodes[NodeIndex].PointerEquivLabel == 0) { - unsigned EquivClass = PEClass++; - Set2PEClass[Labels] = EquivClass; - GraphNodes[NodeIndex].PointerEquivLabel = EquivClass; - Used = true; - } - } - if (!Used) - delete Labels; - } else { - SCCStack.push(NodeIndex); - } -} - -/// The technique used here is described in "Exploiting Pointer and Location -/// Equivalence to Optimize Pointer Analysis. In the 14th International Static -/// Analysis Symposium (SAS), August 2007." It is known as the "HU" algorithm, -/// and is equivalent to value numbering the collapsed constraint graph -/// including evaluating unions. -void Andersens::HU() { - DEBUG(dbgs() << "Beginning HU\n"); - // Build a predecessor graph. This is like our constraint graph with the - // edges going in the opposite direction, and there are edges for all the - // constraints, instead of just copy constraints. We also build implicit - // edges for constraints are implied but not explicit. I.E for the constraint - // a = &b, we add implicit edges *a = b. This helps us capture more cycles - for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { - Constraint &C = Constraints[i]; - if (C.Type == Constraint::AddressOf) { - GraphNodes[C.Src].AddressTaken = true; - GraphNodes[C.Src].Direct = false; - - GraphNodes[C.Dest].PointsTo->set(C.Src); - // *Dest = src edge - unsigned RefNode = C.Dest + FirstRefNode; - if (!GraphNodes[RefNode].ImplicitPredEdges) - GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>; - GraphNodes[RefNode].ImplicitPredEdges->set(C.Src); - GraphNodes[C.Src].PointedToBy->set(C.Dest); - } else if (C.Type == Constraint::Load) { - if (C.Offset == 0) { - // dest = *src edge - if (!GraphNodes[C.Dest].PredEdges) - GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; - GraphNodes[C.Dest].PredEdges->set(C.Src + FirstRefNode); - } else { - GraphNodes[C.Dest].Direct = false; - } - } else if (C.Type == Constraint::Store) { - if (C.Offset == 0) { - // *dest = src edge - unsigned RefNode = C.Dest + FirstRefNode; - if (!GraphNodes[RefNode].PredEdges) - GraphNodes[RefNode].PredEdges = new SparseBitVector<>; - GraphNodes[RefNode].PredEdges->set(C.Src); - } - } else { - // Dest = Src edge and *Dest = *Src edg - if (!GraphNodes[C.Dest].PredEdges) - GraphNodes[C.Dest].PredEdges = new SparseBitVector<>; - GraphNodes[C.Dest].PredEdges->set(C.Src); - unsigned RefNode = C.Dest + FirstRefNode; - if (!GraphNodes[RefNode].ImplicitPredEdges) - GraphNodes[RefNode].ImplicitPredEdges = new SparseBitVector<>; - GraphNodes[RefNode].ImplicitPredEdges->set(C.Src + FirstRefNode); - } - } - PEClass = 1; - // Do SCC finding first to condense our predecessor graph - DFSNumber = 0; - Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0); - Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false); - Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false); - - for (unsigned i = 0; i < FirstRefNode; ++i) { - if (FindNode(i) == i) { - unsigned Node = VSSCCRep[i]; - if (!Node2Visited[Node]) - Condense(Node); - } - } - - // Reset tables for actual labeling - Node2DFS.clear(); - Node2Visited.clear(); - Node2Deleted.clear(); - // Pre-grow our densemap so that we don't get really bad behavior - Set2PEClass.resize(GraphNodes.size()); - - // Visit the condensed graph and generate pointer equivalence labels. - Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false); - for (unsigned i = 0; i < FirstRefNode; ++i) { - if (FindNode(i) == i) { - unsigned Node = VSSCCRep[i]; - if (!Node2Visited[Node]) - HUValNum(Node); - } - } - // PEClass nodes will be deleted by the deleting of N->PointsTo in our caller. - Set2PEClass.clear(); - DEBUG(dbgs() << "Finished HU\n"); -} - - -/// Implementation of standard Tarjan SCC algorithm as modified by Nuutilla. -void Andersens::Condense(unsigned NodeIndex) { - unsigned MyDFS = DFSNumber++; - Node *N = &GraphNodes[NodeIndex]; - Node2Visited[NodeIndex] = true; - Node2DFS[NodeIndex] = MyDFS; - - // First process all our explicit edges - if (N->PredEdges) - for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); - Iter != N->PredEdges->end(); - ++Iter) { - unsigned j = VSSCCRep[*Iter]; - if (!Node2Deleted[j]) { - if (!Node2Visited[j]) - Condense(j); - if (Node2DFS[NodeIndex] > Node2DFS[j]) - Node2DFS[NodeIndex] = Node2DFS[j]; - } - } - - // Now process all the implicit edges - if (N->ImplicitPredEdges) - for (SparseBitVector<>::iterator Iter = N->ImplicitPredEdges->begin(); - Iter != N->ImplicitPredEdges->end(); - ++Iter) { - unsigned j = VSSCCRep[*Iter]; - if (!Node2Deleted[j]) { - if (!Node2Visited[j]) - Condense(j); - if (Node2DFS[NodeIndex] > Node2DFS[j]) - Node2DFS[NodeIndex] = Node2DFS[j]; - } - } - - // See if we found any cycles - if (MyDFS == Node2DFS[NodeIndex]) { - while (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS) { - unsigned CycleNodeIndex = SCCStack.top(); - Node *CycleNode = &GraphNodes[CycleNodeIndex]; - VSSCCRep[CycleNodeIndex] = NodeIndex; - // Unify the nodes - N->Direct &= CycleNode->Direct; - - *(N->PointsTo) |= CycleNode->PointsTo; - delete CycleNode->PointsTo; - CycleNode->PointsTo = NULL; - if (CycleNode->PredEdges) { - if (!N->PredEdges) - N->PredEdges = new SparseBitVector<>; - *(N->PredEdges) |= CycleNode->PredEdges; - delete CycleNode->PredEdges; - CycleNode->PredEdges = NULL; - } - if (CycleNode->ImplicitPredEdges) { - if (!N->ImplicitPredEdges) - N->ImplicitPredEdges = new SparseBitVector<>; - *(N->ImplicitPredEdges) |= CycleNode->ImplicitPredEdges; - delete CycleNode->ImplicitPredEdges; - CycleNode->ImplicitPredEdges = NULL; - } - SCCStack.pop(); - } - - Node2Deleted[NodeIndex] = true; - - // Set up number of incoming edges for other nodes - if (N->PredEdges) - for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); - Iter != N->PredEdges->end(); - ++Iter) - ++GraphNodes[VSSCCRep[*Iter]].NumInEdges; - } else { - SCCStack.push(NodeIndex); - } -} - -void Andersens::HUValNum(unsigned NodeIndex) { - Node *N = &GraphNodes[NodeIndex]; - Node2Visited[NodeIndex] = true; - - // Eliminate dereferences of non-pointers for those non-pointers we have - // already identified. These are ref nodes whose non-ref node: - // 1. Has already been visited determined to point to nothing (and thus, a - // dereference of it must point to nothing) - // 2. Any direct node with no predecessor edges in our graph and with no - // points-to set (since it can't point to anything either, being that it - // receives no points-to sets and has none). - if (NodeIndex >= FirstRefNode) { - unsigned j = VSSCCRep[FindNode(NodeIndex - FirstRefNode)]; - if ((Node2Visited[j] && !GraphNodes[j].PointerEquivLabel) - || (GraphNodes[j].Direct && !GraphNodes[j].PredEdges - && GraphNodes[j].PointsTo->empty())){ - return; - } - } - // Process all our explicit edges - if (N->PredEdges) - for (SparseBitVector<>::iterator Iter = N->PredEdges->begin(); - Iter != N->PredEdges->end(); - ++Iter) { - unsigned j = VSSCCRep[*Iter]; - if (!Node2Visited[j]) - HUValNum(j); - - // If this edge turned out to be the same as us, or got no pointer - // equivalence label (and thus points to nothing) , just decrement our - // incoming edges and continue. - if (j == NodeIndex || GraphNodes[j].PointerEquivLabel == 0) { - --GraphNodes[j].NumInEdges; - continue; - } - - *(N->PointsTo) |= GraphNodes[j].PointsTo; - - // If we didn't end up storing this in the hash, and we're done with all - // the edges, we don't need the points-to set anymore. - --GraphNodes[j].NumInEdges; - if (!GraphNodes[j].NumInEdges && !GraphNodes[j].StoredInHash) { - delete GraphNodes[j].PointsTo; - GraphNodes[j].PointsTo = NULL; - } - } - // If this isn't a direct node, generate a fresh variable. - if (!N->Direct) { - N->PointsTo->set(FirstRefNode + NodeIndex); - } - - // See If we have something equivalent to us, if not, generate a new - // equivalence class. - if (N->PointsTo->empty()) { - delete N->PointsTo; - N->PointsTo = NULL; - } else { - if (N->Direct) { - N->PointerEquivLabel = Set2PEClass[N->PointsTo]; - if (N->PointerEquivLabel == 0) { - unsigned EquivClass = PEClass++; - N->StoredInHash = true; - Set2PEClass[N->PointsTo] = EquivClass; - N->PointerEquivLabel = EquivClass; - } - } else { - N->PointerEquivLabel = PEClass++; - } - } -} - -/// Rewrite our list of constraints so that pointer equivalent nodes are -/// replaced by their the pointer equivalence class representative. -void Andersens::RewriteConstraints() { - std::vector NewConstraints; - DenseSet Seen; - - PEClass2Node.clear(); - PENLEClass2Node.clear(); - - // We may have from 1 to Graphnodes + 1 equivalence classes. - PEClass2Node.insert(PEClass2Node.begin(), GraphNodes.size() + 1, -1); - PENLEClass2Node.insert(PENLEClass2Node.begin(), GraphNodes.size() + 1, -1); - - // Rewrite constraints, ignoring non-pointer constraints, uniting equivalent - // nodes, and rewriting constraints to use the representative nodes. - for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { - Constraint &C = Constraints[i]; - unsigned RHSNode = FindNode(C.Src); - unsigned LHSNode = FindNode(C.Dest); - unsigned RHSLabel = GraphNodes[VSSCCRep[RHSNode]].PointerEquivLabel; - unsigned LHSLabel = GraphNodes[VSSCCRep[LHSNode]].PointerEquivLabel; - - // First we try to eliminate constraints for things we can prove don't point - // to anything. - if (LHSLabel == 0) { - DEBUG(PrintNode(&GraphNodes[LHSNode])); - DEBUG(dbgs() << " is a non-pointer, ignoring constraint.\n"); - continue; - } - if (RHSLabel == 0) { - DEBUG(PrintNode(&GraphNodes[RHSNode])); - DEBUG(dbgs() << " is a non-pointer, ignoring constraint.\n"); - continue; - } - // This constraint may be useless, and it may become useless as we translate - // it. - if (C.Src == C.Dest && C.Type == Constraint::Copy) - continue; - - C.Src = FindEquivalentNode(RHSNode, RHSLabel); - C.Dest = FindEquivalentNode(FindNode(LHSNode), LHSLabel); - if ((C.Src == C.Dest && C.Type == Constraint::Copy) - || Seen.count(C)) - continue; - - Seen.insert(C); - NewConstraints.push_back(C); - } - Constraints.swap(NewConstraints); - PEClass2Node.clear(); -} - -/// See if we have a node that is pointer equivalent to the one being asked -/// about, and if so, unite them and return the equivalent node. Otherwise, -/// return the original node. -unsigned Andersens::FindEquivalentNode(unsigned NodeIndex, - unsigned NodeLabel) { - if (!GraphNodes[NodeIndex].AddressTaken) { - if (PEClass2Node[NodeLabel] != -1) { - // We found an existing node with the same pointer label, so unify them. - // We specifically request that Union-By-Rank not be used so that - // PEClass2Node[NodeLabel] U= NodeIndex and not the other way around. - return UniteNodes(PEClass2Node[NodeLabel], NodeIndex, false); - } else { - PEClass2Node[NodeLabel] = NodeIndex; - PENLEClass2Node[NodeLabel] = NodeIndex; - } - } else if (PENLEClass2Node[NodeLabel] == -1) { - PENLEClass2Node[NodeLabel] = NodeIndex; - } - - return NodeIndex; -} - -void Andersens::PrintLabels() const { - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - if (i < FirstRefNode) { - PrintNode(&GraphNodes[i]); - } else if (i < FirstAdrNode) { - DEBUG(dbgs() << "REF("); - PrintNode(&GraphNodes[i-FirstRefNode]); - DEBUG(dbgs() <<")"); - } else { - DEBUG(dbgs() << "ADR("); - PrintNode(&GraphNodes[i-FirstAdrNode]); - DEBUG(dbgs() <<")"); - } - - DEBUG(dbgs() << " has pointer label " << GraphNodes[i].PointerEquivLabel - << " and SCC rep " << VSSCCRep[i] - << " and is " << (GraphNodes[i].Direct ? "Direct" : "Not direct") - << "\n"); - } -} - -/// The technique used here is described in "The Ant and the -/// Grasshopper: Fast and Accurate Pointer Analysis for Millions of -/// Lines of Code. In Programming Language Design and Implementation -/// (PLDI), June 2007." It is known as the "HCD" (Hybrid Cycle -/// Detection) algorithm. It is called a hybrid because it performs an -/// offline analysis and uses its results during the solving (online) -/// phase. This is just the offline portion; the results of this -/// operation are stored in SDT and are later used in SolveContraints() -/// and UniteNodes(). -void Andersens::HCD() { - DEBUG(dbgs() << "Starting HCD.\n"); - HCDSCCRep.resize(GraphNodes.size()); - - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - GraphNodes[i].Edges = new SparseBitVector<>; - HCDSCCRep[i] = i; - } - - for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { - Constraint &C = Constraints[i]; - assert (C.Src < GraphNodes.size() && C.Dest < GraphNodes.size()); - if (C.Type == Constraint::AddressOf) { - continue; - } else if (C.Type == Constraint::Load) { - if( C.Offset == 0 ) - GraphNodes[C.Dest].Edges->set(C.Src + FirstRefNode); - } else if (C.Type == Constraint::Store) { - if( C.Offset == 0 ) - GraphNodes[C.Dest + FirstRefNode].Edges->set(C.Src); - } else { - GraphNodes[C.Dest].Edges->set(C.Src); - } - } - - Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0); - Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false); - Node2Visited.insert(Node2Visited.begin(), GraphNodes.size(), false); - SDT.insert(SDT.begin(), GraphNodes.size() / 2, -1); - - DFSNumber = 0; - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - unsigned Node = HCDSCCRep[i]; - if (!Node2Deleted[Node]) - Search(Node); - } - - for (unsigned i = 0; i < GraphNodes.size(); ++i) - if (GraphNodes[i].Edges != NULL) { - delete GraphNodes[i].Edges; - GraphNodes[i].Edges = NULL; - } - - while( !SCCStack.empty() ) - SCCStack.pop(); - - Node2DFS.clear(); - Node2Visited.clear(); - Node2Deleted.clear(); - HCDSCCRep.clear(); - DEBUG(dbgs() << "HCD complete.\n"); -} - -// Component of HCD: -// Use Nuutila's variant of Tarjan's algorithm to detect -// Strongly-Connected Components (SCCs). For non-trivial SCCs -// containing ref nodes, insert the appropriate information in SDT. -void Andersens::Search(unsigned Node) { - unsigned MyDFS = DFSNumber++; - - Node2Visited[Node] = true; - Node2DFS[Node] = MyDFS; - - for (SparseBitVector<>::iterator Iter = GraphNodes[Node].Edges->begin(), - End = GraphNodes[Node].Edges->end(); - Iter != End; - ++Iter) { - unsigned J = HCDSCCRep[*Iter]; - assert(GraphNodes[J].isRep() && "Debug check; must be representative"); - if (!Node2Deleted[J]) { - if (!Node2Visited[J]) - Search(J); - if (Node2DFS[Node] > Node2DFS[J]) - Node2DFS[Node] = Node2DFS[J]; - } - } - - if( MyDFS != Node2DFS[Node] ) { - SCCStack.push(Node); - return; - } - - // This node is the root of a SCC, so process it. - // - // If the SCC is "non-trivial" (not a singleton) and contains a reference - // node, we place this SCC into SDT. We unite the nodes in any case. - if (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS) { - SparseBitVector<> SCC; - - SCC.set(Node); - - bool Ref = (Node >= FirstRefNode); - - Node2Deleted[Node] = true; - - do { - unsigned P = SCCStack.top(); SCCStack.pop(); - Ref |= (P >= FirstRefNode); - SCC.set(P); - HCDSCCRep[P] = Node; - } while (!SCCStack.empty() && Node2DFS[SCCStack.top()] >= MyDFS); - - if (Ref) { - unsigned Rep = SCC.find_first(); - assert(Rep < FirstRefNode && "The SCC didn't have a non-Ref node!"); - - SparseBitVector<>::iterator i = SCC.begin(); - - // Skip over the non-ref nodes - while( *i < FirstRefNode ) - ++i; - - while( i != SCC.end() ) - SDT[ (*i++) - FirstRefNode ] = Rep; - } - } -} - - -/// Optimize the constraints by performing offline variable substitution and -/// other optimizations. -void Andersens::OptimizeConstraints() { - DEBUG(dbgs() << "Beginning constraint optimization\n"); - - SDTActive = false; - - // Function related nodes need to stay in the same relative position and can't - // be location equivalent. - for (std::map::iterator Iter = MaxK.begin(); - Iter != MaxK.end(); - ++Iter) { - for (unsigned i = Iter->first; - i != Iter->first + Iter->second; - ++i) { - GraphNodes[i].AddressTaken = true; - GraphNodes[i].Direct = false; - } - } - - ClumpAddressTaken(); - FirstRefNode = GraphNodes.size(); - FirstAdrNode = FirstRefNode + GraphNodes.size(); - GraphNodes.insert(GraphNodes.end(), 2 * GraphNodes.size(), - Node(false)); - VSSCCRep.resize(GraphNodes.size()); - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - VSSCCRep[i] = i; - } - HVN(); - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - Node *N = &GraphNodes[i]; - delete N->PredEdges; - N->PredEdges = NULL; - delete N->ImplicitPredEdges; - N->ImplicitPredEdges = NULL; - } -#undef DEBUG_TYPE -#define DEBUG_TYPE "anders-aa-labels" - DEBUG(PrintLabels()); -#undef DEBUG_TYPE -#define DEBUG_TYPE "anders-aa" - RewriteConstraints(); - // Delete the adr nodes. - GraphNodes.resize(FirstRefNode * 2); - - // Now perform HU - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - Node *N = &GraphNodes[i]; - if (FindNode(i) == i) { - N->PointsTo = new SparseBitVector<>; - N->PointedToBy = new SparseBitVector<>; - // Reset our labels - } - VSSCCRep[i] = i; - N->PointerEquivLabel = 0; - } - HU(); -#undef DEBUG_TYPE -#define DEBUG_TYPE "anders-aa-labels" - DEBUG(PrintLabels()); -#undef DEBUG_TYPE -#define DEBUG_TYPE "anders-aa" - RewriteConstraints(); - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - if (FindNode(i) == i) { - Node *N = &GraphNodes[i]; - delete N->PointsTo; - N->PointsTo = NULL; - delete N->PredEdges; - N->PredEdges = NULL; - delete N->ImplicitPredEdges; - N->ImplicitPredEdges = NULL; - delete N->PointedToBy; - N->PointedToBy = NULL; - } - } - - // perform Hybrid Cycle Detection (HCD) - HCD(); - SDTActive = true; - - // No longer any need for the upper half of GraphNodes (for ref nodes). - GraphNodes.erase(GraphNodes.begin() + FirstRefNode, GraphNodes.end()); - - // HCD complete. - - DEBUG(dbgs() << "Finished constraint optimization\n"); - FirstRefNode = 0; - FirstAdrNode = 0; -} - -/// Unite pointer but not location equivalent variables, now that the constraint -/// graph is built. -void Andersens::UnitePointerEquivalences() { - DEBUG(dbgs() << "Uniting remaining pointer equivalences\n"); - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - if (GraphNodes[i].AddressTaken && GraphNodes[i].isRep()) { - unsigned Label = GraphNodes[i].PointerEquivLabel; - - if (Label && PENLEClass2Node[Label] != -1) - UniteNodes(i, PENLEClass2Node[Label]); - } - } - DEBUG(dbgs() << "Finished remaining pointer equivalences\n"); - PENLEClass2Node.clear(); -} - -/// Create the constraint graph used for solving points-to analysis. -/// -void Andersens::CreateConstraintGraph() { - for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { - Constraint &C = Constraints[i]; - assert (C.Src < GraphNodes.size() && C.Dest < GraphNodes.size()); - if (C.Type == Constraint::AddressOf) - GraphNodes[C.Dest].PointsTo->set(C.Src); - else if (C.Type == Constraint::Load) - GraphNodes[C.Src].Constraints.push_back(C); - else if (C.Type == Constraint::Store) - GraphNodes[C.Dest].Constraints.push_back(C); - else if (C.Offset != 0) - GraphNodes[C.Src].Constraints.push_back(C); - else - GraphNodes[C.Src].Edges->set(C.Dest); - } -} - -// Perform DFS and cycle detection. -bool Andersens::QueryNode(unsigned Node) { - assert(GraphNodes[Node].isRep() && "Querying a non-rep node"); - unsigned OurDFS = ++DFSNumber; - SparseBitVector<> ToErase; - SparseBitVector<> NewEdges; - Tarjan2DFS[Node] = OurDFS; - - // Changed denotes a change from a recursive call that we will bubble up. - // Merged is set if we actually merge a node ourselves. - bool Changed = false, Merged = false; - - for (SparseBitVector<>::iterator bi = GraphNodes[Node].Edges->begin(); - bi != GraphNodes[Node].Edges->end(); - ++bi) { - unsigned RepNode = FindNode(*bi); - // If this edge points to a non-representative node but we are - // already planning to add an edge to its representative, we have no - // need for this edge anymore. - if (RepNode != *bi && NewEdges.test(RepNode)){ - ToErase.set(*bi); - continue; - } - - // Continue about our DFS. - if (!Tarjan2Deleted[RepNode]){ - if (Tarjan2DFS[RepNode] == 0) { - Changed |= QueryNode(RepNode); - // May have been changed by QueryNode - RepNode = FindNode(RepNode); - } - if (Tarjan2DFS[RepNode] < Tarjan2DFS[Node]) - Tarjan2DFS[Node] = Tarjan2DFS[RepNode]; - } - - // We may have just discovered that this node is part of a cycle, in - // which case we can also erase it. - if (RepNode != *bi) { - ToErase.set(*bi); - NewEdges.set(RepNode); - } - } - - GraphNodes[Node].Edges->intersectWithComplement(ToErase); - GraphNodes[Node].Edges |= NewEdges; - - // If this node is a root of a non-trivial SCC, place it on our - // worklist to be processed. - if (OurDFS == Tarjan2DFS[Node]) { - while (!SCCStack.empty() && Tarjan2DFS[SCCStack.top()] >= OurDFS) { - Node = UniteNodes(Node, SCCStack.top()); - - SCCStack.pop(); - Merged = true; - } - Tarjan2Deleted[Node] = true; - - if (Merged) - NextWL->insert(&GraphNodes[Node]); - } else { - SCCStack.push(Node); - } - - return(Changed | Merged); -} - -/// SolveConstraints - This stage iteratively processes the constraints list -/// propagating constraints (adding edges to the Nodes in the points-to graph) -/// until a fixed point is reached. -/// -/// We use a variant of the technique called "Lazy Cycle Detection", which is -/// described in "The Ant and the Grasshopper: Fast and Accurate Pointer -/// Analysis for Millions of Lines of Code. In Programming Language Design and -/// Implementation (PLDI), June 2007." -/// The paper describes performing cycle detection one node at a time, which can -/// be expensive if there are no cycles, but there are long chains of nodes that -/// it heuristically believes are cycles (because it will DFS from each node -/// without state from previous nodes). -/// Instead, we use the heuristic to build a worklist of nodes to check, then -/// cycle detect them all at the same time to do this more cheaply. This -/// catches cycles slightly later than the original technique did, but does it -/// make significantly cheaper. - -void Andersens::SolveConstraints() { - CurrWL = &w1; - NextWL = &w2; - - OptimizeConstraints(); -#undef DEBUG_TYPE -#define DEBUG_TYPE "anders-aa-constraints" - DEBUG(PrintConstraints()); -#undef DEBUG_TYPE -#define DEBUG_TYPE "anders-aa" - - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - Node *N = &GraphNodes[i]; - N->PointsTo = new SparseBitVector<>; - N->OldPointsTo = new SparseBitVector<>; - N->Edges = new SparseBitVector<>; - } - CreateConstraintGraph(); - UnitePointerEquivalences(); - assert(SCCStack.empty() && "SCC Stack should be empty by now!"); - Node2DFS.clear(); - Node2Deleted.clear(); - Node2DFS.insert(Node2DFS.begin(), GraphNodes.size(), 0); - Node2Deleted.insert(Node2Deleted.begin(), GraphNodes.size(), false); - DFSNumber = 0; - DenseSet Seen; - DenseSet, PairKeyInfo> EdgesChecked; - - // Order graph and add initial nodes to work list. - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - Node *INode = &GraphNodes[i]; - - // Add to work list if it's a representative and can contribute to the - // calculation right now. - if (INode->isRep() && !INode->PointsTo->empty() - && (!INode->Edges->empty() || !INode->Constraints.empty())) { - INode->Stamp(); - CurrWL->insert(INode); - } - } - std::queue TarjanWL; -#if !FULL_UNIVERSAL - // "Rep and special variables" - in order for HCD to maintain conservative - // results when !FULL_UNIVERSAL, we need to treat the special variables in - // the same way that the !FULL_UNIVERSAL tweak does throughout the rest of - // the analysis - it's ok to add edges from the special nodes, but never - // *to* the special nodes. - std::vector RSV; -#endif - while( !CurrWL->empty() ) { - DEBUG(dbgs() << "Starting iteration #" << ++NumIters << "\n"); - - Node* CurrNode; - unsigned CurrNodeIndex; - - // Actual cycle checking code. We cycle check all of the lazy cycle - // candidates from the last iteration in one go. - if (!TarjanWL.empty()) { - DFSNumber = 0; - - Tarjan2DFS.clear(); - Tarjan2Deleted.clear(); - while (!TarjanWL.empty()) { - unsigned int ToTarjan = TarjanWL.front(); - TarjanWL.pop(); - if (!Tarjan2Deleted[ToTarjan] - && GraphNodes[ToTarjan].isRep() - && Tarjan2DFS[ToTarjan] == 0) - QueryNode(ToTarjan); - } - } - - // Add to work list if it's a representative and can contribute to the - // calculation right now. - while( (CurrNode = CurrWL->pop()) != NULL ) { - CurrNodeIndex = CurrNode - &GraphNodes[0]; - CurrNode->Stamp(); - - - // Figure out the changed points to bits - SparseBitVector<> CurrPointsTo; - CurrPointsTo.intersectWithComplement(CurrNode->PointsTo, - CurrNode->OldPointsTo); - if (CurrPointsTo.empty()) - continue; - - *(CurrNode->OldPointsTo) |= CurrPointsTo; - - // Check the offline-computed equivalencies from HCD. - bool SCC = false; - unsigned Rep; - - if (SDT[CurrNodeIndex] >= 0) { - SCC = true; - Rep = FindNode(SDT[CurrNodeIndex]); - -#if !FULL_UNIVERSAL - RSV.clear(); -#endif - for (SparseBitVector<>::iterator bi = CurrPointsTo.begin(); - bi != CurrPointsTo.end(); ++bi) { - unsigned Node = FindNode(*bi); -#if !FULL_UNIVERSAL - if (Node < NumberSpecialNodes) { - RSV.push_back(Node); - continue; - } -#endif - Rep = UniteNodes(Rep,Node); - } -#if !FULL_UNIVERSAL - RSV.push_back(Rep); -#endif - - NextWL->insert(&GraphNodes[Rep]); - - if ( ! CurrNode->isRep() ) - continue; - } - - Seen.clear(); - - /* Now process the constraints for this node. */ - for (std::list::iterator li = CurrNode->Constraints.begin(); - li != CurrNode->Constraints.end(); ) { - li->Src = FindNode(li->Src); - li->Dest = FindNode(li->Dest); - - // Delete redundant constraints - if( Seen.count(*li) ) { - std::list::iterator lk = li; li++; - - CurrNode->Constraints.erase(lk); - ++NumErased; - continue; - } - Seen.insert(*li); - - // Src and Dest will be the vars we are going to process. - // This may look a bit ugly, but what it does is allow us to process - // both store and load constraints with the same code. - // Load constraints say that every member of our RHS solution has K - // added to it, and that variable gets an edge to LHS. We also union - // RHS+K's solution into the LHS solution. - // Store constraints say that every member of our LHS solution has K - // added to it, and that variable gets an edge from RHS. We also union - // RHS's solution into the LHS+K solution. - unsigned *Src; - unsigned *Dest; - unsigned K = li->Offset; - unsigned CurrMember; - if (li->Type == Constraint::Load) { - Src = &CurrMember; - Dest = &li->Dest; - } else if (li->Type == Constraint::Store) { - Src = &li->Src; - Dest = &CurrMember; - } else { - // TODO Handle offseted copy constraint - li++; - continue; - } - - // See if we can use Hybrid Cycle Detection (that is, check - // if it was a statically detected offline equivalence that - // involves pointers; if so, remove the redundant constraints). - if( SCC && K == 0 ) { -#if FULL_UNIVERSAL - CurrMember = Rep; - - if (GraphNodes[*Src].Edges->test_and_set(*Dest)) - if (GraphNodes[*Dest].PointsTo |= *(GraphNodes[*Src].PointsTo)) - NextWL->insert(&GraphNodes[*Dest]); -#else - for (unsigned i=0; i < RSV.size(); ++i) { - CurrMember = RSV[i]; - - if (*Dest < NumberSpecialNodes) - continue; - if (GraphNodes[*Src].Edges->test_and_set(*Dest)) - if (GraphNodes[*Dest].PointsTo |= *(GraphNodes[*Src].PointsTo)) - NextWL->insert(&GraphNodes[*Dest]); - } -#endif - // since all future elements of the points-to set will be - // equivalent to the current ones, the complex constraints - // become redundant. - // - std::list::iterator lk = li; li++; -#if !FULL_UNIVERSAL - // In this case, we can still erase the constraints when the - // elements of the points-to sets are referenced by *Dest, - // but not when they are referenced by *Src (i.e. for a Load - // constraint). This is because if another special variable is - // put into the points-to set later, we still need to add the - // new edge from that special variable. - if( lk->Type != Constraint::Load) -#endif - GraphNodes[CurrNodeIndex].Constraints.erase(lk); - } else { - const SparseBitVector<> &Solution = CurrPointsTo; - - for (SparseBitVector<>::iterator bi = Solution.begin(); - bi != Solution.end(); - ++bi) { - CurrMember = *bi; - - // Need to increment the member by K since that is where we are - // supposed to copy to/from. Note that in positive weight cycles, - // which occur in address taking of fields, K can go past - // MaxK[CurrMember] elements, even though that is all it could point - // to. - if (K > 0 && K > MaxK[CurrMember]) - continue; - else - CurrMember = FindNode(CurrMember + K); - - // Add an edge to the graph, so we can just do regular - // bitmap ior next time. It may also let us notice a cycle. -#if !FULL_UNIVERSAL - if (*Dest < NumberSpecialNodes) - continue; -#endif - if (GraphNodes[*Src].Edges->test_and_set(*Dest)) - if (GraphNodes[*Dest].PointsTo |= *(GraphNodes[*Src].PointsTo)) - NextWL->insert(&GraphNodes[*Dest]); - - } - li++; - } - } - SparseBitVector<> NewEdges; - SparseBitVector<> ToErase; - - // Now all we have left to do is propagate points-to info along the - // edges, erasing the redundant edges. - for (SparseBitVector<>::iterator bi = CurrNode->Edges->begin(); - bi != CurrNode->Edges->end(); - ++bi) { - - unsigned DestVar = *bi; - unsigned Rep = FindNode(DestVar); - - // If we ended up with this node as our destination, or we've already - // got an edge for the representative, delete the current edge. - if (Rep == CurrNodeIndex || - (Rep != DestVar && NewEdges.test(Rep))) { - ToErase.set(DestVar); - continue; - } - - std::pair edge(CurrNodeIndex,Rep); - - // This is where we do lazy cycle detection. - // If this is a cycle candidate (equal points-to sets and this - // particular edge has not been cycle-checked previously), add to the - // list to check for cycles on the next iteration. - if (!EdgesChecked.count(edge) && - *(GraphNodes[Rep].PointsTo) == *(CurrNode->PointsTo)) { - EdgesChecked.insert(edge); - TarjanWL.push(Rep); - } - // Union the points-to sets into the dest -#if !FULL_UNIVERSAL - if (Rep >= NumberSpecialNodes) -#endif - if (GraphNodes[Rep].PointsTo |= CurrPointsTo) { - NextWL->insert(&GraphNodes[Rep]); - } - // If this edge's destination was collapsed, rewrite the edge. - if (Rep != DestVar) { - ToErase.set(DestVar); - NewEdges.set(Rep); - } - } - CurrNode->Edges->intersectWithComplement(ToErase); - CurrNode->Edges |= NewEdges; - } - - // Switch to other work list. - WorkList* t = CurrWL; CurrWL = NextWL; NextWL = t; - } - - - Node2DFS.clear(); - Node2Deleted.clear(); - for (unsigned i = 0; i < GraphNodes.size(); ++i) { - Node *N = &GraphNodes[i]; - delete N->OldPointsTo; - delete N->Edges; - } - SDTActive = false; - SDT.clear(); -} - -//===----------------------------------------------------------------------===// -// Union-Find -//===----------------------------------------------------------------------===// - -// Unite nodes First and Second, returning the one which is now the -// representative node. First and Second are indexes into GraphNodes -unsigned Andersens::UniteNodes(unsigned First, unsigned Second, - bool UnionByRank) { - assert (First < GraphNodes.size() && Second < GraphNodes.size() && - "Attempting to merge nodes that don't exist"); - - Node *FirstNode = &GraphNodes[First]; - Node *SecondNode = &GraphNodes[Second]; - - assert (SecondNode->isRep() && FirstNode->isRep() && - "Trying to unite two non-representative nodes!"); - if (First == Second) - return First; - - if (UnionByRank) { - int RankFirst = (int) FirstNode ->NodeRep; - int RankSecond = (int) SecondNode->NodeRep; - - // Rank starts at -1 and gets decremented as it increases. - // Translation: higher rank, lower NodeRep value, which is always negative. - if (RankFirst > RankSecond) { - unsigned t = First; First = Second; Second = t; - Node* tp = FirstNode; FirstNode = SecondNode; SecondNode = tp; - } else if (RankFirst == RankSecond) { - FirstNode->NodeRep = (unsigned) (RankFirst - 1); - } - } - - SecondNode->NodeRep = First; -#if !FULL_UNIVERSAL - if (First >= NumberSpecialNodes) -#endif - if (FirstNode->PointsTo && SecondNode->PointsTo) - FirstNode->PointsTo |= *(SecondNode->PointsTo); - if (FirstNode->Edges && SecondNode->Edges) - FirstNode->Edges |= *(SecondNode->Edges); - if (!SecondNode->Constraints.empty()) - FirstNode->Constraints.splice(FirstNode->Constraints.begin(), - SecondNode->Constraints); - if (FirstNode->OldPointsTo) { - delete FirstNode->OldPointsTo; - FirstNode->OldPointsTo = new SparseBitVector<>; - } - - // Destroy interesting parts of the merged-from node. - delete SecondNode->OldPointsTo; - delete SecondNode->Edges; - delete SecondNode->PointsTo; - SecondNode->Edges = NULL; - SecondNode->PointsTo = NULL; - SecondNode->OldPointsTo = NULL; - - NumUnified++; - DEBUG(dbgs() << "Unified Node "); - DEBUG(PrintNode(FirstNode)); - DEBUG(dbgs() << " and Node "); - DEBUG(PrintNode(SecondNode)); - DEBUG(dbgs() << "\n"); - - if (SDTActive) - if (SDT[Second] >= 0) { - if (SDT[First] < 0) - SDT[First] = SDT[Second]; - else { - UniteNodes( FindNode(SDT[First]), FindNode(SDT[Second]) ); - First = FindNode(First); - } - } - - return First; -} - -// Find the index into GraphNodes of the node representing Node, performing -// path compression along the way -unsigned Andersens::FindNode(unsigned NodeIndex) { - assert (NodeIndex < GraphNodes.size() - && "Attempting to find a node that can't exist"); - Node *N = &GraphNodes[NodeIndex]; - if (N->isRep()) - return NodeIndex; - else - return (N->NodeRep = FindNode(N->NodeRep)); -} - -// Find the index into GraphNodes of the node representing Node, -// don't perform path compression along the way (for Print) -unsigned Andersens::FindNode(unsigned NodeIndex) const { - assert (NodeIndex < GraphNodes.size() - && "Attempting to find a node that can't exist"); - const Node *N = &GraphNodes[NodeIndex]; - if (N->isRep()) - return NodeIndex; - else - return FindNode(N->NodeRep); -} - -//===----------------------------------------------------------------------===// -// Debugging Output -//===----------------------------------------------------------------------===// - -void Andersens::PrintNode(const Node *N) const { - if (N == &GraphNodes[UniversalSet]) { - dbgs() << ""; - return; - } else if (N == &GraphNodes[NullPtr]) { - dbgs() << ""; - return; - } else if (N == &GraphNodes[NullObject]) { - dbgs() << ""; - return; - } - if (!N->getValue()) { - dbgs() << "artificial" << (intptr_t) N; - return; - } - - assert(N->getValue() != 0 && "Never set node label!"); - Value *V = N->getValue(); - if (Function *F = dyn_cast(V)) { - if (isa(F->getFunctionType()->getReturnType()) && - N == &GraphNodes[getReturnNode(F)]) { - dbgs() << F->getName() << ":retval"; - return; - } else if (F->getFunctionType()->isVarArg() && - N == &GraphNodes[getVarargNode(F)]) { - dbgs() << F->getName() << ":vararg"; - return; - } - } - - if (Instruction *I = dyn_cast(V)) - dbgs() << I->getParent()->getParent()->getName() << ":"; - else if (Argument *Arg = dyn_cast(V)) - dbgs() << Arg->getParent()->getName() << ":"; - - if (V->hasName()) - dbgs() << V->getName(); - else - dbgs() << "(unnamed)"; - - if (isa(V) || isa(V) || isMalloc(V)) - if (N == &GraphNodes[getObject(V)]) - dbgs() << ""; -} -void Andersens::PrintConstraint(const Constraint &C) const { - if (C.Type == Constraint::Store) { - dbgs() << "*"; - if (C.Offset != 0) - dbgs() << "("; - } - PrintNode(&GraphNodes[C.Dest]); - if (C.Type == Constraint::Store && C.Offset != 0) - dbgs() << " + " << C.Offset << ")"; - dbgs() << " = "; - if (C.Type == Constraint::Load) { - dbgs() << "*"; - if (C.Offset != 0) - dbgs() << "("; - } - else if (C.Type == Constraint::AddressOf) - dbgs() << "&"; - PrintNode(&GraphNodes[C.Src]); - if (C.Offset != 0 && C.Type != Constraint::Store) - dbgs() << " + " << C.Offset; - if (C.Type == Constraint::Load && C.Offset != 0) - dbgs() << ")"; - dbgs() << "\n"; -} - -void Andersens::PrintConstraints() const { - dbgs() << "Constraints:\n"; - - for (unsigned i = 0, e = Constraints.size(); i != e; ++i) - PrintConstraint(Constraints[i]); -} - -void Andersens::PrintPointsToGraph() const { - dbgs() << "Points-to graph:\n"; - for (unsigned i = 0, e = GraphNodes.size(); i != e; ++i) { - const Node *N = &GraphNodes[i]; - if (FindNode(i) != i) { - PrintNode(N); - dbgs() << "\t--> same as "; - PrintNode(&GraphNodes[FindNode(i)]); - dbgs() << "\n"; - } else { - dbgs() << "[" << (N->PointsTo->count()) << "] "; - PrintNode(N); - dbgs() << "\t--> "; - - bool first = true; - for (SparseBitVector<>::iterator bi = N->PointsTo->begin(); - bi != N->PointsTo->end(); - ++bi) { - if (!first) - dbgs() << ", "; - PrintNode(&GraphNodes[*bi]); - first = false; - } - dbgs() << "\n"; - } - } -} diff --git a/lib/Analysis/IPA/CMakeLists.txt b/lib/Analysis/IPA/CMakeLists.txt index 1ebb0bea36..007ad228ae 100644 --- a/lib/Analysis/IPA/CMakeLists.txt +++ b/lib/Analysis/IPA/CMakeLists.txt @@ -1,5 +1,4 @@ add_llvm_library(LLVMipa - Andersens.cpp CallGraph.cpp CallGraphSCCPass.cpp FindUsedTypes.cpp diff --git a/lib/Analysis/IPA/GlobalsModRef.cpp b/lib/Analysis/IPA/GlobalsModRef.cpp index ec94bc892b..7b43089d59 100644 --- a/lib/Analysis/IPA/GlobalsModRef.cpp +++ b/lib/Analysis/IPA/GlobalsModRef.cpp @@ -213,7 +213,7 @@ void GlobalsModRef::AnalyzeGlobals(Module &M) { ++NumNonAddrTakenGlobalVars; // If this global holds a pointer type, see if it is an indirect global. - if (isa(I->getType()->getElementType()) && + if (I->getType()->getElementType()->isPointerTy() && AnalyzeIndirectGlobalMemory(I)) ++NumIndirectGlobalVars; } @@ -231,7 +231,7 @@ bool GlobalsModRef::AnalyzeUsesOfPointer(Value *V, std::vector &Readers, std::vector &Writers, GlobalValue *OkayStoreDest) { - if (!isa(V->getType())) return true; + if (!V->getType()->isPointerTy()) return true; for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) if (LoadInst *LI = dyn_cast(*UI)) { diff --git a/lib/Analysis/IVUsers.cpp b/lib/Analysis/IVUsers.cpp index 9c472ae73b..98a436f79b 100644 --- a/lib/Analysis/IVUsers.cpp +++ b/lib/Analysis/IVUsers.cpp @@ -21,6 +21,7 @@ #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Assembly/AsmAnnotationWriter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -35,42 +36,30 @@ Pass *llvm::createIVUsersPass() { return new IVUsers(); } -/// containsAddRecFromDifferentLoop - Determine whether expression S involves a -/// subexpression that is an AddRec from a loop other than L. An outer loop -/// of L is OK, but not an inner loop nor a disjoint loop. -static bool containsAddRecFromDifferentLoop(const SCEV *S, Loop *L) { - // This is very common, put it first. - if (isa(S)) - return false; - if (const SCEVCommutativeExpr *AE = dyn_cast(S)) { - for (unsigned int i=0; i< AE->getNumOperands(); i++) - if (containsAddRecFromDifferentLoop(AE->getOperand(i), L)) - return true; - return false; - } - if (const SCEVAddRecExpr *AE = dyn_cast(S)) { - if (const Loop *newLoop = AE->getLoop()) { - if (newLoop == L) - return false; - // if newLoop is an outer loop of L, this is OK. - if (newLoop->contains(L)) - return false; +/// CollectSubexprs - Split S into subexpressions which can be pulled out into +/// separate registers. +static void CollectSubexprs(const SCEV *S, + SmallVectorImpl &Ops, + ScalarEvolution &SE) { + if (const SCEVAddExpr *Add = dyn_cast(S)) { + // Break out add operands. + for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end(); + I != E; ++I) + CollectSubexprs(*I, Ops, SE); + return; + } else if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + // Split a non-zero base out of an addrec. + if (!AR->getStart()->isZero()) { + CollectSubexprs(AR->getStart(), Ops, SE); + CollectSubexprs(SE.getAddRecExpr(SE.getIntegerSCEV(0, AR->getType()), + AR->getStepRecurrence(SE), + AR->getLoop()), Ops, SE); + return; } - return true; } - if (const SCEVUDivExpr *DE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(DE->getLHS(), L) || - containsAddRecFromDifferentLoop(DE->getRHS(), L); -#if 0 - // SCEVSDivExpr has been backed out temporarily, but will be back; we'll - // need this when it is. - if (const SCEVSDivExpr *DE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(DE->getLHS(), L) || - containsAddRecFromDifferentLoop(DE->getRHS(), L); -#endif - if (const SCEVCastExpr *CE = dyn_cast(S)) - return containsAddRecFromDifferentLoop(CE->getOperand(), L); - return false; + + // Otherwise use the value itself. + Ops.push_back(S); } /// getSCEVStartAndStride - Compute the start and stride of this expression, @@ -89,35 +78,42 @@ static bool getSCEVStartAndStride(const SCEV *&SH, Loop *L, Loop *UseLoop, if (const SCEVAddExpr *AE = dyn_cast(SH)) { for (unsigned i = 0, e = AE->getNumOperands(); i != e; ++i) if (const SCEVAddRecExpr *AddRec = - dyn_cast(AE->getOperand(i))) { - if (AddRec->getLoop() == L) - TheAddRec = SE->getAddExpr(AddRec, TheAddRec); - else - return false; // Nested IV of some sort? - } else { + dyn_cast(AE->getOperand(i))) + TheAddRec = SE->getAddExpr(AddRec, TheAddRec); + else Start = SE->getAddExpr(Start, AE->getOperand(i)); - } } else if (isa(SH)) { TheAddRec = SH; } else { return false; // not analyzable. } - const SCEVAddRecExpr *AddRec = dyn_cast(TheAddRec); - if (!AddRec || AddRec->getLoop() != L) return false; + // Break down TheAddRec into its component parts. + SmallVector Subexprs; + CollectSubexprs(TheAddRec, Subexprs, *SE); + + // Look for an addrec on the current loop among the parts. + const SCEV *AddRecStride = 0; + for (SmallVectorImpl::iterator I = Subexprs.begin(), + E = Subexprs.end(); I != E; ++I) { + const SCEV *S = *I; + if (const SCEVAddRecExpr *AR = dyn_cast(S)) + if (AR->getLoop() == L) { + *I = AR->getStart(); + AddRecStride = AR->getStepRecurrence(*SE); + break; + } + } + if (!AddRecStride) + return false; + + // Add up everything else into a start value (which may not be + // loop-invariant). + const SCEV *AddRecStart = SE->getAddExpr(Subexprs); // Use getSCEVAtScope to attempt to simplify other loops out of // the picture. - const SCEV *AddRecStart = AddRec->getStart(); AddRecStart = SE->getSCEVAtScope(AddRecStart, UseLoop); - const SCEV *AddRecStride = AddRec->getStepRecurrence(*SE); - - // FIXME: If Start contains an SCEVAddRecExpr from a different loop, other - // than an outer loop of the current loop, reject it. LSR has no concept of - // operating on more than one loop at a time so don't confuse it with such - // expressions. - if (containsAddRecFromDifferentLoop(AddRecStart, L)) - return false; Start = SE->getAddExpr(Start, AddRecStart); @@ -130,7 +126,7 @@ static bool getSCEVStartAndStride(const SCEV *&SH, Loop *L, Loop *UseLoop, DEBUG(dbgs() << "["; WriteAsOperand(dbgs(), L->getHeader(), /*PrintType=*/false); - dbgs() << "] Variable stride: " << *AddRec << "\n"); + dbgs() << "] Variable stride: " << *AddRecStride << "\n"); } Stride = AddRecStride; @@ -146,8 +142,7 @@ static bool getSCEVStartAndStride(const SCEV *&SH, Loop *L, Loop *UseLoop, /// the loop, resulting in reg-reg copies (if we use the pre-inc value when we /// should use the post-inc value). static bool IVUseShouldUsePostIncValue(Instruction *User, Instruction *IV, - Loop *L, LoopInfo *LI, DominatorTree *DT, - Pass *P) { + Loop *L, DominatorTree *DT) { // If the user is in the loop, use the preinc value. if (L->contains(User)) return false; @@ -227,7 +222,7 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) { // Descend recursively, but not into PHI nodes outside the current loop. // It's important to see the entire expression outside the loop to get // choices that depend on addressing mode use right, although we won't - // consider references ouside the loop in all cases. + // consider references outside the loop in all cases. // If User is already in Processed, we don't want to recurse into it again, // but do want to record a second reference in the same instruction. bool AddUserToIVUsers = false; @@ -246,42 +241,28 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) { } if (AddUserToIVUsers) { - IVUsersOfOneStride *StrideUses = IVUsesByStride[Stride]; - if (!StrideUses) { // First occurrence of this stride? - StrideOrder.push_back(Stride); - StrideUses = new IVUsersOfOneStride(Stride); - IVUses.push_back(StrideUses); - IVUsesByStride[Stride] = StrideUses; - } - // Okay, we found a user that we cannot reduce. Analyze the instruction // and decide what to do with it. If we are a use inside of the loop, use // the value before incrementation, otherwise use it after incrementation. - if (IVUseShouldUsePostIncValue(User, I, L, LI, DT, this)) { + if (IVUseShouldUsePostIncValue(User, I, L, DT)) { // The value used will be incremented by the stride more than we are // expecting, so subtract this off. const SCEV *NewStart = SE->getMinusSCEV(Start, Stride); - StrideUses->addUser(NewStart, User, I); - StrideUses->Users.back().setIsUseOfPostIncrementedValue(true); + IVUses.push_back(new IVStrideUse(this, Stride, NewStart, User, I)); + IVUses.back().setIsUseOfPostIncrementedValue(true); DEBUG(dbgs() << " USING POSTINC SCEV, START=" << *NewStart<< "\n"); } else { - StrideUses->addUser(Start, User, I); + IVUses.push_back(new IVStrideUse(this, Stride, Start, User, I)); } } } return true; } -void IVUsers::AddUser(const SCEV *Stride, const SCEV *Offset, - Instruction *User, Value *Operand) { - IVUsersOfOneStride *StrideUses = IVUsesByStride[Stride]; - if (!StrideUses) { // First occurrence of this stride? - StrideOrder.push_back(Stride); - StrideUses = new IVUsersOfOneStride(Stride); - IVUses.push_back(StrideUses); - IVUsesByStride[Stride] = StrideUses; - } - IVUsesByStride[Stride]->addUser(Offset, User, Operand); +IVStrideUse &IVUsers::AddUser(const SCEV *Stride, const SCEV *Offset, + Instruction *User, Value *Operand) { + IVUses.push_back(new IVStrideUse(this, Stride, Offset, User, Operand)); + return IVUses.back(); } IVUsers::IVUsers() @@ -315,15 +296,15 @@ bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) { /// value of the OperandValToReplace of the given IVStrideUse. const SCEV *IVUsers::getReplacementExpr(const IVStrideUse &U) const { // Start with zero. - const SCEV *RetVal = SE->getIntegerSCEV(0, U.getParent()->Stride->getType()); + const SCEV *RetVal = SE->getIntegerSCEV(0, U.getStride()->getType()); // Create the basic add recurrence. - RetVal = SE->getAddRecExpr(RetVal, U.getParent()->Stride, L); + RetVal = SE->getAddRecExpr(RetVal, U.getStride(), L); // Add the offset in a separate step, because it may be loop-variant. RetVal = SE->getAddExpr(RetVal, U.getOffset()); // For uses of post-incremented values, add an extra stride to compute // the actual replacement value. if (U.isUseOfPostIncrementedValue()) - RetVal = SE->getAddExpr(RetVal, U.getParent()->Stride); + RetVal = SE->getAddExpr(RetVal, U.getStride()); return RetVal; } @@ -332,9 +313,9 @@ const SCEV *IVUsers::getReplacementExpr(const IVStrideUse &U) const { /// isUseOfPostIncrementedValue flag. const SCEV *IVUsers::getCanonicalExpr(const IVStrideUse &U) const { // Start with zero. - const SCEV *RetVal = SE->getIntegerSCEV(0, U.getParent()->Stride->getType()); + const SCEV *RetVal = SE->getIntegerSCEV(0, U.getStride()->getType()); // Create the basic add recurrence. - RetVal = SE->getAddRecExpr(RetVal, U.getParent()->Stride, L); + RetVal = SE->getAddRecExpr(RetVal, U.getStride(), L); // Add the offset in a separate step, because it may be loop-variant. RetVal = SE->getAddExpr(RetVal, U.getOffset()); return RetVal; @@ -349,24 +330,20 @@ void IVUsers::print(raw_ostream &OS, const Module *M) const { } OS << ":\n"; - for (unsigned Stride = 0, e = StrideOrder.size(); Stride != e; ++Stride) { - std::map::const_iterator SI = - IVUsesByStride.find(StrideOrder[Stride]); - assert(SI != IVUsesByStride.end() && "Stride doesn't exist!"); - OS << " Stride " << *SI->first->getType() << " " << *SI->first << ":\n"; - - for (ilist::const_iterator UI = SI->second->Users.begin(), - E = SI->second->Users.end(); UI != E; ++UI) { - OS << " "; - WriteAsOperand(OS, UI->getOperandValToReplace(), false); - OS << " = "; - OS << *getReplacementExpr(*UI); - if (UI->isUseOfPostIncrementedValue()) - OS << " (post-inc)"; - OS << " in "; - UI->getUser()->print(OS); - OS << '\n'; - } + // Use a default AssemblyAnnotationWriter to suppress the default info + // comments, which aren't relevant here. + AssemblyAnnotationWriter Annotator; + for (ilist::const_iterator UI = IVUses.begin(), + E = IVUses.end(); UI != E; ++UI) { + OS << " "; + WriteAsOperand(OS, UI->getOperandValToReplace(), false); + OS << " = " + << *getReplacementExpr(*UI); + if (UI->isUseOfPostIncrementedValue()) + OS << " (post-inc)"; + OS << " in "; + UI->getUser()->print(OS, &Annotator); + OS << '\n'; } } @@ -375,37 +352,12 @@ void IVUsers::dump() const { } void IVUsers::releaseMemory() { - IVUsesByStride.clear(); - StrideOrder.clear(); Processed.clear(); IVUses.clear(); } void IVStrideUse::deleted() { // Remove this user from the list. - Parent->Users.erase(this); + Parent->IVUses.erase(this); // this now dangles! } - -void IVUsersOfOneStride::print(raw_ostream &OS) const { - OS << "IV Users of one stride:\n"; - - if (Stride) - OS << " Stride: " << *Stride << '\n'; - - OS << " Users:\n"; - - unsigned Count = 1; - - for (ilist::const_iterator - I = Users.begin(), E = Users.end(); I != E; ++I) { - const IVStrideUse &SU = *I; - OS << " " << Count++ << '\n'; - OS << " Offset: " << *SU.getOffset() << '\n'; - OS << " Instr: " << *SU << '\n'; - } -} - -void IVUsersOfOneStride::dump() const { - print(dbgs()); -} diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp index 972d0349fd..ca50a1721e 100644 --- a/lib/Analysis/InlineCost.cpp +++ b/lib/Analysis/InlineCost.cpp @@ -84,7 +84,7 @@ unsigned InlineCostAnalyzer::FunctionInfo:: // unsigned InlineCostAnalyzer::FunctionInfo:: CountCodeReductionForAlloca(Value *V) { - if (!isa(V->getType())) return 0; // Not a pointer + if (!V->getType()->isPointerTy()) return 0; // Not a pointer unsigned Reduction = 0; for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ Instruction *I = cast(*UI); @@ -175,7 +175,7 @@ void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) { this->usesDynamicAlloca = true; } - if (isa(II) || isa(II->getType())) + if (isa(II) || II->getType()->isVectorTy()) ++NumVectorInsts; if (const CastInst *CI = dyn_cast(II)) { diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index b53ac13925..8288e96eb7 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -194,11 +194,10 @@ Value *llvm::SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, const Type *ITy = GetCompareTy(LHS); // icmp X, X -> true/false - if (LHS == RHS) + // X icmp undef -> true/false. For example, icmp ugt %X, undef -> false + // because X could be 0. + if (LHS == RHS || isa(RHS)) return ConstantInt::get(ITy, CmpInst::isTrueWhenEqual(Pred)); - - if (isa(RHS)) // X icmp undef -> undef - return UndefValue::get(ITy); // icmp , - Global/Stack value // addresses never equal each other! We already know that Op0 != Op1. @@ -283,6 +282,32 @@ Value *llvm::SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, // True if unordered. return ConstantInt::getTrue(CFP->getContext()); } + // Check whether the constant is an infinity. + if (CFP->getValueAPF().isInfinity()) { + if (CFP->getValueAPF().isNegative()) { + switch (Pred) { + case FCmpInst::FCMP_OLT: + // No value is ordered and less than negative infinity. + return ConstantInt::getFalse(CFP->getContext()); + case FCmpInst::FCMP_UGE: + // All values are unordered with or at least negative infinity. + return ConstantInt::getTrue(CFP->getContext()); + default: + break; + } + } else { + switch (Pred) { + case FCmpInst::FCMP_OGT: + // No value is ordered and greater than infinity. + return ConstantInt::getFalse(CFP->getContext()); + case FCmpInst::FCMP_ULE: + // All values are unordered with and at most infinity. + return ConstantInt::getTrue(CFP->getContext()); + default: + break; + } + } + } } } diff --git a/lib/Analysis/MemoryDependenceAnalysis.cpp b/lib/Analysis/MemoryDependenceAnalysis.cpp index 2d74709df2..2aa2f17877 100644 --- a/lib/Analysis/MemoryDependenceAnalysis.cpp +++ b/lib/Analysis/MemoryDependenceAnalysis.cpp @@ -580,7 +580,7 @@ MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) { void MemoryDependenceAnalysis:: getNonLocalPointerDependency(Value *Pointer, bool isLoad, BasicBlock *FromBB, SmallVectorImpl &Result) { - assert(isa(Pointer->getType()) && + assert(Pointer->getType()->isPointerTy() && "Can't get pointer deps of a non-pointer!"); Result.clear(); @@ -861,7 +861,7 @@ getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, uint64_t PointeeSize, // Get the PHI translated pointer in this predecessor. This can fail if // not translatable, in which case the getAddr() returns null. PHITransAddr PredPointer(Pointer); - PredPointer.PHITranslateValue(BB, Pred); + PredPointer.PHITranslateValue(BB, Pred, 0); Value *PredPtrVal = PredPointer.getAddr(); @@ -1009,13 +1009,20 @@ RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P) { /// in more places that cached info does not necessarily keep. void MemoryDependenceAnalysis::invalidateCachedPointerInfo(Value *Ptr) { // If Ptr isn't really a pointer, just ignore it. - if (!isa(Ptr->getType())) return; + if (!Ptr->getType()->isPointerTy()) return; // Flush store info for the pointer. RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, false)); // Flush load info for the pointer. RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, true)); } +/// invalidateCachedPredecessors - Clear the PredIteratorCache info. +/// This needs to be done when the CFG changes, e.g., due to splitting +/// critical edges. +void MemoryDependenceAnalysis::invalidateCachedPredecessors() { + PredCache->clear(); +} + /// removeInstruction - Remove an instruction from the dependence analysis, /// updating the dependence of instructions that previously depended on it. /// This method attempts to keep the cache coherent using the reverse map. @@ -1050,7 +1057,7 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) { // Remove it from both the load info and the store info. The instruction // can't be in either of these maps if it is non-pointer. - if (isa(RemInst->getType())) { + if (RemInst->getType()->isPointerTy()) { RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(RemInst, false)); RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(RemInst, true)); } diff --git a/lib/Analysis/PHITransAddr.cpp b/lib/Analysis/PHITransAddr.cpp index 334a188d12..8e4fa03f21 100644 --- a/lib/Analysis/PHITransAddr.cpp +++ b/lib/Analysis/PHITransAddr.cpp @@ -134,7 +134,8 @@ static void RemoveInstInputs(Value *V, } Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, - BasicBlock *PredBB) { + BasicBlock *PredBB, + const DominatorTree *DT) { // If this is a non-instruction value, it can't require PHI translation. Instruction *Inst = dyn_cast(V); if (Inst == 0) return V; @@ -177,7 +178,7 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, // operands need to be phi translated, and if so, reconstruct it. if (BitCastInst *BC = dyn_cast(Inst)) { - Value *PHIIn = PHITranslateSubExpr(BC->getOperand(0), CurBB, PredBB); + Value *PHIIn = PHITranslateSubExpr(BC->getOperand(0), CurBB, PredBB, DT); if (PHIIn == 0) return 0; if (PHIIn == BC->getOperand(0)) return BC; @@ -193,7 +194,8 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, for (Value::use_iterator UI = PHIIn->use_begin(), E = PHIIn->use_end(); UI != E; ++UI) { if (BitCastInst *BCI = dyn_cast(*UI)) - if (BCI->getType() == BC->getType()) + if (BCI->getType() == BC->getType() && + (!DT || DT->dominates(BCI->getParent(), PredBB))) return BCI; } return 0; @@ -204,7 +206,7 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, SmallVector GEPOps; bool AnyChanged = false; for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) { - Value *GEPOp = PHITranslateSubExpr(GEP->getOperand(i), CurBB, PredBB); + Value *GEPOp = PHITranslateSubExpr(GEP->getOperand(i), CurBB, PredBB, DT); if (GEPOp == 0) return 0; AnyChanged |= GEPOp != GEP->getOperand(i); @@ -229,7 +231,8 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, if (GetElementPtrInst *GEPI = dyn_cast(*UI)) if (GEPI->getType() == GEP->getType() && GEPI->getNumOperands() == GEPOps.size() && - GEPI->getParent()->getParent() == CurBB->getParent()) { + GEPI->getParent()->getParent() == CurBB->getParent() && + (!DT || DT->dominates(GEPI->getParent(), PredBB))) { bool Mismatch = false; for (unsigned i = 0, e = GEPOps.size(); i != e; ++i) if (GEPI->getOperand(i) != GEPOps[i]) { @@ -251,7 +254,7 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, bool isNSW = cast(Inst)->hasNoSignedWrap(); bool isNUW = cast(Inst)->hasNoUnsignedWrap(); - Value *LHS = PHITranslateSubExpr(Inst->getOperand(0), CurBB, PredBB); + Value *LHS = PHITranslateSubExpr(Inst->getOperand(0), CurBB, PredBB, DT); if (LHS == 0) return 0; // If the PHI translated LHS is an add of a constant, fold the immediates. @@ -287,7 +290,8 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, if (BinaryOperator *BO = dyn_cast(*UI)) if (BO->getOpcode() == Instruction::Add && BO->getOperand(0) == LHS && BO->getOperand(1) == RHS && - BO->getParent()->getParent() == CurBB->getParent()) + BO->getParent()->getParent() == CurBB->getParent() && + (!DT || DT->dominates(BO->getParent(), PredBB))) return BO; } @@ -300,33 +304,24 @@ Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB, /// PHITranslateValue - PHI translate the current address up the CFG from -/// CurBB to Pred, updating our state the reflect any needed changes. This -/// returns true on failure and sets Addr to null. -bool PHITransAddr::PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB) { +/// CurBB to Pred, updating our state to reflect any needed changes. If the +/// dominator tree DT is non-null, the translated value must dominate +/// PredBB. This returns true on failure and sets Addr to null. +bool PHITransAddr::PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB, + const DominatorTree *DT) { assert(Verify() && "Invalid PHITransAddr!"); - Addr = PHITranslateSubExpr(Addr, CurBB, PredBB); + Addr = PHITranslateSubExpr(Addr, CurBB, PredBB, DT); assert(Verify() && "Invalid PHITransAddr!"); - return Addr == 0; -} -/// GetAvailablePHITranslatedSubExpr - Return the value computed by -/// PHITranslateSubExpr if it dominates PredBB, otherwise return null. -Value *PHITransAddr:: -GetAvailablePHITranslatedSubExpr(Value *V, BasicBlock *CurBB,BasicBlock *PredBB, - const DominatorTree &DT) const { - PHITransAddr Tmp(V, TD); - Tmp.PHITranslateValue(CurBB, PredBB); - - // See if PHI translation succeeds. - V = Tmp.getAddr(); - - // Make sure the value is live in the predecessor. - if (Instruction *Inst = dyn_cast_or_null(V)) - if (!DT.dominates(Inst->getParent(), PredBB)) - return 0; - return V; -} + if (DT) { + // Make sure the value is live in the predecessor. + if (Instruction *Inst = dyn_cast_or_null(Addr)) + if (!DT->dominates(Inst->getParent(), PredBB)) + Addr = 0; + } + return Addr == 0; +} /// PHITranslateWithInsertion - PHI translate this value into the specified /// predecessor block, inserting a computation of the value if it is @@ -365,8 +360,9 @@ InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB, SmallVectorImpl &NewInsts) { // See if we have a version of this value already available and dominating // PredBB. If so, there is no need to insert a new instance of it. - if (Value *Res = GetAvailablePHITranslatedSubExpr(InVal, CurBB, PredBB, DT)) - return Res; + PHITransAddr Tmp(InVal, TD); + if (!Tmp.PHITranslateValue(CurBB, PredBB, &DT)) + return Tmp.getAddr(); // If we don't have an available version of this value, it must be an // instruction. diff --git a/lib/Analysis/PointerTracking.cpp b/lib/Analysis/PointerTracking.cpp index 8da07e756d..ce7ac899cd 100644 --- a/lib/Analysis/PointerTracking.cpp +++ b/lib/Analysis/PointerTracking.cpp @@ -231,7 +231,7 @@ void PointerTracking::print(raw_ostream &OS, const Module* M) const { // this should be safe for the same reason its safe for SCEV. PointerTracking &PT = *const_cast(this); for (inst_iterator I=inst_begin(*FF), E=inst_end(*FF); I != E; ++I) { - if (!isa(I->getType())) + if (!I->getType()->isPointerTy()) continue; Value *Base; const SCEV *Limit, *Offset; diff --git a/lib/Analysis/ProfileInfo.cpp b/lib/Analysis/ProfileInfo.cpp index 85531be76a..66760c667e 100644 --- a/lib/Analysis/ProfileInfo.cpp +++ b/lib/Analysis/ProfileInfo.cpp @@ -246,7 +246,7 @@ const BasicBlock *ProfileInfoT:: succ_const_iterator Succ = succ_begin(BB), End = succ_end(BB); if (Succ == End) { - P[0] = BB; + P[ reinterpret_cast(0) ] = BB; if (Mode & GetPathToExit) { hasFoundPath = true; BB = 0; @@ -753,10 +753,10 @@ void ProfileInfoT::repair(const Function *F) { Succ != End; ++Succ) { Path P; GetPath(*Succ, 0, P, GetPathToExit); - if (Dest && Dest != P[0]) { + if (Dest && Dest != P[ reinterpret_cast(0) ]) { AllEdgesHaveSameReturn = false; } - Dest = P[0]; + Dest = P[ reinterpret_cast(0) ]; } if (AllEdgesHaveSameReturn) { if(EstimateMissingEdges(BB)) { @@ -928,7 +928,7 @@ void ProfileInfoT::repair(const Function *F) { Path P; const BasicBlock *Dest = GetPath(BB, 0, P, GetPathToExit | GetPathWithNewEdges); - Dest = P[0]; + Dest = P[ reinterpret_cast(0) ]; if (!Dest) continue; if (getEdgeWeight(getEdge(Dest,0)) == MissingValue) { diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 82be9cd5c4..b979f3328d 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -214,8 +214,8 @@ bool SCEVCastExpr::properlyDominates(BasicBlock *BB, DominatorTree *DT) const { SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeID &ID, const SCEV *op, const Type *ty) : SCEVCastExpr(ID, scTruncate, op, ty) { - assert((Op->getType()->isInteger() || isa(Op->getType())) && - (Ty->isInteger() || isa(Ty)) && + assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot truncate non-integer value!"); } @@ -226,8 +226,8 @@ void SCEVTruncateExpr::print(raw_ostream &OS) const { SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeID &ID, const SCEV *op, const Type *ty) : SCEVCastExpr(ID, scZeroExtend, op, ty) { - assert((Op->getType()->isInteger() || isa(Op->getType())) && - (Ty->isInteger() || isa(Ty)) && + assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot zero extend non-integer value!"); } @@ -238,8 +238,8 @@ void SCEVZeroExtendExpr::print(raw_ostream &OS) const { SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeID &ID, const SCEV *op, const Type *ty) : SCEVCastExpr(ID, scSignExtend, op, ty) { - assert((Op->getType()->isInteger() || isa(Op->getType())) && - (Ty->isInteger() || isa(Ty)) && + assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot sign extend non-integer value!"); } @@ -312,6 +312,21 @@ bool SCEVAddRecExpr::isLoopInvariant(const Loop *QueryLoop) const { return true; } +bool +SCEVAddRecExpr::dominates(BasicBlock *BB, DominatorTree *DT) const { + return DT->dominates(L->getHeader(), BB) && + SCEVNAryExpr::dominates(BB, DT); +} + +bool +SCEVAddRecExpr::properlyDominates(BasicBlock *BB, DominatorTree *DT) const { + // This uses a "dominates" query instead of "properly dominates" query because + // the instruction which produces the addrec's value is a PHI, and a PHI + // effectively properly dominates its entire containing block. + return DT->dominates(L->getHeader(), BB) && + SCEVNAryExpr::properlyDominates(BB, DT); +} + void SCEVAddRecExpr::print(raw_ostream &OS) const { OS << "{" << *Operands[0]; for (unsigned i = 1, e = Operands.size(); i != e; ++i) @@ -379,7 +394,7 @@ bool SCEVUnknown::isAlignOf(const Type *&AllocTy) const { if (ConstantInt *CI = dyn_cast(CE->getOperand(2))) if (CI->isOne() && STy->getNumElements() == 2 && - STy->getElementType(0)->isInteger(1)) { + STy->getElementType(0)->isIntegerTy(1)) { AllocTy = STy->getElementType(1); return true; } @@ -401,7 +416,7 @@ bool SCEVUnknown::isOffsetOf(const Type *&CTy, Constant *&FieldNo) const { cast(CE->getOperand(0)->getType())->getElementType(); // Ignore vector types here so that ScalarEvolutionExpander doesn't // emit getelementptrs that index into vectors. - if (isa(Ty) || isa(Ty)) { + if (Ty->isStructTy() || Ty->isArrayTy()) { CTy = Ty; FieldNo = CE->getOperand(2); return true; @@ -503,9 +518,9 @@ namespace { // Order pointer values after integer values. This helps SCEVExpander // form GEPs. - if (isa(LU->getType()) && !isa(RU->getType())) + if (LU->getType()->isPointerTy() && !RU->getType()->isPointerTy()) return false; - if (isa(RU->getType()) && !isa(LU->getType())) + if (RU->getType()->isPointerTy() && !LU->getType()->isPointerTy()) return true; // Compare getValueID values. @@ -601,7 +616,7 @@ namespace { /// When this routine is finished, we know that any duplicates in the vector are /// consecutive and that complexity is monotonically increasing. /// -/// Note that we go take special precautions to ensure that we get determinstic +/// Note that we go take special precautions to ensure that we get deterministic /// results from this routine. In other words, we don't want the results of /// this to depend on where the addresses of various SCEV objects happened to /// land in memory. @@ -729,7 +744,7 @@ static const SCEV *BinomialCoefficient(const SCEV *It, unsigned K, // We need at least W + T bits for the multiplication step unsigned CalculationBits = W + T; - // Calcuate 2^T, at width T+W. + // Calculate 2^T, at width T+W. APInt DivFactor = APInt(CalculationBits, 1).shl(T); // Calculate the multiplicative inverse of K! / 2^T; @@ -906,9 +921,7 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, if (MaxBECount == RecastedMaxBECount) { const Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); // Check whether Start+Step*MaxBECount has no unsigned overflow. - const SCEV *ZMul = - getMulExpr(CastedMaxBECount, - getTruncateOrZeroExtend(Step, Start->getType())); + const SCEV *ZMul = getMulExpr(CastedMaxBECount, Step); const SCEV *Add = getAddExpr(Start, ZMul); const SCEV *OperandExtendedAdd = getAddExpr(getZeroExtendExpr(Start, WideTy), @@ -922,9 +935,7 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, // Similar to above, only this time treat the step value as signed. // This covers loops that count down. - const SCEV *SMul = - getMulExpr(CastedMaxBECount, - getTruncateOrSignExtend(Step, Start->getType())); + const SCEV *SMul = getMulExpr(CastedMaxBECount, Step); Add = getAddExpr(Start, SMul); OperandExtendedAdd = getAddExpr(getZeroExtendExpr(Start, WideTy), @@ -1045,9 +1056,7 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, if (MaxBECount == RecastedMaxBECount) { const Type *WideTy = IntegerType::get(getContext(), BitWidth * 2); // Check whether Start+Step*MaxBECount has no signed overflow. - const SCEV *SMul = - getMulExpr(CastedMaxBECount, - getTruncateOrSignExtend(Step, Start->getType())); + const SCEV *SMul = getMulExpr(CastedMaxBECount, Step); const SCEV *Add = getAddExpr(Start, SMul); const SCEV *OperandExtendedAdd = getAddExpr(getSignExtendExpr(Start, WideTy), @@ -1061,9 +1070,7 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op, // Similar to above, only this time treat the step value as unsigned. // This covers loops that count up with an unsigned step. - const SCEV *UMul = - getMulExpr(CastedMaxBECount, - getTruncateOrZeroExtend(Step, Start->getType())); + const SCEV *UMul = getMulExpr(CastedMaxBECount, Step); Add = getAddExpr(Start, UMul); OperandExtendedAdd = getAddExpr(getSignExtendExpr(Start, WideTy), @@ -1403,7 +1410,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl &Ops, // If we deleted at least one add, we added operands to the end of the list, // and they are not necessarily sorted. Recurse to resort and resimplify - // any operands we just aquired. + // any operands we just acquired. if (DeletedAdd) return getAddExpr(Ops); } @@ -1710,7 +1717,7 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl &Ops, // If we deleted at least one mul, we added operands to the end of the list, // and they are not necessarily sorted. Recurse to resort and resimplify - // any operands we just aquired. + // any operands we just acquired. if (DeletedMul) return getMulExpr(Ops); } @@ -1958,6 +1965,12 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl &Operands, return getAddRecExpr(Operands, L, HasNUW, HasNSW); // {X,+,0} --> X } + // It's tempting to want to call getMaxBackedgeTakenCount count here and + // use that information to infer NUW and NSW flags. However, computing a + // BE count requires calling getAddRecExpr, so we may not yet have a + // meaningful BE count at this point (and if we don't, we'd be stuck + // with a SCEVCouldNotCompute as the cached BE count). + // If HasNSW is true and all the operands are non-negative, infer HasNUW. if (!HasNUW && HasNSW) { bool All = true; @@ -2293,7 +2306,7 @@ const SCEV *ScalarEvolution::getUnknown(Value *V) { /// has access to target-specific information. bool ScalarEvolution::isSCEVable(const Type *Ty) const { // Integers and pointers are always SCEVable. - return Ty->isInteger() || isa(Ty); + return Ty->isIntegerTy() || Ty->isPointerTy(); } /// getTypeSizeInBits - Return the size in bits of the specified type, @@ -2306,12 +2319,12 @@ uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { return TD->getTypeSizeInBits(Ty); // Integer types have fixed sizes. - if (Ty->isInteger()) + if (Ty->isIntegerTy()) return Ty->getPrimitiveSizeInBits(); // The only other support type is pointer. Without TargetData, conservatively // assume pointers are 64-bit. - assert(isa(Ty) && "isSCEVable permitted a non-SCEVable type!"); + assert(Ty->isPointerTy() && "isSCEVable permitted a non-SCEVable type!"); return 64; } @@ -2322,11 +2335,11 @@ uint64_t ScalarEvolution::getTypeSizeInBits(const Type *Ty) const { const Type *ScalarEvolution::getEffectiveSCEVType(const Type *Ty) const { assert(isSCEVable(Ty) && "Type is not SCEVable!"); - if (Ty->isInteger()) + if (Ty->isIntegerTy()) return Ty; // The only other support type is pointer. - assert(isa(Ty) && "Unexpected non-pointer non-integer type!"); + assert(Ty->isPointerTy() && "Unexpected non-pointer non-integer type!"); if (TD) return TD->getIntPtrType(getContext()); // Without TargetData, conservatively assume pointers are 64-bit. @@ -2397,8 +2410,8 @@ const SCEV * ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, const Type *Ty) { const Type *SrcTy = V->getType(); - assert((SrcTy->isInteger() || isa(SrcTy)) && - (Ty->isInteger() || isa(Ty)) && + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot truncate or zero extend with non-integer arguments!"); if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) return V; // No conversion @@ -2414,8 +2427,8 @@ const SCEV * ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, const Type *Ty) { const Type *SrcTy = V->getType(); - assert((SrcTy->isInteger() || isa(SrcTy)) && - (Ty->isInteger() || isa(Ty)) && + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot truncate or zero extend with non-integer arguments!"); if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty)) return V; // No conversion @@ -2430,8 +2443,8 @@ ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, const SCEV * ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, const Type *Ty) { const Type *SrcTy = V->getType(); - assert((SrcTy->isInteger() || isa(SrcTy)) && - (Ty->isInteger() || isa(Ty)) && + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot noop or zero extend with non-integer arguments!"); assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && "getNoopOrZeroExtend cannot truncate!"); @@ -2446,8 +2459,8 @@ ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, const Type *Ty) { const SCEV * ScalarEvolution::getNoopOrSignExtend(const SCEV *V, const Type *Ty) { const Type *SrcTy = V->getType(); - assert((SrcTy->isInteger() || isa(SrcTy)) && - (Ty->isInteger() || isa(Ty)) && + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot noop or sign extend with non-integer arguments!"); assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && "getNoopOrSignExtend cannot truncate!"); @@ -2463,8 +2476,8 @@ ScalarEvolution::getNoopOrSignExtend(const SCEV *V, const Type *Ty) { const SCEV * ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, const Type *Ty) { const Type *SrcTy = V->getType(); - assert((SrcTy->isInteger() || isa(SrcTy)) && - (Ty->isInteger() || isa(Ty)) && + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot noop or any extend with non-integer arguments!"); assert(getTypeSizeInBits(SrcTy) <= getTypeSizeInBits(Ty) && "getNoopOrAnyExtend cannot truncate!"); @@ -2478,8 +2491,8 @@ ScalarEvolution::getNoopOrAnyExtend(const SCEV *V, const Type *Ty) { const SCEV * ScalarEvolution::getTruncateOrNoop(const SCEV *V, const Type *Ty) { const Type *SrcTy = V->getType(); - assert((SrcTy->isInteger() || isa(SrcTy)) && - (Ty->isInteger() || isa(Ty)) && + assert((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && + (Ty->isIntegerTy() || Ty->isPointerTy()) && "Cannot truncate or noop with non-integer arguments!"); assert(getTypeSizeInBits(SrcTy) >= getTypeSizeInBits(Ty) && "getTruncateOrNoop cannot extend!"); @@ -2536,12 +2549,12 @@ PushDefUseChildren(Instruction *I, /// the Scalars map if they reference SymName. This is used during PHI /// resolution. void -ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) { +ScalarEvolution::ForgetSymbolicName(Instruction *PN, const SCEV *SymName) { SmallVector Worklist; - PushDefUseChildren(I, Worklist); + PushDefUseChildren(PN, Worklist); SmallPtrSet Visited; - Visited.insert(I); + Visited.insert(PN); while (!Worklist.empty()) { Instruction *I = Worklist.pop_back_val(); if (!Visited.insert(I)) continue; @@ -2551,16 +2564,19 @@ ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) { if (It != Scalars.end()) { // Short-circuit the def-use traversal if the symbolic name // ceases to appear in expressions. - if (!It->second->hasOperand(SymName)) + if (It->second != SymName && !It->second->hasOperand(SymName)) continue; // SCEVUnknown for a PHI either means that it has an unrecognized - // structure, or it's a PHI that's in the progress of being computed - // by createNodeForPHI. In the former case, additional loop trip - // count information isn't going to change anything. In the later - // case, createNodeForPHI will perform the necessary updates on its - // own when it gets to that point. - if (!isa(I) || !isa(It->second)) { + // structure, it's a PHI that's in the progress of being computed + // by createNodeForPHI, or it's a single-value PHI. In the first case, + // additional loop trip count information isn't going to change anything. + // In the second case, createNodeForPHI will perform the necessary + // updates on its own when it gets to that point. In the third, we do + // want to forget the SCEVUnknown. + if (!isa(I) || + !isa(It->second) || + (I != PN && It->second == SymName)) { ValuesAtScopes.erase(It->second); Scalars.erase(It); } @@ -2683,9 +2699,21 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) { return SymbolicName; } - // It's tempting to recognize PHIs with a unique incoming value, however - // this leads passes like indvars to break LCSSA form. Fortunately, such - // PHIs are rare, as instcombine zaps them. + // If the PHI has a single incoming value, follow that value, unless the + // PHI's incoming blocks are in a different loop, in which case doing so + // risks breaking LCSSA form. Instcombine would normally zap these, but + // it doesn't have DominatorTree information, so it may miss cases. + if (Value *V = PN->hasConstantValue(DT)) { + bool AllSameLoop = true; + Loop *PNLoop = LI->getLoopFor(PN->getParent()); + for (size_t i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (LI->getLoopFor(PN->getIncomingBlock(i)) != PNLoop) { + AllSameLoop = false; + break; + } + if (AllSameLoop) + return getSCEV(V); + } // If it's not a loop phi, we can't handle it yet. return getUnknown(PN); @@ -2718,7 +2746,7 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) { } else { // For an array, add the element offset, explicitly scaled. const SCEV *LocalOffset = getSCEV(Index); - // Getelementptr indicies are signed. + // Getelementptr indices are signed. LocalOffset = getTruncateOrSignExtend(LocalOffset, IntPtrTy); // Lower "inbounds" GEPs to NSW arithmetic. LocalOffset = getMulExpr(LocalOffset, getSizeOfExpr(*GTI), @@ -2921,7 +2949,6 @@ ScalarEvolution::getUnsignedRange(const SCEV *S) { if (const SCEVUnknown *U = dyn_cast(S)) { // For a SCEVUnknown, ask ValueTracking. - unsigned BitWidth = getTypeSizeInBits(U->getType()); APInt Mask = APInt::getAllOnesValue(BitWidth); APInt Zeros(BitWidth, 0), Ones(BitWidth, 0); ComputeMaskedBits(U->getValue(), Mask, Zeros, Ones, TD); @@ -3053,7 +3080,7 @@ ScalarEvolution::getSignedRange(const SCEV *S) { if (const SCEVUnknown *U = dyn_cast(S)) { // For a SCEVUnknown, ask ValueTracking. - if (!U->getValue()->getType()->isInteger() && !TD) + if (!U->getValue()->getType()->isIntegerTy() && !TD) return ConservativeResult; unsigned NS = ComputeNumSignBits(U->getValue(), TD); if (NS == 1) @@ -3193,7 +3220,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { const Type *Z0Ty = Z0->getType(); unsigned Z0TySize = getTypeSizeInBits(Z0Ty); - // If C is a low-bits mask, the zero extend is zerving to + // If C is a low-bits mask, the zero extend is serving to // mask off the high bits. Complement the operand and // re-apply the zext. if (APIntOps::isMask(Z0TySize, CI->getValue())) @@ -3378,7 +3405,7 @@ PushLoopPHIs(const Loop *L, SmallVectorImpl &Worklist) { const ScalarEvolution::BackedgeTakenInfo & ScalarEvolution::getBackedgeTakenInfo(const Loop *L) { // Initially insert a CouldNotCompute for this loop. If the insertion - // succeeds, procede to actually compute a backedge-taken count and + // succeeds, proceed to actually compute a backedge-taken count and // update the value. The temporary CouldNotCompute value tells SCEV // code elsewhere that it shouldn't attempt to request a new // backedge-taken count, which could result in infinite recursion. @@ -3470,6 +3497,35 @@ void ScalarEvolution::forgetLoop(const Loop *L) { } } +/// forgetValue - This method should be called by the client when it has +/// changed a value in a way that may effect its value, or which may +/// disconnect it from a def-use chain linking it to a loop. +void ScalarEvolution::forgetValue(Value *V) { + Instruction *I = dyn_cast(V); + if (!I) return; + + // Drop information about expressions based on loop-header PHIs. + SmallVector Worklist; + Worklist.push_back(I); + + SmallPtrSet Visited; + while (!Worklist.empty()) { + I = Worklist.pop_back_val(); + if (!Visited.insert(I)) continue; + + std::map::iterator It = + Scalars.find(static_cast(I)); + if (It != Scalars.end()) { + ValuesAtScopes.erase(It->second); + Scalars.erase(It); + if (PHINode *PN = dyn_cast(I)) + ConstantEvolutionLoopExitValue.erase(PN); + } + + PushDefUseChildren(I, Worklist); + } +} + /// ComputeBackedgeTakenCount - Compute the number of times the backedge /// of the specified loop will execute. ScalarEvolution::BackedgeTakenInfo @@ -3566,7 +3622,7 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExit(const Loop *L, return getCouldNotCompute(); } - // Procede to the next level to examine the exit condition expression. + // Proceed to the next level to examine the exit condition expression. return ComputeBackedgeTakenCountFromExitCond(L, ExitBr->getCondition(), ExitBr->getSuccessor(0), ExitBr->getSuccessor(1)); @@ -3655,10 +3711,23 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L, } // With an icmp, it may be feasible to compute an exact backedge-taken count. - // Procede to the next level to examine the icmp. + // Proceed to the next level to examine the icmp. if (ICmpInst *ExitCondICmp = dyn_cast(ExitCond)) return ComputeBackedgeTakenCountFromExitCondICmp(L, ExitCondICmp, TBB, FBB); + // Check for a constant condition. These are normally stripped out by + // SimplifyCFG, but ScalarEvolution may be used by a pass which wishes to + // preserve the CFG and is temporarily leaving constant conditions + // in place. + if (ConstantInt *CI = dyn_cast(ExitCond)) { + if (L->contains(FBB) == !CI->getZExtValue()) + // The backedge is always taken. + return getCouldNotCompute(); + else + // The backedge is never taken. + return getIntegerSCEV(0, CI->getType()); + } + // If it's not an integer or pointer comparison then compute it the hard way. return ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB)); } @@ -3682,14 +3751,10 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, // Handle common loops like: for (X = "string"; *X; ++X) if (LoadInst *LI = dyn_cast(ExitCond->getOperand(0))) if (Constant *RHS = dyn_cast(ExitCond->getOperand(1))) { - const SCEV *ItCnt = + BackedgeTakenInfo ItCnt = ComputeLoadConstantCompareBackedgeTakenCount(LI, RHS, L, Cond); - if (!isa(ItCnt)) { - unsigned BitWidth = getTypeSizeInBits(ItCnt->getType()); - return BackedgeTakenInfo(ItCnt, - isa(ItCnt) ? ItCnt : - getConstant(APInt::getMaxValue(BitWidth)-1)); - } + if (ItCnt.hasAnyInfo()) + return ItCnt; } const SCEV *LHS = getSCEV(ExitCond->getOperand(0)); @@ -3723,14 +3788,14 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L, switch (Cond) { case ICmpInst::ICMP_NE: { // while (X != Y) // Convert to: while (X-Y != 0) - const SCEV *TC = HowFarToZero(getMinusSCEV(LHS, RHS), L); - if (!isa(TC)) return TC; + BackedgeTakenInfo BTI = HowFarToZero(getMinusSCEV(LHS, RHS), L); + if (BTI.hasAnyInfo()) return BTI; break; } case ICmpInst::ICMP_EQ: { // while (X == Y) // Convert to: while (X-Y == 0) - const SCEV *TC = HowFarToNonZero(getMinusSCEV(LHS, RHS), L); - if (!isa(TC)) return TC; + BackedgeTakenInfo BTI = HowFarToNonZero(getMinusSCEV(LHS, RHS), L); + if (BTI.hasAnyInfo()) return BTI; break; } case ICmpInst::ICMP_SLT: { @@ -3817,7 +3882,7 @@ GetAddressedElementFromGlobal(GlobalVariable *GV, /// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition of /// 'icmp op load X, cst', try to see if we can compute the backedge /// execution count. -const SCEV * +ScalarEvolution::BackedgeTakenInfo ScalarEvolution::ComputeLoadConstantCompareBackedgeTakenCount( LoadInst *LI, Constant *RHS, @@ -3826,6 +3891,7 @@ ScalarEvolution::ComputeLoadConstantCompareBackedgeTakenCount( if (LI->isVolatile()) return getCouldNotCompute(); // Check to see if the loaded pointer is a getelementptr of a global. + // TODO: Use SCEV instead of manually grubbing with GEPs. GetElementPtrInst *GEP = dyn_cast(LI->getOperand(0)); if (!GEP) return getCouldNotCompute(); @@ -4175,14 +4241,15 @@ const SCEV *ScalarEvolution::computeSCEVAtScope(const SCEV *V, const Loop *L) { } } - Constant *C; + Constant *C = 0; if (const CmpInst *CI = dyn_cast(I)) C = ConstantFoldCompareInstOperands(CI->getPredicate(), Operands[0], Operands[1], TD); else C = ConstantFoldInstOperands(I->getOpcode(), I->getType(), &Operands[0], Operands.size(), TD); - return getSCEV(C); + if (C) + return getSCEV(C); } } @@ -4390,7 +4457,8 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec, ScalarEvolution &SE) { /// HowFarToZero - Return the number of times a backedge comparing the specified /// value to zero will execute. If not computable, return CouldNotCompute. -const SCEV *ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { // If the value is a constant if (const SCEVConstant *C = dyn_cast(V)) { // If the value is already zero, the branch will execute zero times. @@ -4435,7 +4503,7 @@ const SCEV *ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { -StartC->getValue()->getValue(), *this); } - } else if (AddRec->isQuadratic() && AddRec->getType()->isInteger()) { + } else if (AddRec->isQuadratic() && AddRec->getType()->isIntegerTy()) { // If this is a quadratic (3-term) AddRec {L,+,M,+,N}, find the roots of // the quadratic equation to solve it. std::pair Roots = SolveQuadraticEquation(AddRec, @@ -4470,7 +4538,8 @@ const SCEV *ScalarEvolution::HowFarToZero(const SCEV *V, const Loop *L) { /// HowFarToNonZero - Return the number of times a backedge checking the /// specified value for nonzero will execute. If not computable, return /// CouldNotCompute -const SCEV *ScalarEvolution::HowFarToNonZero(const SCEV *V, const Loop *L) { +ScalarEvolution::BackedgeTakenInfo +ScalarEvolution::HowFarToNonZero(const SCEV *V, const Loop *L) { // Loops that look like: while (X == 0) are very strange indeed. We don't // handle them yet except for the trivial case. This could be expanded in the // future as needed. @@ -4711,7 +4780,7 @@ bool ScalarEvolution::isImpliedCond(Value *CondValue, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, bool Inverse) { - // Recursivly handle And and Or conditions. + // Recursively handle And and Or conditions. if (BinaryOperator *BO = dyn_cast(CondValue)) { if (BO->getOpcode() == Instruction::And) { if (!Inverse) @@ -4914,7 +4983,7 @@ bool ScalarEvolution::isImpliedCond(Value *CondValue, } /// isImpliedCondOperands - Test whether the condition described by Pred, -/// LHS, and RHS is true whenever the condition desribed by Pred, FoundLHS, +/// LHS, and RHS is true whenever the condition described by Pred, FoundLHS, /// and FoundRHS is true. bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS, @@ -4929,7 +4998,7 @@ bool ScalarEvolution::isImpliedCondOperands(ICmpInst::Predicate Pred, } /// isImpliedCondOperandsHelper - Test whether the condition described by -/// Pred, LHS, and RHS is true whenever the condition desribed by Pred, +/// Pred, LHS, and RHS is true whenever the condition described by Pred, /// FoundLHS, and FoundRHS is true. bool ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, @@ -5087,7 +5156,7 @@ ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS, // If MaxEnd is within a step of the maximum integer value in its type, // adjust it down to the minimum value which would produce the same effect. - // This allows the subsequent ceiling divison of (N+(step-1))/step to + // This allows the subsequent ceiling division of (N+(step-1))/step to // compute the correct value. const SCEV *StepMinusOne = getMinusSCEV(Step, getIntegerSCEV(1, Step->getType())); @@ -5304,8 +5373,8 @@ ScalarEvolution::ScalarEvolution() bool ScalarEvolution::runOnFunction(Function &F) { this->F = &F; LI = &getAnalysis(); - DT = &getAnalysis(); TD = getAnalysisIfAvailable(); + DT = &getAnalysis(); return false; } @@ -5364,7 +5433,7 @@ static void PrintLoopInfo(raw_ostream &OS, ScalarEvolution *SE, } void ScalarEvolution::print(raw_ostream &OS, const Module *) const { - // ScalarEvolution's implementaiton of the print method is to print + // ScalarEvolution's implementation of the print method is to print // out SCEV values of all instructions that are interesting. Doing // this potentially causes it to create new SCEV objects though, // which technically conflicts with the const qualifier. This isn't diff --git a/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp index 498c4a876c..17b254fca6 100644 --- a/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp +++ b/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp @@ -10,6 +10,10 @@ // This file defines the ScalarEvolutionAliasAnalysis pass, which implements a // simple alias analysis implemented in terms of ScalarEvolution queries. // +// This differs from traditional loop dependence analysis in that it tests +// for dependencies within a single iteration of a loop, rather than +// dependences between different iterations. +// // ScalarEvolution has a more complete understanding of pointer arithmetic // than BasicAliasAnalysis' collection of ad-hoc analyses. // @@ -41,7 +45,7 @@ namespace { return (AliasAnalysis*)this; return this; } - + private: virtual void getAnalysisUsage(AnalysisUsage &AU) const; virtual bool runOnFunction(Function &F); @@ -89,7 +93,7 @@ ScalarEvolutionAliasAnalysis::GetBaseValue(const SCEV *S) { } else if (const SCEVAddExpr *A = dyn_cast(S)) { // If there's a pointer operand, it'll be sorted at the end of the list. const SCEV *Last = A->getOperand(A->getNumOperands()-1); - if (isa(Last->getType())) + if (Last->getType()->isPointerTy()) return GetBaseValue(Last); } else if (const SCEVUnknown *U = dyn_cast(S)) { // This is a leaf node. diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index 4310e3ccfa..e27da96692 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -15,6 +15,7 @@ #include "llvm/Analysis/ScalarEvolutionExpander.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/IntrinsicInst.h" #include "llvm/LLVMContext.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/STLExtras.h" @@ -137,6 +138,10 @@ Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, if (IP != BlockBegin) { --IP; for (; ScanLimit; --IP, --ScanLimit) { + // Don't count dbg.value against the ScanLimit, to avoid perturbing the + // generated code. + if (isa(IP)) + ScanLimit++; if (IP->getOpcode() == (unsigned)Opcode && IP->getOperand(0) == LHS && IP->getOperand(1) == RHS) return IP; @@ -144,15 +149,34 @@ Value *SCEVExpander::InsertBinop(Instruction::BinaryOps Opcode, } } + // Save the original insertion point so we can restore it when we're done. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + + // Move the insertion point out of as many loops as we can. + while (const Loop *L = SE.LI->getLoopFor(Builder.GetInsertBlock())) { + if (!L->isLoopInvariant(LHS) || !L->isLoopInvariant(RHS)) break; + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) break; + + // Ok, move up a level. + Builder.SetInsertPoint(Preheader, Preheader->getTerminator()); + } + // If we haven't found this binop, insert it. Value *BO = Builder.CreateBinOp(Opcode, LHS, RHS, "tmp"); rememberInstruction(BO); + + // Restore the original insert point. + if (SaveInsertBB) + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + return BO; } /// FactorOutConstant - Test if S is divisible by Factor, using signed /// division. If so, update S with Factor divided out and return true. -/// S need not be evenly divisble if a reasonable remainder can be +/// S need not be evenly divisible if a reasonable remainder can be /// computed. /// TODO: When ScalarEvolution gets a SCEVSDivExpr, this can be made /// unnecessary; in its place, just signed-divide Ops[i] by the scale and @@ -462,7 +486,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, break; } - // If none of the operands were convertable to proper GEP indices, cast + // If none of the operands were convertible to proper GEP indices, cast // the base to i8* and do an ugly getelementptr with that. It's still // better than ptrtoint+arithmetic+inttoptr at least. if (!AnyNonZeroIndices) { @@ -486,6 +510,10 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, if (IP != BlockBegin) { --IP; for (; ScanLimit; --IP, --ScanLimit) { + // Don't count dbg.value against the ScanLimit, to avoid perturbing the + // generated code. + if (isa(IP)) + ScanLimit++; if (IP->getOpcode() == Instruction::GetElementPtr && IP->getOperand(0) == V && IP->getOperand(1) == Idx) return IP; @@ -493,12 +521,56 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, } } + // Save the original insertion point so we can restore it when we're done. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + + // Move the insertion point out of as many loops as we can. + while (const Loop *L = SE.LI->getLoopFor(Builder.GetInsertBlock())) { + if (!L->isLoopInvariant(V) || !L->isLoopInvariant(Idx)) break; + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) break; + + // Ok, move up a level. + Builder.SetInsertPoint(Preheader, Preheader->getTerminator()); + } + // Emit a GEP. Value *GEP = Builder.CreateGEP(V, Idx, "uglygep"); rememberInstruction(GEP); + + // Restore the original insert point. + if (SaveInsertBB) + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + return GEP; } + // Save the original insertion point so we can restore it when we're done. + BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); + BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); + + // Move the insertion point out of as many loops as we can. + while (const Loop *L = SE.LI->getLoopFor(Builder.GetInsertBlock())) { + if (!L->isLoopInvariant(V)) break; + + bool AnyIndexNotLoopInvariant = false; + for (SmallVectorImpl::const_iterator I = GepIndices.begin(), + E = GepIndices.end(); I != E; ++I) + if (!L->isLoopInvariant(*I)) { + AnyIndexNotLoopInvariant = true; + break; + } + if (AnyIndexNotLoopInvariant) + break; + + BasicBlock *Preheader = L->getLoopPreheader(); + if (!Preheader) break; + + // Ok, move up a level. + Builder.SetInsertPoint(Preheader, Preheader->getTerminator()); + } + // Insert a pretty getelementptr. Note that this GEP is not marked inbounds, // because ScalarEvolution may have changed the address arithmetic to // compute a value which is beyond the end of the allocated object. @@ -511,6 +583,11 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, "scevgep"); Ops.push_back(SE.getUnknown(GEP)); rememberInstruction(GEP); + + // Restore the original insert point. + if (SaveInsertBB) + restoreInsertPoint(SaveInsertBB, SaveInsertPt); + return expand(SE.getAddExpr(Ops)); } @@ -528,70 +605,179 @@ static bool isNonConstantNegative(const SCEV *F) { return SC->getValue()->getValue().isNegative(); } -Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { - int NumOperands = S->getNumOperands(); - const Type *Ty = SE.getEffectiveSCEVType(S->getType()); +/// PickMostRelevantLoop - Given two loops pick the one that's most relevant for +/// SCEV expansion. If they are nested, this is the most nested. If they are +/// neighboring, pick the later. +static const Loop *PickMostRelevantLoop(const Loop *A, const Loop *B, + DominatorTree &DT) { + if (!A) return B; + if (!B) return A; + if (A->contains(B)) return B; + if (B->contains(A)) return A; + if (DT.dominates(A->getHeader(), B->getHeader())) return B; + if (DT.dominates(B->getHeader(), A->getHeader())) return A; + return A; // Arbitrarily break the tie. +} - // Find the index of an operand to start with. Choose the operand with - // pointer type, if there is one, or the last operand otherwise. - int PIdx = 0; - for (; PIdx != NumOperands - 1; ++PIdx) - if (isa(S->getOperand(PIdx)->getType())) break; +/// GetRelevantLoop - Get the most relevant loop associated with the given +/// expression, according to PickMostRelevantLoop. +static const Loop *GetRelevantLoop(const SCEV *S, LoopInfo &LI, + DominatorTree &DT) { + if (isa(S)) + return 0; + if (const SCEVUnknown *U = dyn_cast(S)) { + if (const Instruction *I = dyn_cast(U->getValue())) + return LI.getLoopFor(I->getParent()); + return 0; + } + if (const SCEVNAryExpr *N = dyn_cast(S)) { + const Loop *L = 0; + if (const SCEVAddRecExpr *AR = dyn_cast(S)) + L = AR->getLoop(); + for (SCEVNAryExpr::op_iterator I = N->op_begin(), E = N->op_end(); + I != E; ++I) + L = PickMostRelevantLoop(L, GetRelevantLoop(*I, LI, DT), DT); + return L; + } + if (const SCEVCastExpr *C = dyn_cast(S)) + return GetRelevantLoop(C->getOperand(), LI, DT); + if (const SCEVUDivExpr *D = dyn_cast(S)) + return PickMostRelevantLoop(GetRelevantLoop(D->getLHS(), LI, DT), + GetRelevantLoop(D->getRHS(), LI, DT), + DT); + llvm_unreachable("Unexpected SCEV type!"); +} - // Expand code for the operand that we chose. - Value *V = expand(S->getOperand(PIdx)); +/// LoopCompare - Compare loops by PickMostRelevantLoop. +class LoopCompare { + DominatorTree &DT; +public: + explicit LoopCompare(DominatorTree &dt) : DT(dt) {} + + bool operator()(std::pair LHS, + std::pair RHS) const { + // Compare loops with PickMostRelevantLoop. + if (LHS.first != RHS.first) + return PickMostRelevantLoop(LHS.first, RHS.first, DT) != LHS.first; + + // If one operand is a non-constant negative and the other is not, + // put the non-constant negative on the right so that a sub can + // be used instead of a negate and add. + if (isNonConstantNegative(LHS.second)) { + if (!isNonConstantNegative(RHS.second)) + return false; + } else if (isNonConstantNegative(RHS.second)) + return true; - // Turn things like ptrtoint+arithmetic+inttoptr into GEP. See the - // comments on expandAddToGEP for details. - if (const PointerType *PTy = dyn_cast(V->getType())) { - // Take the operand at PIdx out of the list. - const SmallVectorImpl &Ops = S->getOperands(); - SmallVector NewOps; - NewOps.insert(NewOps.end(), Ops.begin(), Ops.begin() + PIdx); - NewOps.insert(NewOps.end(), Ops.begin() + PIdx + 1, Ops.end()); - // Make a GEP. - return expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, V); + // Otherwise they are equivalent according to this comparison. + return false; } +}; - // Otherwise, we'll expand the rest of the SCEVAddExpr as plain integer - // arithmetic. - V = InsertNoopCastOfTo(V, Ty); +Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) { + const Type *Ty = SE.getEffectiveSCEVType(S->getType()); - // Emit a bunch of add instructions - for (int i = NumOperands-1; i >= 0; --i) { - if (i == PIdx) continue; - const SCEV *Op = S->getOperand(i); - if (isNonConstantNegative(Op)) { + // Collect all the add operands in a loop, along with their associated loops. + // Iterate in reverse so that constants are emitted last, all else equal, and + // so that pointer operands are inserted first, which the code below relies on + // to form more involved GEPs. + SmallVector, 8> OpsAndLoops; + for (std::reverse_iterator I(S->op_end()), + E(S->op_begin()); I != E; ++I) + OpsAndLoops.push_back(std::make_pair(GetRelevantLoop(*I, *SE.LI, *SE.DT), + *I)); + + // Sort by loop. Use a stable sort so that constants follow non-constants and + // pointer operands precede non-pointer operands. + std::stable_sort(OpsAndLoops.begin(), OpsAndLoops.end(), LoopCompare(*SE.DT)); + + // Emit instructions to add all the operands. Hoist as much as possible + // out of loops, and form meaningful getelementptrs where possible. + Value *Sum = 0; + for (SmallVectorImpl >::iterator + I = OpsAndLoops.begin(), E = OpsAndLoops.end(); I != E; ) { + const Loop *CurLoop = I->first; + const SCEV *Op = I->second; + if (!Sum) { + // This is the first operand. Just expand it. + Sum = expand(Op); + ++I; + } else if (const PointerType *PTy = dyn_cast(Sum->getType())) { + // The running sum expression is a pointer. Try to form a getelementptr + // at this level with that as the base. + SmallVector NewOps; + for (; I != E && I->first == CurLoop; ++I) + NewOps.push_back(I->second); + Sum = expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, Sum); + } else if (const PointerType *PTy = dyn_cast(Op->getType())) { + // The running sum is an integer, and there's a pointer at this level. + // Try to form a getelementptr. + SmallVector NewOps; + NewOps.push_back(SE.getUnknown(Sum)); + for (++I; I != E && I->first == CurLoop; ++I) + NewOps.push_back(I->second); + Sum = expandAddToGEP(NewOps.begin(), NewOps.end(), PTy, Ty, expand(Op)); + } else if (isNonConstantNegative(Op)) { + // Instead of doing a negate and add, just do a subtract. Value *W = expandCodeFor(SE.getNegativeSCEV(Op), Ty); - V = InsertBinop(Instruction::Sub, V, W); + Sum = InsertNoopCastOfTo(Sum, Ty); + Sum = InsertBinop(Instruction::Sub, Sum, W); + ++I; } else { + // A simple add. Value *W = expandCodeFor(Op, Ty); - V = InsertBinop(Instruction::Add, V, W); + Sum = InsertNoopCastOfTo(Sum, Ty); + // Canonicalize a constant to the RHS. + if (isa(Sum)) std::swap(Sum, W); + Sum = InsertBinop(Instruction::Add, Sum, W); + ++I; } } - return V; + + return Sum; } Value *SCEVExpander::visitMulExpr(const SCEVMulExpr *S) { const Type *Ty = SE.getEffectiveSCEVType(S->getType()); - int FirstOp = 0; // Set if we should emit a subtract. - if (const SCEVConstant *SC = dyn_cast(S->getOperand(0))) - if (SC->getValue()->isAllOnesValue()) - FirstOp = 1; - - int i = S->getNumOperands()-2; - Value *V = expandCodeFor(S->getOperand(i+1), Ty); - - // Emit a bunch of multiply instructions - for (; i >= FirstOp; --i) { - Value *W = expandCodeFor(S->getOperand(i), Ty); - V = InsertBinop(Instruction::Mul, V, W); + + // Collect all the mul operands in a loop, along with their associated loops. + // Iterate in reverse so that constants are emitted last, all else equal. + SmallVector, 8> OpsAndLoops; + for (std::reverse_iterator I(S->op_end()), + E(S->op_begin()); I != E; ++I) + OpsAndLoops.push_back(std::make_pair(GetRelevantLoop(*I, *SE.LI, *SE.DT), + *I)); + + // Sort by loop. Use a stable sort so that constants follow non-constants. + std::stable_sort(OpsAndLoops.begin(), OpsAndLoops.end(), LoopCompare(*SE.DT)); + + // Emit instructions to mul all the operands. Hoist as much as possible + // out of loops. + Value *Prod = 0; + for (SmallVectorImpl >::iterator + I = OpsAndLoops.begin(), E = OpsAndLoops.end(); I != E; ) { + const SCEV *Op = I->second; + if (!Prod) { + // This is the first operand. Just expand it. + Prod = expand(Op); + ++I; + } else if (Op->isAllOnesValue()) { + // Instead of doing a multiply by negative one, just do a negate. + Prod = InsertNoopCastOfTo(Prod, Ty); + Prod = InsertBinop(Instruction::Sub, Constant::getNullValue(Ty), Prod); + ++I; + } else { + // A simple mul. + Value *W = expandCodeFor(Op, Ty); + Prod = InsertNoopCastOfTo(Prod, Ty); + // Canonicalize a constant to the RHS. + if (isa(Prod)) std::swap(Prod, W); + Prod = InsertBinop(Instruction::Mul, Prod, W); + ++I; + } } - // -1 * ... ---> 0 - ... - if (FirstOp == 1) - V = InsertBinop(Instruction::Sub, Constant::getNullValue(Ty), V); - return V; + return Prod; } Value *SCEVExpander::visitUDivExpr(const SCEVUDivExpr *S) { @@ -641,8 +827,65 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, // Reuse a previously-inserted PHI, if present. for (BasicBlock::iterator I = L->getHeader()->begin(); PHINode *PN = dyn_cast(I); ++I) - if (isInsertedInstruction(PN) && SE.getSCEV(PN) == Normalized) - return PN; + if (SE.isSCEVable(PN->getType()) && + (SE.getEffectiveSCEVType(PN->getType()) == + SE.getEffectiveSCEVType(Normalized->getType())) && + SE.getSCEV(PN) == Normalized) + if (BasicBlock *LatchBlock = L->getLoopLatch()) { + Instruction *IncV = + cast(PN->getIncomingValueForBlock(LatchBlock)); + + // Determine if this is a well-behaved chain of instructions leading + // back to the PHI. It probably will be, if we're scanning an inner + // loop already visited by LSR for example, but it wouldn't have + // to be. + do { + if (IncV->getNumOperands() == 0 || isa(IncV)) { + IncV = 0; + break; + } + // If any of the operands don't dominate the insert position, bail. + // Addrec operands are always loop-invariant, so this can only happen + // if there are instructions which haven't been hoisted. + for (User::op_iterator OI = IncV->op_begin()+1, + OE = IncV->op_end(); OI != OE; ++OI) + if (Instruction *OInst = dyn_cast(OI)) + if (!SE.DT->dominates(OInst, IVIncInsertPos)) { + IncV = 0; + break; + } + if (!IncV) + break; + // Advance to the next instruction. + IncV = dyn_cast(IncV->getOperand(0)); + if (!IncV) + break; + if (IncV->mayHaveSideEffects()) { + IncV = 0; + break; + } + } while (IncV != PN); + + if (IncV) { + // Ok, the add recurrence looks usable. + // Remember this PHI, even in post-inc mode. + InsertedValues.insert(PN); + // Remember the increment. + IncV = cast(PN->getIncomingValueForBlock(LatchBlock)); + rememberInstruction(IncV); + if (L == IVIncInsertLoop) + do { + if (SE.DT->dominates(IncV, IVIncInsertPos)) + break; + // Make sure the increment is where we want it. But don't move it + // down past a potential existing post-inc user. + IncV->moveBefore(IVIncInsertPos); + IVIncInsertPos = IncV; + IncV = cast(IncV->getOperand(0)); + } while (IncV != PN); + return PN; + } + } // Save the original insertion point so we can restore it when we're done. BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); @@ -658,7 +901,7 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, // negative, insert a sub instead of an add for the increment (unless it's a // constant, because subtracts of constants are canonicalized to adds). const SCEV *Step = Normalized->getStepRecurrence(SE); - bool isPointer = isa(ExpandTy); + bool isPointer = ExpandTy->isPointerTy(); bool isNegative = !isPointer && isNonConstantNegative(Step); if (isNegative) Step = SE.getNegativeSCEV(Step); @@ -713,7 +956,7 @@ SCEVExpander::getAddRecExprPHILiterally(const SCEVAddRecExpr *Normalized, // Restore the original insert point. if (SaveInsertBB) - Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); + restoreInsertPoint(SaveInsertBB, SaveInsertPt); // Remember this PHI, even in post-inc mode. InsertedValues.insert(PN); @@ -763,7 +1006,7 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { const Type *ExpandTy = PostLoopScale ? IntTy : STy; PHINode *PN = getAddRecExprPHILiterally(Normalized, L, ExpandTy, IntTy); - // Accomodate post-inc mode, if necessary. + // Accommodate post-inc mode, if necessary. Value *Result; if (L != PostIncLoop) Result = PN; @@ -776,6 +1019,7 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { // Re-apply any non-loop-dominating scale. if (PostLoopScale) { + Result = InsertNoopCastOfTo(Result, IntTy); Result = Builder.CreateMul(Result, expandCodeFor(PostLoopScale, IntTy)); rememberInstruction(Result); @@ -787,6 +1031,7 @@ Value *SCEVExpander::expandAddRecExprLiterally(const SCEVAddRecExpr *S) { const SCEV *const OffsetArray[1] = { PostLoopOffset }; Result = expandAddToGEP(OffsetArray, OffsetArray+1, PTy, IntTy, Result); } else { + Result = InsertNoopCastOfTo(Result, IntTy); Result = Builder.CreateAdd(Result, expandCodeFor(PostLoopOffset, IntTy)); rememberInstruction(Result); @@ -806,7 +1051,7 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { PHINode *CanonicalIV = 0; if (PHINode *PN = L->getCanonicalInductionVariable()) if (SE.isSCEVable(PN->getType()) && - isa(SE.getEffectiveSCEVType(PN->getType())) && + SE.getEffectiveSCEVType(PN->getType())->isIntegerTy() && SE.getTypeSizeInBits(PN->getType()) >= SE.getTypeSizeInBits(Ty)) CanonicalIV = PN; @@ -827,7 +1072,7 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) { while (isa(NewInsertPt)) ++NewInsertPt; V = expandCodeFor(SE.getTruncateExpr(SE.getUnknown(V), Ty), 0, NewInsertPt); - Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); + restoreInsertPoint(SaveInsertBB, SaveInsertPt); return V; } @@ -1022,13 +1267,24 @@ Value *SCEVExpander::expand(const SCEV *S) { L = L->getParentLoop()) if (S->isLoopInvariant(L)) { if (!L) break; - if (BasicBlock *Preheader = L->getLoopPreheader()) + if (BasicBlock *Preheader = L->getLoopPreheader()) { InsertPt = Preheader->getTerminator(); + BasicBlock::iterator IP = InsertPt; + // Back past any debug info instructions. Sometimes we inserted + // something earlier before debug info but after any real instructions. + // This should behave the same as if debug info was not present. + while (IP != Preheader->begin()) { + --IP; + if (!isa(IP)) + break; + InsertPt = IP; + } + } } else { // If the SCEV is computable at this level, insert it into the header // after the PHIs (and after any other instructions that we've inserted // there) so that it is guaranteed to dominate any user inside the loop. - if (L && S->hasComputableLoopEvolution(L)) + if (L && S->hasComputableLoopEvolution(L) && L != PostIncLoop) InsertPt = L->getHeader()->getFirstNonPHI(); while (isInsertedInstruction(InsertPt)) InsertPt = llvm::next(BasicBlock::iterator(InsertPt)); @@ -1053,10 +1309,32 @@ Value *SCEVExpander::expand(const SCEV *S) { if (!PostIncLoop) InsertedExpressions[std::make_pair(S, InsertPt)] = V; - Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); + restoreInsertPoint(SaveInsertBB, SaveInsertPt); return V; } +void SCEVExpander::rememberInstruction(Value *I) { + if (!PostIncLoop) + InsertedValues.insert(I); + + // If we just claimed an existing instruction and that instruction had + // been the insert point, adjust the insert point forward so that + // subsequently inserted code will be dominated. + if (Builder.GetInsertPoint() == I) { + BasicBlock::iterator It = cast(I); + do { ++It; } while (isInsertedInstruction(It)); + Builder.SetInsertPoint(Builder.GetInsertBlock(), It); + } +} + +void SCEVExpander::restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I) { + // If we acquired more instructions since the old insert point was saved, + // advance past them. + while (isInsertedInstruction(I)) ++I; + + Builder.SetInsertPoint(BB, I); +} + /// getOrInsertCanonicalInductionVariable - This method returns the /// canonical induction variable of the specified type for the specified /// loop (inserting one if there is none). A canonical induction variable @@ -1064,13 +1342,13 @@ Value *SCEVExpander::expand(const SCEV *S) { Value * SCEVExpander::getOrInsertCanonicalInductionVariable(const Loop *L, const Type *Ty) { - assert(Ty->isInteger() && "Can only insert integer induction variables!"); + assert(Ty->isIntegerTy() && "Can only insert integer induction variables!"); const SCEV *H = SE.getAddRecExpr(SE.getIntegerSCEV(0, Ty), SE.getIntegerSCEV(1, Ty), L); BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); Value *V = expandCodeFor(H, 0, L->getHeader()->begin()); if (SaveInsertBB) - Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); + restoreInsertPoint(SaveInsertBB, SaveInsertPt); return V; } diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index f9331e76d0..92cbb7c95c 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -23,6 +23,7 @@ #include "llvm/Target/TargetData.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/MathExtras.h" +#include "llvm/ADT/SmallPtrSet.h" #include using namespace llvm; @@ -49,11 +50,11 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, assert(V && "No Value?"); assert(Depth <= MaxDepth && "Limit Search Depth"); unsigned BitWidth = Mask.getBitWidth(); - assert((V->getType()->isIntOrIntVector() || isa(V->getType())) && - "Not integer or pointer type!"); + assert((V->getType()->isIntOrIntVectorTy() || V->getType()->isPointerTy()) + && "Not integer or pointer type!"); assert((!TD || TD->getTypeSizeInBits(V->getType()->getScalarType()) == BitWidth) && - (!V->getType()->isIntOrIntVector() || + (!V->getType()->isIntOrIntVectorTy() || V->getType()->getScalarSizeInBits() == BitWidth) && KnownZero.getBitWidth() == BitWidth && KnownOne.getBitWidth() == BitWidth && @@ -249,7 +250,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, unsigned SrcBitWidth; // Note that we handle pointer operands here because of inttoptr/ptrtoint // which fall through here. - if (isa(SrcTy)) + if (SrcTy->isPointerTy()) SrcBitWidth = TD->getTypeSizeInBits(SrcTy); else SrcBitWidth = SrcTy->getScalarSizeInBits(); @@ -269,10 +270,10 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask, } case Instruction::BitCast: { const Type *SrcTy = I->getOperand(0)->getType(); - if ((SrcTy->isInteger() || isa(SrcTy)) && + if ((SrcTy->isIntegerTy() || SrcTy->isPointerTy()) && // TODO: For now, not handling conversions like: // (bitcast i64 %x to <2 x i32>) - !isa(I->getType())) { + !I->getType()->isVectorTy()) { ComputeMaskedBits(I->getOperand(0), Mask, KnownZero, KnownOne, TD, Depth+1); return; @@ -649,7 +650,7 @@ bool llvm::MaskedValueIsZero(Value *V, const APInt &Mask, /// unsigned llvm::ComputeNumSignBits(Value *V, const TargetData *TD, unsigned Depth) { - assert((TD || V->getType()->isIntOrIntVector()) && + assert((TD || V->getType()->isIntOrIntVectorTy()) && "ComputeNumSignBits requires a TargetData object to operate " "on non-integer values!"); const Type *Ty = V->getType(); @@ -823,7 +824,7 @@ bool llvm::ComputeMultiple(Value *V, unsigned Base, Value *&Multiple, assert(V && "No Value?"); assert(Depth <= MaxDepth && "Limit Search Depth"); - assert(V->getType()->isInteger() && "Not integer or pointer type!"); + assert(V->getType()->isIntegerTy() && "Not integer or pointer type!"); const Type *T = V->getType(); @@ -980,7 +981,7 @@ bool llvm::CannotBeNegativeZero(const Value *V, unsigned Depth) { /// may not be represented in the result. static Value *GetLinearExpression(Value *V, APInt &Scale, APInt &Offset, const TargetData *TD, unsigned Depth) { - assert(isa(V->getType()) && "Not an integer value"); + assert(V->getType()->isIntegerTy() && "Not an integer value"); // Limit our recursion depth. if (Depth == 6) { @@ -1253,7 +1254,7 @@ Value *llvm::FindInsertedValue(Value *V, const unsigned *idx_begin, if (idx_begin == idx_end) return V; // We have indices, so V should have an indexable type - assert((isa(V->getType()) || isa(V->getType())) + assert((V->getType()->isStructTy() || V->getType()->isArrayTy()) && "Not looking at a struct or array?"); assert(ExtractValueInst::getIndexedType(V->getType(), idx_begin, idx_end) && "Invalid indices for type?"); @@ -1372,7 +1373,7 @@ bool llvm::GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset, // Make sure the index-ee is a pointer to array of i8. const PointerType *PT = cast(GEP->getOperand(0)->getType()); const ArrayType *AT = dyn_cast(PT->getElementType()); - if (AT == 0 || !AT->getElementType()->isInteger(8)) + if (AT == 0 || !AT->getElementType()->isIntegerTy(8)) return false; // Check to make sure that the first operand of the GEP is an integer and @@ -1411,7 +1412,7 @@ bool llvm::GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset, // Must be a Constant Array ConstantArray *Array = dyn_cast(GlobalInit); - if (Array == 0 || !Array->getType()->getElementType()->isInteger(8)) + if (Array == 0 || !Array->getType()->getElementType()->isIntegerTy(8)) return false; // Get the number of elements in the array @@ -1436,3 +1437,131 @@ bool llvm::GetConstantStringInfo(Value *V, std::string &Str, uint64_t Offset, // The array isn't null terminated, but maybe this is a memcpy, not a strcpy. return true; } + +// These next two are very similar to the above, but also look through PHI +// nodes. +// TODO: See if we can integrate these two together. + +/// GetStringLengthH - If we can compute the length of the string pointed to by +/// the specified pointer, return 'len+1'. If we can't, return 0. +static uint64_t GetStringLengthH(Value *V, SmallPtrSet &PHIs) { + // Look through noop bitcast instructions. + if (BitCastInst *BCI = dyn_cast(V)) + return GetStringLengthH(BCI->getOperand(0), PHIs); + + // If this is a PHI node, there are two cases: either we have already seen it + // or we haven't. + if (PHINode *PN = dyn_cast(V)) { + if (!PHIs.insert(PN)) + return ~0ULL; // already in the set. + + // If it was new, see if all the input strings are the same length. + uint64_t LenSoFar = ~0ULL; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { + uint64_t Len = GetStringLengthH(PN->getIncomingValue(i), PHIs); + if (Len == 0) return 0; // Unknown length -> unknown. + + if (Len == ~0ULL) continue; + + if (Len != LenSoFar && LenSoFar != ~0ULL) + return 0; // Disagree -> unknown. + LenSoFar = Len; + } + + // Success, all agree. + return LenSoFar; + } + + // strlen(select(c,x,y)) -> strlen(x) ^ strlen(y) + if (SelectInst *SI = dyn_cast(V)) { + uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs); + if (Len1 == 0) return 0; + uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs); + if (Len2 == 0) return 0; + if (Len1 == ~0ULL) return Len2; + if (Len2 == ~0ULL) return Len1; + if (Len1 != Len2) return 0; + return Len1; + } + + // If the value is not a GEP instruction nor a constant expression with a + // GEP instruction, then return unknown. + User *GEP = 0; + if (GetElementPtrInst *GEPI = dyn_cast(V)) { + GEP = GEPI; + } else if (ConstantExpr *CE = dyn_cast(V)) { + if (CE->getOpcode() != Instruction::GetElementPtr) + return 0; + GEP = CE; + } else { + return 0; + } + + // Make sure the GEP has exactly three arguments. + if (GEP->getNumOperands() != 3) + return 0; + + // Check to make sure that the first operand of the GEP is an integer and + // has value 0 so that we are sure we're indexing into the initializer. + if (ConstantInt *Idx = dyn_cast(GEP->getOperand(1))) { + if (!Idx->isZero()) + return 0; + } else + return 0; + + // If the second index isn't a ConstantInt, then this is a variable index + // into the array. If this occurs, we can't say anything meaningful about + // the string. + uint64_t StartIdx = 0; + if (ConstantInt *CI = dyn_cast(GEP->getOperand(2))) + StartIdx = CI->getZExtValue(); + else + return 0; + + // The GEP instruction, constant or instruction, must reference a global + // variable that is a constant and is initialized. The referenced constant + // initializer is the array that we'll use for optimization. + GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); + if (!GV || !GV->isConstant() || !GV->hasInitializer() || + GV->mayBeOverridden()) + return 0; + Constant *GlobalInit = GV->getInitializer(); + + // Handle the ConstantAggregateZero case, which is a degenerate case. The + // initializer is constant zero so the length of the string must be zero. + if (isa(GlobalInit)) + return 1; // Len = 0 offset by 1. + + // Must be a Constant Array + ConstantArray *Array = dyn_cast(GlobalInit); + if (!Array || !Array->getType()->getElementType()->isIntegerTy(8)) + return false; + + // Get the number of elements in the array + uint64_t NumElts = Array->getType()->getNumElements(); + + // Traverse the constant array from StartIdx (derived above) which is + // the place the GEP refers to in the array. + for (unsigned i = StartIdx; i != NumElts; ++i) { + Constant *Elt = Array->getOperand(i); + ConstantInt *CI = dyn_cast(Elt); + if (!CI) // This array isn't suitable, non-int initializer. + return 0; + if (CI->isZero()) + return i-StartIdx+1; // We found end of string, success! + } + + return 0; // The array isn't null terminated, conservatively return 'unknown'. +} + +/// GetStringLength - If we can compute the length of the string pointed to by +/// the specified pointer, return 'len+1'. If we can't, return 0. +uint64_t llvm::GetStringLength(Value *V) { + if (!V->getType()->isPointerTy()) return 0; + + SmallPtrSet PHIs; + uint64_t Len = GetStringLengthH(V, PHIs); + // If Len is ~0ULL, we had an infinite phi cycle: this is dead code, so return + // an empty string as a length. + return Len == ~0ULL ? 1 : Len; +} diff --git a/lib/AsmParser/Android.mk b/lib/AsmParser/Android.mk new file mode 100644 index 0000000000..548f719ade --- /dev/null +++ b/lib/AsmParser/Android.mk @@ -0,0 +1,28 @@ +LOCAL_PATH:= $(call my-dir) + +asm_parser_SRC_FILES := \ + LLLexer.cpp \ + LLParser.cpp \ + Parser.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(asm_parser_SRC_FILES) + +LOCAL_MODULE:= libLLVMAsmParser + +include $(LOCAL_PATH)/../../llvm-host-build.mk +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(asm_parser_SRC_FILES) + +LOCAL_MODULE:= libLLVMAsmParser + +include $(LOCAL_PATH)/../../llvm-device-build.mk +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index 8ad658d858..46f3cbcfa3 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -570,6 +570,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(type); KEYWORD(opaque); + KEYWORD(union); KEYWORD(eq); KEYWORD(ne); KEYWORD(slt); KEYWORD(sgt); KEYWORD(sle); KEYWORD(sge); KEYWORD(ult); KEYWORD(ugt); KEYWORD(ule); KEYWORD(uge); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 5dd65691a3..8083a07fdb 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -614,7 +614,7 @@ bool LLParser::ParseAlias(const std::string &Name, LocTy NameLoc, Aliasee = ID.ConstantVal; } - if (!isa(Aliasee->getType())) + if (!Aliasee->getType()->isPointerTy()) return Error(AliaseeLoc, "alias must have pointer type"); // Okay, create the alias but do not insert it into the module yet. @@ -685,7 +685,7 @@ bool LLParser::ParseGlobal(const std::string &Name, LocTy NameLoc, return true; } - if (isa(Ty) || Ty->isLabelTy()) + if (Ty->isFunctionTy() || Ty->isLabelTy()) return Error(TyLoc, "invalid type for global variable"); GlobalVariable *GV = 0; @@ -791,7 +791,7 @@ GlobalValue *LLParser::GetGlobalVal(const std::string &Name, const Type *Ty, GlobalValue *FwdVal; if (const FunctionType *FT = dyn_cast(PTy->getElementType())) { // Function types can return opaque but functions can't. - if (isa(FT->getReturnType())) { + if (FT->getReturnType()->isOpaqueTy()) { Error(Loc, "function may not return opaque type"); return 0; } @@ -836,7 +836,7 @@ GlobalValue *LLParser::GetGlobalVal(unsigned ID, const Type *Ty, LocTy Loc) { GlobalValue *FwdVal; if (const FunctionType *FT = dyn_cast(PTy->getElementType())) { // Function types can return opaque but functions can't. - if (isa(FT->getReturnType())) { + if (FT->getReturnType()->isOpaqueTy()) { Error(Loc, "function may not return opaque type"); return 0; } @@ -956,6 +956,14 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break; case lltok::kw_naked: Attrs |= Attribute::Naked; break; + case lltok::kw_alignstack: { + unsigned Alignment; + if (ParseOptionalStackAlignment(Alignment)) + return true; + Attrs |= Attribute::constructStackAlignmentFromInt(Alignment); + continue; + } + case lltok::kw_align: { unsigned Alignment; if (ParseOptionalAlignment(Alignment)) @@ -963,6 +971,7 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { Attrs |= Attribute::constructAlignmentFromInt(Alignment); continue; } + } Lex.Lex(); } @@ -1131,6 +1140,25 @@ bool LLParser::ParseOptionalCommaAlign(unsigned &Alignment, return false; } +/// ParseOptionalStackAlignment +/// ::= /* empty */ +/// ::= 'alignstack' '(' 4 ')' +bool LLParser::ParseOptionalStackAlignment(unsigned &Alignment) { + Alignment = 0; + if (!EatIfPresent(lltok::kw_alignstack)) + return false; + LocTy ParenLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::lparen)) + return Error(ParenLoc, "expected '('"); + LocTy AlignLoc = Lex.getLoc(); + if (ParseUInt32(Alignment)) return true; + ParenLoc = Lex.getLoc(); + if (!EatIfPresent(lltok::rparen)) + return Error(ParenLoc, "expected ')'"); + if (!isPowerOf2_32(Alignment)) + return Error(AlignLoc, "stack alignment is not a power of two"); + return false; +} /// ParseIndexList - This parses the index list for an insert/extractvalue /// instruction. This sets AteExtraComma in the case where we eat an extra @@ -1267,6 +1295,11 @@ bool LLParser::ParseTypeRec(PATypeHolder &Result) { if (ParseStructType(Result, false)) return true; break; + case lltok::kw_union: + // TypeRec ::= 'union' '{' ... '}' + if (ParseUnionType(Result)) + return true; + break; case lltok::lsquare: // TypeRec ::= '[' ... ']' Lex.Lex(); // eat the lsquare. @@ -1482,7 +1515,7 @@ bool LLParser::ParseArgumentList(std::vector &ArgList, Name = ""; } - if (!ArgTy->isFirstClassType() && !isa(ArgTy)) + if (!ArgTy->isFirstClassType() && !ArgTy->isOpaqueTy()) return Error(TypeLoc, "invalid type for function argument"); ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attrs, Name)); @@ -1576,6 +1609,38 @@ bool LLParser::ParseStructType(PATypeHolder &Result, bool Packed) { return false; } +/// ParseUnionType +/// TypeRec +/// ::= 'union' '{' TypeRec (',' TypeRec)* '}' +bool LLParser::ParseUnionType(PATypeHolder &Result) { + assert(Lex.getKind() == lltok::kw_union); + Lex.Lex(); // Consume the 'union' + + if (ParseToken(lltok::lbrace, "'{' expected after 'union'")) return true; + + SmallVector ParamsList; + do { + LocTy EltTyLoc = Lex.getLoc(); + if (ParseTypeRec(Result)) return true; + ParamsList.push_back(Result); + + if (Result->isVoidTy()) + return Error(EltTyLoc, "union element can not have void type"); + if (!UnionType::isValidElementType(Result)) + return Error(EltTyLoc, "invalid element type for union"); + + } while (EatIfPresent(lltok::comma)) ; + + if (ParseToken(lltok::rbrace, "expected '}' at end of union")) + return true; + + SmallVector ParamsListTy; + for (unsigned i = 0, e = ParamsList.size(); i != e; ++i) + ParamsListTy.push_back(ParamsList[i].get()); + Result = HandleUpRefs(UnionType::get(&ParamsListTy[0], ParamsListTy.size())); + return false; +} + /// ParseArrayVectorType - Parse an array or vector type, assuming the first /// token has already been consumed. /// TypeRec @@ -1720,7 +1785,7 @@ Value *LLParser::PerFunctionState::GetVal(const std::string &Name, } // Don't make placeholders with invalid type. - if (!Ty->isFirstClassType() && !isa(Ty) && !Ty->isLabelTy()) { + if (!Ty->isFirstClassType() && !Ty->isOpaqueTy() && !Ty->isLabelTy()) { P.Error(Loc, "invalid use of a non-first-class type"); return 0; } @@ -1761,7 +1826,7 @@ Value *LLParser::PerFunctionState::GetVal(unsigned ID, const Type *Ty, return 0; } - if (!Ty->isFirstClassType() && !isa(Ty) && !Ty->isLabelTy()) { + if (!Ty->isFirstClassType() && !Ty->isOpaqueTy() && !Ty->isLabelTy()) { P.Error(Loc, "invalid use of a non-first-class type"); return 0; } @@ -1992,8 +2057,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { if (Elts.empty()) return Error(ID.Loc, "constant vector must not be empty"); - if (!Elts[0]->getType()->isInteger() && - !Elts[0]->getType()->isFloatingPoint()) + if (!Elts[0]->getType()->isIntegerTy() && + !Elts[0]->getType()->isFloatingPointTy()) return Error(FirstEltLoc, "vector elements must have integer or floating point type"); @@ -2135,8 +2200,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { ParseToken(lltok::rparen, "expected ')' in extractvalue constantexpr")) return true; - if (!isa(Val->getType()) && !isa(Val->getType())) - return Error(ID.Loc, "extractvalue operand must be array or struct"); + if (!Val->getType()->isAggregateType()) + return Error(ID.Loc, "extractvalue operand must be aggregate type"); if (!ExtractValueInst::getIndexedType(Val->getType(), Indices.begin(), Indices.end())) return Error(ID.Loc, "invalid indices for extractvalue"); @@ -2156,8 +2221,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { ParseIndexList(Indices) || ParseToken(lltok::rparen, "expected ')' in insertvalue constantexpr")) return true; - if (!isa(Val0->getType()) && !isa(Val0->getType())) - return Error(ID.Loc, "extractvalue operand must be array or struct"); + if (!Val0->getType()->isAggregateType()) + return Error(ID.Loc, "insertvalue operand must be aggregate type"); if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices.begin(), Indices.end())) return Error(ID.Loc, "invalid indices for insertvalue"); @@ -2185,13 +2250,13 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { CmpInst::Predicate Pred = (CmpInst::Predicate)PredVal; if (Opc == Instruction::FCmp) { - if (!Val0->getType()->isFPOrFPVector()) + if (!Val0->getType()->isFPOrFPVectorTy()) return Error(ID.Loc, "fcmp requires floating point operands"); ID.ConstantVal = ConstantExpr::getFCmp(Pred, Val0, Val1); } else { assert(Opc == Instruction::ICmp && "Unexpected opcode for CmpInst!"); - if (!Val0->getType()->isIntOrIntVector() && - !isa(Val0->getType())) + if (!Val0->getType()->isIntOrIntVectorTy() && + !Val0->getType()->isPointerTy()) return Error(ID.Loc, "icmp requires pointer or integer operands"); ID.ConstantVal = ConstantExpr::getICmp(Pred, Val0, Val1); } @@ -2241,7 +2306,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { return true; if (Val0->getType() != Val1->getType()) return Error(ID.Loc, "operands of constexpr must have same type"); - if (!Val0->getType()->isIntOrIntVector()) { + if (!Val0->getType()->isIntOrIntVectorTy()) { if (NUW) return Error(ModifierLoc, "nuw only applies to integer operations"); if (NSW) @@ -2249,8 +2314,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { } // API compatibility: Accept either integer or floating-point types with // add, sub, and mul. - if (!Val0->getType()->isIntOrIntVector() && - !Val0->getType()->isFPOrFPVector()) + if (!Val0->getType()->isIntOrIntVectorTy() && + !Val0->getType()->isFPOrFPVectorTy()) return Error(ID.Loc,"constexpr requires integer, fp, or vector operands"); unsigned Flags = 0; if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap; @@ -2280,7 +2345,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { return true; if (Val0->getType() != Val1->getType()) return Error(ID.Loc, "operands of constexpr must have same type"); - if (!Val0->getType()->isIntOrIntVector()) + if (!Val0->getType()->isIntOrIntVectorTy()) return Error(ID.Loc, "constexpr requires integer or integer vector operands"); ID.ConstantVal = ConstantExpr::get(Opc, Val0, Val1); @@ -2305,7 +2370,7 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { return true; if (Opc == Instruction::GetElementPtr) { - if (Elts.size() == 0 || !isa(Elts[0]->getType())) + if (Elts.size() == 0 || !Elts[0]->getType()->isPointerTy()) return Error(ID.Loc, "getelementptr requires pointer operand"); if (!GetElementPtrInst::getIndexedType(Elts[0]->getType(), @@ -2405,7 +2470,7 @@ bool LLParser::ParseGlobalValueVector(SmallVectorImpl &Elts) { bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, PerFunctionState *PFS) { - if (isa(Ty)) + if (Ty->isFunctionTy()) return Error(ID.Loc, "functions are not values, refer to them as pointers"); switch (ID.Kind) { @@ -2444,13 +2509,13 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, V = GetGlobalVal(ID.UIntVal, Ty, ID.Loc); return V == 0; case ValID::t_APSInt: - if (!isa(Ty)) + if (!Ty->isIntegerTy()) return Error(ID.Loc, "integer constant must have integer type"); ID.APSIntVal.extOrTrunc(Ty->getPrimitiveSizeInBits()); V = ConstantInt::get(Context, ID.APSIntVal); return false; case ValID::t_APFloat: - if (!Ty->isFloatingPoint() || + if (!Ty->isFloatingPointTy() || !ConstantFP::isValueValidForType(Ty, ID.APFloatVal)) return Error(ID.Loc, "floating point constant invalid for type"); @@ -2470,19 +2535,19 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, return false; case ValID::t_Null: - if (!isa(Ty)) + if (!Ty->isPointerTy()) return Error(ID.Loc, "null must be a pointer type"); V = ConstantPointerNull::get(cast(Ty)); return false; case ValID::t_Undef: // FIXME: LabelTy should not be a first-class type. if ((!Ty->isFirstClassType() || Ty->isLabelTy()) && - !isa(Ty)) + !Ty->isOpaqueTy()) return Error(ID.Loc, "invalid type for undef constant"); V = UndefValue::get(Ty); return false; case ValID::t_EmptyArray: - if (!isa(Ty) || cast(Ty)->getNumElements() != 0) + if (!Ty->isArrayTy() || cast(Ty)->getNumElements() != 0) return Error(ID.Loc, "invalid empty array initializer"); V = UndefValue::get(Ty); return false; @@ -2493,8 +2558,17 @@ bool LLParser::ConvertValIDToValue(const Type *Ty, ValID &ID, Value *&V, V = Constant::getNullValue(Ty); return false; case ValID::t_Constant: - if (ID.ConstantVal->getType() != Ty) + if (ID.ConstantVal->getType() != Ty) { + // Allow a constant struct with a single member to be converted + // to a union, if the union has a member which is the same type + // as the struct member. + if (const UnionType* utype = dyn_cast(Ty)) { + return ParseUnionValue(utype, ID, V); + } + return Error(ID.Loc, "constant expression type mismatch"); + } + V = ID.ConstantVal; return false; } @@ -2524,6 +2598,22 @@ bool LLParser::ParseTypeAndBasicBlock(BasicBlock *&BB, LocTy &Loc, return false; } +bool LLParser::ParseUnionValue(const UnionType* utype, ValID &ID, Value *&V) { + if (const StructType* stype = dyn_cast(ID.ConstantVal->getType())) { + if (stype->getNumContainedTypes() != 1) + return Error(ID.Loc, "constant expression type mismatch"); + int index = utype->getElementTypeIndex(stype->getContainedType(0)); + if (index < 0) + return Error(ID.Loc, "initializer type is not a member of the union"); + + V = ConstantUnion::get( + utype, cast(ID.ConstantVal->getOperand(0))); + return false; + } + + return Error(ID.Loc, "constant expression type mismatch"); +} + /// FunctionHeader /// ::= OptionalLinkage OptionalVisibility OptionalCallingConv OptRetAttrs @@ -2572,7 +2662,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { } if (!FunctionType::isValidReturnType(RetType) || - isa(RetType)) + RetType->isOpaqueTy()) return Error(RetTypeLoc, "invalid function return type"); LocTy NameLoc = Lex.getLoc(); @@ -2873,7 +2963,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, // API compatibility: Accept either integer or floating-point types. bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 0); if (!Result) { - if (!Inst->getType()->isIntOrIntVector()) { + if (!Inst->getType()->isIntOrIntVectorTy()) { if (NUW) return Error(ModifierLoc, "nuw only applies to integer operations"); if (NSW) @@ -3096,7 +3186,7 @@ bool LLParser::ParseSwitch(Instruction *&Inst, PerFunctionState &PFS) { ParseToken(lltok::lsquare, "expected '[' with switch table")) return true; - if (!isa(Cond->getType())) + if (!Cond->getType()->isIntegerTy()) return Error(CondLoc, "switch condition must have integer type"); // Parse the jump table pairs. @@ -3139,7 +3229,7 @@ bool LLParser::ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS) { ParseToken(lltok::lsquare, "expected '[' with indirectbr")) return true; - if (!isa(Address->getType())) + if (!Address->getType()->isPointerTy()) return Error(AddrLoc, "indirectbr address must have pointer type"); // Parse the destination list. @@ -3292,11 +3382,11 @@ bool LLParser::ParseArithmetic(Instruction *&Inst, PerFunctionState &PFS, switch (OperandType) { default: llvm_unreachable("Unknown operand type!"); case 0: // int or FP. - Valid = LHS->getType()->isIntOrIntVector() || - LHS->getType()->isFPOrFPVector(); + Valid = LHS->getType()->isIntOrIntVectorTy() || + LHS->getType()->isFPOrFPVectorTy(); break; - case 1: Valid = LHS->getType()->isIntOrIntVector(); break; - case 2: Valid = LHS->getType()->isFPOrFPVector(); break; + case 1: Valid = LHS->getType()->isIntOrIntVectorTy(); break; + case 2: Valid = LHS->getType()->isFPOrFPVectorTy(); break; } if (!Valid) @@ -3316,7 +3406,7 @@ bool LLParser::ParseLogical(Instruction *&Inst, PerFunctionState &PFS, ParseValue(LHS->getType(), RHS, PFS)) return true; - if (!LHS->getType()->isIntOrIntVector()) + if (!LHS->getType()->isIntOrIntVectorTy()) return Error(Loc,"instruction requires integer or integer vector operands"); Inst = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); @@ -3340,13 +3430,13 @@ bool LLParser::ParseCompare(Instruction *&Inst, PerFunctionState &PFS, return true; if (Opc == Instruction::FCmp) { - if (!LHS->getType()->isFPOrFPVector()) + if (!LHS->getType()->isFPOrFPVectorTy()) return Error(Loc, "fcmp requires floating point operands"); Inst = new FCmpInst(CmpInst::Predicate(Pred), LHS, RHS); } else { assert(Opc == Instruction::ICmp && "Unknown opcode for CmpInst!"); - if (!LHS->getType()->isIntOrIntVector() && - !isa(LHS->getType())) + if (!LHS->getType()->isIntOrIntVectorTy() && + !LHS->getType()->isPointerTy()) return Error(Loc, "icmp requires integer operands"); Inst = new ICmpInst(CmpInst::Predicate(Pred), LHS, RHS); } @@ -3643,7 +3733,7 @@ int LLParser::ParseAlloc(Instruction *&Inst, PerFunctionState &PFS, } } - if (Size && !Size->getType()->isInteger(32)) + if (Size && !Size->getType()->isIntegerTy(32)) return Error(SizeLoc, "element count must be i32"); if (isAlloca) { @@ -3671,7 +3761,7 @@ bool LLParser::ParseFree(Instruction *&Inst, PerFunctionState &PFS, BasicBlock* BB) { Value *Val; LocTy Loc; if (ParseTypeAndValue(Val, Loc, PFS)) return true; - if (!isa(Val->getType())) + if (!Val->getType()->isPointerTy()) return Error(Loc, "operand to free must be a pointer"); Inst = CallInst::CreateFree(Val, BB); return false; @@ -3688,7 +3778,7 @@ int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS, ParseOptionalCommaAlign(Alignment, AteExtraComma)) return true; - if (!isa(Val->getType()) || + if (!Val->getType()->isPointerTy() || !cast(Val->getType())->getElementType()->isFirstClassType()) return Error(Loc, "load operand must be a pointer to a first class type"); @@ -3709,7 +3799,7 @@ int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS, ParseOptionalCommaAlign(Alignment, AteExtraComma)) return true; - if (!isa(Ptr->getType())) + if (!Ptr->getType()->isPointerTy()) return Error(PtrLoc, "store operand must be a pointer"); if (!Val->getType()->isFirstClassType()) return Error(Loc, "store operand must be a first class value"); @@ -3731,7 +3821,7 @@ bool LLParser::ParseGetResult(Instruction *&Inst, PerFunctionState &PFS) { ParseUInt32(Element, EltLoc)) return true; - if (!isa(Val->getType()) && !isa(Val->getType())) + if (!Val->getType()->isStructTy() && !Val->getType()->isArrayTy()) return Error(ValLoc, "getresult inst requires an aggregate operand"); if (!ExtractValueInst::getIndexedType(Val->getType(), Element)) return Error(EltLoc, "invalid getresult index for value"); @@ -3748,7 +3838,7 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { if (ParseTypeAndValue(Ptr, Loc, PFS)) return true; - if (!isa(Ptr->getType())) + if (!Ptr->getType()->isPointerTy()) return Error(Loc, "base of getelementptr must be a pointer"); SmallVector Indices; @@ -3759,7 +3849,7 @@ int LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { break; } if (ParseTypeAndValue(Val, EltLoc, PFS)) return true; - if (!isa(Val->getType())) + if (!Val->getType()->isIntegerTy()) return Error(EltLoc, "getelementptr index must be an integer"); Indices.push_back(Val); } @@ -3783,8 +3873,8 @@ int LLParser::ParseExtractValue(Instruction *&Inst, PerFunctionState &PFS) { ParseIndexList(Indices, AteExtraComma)) return true; - if (!isa(Val->getType()) && !isa(Val->getType())) - return Error(Loc, "extractvalue operand must be array or struct"); + if (!Val->getType()->isAggregateType()) + return Error(Loc, "extractvalue operand must be aggregate type"); if (!ExtractValueInst::getIndexedType(Val->getType(), Indices.begin(), Indices.end())) @@ -3805,8 +3895,8 @@ int LLParser::ParseInsertValue(Instruction *&Inst, PerFunctionState &PFS) { ParseIndexList(Indices, AteExtraComma)) return true; - if (!isa(Val0->getType()) && !isa(Val0->getType())) - return Error(Loc0, "extractvalue operand must be array or struct"); + if (!Val0->getType()->isAggregateType()) + return Error(Loc0, "insertvalue operand must be aggregate type"); if (!ExtractValueInst::getIndexedType(Val0->getType(), Indices.begin(), Indices.end())) diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h index 85c07ffa8f..9abe404273 100644 --- a/lib/AsmParser/LLParser.h +++ b/lib/AsmParser/LLParser.h @@ -31,6 +31,7 @@ namespace llvm { class GlobalValue; class MDString; class MDNode; + class UnionType; /// ValID - Represents a reference of a definition of some sort with no type. /// There are several cases where we have to parse the value but where the @@ -169,6 +170,7 @@ namespace llvm { bool ParseOptionalVisibility(unsigned &Visibility); bool ParseOptionalCallingConv(CallingConv::ID &CC); bool ParseOptionalAlignment(unsigned &Alignment); + bool ParseOptionalStackAlignment(unsigned &Alignment); bool ParseInstructionMetadata(SmallVectorImpl > &); bool ParseOptionalCommaAlign(unsigned &Alignment, bool &AteExtraComma); @@ -211,6 +213,7 @@ namespace llvm { } bool ParseTypeRec(PATypeHolder &H); bool ParseStructType(PATypeHolder &H, bool Packed); + bool ParseUnionType(PATypeHolder &H); bool ParseArrayVectorType(PATypeHolder &H, bool isVector); bool ParseFunctionType(PATypeHolder &Result); PATypeHolder HandleUpRefs(const Type *Ty); @@ -279,6 +282,8 @@ namespace llvm { return ParseTypeAndBasicBlock(BB, Loc, PFS); } + bool ParseUnionValue(const UnionType* utype, ValID &ID, Value *&V); + struct ParamInfo { LocTy Loc; Value *V; diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 7f1807c7d0..3ac9169006 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -97,6 +97,7 @@ namespace lltok { kw_type, kw_opaque, + kw_union, kw_eq, kw_ne, kw_slt, kw_sgt, kw_sle, kw_sge, kw_ult, kw_ugt, kw_ule, kw_uge, kw_oeq, kw_one, kw_olt, kw_ogt, kw_ole, kw_oge, kw_ord, kw_uno, diff --git a/lib/Bitcode/Reader/Android.mk b/lib/Bitcode/Reader/Android.mk new file mode 100644 index 0000000000..165b0d0cde --- /dev/null +++ b/lib/Bitcode/Reader/Android.mk @@ -0,0 +1,29 @@ +LOCAL_PATH:= $(call my-dir) + +bitcode_reader_SRC_FILES := \ + BitReader.cpp \ + BitcodeReader.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(bitcode_reader_SRC_FILES) + +LOCAL_MODULE:= libLLVMBitReader + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(bitcode_reader_SRC_FILES) + +LOCAL_MODULE:= libLLVMBitReader + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/Bitcode/Reader/BitReader.cpp b/lib/Bitcode/Reader/BitReader.cpp index 1facbc37ff..15844c0041 100644 --- a/lib/Bitcode/Reader/BitReader.cpp +++ b/lib/Bitcode/Reader/BitReader.cpp @@ -21,17 +21,8 @@ using namespace llvm; Optionally returns a human-readable error message via OutMessage. */ LLVMBool LLVMParseBitcode(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutModule, char **OutMessage) { - std::string Message; - - *OutModule = wrap(ParseBitcodeFile(unwrap(MemBuf), getGlobalContext(), - &Message)); - if (!*OutModule) { - if (OutMessage) - *OutMessage = strdup(Message.c_str()); - return 1; - } - - return 0; + return LLVMParseBitcodeInContext(wrap(&getGlobalContext()), MemBuf, OutModule, + OutMessage); } LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, @@ -54,36 +45,44 @@ LLVMBool LLVMParseBitcodeInContext(LLVMContextRef ContextRef, /* Reads a module from the specified path, returning via the OutModule parameter a module provider which performs lazy deserialization. Returns 0 on success. Optionally returns a human-readable error message via OutMessage. */ -LLVMBool LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf, - LLVMModuleProviderRef *OutMP, - char **OutMessage) { +LLVMBool LLVMGetBitcodeModuleInContext(LLVMContextRef ContextRef, + LLVMMemoryBufferRef MemBuf, + LLVMModuleRef *OutM, + char **OutMessage) { std::string Message; - - *OutMP = reinterpret_cast( - getLazyBitcodeModule(unwrap(MemBuf), getGlobalContext(), &Message)); - - if (!*OutMP) { + + *OutM = wrap(getLazyBitcodeModule(unwrap(MemBuf), *unwrap(ContextRef), + &Message)); + if (!*OutM) { if (OutMessage) *OutMessage = strdup(Message.c_str()); - return 1; + return 1; } - + return 0; + } +LLVMBool LLVMGetBitcodeModule(LLVMMemoryBufferRef MemBuf, LLVMModuleRef *OutM, + char **OutMessage) { + return LLVMGetBitcodeModuleInContext(LLVMGetGlobalContext(), MemBuf, OutM, + OutMessage); +} + +/* Deprecated: Use LLVMGetBitcodeModuleInContext instead. */ LLVMBool LLVMGetBitcodeModuleProviderInContext(LLVMContextRef ContextRef, LLVMMemoryBufferRef MemBuf, LLVMModuleProviderRef *OutMP, char **OutMessage) { - std::string Message; - - *OutMP = reinterpret_cast( - getLazyBitcodeModule(unwrap(MemBuf), *unwrap(ContextRef), &Message)); - if (!*OutMP) { - if (OutMessage) - *OutMessage = strdup(Message.c_str()); - return 1; - } - - return 0; + return LLVMGetBitcodeModuleInContext(ContextRef, MemBuf, + reinterpret_cast(OutMP), + OutMessage); +} + +/* Deprecated: Use LLVMGetBitcodeModule instead. */ +LLVMBool LLVMGetBitcodeModuleProvider(LLVMMemoryBufferRef MemBuf, + LLVMModuleProviderRef *OutMP, + char **OutMessage) { + return LLVMGetBitcodeModuleProviderInContext(LLVMGetGlobalContext(), MemBuf, + OutMP, OutMessage); } diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index 4dfc6cef5a..a32883720b 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -108,17 +108,17 @@ static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) { switch (Val) { default: return -1; case bitc::BINOP_ADD: - return Ty->isFPOrFPVector() ? Instruction::FAdd : Instruction::Add; + return Ty->isFPOrFPVectorTy() ? Instruction::FAdd : Instruction::Add; case bitc::BINOP_SUB: - return Ty->isFPOrFPVector() ? Instruction::FSub : Instruction::Sub; + return Ty->isFPOrFPVectorTy() ? Instruction::FSub : Instruction::Sub; case bitc::BINOP_MUL: - return Ty->isFPOrFPVector() ? Instruction::FMul : Instruction::Mul; + return Ty->isFPOrFPVectorTy() ? Instruction::FMul : Instruction::Mul; case bitc::BINOP_UDIV: return Instruction::UDiv; case bitc::BINOP_SDIV: - return Ty->isFPOrFPVector() ? Instruction::FDiv : Instruction::SDiv; + return Ty->isFPOrFPVectorTy() ? Instruction::FDiv : Instruction::SDiv; case bitc::BINOP_UREM: return Instruction::URem; case bitc::BINOP_SREM: - return Ty->isFPOrFPVector() ? Instruction::FRem : Instruction::SRem; + return Ty->isFPOrFPVectorTy() ? Instruction::FRem : Instruction::SRem; case bitc::BINOP_SHL: return Instruction::Shl; case bitc::BINOP_LSHR: return Instruction::LShr; case bitc::BINOP_ASHR: return Instruction::AShr; @@ -585,6 +585,13 @@ bool BitcodeReader::ParseTypeTable() { ResultTy = StructType::get(Context, EltTys, Record[0]); break; } + case bitc::TYPE_CODE_UNION: { // UNION: [eltty x N] + SmallVector EltTys; + for (unsigned i = 0, e = Record.size(); i != e; ++i) + EltTys.push_back(getTypeByID(Record[i], true)); + ResultTy = UnionType::get(&EltTys[0], EltTys.size()); + break; + } case bitc::TYPE_CODE_ARRAY: // ARRAY: [numelts, eltty] if (Record.size() < 2) return Error("Invalid ARRAY type record"); @@ -956,12 +963,12 @@ bool BitcodeReader::ParseConstants() { V = Constant::getNullValue(CurTy); break; case bitc::CST_CODE_INTEGER: // INTEGER: [intval] - if (!isa(CurTy) || Record.empty()) + if (!CurTy->isIntegerTy() || Record.empty()) return Error("Invalid CST_INTEGER record"); V = ConstantInt::get(CurTy, DecodeSignRotatedValue(Record[0])); break; case bitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval] - if (!isa(CurTy) || Record.empty()) + if (!CurTy->isIntegerTy() || Record.empty()) return Error("Invalid WIDE_INTEGER record"); unsigned NumWords = Record.size(); @@ -1168,7 +1175,7 @@ bool BitcodeReader::ParseConstants() { Constant *Op0 = ValueList.getConstantFwdRef(Record[1], OpTy); Constant *Op1 = ValueList.getConstantFwdRef(Record[2], OpTy); - if (OpTy->isFPOrFPVector()) + if (OpTy->isFPOrFPVectorTy()) V = ConstantExpr::getFCmp(Record[3], Op0, Op1); else V = ConstantExpr::getICmp(Record[3], Op0, Op1); @@ -1400,7 +1407,7 @@ bool BitcodeReader::ParseModule() { if (Record.size() < 6) return Error("Invalid MODULE_CODE_GLOBALVAR record"); const Type *Ty = getTypeByID(Record[0]); - if (!isa(Ty)) + if (!Ty->isPointerTy()) return Error("Global not a pointer type!"); unsigned AddressSpace = cast(Ty)->getAddressSpace(); Ty = cast(Ty)->getElementType(); @@ -1443,7 +1450,7 @@ bool BitcodeReader::ParseModule() { if (Record.size() < 8) return Error("Invalid MODULE_CODE_FUNCTION record"); const Type *Ty = getTypeByID(Record[0]); - if (!isa(Ty)) + if (!Ty->isPointerTy()) return Error("Function not a pointer type!"); const FunctionType *FTy = dyn_cast(cast(Ty)->getElementType()); @@ -1484,7 +1491,7 @@ bool BitcodeReader::ParseModule() { if (Record.size() < 3) return Error("Invalid MODULE_ALIAS record"); const Type *Ty = getTypeByID(Record[0]); - if (!isa(Ty)) + if (!Ty->isPointerTy()) return Error("Function not a pointer type!"); GlobalAlias *NewGA = new GlobalAlias(Ty, GetDecodedLinkage(Record[2]), @@ -1615,6 +1622,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { if (Stream.EnterSubBlock(bitc::FUNCTION_BLOCK_ID)) return Error("Malformed block record"); + InstructionList.clear(); unsigned ModuleValueListSize = ValueList.size(); // Add all the function arguments to the value table. @@ -1885,7 +1893,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { OpNum+1 != Record.size()) return Error("Invalid CMP record"); - if (LHS->getType()->isFPOrFPVector()) + if (LHS->getType()->isFPOrFPVectorTy()) I = new FCmpInst((FCmpInst::Predicate)Record[OpNum], LHS, RHS); else I = new ICmpInst((ICmpInst::Predicate)Record[OpNum], LHS, RHS); @@ -1925,7 +1933,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { const Type *ReturnType = F->getReturnType(); if (Vs.size() > 1 || - (isa(ReturnType) && + (ReturnType->isStructTy() && (Vs.empty() || Vs[0]->getType() != ReturnType))) { Value *RV = UndefValue::get(ReturnType); for (unsigned i = 0, e = Vs.size(); i != e; ++i) { diff --git a/lib/Bitcode/Writer/BitWriter.cpp b/lib/Bitcode/Writer/BitWriter.cpp index 7ed651b77e..4288422463 100644 --- a/lib/Bitcode/Writer/BitWriter.cpp +++ b/lib/Bitcode/Writer/BitWriter.cpp @@ -27,20 +27,14 @@ int LLVMWriteBitcodeToFile(LLVMModuleRef M, const char *Path) { return 0; } -#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR >= 4) -#include - -int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int FileHandle) { - raw_fd_ostream OS(FileHandle, false); +int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose, + int Unbuffered) { + raw_fd_ostream OS(FD, ShouldClose, Unbuffered); WriteBitcodeToFile(unwrap(M), OS); return 0; } -#else - int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int FileHandle) { - return -1; // Not supported. + return LLVMWriteBitcodeToFD(M, FileHandle, true, false); } - -#endif diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index a5bb526416..82e73b5cff 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -181,6 +181,14 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Log2_32_Ceil(VE.getTypes().size()+1))); unsigned StructAbbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for TYPE_CODE_UNION. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_UNION)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, + Log2_32_Ceil(VE.getTypes().size()+1))); + unsigned UnionAbbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for TYPE_CODE_ARRAY. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY)); @@ -250,6 +258,17 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { AbbrevToUse = StructAbbrev; break; } + case Type::UnionTyID: { + const UnionType *UT = cast(T); + // UNION: [eltty x N] + Code = bitc::TYPE_CODE_UNION; + // Output all of the element types. + for (UnionType::element_iterator I = UT->element_begin(), + E = UT->element_end(); I != E; ++I) + TypeVals.push_back(VE.getTypeID(*I)); + AbbrevToUse = UnionAbbrev; + break; + } case Type::ArrayTyID: { const ArrayType *AT = cast(T); // ARRAY: [numelts, eltty] @@ -789,7 +808,7 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, else if (isCStr7) AbbrevToUse = CString7Abbrev; } else if (isa(C) || isa(V) || - isa(V)) { + isa(C) || isa(V)) { Code = bitc::CST_CODE_AGGREGATE; for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) Record.push_back(VE.getValueID(C->getOperand(i))); @@ -1510,16 +1529,50 @@ enum { DarwinBCHeaderSize = 5*4 }; +/// isARMTriplet - Return true if the triplet looks like: +/// arm-*, thumb-*, armv[0-9]-*, thumbv[0-9]-*, armv5te-*, or armv6t2-*. +static bool isARMTriplet(const std::string &TT) { + size_t Pos = 0; + size_t Size = TT.size(); + if (Size >= 6 && + TT[0] == 't' && TT[1] == 'h' && TT[2] == 'u' && + TT[3] == 'm' && TT[4] == 'b') + Pos = 5; + else if (Size >= 4 && TT[0] == 'a' && TT[1] == 'r' && TT[2] == 'm') + Pos = 3; + else + return false; + + if (TT[Pos] == '-') + return true; + else if (TT[Pos] == 'v') { + if (Size >= Pos+4 && + TT[Pos+1] == '6' && TT[Pos+2] == 't' && TT[Pos+3] == '2') + return true; + else if (Size >= Pos+4 && + TT[Pos+1] == '5' && TT[Pos+2] == 't' && TT[Pos+3] == 'e') + return true; + } else + return false; + while (++Pos < Size && TT[Pos] != '-') { + if (!isdigit(TT[Pos])) + return false; + } + return true; +} + static void EmitDarwinBCHeader(BitstreamWriter &Stream, const std::string &TT) { unsigned CPUType = ~0U; - // Match x86_64-*, i[3-9]86-*, powerpc-*, powerpc64-*. The CPUType is a - // magic number from /usr/include/mach/machine.h. It is ok to reproduce the + // Match x86_64-*, i[3-9]86-*, powerpc-*, powerpc64-*, arm-*, thumb-*, + // armv[0-9]-*, thumbv[0-9]-*, armv5te-*, or armv6t2-*. The CPUType is a magic + // number from /usr/include/mach/machine.h. It is ok to reproduce the // specific constants here because they are implicitly part of the Darwin ABI. enum { DARWIN_CPU_ARCH_ABI64 = 0x01000000, DARWIN_CPU_TYPE_X86 = 7, + DARWIN_CPU_TYPE_ARM = 12, DARWIN_CPU_TYPE_POWERPC = 18 }; @@ -1532,6 +1585,8 @@ static void EmitDarwinBCHeader(BitstreamWriter &Stream, CPUType = DARWIN_CPU_TYPE_POWERPC; else if (TT.find("powerpc64-") == 0) CPUType = DARWIN_CPU_TYPE_POWERPC | DARWIN_CPU_ARCH_ABI64; + else if (isARMTriplet(TT)) + CPUType = DARWIN_CPU_TYPE_ARM; // Traditional Bitcode starts after header. unsigned BCOffset = DarwinBCHeaderSize; diff --git a/lib/Bitcode/Writer/ValueEnumerator.cpp b/lib/Bitcode/Writer/ValueEnumerator.cpp index 595497f6de..aa4c3afab4 100644 --- a/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -27,7 +27,7 @@ static bool isSingleValueType(const std::pair &V) { - return isa(V.first->getType()); + return V.first->getType()->isIntegerTy(); } static bool CompareByFrequency(const std::pairglobal_begin(), E = M->global_end(); I != E; ++I) @@ -377,6 +375,7 @@ void ValueEnumerator::EnumerateAttributes(const AttrListPtr &PAL) { void ValueEnumerator::incorporateFunction(const Function &F) { + InstructionCount = 0; NumModuleValues = Values.size(); // Adding function arguments to the value table. diff --git a/lib/CodeGen/Android.mk b/lib/CodeGen/Android.mk new file mode 100644 index 0000000000..9fa2ecdbd5 --- /dev/null +++ b/lib/CodeGen/Android.mk @@ -0,0 +1,99 @@ +LOCAL_PATH:= $(call my-dir) + +codegen_SRC_FILES := \ + AggressiveAntiDepBreaker.cpp \ + BranchFolding.cpp \ + CalcSpillWeights.cpp \ + CodePlacementOpt.cpp \ + CriticalAntiDepBreaker.cpp \ + DeadMachineInstructionElim.cpp \ + DwarfEHPrepare.cpp \ + ELFCodeEmitter.cpp \ + ELFWriter.cpp \ + ExactHazardRecognizer.cpp \ + GCMetadata.cpp \ + GCMetadataPrinter.cpp \ + GCStrategy.cpp \ + IfConversion.cpp \ + IntrinsicLowering.cpp \ + LLVMTargetMachine.cpp \ + LatencyPriorityQueue.cpp \ + LiveInterval.cpp \ + LiveIntervalAnalysis.cpp \ + LiveStackAnalysis.cpp \ + LiveVariables.cpp \ + LowerSubregs.cpp \ + MachineBasicBlock.cpp \ + MachineCSE.cpp \ + MachineDominators.cpp \ + MachineFunction.cpp \ + MachineFunctionAnalysis.cpp \ + MachineFunctionPass.cpp \ + MachineInstr.cpp \ + MachineLICM.cpp \ + MachineLoopInfo.cpp \ + MachineModuleInfo.cpp \ + MachineModuleInfoImpls.cpp \ + MachinePassRegistry.cpp \ + MachineRegisterInfo.cpp \ + MachineSSAUpdater.cpp \ + MachineSink.cpp \ + MachineVerifier.cpp \ + ObjectCodeEmitter.cpp \ + OcamlGC.cpp \ + OptimizeExts.cpp \ + OptimizePHIs.cpp \ + PHIElimination.cpp \ + Passes.cpp \ + PostRASchedulerList.cpp \ + PreAllocSplitting.cpp \ + ProcessImplicitDefs.cpp \ + PrologEpilogInserter.cpp \ + PseudoSourceValue.cpp \ + RegAllocLinearScan.cpp \ + RegAllocLocal.cpp \ + RegAllocPBQP.cpp \ + RegisterCoalescer.cpp \ + RegisterScavenging.cpp \ + ScheduleDAG.cpp \ + ScheduleDAGEmit.cpp \ + ScheduleDAGInstrs.cpp \ + ScheduleDAGPrinter.cpp \ + ShadowStackGC.cpp \ + ShrinkWrapping.cpp \ + SimpleRegisterCoalescing.cpp \ + SjLjEHPrepare.cpp \ + SlotIndexes.cpp \ + Spiller.cpp \ + StackProtector.cpp \ + StackSlotColoring.cpp \ + StrongPHIElimination.cpp \ + TailDuplication.cpp \ + TargetInstrInfoImpl.cpp \ + TargetLoweringObjectFileImpl.cpp \ + TwoAddressInstructionPass.cpp \ + UnreachableBlockElim.cpp \ + VirtRegMap.cpp \ + VirtRegRewriter.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(codegen_SRC_FILES) +LOCAL_MODULE:= libLLVMCodeGen + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(codegen_SRC_FILES) +LOCAL_MODULE:= libLLVMCodeGen + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/CodeGen/AsmPrinter/Android.mk b/lib/CodeGen/AsmPrinter/Android.mk new file mode 100644 index 0000000000..62601f0a2d --- /dev/null +++ b/lib/CodeGen/AsmPrinter/Android.mk @@ -0,0 +1,31 @@ +LOCAL_PATH := $(call my-dir) + +codegen_asmprinter_SRC_FILES := \ + AsmPrinter.cpp \ + DIE.cpp \ + DwarfDebug.cpp \ + DwarfException.cpp \ + DwarfLabel.cpp \ + DwarfPrinter.cpp \ + DwarfWriter.cpp \ + OcamlGCPrinter.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(codegen_asmprinter_SRC_FILES) +LOCAL_MODULE:= libLLVMAsmPrinter + +include $(LLVM_HOST_BUILD_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(codegen_asmprinter_SRC_FILES) +LOCAL_MODULE:= libLLVMAsmPrinter + +include $(LLVM_DEVICE_BUILD_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index fc08384593..bbeb02679c 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -50,6 +50,7 @@ #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" #include +#include using namespace llvm; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -917,11 +918,10 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV, if (NumBits == 0) return; // No need to emit alignment. - unsigned FillValue = 0; if (getCurrentSection()->getKind().isText()) - FillValue = MAI->getTextAlignFillValue(); - - OutStreamer.EmitValueToAlignment(1 << NumBits, FillValue, 1, 0); + OutStreamer.EmitCodeAlignment(1 << NumBits); + else + OutStreamer.EmitValueToAlignment(1 << NumBits, 0, 1, 0); } /// LowerConstant - Lower the specified LLVM Constant to an MCExpr. @@ -1717,7 +1717,7 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { } // Print the main label for the block. - if (MBB->pred_empty() || MBB->isOnlyReachableByFallthrough()) { + if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) { if (VerboseAsm) { // NOTE: Want this comment at start of line. O << MAI->getCommentString() << " BB#" << MBB->getNumber() << ':'; @@ -1764,6 +1764,39 @@ void AsmPrinter::printOffset(int64_t Offset) const { O << Offset; } +/// isBlockOnlyReachableByFallthough - Return true if the basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +bool AsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) + const { + // If this is a landing pad, it isn't a fall through. If it has no preds, + // then nothing falls through to it. + if (MBB->isLandingPad() || MBB->pred_empty()) + return false; + + // If there isn't exactly one predecessor, it can't be a fall through. + MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; + ++PI2; + if (PI2 != MBB->pred_end()) + return false; + + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *PI; + + if (!Pred->isLayoutSuccessor(MBB)) + return false; + + // If the block is completely empty, then it definitely does fall through. + if (Pred->empty()) + return true; + + // Otherwise, check the last instruction. + const MachineInstr &LastInst = Pred->back(); + return !LastInst.getDesc().isBarrier(); +} + + + GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { if (!S->usesMetadata()) return 0; diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 349e0ac40f..63360c0892 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -313,6 +313,7 @@ void DIESectionOffset::EmitValue(DwarfPrinter *D, unsigned Form) const { D->EmitSectionOffset(Label.getTag(), Section.getTag(), Label.getNumber(), Section.getNumber(), IsSmall, IsEH, UseSet); + D->getAsm()->O << '\n'; // FIXME: Necesssary? } /// SizeOf - Determine size of delta value in bytes. diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 5093dd9a9c..5ad1e5ea05 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -238,7 +238,18 @@ public: LIndex = DSI; } } - setLastInsn(LastInsn); + + unsigned CurrentLastInsnIndex = 0; + if (const MachineInstr *CL = getLastInsn()) + CurrentLastInsnIndex = MIIndexMap[CL]; + unsigned FIndex = MIIndexMap[getFirstInsn()]; + + // Set LastInsn as the last instruction for this scope only if + // it follows + // 1) this scope's first instruction and + // 2) current last instruction for this scope, if any. + if (LIndex >= CurrentLastInsnIndex && LIndex >= FIndex) + setLastInsn(LastInsn); } #ifndef NDEBUG @@ -1166,7 +1177,9 @@ DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) { return SPDie; SPDie = new DIE(dwarf::DW_TAG_subprogram); - addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName()); + // Constructors and operators for anonymous aggregates do not have names. + if (!SP.getName().empty()) + addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName()); StringRef LinkageName = SP.getLinkageName(); if (!LinkageName.empty()) diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index b6801dc61d..2b08ba4ad3 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -50,26 +50,6 @@ DwarfException::~DwarfException() { delete ExceptionTimer; } -/// SizeOfEncodedValue - Return the size of the encoding in bytes. -unsigned DwarfException::SizeOfEncodedValue(unsigned Encoding) { - if (Encoding == dwarf::DW_EH_PE_omit) - return 0; - - switch (Encoding & 0x07) { - case dwarf::DW_EH_PE_absptr: - return TD->getPointerSize(); - case dwarf::DW_EH_PE_udata2: - return 2; - case dwarf::DW_EH_PE_udata4: - return 4; - case dwarf::DW_EH_PE_udata8: - return 8; - } - - assert(0 && "Invalid encoded value."); - return 0; -} - /// CreateLabelDiff - Emit a label and subtract it from the expression we /// already have. This is equivalent to emitting "foo - .", but we have to emit /// the label for "." directly. @@ -100,7 +80,7 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { TD->getPointerSize() : -TD->getPointerSize(); const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - + // Begin eh frame section. Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); @@ -128,30 +108,16 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { // The personality presence indicates that language specific information will // show up in the eh frame. Find out how we are supposed to lower the // personality function reference: - const MCExpr *PersonalityRef = 0; - bool IsPersonalityIndirect = false, IsPersonalityPCRel = false; - if (PersonalityFn) { - // FIXME: HANDLE STATIC CODEGEN MODEL HERE. - - // In non-static mode, ask the object file how to represent this reference. - PersonalityRef = - TLOF.getSymbolForDwarfGlobalReference(PersonalityFn, Asm->Mang, - Asm->MMI, - IsPersonalityIndirect, - IsPersonalityPCRel); - } - - unsigned PerEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - if (IsPersonalityIndirect) - PerEncoding |= dwarf::DW_EH_PE_indirect; - unsigned LSDAEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; - unsigned FDEEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; + + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(); + unsigned PerEncoding = TLOF.getPersonalityEncoding(); char Augmentation[6] = { 0 }; unsigned AugmentationSize = 0; char *APtr = Augmentation + 1; - if (PersonalityRef) { + if (PersonalityFn) { // There is a personality function. *APtr++ = 'P'; AugmentationSize += 1 + SizeOfEncodedValue(PerEncoding); @@ -181,20 +147,19 @@ void DwarfException::EmitCIE(const Function *PersonalityFn, unsigned Index) { Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); EOL("CIE Return Address Column"); - EmitULEB128(AugmentationSize, "Augmentation Size"); - EmitEncodingByte(PerEncoding, "Personality"); - - // If there is a personality, we need to indicate the function's location. - if (PersonalityRef) { - if (!IsPersonalityPCRel) - PersonalityRef = CreateLabelDiff(PersonalityRef, "personalityref_addr", - Index); + if (Augmentation[0]) { + EmitULEB128(AugmentationSize, "Augmentation Size"); - O << MAI->getData32bitsDirective() << *PersonalityRef; - EOL("Personality"); - - EmitEncodingByte(LSDAEncoding, "LSDA"); - EmitEncodingByte(FDEEncoding, "FDE"); + // If there is a personality, we need to indicate the function's location. + if (PersonalityFn) { + EmitEncodingByte(PerEncoding, "Personality"); + EmitReference(PersonalityFn, PerEncoding); + EOL("Personality"); + } + if (UsesLSDA[Index]) + EmitEncodingByte(LSDAEncoding, "LSDA"); + if (FDEEncoding != dwarf::DW_EH_PE_absptr) + EmitEncodingByte(FDEEncoding, "FDE"); } // Indicate locations of general callee saved registers in frame. @@ -216,8 +181,12 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { "Should not emit 'available externally' functions at all"); const Function *TheFunc = EHFrameInfo.function; + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getEHFrameSection()); + unsigned LSDAEncoding = TLOF.getLSDAEncoding(); + unsigned FDEEncoding = TLOF.getFDEEncoding(); + + Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); // Externally visible entry into the functions eh frame info. If the // corresponding function is static, this should not be externally visible. @@ -255,7 +224,8 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { // EH frame header. EmitDifference("eh_frame_end", EHFrameInfo.Number, - "eh_frame_begin", EHFrameInfo.Number, true); + "eh_frame_begin", EHFrameInfo.Number, + true); EOL("Length of Frame Information Entry"); EmitLabel("eh_frame_begin", EHFrameInfo.Number); @@ -266,33 +236,23 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) { EOL("FDE CIE offset"); - EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); + EmitReference("eh_func_begin", EHFrameInfo.Number, FDEEncoding); EOL("FDE initial location"); EmitDifference("eh_func_end", EHFrameInfo.Number, - "eh_func_begin", EHFrameInfo.Number, true); + "eh_func_begin", EHFrameInfo.Number, + SizeOfEncodedValue(FDEEncoding) == 4); EOL("FDE address range"); // If there is a personality and landing pads then point to the language // specific data area in the exception table. if (MMI->getPersonalities()[0] != NULL) { + unsigned Size = SizeOfEncodedValue(LSDAEncoding); - if (Asm->TM.getLSDAEncoding() != DwarfLSDAEncoding::EightByte) { - EmitULEB128(4, "Augmentation size"); - - if (EHFrameInfo.hasLandingPads) - EmitReference("exception", EHFrameInfo.Number, true, true); - else - Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); - } else { - EmitULEB128(TD->getPointerSize(), "Augmentation size"); - - if (EHFrameInfo.hasLandingPads) { - EmitReference("exception", EHFrameInfo.Number, true, false); - } else { - Asm->OutStreamer.EmitIntValue(0, TD->getPointerSize(), - 0/*addrspace*/); - } - } + EmitULEB128(Size, "Augmentation size"); + if (EHFrameInfo.hasLandingPads) + EmitReference("exception", EHFrameInfo.Number, LSDAEncoding); + else + Asm->OutStreamer.EmitIntValue(0, Size/*size*/, 0/*addrspace*/); EOL("Language Specific Data Area"); } else { @@ -407,20 +367,22 @@ ComputeActionsTable(const SmallVectorImpl &LandingPads, if (NumShared < TypeIds.size()) { unsigned SizeAction = 0; - ActionEntry *PrevAction = 0; + unsigned PrevAction = (unsigned)-1; if (NumShared) { const unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); - PrevAction = &Actions.back(); - SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + - MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); + PrevAction = Actions.size() - 1; + SizeAction = + MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) + + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { + assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); SizeAction -= - MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); - SizeAction += -PrevAction->NextAction; - PrevAction = PrevAction->Previous; + MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); + SizeAction += -Actions[PrevAction].NextAction; + PrevAction = Actions[PrevAction].Previous; } } @@ -437,7 +399,7 @@ ComputeActionsTable(const SmallVectorImpl &LandingPads, ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; Actions.push_back(Action); - PrevAction = &Actions.back(); + PrevAction = Actions.size() - 1; } // Record the first action of the landing pad site. @@ -447,7 +409,7 @@ ComputeActionsTable(const SmallVectorImpl &LandingPads, // Information used when created the call-site table. The action record // field of the call site record is the offset of the first associated // action record, relative to the start of the actions table. This value is - // biased by 1 (1 in dicating the start of the actions table), and 0 + // biased by 1 (1 indicating the start of the actions table), and 0 // indicates that there are no actions. FirstActions.push_back(FirstAction); @@ -648,8 +610,7 @@ void DwarfException::EmitExceptionTable() { // landing pad site. SmallVector Actions; SmallVector FirstActions; - unsigned SizeActions = ComputeActionsTable(LandingPads, Actions, - FirstActions); + unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions); // Invokes and nounwind calls have entries in PadMap (due to being bracketed // by try-range labels when lowered). Ordinary calls do not, so appropriate @@ -677,29 +638,29 @@ void DwarfException::EmitExceptionTable() { const unsigned LandingPadSize = SizeOfEncodedValue(dwarf::DW_EH_PE_udata4); bool IsSJLJ = MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; - unsigned SizeSites; + unsigned CallSiteTableLength; if (IsSJLJ) - SizeSites = 0; + CallSiteTableLength = 0; else - SizeSites = CallSites.size() * + CallSiteTableLength = CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize); for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { - SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); + CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action); if (IsSJLJ) - SizeSites += MCAsmInfo::getULEB128Size(i); + CallSiteTableLength += MCAsmInfo::getULEB128Size(i); } // Type infos. const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); - unsigned TTypeFormat; + unsigned TTypeEncoding; unsigned TypeFormatSize; if (!HaveTTData) { // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say // that we're omitting that bit. - TTypeFormat = dwarf::DW_EH_PE_omit; + TTypeEncoding = dwarf::DW_EH_PE_omit; TypeFormatSize = SizeOfEncodedValue(dwarf::DW_EH_PE_absptr); } else { // Okay, we have actual filters or typeinfos to emit. As such, we need to @@ -729,21 +690,28 @@ void DwarfException::EmitExceptionTable() { // somewhere. This predicate should be moved to a shared location that is // in target-independent code. // - if (LSDASection->getKind().isWriteable() || - Asm->TM.getRelocationModel() == Reloc::Static) - TTypeFormat = dwarf::DW_EH_PE_absptr; - else - TTypeFormat = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | - dwarf::DW_EH_PE_sdata4; - - TypeFormatSize = SizeOfEncodedValue(TTypeFormat); + TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); + TypeFormatSize = SizeOfEncodedValue(TTypeEncoding); } // Begin the exception table. Asm->OutStreamer.SwitchSection(LSDASection); Asm->EmitAlignment(2, 0, 0, false); + // Emit the LSDA. O << "GCC_except_table" << SubprogramCount << ":\n"; + EmitLabel("exception", SubprogramCount); + + if (IsSJLJ) { + SmallString<16> LSDAName; + raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << + "_LSDA_" << Asm->getFunctionNumber(); + O << LSDAName.str() << ":\n"; + } + + // Emit the LSDA header. + EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); + EmitEncodingByte(TTypeEncoding, "@TType"); // The type infos need to be aligned. GCC does this by inserting padding just // before the type infos. However, this changes the size of the exception @@ -752,7 +720,7 @@ void DwarfException::EmitExceptionTable() { // So by increasing the size by inserting padding, you may increase the number // of bytes used for writing the size. If it increases, say by one byte, then // you now need to output one less byte of padding to get the type infos - // aligned. However this decreases the size of the exception table. This + // aligned. However this decreases the size of the exception table. This // changes the value you have to output for the exception table size. Due to // the variable length encoding, the number of bytes used for writing the // length may decrease. If so, you then have to increase the amount of @@ -761,41 +729,35 @@ void DwarfException::EmitExceptionTable() { // We chose another solution: don't output padding inside the table like GCC // does, instead output it before the table. unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; - unsigned TyOffset = sizeof(int8_t) + // Call site format - MCAsmInfo::getULEB128Size(SizeSites) + // Call site table length - SizeSites + SizeActions + SizeTypes; - unsigned TotalSize = sizeof(int8_t) + // LPStart format - sizeof(int8_t) + // TType format - (HaveTTData ? - MCAsmInfo::getULEB128Size(TyOffset) : 0) + // TType base offset - TyOffset; + unsigned CallSiteTableLengthSize = + MCAsmInfo::getULEB128Size(CallSiteTableLength); + unsigned TTypeBaseOffset = + sizeof(int8_t) + // Call site format + CallSiteTableLengthSize + // Call site table length size + CallSiteTableLength + // Call site table length + SizeActions + // Actions size + SizeTypes; + unsigned TTypeBaseOffsetSize = MCAsmInfo::getULEB128Size(TTypeBaseOffset); + unsigned TotalSize = + sizeof(int8_t) + // LPStart format + sizeof(int8_t) + // TType format + (HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size + TTypeBaseOffset; // TType base offset unsigned SizeAlign = (4 - TotalSize) & 3; - for (unsigned i = 0; i != SizeAlign; ++i) { - Asm->EmitInt8(0); - EOL("Padding"); - } - - EmitLabel("exception", SubprogramCount); - - if (IsSJLJ) { - SmallString<16> LSDAName; - raw_svector_ostream(LSDAName) << MAI->getPrivateGlobalPrefix() << - "_LSDA_" << Asm->getFunctionNumber(); - O << LSDAName.str() << ":\n"; + if (HaveTTData) { + // Account for any extra padding that will be added to the call site table + // length. + EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign); + SizeAlign = 0; } - // Emit the header. - EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); - EmitEncodingByte(TTypeFormat, "@TType"); - - if (HaveTTData) - EmitULEB128(TyOffset, "@TType base offset"); - // SjLj Exception handling if (IsSJLJ) { EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); - EmitULEB128(SizeSites, "Call site table length"); + + // Add extra padding if it wasn't added to the TType base offset. + EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); // Emit the landing pad site information. unsigned idx = 0; @@ -836,7 +798,9 @@ void DwarfException::EmitExceptionTable() { // Emit the landing pad call site table. EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); - EmitULEB128(SizeSites, "Call site table length"); + + // Add extra padding if it wasn't added to the TType base offset. + EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); for (SmallVectorImpl::const_iterator I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { @@ -906,23 +870,23 @@ void DwarfException::EmitExceptionTable() { } // Emit the Catch TypeInfos. - if (TypeInfos.size() != 0) EOL("-- Catch TypeInfos --"); + if (!TypeInfos.empty()) EOL("-- Catch TypeInfos --"); for (std::vector::const_reverse_iterator I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { const GlobalVariable *GV = *I; - PrintRelDirective(); if (GV) { - O << *Asm->GetGlobalValueSymbol(GV); + EmitReference(GV, TTypeEncoding); EOL("TypeInfo"); } else { + PrintRelDirective(TTypeEncoding); O << "0x0"; EOL(""); } } // Emit the Exception Specifications. - if (FilterIds.size() != 0) EOL("-- Filter IDs --"); + if (!FilterIds.empty()) EOL("-- Filter IDs --"); for (std::vector::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { unsigned TypeID = *I; diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index 06033a1a6f..3db1a00802 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -76,9 +76,6 @@ class DwarfException : public DwarfPrinter { /// ExceptionTimer - Timer for the Dwarf exception writer. Timer *ExceptionTimer; - /// SizeOfEncodedValue - Return the size of the encoding in bytes. - unsigned SizeOfEncodedValue(unsigned Encoding); - /// EmitCIE - Emit a Common Information Entry (CIE). This holds information /// that is shared among many Frame Description Entries. There is at least /// one CIE in every non-empty .debug_frame section. @@ -135,7 +132,7 @@ class DwarfException : public DwarfPrinter { struct ActionEntry { int ValueForTypeID; // The value to write - may not be equal to the type id. int NextAction; - struct ActionEntry *Previous; + unsigned Previous; }; /// CallSiteEntry - Structure describing an entry in the call-site table. diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp index 415390bc28..28ff0ebb93 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // Emit general DWARF directives. -// +// //===----------------------------------------------------------------------===// #include "DwarfPrinter.h" @@ -18,13 +18,17 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/SmallString.h" using namespace llvm; DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, @@ -33,6 +37,26 @@ DwarfPrinter::DwarfPrinter(raw_ostream &OS, AsmPrinter *A, const MCAsmInfo *T, RI(Asm->TM.getRegisterInfo()), M(NULL), MF(NULL), MMI(NULL), SubprogramCount(0), Flavor(flavor), SetCounter(1) {} +/// SizeOfEncodedValue - Return the size of the encoding in bytes. +unsigned DwarfPrinter::SizeOfEncodedValue(unsigned Encoding) const { + if (Encoding == dwarf::DW_EH_PE_omit) + return 0; + + switch (Encoding & 0x07) { + case dwarf::DW_EH_PE_absptr: + return TD->getPointerSize(); + case dwarf::DW_EH_PE_udata2: + return 2; + case dwarf::DW_EH_PE_udata4: + return 4; + case dwarf::DW_EH_PE_udata8: + return 8; + } + + assert(0 && "Invalid encoded value."); + return 0; +} + void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { if (isInSection && MAI->getDwarfSectionOffsetDirective()) O << MAI->getDwarfSectionOffsetDirective(); @@ -42,6 +66,14 @@ void DwarfPrinter::PrintRelDirective(bool Force32Bit, bool isInSection) const { O << MAI->getData64bitsDirective(); } +void DwarfPrinter::PrintRelDirective(unsigned Encoding) const { + unsigned Size = SizeOfEncodedValue(Encoding); + assert((Size == 4 || Size == 8) && "Do not support other types or rels!"); + + O << (Size == 4 ? + MAI->getData32bitsDirective() : MAI->getData64bitsDirective()); +} + /// EOL - Print a newline character to asm stream. If a comment is present /// then it will be printed first. Comments should not contain '\n'. void DwarfPrinter::EOL(const Twine &Comment) const { @@ -127,29 +159,35 @@ void DwarfPrinter::EmitSLEB128(int Value, const char *Desc) const { Value >>= 7; IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; if (IsMore) Byte |= 0x80; - Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); } while (IsMore); } /// EmitULEB128 - emit the specified signed leb128 value. -void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc) const { +void DwarfPrinter::EmitULEB128(unsigned Value, const char *Desc, + unsigned PadTo) const { if (Asm->VerboseAsm && Desc) Asm->OutStreamer.AddComment(Desc); - if (MAI->hasLEB128()) { + if (MAI->hasLEB128() && PadTo == 0) { O << "\t.uleb128\t" << Value; Asm->OutStreamer.AddBlankLine(); return; } - // If we don't have .uleb128, emit as .bytes. + // If we don't have .uleb128 or we want to emit padding, emit as .bytes. do { unsigned char Byte = static_cast(Value & 0x7f); Value >>= 7; - if (Value) Byte |= 0x80; + if (Value || PadTo != 0) Byte |= 0x80; Asm->OutStreamer.EmitIntValue(Byte, 1, /*addrspace*/0); } while (Value); + + if (PadTo) { + if (PadTo > 1) + Asm->OutStreamer.EmitFill(PadTo - 1, 0x80/*fillval*/, 0/*addrspace*/); + Asm->OutStreamer.EmitFill(1, 0/*fillval*/, 0/*addrspace*/); + } } @@ -195,6 +233,31 @@ void DwarfPrinter::EmitReference(const MCSymbol *Sym, bool IsPCRelative, if (IsPCRelative) O << "-" << MAI->getPCSymbol(); } +void DwarfPrinter::EmitReference(const char *Tag, unsigned Number, + unsigned Encoding) const { + SmallString<64> Name; + raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() + << Tag << Number; + + MCSymbol *Sym = Asm->OutContext.GetOrCreateSymbol(Name.str()); + EmitReference(Sym, Encoding); +} + +void DwarfPrinter::EmitReference(const MCSymbol *Sym, unsigned Encoding) const { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + PrintRelDirective(Encoding); + O << *TLOF.getSymbolForDwarfReference(Sym, Asm->MMI, Encoding);; +} + +void DwarfPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const { + const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); + + PrintRelDirective(Encoding); + O << *TLOF.getSymbolForDwarfGlobalReference(GV, Asm->Mang, + Asm->MMI, Encoding);; +} + /// EmitDifference - Emit the difference between two labels. If this assembler /// supports .set, we emit a .set of a temporary and then use it in the .word. void DwarfPrinter::EmitDifference(const char *TagHi, unsigned NumberHi, @@ -248,7 +311,6 @@ void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section, PrintRelDirective(IsSmall); PrintLabelName("set", SetCounter, Flavor); ++SetCounter; - O << "\n"; } else { PrintRelDirective(IsSmall, true); PrintLabelName(Label, LabelNumber); @@ -257,7 +319,6 @@ void DwarfPrinter::EmitSectionOffset(const char* Label, const char* Section, O << "-"; PrintLabelName(Section, SectionNumber); } - O << "\n"; } } diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.h b/lib/CodeGen/AsmPrinter/DwarfPrinter.h index 69d9c27ff0..bd715f2154 100644 --- a/lib/CodeGen/AsmPrinter/DwarfPrinter.h +++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.h @@ -28,6 +28,7 @@ class Module; class MCAsmInfo; class TargetData; class TargetRegisterInfo; +class GlobalValue; class MCSymbol; class Twine; @@ -85,6 +86,10 @@ public: const MCAsmInfo *getMCAsmInfo() const { return MAI; } const TargetData *getTargetData() const { return TD; } + /// SizeOfEncodedValue - Return the size of the encoding in bytes. + unsigned SizeOfEncodedValue(unsigned Encoding) const; + + void PrintRelDirective(unsigned Encoding) const; void PrintRelDirective(bool Force32Bit = false, bool isInSection = false) const; @@ -106,7 +111,8 @@ public: void EmitSLEB128(int Value, const char *Desc) const; /// EmitULEB128 - emit the specified unsigned leb128 value. - void EmitULEB128(unsigned Value, const char *Desc = 0) const; + void EmitULEB128(unsigned Value, const char *Desc = 0, + unsigned PadTo = 0) const; /// PrintLabelName - Print label name in form used by Dwarf writer. @@ -140,6 +146,10 @@ public: void EmitReference(const MCSymbol *Sym, bool IsPCRelative = false, bool Force32Bit = false) const; + void EmitReference(const char *Tag, unsigned Number, unsigned Encoding) const; + void EmitReference(const MCSymbol *Sym, unsigned Encoding) const; + void EmitReference(const GlobalValue *GV, unsigned Encoding) const; + /// EmitDifference - Emit the difference between two labels. void EmitDifference(const DWLabel &LabelHi, const DWLabel &LabelLo, bool IsSmall = false) { diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index 3531ed6039..a9502fdbc1 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -22,6 +22,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" +#include using namespace llvm; namespace { diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index faf4d9515a..d94729ad7a 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -334,7 +334,9 @@ static unsigned ComputeCommonTailLength(MachineBasicBlock *MBB1, unsigned TailLen = 0; while (I1 != MBB1->begin() && I2 != MBB2->begin()) { --I1; --I2; - if (!I1->isIdenticalTo(I2) || + // Don't merge debugging pseudos. + if (I1->isDebugValue() || I2->isDebugValue() || + !I1->isIdenticalTo(I2) || // FIXME: This check is dubious. It's used to get around a problem where // people incorrectly expect inline asm directives to remain in the same // relative order. This is untenable because normal compiler @@ -412,6 +414,8 @@ static unsigned EstimateRuntime(MachineBasicBlock::iterator I, MachineBasicBlock::iterator E) { unsigned Time = 0; for (; I != E; ++I) { + if (I->isDebugValue()) + continue; const TargetInstrDesc &TID = I->getDesc(); if (TID.isCall()) Time += 10; diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt index 9fcbea9437..d385b860d8 100644 --- a/lib/CodeGen/CMakeLists.txt +++ b/lib/CodeGen/CMakeLists.txt @@ -22,6 +22,7 @@ add_llvm_library(LLVMCodeGen LiveVariables.cpp LowerSubregs.cpp MachineBasicBlock.cpp + MachineCSE.cpp MachineDominators.cpp MachineFunction.cpp MachineFunctionAnalysis.cpp @@ -39,6 +40,7 @@ add_llvm_library(LLVMCodeGen ObjectCodeEmitter.cpp OcamlGC.cpp OptimizeExts.cpp + OptimizePHIs.cpp PHIElimination.cpp Passes.cpp PostRASchedulerList.cpp @@ -66,6 +68,7 @@ add_llvm_library(LLVMCodeGen StrongPHIElimination.cpp TailDuplication.cpp TargetInstrInfoImpl.cpp + TargetLoweringObjectFileImpl.cpp TwoAddressInstructionPass.cpp UnreachableBlockElim.cpp VirtRegMap.cpp diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp index 2bedd04243..a328d0e556 100644 --- a/lib/CodeGen/CalcSpillWeights.cpp +++ b/lib/CodeGen/CalcSpillWeights.cpp @@ -131,10 +131,7 @@ bool CalculateSpillWeights::runOnMachineFunction(MachineFunction &fn) { if (Hint.first || Hint.second) li.weight *= 1.01F; - // Divide the weight of the interval by its size. This encourages - // spilling of intervals that are large and have few uses, and - // discourages spilling of small intervals with many uses. - li.weight /= lis->getApproximateInstructionCount(li) * SlotIndex::NUM; + lis->normalizeSpillWeight(li); } } diff --git a/lib/CodeGen/CodePlacementOpt.cpp b/lib/CodeGen/CodePlacementOpt.cpp index 05a57d4534..3ff2a046d2 100644 --- a/lib/CodeGen/CodePlacementOpt.cpp +++ b/lib/CodeGen/CodePlacementOpt.cpp @@ -102,22 +102,23 @@ bool CodePlacementOpt::HasAnalyzableTerminator(MachineBasicBlock *MBB) { // Conservatively ignore EH landing pads. if (MBB->isLandingPad()) return false; - // Ignore blocks which look like they might have EH-related control flow. - // At the time of this writing, there are blocks which AnalyzeBranch - // thinks end in single uncoditional branches, yet which have two CFG - // successors. Code in this file is not prepared to reason about such things. - if (!MBB->empty() && MBB->back().isEHLabel()) - return false; - // Aggressively handle return blocks and similar constructs. if (MBB->succ_empty()) return true; // Ask the target's AnalyzeBranch if it can handle this block. MachineBasicBlock *TBB = 0, *FBB = 0; SmallVector Cond; - // Make the terminator is understood. + // Make sure the terminator is understood. if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond)) return false; + // Ignore blocks which look like they might have EH-related control flow. + // AnalyzeBranch thinks it knows how to analyze such things, but it doesn't + // recognize the possibility of a control transfer through an unwind. + // Such blocks contain EH_LABEL instructions, however they may be in the + // middle of the block. Instead of searching for them, just check to see + // if the CFG disagrees with AnalyzeBranch. + if (1u + !Cond.empty() != MBB->succ_size()) + return false; // Make sure we have the option of reversing the condition. if (!Cond.empty() && TII->ReverseBranchCondition(Cond)) return false; diff --git a/lib/CodeGen/CriticalAntiDepBreaker.cpp b/lib/CodeGen/CriticalAntiDepBreaker.cpp index 056e2d5b01..7d3de89ada 100644 --- a/lib/CodeGen/CriticalAntiDepBreaker.cpp +++ b/lib/CodeGen/CriticalAntiDepBreaker.cpp @@ -119,6 +119,8 @@ void CriticalAntiDepBreaker::FinishBlock() { void CriticalAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count, unsigned InsertPosIndex) { + if (MI->isDebugValue()) + return; assert(Count < InsertPosIndex && "Instruction index out of expected range!"); // Any register which was defined within the previous scheduling region @@ -409,6 +411,8 @@ BreakAntiDependencies(std::vector& SUnits, for (MachineBasicBlock::iterator I = End, E = Begin; I != E; --Count) { MachineInstr *MI = --I; + if (MI->isDebugValue()) + continue; // Check if this instruction has a dependence on the critical path that // is an anti-dependence that we may be able to break. If it is, set diff --git a/lib/CodeGen/DeadMachineInstructionElim.cpp b/lib/CodeGen/DeadMachineInstructionElim.cpp index b0cb24d95f..d69c995b3e 100644 --- a/lib/CodeGen/DeadMachineInstructionElim.cpp +++ b/lib/CodeGen/DeadMachineInstructionElim.cpp @@ -55,7 +55,7 @@ FunctionPass *llvm::createDeadMachineInstructionElimPass() { bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const { // Don't delete instructions with side effects. bool SawStore = false; - if (!MI->isSafeToMove(TII, SawStore, 0)) + if (!MI->isSafeToMove(TII, 0, SawStore) && !MI->isPHI()) return false; // Examine each operand. @@ -64,8 +64,8 @@ bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const { if (MO.isReg() && MO.isDef()) { unsigned Reg = MO.getReg(); if (TargetRegisterInfo::isPhysicalRegister(Reg) ? - LivePhysRegs[Reg] : !MRI->use_empty(Reg)) { - // This def has a use. Don't delete the instruction! + LivePhysRegs[Reg] : !MRI->use_nodbg_empty(Reg)) { + // This def has a non-debug use. Don't delete the instruction! return false; } } @@ -111,23 +111,31 @@ bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) { MIE = MBB->rend(); MII != MIE; ) { MachineInstr *MI = &*MII; - if (MI->isDebugValue()) { - // Don't delete the DBG_VALUE itself, but if its Value operand is - // a vreg and this is the only use, substitute an undef operand; - // the former operand will then be deleted normally. - if (MI->getNumOperands()==3 && MI->getOperand(0).isReg()) { - unsigned Reg = MI->getOperand(0).getReg(); - MachineRegisterInfo::use_iterator I = MRI->use_begin(Reg); - assert(I != MRI->use_end()); - if (++I == MRI->use_end()) - // only one use, which must be this DBG_VALUE. - MI->getOperand(0).setReg(0U); - } - } - // If the instruction is dead, delete it! if (isDead(MI)) { DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << *MI); + // It is possible that some DBG_VALUE instructions refer to this + // instruction. Examine each def operand for such references; + // if found, mark the DBG_VALUE as undef (but don't delete it). + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned Reg = MO.getReg(); + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + MachineRegisterInfo::use_iterator nextI; + for (MachineRegisterInfo::use_iterator I = MRI->use_begin(Reg), + E = MRI->use_end(); I!=E; I=nextI) { + nextI = llvm::next(I); // I is invalidated by the setReg + MachineOperand& Use = I.getOperand(); + MachineInstr *UseMI = Use.getParent(); + if (UseMI==MI) + continue; + assert(Use.isDebug()); + UseMI->getOperand(0).setReg(0U); + } + } AnyChanges = true; MI->eraseFromParent(); ++NumDeletes; diff --git a/lib/CodeGen/IntrinsicLowering.cpp b/lib/CodeGen/IntrinsicLowering.cpp index 9997a48442..87ab7ef52e 100644 --- a/lib/CodeGen/IntrinsicLowering.cpp +++ b/lib/CodeGen/IntrinsicLowering.cpp @@ -155,7 +155,7 @@ void IntrinsicLowering::AddPrototypes(Module &M) { /// LowerBSWAP - Emit the code to lower bswap of V before the specified /// instruction IP. static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) { - assert(V->getType()->isInteger() && "Can't bswap a non-integer type!"); + assert(V->getType()->isIntegerTy() && "Can't bswap a non-integer type!"); unsigned BitSize = V->getType()->getPrimitiveSizeInBits(); @@ -251,7 +251,7 @@ static Value *LowerBSWAP(LLVMContext &Context, Value *V, Instruction *IP) { /// LowerCTPOP - Emit the code to lower ctpop of V before the specified /// instruction IP. static Value *LowerCTPOP(LLVMContext &Context, Value *V, Instruction *IP) { - assert(V->getType()->isInteger() && "Can't ctpop a non-integer type!"); + assert(V->getType()->isIntegerTy() && "Can't ctpop a non-integer type!"); static const uint64_t MaskValues[6] = { 0x5555555555555555ULL, 0x3333333333333333ULL, diff --git a/lib/CodeGen/LLVMTargetMachine.cpp b/lib/CodeGen/LLVMTargetMachine.cpp index 40e015067f..5e888650ba 100644 --- a/lib/CodeGen/LLVMTargetMachine.cpp +++ b/lib/CodeGen/LLVMTargetMachine.cpp @@ -14,6 +14,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/PassManager.h" #include "llvm/Pass.h" +#include "llvm/Analysis/Verifier.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/Passes.h" @@ -66,6 +67,9 @@ static cl::opt VerifyMachineCode("verify-machineinstrs", cl::Hidden, cl::desc("Verify generated machine code"), cl::init(getenv("LLVM_VERIFY_MACHINEINSTRS")!=NULL)); +static cl::opt EnableMachineCSE("enable-machine-cse", cl::Hidden, + cl::desc("Enable Machine CSE")); + static cl::opt AsmVerbose("asm-verbose", cl::desc("Add comments to directives."), cl::init(cl::BOU_UNSET)); @@ -114,9 +118,10 @@ LLVMTargetMachine::setCodeModelForStatic() { bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, CodeGenFileType FileType, - CodeGenOpt::Level OptLevel) { + CodeGenOpt::Level OptLevel, + bool DisableVerify) { // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify)) return true; OwningPtr Context(new MCContext()); @@ -140,7 +145,7 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, case CGFT_ObjectFile: { // Create the code emitter for the target if it exists. If not, .o file // emission fails. - MCCodeEmitter *MCE = getTarget().createCodeEmitter(*this); + MCCodeEmitter *MCE = getTarget().createCodeEmitter(*this, *Context); if (MCE == 0) return true; @@ -192,12 +197,13 @@ bool LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &PM, /// bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, JITCodeEmitter &JCE, - CodeGenOpt::Level OptLevel) { + CodeGenOpt::Level OptLevel, + bool DisableVerify) { // Make sure the code model is set. setCodeModelForJIT(); // Add common CodeGen passes. - if (addCommonCodeGenPasses(PM, OptLevel)) + if (addCommonCodeGenPasses(PM, OptLevel, DisableVerify)) return true; addCodeEmitter(PM, OptLevel, JCE); @@ -206,6 +212,12 @@ bool LLVMTargetMachine::addPassesToEmitMachineCode(PassManagerBase &PM, return false; // success! } +static void printNoVerify(PassManagerBase &PM, + const char *Banner) { + if (PrintMachineCode) + PM.add(createMachineFunctionPrinterPass(dbgs(), Banner)); +} + static void printAndVerify(PassManagerBase &PM, const char *Banner, bool allowDoubleDefs = false) { @@ -220,13 +232,19 @@ static void printAndVerify(PassManagerBase &PM, /// emitting to assembly files or machine code output. /// bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, - CodeGenOpt::Level OptLevel) { + CodeGenOpt::Level OptLevel, + bool DisableVerify) { // Standard LLVM-Level Passes. + // Before running any passes, run the verifier to determine if the input + // coming from the front-end and/or optimizer is valid. + if (!DisableVerify) + PM.add(createVerifierPass()); + // Optionally, tun split-GEPs and no-load GVN. if (EnableSplitGEPGVN) { PM.add(createGEPSplitterPass()); - PM.add(createGVNPass(/*NoPRE=*/false, /*NoLoads=*/true)); + PM.add(createGVNPass(/*NoLoads=*/true)); } // Run loop strength reduction before anything else. @@ -273,6 +291,11 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, "*** Final LLVM Code input to ISel ***\n", &dbgs())); + // All passes which modify the LLVM IR are now complete; run the verifier + // to ensure that the IR is valid. + if (!DisableVerify) + PM.add(createVerifierPass()); + // Standard Lower-Level Passes. // Set up a MachineFunction for the rest of CodeGen to work on. @@ -291,6 +314,10 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, printAndVerify(PM, "After Instruction Selection", /* allowDoubleDefs= */ true); + // Optimize PHIs before DCE: removing dead PHI cycles may make more + // instructions dead. + if (OptLevel != CodeGenOpt::None) + PM.add(createOptimizePHIsPass()); // Delete dead machine instructions regardless of optimization level. PM.add(createDeadMachineInstructionElimPass()); @@ -301,6 +328,8 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, PM.add(createOptimizeExtsPass()); if (!DisableMachineLICM) PM.add(createMachineLICMPass()); + if (EnableMachineCSE) + PM.add(createMachineCSEPass()); if (!DisableMachineSink) PM.add(createMachineSinkingPass()); printAndVerify(PM, "After MachineLICM and MachineSinking", @@ -355,13 +384,13 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, // Branch folding must be run after regalloc and prolog/epilog insertion. if (OptLevel != CodeGenOpt::None && !DisableBranchFold) { PM.add(createBranchFoldingPass(getEnableTailMergeDefault())); - printAndVerify(PM, "After BranchFolding"); + printNoVerify(PM, "After BranchFolding"); } // Tail duplication. if (OptLevel != CodeGenOpt::None && !DisableTailDuplicate) { PM.add(createTailDuplicatePass(false)); - printAndVerify(PM, "After TailDuplicate"); + printNoVerify(PM, "After TailDuplicate"); } PM.add(createGCMachineCodeAnalysisPass()); @@ -371,11 +400,11 @@ bool LLVMTargetMachine::addCommonCodeGenPasses(PassManagerBase &PM, if (OptLevel != CodeGenOpt::None && !DisableCodePlace) { PM.add(createCodePlacementOptPass()); - printAndVerify(PM, "After CodePlacementOpt"); + printNoVerify(PM, "After CodePlacementOpt"); } if (addPreEmitPass(PM, OptLevel)) - printAndVerify(PM, "After PreEmit passes"); + printNoVerify(PM, "After PreEmit passes"); return false; } diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index 432409acd3..ccda66f005 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -329,24 +329,43 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, DEBUG(dbgs() << " +" << NewLR); interval.addRange(NewLR); - // Iterate over all of the blocks that the variable is completely - // live in, adding [insrtIndex(begin), instrIndex(end)+4) to the - // live interval. - for (SparseBitVector<>::iterator I = vi.AliveBlocks.begin(), - E = vi.AliveBlocks.end(); I != E; ++I) { - MachineBasicBlock *aliveBlock = mf_->getBlockNumbered(*I); - LiveRange LR(getMBBStartIdx(aliveBlock), getMBBEndIdx(aliveBlock), ValNo); - interval.addRange(LR); - DEBUG(dbgs() << " +" << LR); + bool PHIJoin = lv_->isPHIJoin(interval.reg); + + if (PHIJoin) { + // A phi join register is killed at the end of the MBB and revived as a new + // valno in the killing blocks. + assert(vi.AliveBlocks.empty() && "Phi join can't pass through blocks"); + DEBUG(dbgs() << " phi-join"); + ValNo->addKill(indexes_->getTerminatorGap(mbb)); + ValNo->setHasPHIKill(true); + } else { + // Iterate over all of the blocks that the variable is completely + // live in, adding [insrtIndex(begin), instrIndex(end)+4) to the + // live interval. + for (SparseBitVector<>::iterator I = vi.AliveBlocks.begin(), + E = vi.AliveBlocks.end(); I != E; ++I) { + MachineBasicBlock *aliveBlock = mf_->getBlockNumbered(*I); + LiveRange LR(getMBBStartIdx(aliveBlock), getMBBEndIdx(aliveBlock), ValNo); + interval.addRange(LR); + DEBUG(dbgs() << " +" << LR); + } } // Finally, this virtual register is live from the start of any killing // block to the 'use' slot of the killing instruction. for (unsigned i = 0, e = vi.Kills.size(); i != e; ++i) { MachineInstr *Kill = vi.Kills[i]; - SlotIndex killIdx = - getInstructionIndex(Kill).getDefIndex(); - LiveRange LR(getMBBStartIdx(Kill->getParent()), killIdx, ValNo); + SlotIndex Start = getMBBStartIdx(Kill->getParent()); + SlotIndex killIdx = getInstructionIndex(Kill).getDefIndex(); + + // Create interval with one of a NEW value number. Note that this value + // number isn't actually defined by an instruction, weird huh? :) + if (PHIJoin) { + ValNo = interval.getNextValue(SlotIndex(Start, true), 0, false, + VNInfoAllocator); + ValNo->setIsPHIDef(true); + } + LiveRange LR(Start, killIdx, ValNo); interval.addRange(LR); ValNo->addKill(killIdx); DEBUG(dbgs() << " +" << LR); @@ -409,48 +428,11 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, interval.print(dbgs(), tri_); }); } else { - // Otherwise, this must be because of phi elimination. If this is the - // first redefinition of the vreg that we have seen, go back and change - // the live range in the PHI block to be a different value number. - if (interval.containsOneValue()) { - - VNInfo *VNI = interval.getValNumInfo(0); - // Phi elimination may have reused the register for multiple identical - // phi nodes. There will be a kill per phi. Remove the old ranges that - // we now know have an incorrect number. - for (unsigned ki=0, ke=vi.Kills.size(); ki != ke; ++ki) { - MachineInstr *Killer = vi.Kills[ki]; - SlotIndex Start = getMBBStartIdx(Killer->getParent()); - SlotIndex End = getInstructionIndex(Killer).getDefIndex(); - DEBUG({ - dbgs() << "\n\t\trenaming [" << Start << "," << End << "] in: "; - interval.print(dbgs(), tri_); - }); - interval.removeRange(Start, End); - - // Replace the interval with one of a NEW value number. Note that - // this value number isn't actually defined by an instruction, weird - // huh? :) - LiveRange LR(Start, End, - interval.getNextValue(SlotIndex(Start, true), - 0, false, VNInfoAllocator)); - LR.valno->setIsPHIDef(true); - interval.addRange(LR); - LR.valno->addKill(End); - } - - MachineBasicBlock *killMBB = getMBBFromIndex(VNI->def); - VNI->addKill(indexes_->getTerminatorGap(killMBB)); - VNI->setHasPHIKill(true); - DEBUG({ - dbgs() << " RESULT: "; - interval.print(dbgs(), tri_); - }); - } - + assert(lv_->isPHIJoin(interval.reg) && "Multiply defined register"); // In the case of PHI elimination, each variable definition is only // live until the end of the block. We've already taken care of the // rest of the live range. + SlotIndex defIndex = MIIdx.getDefIndex(); if (MO.isEarlyClobber()) defIndex = MIIdx.getUseIndex(); @@ -468,7 +450,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb, interval.addRange(LR); ValNo->addKill(indexes_->getTerminatorGap(mbb)); ValNo->setHasPHIKill(true); - DEBUG(dbgs() << " +" << LR); + DEBUG(dbgs() << " phi-join +" << LR); } } @@ -613,6 +595,9 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB, while (mi != E) { if (mi->isDebugValue()) { ++mi; + if (mi != E && !mi->isDebugValue()) { + baseIndex = indexes_->getNextNonNullIndex(baseIndex); + } continue; } if (mi->killsRegister(interval.reg, tri_)) { @@ -1355,11 +1340,9 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, MachineBasicBlock *MBB = MI->getParent(); if (ImpUse && MI != ReMatDefMI) { - // Re-matting an instruction with virtual register use. Update the - // register interval's spill weight to HUGE_VALF to prevent it from - // being spilled. - LiveInterval &ImpLi = getInterval(ImpUse); - ImpLi.weight = HUGE_VALF; + // Re-matting an instruction with virtual register use. Prevent interval + // from being spilled. + getInterval(ImpUse).markNotSpillable(); } unsigned MBBId = MBB->getNumber(); @@ -1411,7 +1394,7 @@ rewriteInstructionsForSpills(const LiveInterval &li, bool TrySplit, LiveInterval &nI = getOrCreateInterval(NewVReg); if (!TrySplit) { // The spill weight is now infinity as it cannot be spilled again. - nI.weight = HUGE_VALF; + nI.markNotSpillable(); continue; } @@ -1559,6 +1542,28 @@ LiveIntervals::handleSpilledImpDefs(const LiveInterval &li, VirtRegMap &vrm, } } +float +LiveIntervals::getSpillWeight(bool isDef, bool isUse, unsigned loopDepth) { + // Limit the loop depth ridiculousness. + if (loopDepth > 200) + loopDepth = 200; + + // The loop depth is used to roughly estimate the number of times the + // instruction is executed. Something like 10^d is simple, but will quickly + // overflow a float. This expression behaves like 10^d for small d, but is + // more tempered for large d. At d=200 we get 6.7e33 which leaves a bit of + // headroom before overflow. + float lc = powf(1 + (100.0f / (loopDepth+10)), (float)loopDepth); + + return (isDef + isUse) * lc; +} + +void +LiveIntervals::normalizeSpillWeights(std::vector &NewLIs) { + for (unsigned i = 0, e = NewLIs.size(); i != e; ++i) + normalizeSpillWeight(*NewLIs[i]); +} + std::vector LiveIntervals:: addIntervalsForSpillsFast(const LiveInterval &li, const MachineLoopInfo *loopInfo, @@ -1567,8 +1572,7 @@ addIntervalsForSpillsFast(const LiveInterval &li, std::vector added; - assert(li.weight != HUGE_VALF && - "attempt to spill already spilled interval!"); + assert(li.isSpillable() && "attempt to spill already spilled interval!"); DEBUG({ dbgs() << "\t\t\t\tadding intervals for spills for interval: "; @@ -1604,10 +1608,7 @@ addIntervalsForSpillsFast(const LiveInterval &li, // create a new register for this spill LiveInterval &nI = getOrCreateInterval(NewVReg); - - // the spill weight is now infinity as it - // cannot be spilled again - nI.weight = HUGE_VALF; + nI.markNotSpillable(); // Rewrite register operands to use the new vreg. for (SmallVectorImpl::iterator I = Indices.begin(), @@ -1661,8 +1662,7 @@ addIntervalsForSpills(const LiveInterval &li, if (EnableFastSpilling) return addIntervalsForSpillsFast(li, loopInfo, vrm); - assert(li.weight != HUGE_VALF && - "attempt to spill already spilled interval!"); + assert(li.isSpillable() && "attempt to spill already spilled interval!"); DEBUG({ dbgs() << "\t\t\t\tadding intervals for spills for interval: "; @@ -1736,6 +1736,7 @@ addIntervalsForSpills(const LiveInterval &li, } handleSpilledImpDefs(li, vrm, rc, NewLIs); + normalizeSpillWeights(NewLIs); return NewLIs; } @@ -1811,6 +1812,7 @@ addIntervalsForSpills(const LiveInterval &li, // Insert spills / restores if we are splitting. if (!TrySplit) { handleSpilledImpDefs(li, vrm, rc, NewLIs); + normalizeSpillWeights(NewLIs); return NewLIs; } @@ -1927,11 +1929,10 @@ addIntervalsForSpills(const LiveInterval &li, unsigned ImpUse = getReMatImplicitUse(li, ReMatDefMI); if (ImpUse) { // Re-matting an instruction with virtual register use. Add the - // register as an implicit use on the use MI and update the register - // interval's spill weight to HUGE_VALF to prevent it from being - // spilled. + // register as an implicit use on the use MI and mark the register + // interval as unspillable. LiveInterval &ImpLi = getInterval(ImpUse); - ImpLi.weight = HUGE_VALF; + ImpLi.markNotSpillable(); MI->addOperand(MachineOperand::CreateReg(ImpUse, false, true)); } } @@ -1970,6 +1971,7 @@ addIntervalsForSpills(const LiveInterval &li, } handleSpilledImpDefs(li, vrm, rc, RetNewLIs); + normalizeSpillWeights(RetNewLIs); return RetNewLIs; } diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp index 8a124dc79b..519990e04a 100644 --- a/lib/CodeGen/LiveVariables.cpp +++ b/lib/CodeGen/LiveVariables.cpp @@ -365,27 +365,7 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) { } } - if (LastRefOrPartRef == PhysRegDef[Reg] && LastRefOrPartRef != MI) { - if (LastPartDef) - // The last partial def kills the register. - LastPartDef->addOperand(MachineOperand::CreateReg(Reg, false/*IsDef*/, - true/*IsImp*/, true/*IsKill*/)); - else { - MachineOperand *MO = - LastRefOrPartRef->findRegisterDefOperand(Reg, false, TRI); - bool NeedEC = MO->isEarlyClobber() && MO->getReg() != Reg; - // If the last reference is the last def, then it's not used at all. - // That is, unless we are currently processing the last reference itself. - LastRefOrPartRef->addRegisterDead(Reg, TRI, true); - if (NeedEC) { - // If we are adding a subreg def and the superreg def is marked early - // clobber, add an early clobber marker to the subreg def. - MO = LastRefOrPartRef->findRegisterDefOperand(Reg); - if (MO) - MO->setIsEarlyClobber(); - } - } - } else if (!PhysRegUse[Reg]) { + if (!PhysRegUse[Reg]) { // Partial uses. Mark register def dead and add implicit def of // sub-registers which are used. // EAX = op AL @@ -419,6 +399,26 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) { for (const unsigned *SS = TRI->getSubRegisters(SubReg); *SS; ++SS) PartUses.erase(*SS); } + } else if (LastRefOrPartRef == PhysRegDef[Reg] && LastRefOrPartRef != MI) { + if (LastPartDef) + // The last partial def kills the register. + LastPartDef->addOperand(MachineOperand::CreateReg(Reg, false/*IsDef*/, + true/*IsImp*/, true/*IsKill*/)); + else { + MachineOperand *MO = + LastRefOrPartRef->findRegisterDefOperand(Reg, false, TRI); + bool NeedEC = MO->isEarlyClobber() && MO->getReg() != Reg; + // If the last reference is the last def, then it's not used at all. + // That is, unless we are currently processing the last reference itself. + LastRefOrPartRef->addRegisterDead(Reg, TRI, true); + if (NeedEC) { + // If we are adding a subreg def and the superreg def is marked early + // clobber, add an early clobber marker to the subreg def. + MO = LastRefOrPartRef->findRegisterDefOperand(Reg); + if (MO) + MO->setIsEarlyClobber(); + } + } } else LastRefOrPartRef->addRegisterKilled(Reg, TRI, true); return true; @@ -510,6 +510,7 @@ bool LiveVariables::runOnMachineFunction(MachineFunction &mf) { PHIVarInfo = new SmallVector[MF->getNumBlockIDs()]; std::fill(PhysRegDef, PhysRegDef + NumRegs, (MachineInstr*)0); std::fill(PhysRegUse, PhysRegUse + NumRegs, (MachineInstr*)0); + PHIJoins.clear(); /// Get some space for a respectable number of registers. VirtRegInfo.resize(64); diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index 655a0bf445..64134ce59e 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -143,36 +143,6 @@ MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminator() { return I; } -/// isOnlyReachableViaFallthough - Return true if this basic block has -/// exactly one predecessor and the control transfer mechanism between -/// the predecessor and this block is a fall-through. -bool MachineBasicBlock::isOnlyReachableByFallthrough() const { - // If this is a landing pad, it isn't a fall through. If it has no preds, - // then nothing falls through to it. - if (isLandingPad() || pred_empty()) - return false; - - // If there isn't exactly one predecessor, it can't be a fall through. - const_pred_iterator PI = pred_begin(), PI2 = PI; - ++PI2; - if (PI2 != pred_end()) - return false; - - // The predecessor has to be immediately before this block. - const MachineBasicBlock *Pred = *PI; - - if (!Pred->isLayoutSuccessor(this)) - return false; - - // If the block is completely empty, then it definitely does fall through. - if (Pred->empty()) - return true; - - // Otherwise, check the last instruction. - const MachineInstr &LastInst = Pred->back(); - return !LastInst.getDesc().isBarrier(); -} - void MachineBasicBlock::dump() const { print(dbgs()); } diff --git a/lib/CodeGen/MachineCSE.cpp b/lib/CodeGen/MachineCSE.cpp new file mode 100644 index 0000000000..b376e3d05f --- /dev/null +++ b/lib/CodeGen/MachineCSE.cpp @@ -0,0 +1,268 @@ +//===-- MachineCSE.cpp - Machine Common Subexpression Elimination Pass ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass performs global common subexpression elimination on machine +// instructions using a scoped hash table based value numbering scheme. It +// must be run while the machine function is still in SSA form. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "machine-cse" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/ScopedHashTable.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +STATISTIC(NumCoalesces, "Number of copies coalesced"); +STATISTIC(NumCSEs, "Number of common subexpression eliminated"); + +namespace { + class MachineCSE : public MachineFunctionPass { + const TargetInstrInfo *TII; + const TargetRegisterInfo *TRI; + MachineRegisterInfo *MRI; + MachineDominatorTree *DT; + AliasAnalysis *AA; + public: + static char ID; // Pass identification + MachineCSE() : MachineFunctionPass(&ID), CurrVN(0) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); + AU.addPreserved(); + } + + private: + unsigned CurrVN; + ScopedHashTable VNT; + SmallVector Exps; + + bool PerformTrivialCoalescing(MachineInstr *MI, MachineBasicBlock *MBB); + bool isPhysDefTriviallyDead(unsigned Reg, + MachineBasicBlock::const_iterator I, + MachineBasicBlock::const_iterator E); + bool hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB); + bool isCSECandidate(MachineInstr *MI); + bool ProcessBlock(MachineDomTreeNode *Node); + }; +} // end anonymous namespace + +char MachineCSE::ID = 0; +static RegisterPass +X("machine-cse", "Machine Common Subexpression Elimination"); + +FunctionPass *llvm::createMachineCSEPass() { return new MachineCSE(); } + +bool MachineCSE::PerformTrivialCoalescing(MachineInstr *MI, + MachineBasicBlock *MBB) { + bool Changed = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isUse()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg || TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + if (!MRI->hasOneUse(Reg)) + // Only coalesce single use copies. This ensure the copy will be + // deleted. + continue; + MachineInstr *DefMI = MRI->getVRegDef(Reg); + if (DefMI->getParent() != MBB) + continue; + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (TII->isMoveInstr(*DefMI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) && + TargetRegisterInfo::isVirtualRegister(SrcReg) && + !SrcSubIdx && !DstSubIdx) { + MO.setReg(SrcReg); + DefMI->eraseFromParent(); + ++NumCoalesces; + Changed = true; + } + } + + return Changed; +} + +bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg, + MachineBasicBlock::const_iterator I, + MachineBasicBlock::const_iterator E) { + unsigned LookAheadLeft = 5; + while (LookAheadLeft--) { + if (I == E) + // Reached end of block, register is obviously dead. + return true; + + if (I->isDebugValue()) + continue; + bool SeenDef = false; + for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = I->getOperand(i); + if (!MO.isReg() || !MO.getReg()) + continue; + if (!TRI->regsOverlap(MO.getReg(), Reg)) + continue; + if (MO.isUse()) + return false; + SeenDef = true; + } + if (SeenDef) + // See a def of Reg (or an alias) before encountering any use, it's + // trivially dead. + return true; + ++I; + } + return false; +} + +bool MachineCSE::hasLivePhysRegDefUse(MachineInstr *MI, MachineBasicBlock *MBB){ + unsigned PhysDef = 0; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (!Reg) + continue; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + if (MO.isUse()) + // Can't touch anything to read a physical register. + return true; + if (MO.isDead()) + // If the def is dead, it's ok. + continue; + // Ok, this is a physical register def that's not marked "dead". That's + // common since this pass is run before livevariables. We can scan + // forward a few instructions and check if it is obviously dead. + if (PhysDef) + // Multiple physical register defs. These are rare, forget about it. + return true; + PhysDef = Reg; + } + } + + if (PhysDef) { + MachineBasicBlock::iterator I = MI; I = llvm::next(I); + if (!isPhysDefTriviallyDead(PhysDef, I, MBB->end())) + return true; + } + return false; +} + +bool MachineCSE::isCSECandidate(MachineInstr *MI) { + // Ignore copies or instructions that read / write physical registers + // (except for dead defs of physical registers). + unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx; + if (TII->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) || + MI->isExtractSubreg() || MI->isInsertSubreg() || MI->isSubregToReg()) + return false; + + // Ignore stuff that we obviously can't move. + const TargetInstrDesc &TID = MI->getDesc(); + if (TID.mayStore() || TID.isCall() || TID.isTerminator() || + TID.hasUnmodeledSideEffects()) + return false; + + if (TID.mayLoad()) { + // Okay, this instruction does a load. As a refinement, we allow the target + // to decide whether the loaded value is actually a constant. If so, we can + // actually use it as a load. + if (!MI->isInvariantLoad(AA)) + // FIXME: we should be able to hoist loads with no other side effects if + // there are no other instructions which can change memory in this loop. + // This is a trivial form of alias analysis. + return false; + } + return true; +} + +bool MachineCSE::ProcessBlock(MachineDomTreeNode *Node) { + bool Changed = false; + + ScopedHashTableScope VNTS(VNT); + MachineBasicBlock *MBB = Node->getBlock(); + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ) { + MachineInstr *MI = &*I; + ++I; + + if (!isCSECandidate(MI)) + continue; + + bool FoundCSE = VNT.count(MI); + if (!FoundCSE) { + // Look for trivial copy coalescing opportunities. + if (PerformTrivialCoalescing(MI, MBB)) + FoundCSE = VNT.count(MI); + } + // FIXME: commute commutable instructions? + + // If the instruction defines a physical register and the value *may* be + // used, then it's not safe to replace it with a common subexpression. + if (FoundCSE && hasLivePhysRegDefUse(MI, MBB)) + FoundCSE = false; + + if (!FoundCSE) { + VNT.insert(MI, CurrVN++); + Exps.push_back(MI); + continue; + } + + // Found a common subexpression, eliminate it. + unsigned CSVN = VNT.lookup(MI); + MachineInstr *CSMI = Exps[CSVN]; + DEBUG(dbgs() << "Examining: " << *MI); + DEBUG(dbgs() << "*** Found a common subexpression: " << *CSMI); + unsigned NumDefs = MI->getDesc().getNumDefs(); + for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (!MO.isReg() || !MO.isDef()) + continue; + unsigned OldReg = MO.getReg(); + unsigned NewReg = CSMI->getOperand(i).getReg(); + if (OldReg == NewReg) + continue; + assert(TargetRegisterInfo::isVirtualRegister(OldReg) && + TargetRegisterInfo::isVirtualRegister(NewReg) && + "Do not CSE physical register defs!"); + MRI->replaceRegWith(OldReg, NewReg); + --NumDefs; + } + MI->eraseFromParent(); + ++NumCSEs; + } + + // Recursively call ProcessBlock with childred. + const std::vector &Children = Node->getChildren(); + for (unsigned i = 0, e = Children.size(); i != e; ++i) + Changed |= ProcessBlock(Children[i]); + + return Changed; +} + +bool MachineCSE::runOnMachineFunction(MachineFunction &MF) { + TII = MF.getTarget().getInstrInfo(); + TRI = MF.getTarget().getRegisterInfo(); + MRI = &MF.getRegInfo(); + DT = &getAnalysis(); + AA = &getAnalysis(); + return ProcessBlock(DT->getRootNode()); +} diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index f141c56770..4377d5bd71 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -95,6 +95,9 @@ MachineFunction::MachineFunction(Function *F, const TargetMachine &TM, MFInfo = 0; FrameInfo = new (Allocator.Allocate()) MachineFrameInfo(*TM.getFrameInfo()); + if (Fn->hasFnAttr(Attribute::StackAlignment)) + FrameInfo->setMaxAlignment(Attribute::getStackAlignmentFromAttrs( + Fn->getAttributes().getFnAttributes())); ConstantPool = new (Allocator.Allocate()) MachineConstantPool(TM.getTargetData()); Alignment = TM.getTargetLowering()->getFunctionAlignment(F); diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index df61c74576..e23670d1d1 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -18,6 +18,7 @@ #include "llvm/Type.h" #include "llvm/Value.h" #include "llvm/Assembly/Writer.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -305,7 +306,7 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { MachineMemOperand::MachineMemOperand(const Value *v, unsigned int f, int64_t o, uint64_t s, unsigned int a) : Offset(o), Size(s), V(v), - Flags((f & 7) | ((Log2_32(a) + 1) << 3)) { + Flags((f & ((1 << MOMaxBits) - 1)) | ((Log2_32(a) + 1) << MOMaxBits)) { assert(getBaseAlignment() == a && "Alignment is not a power of 2!"); assert((isLoad() || isStore()) && "Not a load/store!"); } @@ -327,7 +328,8 @@ void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) { if (MMO->getBaseAlignment() >= getBaseAlignment()) { // Update the alignment value. - Flags = (Flags & 7) | ((Log2_32(MMO->getBaseAlignment()) + 1) << 3); + Flags = (Flags & ((1 << MOMaxBits) - 1)) | + ((Log2_32(MMO->getBaseAlignment()) + 1) << MOMaxBits); // Also update the base and offset, because the new alignment may // not be applicable with the old ones. V = MMO->getValue(); @@ -700,6 +702,35 @@ void MachineInstr::addMemOperand(MachineFunction &MF, MemRefsEnd = NewMemRefsEnd; } +bool MachineInstr::isIdenticalTo(const MachineInstr *Other, + MICheckType Check) const { + // If opcodes or number of operands are not the same then the two + // instructions are obviously not identical. + if (Other->getOpcode() != getOpcode() || + Other->getNumOperands() != getNumOperands()) + return false; + + // Check operands to make sure they match. + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); + const MachineOperand &OMO = Other->getOperand(i); + // Clients may or may not want to ignore defs when testing for equality. + // For example, machine CSE pass only cares about finding common + // subexpressions, so it's safe to ignore virtual register defs. + if (Check != CheckDefs && MO.isReg() && MO.isDef()) { + if (Check == IgnoreDefs) + continue; + // Check == IgnoreVRegDefs + if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) || + TargetRegisterInfo::isPhysicalRegister(OMO.getReg())) + if (MO.getReg() != OMO.getReg()) + return false; + } else if (!MO.isIdenticalTo(OMO)) + return false; + } + return true; +} + /// removeFromParent - This method unlinks 'this' from the containing basic /// block, and returns it, but does not delete it. MachineInstr *MachineInstr::removeFromParent() { @@ -958,8 +989,8 @@ void MachineInstr::copyPredicates(const MachineInstr *MI) { /// SawStore is set to true, it means that there is a store (or call) between /// the instruction's location and its intended destination. bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, - bool &SawStore, - AliasAnalysis *AA) const { + AliasAnalysis *AA, + bool &SawStore) const { // Ignore stuff that we obviously can't move. if (TID->mayStore() || TID->isCall()) { SawStore = true; @@ -984,11 +1015,11 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, /// isSafeToReMat - Return true if it's safe to rematerialize the specified /// instruction which defined the specified register instead of copying it. bool MachineInstr::isSafeToReMat(const TargetInstrInfo *TII, - unsigned DstReg, - AliasAnalysis *AA) const { + AliasAnalysis *AA, + unsigned DstReg) const { bool SawStore = false; if (!TII->isTriviallyReMaterializable(this, AA) || - !isSafeToMove(TII, SawStore, AA)) + !isSafeToMove(TII, AA, SawStore)) return false; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { const MachineOperand &MO = getOperand(i); @@ -1324,3 +1355,48 @@ void MachineInstr::addRegisterDefined(unsigned IncomingReg, true /*IsDef*/, true /*IsImp*/)); } + +unsigned +MachineInstrExpressionTrait::getHashValue(const MachineInstr* const &MI) { + unsigned Hash = MI->getOpcode() * 37; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + uint64_t Key = (uint64_t)MO.getType() << 32; + switch (MO.getType()) { + default: break; + case MachineOperand::MO_Register: + if (MO.isDef() && MO.getReg() && + TargetRegisterInfo::isVirtualRegister(MO.getReg())) + continue; // Skip virtual register defs. + Key |= MO.getReg(); + break; + case MachineOperand::MO_Immediate: + Key |= MO.getImm(); + break; + case MachineOperand::MO_FrameIndex: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_JumpTableIndex: + Key |= MO.getIndex(); + break; + case MachineOperand::MO_MachineBasicBlock: + Key |= DenseMapInfo::getHashValue(MO.getMBB()); + break; + case MachineOperand::MO_GlobalAddress: + Key |= DenseMapInfo::getHashValue(MO.getGlobal()); + break; + case MachineOperand::MO_BlockAddress: + Key |= DenseMapInfo::getHashValue(MO.getBlockAddress()); + break; + } + Key += ~(Key << 32); + Key ^= (Key >> 22); + Key += ~(Key << 13); + Key ^= (Key >> 8); + Key += (Key << 3); + Key ^= (Key >> 15); + Key += ~(Key << 27); + Key ^= (Key >> 31); + Hash = (unsigned)Key + Hash * 37; + } + return Hash; +} diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index 92c84f3e83..0361694d66 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -252,32 +252,6 @@ bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) { return false; } - DEBUG({ - dbgs() << "--- Checking if we can hoist " << I; - if (I.getDesc().getImplicitUses()) { - dbgs() << " * Instruction has implicit uses:\n"; - - const TargetRegisterInfo *TRI = TM->getRegisterInfo(); - for (const unsigned *ImpUses = I.getDesc().getImplicitUses(); - *ImpUses; ++ImpUses) - dbgs() << " -> " << TRI->getName(*ImpUses) << "\n"; - } - - if (I.getDesc().getImplicitDefs()) { - dbgs() << " * Instruction has implicit defines:\n"; - - const TargetRegisterInfo *TRI = TM->getRegisterInfo(); - for (const unsigned *ImpDefs = I.getDesc().getImplicitDefs(); - *ImpDefs; ++ImpDefs) - dbgs() << " -> " << TRI->getName(*ImpDefs) << "\n"; - } - }); - - if (I.getDesc().getImplicitDefs() || I.getDesc().getImplicitUses()) { - DEBUG(dbgs() << "Cannot hoist with implicit defines or uses\n"); - return false; - } - // The instruction is loop invariant if all of its operands are. for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { const MachineOperand &MO = I.getOperand(i); @@ -311,6 +285,10 @@ bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) { } else if (!MO.isDead()) { // A def that isn't dead. We can't move it. return false; + } else if (CurLoop->getHeader()->isLiveIn(Reg)) { + // If the reg is live into the loop, we can't hoist an instruction + // which would clobber it. + return false; } } @@ -467,7 +445,7 @@ MachineLICM::LookForDuplicate(const MachineInstr *MI, std::vector &PrevMIs) { for (unsigned i = 0, e = PrevMIs.size(); i != e; ++i) { const MachineInstr *PrevMI = PrevMIs[i]; - if (TII->isIdentical(MI, PrevMI, RegInfo)) + if (TII->produceSameValue(MI, PrevMI)) return PrevMI; } return 0; @@ -480,9 +458,20 @@ bool MachineLICM::EliminateCSE(MachineInstr *MI, if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second)) { DEBUG(dbgs() << "CSEing " << *MI << " with " << *Dup); + + // Replace virtual registers defined by MI by their counterparts defined + // by Dup. for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isDef()) + + // Physical registers may not differ here. + assert((!MO.isReg() || MO.getReg() == 0 || + !TargetRegisterInfo::isPhysicalRegister(MO.getReg()) || + MO.getReg() == Dup->getOperand(i).getReg()) && + "Instructions with different phys regs are not identical!"); + + if (MO.isReg() && MO.isDef() && + !TargetRegisterInfo::isPhysicalRegister(MO.getReg())) RegInfo->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg()); } MI->eraseFromParent(); diff --git a/lib/CodeGen/MachineModuleInfoImpls.cpp b/lib/CodeGen/MachineModuleInfoImpls.cpp index 837890669b..39d2c7504f 100644 --- a/lib/CodeGen/MachineModuleInfoImpls.cpp +++ b/lib/CodeGen/MachineModuleInfoImpls.cpp @@ -22,7 +22,7 @@ using namespace llvm; // Out of line virtual method. void MachineModuleInfoMachO::Anchor() {} - +void MachineModuleInfoELF::Anchor() {} static int SortSymbolPair(const void *LHS, const void *RHS) { const MCSymbol *LHSS = @@ -34,10 +34,11 @@ static int SortSymbolPair(const void *LHS, const void *RHS) { /// GetSortedStubs - Return the entries from a DenseMap in a deterministic /// sorted orer. -MachineModuleInfoMachO::SymbolListTy -MachineModuleInfoMachO::GetSortedStubs(const DenseMap &Map) { - MachineModuleInfoMachO::SymbolListTy List(Map.begin(), Map.end()); +MachineModuleInfoImpl::SymbolListTy +MachineModuleInfoImpl::GetSortedStubs(const DenseMap &Map) { + MachineModuleInfoImpl::SymbolListTy List(Map.begin(), Map.end()); + if (!List.empty()) qsort(&List[0], List.size(), sizeof(List[0]), SortSymbolPair); return List; diff --git a/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp index b31973e04f..d9ab6773a5 100644 --- a/lib/CodeGen/MachineRegisterInfo.cpp +++ b/lib/CodeGen/MachineRegisterInfo.cpp @@ -116,6 +116,19 @@ MachineInstr *MachineRegisterInfo::getVRegDef(unsigned Reg) const { return 0; } +bool MachineRegisterInfo::hasOneUse(unsigned RegNo) const { + use_iterator UI = use_begin(RegNo); + if (UI == use_end()) + return false; + return ++UI == use_end(); +} + +bool MachineRegisterInfo::hasOneNonDBGUse(unsigned RegNo) const { + use_nodbg_iterator UI = use_nodbg_begin(RegNo); + if (UI == use_nodbg_end()) + return false; + return ++UI == use_nodbg_end(); +} #ifndef NDEBUG void MachineRegisterInfo::dumpUses(unsigned Reg) const { diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp index c391576164..e47ba7c2cc 100644 --- a/lib/CodeGen/MachineSink.cpp +++ b/lib/CodeGen/MachineSink.cpp @@ -72,8 +72,13 @@ bool MachineSinking::AllUsesDominatedByBlock(unsigned Reg, MachineBasicBlock *MBB) const { assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Only makes sense for vregs"); - for (MachineRegisterInfo::use_iterator I = RegInfo->use_begin(Reg), - E = RegInfo->use_end(); I != E; ++I) { + // Ignoring debug uses is necessary so debug info doesn't affect the code. + // This may leave a referencing dbg_value in the original block, before + // the definition of the vreg. Dwarf generator handles this although the + // user might not get the right info at runtime. + for (MachineRegisterInfo::use_nodbg_iterator I = + RegInfo->use_nodbg_begin(Reg), + E = RegInfo->use_nodbg_end(); I != E; ++I) { // Determine the block of the use. MachineInstr *UseInst = &*I; MachineBasicBlock *UseBlock = UseInst->getParent(); @@ -135,7 +140,10 @@ bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { ProcessedBegin = I == MBB.begin(); if (!ProcessedBegin) --I; - + + if (MI->isDebugValue()) + continue; + if (SinkInstruction(MI, SawStore)) ++NumSunk, MadeChange = true; @@ -149,7 +157,7 @@ bool MachineSinking::ProcessBlock(MachineBasicBlock &MBB) { /// instruction out of its current block into a successor. bool MachineSinking::SinkInstruction(MachineInstr *MI, bool &SawStore) { // Check if it's safe to move the instruction. - if (!MI->isSafeToMove(TII, SawStore, AA)) + if (!MI->isSafeToMove(TII, AA, SawStore)) return false; // FIXME: This should include support for sinking instructions within the diff --git a/lib/CodeGen/OptimizePHIs.cpp b/lib/CodeGen/OptimizePHIs.cpp new file mode 100644 index 0000000000..2717d4d5ce --- /dev/null +++ b/lib/CodeGen/OptimizePHIs.cpp @@ -0,0 +1,189 @@ +//===-- OptimizePHIs.cpp - Optimize machine instruction PHIs --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass optimizes machine instruction PHIs to take advantage of +// opportunities created during DAG legalization. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "phi-opt" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Function.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +STATISTIC(NumPHICycles, "Number of PHI cycles replaced"); +STATISTIC(NumDeadPHICycles, "Number of dead PHI cycles"); + +namespace { + class OptimizePHIs : public MachineFunctionPass { + MachineRegisterInfo *MRI; + const TargetInstrInfo *TII; + + public: + static char ID; // Pass identification + OptimizePHIs() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + } + + private: + typedef SmallPtrSet InstrSet; + typedef SmallPtrSetIterator InstrSetIterator; + + bool IsSingleValuePHICycle(MachineInstr *MI, unsigned &SingleValReg, + InstrSet &PHIsInCycle); + bool IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle); + bool OptimizeBB(MachineBasicBlock &MBB); + }; +} + +char OptimizePHIs::ID = 0; +static RegisterPass +X("opt-phis", "Optimize machine instruction PHIs"); + +FunctionPass *llvm::createOptimizePHIsPass() { return new OptimizePHIs(); } + +bool OptimizePHIs::runOnMachineFunction(MachineFunction &Fn) { + MRI = &Fn.getRegInfo(); + TII = Fn.getTarget().getInstrInfo(); + + // Find dead PHI cycles and PHI cycles that can be replaced by a single + // value. InstCombine does these optimizations, but DAG legalization may + // introduce new opportunities, e.g., when i64 values are split up for + // 32-bit targets. + bool Changed = false; + for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) + Changed |= OptimizeBB(*I); + + return Changed; +} + +/// IsSingleValuePHICycle - Check if MI is a PHI where all the source operands +/// are copies of SingleValReg, possibly via copies through other PHIs. If +/// SingleValReg is zero on entry, it is set to the register with the single +/// non-copy value. PHIsInCycle is a set used to keep track of the PHIs that +/// have been scanned. +bool OptimizePHIs::IsSingleValuePHICycle(MachineInstr *MI, + unsigned &SingleValReg, + InstrSet &PHIsInCycle) { + assert(MI->isPHI() && "IsSingleValuePHICycle expects a PHI instruction"); + unsigned DstReg = MI->getOperand(0).getReg(); + + // See if we already saw this register. + if (!PHIsInCycle.insert(MI)) + return true; + + // Don't scan crazily complex things. + if (PHIsInCycle.size() == 16) + return false; + + // Scan the PHI operands. + for (unsigned i = 1; i != MI->getNumOperands(); i += 2) { + unsigned SrcReg = MI->getOperand(i).getReg(); + if (SrcReg == DstReg) + continue; + MachineInstr *SrcMI = MRI->getVRegDef(SrcReg); + + // Skip over register-to-register moves. + unsigned MvSrcReg, MvDstReg, SrcSubIdx, DstSubIdx; + if (SrcMI && + TII->isMoveInstr(*SrcMI, MvSrcReg, MvDstReg, SrcSubIdx, DstSubIdx) && + SrcSubIdx == 0 && DstSubIdx == 0 && + TargetRegisterInfo::isVirtualRegister(MvSrcReg)) + SrcMI = MRI->getVRegDef(MvSrcReg); + if (!SrcMI) + return false; + + if (SrcMI->isPHI()) { + if (!IsSingleValuePHICycle(SrcMI, SingleValReg, PHIsInCycle)) + return false; + } else { + // Fail if there is more than one non-phi/non-move register. + if (SingleValReg != 0) + return false; + SingleValReg = SrcReg; + } + } + return true; +} + +/// IsDeadPHICycle - Check if the register defined by a PHI is only used by +/// other PHIs in a cycle. +bool OptimizePHIs::IsDeadPHICycle(MachineInstr *MI, InstrSet &PHIsInCycle) { + assert(MI->isPHI() && "IsDeadPHICycle expects a PHI instruction"); + unsigned DstReg = MI->getOperand(0).getReg(); + assert(TargetRegisterInfo::isVirtualRegister(DstReg) && + "PHI destination is not a virtual register"); + + // See if we already saw this register. + if (!PHIsInCycle.insert(MI)) + return true; + + // Don't scan crazily complex things. + if (PHIsInCycle.size() == 16) + return false; + + for (MachineRegisterInfo::use_iterator I = MRI->use_begin(DstReg), + E = MRI->use_end(); I != E; ++I) { + MachineInstr *UseMI = &*I; + if (!UseMI->isPHI() || !IsDeadPHICycle(UseMI, PHIsInCycle)) + return false; + } + + return true; +} + +/// OptimizeBB - Remove dead PHI cycles and PHI cycles that can be replaced by +/// a single value. +bool OptimizePHIs::OptimizeBB(MachineBasicBlock &MBB) { + bool Changed = false; + for (MachineBasicBlock::iterator + MII = MBB.begin(), E = MBB.end(); MII != E; ) { + MachineInstr *MI = &*MII++; + if (!MI->isPHI()) + break; + + // Check for single-value PHI cycles. + unsigned SingleValReg = 0; + InstrSet PHIsInCycle; + if (IsSingleValuePHICycle(MI, SingleValReg, PHIsInCycle) && + SingleValReg != 0) { + MRI->replaceRegWith(MI->getOperand(0).getReg(), SingleValReg); + MI->eraseFromParent(); + ++NumPHICycles; + Changed = true; + continue; + } + + // Check for dead PHI cycles. + PHIsInCycle.clear(); + if (IsDeadPHICycle(MI, PHIsInCycle)) { + for (InstrSetIterator PI = PHIsInCycle.begin(), PE = PHIsInCycle.end(); + PI != PE; ++PI) { + MachineInstr *PhiMI = *PI; + if (&*MII == PhiMI) + ++MII; + PhiMI->eraseFromParent(); + } + ++NumDeadPHICycles; + Changed = true; + } + } + return Changed; +} diff --git a/lib/CodeGen/PBQP/HeuristicSolver.h b/lib/CodeGen/PBQP/HeuristicSolver.h index b48f548950..bd18b5216f 100644 --- a/lib/CodeGen/PBQP/HeuristicSolver.h +++ b/lib/CodeGen/PBQP/HeuristicSolver.h @@ -18,7 +18,6 @@ #include "Graph.h" #include "Solution.h" -#include "llvm/Support/raw_ostream.h" #include #include @@ -230,7 +229,7 @@ namespace PBQP { } /// \brief Apply rule R1. - /// @param nItr Node iterator for node to apply R1 to. + /// @param xnItr Node iterator for node to apply R1 to. /// /// Node will be automatically pushed to the solver stack. void applyR1(Graph::NodeItr xnItr) { @@ -278,7 +277,7 @@ namespace PBQP { } /// \brief Apply rule R2. - /// @param nItr Node iterator for node to apply R2 to. + /// @param xnItr Node iterator for node to apply R2 to. /// /// Node will be automatically pushed to the solver stack. void applyR2(Graph::NodeItr xnItr) { @@ -494,14 +493,23 @@ namespace PBQP { bool tryNormaliseEdgeMatrix(Graph::EdgeItr &eItr) { + const PBQPNum infinity = std::numeric_limits::infinity(); + Matrix &edgeCosts = g.getEdgeCosts(eItr); Vector &uCosts = g.getNodeCosts(g.getEdgeNode1(eItr)), &vCosts = g.getNodeCosts(g.getEdgeNode2(eItr)); for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { - PBQPNum rowMin = edgeCosts.getRowMin(r); + PBQPNum rowMin = infinity; + + for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { + if (vCosts[c] != infinity && edgeCosts[r][c] < rowMin) + rowMin = edgeCosts[r][c]; + } + uCosts[r] += rowMin; - if (rowMin != std::numeric_limits::infinity()) { + + if (rowMin != infinity) { edgeCosts.subFromRow(r, rowMin); } else { @@ -510,9 +518,16 @@ namespace PBQP { } for (unsigned c = 0; c < edgeCosts.getCols(); ++c) { - PBQPNum colMin = edgeCosts.getColMin(c); + PBQPNum colMin = infinity; + + for (unsigned r = 0; r < edgeCosts.getRows(); ++r) { + if (uCosts[r] != infinity && edgeCosts[r][c] < colMin) + colMin = edgeCosts[r][c]; + } + vCosts[c] += colMin; - if (colMin != std::numeric_limits::infinity()) { + + if (colMin != infinity) { edgeCosts.subFromCol(c, colMin); } else { diff --git a/lib/CodeGen/PBQP/Heuristics/Briggs.h b/lib/CodeGen/PBQP/Heuristics/Briggs.h index c09ad74b19..30d34d9e3e 100644 --- a/lib/CodeGen/PBQP/Heuristics/Briggs.h +++ b/lib/CodeGen/PBQP/Heuristics/Briggs.h @@ -128,14 +128,7 @@ namespace PBQP { /// selected for heuristic reduction instead. bool shouldOptimallyReduce(Graph::NodeItr nItr) { if (getSolver().getSolverDegree(nItr) < 3) { - if (getGraph().getNodeCosts(nItr)[0] != - std::numeric_limits::infinity()) { - return true; - } - // Otherwise we have an infinite spill cost node. - initializeNode(nItr); - NodeData &nd = getHeuristicNodeData(nItr); - return nd.isAllocable; + return true; } // else return false; diff --git a/lib/CodeGen/PHIElimination.cpp b/lib/CodeGen/PHIElimination.cpp index b740c68f59..8bbe0a7252 100644 --- a/lib/CodeGen/PHIElimination.cpp +++ b/lib/CodeGen/PHIElimination.cpp @@ -55,8 +55,6 @@ void llvm::PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const { bool llvm::PHIElimination::runOnMachineFunction(MachineFunction &Fn) { MRI = &Fn.getRegInfo(); - PHIDefs.clear(); - PHIKills.clear(); bool Changed = false; // Split critical edges to help the coalescer @@ -215,10 +213,6 @@ void llvm::PHIElimination::LowerAtomicPHINode( TII->copyRegToReg(MBB, AfterPHIsIt, DestReg, IncomingReg, RC, RC); } - // Record PHI def. - assert(!hasPHIDef(DestReg) && "Vreg has multiple phi-defs?"); - PHIDefs[DestReg] = &MBB; - // Update live variable information if there is any. LiveVariables *LV = getAnalysisIfAvailable(); if (LV) { @@ -229,6 +223,7 @@ void llvm::PHIElimination::LowerAtomicPHINode( // Increment use count of the newly created virtual register. VI.NumUses++; + LV->setPHIJoin(IncomingReg); // When we are reusing the incoming register, it may already have been // killed in this block. The old kill will also have been inserted at @@ -276,9 +271,6 @@ void llvm::PHIElimination::LowerAtomicPHINode( // path the PHI. MachineBasicBlock &opBlock = *MPhi->getOperand(i*2+2).getMBB(); - // Record the kill. - PHIKills[SrcReg].insert(&opBlock); - // If source is defined by an implicit def, there is no need to insert a // copy. MachineInstr *DefMI = MRI->getVRegDef(SrcReg); @@ -451,34 +443,3 @@ MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A, return NMBB; } - -unsigned -PHIElimination::PHINodeTraits::getHashValue(const MachineInstr *MI) { - if (!MI || MI==getEmptyKey() || MI==getTombstoneKey()) - return DenseMapInfo::getHashValue(MI); - unsigned hash = 0; - for (unsigned ni = 1, ne = MI->getNumOperands(); ni != ne; ni += 2) - hash = hash*37 + DenseMapInfo:: - getHashValue(BBVRegPair(MI->getOperand(ni+1).getMBB()->getNumber(), - MI->getOperand(ni).getReg())); - return hash; -} - -bool PHIElimination::PHINodeTraits::isEqual(const MachineInstr *LHS, - const MachineInstr *RHS) { - const MachineInstr *EmptyKey = getEmptyKey(); - const MachineInstr *TombstoneKey = getTombstoneKey(); - if (!LHS || !RHS || LHS==EmptyKey || RHS==EmptyKey || - LHS==TombstoneKey || RHS==TombstoneKey) - return LHS==RHS; - - unsigned ne = LHS->getNumOperands(); - if (ne != RHS->getNumOperands()) - return false; - // Ignore operand 0, the defined register. - for (unsigned ni = 1; ni != ne; ni += 2) - if (LHS->getOperand(ni).getReg() != RHS->getOperand(ni).getReg() || - LHS->getOperand(ni+1).getMBB() != RHS->getOperand(ni+1).getMBB()) - return false; - return true; -} diff --git a/lib/CodeGen/PHIElimination.h b/lib/CodeGen/PHIElimination.h index 895aaa4115..7dedf0318a 100644 --- a/lib/CodeGen/PHIElimination.h +++ b/lib/CodeGen/PHIElimination.h @@ -22,17 +22,8 @@ namespace llvm { /// Lower PHI instructions to copies. class PHIElimination : public MachineFunctionPass { MachineRegisterInfo *MRI; // Machine register information - private: - - typedef SmallSet PHIKillList; - typedef DenseMap PHIKillMap; - typedef DenseMap PHIDefMap; public: - - typedef PHIKillList::iterator phi_kill_iterator; - typedef PHIKillList::const_iterator const_phi_kill_iterator; - static char ID; // Pass identification, replacement for typeid PHIElimination() : MachineFunctionPass(&ID) {} @@ -40,38 +31,6 @@ namespace llvm { virtual void getAnalysisUsage(AnalysisUsage &AU) const; - /// Return true if the given vreg was defined by a PHI intsr prior to - /// lowering. - bool hasPHIDef(unsigned vreg) const { - return PHIDefs.count(vreg); - } - - /// Returns the block in which the PHI instruction which defined the - /// given vreg used to reside. - MachineBasicBlock* getPHIDefBlock(unsigned vreg) { - PHIDefMap::iterator phiDefItr = PHIDefs.find(vreg); - assert(phiDefItr != PHIDefs.end() && "vreg has no phi-def."); - return phiDefItr->second; - } - - /// Returns true if the given vreg was killed by a PHI instr. - bool hasPHIKills(unsigned vreg) const { - return PHIKills.count(vreg); - } - - /// Returns an iterator over the BasicBlocks which contained PHI - /// kills of this register prior to lowering. - phi_kill_iterator phiKillsBegin(unsigned vreg) { - PHIKillMap::iterator phiKillItr = PHIKills.find(vreg); - assert(phiKillItr != PHIKills.end() && "vreg has no phi-kills."); - return phiKillItr->second.begin(); - } - phi_kill_iterator phiKillsEnd(unsigned vreg) { - PHIKillMap::iterator phiKillItr = PHIKills.find(vreg); - assert(phiKillItr != PHIKills.end() && "vreg has no phi-kills."); - return phiKillItr->second.end(); - } - private: /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions /// in predecessor basic blocks. @@ -109,12 +68,29 @@ namespace llvm { // SkipPHIsAndLabels - Copies need to be inserted after phi nodes and // also after any exception handling labels: in landing pads execution // starts at the label, so any copies placed before it won't be executed! + // We also deal with DBG_VALUEs, which are a bit tricky: + // PHI + // DBG_VALUE + // LABEL + // Here the DBG_VALUE needs to be skipped, and if it refers to a PHI it + // needs to be annulled or, better, moved to follow the label, as well. + // PHI + // DBG_VALUE + // no label + // Here it is not a good idea to skip the DBG_VALUE. + // FIXME: For now we skip and annul all DBG_VALUEs, maximally simple and + // maximally stupid. MachineBasicBlock::iterator SkipPHIsAndLabels(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) { // Rather than assuming that EH labels come before other kinds of labels, // just skip all labels. - while (I != MBB.end() && (I->isPHI() || I->isLabel())) + while (I != MBB.end() && + (I->isPHI() || I->isLabel() || I->isDebugValue())) { + if (I->isDebugValue() && I->getNumOperands()==3 && + I->getOperand(0).isReg()) + I->getOperand(0).setReg(0U); ++I; + } return I; } @@ -122,21 +98,13 @@ namespace llvm { typedef DenseMap VRegPHIUse; VRegPHIUse VRegPHIUseCount; - PHIDefMap PHIDefs; - PHIKillMap PHIKills; // Defs of PHI sources which are implicit_def. SmallPtrSet ImpDefs; - // Lowered PHI nodes may be reused. We provide special DenseMap traits to - // match PHI nodes with identical arguments. - struct PHINodeTraits : public DenseMapInfo { - static unsigned getHashValue(const MachineInstr *PtrVal); - static bool isEqual(const MachineInstr *LHS, const MachineInstr *RHS); - }; - // Map reusable lowered PHI node -> incoming join register. - typedef DenseMap LoweredPHIMap; + typedef DenseMap LoweredPHIMap; LoweredPHIMap LoweredPHIs; }; diff --git a/lib/CodeGen/Passes.cpp b/lib/CodeGen/Passes.cpp index f67eb79be3..5ea2941b48 100644 --- a/lib/CodeGen/Passes.cpp +++ b/lib/CodeGen/Passes.cpp @@ -34,7 +34,7 @@ static cl::opt > RegAlloc("regalloc", cl::init(&createLinearScanRegisterAllocator), - cl::desc("Register allocator to use: (default = linearscan)")); + cl::desc("Register allocator to use (default=linearscan)")); //===---------------------------------------------------------------------===// diff --git a/lib/CodeGen/PostRASchedulerList.cpp b/lib/CodeGen/PostRASchedulerList.cpp index f43395fa2e..424181c025 100644 --- a/lib/CodeGen/PostRASchedulerList.cpp +++ b/lib/CodeGen/PostRASchedulerList.cpp @@ -460,6 +460,8 @@ void SchedulePostRATDList::FixupKills(MachineBasicBlock *MBB) { for (MachineBasicBlock::iterator I = MBB->end(), E = MBB->begin(); I != E; --Count) { MachineInstr *MI = --I; + if (MI->isDebugValue()) + continue; // Update liveness. Registers that are defed but not used in this // instruction are now dead. Mark register and all subregs as they diff --git a/lib/CodeGen/ProcessImplicitDefs.cpp b/lib/CodeGen/ProcessImplicitDefs.cpp index e3df2e42cf..d7179b3e59 100644 --- a/lib/CodeGen/ProcessImplicitDefs.cpp +++ b/lib/CodeGen/ProcessImplicitDefs.cpp @@ -205,10 +205,9 @@ bool ProcessImplicitDefs::runOnMachineFunction(MachineFunction &fn) { // Process each use instruction once. for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(Reg), UE = mri_->use_end(); UI != UE; ++UI) { - MachineInstr *RMI = &*UI; - MachineBasicBlock *RMBB = RMI->getParent(); - if (RMBB == MBB) + if (UI.getOperand().isUndef()) continue; + MachineInstr *RMI = &*UI; if (ModInsts.insert(RMI)) RUses.push_back(RMI); } diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 036f59a2a5..138e711030 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -175,9 +175,10 @@ void PEI::calculateCallsInformation(MachineFunction &Fn) { MachineBasicBlock::iterator I = *i; // If call frames are not being included as part of the stack frame, and - // there is no dynamic allocation (therefore referencing frame slots off - // sp), leave the pseudo ops alone. We'll eliminate them later. - if (RegInfo->hasReservedCallFrame(Fn) || RegInfo->hasFP(Fn)) + // the target doesn't indicate otherwise, remove the call frame pseudos + // here. The sub/add sp instruction pairs are still inserted, but we don't + // need to track the SP adjustment for frame index elimination. + if (RegInfo->canSimplifyCallFramePseudos(Fn)) RegInfo->eliminateCallFramePseudoInstr(Fn, *I->getParent(), I); } } @@ -476,8 +477,6 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // Loop over all of the stack objects, assigning sequential addresses... MachineFrameInfo *FFI = Fn.getFrameInfo(); - unsigned MaxAlign = 1; - // Start at the beginning of the local area. // The Offset is the distance from the stack top in the direction // of stack growth -- so it's always nonnegative. @@ -517,9 +516,6 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { Offset += FFI->getObjectSize(i); unsigned Align = FFI->getObjectAlignment(i); - // If the alignment of this object is greater than that of the stack, - // then increase the stack alignment to match. - MaxAlign = std::max(MaxAlign, Align); // Adjust to alignment boundary Offset = (Offset+Align-1)/Align*Align; @@ -529,9 +525,6 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { int MaxCSFI = MaxCSFrameIndex, MinCSFI = MinCSFrameIndex; for (int i = MaxCSFI; i >= MinCSFI ; --i) { unsigned Align = FFI->getObjectAlignment(i); - // If the alignment of this object is greater than that of the stack, - // then increase the stack alignment to match. - MaxAlign = std::max(MaxAlign, Align); // Adjust to alignment boundary Offset = (Offset+Align-1)/Align*Align; @@ -540,6 +533,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { } } + unsigned MaxAlign = FFI->getMaxAlignment(); + // Make sure the special register scavenging spill slot is closest to the // frame pointer if a frame pointer is required. const TargetRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo(); @@ -605,11 +600,6 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // Update frame info to pretend that this is part of the stack... FFI->setStackSize(Offset - LocalAreaOffset); - - // Remember the required stack alignment in case targets need it to perform - // dynamic stack alignment. - if (MaxAlign > FFI->getMaxAlignment()) - FFI->setMaxAlignment(MaxAlign); } diff --git a/lib/CodeGen/PseudoSourceValue.cpp b/lib/CodeGen/PseudoSourceValue.cpp index 7fb3e6e6d2..5e86e5a944 100644 --- a/lib/CodeGen/PseudoSourceValue.cpp +++ b/lib/CodeGen/PseudoSourceValue.cpp @@ -18,19 +18,38 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/System/Mutex.h" #include using namespace llvm; -static ManagedStatic PSVs; +namespace { +struct PSVGlobalsTy { + // PseudoSourceValues are immutable so don't need locking. + const PseudoSourceValue PSVs[4]; + sys::Mutex Lock; // Guards FSValues, but not the values inside it. + std::map FSValues; + + PSVGlobalsTy() : PSVs() {} + ~PSVGlobalsTy() { + for (std::map::iterator + I = FSValues.begin(), E = FSValues.end(); I != E; ++I) { + delete I->second; + } + } +}; + +static ManagedStatic PSVGlobals; + +} // anonymous namespace const PseudoSourceValue *PseudoSourceValue::getStack() -{ return &(*PSVs)[0]; } +{ return &PSVGlobals->PSVs[0]; } const PseudoSourceValue *PseudoSourceValue::getGOT() -{ return &(*PSVs)[1]; } +{ return &PSVGlobals->PSVs[1]; } const PseudoSourceValue *PseudoSourceValue::getJumpTable() -{ return &(*PSVs)[2]; } +{ return &PSVGlobals->PSVs[2]; } const PseudoSourceValue *PseudoSourceValue::getConstantPool() -{ return &(*PSVs)[3]; } +{ return &PSVGlobals->PSVs[3]; } static const char *const PSVNames[] = { "Stack", @@ -48,13 +67,13 @@ PseudoSourceValue::PseudoSourceValue(enum ValueTy Subclass) : Subclass) {} void PseudoSourceValue::printCustom(raw_ostream &O) const { - O << PSVNames[this - *PSVs]; + O << PSVNames[this - PSVGlobals->PSVs]; } -static ManagedStatic > FSValues; - const PseudoSourceValue *PseudoSourceValue::getFixedStack(int FI) { - const PseudoSourceValue *&V = (*FSValues)[FI]; + PSVGlobalsTy &PG = *PSVGlobals; + sys::ScopedLock locked(PG.Lock); + const PseudoSourceValue *&V = PG.FSValues[FI]; if (!V) V = new FixedStackPseudoSourceValue(FI); return V; diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index 8e44a576d6..5c5a394cc0 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -334,10 +334,6 @@ namespace { SmallVector &inactiveCounts, bool SkipDGRegs); - /// assignVirt2StackSlot - assigns this virtual register to a - /// stack slot. returns the stack slot - int assignVirt2StackSlot(unsigned virtReg); - void ComputeRelatedRegClasses(); template diff --git a/lib/CodeGen/RegAllocLocal.cpp b/lib/CodeGen/RegAllocLocal.cpp index 4d2e3a318b..04303cff5b 100644 --- a/lib/CodeGen/RegAllocLocal.cpp +++ b/lib/CodeGen/RegAllocLocal.cpp @@ -490,9 +490,12 @@ MachineInstr *RALocal::reloadVirtReg(MachineBasicBlock &MBB, MachineInstr *MI, // If the virtual register is already available, just update the instruction // and return. if (unsigned PR = getVirt2PhysRegMapSlot(VirtReg)) { - MarkPhysRegRecentlyUsed(PR); // Already have this value available! MI->getOperand(OpNum).setReg(PR); // Assign the input register - getVirtRegLastUse(VirtReg) = std::make_pair(MI, OpNum); + if (!MI->isDebugValue()) { + // Do not do these for DBG_VALUE as they can affect codegen. + MarkPhysRegRecentlyUsed(PR); // Already have this value available! + getVirtRegLastUse(VirtReg) = std::make_pair(MI, OpNum); + } return MI; } @@ -609,6 +612,8 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) { DenseMap > LastUseDef; for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E; ++I) { + if (I->isDebugValue()) + continue; for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { MachineOperand& MO = I->getOperand(i); // Uses don't trigger any flags, but we need to save @@ -691,7 +696,13 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) { bool usedOutsideBlock = isPhysReg ? false : UsedInMultipleBlocks.test(MO.getReg() - TargetRegisterInfo::FirstVirtualRegister); - if (!isPhysReg && !usedOutsideBlock) + if (!isPhysReg && !usedOutsideBlock) { + // DBG_VALUE complicates this: if the only refs of a register outside + // this block are DBG_VALUE, we can't keep the reg live just for that, + // as it will cause the reg to be spilled at the end of this block when + // it wouldn't have been otherwise. Nullify the DBG_VALUEs when that + // happens. + bool UsedByDebugValueOnly = false; for (MachineRegisterInfo::reg_iterator UI = MRI.reg_begin(MO.getReg()), UE = MRI.reg_end(); UI != UE; ++UI) // Two cases: @@ -699,12 +710,26 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) { // - used in the same block before it is defined (loop) if (UI->getParent() != &MBB || (MO.isDef() && UI.getOperand().isUse() && precedes(&*UI, MI))) { + if (UI->isDebugValue()) { + UsedByDebugValueOnly = true; + continue; + } + // A non-DBG_VALUE use means we can leave DBG_VALUE uses alone. UsedInMultipleBlocks.set(MO.getReg() - TargetRegisterInfo::FirstVirtualRegister); usedOutsideBlock = true; + UsedByDebugValueOnly = false; break; } - + if (UsedByDebugValueOnly) + for (MachineRegisterInfo::reg_iterator UI = MRI.reg_begin(MO.getReg()), + UE = MRI.reg_end(); UI != UE; ++UI) + if (UI->isDebugValue() && + (UI->getParent() != &MBB || + (MO.isDef() && precedes(&*UI, MI)))) + UI.getOperand().setReg(0U); + } + // Physical registers and those that are not live-out of the block // are killed/dead at their last use/def within this block. if (isPhysReg || !usedOutsideBlock) { diff --git a/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp index 2701fafbf9..81cfd8f0bb 100644 --- a/lib/CodeGen/RegAllocPBQP.cpp +++ b/lib/CodeGen/RegAllocPBQP.cpp @@ -57,7 +57,7 @@ using namespace llvm; static RegisterRegAlloc -registerPBQPRepAlloc("pbqp", "PBQP register allocator.", +registerPBQPRepAlloc("pbqp", "PBQP register allocator", llvm::createPBQPRegisterAllocator); static cl::opt @@ -867,10 +867,6 @@ bool PBQPRegAlloc::runOnMachineFunction(MachineFunction &MF) { // Find the vreg intervals in need of allocation. findVRegIntervalsToAlloc(); - // If there aren't any then we're done here. - if (vregIntervalsToAlloc.empty() && emptyVRegIntervals.empty()) - return true; - // If there are non-empty intervals allocate them using pbqp. if (!vregIntervalsToAlloc.empty()) { diff --git a/lib/CodeGen/ScheduleDAGInstrs.cpp b/lib/CodeGen/ScheduleDAGInstrs.cpp index 56dd533459..badf34e66c 100644 --- a/lib/CodeGen/ScheduleDAGInstrs.cpp +++ b/lib/CodeGen/ScheduleDAGInstrs.cpp @@ -72,7 +72,7 @@ static const Value *getUnderlyingObjectFromInt(const Value *V) { } else { return V; } - assert(isa(V->getType()) && "Unexpected operand type!"); + assert(V->getType()->isIntegerTy() && "Unexpected operand type!"); } while (1); } @@ -87,7 +87,7 @@ static const Value *getUnderlyingObject(const Value *V) { break; const Value *O = getUnderlyingObjectFromInt(cast(V)->getOperand(0)); // If that succeeded in finding a pointer, continue the search. - if (!isa(O->getType())) + if (!O->getType()->isPointerTy()) break; V = O; } while (1); diff --git a/lib/CodeGen/SelectionDAG/Android.mk b/lib/CodeGen/SelectionDAG/Android.mk new file mode 100644 index 0000000000..eb15a1856c --- /dev/null +++ b/lib/CodeGen/SelectionDAG/Android.mk @@ -0,0 +1,48 @@ +LOCAL_PATH:= $(call my-dir) + +codegen_selectiondag_SRC_FILES := \ + CallingConvLower.cpp \ + DAGCombiner.cpp \ + FastISel.cpp \ + FunctionLoweringInfo.cpp \ + InstrEmitter.cpp \ + LegalizeDAG.cpp \ + LegalizeFloatTypes.cpp \ + LegalizeIntegerTypes.cpp \ + LegalizeTypes.cpp \ + LegalizeTypesGeneric.cpp \ + LegalizeVectorOps.cpp \ + LegalizeVectorTypes.cpp \ + ScheduleDAGFast.cpp \ + ScheduleDAGList.cpp \ + ScheduleDAGRRList.cpp \ + ScheduleDAGSDNodes.cpp \ + SelectionDAG.cpp \ + SelectionDAGBuilder.cpp \ + SelectionDAGISel.cpp \ + SelectionDAGPrinter.cpp \ + TargetLowering.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(codegen_selectiondag_SRC_FILES) + +LOCAL_MODULE:= libLLVMSelectionDAG + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(codegen_selectiondag_SRC_FILES) + +LOCAL_MODULE:= libLLVMSelectionDAG + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 9189e71a66..3be6b43116 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1064,7 +1064,7 @@ SDValue DAGCombiner::visitADD(SDNode *N) { if (VT.isInteger() && !VT.isVector()) { APInt LHSZero, LHSOne; APInt RHSZero, RHSOne; - APInt Mask = APInt::getAllOnesValue(VT.getSizeInBits()); + APInt Mask = APInt::getAllOnesValue(VT.getScalarType().getSizeInBits()); DAG.ComputeMaskedBits(N0, Mask, LHSZero, LHSOne); if (LHSZero.getBoolValue()) { @@ -1136,7 +1136,7 @@ SDValue DAGCombiner::visitADDC(SDNode *N) { // fold (addc a, b) -> (or a, b), CARRY_FALSE iff a and b share no bits. APInt LHSZero, LHSOne; APInt RHSZero, RHSOne; - APInt Mask = APInt::getAllOnesValue(VT.getSizeInBits()); + APInt Mask = APInt::getAllOnesValue(VT.getScalarType().getSizeInBits()); DAG.ComputeMaskedBits(N0, Mask, LHSZero, LHSOne); if (LHSZero.getBoolValue()) { @@ -1758,7 +1758,7 @@ SDValue DAGCombiner::visitAND(SDNode *N) { ConstantSDNode *N0C = dyn_cast(N0); ConstantSDNode *N1C = dyn_cast(N1); EVT VT = N1.getValueType(); - unsigned BitWidth = VT.getSizeInBits(); + unsigned BitWidth = VT.getScalarType().getSizeInBits(); // fold vector ops if (VT.isVector()) { @@ -1786,7 +1786,7 @@ SDValue DAGCombiner::visitAND(SDNode *N) { SDValue RAND = ReassociateOps(ISD::AND, N->getDebugLoc(), N0, N1); if (RAND.getNode() != 0) return RAND; - // fold (and (or x, 0xFFFF), 0xFF) -> 0xFF + // fold (and (or x, C), D) -> D if (C & D) == D if (N1C && N0.getOpcode() == ISD::OR) if (ConstantSDNode *ORI = dyn_cast(N0.getOperand(1))) if ((ORI->getAPIntValue() & N1C->getAPIntValue()) == N1C->getAPIntValue()) @@ -1872,16 +1872,17 @@ SDValue DAGCombiner::visitAND(SDNode *N) { EVT MemVT = LN0->getMemoryVT(); // If we zero all the possible extended bits, then we can turn this into // a zextload if we are running before legalize or the operation is legal. - unsigned BitWidth = N1.getValueSizeInBits(); + unsigned BitWidth = N1.getValueType().getScalarType().getSizeInBits(); if (DAG.MaskedValueIsZero(N1, APInt::getHighBitsSet(BitWidth, - BitWidth - MemVT.getSizeInBits())) && + BitWidth - MemVT.getScalarType().getSizeInBits())) && ((!LegalOperations && !LN0->isVolatile()) || TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT))) { SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N0.getDebugLoc(), VT, LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); AddToWorkList(N); CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -1894,16 +1895,17 @@ SDValue DAGCombiner::visitAND(SDNode *N) { EVT MemVT = LN0->getMemoryVT(); // If we zero all the possible extended bits, then we can turn this into // a zextload if we are running before legalize or the operation is legal. - unsigned BitWidth = N1.getValueSizeInBits(); + unsigned BitWidth = N1.getValueType().getScalarType().getSizeInBits(); if (DAG.MaskedValueIsZero(N1, APInt::getHighBitsSet(BitWidth, - BitWidth - MemVT.getSizeInBits())) && + BitWidth - MemVT.getScalarType().getSizeInBits())) && ((!LegalOperations && !LN0->isVolatile()) || TLI.isLoadExtLegal(ISD::ZEXTLOAD, MemVT))) { SDValue ExtLoad = DAG.getExtLoad(ISD::ZEXTLOAD, N0.getDebugLoc(), VT, LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); AddToWorkList(N); CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -1935,7 +1937,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { DAG.getExtLoad(ISD::ZEXTLOAD, LN0->getDebugLoc(), LoadResultTy, LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), - ExtVT, LN0->isVolatile(), LN0->getAlignment()); + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); AddToWorkList(N); CombineTo(LN0, NewLoad, NewLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -1970,7 +1973,8 @@ SDValue DAGCombiner::visitAND(SDNode *N) { DAG.getExtLoad(ISD::ZEXTLOAD, LN0->getDebugLoc(), LoadResultTy, LN0->getChain(), NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset(), - ExtVT, LN0->isVolatile(), Alignment); + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + Alignment); AddToWorkList(N); CombineTo(LN0, Load, Load.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -2021,13 +2025,15 @@ SDValue DAGCombiner::visitOR(SDNode *N) { if (ROR.getNode() != 0) return ROR; // Canonicalize (or (and X, c1), c2) -> (and (or X, c2), c1|c2) + // iff (c1 & c2) == 0. if (N1C && N0.getOpcode() == ISD::AND && N0.getNode()->hasOneUse() && isa(N0.getOperand(1))) { ConstantSDNode *C1 = cast(N0.getOperand(1)); - return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, - DAG.getNode(ISD::OR, N0.getDebugLoc(), VT, - N0.getOperand(0), N1), - DAG.FoldConstantArithmetic(ISD::OR, VT, N1C, C1)); + if ((C1->getAPIntValue() & N1C->getAPIntValue()) != 0) + return DAG.getNode(ISD::AND, N->getDebugLoc(), VT, + DAG.getNode(ISD::OR, N0.getDebugLoc(), VT, + N0.getOperand(0), N1), + DAG.FoldConstantArithmetic(ISD::OR, VT, N1C, C1)); } // fold (or (setcc x), (setcc y)) -> (setcc (or x, y)) if (isSetCCEquivalent(N0, LL, LR, CC0) && isSetCCEquivalent(N1, RL, RR, CC1)){ @@ -2750,7 +2756,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) { if (N1C && N0.getOpcode() == ISD::CTLZ && N1C->getAPIntValue() == Log2_32(VT.getSizeInBits())) { APInt KnownZero, KnownOne; - APInt Mask = APInt::getAllOnesValue(VT.getSizeInBits()); + APInt Mask = APInt::getAllOnesValue(VT.getScalarType().getSizeInBits()); DAG.ComputeMaskedBits(N0.getOperand(0), Mask, KnownZero, KnownOne); // If any of the input bits are KnownOne, then the input couldn't be all @@ -3143,7 +3149,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), N0.getValueType(), - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), ExtLoad); @@ -3185,7 +3192,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), @@ -3315,7 +3323,8 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), N0.getValueType(), - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), ExtLoad); @@ -3357,7 +3366,8 @@ SDValue DAGCombiner::visitZERO_EXTEND(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), @@ -3471,7 +3481,8 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), N0.getValueType(), - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), N0.getValueType(), ExtLoad); @@ -3513,7 +3524,8 @@ SDValue DAGCombiner::visitANY_EXTEND(SDNode *N) { VT, LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), MemVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), @@ -3636,10 +3648,11 @@ SDValue DAGCombiner::ReduceLoadWidth(SDNode *N) { SDValue Load = (ExtType == ISD::NON_EXTLOAD) ? DAG.getLoad(VT, N0.getDebugLoc(), LN0->getChain(), NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset() + PtrOff, - LN0->isVolatile(), NewAlign) + LN0->isVolatile(), LN0->isNonTemporal(), NewAlign) : DAG.getExtLoad(ExtType, N0.getDebugLoc(), VT, LN0->getChain(), NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset() + PtrOff, - ExtVT, LN0->isVolatile(), NewAlign); + ExtVT, LN0->isVolatile(), LN0->isNonTemporal(), + NewAlign); // Replace the old load's chain with the new load's chain. WorkListRemover DeadNodes(*this); @@ -3726,7 +3739,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -3742,7 +3756,8 @@ SDValue DAGCombiner::visitSIGN_EXTEND_INREG(SDNode *N) { LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), EVT, - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), ExtLoad, ExtLoad.getValue(1)); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -3826,7 +3841,7 @@ SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *N, EVT VT) { (!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT))) return DAG.getLoad(VT, N->getDebugLoc(), LD1->getChain(), LD1->getBasePtr(), LD1->getSrcValue(), - LD1->getSrcValueOffset(), false, Align); + LD1->getSrcValueOffset(), false, false, Align); } return SDValue(); @@ -3896,7 +3911,8 @@ SDValue DAGCombiner::visitBIT_CONVERT(SDNode *N) { SDValue Load = DAG.getLoad(VT, N->getDebugLoc(), LN0->getChain(), LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), - LN0->isVolatile(), OrigAlign); + LN0->isVolatile(), LN0->isNonTemporal(), + OrigAlign); AddToWorkList(N); CombineTo(N0.getNode(), DAG.getNode(ISD::BIT_CONVERT, N0.getDebugLoc(), @@ -4492,7 +4508,8 @@ SDValue DAGCombiner::visitFP_EXTEND(SDNode *N) { LN0->getBasePtr(), LN0->getSrcValue(), LN0->getSrcValueOffset(), N0.getValueType(), - LN0->isVolatile(), LN0->getAlignment()); + LN0->isVolatile(), LN0->isNonTemporal(), + LN0->getAlignment()); CombineTo(N, ExtLoad); CombineTo(N0.getNode(), DAG.getNode(ISD::FP_ROUND, N0.getDebugLoc(), @@ -4640,7 +4657,8 @@ SDValue DAGCombiner::visitBRCOND(SDNode *N) { DAG.DeleteNode(Trunc); } // Replace the uses of SRL with SETCC - DAG.ReplaceAllUsesOfValueWith(N1, SetCC); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N1, SetCC, &DeadNodes); removeFromWorkList(N1.getNode()); DAG.DeleteNode(N1.getNode()); return SDValue(N, 0); // Return N so it doesn't get rechecked! @@ -4648,6 +4666,56 @@ SDValue DAGCombiner::visitBRCOND(SDNode *N) { } } } + + // Transform br(xor(x, y)) -> br(x != y) + // Transform br(xor(xor(x,y), 1)) -> br (x == y) + if (N1.hasOneUse() && N1.getOpcode() == ISD::XOR) { + SDNode *TheXor = N1.getNode(); + SDValue Op0 = TheXor->getOperand(0); + SDValue Op1 = TheXor->getOperand(1); + if (Op0.getOpcode() == Op1.getOpcode()) { + // Avoid missing important xor optimizations. + SDValue Tmp = visitXOR(TheXor); + if (Tmp.getNode()) { + DEBUG(dbgs() << "\nReplacing.8 "; + TheXor->dump(&DAG); + dbgs() << "\nWith: "; + Tmp.getNode()->dump(&DAG); + dbgs() << '\n'); + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N1, Tmp, &DeadNodes); + removeFromWorkList(TheXor); + DAG.DeleteNode(TheXor); + return DAG.getNode(ISD::BRCOND, N->getDebugLoc(), + MVT::Other, Chain, Tmp, N2); + } + } + + if (Op0.getOpcode() != ISD::SETCC && Op1.getOpcode() != ISD::SETCC) { + bool Equal = false; + if (ConstantSDNode *RHSCI = dyn_cast(Op0)) + if (RHSCI->getAPIntValue() == 1 && Op0.hasOneUse() && + Op0.getOpcode() == ISD::XOR) { + TheXor = Op0.getNode(); + Equal = true; + } + + EVT SetCCVT = N1.getValueType(); + if (LegalTypes) + SetCCVT = TLI.getSetCCResultType(SetCCVT); + SDValue SetCC = DAG.getSetCC(TheXor->getDebugLoc(), + SetCCVT, + Op0, Op1, + Equal ? ISD::SETEQ : ISD::SETNE); + // Replace the uses of XOR with SETCC + WorkListRemover DeadNodes(*this); + DAG.ReplaceAllUsesOfValueWith(N1, SetCC, &DeadNodes); + removeFromWorkList(N1.getNode()); + DAG.DeleteNode(N1.getNode()); + return DAG.getNode(ISD::BRCOND, N->getDebugLoc(), + MVT::Other, Chain, SetCC, N2); + } + } return SDValue(); } @@ -4960,7 +5028,7 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { LD->getValueType(0), Chain, Ptr, LD->getSrcValue(), LD->getSrcValueOffset(), LD->getMemoryVT(), - LD->isVolatile(), Align); + LD->isVolatile(), LD->isNonTemporal(), Align); } } @@ -4997,7 +5065,7 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { assert(N->getValueType(2) == MVT::Other && "Malformed indexed loads?"); if (N->hasNUsesOfValue(0, 0) && N->hasNUsesOfValue(0, 1)) { SDValue Undef = DAG.getUNDEF(N->getValueType(0)); - DEBUG(dbgs() << "\nReplacing.6 "; + DEBUG(dbgs() << "\nReplacing.7 "; N->dump(&DAG); dbgs() << "\nWith: "; Undef.getNode()->dump(&DAG); @@ -5042,7 +5110,8 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { ReplLoad = DAG.getLoad(N->getValueType(0), LD->getDebugLoc(), BetterChain, Ptr, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); } else { ReplLoad = DAG.getExtLoad(LD->getExtensionType(), LD->getDebugLoc(), LD->getValueType(0), @@ -5050,6 +5119,7 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { LD->getSrcValueOffset(), LD->getMemoryVT(), LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); } @@ -5149,13 +5219,14 @@ SDValue DAGCombiner::ReduceLoadOpStoreWidth(SDNode *N) { SDValue NewLD = DAG.getLoad(NewVT, N0.getDebugLoc(), LD->getChain(), NewPtr, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), NewAlign); + LD->isVolatile(), LD->isNonTemporal(), + NewAlign); SDValue NewVal = DAG.getNode(Opc, Value.getDebugLoc(), NewVT, NewLD, DAG.getConstant(NewImm, NewVT)); SDValue NewST = DAG.getStore(Chain, N->getDebugLoc(), NewVal, NewPtr, ST->getSrcValue(), ST->getSrcValueOffset(), - false, NewAlign); + false, false, NewAlign); AddToWorkList(NewPtr.getNode()); AddToWorkList(NewLD.getNode()); @@ -5184,7 +5255,7 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getTruncStore(Chain, N->getDebugLoc(), Value, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->getMemoryVT(), - ST->isVolatile(), Align); + ST->isVolatile(), ST->isNonTemporal(), Align); } } @@ -5201,7 +5272,8 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { TLI.isOperationLegalOrCustom(ISD::STORE, SVT))) return DAG.getStore(Chain, N->getDebugLoc(), Value.getOperand(0), Ptr, ST->getSrcValue(), - ST->getSrcValueOffset(), ST->isVolatile(), OrigAlign); + ST->getSrcValueOffset(), ST->isVolatile(), + ST->isNonTemporal(), OrigAlign); } // Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr' @@ -5227,7 +5299,7 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getStore(Chain, N->getDebugLoc(), Tmp, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->isVolatile(), - ST->getAlignment()); + ST->isNonTemporal(), ST->getAlignment()); } break; case MVT::f64: @@ -5239,7 +5311,7 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getStore(Chain, N->getDebugLoc(), Tmp, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->isVolatile(), - ST->getAlignment()); + ST->isNonTemporal(), ST->getAlignment()); } else if (!ST->isVolatile() && TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { // Many FP stores are not made apparent until after legalize, e.g. for @@ -5253,18 +5325,21 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { int SVOffset = ST->getSrcValueOffset(); unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); SDValue St0 = DAG.getStore(Chain, ST->getDebugLoc(), Lo, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), - isVolatile, ST->getAlignment()); + isVolatile, isNonTemporal, + ST->getAlignment()); Ptr = DAG.getNode(ISD::ADD, N->getDebugLoc(), Ptr.getValueType(), Ptr, DAG.getConstant(4, Ptr.getValueType())); SVOffset += 4; Alignment = MinAlign(Alignment, 4U); SDValue St1 = DAG.getStore(Chain, ST->getDebugLoc(), Hi, Ptr, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, + Alignment); return DAG.getNode(ISD::TokenFactor, N->getDebugLoc(), MVT::Other, St0, St1); } @@ -5286,12 +5361,13 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { if (ST->isTruncatingStore()) { ReplStore = DAG.getTruncStore(BetterChain, N->getDebugLoc(), Value, Ptr, ST->getSrcValue(),ST->getSrcValueOffset(), - ST->getMemoryVT(), - ST->isVolatile(), ST->getAlignment()); + ST->getMemoryVT(), ST->isVolatile(), + ST->isNonTemporal(), ST->getAlignment()); } else { ReplStore = DAG.getStore(BetterChain, N->getDebugLoc(), Value, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), - ST->isVolatile(), ST->getAlignment()); + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); } // Create token to keep both nodes around. @@ -5325,7 +5401,8 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getTruncStore(Chain, N->getDebugLoc(), Shorter, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->getMemoryVT(), - ST->isVolatile(), ST->getAlignment()); + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); // Otherwise, see if we can simplify the operation with // SimplifyDemandedBits, which only works if the value has a single use. @@ -5358,7 +5435,8 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { return DAG.getTruncStore(Chain, N->getDebugLoc(), Value.getOperand(0), Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), ST->getMemoryVT(), - ST->isVolatile(), ST->getAlignment()); + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); } return ReduceLoadOpStoreWidth(N); @@ -5503,7 +5581,7 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { return DAG.getLoad(LVT, N->getDebugLoc(), LN0->getChain(), NewPtr, LN0->getSrcValue(), LN0->getSrcValueOffset(), - LN0->isVolatile(), Align); + LN0->isVolatile(), LN0->isNonTemporal(), Align); } return SDValue(); @@ -5883,6 +5961,7 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, LLD->getChain(), Addr, 0, 0, LLD->isVolatile(), + LLD->isNonTemporal(), LLD->getAlignment()); } else { Load = DAG.getExtLoad(LLD->getExtensionType(), @@ -5891,6 +5970,7 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, LLD->getChain(), Addr, 0, 0, LLD->getMemoryVT(), LLD->isVolatile(), + LLD->isNonTemporal(), LLD->getAlignment()); } @@ -5998,7 +6078,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, CstOffset); return DAG.getLoad(TV->getValueType(0), DL, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, false, - Alignment); + false, Alignment); } } diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp index 35ef5b7053..1d76c7c390 100644 --- a/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -350,6 +350,34 @@ bool FastISel::SelectCall(User *I) { (void)TargetSelectInstruction(cast(I)); return true; } + case Intrinsic::dbg_value: { + // This requires target support, but right now X86 is the only Fast target. + DbgValueInst *DI = cast(I); + const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); + Value *V = DI->getValue(); + if (!V) { + // Currently the optimizer can produce this; insert an undef to + // help debugging. Probably the optimizer should not do this. + BuildMI(MBB, DL, II).addReg(0U).addImm(DI->getOffset()). + addMetadata(DI->getVariable()); + } else if (ConstantInt *CI = dyn_cast(V)) { + BuildMI(MBB, DL, II).addImm(CI->getZExtValue()).addImm(DI->getOffset()). + addMetadata(DI->getVariable()); + } else if (ConstantFP *CF = dyn_cast(V)) { + BuildMI(MBB, DL, II).addFPImm(CF).addImm(DI->getOffset()). + addMetadata(DI->getVariable()); + } else if (unsigned Reg = lookUpRegForValue(V)) { + BuildMI(MBB, DL, II).addReg(Reg, RegState::Debug).addImm(DI->getOffset()). + addMetadata(DI->getVariable()); + } else { + // We can't yet handle anything else here because it would require + // generating code, thus altering codegen because of debug info. + // Insert an undef so we can see what we dropped. + BuildMI(MBB, DL, II).addReg(0U).addImm(DI->getOffset()). + addMetadata(DI->getVariable()); + } + return true; + } case Intrinsic::eh_exception: { EVT VT = TLI.getValueType(I->getType()); switch (TLI.getOperationAction(ISD::EXCEPTIONADDR, VT)) { diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp index 02fe85dd99..625de11432 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.cpp +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.cpp @@ -15,6 +15,7 @@ #define DEBUG_TYPE "instr-emitter" #include "InstrEmitter.h" +#include "SDDbgValue.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" @@ -497,6 +498,56 @@ InstrEmitter::EmitCopyToRegClassNode(SDNode *Node, assert(isNew && "Node emitted out of order - early"); } +/// EmitDbgValue - Generate any debug info that refers to this Node. Constant +/// dbg_value is not handled here. +void +InstrEmitter::EmitDbgValue(SDNode *Node, + DenseMap &VRBaseMap, + SDDbgValue *sd) { + if (!Node->getHasDebugValue()) + return; + if (!sd) + return; + unsigned VReg = getVR(SDValue(sd->getSDNode(), sd->getResNo()), VRBaseMap); + const TargetInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE); + DebugLoc DL = sd->getDebugLoc(); + MachineInstr *MI; + if (VReg) { + MI = BuildMI(*MF, DL, II).addReg(VReg, RegState::Debug). + addImm(sd->getOffset()). + addMetadata(sd->getMDPtr()); + } else { + // Insert an Undef so we can see what we dropped. + MI = BuildMI(*MF, DL, II).addReg(0U).addImm(sd->getOffset()). + addMetadata(sd->getMDPtr()); + } + MBB->insert(InsertPos, MI); +} + +/// EmitDbgValue - Generate constant debug info. No SDNode is involved. +void +InstrEmitter::EmitDbgValue(SDDbgValue *sd) { + if (!sd) + return; + const TargetInstrDesc &II = TII->get(TargetOpcode::DBG_VALUE); + DebugLoc DL = sd->getDebugLoc(); + MachineInstr *MI; + Value *V = sd->getConst(); + if (ConstantInt *CI = dyn_cast(V)) { + MI = BuildMI(*MF, DL, II).addImm(CI->getZExtValue()). + addImm(sd->getOffset()). + addMetadata(sd->getMDPtr()); + } else if (ConstantFP *CF = dyn_cast(V)) { + MI = BuildMI(*MF, DL, II).addFPImm(CF).addImm(sd->getOffset()). + addMetadata(sd->getMDPtr()); + } else { + // Insert an Undef so we can see what we dropped. + MI = BuildMI(*MF, DL, II).addReg(0U).addImm(sd->getOffset()). + addMetadata(sd->getMDPtr()); + } + MBB->insert(InsertPos, MI); +} + /// EmitNode - Generate machine code for a node and needed dependencies. /// void InstrEmitter::EmitNode(SDNode *Node, bool IsClone, bool IsCloned, diff --git a/lib/CodeGen/SelectionDAG/InstrEmitter.h b/lib/CodeGen/SelectionDAG/InstrEmitter.h index 91817e4d38..4fe9f19cc9 100644 --- a/lib/CodeGen/SelectionDAG/InstrEmitter.h +++ b/lib/CodeGen/SelectionDAG/InstrEmitter.h @@ -23,6 +23,7 @@ namespace llvm { class TargetInstrDesc; +class SDDbgValue; class InstrEmitter { MachineFunction *MF; @@ -97,6 +98,16 @@ public: /// MachineInstr. static unsigned CountOperands(SDNode *Node); + /// EmitDbgValue - Generate any debug info that refers to this Node. Constant + /// dbg_value is not handled here. + void EmitDbgValue(SDNode *Node, + DenseMap &VRBaseMap, + SDDbgValue* sd); + + + /// EmitDbgValue - Generate a constant DBG_VALUE. No node is involved. + void EmitDbgValue(SDDbgValue* sd); + /// EmitNode - Generate machine code for a node and needed dependencies. /// void EmitNode(SDNode *Node, bool IsClone, bool IsCloned, diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 78e6e4ee9d..f498263b73 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -377,9 +377,10 @@ static SDValue ExpandConstantFP(ConstantFPSDNode *CFP, bool UseCP, return DAG.getExtLoad(ISD::EXTLOAD, dl, OrigVT, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), - 0, VT, false, Alignment); + 0, VT, false, false, Alignment); return DAG.getLoad(OrigVT, dl, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0, false, Alignment); + PseudoSourceValue::getConstantPool(), 0, false, false, + Alignment); } /// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores. @@ -402,7 +403,8 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, // FIXME: Does not handle truncating floating point stores! SDValue Result = DAG.getNode(ISD::BIT_CONVERT, dl, intVT, Val); return DAG.getStore(Chain, dl, Result, Ptr, ST->getSrcValue(), - SVOffset, ST->isVolatile(), Alignment); + SVOffset, ST->isVolatile(), ST->isNonTemporal(), + Alignment); } else { // Do a (aligned) store to a stack slot, then copy from the stack slot // to the final destination using (unaligned) integer loads and stores. @@ -418,7 +420,8 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, // Perform the original store, only redirected to the stack slot. SDValue Store = DAG.getTruncStore(Chain, dl, - Val, StackPtr, NULL, 0, StoredVT); + Val, StackPtr, NULL, 0, StoredVT, + false, false, 0); SDValue Increment = DAG.getConstant(RegBytes, TLI.getPointerTy()); SmallVector Stores; unsigned Offset = 0; @@ -426,11 +429,12 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, // Do all but one copies using the full register width. for (unsigned i = 1; i < NumRegs; i++) { // Load one integer register's worth from the stack slot. - SDValue Load = DAG.getLoad(RegVT, dl, Store, StackPtr, NULL, 0); + SDValue Load = DAG.getLoad(RegVT, dl, Store, StackPtr, NULL, 0, + false, false, 0); // Store it to the final location. Remember the store. Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, Ptr, ST->getSrcValue(), SVOffset + Offset, - ST->isVolatile(), + ST->isVolatile(), ST->isNonTemporal(), MinAlign(ST->getAlignment(), Offset))); // Increment the pointers. Offset += RegBytes; @@ -446,11 +450,12 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, // Load from the stack slot. SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Store, StackPtr, - NULL, 0, MemVT); + NULL, 0, MemVT, false, false, 0); Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, Ptr, ST->getSrcValue(), SVOffset + Offset, MemVT, ST->isVolatile(), + ST->isNonTemporal(), MinAlign(ST->getAlignment(), Offset))); // The order of the stores doesn't matter - say it with a TokenFactor. return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0], @@ -474,13 +479,14 @@ SDValue ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG, SDValue Store1, Store2; Store1 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Lo:Hi, Ptr, ST->getSrcValue(), SVOffset, NewStoredVT, - ST->isVolatile(), Alignment); + ST->isVolatile(), ST->isNonTemporal(), Alignment); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, TLI.getPointerTy())); Alignment = MinAlign(Alignment, IncrementSize); Store2 = DAG.getTruncStore(Chain, dl, TLI.isLittleEndian()?Hi:Lo, Ptr, ST->getSrcValue(), SVOffset + IncrementSize, - NewStoredVT, ST->isVolatile(), Alignment); + NewStoredVT, ST->isVolatile(), ST->isNonTemporal(), + Alignment); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, Store2); } @@ -502,7 +508,7 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, // then bitconvert to floating point or vector. SDValue newLoad = DAG.getLoad(intVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset, LD->isVolatile(), - LD->getAlignment()); + LD->isNonTemporal(), LD->getAlignment()); SDValue Result = DAG.getNode(ISD::BIT_CONVERT, dl, LoadedVT, newLoad); if (VT.isFloatingPoint() && LoadedVT != VT) Result = DAG.getNode(ISD::FP_EXTEND, dl, VT, Result); @@ -530,10 +536,11 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, // Load one integer register's worth from the original location. SDValue Load = DAG.getLoad(RegVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset + Offset, LD->isVolatile(), + LD->isNonTemporal(), MinAlign(LD->getAlignment(), Offset)); // Follow the load with a store to the stack slot. Remember the store. Stores.push_back(DAG.getStore(Load.getValue(1), dl, Load, StackPtr, - NULL, 0)); + NULL, 0, false, false, 0)); // Increment the pointers. Offset += RegBytes; Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment); @@ -546,12 +553,13 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, RegVT, Chain, Ptr, LD->getSrcValue(), SVOffset + Offset, MemVT, LD->isVolatile(), + LD->isNonTemporal(), MinAlign(LD->getAlignment(), Offset)); // Follow the load with a store to the stack slot. Remember the store. // On big-endian machines this requires a truncating store to ensure // that the bits end up in the right place. Stores.push_back(DAG.getTruncStore(Load.getValue(1), dl, Load, StackPtr, - NULL, 0, MemVT)); + NULL, 0, MemVT, false, false, 0)); // The order of the stores doesn't matter - say it with a TokenFactor. SDValue TF = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Stores[0], @@ -559,7 +567,7 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, // Finally, perform the original load only redirected to the stack slot. Load = DAG.getExtLoad(LD->getExtensionType(), dl, VT, TF, StackBase, - NULL, 0, LoadedVT); + NULL, 0, LoadedVT, false, false, 0); // Callers expect a MERGE_VALUES node. SDValue Ops[] = { Load, TF }; @@ -588,20 +596,22 @@ SDValue ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG, SDValue Lo, Hi; if (TLI.isLittleEndian()) { Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getSrcValue(), - SVOffset, NewLoadedVT, LD->isVolatile(), Alignment); + SVOffset, NewLoadedVT, LD->isVolatile(), + LD->isNonTemporal(), Alignment); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, TLI.getPointerTy())); Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getSrcValue(), SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(), - MinAlign(Alignment, IncrementSize)); + LD->isNonTemporal(), MinAlign(Alignment, IncrementSize)); } else { Hi = DAG.getExtLoad(HiExtType, dl, VT, Chain, Ptr, LD->getSrcValue(), - SVOffset, NewLoadedVT, LD->isVolatile(), Alignment); + SVOffset, NewLoadedVT, LD->isVolatile(), + LD->isNonTemporal(), Alignment); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(IncrementSize, TLI.getPointerTy())); Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, VT, Chain, Ptr, LD->getSrcValue(), SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(), - MinAlign(Alignment, IncrementSize)); + LD->isNonTemporal(), MinAlign(Alignment, IncrementSize)); } // aggregate the two parts @@ -643,7 +653,8 @@ PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, // Store the vector. SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Tmp1, StackPtr, - PseudoSourceValue::getFixedStack(SPFI), 0); + PseudoSourceValue::getFixedStack(SPFI), 0, + false, false, 0); // Truncate or zero extend offset to target pointer type. unsigned CastOpc = IdxVT.bitsGT(PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; @@ -654,10 +665,12 @@ PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx, SDValue StackPtr2 = DAG.getNode(ISD::ADD, dl, IdxVT, Tmp3, StackPtr); // Store the scalar value. Ch = DAG.getTruncStore(Ch, dl, Tmp2, StackPtr2, - PseudoSourceValue::getFixedStack(SPFI), 0, EltVT); + PseudoSourceValue::getFixedStack(SPFI), 0, EltVT, + false, false, 0); // Load the updated vector. return DAG.getLoad(VT, dl, Ch, StackPtr, - PseudoSourceValue::getFixedStack(SPFI), 0); + PseudoSourceValue::getFixedStack(SPFI), 0, + false, false, 0); } @@ -702,6 +715,7 @@ SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { int SVOffset = ST->getSrcValueOffset(); unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); DebugLoc dl = ST->getDebugLoc(); if (ConstantFPSDNode *CFP = dyn_cast(ST->getValue())) { if (CFP->getValueType(0) == MVT::f32 && @@ -710,14 +724,14 @@ SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { bitcastToAPInt().zextOrTrunc(32), MVT::i32); return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, Alignment); } else if (CFP->getValueType(0) == MVT::f64) { // If this target supports 64-bit registers, do a single 64-bit store. if (getTypeAction(MVT::i64) == Legal) { Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt(). zextOrTrunc(64), MVT::i64); return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, Alignment); } else if (getTypeAction(MVT::i32) == Legal && !ST->isVolatile()) { // Otherwise, if the target supports 32-bit registers, use 2 32-bit // stores. If the target supports neither 32- nor 64-bits, this @@ -728,11 +742,11 @@ SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) { if (TLI.isBigEndian()) std::swap(Lo, Hi); Lo = DAG.getStore(Tmp1, dl, Lo, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, Alignment); Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2, DAG.getIntPtrConstant(4)); Hi = DAG.getStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), SVOffset+4, - isVolatile, MinAlign(Alignment, 4U)); + isVolatile, isNonTemporal, MinAlign(Alignment, 4U)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } @@ -1108,7 +1122,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp1 = DAG.getLoad(NVT, dl, Tmp1, Tmp2, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); Tmp3 = LegalizeOp(DAG.getNode(ISD::BIT_CONVERT, dl, VT, Tmp1)); Tmp4 = LegalizeOp(Tmp1.getValue(1)); break; @@ -1125,6 +1140,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { int SVOffset = LD->getSrcValueOffset(); unsigned Alignment = LD->getAlignment(); bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); if (SrcWidth != SrcVT.getStoreSizeInBits() && // Some targets pretend to have an i1 loading operation, and actually @@ -1150,7 +1166,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.getExtLoad(NewExtType, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset, - NVT, isVolatile, Alignment); + NVT, isVolatile, isNonTemporal, Alignment); Ch = Result.getValue(1); // The chain. @@ -1187,7 +1203,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset, RoundVT, isVolatile, - Alignment); + isNonTemporal, Alignment); // Load the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1195,7 +1211,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset + IncrementSize, - ExtraVT, isVolatile, + ExtraVT, isVolatile, isNonTemporal, MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the @@ -1215,7 +1231,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Load the top RoundWidth bits. Hi = DAG.getExtLoad(ExtType, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset, RoundVT, isVolatile, - Alignment); + isNonTemporal, Alignment); // Load the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1224,7 +1240,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), SVOffset + IncrementSize, - ExtraVT, isVolatile, + ExtraVT, isVolatile, isNonTemporal, MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the @@ -1284,7 +1300,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { (SrcVT == MVT::f64 && Node->getValueType(0) == MVT::f128)) { SDValue Load = DAG.getLoad(SrcVT, dl, Tmp1, Tmp2, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); Result = DAG.getNode(ISD::FP_EXTEND, dl, Node->getValueType(0), Load); Tmp1 = LegalizeOp(Result); // Relegalize new nodes. @@ -1297,7 +1314,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.getExtLoad(ISD::EXTLOAD, dl, Node->getValueType(0), Tmp1, Tmp2, LD->getSrcValue(), LD->getSrcValueOffset(), SrcVT, - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); SDValue ValRes; if (ExtType == ISD::SEXTLOAD) ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, dl, @@ -1325,6 +1343,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { int SVOffset = ST->getSrcValueOffset(); unsigned Alignment = ST->getAlignment(); bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); if (!ST->isTruncatingStore()) { if (SDNode *OptStore = OptimizeFloatStore(ST).getNode()) { @@ -1361,7 +1380,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { TLI.getTypeToPromoteTo(ISD::STORE, VT), Tmp3); Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), SVOffset, isVolatile, - Alignment); + isNonTemporal, Alignment); break; } break; @@ -1379,7 +1398,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { EVT NVT = EVT::getIntegerVT(*DAG.getContext(), StVT.getStoreSizeInBits()); Tmp3 = DAG.getZeroExtendInReg(Tmp3, dl, StVT); Result = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, NVT, isVolatile, Alignment); + SVOffset, NVT, isVolatile, isNonTemporal, + Alignment); } else if (StWidth & (StWidth - 1)) { // If not storing a power-of-2 number of bits, expand as two stores. assert(!StVT.isVector() && "Unsupported truncstore!"); @@ -1399,7 +1419,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // Store the bottom RoundWidth bits. Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), SVOffset, RoundVT, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); // Store the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1409,6 +1429,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { DAG.getConstant(RoundWidth, TLI.getShiftAmountTy())); Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), SVOffset + IncrementSize, ExtraVT, isVolatile, + isNonTemporal, MinAlign(Alignment, IncrementSize)); } else { // Big endian - avoid unaligned stores. @@ -1417,7 +1438,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Hi = DAG.getNode(ISD::SRL, dl, Tmp3.getValueType(), Tmp3, DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy())); Hi = DAG.getTruncStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), - SVOffset, RoundVT, isVolatile, Alignment); + SVOffset, RoundVT, isVolatile, isNonTemporal, + Alignment); // Store the remaining ExtraWidth bits. IncrementSize = RoundWidth / 8; @@ -1425,6 +1447,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { DAG.getIntPtrConstant(IncrementSize)); Lo = DAG.getTruncStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), SVOffset + IncrementSize, ExtraVT, isVolatile, + isNonTemporal, MinAlign(Alignment, IncrementSize)); } @@ -1457,7 +1480,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { assert(isTypeLegal(StVT) && "Do not know how to expand this store!"); Tmp3 = DAG.getNode(ISD::TRUNCATE, dl, StVT, Tmp3); Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(), - SVOffset, isVolatile, Alignment); + SVOffset, isVolatile, isNonTemporal, + Alignment); break; } } @@ -1484,7 +1508,8 @@ SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) { DebugLoc dl = Op.getDebugLoc(); // Store the value to a temporary stack slot, then LOAD the returned part. SDValue StackPtr = DAG.CreateStackTemporary(Vec.getValueType()); - SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0); + SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0, + false, false, 0); // Add the offset to the index. unsigned EltSize = @@ -1500,10 +1525,12 @@ SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) { StackPtr = DAG.getNode(ISD::ADD, dl, Idx.getValueType(), Idx, StackPtr); if (Op.getValueType().isVector()) - return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0); + return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0, + false, false, 0); else return DAG.getExtLoad(ISD::EXTLOAD, dl, Op.getValueType(), Ch, StackPtr, - NULL, 0, Vec.getValueType().getVectorElementType()); + NULL, 0, Vec.getValueType().getVectorElementType(), + false, false, 0); } SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { @@ -1512,7 +1539,6 @@ SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { // the result as a vector. // Create the stack frame object. EVT VT = Node->getValueType(0); - EVT OpVT = Node->getOperand(0).getValueType(); EVT EltVT = VT.getVectorElementType(); DebugLoc dl = Node->getDebugLoc(); SDValue FIPtr = DAG.CreateStackTemporary(VT); @@ -1532,13 +1558,16 @@ SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { SDValue Idx = DAG.getConstant(Offset, FIPtr.getValueType()); Idx = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, Idx); - // If EltVT smaller than OpVT, only store the bits necessary. - if (!OpVT.isVector() && EltVT.bitsLT(OpVT)) { + // If the destination vector element type is narrower than the source + // element type, only store the bits necessary. + if (EltVT.bitsLT(Node->getOperand(i).getValueType().getScalarType())) { Stores.push_back(DAG.getTruncStore(DAG.getEntryNode(), dl, - Node->getOperand(i), Idx, SV, Offset, EltVT)); + Node->getOperand(i), Idx, SV, Offset, + EltVT, false, false, 0)); } else Stores.push_back(DAG.getStore(DAG.getEntryNode(), dl, - Node->getOperand(i), Idx, SV, Offset)); + Node->getOperand(i), Idx, SV, Offset, + false, false, 0)); } SDValue StoreChain; @@ -1549,7 +1578,7 @@ SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) { StoreChain = DAG.getEntryNode(); // Result is a load from the stack slot. - return DAG.getLoad(VT, dl, StoreChain, FIPtr, SV, 0); + return DAG.getLoad(VT, dl, StoreChain, FIPtr, SV, 0, false, false, 0); } SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) { @@ -1572,12 +1601,14 @@ SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) { SDValue StackPtr = DAG.CreateStackTemporary(Tmp2.getValueType()); SDValue StorePtr = StackPtr, LoadPtr = StackPtr; SDValue Ch = - DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StorePtr, NULL, 0); + DAG.getStore(DAG.getEntryNode(), dl, Tmp2, StorePtr, NULL, 0, + false, false, 0); if (Tmp2.getValueType() == MVT::f64 && TLI.isLittleEndian()) LoadPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), LoadPtr, DAG.getIntPtrConstant(4)); SignBit = DAG.getExtLoad(ISD::SEXTLOAD, dl, TLI.getPointerTy(), - Ch, LoadPtr, NULL, 0, MVT::i32); + Ch, LoadPtr, NULL, 0, MVT::i32, + false, false, 0); } SignBit = DAG.getSetCC(dl, TLI.getSetCCResultType(SignBit.getValueType()), @@ -1701,20 +1732,21 @@ SDValue SelectionDAGLegalize::EmitStackConvert(SDValue SrcOp, if (SrcSize > SlotSize) Store = DAG.getTruncStore(DAG.getEntryNode(), dl, SrcOp, FIPtr, - SV, 0, SlotVT, false, SrcAlign); + SV, 0, SlotVT, false, false, SrcAlign); else { assert(SrcSize == SlotSize && "Invalid store"); Store = DAG.getStore(DAG.getEntryNode(), dl, SrcOp, FIPtr, - SV, 0, false, SrcAlign); + SV, 0, false, false, SrcAlign); } // Result is a load from the stack slot. if (SlotSize == DestSize) - return DAG.getLoad(DestVT, dl, Store, FIPtr, SV, 0, false, DestAlign); + return DAG.getLoad(DestVT, dl, Store, FIPtr, SV, 0, false, false, + DestAlign); assert(SlotSize < DestSize && "Unknown extension!"); return DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, Store, FIPtr, SV, 0, SlotVT, - false, DestAlign); + false, false, DestAlign); } SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) { @@ -1729,9 +1761,11 @@ SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) { SDValue Ch = DAG.getTruncStore(DAG.getEntryNode(), dl, Node->getOperand(0), StackPtr, PseudoSourceValue::getFixedStack(SPFI), 0, - Node->getValueType(0).getVectorElementType()); + Node->getValueType(0).getVectorElementType(), + false, false, 0); return DAG.getLoad(Node->getValueType(0), dl, Ch, StackPtr, - PseudoSourceValue::getFixedStack(SPFI), 0); + PseudoSourceValue::getFixedStack(SPFI), 0, + false, false, 0); } @@ -1805,7 +1839,7 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { unsigned Alignment = cast(CPIdx)->getAlignment(); return DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, - false, Alignment); + false, false, Alignment); } if (!MoreThanTwoValues) { @@ -1865,8 +1899,7 @@ SDValue SelectionDAGLegalize::ExpandLibCall(RTLIB::Libcall LC, SDNode *Node, TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, 0, TLI.getLibcallCallingConv(LC), false, /*isReturnValueUsed=*/true, - Callee, Args, DAG, - Node->getDebugLoc(), DAG.GetOrdering(Node)); + Callee, Args, DAG, Node->getDebugLoc()); // Legalize the call sequence, starting with the chain. This will advance // the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that @@ -1943,13 +1976,16 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, } // store the lo of the constructed double - based on integer input SDValue Store1 = DAG.getStore(DAG.getEntryNode(), dl, - Op0Mapped, Lo, NULL, 0); + Op0Mapped, Lo, NULL, 0, + false, false, 0); // initial hi portion of constructed double SDValue InitialHi = DAG.getConstant(0x43300000u, MVT::i32); // store the hi of the constructed double - biased exponent - SDValue Store2=DAG.getStore(Store1, dl, InitialHi, Hi, NULL, 0); + SDValue Store2=DAG.getStore(Store1, dl, InitialHi, Hi, NULL, 0, + false, false, 0); // load the constructed double - SDValue Load = DAG.getLoad(MVT::f64, dl, Store2, StackSlot, NULL, 0); + SDValue Load = DAG.getLoad(MVT::f64, dl, Store2, StackSlot, NULL, 0, + false, false, 0); // FP constant to bias correct the final result SDValue Bias = DAG.getConstantFP(isSigned ? BitsToDouble(0x4330000080000000ULL) : @@ -1972,6 +2008,31 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, return Result; } assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet"); + + // Implementation of unsigned i64 to f64 following the algorithm in + // __floatundidf in compiler_rt. This implementation has the advantage + // of performing rounding correctly, both in the default rounding mode + // and in all alternate rounding modes. + // TODO: Generalize this for use with other types. + if (Op0.getValueType() == MVT::i64 && DestVT == MVT::f64) { + SDValue TwoP52 = + DAG.getConstant(UINT64_C(0x4330000000000000), MVT::i64); + SDValue TwoP84PlusTwoP52 = + DAG.getConstantFP(BitsToDouble(UINT64_C(0x4530000000100000)), MVT::f64); + SDValue TwoP84 = + DAG.getConstant(UINT64_C(0x4530000000000000), MVT::i64); + + SDValue Lo = DAG.getZeroExtendInReg(Op0, dl, MVT::i32); + SDValue Hi = DAG.getNode(ISD::SRL, dl, MVT::i64, Op0, + DAG.getConstant(32, MVT::i64)); + SDValue LoOr = DAG.getNode(ISD::OR, dl, MVT::i64, Lo, TwoP52); + SDValue HiOr = DAG.getNode(ISD::OR, dl, MVT::i64, Hi, TwoP84); + SDValue LoFlt = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, LoOr); + SDValue HiFlt = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::f64, HiOr); + SDValue HiSub = DAG.getNode(ISD::FSUB, dl, MVT::f64, HiFlt, TwoP84PlusTwoP52); + return DAG.getNode(ISD::FADD, dl, MVT::f64, LoFlt, HiSub); + } + SDValue Tmp1 = DAG.getNode(ISD::SINT_TO_FP, dl, DestVT, Op0); SDValue SignSet = DAG.getSetCC(dl, TLI.getSetCCResultType(Op0.getValueType()), @@ -2004,13 +2065,13 @@ SDValue SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned, if (DestVT == MVT::f32) FudgeInReg = DAG.getLoad(MVT::f32, dl, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, - false, Alignment); + false, false, Alignment); else { FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, dl, DestVT, DAG.getEntryNode(), CPIdx, PseudoSourceValue::getConstantPool(), 0, - MVT::f32, false, Alignment)); + MVT::f32, false, false, Alignment)); } return DAG.getNode(ISD::FADD, dl, DestVT, Tmp1, FudgeInReg); @@ -2271,7 +2332,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, false, false, false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/true, DAG.getExternalSymbol("abort", TLI.getPointerTy()), - Args, DAG, dl, DAG.GetOrdering(Node)); + Args, DAG, dl); Results.push_back(CallResult.second); break; } @@ -2350,16 +2411,19 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, EVT VT = Node->getValueType(0); Tmp1 = Node->getOperand(0); Tmp2 = Node->getOperand(1); - SDValue VAList = DAG.getLoad(TLI.getPointerTy(), dl, Tmp1, Tmp2, V, 0); + SDValue VAList = DAG.getLoad(TLI.getPointerTy(), dl, Tmp1, Tmp2, V, 0, + false, false, 0); // Increment the pointer, VAList, to the next vaarg Tmp3 = DAG.getNode(ISD::ADD, dl, TLI.getPointerTy(), VAList, DAG.getConstant(TLI.getTargetData()-> getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())), TLI.getPointerTy())); // Store the incremented VAList to the legalized pointer - Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Tmp2, V, 0); + Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Tmp2, V, 0, + false, false, 0); // Load the actual argument out of the pointer VAList - Results.push_back(DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0)); + Results.push_back(DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0, + false, false, 0)); Results.push_back(Results[0].getValue(1)); break; } @@ -2369,8 +2433,9 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, const Value *VD = cast(Node->getOperand(3))->getValue(); const Value *VS = cast(Node->getOperand(4))->getValue(); Tmp1 = DAG.getLoad(TLI.getPointerTy(), dl, Node->getOperand(0), - Node->getOperand(2), VS, 0); - Tmp1 = DAG.getStore(Tmp1.getValue(1), dl, Tmp1, Node->getOperand(1), VD, 0); + Node->getOperand(2), VS, 0, false, false, 0); + Tmp1 = DAG.getStore(Tmp1.getValue(1), dl, Tmp1, Node->getOperand(1), VD, 0, + false, false, 0); Results.push_back(Tmp1); break; } @@ -2827,7 +2892,8 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node, EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); SDValue LD = DAG.getExtLoad(ISD::SEXTLOAD, dl, PTy, Chain, Addr, - PseudoSourceValue::getJumpTable(), 0, MemVT); + PseudoSourceValue::getJumpTable(), 0, MemVT, + false, false, 0); Addr = LD; if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) { // For PIC, the sequence is: diff --git a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp index 4f0fce7434..35a7c7cedd 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -444,7 +444,7 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) { NewL = DAG.getLoad(L->getAddressingMode(), dl, L->getExtensionType(), NVT, L->getChain(), L->getBasePtr(), L->getOffset(), L->getSrcValue(), L->getSrcValueOffset(), NVT, - L->isVolatile(), L->getAlignment()); + L->isVolatile(), L->isNonTemporal(), L->getAlignment()); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); @@ -456,8 +456,8 @@ SDValue DAGTypeLegalizer::SoftenFloatRes_LOAD(SDNode *N) { L->getMemoryVT(), L->getChain(), L->getBasePtr(), L->getOffset(), L->getSrcValue(), L->getSrcValueOffset(), - L->getMemoryVT(), - L->isVolatile(), L->getAlignment()); + L->getMemoryVT(), L->isVolatile(), + L->isNonTemporal(), L->getAlignment()); // Legalized the chain result - switch anything that used the old chain to // use the new one. ReplaceValueWith(SDValue(N, 1), NewL.getValue(1)); @@ -755,7 +755,8 @@ SDValue DAGTypeLegalizer::SoftenFloatOp_STORE(SDNode *N, unsigned OpNo) { return DAG.getStore(ST->getChain(), dl, Val, ST->getBasePtr(), ST->getSrcValue(), ST->getSrcValueOffset(), - ST->isVolatile(), ST->getAlignment()); + ST->isVolatile(), ST->isNonTemporal(), + ST->getAlignment()); } @@ -1073,8 +1074,8 @@ void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo, Hi = DAG.getExtLoad(LD->getExtensionType(), dl, NVT, Chain, Ptr, LD->getSrcValue(), LD->getSrcValueOffset(), - LD->getMemoryVT(), - LD->isVolatile(), LD->getAlignment()); + LD->getMemoryVT(), LD->isVolatile(), + LD->isNonTemporal(), LD->getAlignment()); // Remember the chain. Chain = Hi.getValue(1); @@ -1382,6 +1383,6 @@ SDValue DAGTypeLegalizer::ExpandFloatOp_STORE(SDNode *N, unsigned OpNo) { return DAG.getTruncStore(Chain, N->getDebugLoc(), Hi, Ptr, ST->getSrcValue(), ST->getSrcValueOffset(), - ST->getMemoryVT(), - ST->isVolatile(), ST->getAlignment()); + ST->getMemoryVT(), ST->isVolatile(), + ST->isNonTemporal(), ST->getAlignment()); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 9932cf49eb..81f28adc0d 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -359,7 +359,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) { SDValue Res = DAG.getExtLoad(ExtType, dl, NVT, N->getChain(), N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), N->getMemoryVT(), N->isVolatile(), - N->getAlignment()); + N->isNonTemporal(), N->getAlignment()); // Legalized the chain result - switch anything that used the old chain to // use the new one. @@ -873,6 +873,7 @@ SDValue DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); DebugLoc dl = N->getDebugLoc(); SDValue Val = GetPromotedInteger(N->getValue()); // Get promoted value. @@ -880,7 +881,7 @@ SDValue DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ // Truncate the value and store the result. return DAG.getTruncStore(Ch, dl, Val, Ptr, N->getSrcValue(), SVOffset, N->getMemoryVT(), - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); } SDValue DAGTypeLegalizer::PromoteIntOp_TRUNCATE(SDNode *N) { @@ -1079,8 +1080,8 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi) { SDValue Amt = N->getOperand(1); EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); EVT ShTy = Amt.getValueType(); - unsigned ShBits = ShTy.getSizeInBits(); - unsigned NVTBits = NVT.getSizeInBits(); + unsigned ShBits = ShTy.getScalarType().getSizeInBits(); + unsigned NVTBits = NVT.getScalarType().getSizeInBits(); assert(isPowerOf2_32(NVTBits) && "Expanded integer type size not a power of two!"); DebugLoc dl = N->getDebugLoc(); @@ -1500,6 +1501,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); DebugLoc dl = N->getDebugLoc(); assert(NVT.isByteSized() && "Expanded type not byte sized!"); @@ -1508,7 +1510,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, EVT MemVT = N->getMemoryVT(); Lo = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, - MemVT, isVolatile, Alignment); + MemVT, isVolatile, isNonTemporal, Alignment); // Remember the chain. Ch = Lo.getValue(1); @@ -1530,7 +1532,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, } else if (TLI.isLittleEndian()) { // Little-endian - low bits are at low addresses. Lo = DAG.getLoad(NVT, dl, Ch, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); unsigned ExcessBits = N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); @@ -1542,7 +1544,8 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize, NEVT, - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the // other one. @@ -1560,7 +1563,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, Hi = DAG.getExtLoad(ExtType, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT::getIntegerVT(*DAG.getContext(), MemVT.getSizeInBits() - ExcessBits), - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -1569,7 +1572,8 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, Lo = DAG.getExtLoad(ISD::ZEXTLOAD, dl, NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize, EVT::getIntegerVT(*DAG.getContext(), ExcessBits), - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the // other one. @@ -2212,6 +2216,7 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); + bool isNonTemporal = N->isNonTemporal(); DebugLoc dl = N->getDebugLoc(); SDValue Lo, Hi; @@ -2220,13 +2225,14 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { if (N->getMemoryVT().bitsLE(NVT)) { GetExpandedInteger(N->getValue(), Lo, Hi); return DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, - N->getMemoryVT(), isVolatile, Alignment); + N->getMemoryVT(), isVolatile, isNonTemporal, + Alignment); } else if (TLI.isLittleEndian()) { // Little-endian - low bits are at low addresses. GetExpandedInteger(N->getValue(), Lo, Hi); Lo = DAG.getStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); unsigned ExcessBits = N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits(); @@ -2238,7 +2244,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, NEVT, - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } else { // Big-endian - high bits are at low addresses. Favor aligned stores at @@ -2264,7 +2271,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { // Store both the high bits and maybe some of the low bits. Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), - SVOffset, HiVT, isVolatile, Alignment); + SVOffset, HiVT, isVolatile, isNonTemporal, + Alignment); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -2273,7 +2281,8 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { Lo = DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset+IncrementSize, EVT::getIntegerVT(*DAG.getContext(), ExcessBits), - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } } @@ -2341,7 +2350,7 @@ SDValue DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) { // FIXME: Avoid the extend by constructing the right constant pool? SDValue Fudge = DAG.getExtLoad(ISD::EXTLOAD, dl, DstVT, DAG.getEntryNode(), FudgePtr, NULL, 0, MVT::f32, - false, Alignment); + false, false, Alignment); return DAG.getNode(ISD::FADD, dl, DstVT, SignedConv, Fudge); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index 37f36a3ea3..f3e7ca4fa3 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -871,9 +871,10 @@ SDValue DAGTypeLegalizer::CreateStackStoreLoad(SDValue Op, // the source and destination types. SDValue StackPtr = DAG.CreateStackTemporary(Op.getValueType(), DestVT); // Emit a store to the stack slot. - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Op, StackPtr, NULL, 0); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Op, StackPtr, NULL, 0, + false, false, 0); // Result is a load from the stack slot. - return DAG.getLoad(DestVT, dl, Store, StackPtr, NULL, 0); + return DAG.getLoad(DestVT, dl, Store, StackPtr, NULL, 0, false, false, 0); } /// CustomLowerNode - Replace the node's results with custom code provided @@ -1033,8 +1034,7 @@ SDValue DAGTypeLegalizer::MakeLibCall(RTLIB::Libcall LC, EVT RetVT, TLI.LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, false, 0, TLI.getLibcallCallingConv(LC), false, /*isReturnValueUsed=*/true, - Callee, Args, DAG, dl, - DAG.GetOrdering(DAG.getEntryNode().getNode())); + Callee, Args, DAG, dl); return CallInfo.first; } diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp index a1b6ced0c4..5e83b4ba33 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -122,10 +122,11 @@ void DAGTypeLegalizer::ExpandRes_BIT_CONVERT(SDNode *N, SDValue &Lo, const Value *SV = PseudoSourceValue::getFixedStack(SPFI); // Emit a store to the stack slot. - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, SV, 0); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, InOp, StackPtr, SV, 0, + false, false, 0); // Load the first half from the stack slot. - Lo = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, 0); + Lo = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, 0, false, false, 0); // Increment the pointer to the other half. unsigned IncrementSize = NOutVT.getSizeInBits() / 8; @@ -134,7 +135,7 @@ void DAGTypeLegalizer::ExpandRes_BIT_CONVERT(SDNode *N, SDValue &Lo, // Load the second half from the stack slot. Hi = DAG.getLoad(NOutVT, dl, Store, StackPtr, SV, IncrementSize, false, - MinAlign(Alignment, IncrementSize)); + false, MinAlign(Alignment, IncrementSize)); // Handle endianness of the load. if (TLI.isBigEndian()) @@ -205,11 +206,12 @@ void DAGTypeLegalizer::ExpandRes_NormalLoad(SDNode *N, SDValue &Lo, int SVOffset = LD->getSrcValueOffset(); unsigned Alignment = LD->getAlignment(); bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); assert(NVT.isByteSized() && "Expanded type not byte sized!"); Lo = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); // Increment the pointer to the other half. unsigned IncrementSize = NVT.getSizeInBits() / 8; @@ -217,7 +219,8 @@ void DAGTypeLegalizer::ExpandRes_NormalLoad(SDNode *N, SDValue &Lo, DAG.getIntPtrConstant(IncrementSize)); Hi = DAG.getLoad(NVT, dl, Chain, Ptr, LD->getSrcValue(), SVOffset+IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); // Build a factor node to remember that this load is independent of the // other one. @@ -383,6 +386,7 @@ SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) { int SVOffset = St->getSrcValueOffset(); unsigned Alignment = St->getAlignment(); bool isVolatile = St->isVolatile(); + bool isNonTemporal = St->isNonTemporal(); assert(NVT.isByteSized() && "Expanded type not byte sized!"); unsigned IncrementSize = NVT.getSizeInBits() / 8; @@ -394,14 +398,15 @@ SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) { std::swap(Lo, Hi); Lo = DAG.getStore(Chain, dl, Lo, Ptr, St->getSrcValue(), SVOffset, - isVolatile, Alignment); + isVolatile, isNonTemporal, Alignment); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getIntPtrConstant(IncrementSize)); assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); Hi = DAG.getStore(Chain, dl, Hi, Ptr, St->getSrcValue(), SVOffset + IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); + isVolatile, isNonTemporal, + MinAlign(Alignment, IncrementSize)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index bf95bb532f..8363c3af21 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -172,7 +172,8 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) { DAG.getUNDEF(N->getBasePtr().getValueType()), N->getSrcValue(), N->getSrcValueOffset(), N->getMemoryVT().getVectorElementType(), - N->isVolatile(), N->getOriginalAlignment()); + N->isVolatile(), N->isNonTemporal(), + N->getOriginalAlignment()); // Legalized the chain result - switch anything that used the old chain to // use the new one. @@ -366,11 +367,13 @@ SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){ N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), N->getMemoryVT().getVectorElementType(), - N->isVolatile(), N->getAlignment()); + N->isVolatile(), N->isNonTemporal(), + N->getAlignment()); return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)), N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(), - N->isVolatile(), N->getOriginalAlignment()); + N->isVolatile(), N->isNonTemporal(), + N->getOriginalAlignment()); } @@ -696,17 +699,20 @@ void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, EVT VecVT = Vec.getValueType(); EVT EltVT = VecVT.getVectorElementType(); SDValue StackPtr = DAG.CreateStackTemporary(VecVT); - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, NULL, 0, + false, false, 0); // Store the new element. This may be larger than the vector element type, // so use a truncating store. SDValue EltPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); unsigned Alignment = TLI.getTargetData()->getPrefTypeAlignment(VecVT.getTypeForEVT(*DAG.getContext())); - Store = DAG.getTruncStore(Store, dl, Elt, EltPtr, NULL, 0, EltVT); + Store = DAG.getTruncStore(Store, dl, Elt, EltPtr, NULL, 0, EltVT, + false, false, 0); // Load the Lo part from the stack slot. - Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, NULL, 0); + Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, NULL, 0, + false, false, 0); // Increment the pointer to the other part. unsigned IncrementSize = Lo.getValueType().getSizeInBits() / 8; @@ -715,7 +721,7 @@ void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo, // Load the Hi part from the stack slot. Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, NULL, 0, false, - MinAlign(Alignment, IncrementSize)); + false, MinAlign(Alignment, IncrementSize)); } void DAGTypeLegalizer::SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, @@ -743,19 +749,20 @@ void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo, EVT MemoryVT = LD->getMemoryVT(); unsigned Alignment = LD->getOriginalAlignment(); bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); EVT LoMemVT, HiMemVT; GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT); Lo = DAG.getLoad(ISD::UNINDEXED, dl, ExtType, LoVT, Ch, Ptr, Offset, - SV, SVOffset, LoMemVT, isVolatile, Alignment); + SV, SVOffset, LoMemVT, isVolatile, isNonTemporal, Alignment); unsigned IncrementSize = LoMemVT.getSizeInBits()/8; Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getIntPtrConstant(IncrementSize)); SVOffset += IncrementSize; Hi = DAG.getLoad(ISD::UNINDEXED, dl, ExtType, HiVT, Ch, Ptr, Offset, - SV, SVOffset, HiMemVT, isVolatile, Alignment); + SV, SVOffset, HiMemVT, isVolatile, isNonTemporal, Alignment); // Build a factor node to remember that this load is independent of the // other one. @@ -1086,12 +1093,13 @@ SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) { SDValue StackPtr = DAG.CreateStackTemporary(VecVT); int SPFI = cast(StackPtr.getNode())->getIndex(); const Value *SV = PseudoSourceValue::getFixedStack(SPFI); - SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, SV, 0); + SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr, SV, 0, + false, false, 0); // Load back the required element. StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx); return DAG.getExtLoad(ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr, - SV, 0, EltVT); + SV, 0, EltVT, false, false, 0); } SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { @@ -1106,6 +1114,7 @@ SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { EVT MemoryVT = N->getMemoryVT(); unsigned Alignment = N->getOriginalAlignment(); bool isVol = N->isVolatile(); + bool isNT = N->isNonTemporal(); SDValue Lo, Hi; GetSplitVector(N->getOperand(1), Lo, Hi); @@ -1116,10 +1125,10 @@ SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { if (isTruncating) Lo = DAG.getTruncStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, - LoMemVT, isVol, Alignment); + LoMemVT, isVol, isNT, Alignment); else Lo = DAG.getStore(Ch, dl, Lo, Ptr, N->getSrcValue(), SVOffset, - isVol, Alignment); + isVol, isNT, Alignment); // Increment the pointer to the other half. Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, @@ -1128,10 +1137,10 @@ SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) { if (isTruncating) Hi = DAG.getTruncStore(Ch, dl, Hi, Ptr, N->getSrcValue(), SVOffset, - HiMemVT, isVol, Alignment); + HiMemVT, isVol, isNT, Alignment); else Hi = DAG.getStore(Ch, dl, Hi, Ptr, N->getSrcValue(), SVOffset, - isVol, Alignment); + isVol, isNT, Alignment); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi); } @@ -1242,10 +1251,96 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) { // Binary op widening. + unsigned Opcode = N->getOpcode(); + DebugLoc dl = N->getDebugLoc(); EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); - SDValue InOp1 = GetWidenedVector(N->getOperand(0)); - SDValue InOp2 = GetWidenedVector(N->getOperand(1)); - return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp1, InOp2); + EVT WidenEltVT = WidenVT.getVectorElementType(); + EVT VT = WidenVT; + unsigned NumElts = VT.getVectorNumElements(); + while (!TLI.isTypeLegal(VT) && NumElts != 1) { + NumElts = NumElts / 2; + VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts); + } + + if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) { + // Operation doesn't trap so just widen as normal. + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2); + } else if (NumElts == 1) { + // No legal vector version so unroll the vector operation and then widen. + return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements()); + } else { + // Since the operation can trap, apply operation on the original vector. + SDValue InOp1 = GetWidenedVector(N->getOperand(0)); + SDValue InOp2 = GetWidenedVector(N->getOperand(1)); + unsigned CurNumElts = N->getValueType(0).getVectorNumElements(); + + SmallVector ConcatOps(CurNumElts); + unsigned ConcatEnd = 0; // Current ConcatOps index. + unsigned Idx = 0; // Current Idx into input vectors. + while (CurNumElts != 0) { + while (CurNumElts >= NumElts) { + SDValue EOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp1, + DAG.getIntPtrConstant(Idx)); + SDValue EOp2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp2, + DAG.getIntPtrConstant(Idx)); + ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2); + Idx += NumElts; + CurNumElts -= NumElts; + } + EVT PrevVecVT = VT; + do { + NumElts = NumElts / 2; + VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts); + } while (!TLI.isTypeLegal(VT) && NumElts != 1); + + if (NumElts == 1) { + // Since we are using concat vector, build a vector from the scalar ops. + SDValue VecOp = DAG.getUNDEF(PrevVecVT); + for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) { + SDValue EOp1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT, + InOp1, DAG.getIntPtrConstant(Idx)); + SDValue EOp2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT, + InOp2, DAG.getIntPtrConstant(Idx)); + VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, PrevVecVT, VecOp, + DAG.getNode(Opcode, dl, WidenEltVT, EOp1, EOp2), + DAG.getIntPtrConstant(i)); + } + CurNumElts = 0; + ConcatOps[ConcatEnd++] = VecOp; + } + } + + // Check to see if we have a single operation with the widen type. + if (ConcatEnd == 1) { + VT = ConcatOps[0].getValueType(); + if (VT == WidenVT) + return ConcatOps[0]; + } + + // Rebuild vector to one with the widen type + Idx = ConcatEnd - 1; + while (Idx != 0) { + VT = ConcatOps[Idx--].getValueType(); + while (Idx != 0 && ConcatOps[Idx].getValueType() == VT) + --Idx; + if (Idx != 0) { + VT = ConcatOps[Idx].getValueType(); + ConcatOps[Idx+1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, VT, + &ConcatOps[Idx+1], ConcatEnd - Idx - 1); + ConcatEnd = Idx + 2; + } + } + + unsigned NumOps = WidenVT.getVectorNumElements()/VT.getVectorNumElements(); + if (NumOps != ConcatEnd ) { + SDValue UndefVal = DAG.getUNDEF(VT); + for (unsigned j = ConcatEnd; j < NumOps; ++j) + ConcatOps[j] = UndefVal; + } + return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &ConcatOps[0], NumOps); + } } SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) { @@ -2042,6 +2137,7 @@ SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVector& LdChain, int SVOffset = LD->getSrcValueOffset(); unsigned Align = LD->getAlignment(); bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); const Value *SV = LD->getSrcValue(); int LdWidth = LdVT.getSizeInBits(); @@ -2052,7 +2148,7 @@ SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVector& LdChain, EVT NewVT = FindMemType(DAG, TLI, LdWidth, WidenVT, LdAlign, WidthDiff); int NewVTWidth = NewVT.getSizeInBits(); SDValue LdOp = DAG.getLoad(NewVT, dl, Chain, BasePtr, SV, SVOffset, - isVolatile, Align); + isVolatile, isNonTemporal, Align); LdChain.push_back(LdOp.getValue(1)); // Check if we can load the element with one instruction @@ -2099,7 +2195,7 @@ SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVector& LdChain, SDValue LdOp = DAG.getLoad(NewVT, dl, Chain, BasePtr, SV, SVOffset+Offset, isVolatile, - MinAlign(Align, Increment)); + isNonTemporal, MinAlign(Align, Increment)); LdChain.push_back(LdOp.getValue(1)); LdOps.push_back(LdOp); @@ -2173,6 +2269,7 @@ DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVector& LdChain, int SVOffset = LD->getSrcValueOffset(); unsigned Align = LD->getAlignment(); bool isVolatile = LD->isVolatile(); + bool isNonTemporal = LD->isNonTemporal(); const Value *SV = LD->getSrcValue(); EVT EltVT = WidenVT.getVectorElementType(); @@ -2184,14 +2281,15 @@ DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVector& LdChain, SmallVector Ops(WidenNumElts); unsigned Increment = LdEltVT.getSizeInBits() / 8; Ops[0] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr, SV, SVOffset, - LdEltVT, isVolatile, Align); + LdEltVT, isVolatile, isNonTemporal, Align); LdChain.push_back(Ops[0].getValue(1)); unsigned i = 0, Offset = Increment; for (i=1; i < NumElts; ++i, Offset += Increment) { SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, DAG.getIntPtrConstant(Offset)); Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr, SV, - SVOffset + Offset, LdEltVT, isVolatile, Align); + SVOffset + Offset, LdEltVT, isVolatile, + isNonTemporal, Align); LdChain.push_back(Ops[i].getValue(1)); } @@ -2215,6 +2313,7 @@ void DAGTypeLegalizer::GenWidenVectorStores(SmallVector& StChain, int SVOffset = ST->getSrcValueOffset(); unsigned Align = ST->getAlignment(); bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); SDValue ValOp = GetWidenedVector(ST->getValue()); DebugLoc dl = ST->getDebugLoc(); @@ -2240,6 +2339,7 @@ void DAGTypeLegalizer::GenWidenVectorStores(SmallVector& StChain, DAG.getIntPtrConstant(Idx)); StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, SV, SVOffset + Offset, isVolatile, + isNonTemporal, MinAlign(Align, Offset))); StWidth -= NewVTWidth; Offset += Increment; @@ -2258,8 +2358,8 @@ void DAGTypeLegalizer::GenWidenVectorStores(SmallVector& StChain, SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, VecOp, DAG.getIntPtrConstant(Idx++)); StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr, SV, - SVOffset + Offset, isVolatile, - MinAlign(Align, Offset))); + SVOffset + Offset, isVolatile, + isNonTemporal, MinAlign(Align, Offset))); StWidth -= NewVTWidth; Offset += Increment; BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr, @@ -2282,6 +2382,7 @@ DAGTypeLegalizer::GenWidenVectorTruncStores(SmallVector& StChain, int SVOffset = ST->getSrcValueOffset(); unsigned Align = ST->getAlignment(); bool isVolatile = ST->isVolatile(); + bool isNonTemporal = ST->isNonTemporal(); SDValue ValOp = GetWidenedVector(ST->getValue()); DebugLoc dl = ST->getDebugLoc(); @@ -2304,7 +2405,7 @@ DAGTypeLegalizer::GenWidenVectorTruncStores(SmallVector& StChain, DAG.getIntPtrConstant(0)); StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, BasePtr, SV, SVOffset, StEltVT, - isVolatile, Align)); + isVolatile, isNonTemporal, Align)); unsigned Offset = Increment; for (unsigned i=1; i < NumElts; ++i, Offset += Increment) { SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), @@ -2313,7 +2414,8 @@ DAGTypeLegalizer::GenWidenVectorTruncStores(SmallVector& StChain, DAG.getIntPtrConstant(0)); StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, NewBasePtr, SV, SVOffset + Offset, StEltVT, - isVolatile, MinAlign(Align, Offset))); + isVolatile, isNonTemporal, + MinAlign(Align, Offset))); } } diff --git a/lib/CodeGen/SelectionDAG/SDDbgValue.h b/lib/CodeGen/SelectionDAG/SDDbgValue.h new file mode 100644 index 0000000000..9e15fc98bc --- /dev/null +++ b/lib/CodeGen/SelectionDAG/SDDbgValue.h @@ -0,0 +1,67 @@ +//===-- llvm/CodeGen/SDDbgValue.h - SD dbg_value handling--------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SDDbgValue class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SDDBGVALUE_H +#define LLVM_CODEGEN_SDDBGVALUE_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DebugLoc.h" + +namespace llvm { + +class MDNode; +class SDNode; +class Value; + +/// SDDbgValue - Holds the information from a dbg_value node through SDISel. +/// Either Const or Node is nonzero, but not both. +/// We do not use SDValue here to avoid including its header. + +class SDDbgValue { + SDNode *Node; // valid for non-constants + unsigned ResNo; // valid for non-constants + Value *Const; // valid for constants + MDNode *mdPtr; + uint64_t Offset; + DebugLoc DL; +public: + // Constructor for non-constants. + SDDbgValue(MDNode *mdP, SDNode *N, unsigned R, uint64_t off, DebugLoc dl) : + Node(N), ResNo(R), Const(0), mdPtr(mdP), Offset(off), DL(dl) {} + + // Constructor for constants. + SDDbgValue(MDNode *mdP, Value *C, uint64_t off, DebugLoc dl) : Node(0), + ResNo(0), Const(C), mdPtr(mdP), Offset(off), DL(dl) {} + + // Returns the MDNode pointer. + MDNode *getMDPtr() { return mdPtr; } + + // Returns the SDNode* (valid for non-constants only). + SDNode *getSDNode() { assert (!Const); return Node; } + + // Returns the ResNo (valid for non-constants only). + unsigned getResNo() { assert (!Const); return ResNo; } + + // Returns the Value* for a constant (invalid for non-constants). + Value *getConst() { assert (!Node); return Const; } + + // Returns the offset. + uint64_t getOffset() { return Offset; } + + // Returns the DebugLoc. + DebugLoc getDebugLoc() { return DL; } +}; + +} // end llvm namespace + +#endif diff --git a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index b51c61bf6d..06e7b8c905 100644 --- a/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -218,8 +218,20 @@ void ScheduleDAGSDNodes::BuildSchedUnits() { // Check to see if the scheduler cares about latencies. bool UnitLatencies = ForceUnitLatencies(); - for (SelectionDAG::allnodes_iterator NI = DAG->allnodes_begin(), - E = DAG->allnodes_end(); NI != E; ++NI) { + // Add all nodes in depth first order. + SmallVector Worklist; + SmallPtrSet Visited; + Worklist.push_back(DAG->getRoot().getNode()); + Visited.insert(DAG->getRoot().getNode()); + + while (!Worklist.empty()) { + SDNode *NI = Worklist.pop_back_val(); + + // Add all operands to the worklist unless they've already been added. + for (unsigned i = 0, e = NI->getNumOperands(); i != e; ++i) + if (Visited.insert(NI->getOperand(i).getNode())) + Worklist.push_back(NI->getOperand(i).getNode()); + if (isPassiveNode(NI)) // Leaf node, e.g. a TargetImmediate. continue; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 6122a2ae27..746d4e2e1a 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -468,18 +468,20 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, const SDNode *N) { } /// encodeMemSDNodeFlags - Generic routine for computing a value for use in -/// the CSE map that carries volatility, indexing mode, and +/// the CSE map that carries volatility, temporalness, indexing mode, and /// extension/truncation information. /// static inline unsigned -encodeMemSDNodeFlags(int ConvType, ISD::MemIndexedMode AM, bool isVolatile) { +encodeMemSDNodeFlags(int ConvType, ISD::MemIndexedMode AM, bool isVolatile, + bool isNonTemporal) { assert((ConvType & 3) == ConvType && "ConvType may not require more than 2 bits!"); assert((AM & 7) == AM && "AM may not require more than 3 bits!"); return ConvType | (AM << 2) | - (isVolatile << 5); + (isVolatile << 5) | + (isNonTemporal << 6); } //===----------------------------------------------------------------------===// @@ -829,6 +831,7 @@ void SelectionDAG::clear() { EntryNode.UseList = 0; AllNodes.push_back(&EntryNode); Root = getEntryNode(); + delete Ordering; Ordering = new SDNodeOrdering(); } @@ -859,14 +862,14 @@ SDValue SelectionDAG::getZeroExtendInReg(SDValue Op, DebugLoc DL, EVT VT) { /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). /// SDValue SelectionDAG::getNOT(DebugLoc DL, SDValue Val, EVT VT) { - EVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + EVT EltVT = VT.getScalarType(); SDValue NegOne = getConstant(APInt::getAllOnesValue(EltVT.getSizeInBits()), VT); return getNode(ISD::XOR, DL, VT, Val, NegOne); } SDValue SelectionDAG::getConstant(uint64_t Val, EVT VT, bool isT) { - EVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + EVT EltVT = VT.getScalarType(); assert((EltVT.getSizeInBits() >= 64 || (uint64_t)((int64_t)Val >> EltVT.getSizeInBits()) + 1 < 2) && "getConstant with a uint64_t value that doesn't fit in the type!"); @@ -880,7 +883,7 @@ SDValue SelectionDAG::getConstant(const APInt &Val, EVT VT, bool isT) { SDValue SelectionDAG::getConstant(const ConstantInt &Val, EVT VT, bool isT) { assert(VT.isInteger() && "Cannot create FP integer constant!"); - EVT EltVT = VT.isVector() ? VT.getVectorElementType() : VT; + EVT EltVT = VT.getScalarType(); assert(Val.getBitWidth() == EltVT.getSizeInBits() && "APInt size does not match type size!"); @@ -923,8 +926,7 @@ SDValue SelectionDAG::getConstantFP(const APFloat& V, EVT VT, bool isTarget) { SDValue SelectionDAG::getConstantFP(const ConstantFP& V, EVT VT, bool isTarget){ assert(VT.isFloatingPoint() && "Cannot create integer FP constant!"); - EVT EltVT = - VT.isVector() ? VT.getVectorElementType() : VT; + EVT EltVT = VT.getScalarType(); // Do the map lookup using the actual bit pattern for the floating point // value, so that we don't have problems with 0.0 comparing equal to -0.0, and @@ -958,8 +960,7 @@ SDValue SelectionDAG::getConstantFP(const ConstantFP& V, EVT VT, bool isTarget){ } SDValue SelectionDAG::getConstantFP(double Val, EVT VT, bool isTarget) { - EVT EltVT = - VT.isVector() ? VT.getVectorElementType() : VT; + EVT EltVT = VT.getScalarType(); if (EltVT==MVT::f32) return getConstantFP(APFloat((float)Val), VT, isTarget); else @@ -1344,7 +1345,7 @@ SDValue SelectionDAG::getBlockAddress(BlockAddress *BA, EVT VT, } SDValue SelectionDAG::getSrcValue(const Value *V) { - assert((!V || isa(V->getType())) && + assert((!V || V->getType()->isPointerTy()) && "SrcValue is not a pointer?"); FoldingSetNodeID ID; @@ -2232,6 +2233,29 @@ bool SelectionDAG::isKnownNeverNaN(SDValue Op) const { return false; } +bool SelectionDAG::isKnownNeverZero(SDValue Op) const { + // If the value is a constant, we can obviously see if it is a zero or not. + if (const ConstantFPSDNode *C = dyn_cast(Op)) + return !C->isZero(); + + // TODO: Recognize more cases here. + + return false; +} + +bool SelectionDAG::isEqualTo(SDValue A, SDValue B) const { + // Check the obvious case. + if (A == B) return true; + + // For for negative and positive zero. + if (const ConstantFPSDNode *CA = dyn_cast(A)) + if (const ConstantFPSDNode *CB = dyn_cast(B)) + if (CA->isZero() && CB->isZero()) return true; + + // Otherwise they may not be equal. + return false; +} + bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const { GlobalAddressSDNode *GA = dyn_cast(Op); if (!GA) return false; @@ -3080,8 +3104,7 @@ SDValue SelectionDAG::getStackArgumentTokenFactor(SDValue Chain) { /// operand. static SDValue getMemsetValue(SDValue Value, EVT VT, SelectionDAG &DAG, DebugLoc dl) { - unsigned NumBits = VT.isVector() ? - VT.getVectorElementType().getSizeInBits() : VT.getSizeInBits(); + unsigned NumBits = VT.getScalarType().getSizeInBits(); if (ConstantSDNode *C = dyn_cast(Value)) { APInt Val = APInt(NumBits, C->getZExtValue() & 255); unsigned Shift = 8; @@ -3185,7 +3208,7 @@ bool MeetsMaxMemopRequirement(std::vector &MemOps, bool isSrcConst = isa(Src); EVT VT = TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr, DAG); bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses(VT); - if (VT != MVT::iAny) { + if (VT != MVT::Other) { const Type *Ty = VT.getTypeForEVT(*DAG.getContext()); unsigned NewAlign = (unsigned) TLI.getTargetData()->getABITypeAlignment(Ty); // If source is a string constant, this will require an unaligned load. @@ -3193,14 +3216,14 @@ bool MeetsMaxMemopRequirement(std::vector &MemOps, if (Dst.getOpcode() != ISD::FrameIndex) { // Can't change destination alignment. It requires a unaligned store. if (AllowUnalign) - VT = MVT::iAny; + VT = MVT::Other; } else { int FI = cast(Dst)->getIndex(); MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); if (MFI->isFixedObjectIndex(FI)) { // Can't change destination alignment. It requires a unaligned store. if (AllowUnalign) - VT = MVT::iAny; + VT = MVT::Other; } else { // Give the stack frame object a larger alignment if needed. if (MFI->getObjectAlignment(FI) < NewAlign) @@ -3211,7 +3234,7 @@ bool MeetsMaxMemopRequirement(std::vector &MemOps, } } - if (VT == MVT::iAny) { + if (VT == MVT::Other) { if (TLI.allowsUnalignedMemoryAccesses(MVT::i64)) { VT = MVT::i64; } else { @@ -3299,7 +3322,7 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Value = getMemsetStringVal(VT, dl, DAG, TLI, Str, SrcOff); Store = DAG.getStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, DstAlign); + DstSV, DstSVOff + DstOff, false, false, DstAlign); } else { // The type might not be legal for the target. This should only happen // if the type is smaller than a legal type, as on PPC, so the right @@ -3310,10 +3333,11 @@ static SDValue getMemcpyLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, assert(NVT.bitsGE(VT)); Value = DAG.getExtLoad(ISD::EXTLOAD, dl, NVT, Chain, getMemBasePlusOffset(Src, SrcOff, DAG), - SrcSV, SrcSVOff + SrcOff, VT, false, Align); + SrcSV, SrcSVOff + SrcOff, VT, false, false, Align); Store = DAG.getTruncStore(Chain, dl, Value, - getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, VT, false, DstAlign); + getMemBasePlusOffset(Dst, DstOff, DAG), + DstSV, DstSVOff + DstOff, VT, false, false, + DstAlign); } OutChains.push_back(Store); SrcOff += VTSize; @@ -3358,7 +3382,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Value = DAG.getLoad(VT, dl, Chain, getMemBasePlusOffset(Src, SrcOff, DAG), - SrcSV, SrcSVOff + SrcOff, false, Align); + SrcSV, SrcSVOff + SrcOff, false, false, Align); LoadValues.push_back(Value); LoadChains.push_back(Value.getValue(1)); SrcOff += VTSize; @@ -3373,7 +3397,7 @@ static SDValue getMemmoveLoadsAndStores(SelectionDAG &DAG, DebugLoc dl, Store = DAG.getStore(Chain, dl, LoadValues[i], getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff, false, DstAlign); + DstSV, DstSVOff + DstOff, false, false, DstAlign); OutChains.push_back(Store); DstOff += VTSize; } @@ -3408,7 +3432,7 @@ static SDValue getMemsetStores(SelectionDAG &DAG, DebugLoc dl, SDValue Value = getMemsetValue(Src, VT, DAG, dl); SDValue Store = DAG.getStore(Chain, dl, Value, getMemBasePlusOffset(Dst, DstOff, DAG), - DstSV, DstSVOff + DstOff); + DstSV, DstSVOff + DstOff, false, false, 0); OutChains.push_back(Store); DstOff += VTSize; } @@ -3472,7 +3496,7 @@ SDValue SelectionDAG::getMemcpy(SDValue Chain, DebugLoc dl, SDValue Dst, /*isReturnValueUsed=*/false, getExternalSymbol(TLI.getLibcallName(RTLIB::MEMCPY), TLI.getPointerTy()), - Args, *this, dl, GetOrdering(Chain.getNode())); + Args, *this, dl); return CallResult.second; } @@ -3521,7 +3545,7 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, DebugLoc dl, SDValue Dst, /*isReturnValueUsed=*/false, getExternalSymbol(TLI.getLibcallName(RTLIB::MEMMOVE), TLI.getPointerTy()), - Args, *this, dl, GetOrdering(Chain.getNode())); + Args, *this, dl); return CallResult.second; } @@ -3580,7 +3604,7 @@ SDValue SelectionDAG::getMemset(SDValue Chain, DebugLoc dl, SDValue Dst, /*isReturnValueUsed=*/false, getExternalSymbol(TLI.getLibcallName(RTLIB::MEMSET), TLI.getPointerTy()), - Args, *this, dl, GetOrdering(Chain.getNode())); + Args, *this, dl); return CallResult.second; } @@ -3788,7 +3812,8 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, ISD::LoadExtType ExtType, EVT VT, SDValue Chain, SDValue Ptr, SDValue Offset, const Value *SV, int SVOffset, EVT MemVT, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { if (Alignment == 0) // Ensure that codegen never sees alignment 0 Alignment = getEVTAlignment(VT); @@ -3802,6 +3827,8 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, unsigned Flags = MachineMemOperand::MOLoad; if (isVolatile) Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; MachineMemOperand *MMO = MF.getMachineMemOperand(SV, Flags, SVOffset, MemVT.getStoreSize(), Alignment); @@ -3840,7 +3867,8 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::LOAD, VTs, Ops, 3); ID.AddInteger(MemVT.getRawBits()); - ID.AddInteger(encodeMemSDNodeFlags(ExtType, AM, MMO->isVolatile())); + ID.AddInteger(encodeMemSDNodeFlags(ExtType, AM, MMO->isVolatile(), + MMO->isNonTemporal())); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); @@ -3856,20 +3884,22 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl, SDValue SelectionDAG::getLoad(EVT VT, DebugLoc dl, SDValue Chain, SDValue Ptr, const Value *SV, int SVOffset, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { SDValue Undef = getUNDEF(Ptr.getValueType()); return getLoad(ISD::UNINDEXED, dl, ISD::NON_EXTLOAD, VT, Chain, Ptr, Undef, - SV, SVOffset, VT, isVolatile, Alignment); + SV, SVOffset, VT, isVolatile, isNonTemporal, Alignment); } SDValue SelectionDAG::getExtLoad(ISD::LoadExtType ExtType, DebugLoc dl, EVT VT, SDValue Chain, SDValue Ptr, const Value *SV, int SVOffset, EVT MemVT, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { SDValue Undef = getUNDEF(Ptr.getValueType()); return getLoad(ISD::UNINDEXED, dl, ExtType, VT, Chain, Ptr, Undef, - SV, SVOffset, MemVT, isVolatile, Alignment); + SV, SVOffset, MemVT, isVolatile, isNonTemporal, Alignment); } SDValue @@ -3881,12 +3911,13 @@ SelectionDAG::getIndexedLoad(SDValue OrigLoad, DebugLoc dl, SDValue Base, return getLoad(AM, dl, LD->getExtensionType(), OrigLoad.getValueType(), LD->getChain(), Base, Offset, LD->getSrcValue(), LD->getSrcValueOffset(), LD->getMemoryVT(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), LD->getAlignment()); } SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { if (Alignment == 0) // Ensure that codegen never sees alignment 0 Alignment = getEVTAlignment(Val.getValueType()); @@ -3900,6 +3931,8 @@ SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, unsigned Flags = MachineMemOperand::MOStore; if (isVolatile) Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; MachineMemOperand *MMO = MF.getMachineMemOperand(SV, Flags, SVOffset, Val.getValueType().getStoreSize(), Alignment); @@ -3916,7 +3949,8 @@ SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); ID.AddInteger(VT.getRawBits()); - ID.AddInteger(encodeMemSDNodeFlags(false, ISD::UNINDEXED, MMO->isVolatile())); + ID.AddInteger(encodeMemSDNodeFlags(false, ISD::UNINDEXED, MMO->isVolatile(), + MMO->isNonTemporal())); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); @@ -3932,7 +3966,8 @@ SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, SDValue Ptr, const Value *SV, int SVOffset, EVT SVT, - bool isVolatile, unsigned Alignment) { + bool isVolatile, bool isNonTemporal, + unsigned Alignment) { if (Alignment == 0) // Ensure that codegen never sees alignment 0 Alignment = getEVTAlignment(SVT); @@ -3946,6 +3981,8 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, unsigned Flags = MachineMemOperand::MOStore; if (isVolatile) Flags |= MachineMemOperand::MOVolatile; + if (isNonTemporal) + Flags |= MachineMemOperand::MONonTemporal; MachineMemOperand *MMO = MF.getMachineMemOperand(SV, Flags, SVOffset, SVT.getStoreSize(), Alignment); @@ -3976,7 +4013,8 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val, FoldingSetNodeID ID; AddNodeIDNode(ID, ISD::STORE, VTs, Ops, 4); ID.AddInteger(SVT.getRawBits()); - ID.AddInteger(encodeMemSDNodeFlags(true, ISD::UNINDEXED, MMO->isVolatile())); + ID.AddInteger(encodeMemSDNodeFlags(true, ISD::UNINDEXED, MMO->isVolatile(), + MMO->isNonTemporal())); void *IP = 0; if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP)) { cast(E)->refineAlignment(MMO); @@ -4535,91 +4573,13 @@ SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, SDVTList VTs, const SDValue *Ops, unsigned NumOps) { - return MorphNodeTo(N, ~MachineOpc, VTs, Ops, NumOps); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT) { - SDVTList VTs = getVTList(VT); - return MorphNodeTo(N, Opc, VTs, 0, 0); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT, SDValue Op1) { - SDVTList VTs = getVTList(VT); - SDValue Ops[] = { Op1 }; - return MorphNodeTo(N, Opc, VTs, Ops, 1); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT, SDValue Op1, - SDValue Op2) { - SDVTList VTs = getVTList(VT); - SDValue Ops[] = { Op1, Op2 }; - return MorphNodeTo(N, Opc, VTs, Ops, 2); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT, SDValue Op1, - SDValue Op2, SDValue Op3) { - SDVTList VTs = getVTList(VT); - SDValue Ops[] = { Op1, Op2, Op3 }; - return MorphNodeTo(N, Opc, VTs, Ops, 3); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT, const SDValue *Ops, - unsigned NumOps) { - SDVTList VTs = getVTList(VT); - return MorphNodeTo(N, Opc, VTs, Ops, NumOps); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT1, EVT VT2, const SDValue *Ops, - unsigned NumOps) { - SDVTList VTs = getVTList(VT1, VT2); - return MorphNodeTo(N, Opc, VTs, Ops, NumOps); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT1, EVT VT2) { - SDVTList VTs = getVTList(VT1, VT2); - return MorphNodeTo(N, Opc, VTs, (SDValue *)0, 0); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT1, EVT VT2, EVT VT3, - const SDValue *Ops, unsigned NumOps) { - SDVTList VTs = getVTList(VT1, VT2, VT3); - return MorphNodeTo(N, Opc, VTs, Ops, NumOps); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT1, EVT VT2, - SDValue Op1) { - SDVTList VTs = getVTList(VT1, VT2); - SDValue Ops[] = { Op1 }; - return MorphNodeTo(N, Opc, VTs, Ops, 1); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT1, EVT VT2, - SDValue Op1, SDValue Op2) { - SDVTList VTs = getVTList(VT1, VT2); - SDValue Ops[] = { Op1, Op2 }; - return MorphNodeTo(N, Opc, VTs, Ops, 2); -} - -SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, - EVT VT1, EVT VT2, - SDValue Op1, SDValue Op2, - SDValue Op3) { - SDVTList VTs = getVTList(VT1, VT2); - SDValue Ops[] = { Op1, Op2, Op3 }; - return MorphNodeTo(N, Opc, VTs, Ops, 3); + N = MorphNodeTo(N, ~MachineOpc, VTs, Ops, NumOps); + // Reset the NodeID to -1. + N->setNodeId(-1); + return N; } -/// MorphNodeTo - These *mutate* the specified node to have the specified +/// MorphNodeTo - This *mutates* the specified node to have the specified /// return type, opcode, and operands. /// /// Note that MorphNodeTo returns the resultant node. If there is already a @@ -4695,12 +4655,14 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, // Delete any nodes that are still dead after adding the uses for the // new operands. - SmallVector DeadNodes; - for (SmallPtrSet::iterator I = DeadNodeSet.begin(), - E = DeadNodeSet.end(); I != E; ++I) - if ((*I)->use_empty()) - DeadNodes.push_back(*I); - RemoveDeadNodes(DeadNodes); + if (!DeadNodeSet.empty()) { + SmallVector DeadNodes; + for (SmallPtrSet::iterator I = DeadNodeSet.begin(), + E = DeadNodeSet.end(); I != E; ++I) + if ((*I)->use_empty()) + DeadNodes.push_back(*I); + RemoveDeadNodes(DeadNodes); + } if (IP) CSEMap.InsertNode(N, IP); // Memoize the new node. @@ -4907,6 +4869,43 @@ SDNode *SelectionDAG::getNodeIfExists(unsigned Opcode, SDVTList VTList, return NULL; } +namespace { + +/// RAUWUpdateListener - Helper for ReplaceAllUsesWith - When the node +/// pointed to by a use iterator is deleted, increment the use iterator +/// so that it doesn't dangle. +/// +/// This class also manages a "downlink" DAGUpdateListener, to forward +/// messages to ReplaceAllUsesWith's callers. +/// +class RAUWUpdateListener : public SelectionDAG::DAGUpdateListener { + SelectionDAG::DAGUpdateListener *DownLink; + SDNode::use_iterator &UI; + SDNode::use_iterator &UE; + + virtual void NodeDeleted(SDNode *N, SDNode *E) { + // Increment the iterator as needed. + while (UI != UE && N == *UI) + ++UI; + + // Then forward the message. + if (DownLink) DownLink->NodeDeleted(N, E); + } + + virtual void NodeUpdated(SDNode *N) { + // Just forward the message. + if (DownLink) DownLink->NodeUpdated(N); + } + +public: + RAUWUpdateListener(SelectionDAG::DAGUpdateListener *dl, + SDNode::use_iterator &ui, + SDNode::use_iterator &ue) + : DownLink(dl), UI(ui), UE(ue) {} +}; + +} + /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. /// This can cause recursive merging of nodes in the DAG. /// @@ -4927,6 +4926,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To, // is replaced by To, we don't want to replace of all its users with To // too. See PR3018 for more info. SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + RAUWUpdateListener Listener(UpdateListener, UI, UE); while (UI != UE) { SDNode *User = *UI; @@ -4945,7 +4945,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To, // Now that we have modified User, add it back to the CSE maps. If it // already exists there, recursively merge the results together. - AddModifiedNodeToCSEMaps(User, UpdateListener); + AddModifiedNodeToCSEMaps(User, &Listener); } } @@ -4971,6 +4971,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To, // Iterate over just the existing users of From. See the comments in // the ReplaceAllUsesWith above. SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + RAUWUpdateListener Listener(UpdateListener, UI, UE); while (UI != UE) { SDNode *User = *UI; @@ -4989,7 +4990,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To, // Now that we have modified User, add it back to the CSE maps. If it // already exists there, recursively merge the results together. - AddModifiedNodeToCSEMaps(User, UpdateListener); + AddModifiedNodeToCSEMaps(User, &Listener); } } @@ -5007,6 +5008,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, // Iterate over just the existing users of From. See the comments in // the ReplaceAllUsesWith above. SDNode::use_iterator UI = From->use_begin(), UE = From->use_end(); + RAUWUpdateListener Listener(UpdateListener, UI, UE); while (UI != UE) { SDNode *User = *UI; @@ -5026,7 +5028,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, // Now that we have modified User, add it back to the CSE maps. If it // already exists there, recursively merge the results together. - AddModifiedNodeToCSEMaps(User, UpdateListener); + AddModifiedNodeToCSEMaps(User, &Listener); } } @@ -5048,6 +5050,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To, // the ReplaceAllUsesWith above. SDNode::use_iterator UI = From.getNode()->use_begin(), UE = From.getNode()->use_end(); + RAUWUpdateListener Listener(UpdateListener, UI, UE); while (UI != UE) { SDNode *User = *UI; bool UserRemovedFromCSEMaps = false; @@ -5083,7 +5086,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To, // Now that we have modified User, add it back to the CSE maps. If it // already exists there, recursively merge the results together. - AddModifiedNodeToCSEMaps(User, UpdateListener); + AddModifiedNodeToCSEMaps(User, &Listener); } } @@ -5280,8 +5283,11 @@ GlobalAddressSDNode::GlobalAddressSDNode(unsigned Opc, const GlobalValue *GA, MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, EVT memvt, MachineMemOperand *mmo) : SDNode(Opc, dl, VTs), MemoryVT(memvt), MMO(mmo) { - SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile()); + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile(), + MMO->isNonTemporal()); assert(isVolatile() == MMO->isVolatile() && "Volatile encoding error!"); + assert(isNonTemporal() == MMO->isNonTemporal() && + "Non-temporal encoding error!"); assert(memvt.getStoreSize() == MMO->getSize() && "Size mismatch!"); } @@ -5290,7 +5296,8 @@ MemSDNode::MemSDNode(unsigned Opc, DebugLoc dl, SDVTList VTs, MachineMemOperand *mmo) : SDNode(Opc, dl, VTs, Ops, NumOps), MemoryVT(memvt), MMO(mmo) { - SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile()); + SubclassData = encodeMemSDNodeFlags(0, ISD::UNINDEXED, MMO->isVolatile(), + MMO->isNonTemporal()); assert(isVolatile() == MMO->isVolatile() && "Volatile encoding error!"); assert(memvt.getStoreSize() == MMO->getSize() && "Size mismatch!"); } @@ -5459,15 +5466,15 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { if (const TargetInstrInfo *TII = G->getTarget().getInstrInfo()) if (getMachineOpcode() < TII->getNumOpcodes()) return TII->get(getMachineOpcode()).getName(); - return "<>"; + return "<>"; } if (G) { const TargetLowering &TLI = G->getTargetLoweringInfo(); const char *Name = TLI.getTargetNodeName(getOpcode()); if (Name) return Name; - return "<>"; + return "<>"; } - return "<>"; + return "<>"; #ifndef NDEBUG case ISD::DELETED_NODE: @@ -5904,6 +5911,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const { if (G) if (unsigned Order = G->GetOrdering(this)) OS << " [ORD=" << Order << ']'; + + if (getNodeId() != -1) + OS << " [ID=" << getNodeId() << ']'; } void SDNode::print(raw_ostream &OS, const SelectionDAG *G) const { @@ -6292,31 +6302,37 @@ bool ShuffleVectorSDNode::isSplatMask(const int *Mask, EVT VT) { return true; } +#ifdef XDEBUG static void checkForCyclesHelper(const SDNode *N, - std::set &visited) { - if (visited.find(N) != visited.end()) { + SmallPtrSet &Visited, + SmallPtrSet &Checked) { + // If this node has already been checked, don't check it again. + if (Checked.count(N)) + return; + + // If a node has already been visited on this depth-first walk, reject it as + // a cycle. + if (!Visited.insert(N)) { dbgs() << "Offending node:\n"; N->dumprFull(); - assert(0 && "Detected cycle in SelectionDAG"); + errs() << "Detected cycle in SelectionDAG\n"; + abort(); } - - std::set::iterator i; - bool inserted; - - tie(i, inserted) = visited.insert(N); - assert(inserted && "Missed cycle"); - - for(unsigned i = 0; i < N->getNumOperands(); ++i) { - checkForCyclesHelper(N->getOperand(i).getNode(), visited); - } - visited.erase(i); + + for(unsigned i = 0, e = N->getNumOperands(); i != e; ++i) + checkForCyclesHelper(N->getOperand(i).getNode(), Visited, Checked); + + Checked.insert(N); + Visited.erase(N); } +#endif void llvm::checkForCycles(const llvm::SDNode *N) { #ifdef XDEBUG assert(N && "Checking nonexistant SDNode"); - std::set visited; - checkForCyclesHelper(N, visited); + SmallPtrSet visited; + SmallPtrSet checked; + checkForCyclesHelper(N, visited, checked); #endif } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index de17f904d9..05be9a1003 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -155,7 +155,7 @@ namespace { /// this value and returns the result as a ValueVTs value. This uses /// Chain/Flag as the input and updates them for the output Chain/Flag. /// If the Flag pointer is NULL, no flag is used. - SDValue getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, unsigned Order, + SDValue getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, SDValue &Chain, SDValue *Flag) const; /// getCopyToRegs - Emit a series of CopyToReg nodes that copies the @@ -163,14 +163,14 @@ namespace { /// Chain/Flag as the input and updates them for the output Chain/Flag. /// If the Flag pointer is NULL, no flag is used. void getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, - unsigned Order, SDValue &Chain, SDValue *Flag) const; + SDValue &Chain, SDValue *Flag) const; /// AddInlineAsmOperands - Add this value to the specified inlineasm node /// operand list. This adds the code marker, matching input operand index /// (if applicable), and includes the number of values added into it. void AddInlineAsmOperands(unsigned Code, bool HasMatching, unsigned MatchingIdx, - SelectionDAG &DAG, unsigned Order, + SelectionDAG &DAG, std::vector &Ops) const; }; } @@ -180,7 +180,7 @@ namespace { /// larger then ValueVT then AssertOp can be used to specify whether the extra /// bits are known to be zero (ISD::AssertZext) or sign extended from ValueVT /// (ISD::AssertSext). -static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, +static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, const SDValue *Parts, unsigned NumParts, EVT PartVT, EVT ValueVT, ISD::NodeType AssertOp = ISD::DELETED_NODE) { @@ -205,9 +205,9 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, EVT HalfVT = EVT::getIntegerVT(*DAG.getContext(), RoundBits/2); if (RoundParts > 2) { - Lo = getCopyFromParts(DAG, dl, Order, Parts, RoundParts / 2, + Lo = getCopyFromParts(DAG, dl, Parts, RoundParts / 2, PartVT, HalfVT); - Hi = getCopyFromParts(DAG, dl, Order, Parts + RoundParts / 2, + Hi = getCopyFromParts(DAG, dl, Parts + RoundParts / 2, RoundParts / 2, PartVT, HalfVT); } else { Lo = DAG.getNode(ISD::BIT_CONVERT, dl, HalfVT, Parts[0]); @@ -223,7 +223,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, // Assemble the trailing non-power-of-2 part. unsigned OddParts = NumParts - RoundParts; EVT OddVT = EVT::getIntegerVT(*DAG.getContext(), OddParts * PartBits); - Hi = getCopyFromParts(DAG, dl, Order, + Hi = getCopyFromParts(DAG, dl, Parts + RoundParts, OddParts, PartVT, OddVT); // Combine the round and odd parts. @@ -259,7 +259,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, // If the register was not expanded, truncate or copy the value, // as appropriate. for (unsigned i = 0; i != NumParts; ++i) - Ops[i] = getCopyFromParts(DAG, dl, Order, &Parts[i], 1, + Ops[i] = getCopyFromParts(DAG, dl, &Parts[i], 1, PartVT, IntermediateVT); } else if (NumParts > 0) { // If the intermediate type was expanded, build the intermediate @@ -268,7 +268,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, "Must expand into a divisible number of parts!"); unsigned Factor = NumParts / NumIntermediates; for (unsigned i = 0; i != NumIntermediates; ++i) - Ops[i] = getCopyFromParts(DAG, dl, Order, &Parts[i * Factor], Factor, + Ops[i] = getCopyFromParts(DAG, dl, &Parts[i * Factor], Factor, PartVT, IntermediateVT); } @@ -292,7 +292,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, assert(ValueVT.isFloatingPoint() && PartVT.isInteger() && !PartVT.isVector() && "Unexpected split"); EVT IntVT = EVT::getIntegerVT(*DAG.getContext(), ValueVT.getSizeInBits()); - Val = getCopyFromParts(DAG, dl, Order, Parts, NumParts, PartVT, IntVT); + Val = getCopyFromParts(DAG, dl, Parts, NumParts, PartVT, IntVT); } } @@ -349,7 +349,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, /// getCopyToParts - Create a series of nodes that contain the specified value /// split into legal parts. If the parts contain more bits than Val, then, for /// integers, ExtendKind can be used to specify how to generate the extra bits. -static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, +static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, SDValue Val, SDValue *Parts, unsigned NumParts, EVT PartVT, ISD::NodeType ExtendKind = ISD::ANY_EXTEND) { @@ -417,7 +417,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, SDValue OddVal = DAG.getNode(ISD::SRL, dl, ValueVT, Val, DAG.getConstant(RoundBits, TLI.getPointerTy())); - getCopyToParts(DAG, dl, Order, OddVal, Parts + RoundParts, + getCopyToParts(DAG, dl, OddVal, Parts + RoundParts, OddParts, PartVT); if (TLI.isBigEndian()) @@ -514,7 +514,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, // If the register was not expanded, promote or copy the value, // as appropriate. for (unsigned i = 0; i != NumParts; ++i) - getCopyToParts(DAG, dl, Order, Ops[i], &Parts[i], 1, PartVT); + getCopyToParts(DAG, dl, Ops[i], &Parts[i], 1, PartVT); } else if (NumParts > 0) { // If the intermediate type was expanded, split each the value into // legal parts. @@ -522,7 +522,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, unsigned Order, "Must expand into a divisible number of parts!"); unsigned Factor = NumParts / NumIntermediates; for (unsigned i = 0; i != NumIntermediates; ++i) - getCopyToParts(DAG, dl, Order, Ops[i], &Parts[i*Factor], Factor, PartVT); + getCopyToParts(DAG, dl, Ops[i], &Parts[i*Factor], Factor, PartVT); } } @@ -680,7 +680,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { getCurDebugLoc()); } - if (isa(C->getType()) || isa(C->getType())) { + if (C->getType()->isStructTy() || C->getType()->isArrayTy()) { assert((isa(C) || isa(C)) && "Unknown struct or array constant!"); @@ -747,8 +747,7 @@ SDValue SelectionDAGBuilder::getValue(const Value *V) { RegsForValue RFV(*DAG.getContext(), TLI, InReg, V->getType()); SDValue Chain = DAG.getEntryNode(); - return RFV.getCopyFromRegs(DAG, getCurDebugLoc(), - SDNodeOrder, Chain, NULL); + return RFV.getCopyFromRegs(DAG, getCurDebugLoc(), Chain, NULL); } /// Get the EVTs and ArgFlags collections that represent the legalized return @@ -844,19 +843,17 @@ void SelectionDAGBuilder::visitRet(ReturnInst &I) { Chains[i] = DAG.getStore(Chain, getCurDebugLoc(), SDValue(RetOp.getNode(), RetOp.getResNo() + i), - Add, NULL, Offsets[i], false, 0); + Add, NULL, Offsets[i], false, false, 0); } Chain = DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), MVT::Other, &Chains[0], NumValues); - } else { - for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) { - SmallVector ValueVTs; - ComputeValueVTs(TLI, I.getOperand(i)->getType(), ValueVTs); - unsigned NumValues = ValueVTs.size(); - if (NumValues == 0) continue; - - SDValue RetOp = getValue(I.getOperand(i)); + } else if (I.getNumOperands() != 0) { + SmallVector ValueVTs; + ComputeValueVTs(TLI, I.getOperand(0)->getType(), ValueVTs); + unsigned NumValues = ValueVTs.size(); + if (NumValues) { + SDValue RetOp = getValue(I.getOperand(0)); for (unsigned j = 0, f = NumValues; j != f; ++j) { EVT VT = ValueVTs[j]; @@ -881,7 +878,7 @@ void SelectionDAGBuilder::visitRet(ReturnInst &I) { unsigned NumParts = TLI.getNumRegisters(*DAG.getContext(), VT); EVT PartVT = TLI.getRegisterType(*DAG.getContext(), VT); SmallVector Parts(NumParts); - getCopyToParts(DAG, getCurDebugLoc(), SDNodeOrder, + getCopyToParts(DAG, getCurDebugLoc(), SDValue(RetOp.getNode(), RetOp.getResNo() + j), &Parts[0], NumParts, PartVT, ExtendKind); @@ -1973,7 +1970,7 @@ size_t SelectionDAGBuilder::Clusterify(CaseVector& Cases, if (Cases.size() >= 2) // Must recompute end() each iteration because it may be // invalidated by erase if we hold on to it - for (CaseItr I = Cases.begin(), J = ++(Cases.begin()); J != Cases.end(); ) { + for (CaseItr TmpBegin = Cases.begin(), I = TmpBegin, J = ++TmpBegin; J != Cases.end(); ) { const APInt& nextValue = cast(J->Low)->getValue(); const APInt& currentValue = cast(I->High)->getValue(); MachineBasicBlock* nextBB = J->BB; @@ -2062,9 +2059,15 @@ void SelectionDAGBuilder::visitSwitch(SwitchInst &SI) { } void SelectionDAGBuilder::visitIndirectBr(IndirectBrInst &I) { - // Update machine-CFG edges. + // Update machine-CFG edges with unique successors. + SmallVector succs; + succs.reserve(I.getNumSuccessors()); for (unsigned i = 0, e = I.getNumSuccessors(); i != e; ++i) - CurMBB->addSuccessor(FuncInfo.MBBMap[I.getSuccessor(i)]); + succs.push_back(I.getSuccessor(i)); + array_pod_sort(succs.begin(), succs.end()); + succs.erase(std::unique(succs.begin(), succs.end()), succs.end()); + for (unsigned i = 0, e = succs.size(); i != e; ++i) + CurMBB->addSuccessor(FuncInfo.MBBMap[succs[i]]); DAG.setRoot(DAG.getNode(ISD::BRIND, getCurDebugLoc(), MVT::Other, getControlRoot(), @@ -2074,7 +2077,7 @@ void SelectionDAGBuilder::visitIndirectBr(IndirectBrInst &I) { void SelectionDAGBuilder::visitFSub(User &I) { // -0.0 - X --> fneg const Type *Ty = I.getType(); - if (isa(Ty)) { + if (Ty->isVectorTy()) { if (ConstantVector *CV = dyn_cast(I.getOperand(0))) { const VectorType *DestTy = cast(I.getType()); const Type *ElTy = DestTy->getElementType(); @@ -2111,7 +2114,7 @@ void SelectionDAGBuilder::visitBinary(User &I, unsigned OpCode) { void SelectionDAGBuilder::visitShift(User &I, unsigned Opcode) { SDValue Op1 = getValue(I.getOperand(0)); SDValue Op2 = getValue(I.getOperand(1)); - if (!isa(I.getType()) && + if (!I.getType()->isVectorTy() && Op2.getValueType() != TLI.getShiftAmountTy()) { // If the operand is smaller than the shift count type, promote it. EVT PTy = TLI.getPointerTy(); @@ -2699,7 +2702,9 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) { SDValue Ptr = getValue(SV); const Type *Ty = I.getType(); + bool isVolatile = I.isVolatile(); + bool isNonTemporal = I.getMetadata("nontemporal") != 0; unsigned Alignment = I.getAlignment(); SmallVector ValueVTs; @@ -2731,7 +2736,8 @@ void SelectionDAGBuilder::visitLoad(LoadInst &I) { PtrVT, Ptr, DAG.getConstant(Offsets[i], PtrVT)); SDValue L = DAG.getLoad(ValueVTs[i], getCurDebugLoc(), Root, - A, SV, Offsets[i], isVolatile, Alignment); + A, SV, Offsets[i], isVolatile, + isNonTemporal, Alignment); Values[i] = L; Chains[i] = L.getValue(1); @@ -2772,6 +2778,7 @@ void SelectionDAGBuilder::visitStore(StoreInst &I) { SmallVector Chains(NumValues); EVT PtrVT = Ptr.getValueType(); bool isVolatile = I.isVolatile(); + bool isNonTemporal = I.getMetadata("nontemporal") != 0; unsigned Alignment = I.getAlignment(); for (unsigned i = 0; i != NumValues; ++i) { @@ -2779,7 +2786,8 @@ void SelectionDAGBuilder::visitStore(StoreInst &I) { DAG.getConstant(Offsets[i], PtrVT)); Chains[i] = DAG.getStore(Root, getCurDebugLoc(), SDValue(Src.getNode(), Src.getResNo() + i), - Add, PtrV, Offsets[i], isVolatile, Alignment); + Add, PtrV, Offsets[i], isVolatile, + isNonTemporal, Alignment); } DAG.setRoot(DAG.getNode(ISD::TokenFactor, getCurDebugLoc(), @@ -2879,7 +2887,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(CallInst &I, /// /// where Op is the hexidecimal representation of floating point value. static SDValue -GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl, unsigned Order) { +GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl) { SDValue t1 = DAG.getNode(ISD::AND, dl, MVT::i32, Op, DAG.getConstant(0x007fffff, MVT::i32)); SDValue t2 = DAG.getNode(ISD::OR, dl, MVT::i32, t1, @@ -2894,7 +2902,7 @@ GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl, unsigned Order) { /// where Op is the hexidecimal representation of floating point value. static SDValue GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI, - DebugLoc dl, unsigned Order) { + DebugLoc dl) { SDValue t0 = DAG.getNode(ISD::AND, dl, MVT::i32, Op, DAG.getConstant(0x7f800000, MVT::i32)); SDValue t1 = DAG.getNode(ISD::SRL, dl, MVT::i32, t0, @@ -3078,13 +3086,13 @@ SelectionDAGBuilder::visitLog(CallInst &I) { SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); // Scale the exponent by log(2) [0.69314718f]. - SDValue Exp = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); + SDValue Exp = GetExponent(DAG, Op1, TLI, dl); SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, getF32Constant(DAG, 0x3f317218)); // Get the significand and build it into a floating-point number with // exponent of 1. - SDValue X = GetSignificand(DAG, Op1, dl, SDNodeOrder); + SDValue X = GetSignificand(DAG, Op1, dl); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: @@ -3188,11 +3196,11 @@ SelectionDAGBuilder::visitLog2(CallInst &I) { SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); // Get the exponent. - SDValue LogOfExponent = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); + SDValue LogOfExponent = GetExponent(DAG, Op1, TLI, dl); // Get the significand and build it into a floating-point number with // exponent of 1. - SDValue X = GetSignificand(DAG, Op1, dl, SDNodeOrder); + SDValue X = GetSignificand(DAG, Op1, dl); // Different possible minimax approximations of significand in // floating-point for various degrees of accuracy over [1,2]. @@ -3297,13 +3305,13 @@ SelectionDAGBuilder::visitLog10(CallInst &I) { SDValue Op1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::i32, Op); // Scale the exponent by log10(2) [0.30102999f]. - SDValue Exp = GetExponent(DAG, Op1, TLI, dl, SDNodeOrder); + SDValue Exp = GetExponent(DAG, Op1, TLI, dl); SDValue LogOfExponent = DAG.getNode(ISD::FMUL, dl, MVT::f32, Exp, getF32Constant(DAG, 0x3e9a209a)); // Get the significand and build it into a floating-point number with // exponent of 1. - SDValue X = GetSignificand(DAG, Op1, dl, SDNodeOrder); + SDValue X = GetSignificand(DAG, Op1, dl); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: @@ -4058,7 +4066,7 @@ SelectionDAGBuilder::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { // Store the stack protector onto the stack. Res = DAG.getStore(getRoot(), getCurDebugLoc(), Src, FIN, PseudoSourceValue::getFixedStack(FI), - 0, true); + 0, true, false, 0); setValue(&I, Res); DAG.setRoot(Res); return 0; @@ -4276,8 +4284,8 @@ isInTailCallPosition(CallSite CS, Attributes CalleeRetAttr, // Check for a truly no-op bitcast. if (isa(U) && (U->getOperand(0)->getType() == U->getType() || - (isa(U->getOperand(0)->getType()) && - isa(U->getType())))) + (U->getOperand(0)->getType()->isPointerTy() && + U->getType()->isPointerTy()))) continue; // Otherwise it's not a true no-op. return false; @@ -4385,7 +4393,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, CS.getCallingConv(), isTailCall, !CS.getInstruction()->use_empty(), - Callee, Args, DAG, getCurDebugLoc(), SDNodeOrder); + Callee, Args, DAG, getCurDebugLoc()); assert((isTailCall || Result.second.getNode()) && "Non-null chain expected with non-tail call!"); assert((Result.second.getNode() || !Result.first.getNode()) && @@ -4410,7 +4418,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, DemoteStackSlot, DAG.getConstant(Offsets[i], PtrVT)); SDValue L = DAG.getLoad(OutVTs[i], getCurDebugLoc(), Result.second, - Add, NULL, Offsets[i], false, 1); + Add, NULL, Offsets[i], false, false, 1); Values[i] = L; Chains[i] = L.getValue(1); } @@ -4433,7 +4441,7 @@ void SelectionDAGBuilder::LowerCallTo(CallSite CS, SDValue Callee, unsigned NumRegs = TLI.getNumRegisters(RetTy->getContext(), VT); SDValue ReturnValue = - getCopyFromParts(DAG, getCurDebugLoc(), SDNodeOrder, &Values[CurReg], NumRegs, + getCopyFromParts(DAG, getCurDebugLoc(), &Values[CurReg], NumRegs, RegisterVT, VT, AssertOp); ReturnValues.push_back(ReturnValue); CurReg += NumRegs; @@ -4512,7 +4520,8 @@ static SDValue getMemCmpLoad(Value *PtrVal, MVT LoadVT, const Type *LoadTy, SDValue Ptr = Builder.getValue(PtrVal); SDValue LoadVal = Builder.DAG.getLoad(LoadVT, Builder.getCurDebugLoc(), Root, Ptr, PtrVal /*SrcValue*/, 0/*SVOffset*/, - false /*volatile*/, 1 /* align=1 */); + false /*volatile*/, + false /*nontemporal*/, 1 /* align=1 */); if (!ConstantMemory) Builder.PendingLoads.push_back(LoadVal.getValue(1)); @@ -4529,9 +4538,9 @@ bool SelectionDAGBuilder::visitMemCmpCall(CallInst &I) { return false; Value *LHS = I.getOperand(1), *RHS = I.getOperand(2); - if (!isa(LHS->getType()) || !isa(RHS->getType()) || - !isa(I.getOperand(3)->getType()) || - !isa(I.getType())) + if (!LHS->getType()->isPointerTy() || !RHS->getType()->isPointerTy() || + !I.getOperand(3)->getType()->isIntegerTy() || + !I.getType()->isIntegerTy()) return false; ConstantInt *Size = dyn_cast(I.getOperand(3)); @@ -4625,7 +4634,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { StringRef Name = F->getName(); if (Name == "copysign" || Name == "copysignf") { if (I.getNumOperands() == 3 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType() && I.getType() == I.getOperand(2)->getType()) { SDValue LHS = getValue(I.getOperand(1)); @@ -4636,7 +4645,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { } } else if (Name == "fabs" || Name == "fabsf" || Name == "fabsl") { if (I.getNumOperands() == 2 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType()) { SDValue Tmp = getValue(I.getOperand(1)); setValue(&I, DAG.getNode(ISD::FABS, getCurDebugLoc(), @@ -4645,7 +4654,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { } } else if (Name == "sin" || Name == "sinf" || Name == "sinl") { if (I.getNumOperands() == 2 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType() && I.onlyReadsMemory()) { SDValue Tmp = getValue(I.getOperand(1)); @@ -4655,7 +4664,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { } } else if (Name == "cos" || Name == "cosf" || Name == "cosl") { if (I.getNumOperands() == 2 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType() && I.onlyReadsMemory()) { SDValue Tmp = getValue(I.getOperand(1)); @@ -4665,7 +4674,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { } } else if (Name == "sqrt" || Name == "sqrtf" || Name == "sqrtl") { if (I.getNumOperands() == 2 && // Basic sanity checks. - I.getOperand(1)->getType()->isFloatingPoint() && + I.getOperand(1)->getType()->isFloatingPointTy() && I.getType() == I.getOperand(1)->getType() && I.onlyReadsMemory()) { SDValue Tmp = getValue(I.getOperand(1)); @@ -4699,8 +4708,7 @@ void SelectionDAGBuilder::visitCall(CallInst &I) { /// Chain/Flag as the input and updates them for the output Chain/Flag. /// If the Flag pointer is NULL, no flag is used. SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, - unsigned Order, SDValue &Chain, - SDValue *Flag) const { + SDValue &Chain, SDValue *Flag) const { // Assemble the legal parts into the final values. SmallVector Values(ValueVTs.size()); SmallVector Parts; @@ -4765,7 +4773,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, Parts[i] = P; } - Values[Value] = getCopyFromParts(DAG, dl, Order, Parts.begin(), + Values[Value] = getCopyFromParts(DAG, dl, Parts.begin(), NumRegs, RegisterVT, ValueVT); Part += NumRegs; Parts.clear(); @@ -4781,8 +4789,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG, DebugLoc dl, /// Chain/Flag as the input and updates them for the output Chain/Flag. /// If the Flag pointer is NULL, no flag is used. void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, - unsigned Order, SDValue &Chain, - SDValue *Flag) const { + SDValue &Chain, SDValue *Flag) const { // Get the list of the values's legal parts. unsigned NumRegs = Regs.size(); SmallVector Parts(NumRegs); @@ -4791,7 +4798,7 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, unsigned NumParts = TLI->getNumRegisters(*DAG.getContext(), ValueVT); EVT RegisterVT = RegVTs[Value]; - getCopyToParts(DAG, dl, Order, + getCopyToParts(DAG, dl, Val.getValue(Val.getResNo() + Value), &Parts[Part], NumParts, RegisterVT); Part += NumParts; @@ -4832,7 +4839,7 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG, DebugLoc dl, /// values added into it. void RegsForValue::AddInlineAsmOperands(unsigned Code, bool HasMatching,unsigned MatchingIdx, - SelectionDAG &DAG, unsigned Order, + SelectionDAG &DAG, std::vector &Ops) const { assert(Regs.size() < (1 << 13) && "Too many inline asm outputs!"); unsigned Flag = Code | (Regs.size() << 3); @@ -5330,7 +5337,8 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { int SSFI = MF.getFrameInfo()->CreateStackObject(TySize, Align, false); SDValue StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy()); Chain = DAG.getStore(Chain, getCurDebugLoc(), - OpInfo.CallOperand, StackSlot, NULL, 0); + OpInfo.CallOperand, StackSlot, NULL, 0, + false, false, 0); OpInfo.CallOperand = StackSlot; } @@ -5421,7 +5429,7 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { 2 /* REGDEF */ , false, 0, - DAG, SDNodeOrder, + DAG, AsmNodeOperands); break; } @@ -5469,10 +5477,10 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { // Use the produced MatchedRegs object to MatchedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(), - SDNodeOrder, Chain, &Flag); + Chain, &Flag); MatchedRegs.AddInlineAsmOperands(1 /*REGUSE*/, true, OpInfo.getMatchedOperand(), - DAG, SDNodeOrder, AsmNodeOperands); + DAG, AsmNodeOperands); break; } else { assert(((OpFlag & 7) == 4) && "Unknown matching constraint!"); @@ -5533,11 +5541,10 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { } OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(), - SDNodeOrder, Chain, &Flag); + Chain, &Flag); OpInfo.AssignedRegs.AddInlineAsmOperands(1/*REGUSE*/, false, 0, - DAG, SDNodeOrder, - AsmNodeOperands); + DAG, AsmNodeOperands); break; } case InlineAsm::isClobber: { @@ -5545,7 +5552,7 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { // allocator is aware that the physreg got clobbered. if (!OpInfo.AssignedRegs.Regs.empty()) OpInfo.AssignedRegs.AddInlineAsmOperands(6 /* EARLYCLOBBER REGDEF */, - false, 0, DAG, SDNodeOrder, + false, 0, DAG, AsmNodeOperands); break; } @@ -5565,7 +5572,7 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { // and set it as the value of the call. if (!RetValRegs.Regs.empty()) { SDValue Val = RetValRegs.getCopyFromRegs(DAG, getCurDebugLoc(), - SDNodeOrder, Chain, &Flag); + Chain, &Flag); // FIXME: Why don't we do this for inline asms with MRVs? if (CS.getType()->isSingleValueType() && CS.getType()->isSized()) { @@ -5605,7 +5612,7 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { RegsForValue &OutRegs = IndirectStoresToEmit[i].first; Value *Ptr = IndirectStoresToEmit[i].second; SDValue OutVal = OutRegs.getCopyFromRegs(DAG, getCurDebugLoc(), - SDNodeOrder, Chain, &Flag); + Chain, &Flag); StoresToEmit.push_back(std::make_pair(OutVal, Ptr)); } @@ -5616,7 +5623,8 @@ void SelectionDAGBuilder::visitInlineAsm(CallSite CS) { SDValue Val = DAG.getStore(Chain, getCurDebugLoc(), StoresToEmit[i].first, getValue(StoresToEmit[i].second), - StoresToEmit[i].second, 0); + StoresToEmit[i].second, 0, + false, false, 0); OutChains.push_back(Val); } @@ -5669,8 +5677,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, CallingConv::ID CallConv, bool isTailCall, bool isReturnValueUsed, SDValue Callee, - ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl, - unsigned Order) { + ArgListTy &Args, SelectionDAG &DAG, DebugLoc dl) { // Handle all of the outgoing arguments. SmallVector Outs; for (unsigned i = 0, e = Args.size(); i != e; ++i) { @@ -5721,7 +5728,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, else if (Args[i].isZExt) ExtendKind = ISD::ZERO_EXTEND; - getCopyToParts(DAG, dl, Order, Op, &Parts[0], NumParts, + getCopyToParts(DAG, dl, Op, &Parts[0], NumParts, PartVT, ExtendKind); for (unsigned j = 0; j != NumParts; ++j) { @@ -5800,7 +5807,7 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy, EVT RegisterVT = getRegisterType(RetTy->getContext(), VT); unsigned NumRegs = getNumRegisters(RetTy->getContext(), VT); - ReturnValues.push_back(getCopyFromParts(DAG, dl, Order, &InVals[CurReg], + ReturnValues.push_back(getCopyFromParts(DAG, dl, &InVals[CurReg], NumRegs, RegisterVT, VT, AssertOp)); CurReg += NumRegs; @@ -5840,7 +5847,7 @@ void SelectionDAGBuilder::CopyValueToVirtualRegister(Value *V, unsigned Reg) { RegsForValue RFV(V->getContext(), TLI, Reg, V->getType()); SDValue Chain = DAG.getEntryNode(); - RFV.getCopyToRegs(Op, DAG, getCurDebugLoc(), SDNodeOrder, Chain, 0); + RFV.getCopyToRegs(Op, DAG, getCurDebugLoc(), Chain, 0); PendingExports.push_back(Chain); } @@ -5966,7 +5973,7 @@ void SelectionDAGISel::LowerArguments(BasicBlock *LLVMBB) { EVT VT = ValueVTs[0]; EVT RegVT = TLI.getRegisterType(*CurDAG->getContext(), VT); ISD::NodeType AssertOp = ISD::DELETED_NODE; - SDValue ArgValue = getCopyFromParts(DAG, dl, 0, &InVals[0], 1, + SDValue ArgValue = getCopyFromParts(DAG, dl, &InVals[0], 1, RegVT, VT, AssertOp); MachineFunction& MF = SDB->DAG.getMachineFunction(); @@ -6000,7 +6007,7 @@ void SelectionDAGISel::LowerArguments(BasicBlock *LLVMBB) { else if (F.paramHasAttr(Idx, Attribute::ZExt)) AssertOp = ISD::AssertZext; - ArgValues.push_back(getCopyFromParts(DAG, dl, 0, &InVals[i], + ArgValues.push_back(getCopyFromParts(DAG, dl, &InVals[i], NumParts, PartVT, VT, AssertOp)); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index da2e6e42a3..05f9f1ff18 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -56,9 +56,12 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Timer.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Statistic.h" #include using namespace llvm; +STATISTIC(NumFastIselFailures, "Number of instructions fast isel failed on"); + static cl::opt EnableFastISelVerbose("fast-isel-verbose", cl::Hidden, cl::desc("Enable verbose messages in the \"fast\" " @@ -723,9 +726,9 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { // code to the MachineBasicBlock. if (TimePassesIsEnabled) { NamedRegionTimer T("Instruction Selection", GroupName); - InstructionSelect(); + DoInstructionSelection(); } else { - InstructionSelect(); + DoInstructionSelection(); } DEBUG(dbgs() << "Selected selection DAG:\n"); @@ -765,6 +768,66 @@ void SelectionDAGISel::CodeGenAndEmitDAG() { DEBUG(BB->dump()); } +void SelectionDAGISel::DoInstructionSelection() { + DEBUG(errs() << "===== Instruction selection begins:\n"); + + PreprocessISelDAG(); + + // Select target instructions for the DAG. + { + // Number all nodes with a topological order and set DAGSize. + DAGSize = CurDAG->AssignTopologicalOrder(); + + // Create a dummy node (which is not added to allnodes), that adds + // a reference to the root node, preventing it from being deleted, + // and tracking any changes of the root. + HandleSDNode Dummy(CurDAG->getRoot()); + ISelPosition = SelectionDAG::allnodes_iterator(CurDAG->getRoot().getNode()); + ++ISelPosition; + + // The AllNodes list is now topological-sorted. Visit the + // nodes by starting at the end of the list (the root of the + // graph) and preceding back toward the beginning (the entry + // node). + while (ISelPosition != CurDAG->allnodes_begin()) { + SDNode *Node = --ISelPosition; + // Skip dead nodes. DAGCombiner is expected to eliminate all dead nodes, + // but there are currently some corner cases that it misses. Also, this + // makes it theoretically possible to disable the DAGCombiner. + if (Node->use_empty()) + continue; + + SDNode *ResNode = Select(Node); + + // FIXME: This is pretty gross. 'Select' should be changed to not return + // anything at all and this code should be nuked with a tactical strike. + + // If node should not be replaced, continue with the next one. + if (ResNode == Node || Node->getOpcode() == ISD::DELETED_NODE) + continue; + // Replace node. + if (ResNode) + ReplaceUses(Node, ResNode); + + // If after the replacement this node is not used any more, + // remove this dead node. + if (Node->use_empty()) { // Don't delete EntryToken, etc. + ISelUpdater ISU(ISelPosition); + CurDAG->RemoveDeadNode(Node, &ISU); + } + } + + CurDAG->setRoot(Dummy.getValue()); + } + DEBUG(errs() << "===== Instruction selection ends:\n"); + + PostprocessISelDAG(); + + // FIXME: This shouldn't be needed, remove it. + CurDAG->RemoveDeadNodes(); +} + + void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, MachineFunction &MF, MachineModuleInfo *MMI, @@ -870,6 +933,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, // feed PHI nodes in successor blocks. if (isa(BI)) if (!HandlePHINodesInSuccessorBlocksFast(LLVMBB, FastIS)) { + ++NumFastIselFailures; ResetDebugLoc(SDB, FastIS); if (EnableFastISelVerbose || EnableFastISelAbort) { dbgs() << "FastISel miss: "; @@ -894,6 +958,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, // Then handle certain instructions as single-LLVM-Instruction blocks. if (isa(BI)) { + ++NumFastIselFailures; if (EnableFastISelVerbose || EnableFastISelAbort) { dbgs() << "FastISel missed call: "; BI->dump(); @@ -923,6 +988,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(Function &Fn, // Otherwise, give up on FastISel for the rest of the block. // For now, be a little lenient about non-branch terminators. if (!isa(BI) || isa(BI)) { + ++NumFastIselFailures; if (EnableFastISelVerbose || EnableFastISelAbort) { dbgs() << "FastISel miss: "; BI->dump(); @@ -972,6 +1038,8 @@ SelectionDAGISel::FinishBasicBlock() { MachineInstr *PHI = SDB->PHINodesToUpdate[i].first; assert(PHI->isPHI() && "This is not a machine PHI node that we are updating!"); + if (!BB->isSuccessor(PHI->getParent())) + continue; PHI->addOperand(MachineOperand::CreateReg(SDB->PHINodesToUpdate[i].second, false)); PHI->addOperand(MachineOperand::CreateMBB(BB)); @@ -1316,13 +1384,29 @@ static SDNode *findFlagUse(SDNode *N) { /// This function recursively traverses up the operand chain, ignoring /// certain nodes. static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse, - SDNode *Root, - SmallPtrSet &Visited) { - if (Use->getNodeId() < Def->getNodeId() || - !Visited.insert(Use)) + SDNode *Root, SmallPtrSet &Visited, + bool IgnoreChains) { + // The NodeID's are given uniques ID's where a node ID is guaranteed to be + // greater than all of its (recursive) operands. If we scan to a point where + // 'use' is smaller than the node we're scanning for, then we know we will + // never find it. + // + // The Use may be -1 (unassigned) if it is a newly allocated node. This can + // happen because we scan down to newly selected nodes in the case of flag + // uses. + if ((Use->getNodeId() < Def->getNodeId() && Use->getNodeId() != -1)) + return false; + + // Don't revisit nodes if we already scanned it and didn't fail, we know we + // won't fail if we scan it again. + if (!Visited.insert(Use)) return false; for (unsigned i = 0, e = Use->getNumOperands(); i != e; ++i) { + // Ignore chain uses, they are validated by HandleMergeInputChains. + if (Use->getOperand(i).getValueType() == MVT::Other && IgnoreChains) + continue; + SDNode *N = Use->getOperand(i).getNode(); if (N == Def) { if (Use == ImmedUse || Use == Root) @@ -1332,32 +1416,24 @@ static bool findNonImmUse(SDNode *Use, SDNode* Def, SDNode *ImmedUse, } // Traverse up the operand chain. - if (findNonImmUse(N, Def, ImmedUse, Root, Visited)) + if (findNonImmUse(N, Def, ImmedUse, Root, Visited, IgnoreChains)) return true; } return false; } -/// isNonImmUse - Start searching from Root up the DAG to check is Def can -/// be reached. Return true if that's the case. However, ignore direct uses -/// by ImmedUse (which would be U in the example illustrated in -/// IsLegalAndProfitableToFold) and by Root (which can happen in the store -/// case). -/// FIXME: to be really generic, we should allow direct use by any node -/// that is being folded. But realisticly since we only fold loads which -/// have one non-chain use, we only need to watch out for load/op/store -/// and load/op/cmp case where the root (store / cmp) may reach the load via -/// its chain operand. -static inline bool isNonImmUse(SDNode *Root, SDNode *Def, SDNode *ImmedUse) { - SmallPtrSet Visited; - return findNonImmUse(Root, Def, ImmedUse, Root, Visited); +/// IsProfitableToFold - Returns true if it's profitable to fold the specific +/// operand node N of U during instruction selection that starts at Root. +bool SelectionDAGISel::IsProfitableToFold(SDValue N, SDNode *U, + SDNode *Root) const { + if (OptLevel == CodeGenOpt::None) return false; + return N.hasOneUse(); } -/// IsLegalAndProfitableToFold - Returns true if the specific operand node N of -/// U can be folded during instruction selection that starts at Root and -/// folding N is profitable. -bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, - SDNode *Root) const { +/// IsLegalToFold - Returns true if the specific operand node N of +/// U can be folded during instruction selection that starts at Root. +bool SelectionDAGISel::IsLegalToFold(SDValue N, SDNode *U, SDNode *Root, + bool IgnoreChains) const { if (OptLevel == CodeGenOpt::None) return false; // If Root use can somehow reach N through a path that that doesn't contain @@ -1402,6 +1478,8 @@ bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, // Fold. But since Fold and FU are flagged together, this will create // a cycle in the scheduling graph. + // If the node has flags, walk down the graph to the "lowest" node in the + // flagged set. EVT VT = Root->getValueType(Root->getNumValues()-1); while (VT == MVT::Flag) { SDNode *FU = findFlagUse(Root); @@ -1409,9 +1487,17 @@ bool SelectionDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, break; Root = FU; VT = Root->getValueType(Root->getNumValues()-1); + + // If our query node has a flag result with a use, we've walked up it. If + // the user (which has already been selected) has a chain or indirectly uses + // the chain, our WalkChainUsers predicate will not consider it. Because of + // this, we cannot ignore chains in this predicate. + IgnoreChains = false; } + - return !isNonImmUse(Root, N, U); + SmallPtrSet Visited; + return !findNonImmUse(Root, N.getNode(), U, Root, Visited, IgnoreChains); } SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) { @@ -1423,6 +1509,7 @@ SDNode *SelectionDAGISel::Select_INLINEASM(SDNode *N) { VTs.push_back(MVT::Flag); SDValue New = CurDAG->getNode(ISD::INLINEASM, N->getDebugLoc(), VTs, &Ops[0], Ops.size()); + New->setNodeId(-1); return New.getNode(); } @@ -1438,25 +1525,1219 @@ SDNode *SelectionDAGISel::Select_EH_LABEL(SDNode *N) { MVT::Other, Tmp, Chain); } +/// GetVBR - decode a vbr encoding whose top bit is set. +ALWAYS_INLINE static uint64_t +GetVBR(uint64_t Val, const unsigned char *MatcherTable, unsigned &Idx) { + assert(Val >= 128 && "Not a VBR"); + Val &= 127; // Remove first vbr bit. + + unsigned Shift = 7; + uint64_t NextBits; + do { + NextBits = MatcherTable[Idx++]; + Val |= (NextBits&127) << Shift; + Shift += 7; + } while (NextBits & 128); + + return Val; +} + + +/// UpdateChainsAndFlags - When a match is complete, this method updates uses of +/// interior flag and chain results to use the new flag and chain results. +void SelectionDAGISel:: +UpdateChainsAndFlags(SDNode *NodeToMatch, SDValue InputChain, + const SmallVectorImpl &ChainNodesMatched, + SDValue InputFlag, + const SmallVectorImpl &FlagResultNodesMatched, + bool isMorphNodeTo) { + SmallVector NowDeadNodes; + + ISelUpdater ISU(ISelPosition); + + // Now that all the normal results are replaced, we replace the chain and + // flag results if present. + if (!ChainNodesMatched.empty()) { + assert(InputChain.getNode() != 0 && + "Matched input chains but didn't produce a chain"); + // Loop over all of the nodes we matched that produced a chain result. + // Replace all the chain results with the final chain we ended up with. + for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { + SDNode *ChainNode = ChainNodesMatched[i]; + + // If this node was already deleted, don't look at it. + if (ChainNode->getOpcode() == ISD::DELETED_NODE) + continue; + + // Don't replace the results of the root node if we're doing a + // MorphNodeTo. + if (ChainNode == NodeToMatch && isMorphNodeTo) + continue; + + SDValue ChainVal = SDValue(ChainNode, ChainNode->getNumValues()-1); + if (ChainVal.getValueType() == MVT::Flag) + ChainVal = ChainVal.getValue(ChainVal->getNumValues()-2); + assert(ChainVal.getValueType() == MVT::Other && "Not a chain?"); + CurDAG->ReplaceAllUsesOfValueWith(ChainVal, InputChain, &ISU); + + // If the node became dead, delete it. + if (ChainNode->use_empty()) + NowDeadNodes.push_back(ChainNode); + } + } + + // If the result produces a flag, update any flag results in the matched + // pattern with the flag result. + if (InputFlag.getNode() != 0) { + // Handle any interior nodes explicitly marked. + for (unsigned i = 0, e = FlagResultNodesMatched.size(); i != e; ++i) { + SDNode *FRN = FlagResultNodesMatched[i]; + + // If this node was already deleted, don't look at it. + if (FRN->getOpcode() == ISD::DELETED_NODE) + continue; + + assert(FRN->getValueType(FRN->getNumValues()-1) == MVT::Flag && + "Doesn't have a flag result"); + CurDAG->ReplaceAllUsesOfValueWith(SDValue(FRN, FRN->getNumValues()-1), + InputFlag, &ISU); + + // If the node became dead, delete it. + if (FRN->use_empty()) + NowDeadNodes.push_back(FRN); + } + } + + if (!NowDeadNodes.empty()) + CurDAG->RemoveDeadNodes(NowDeadNodes, &ISU); + + DEBUG(errs() << "ISEL: Match complete!\n"); +} + +enum ChainResult { + CR_Simple, + CR_InducesCycle, + CR_LeadsToInteriorNode +}; + +/// WalkChainUsers - Walk down the users of the specified chained node that is +/// part of the pattern we're matching, looking at all of the users we find. +/// This determines whether something is an interior node, whether we have a +/// non-pattern node in between two pattern nodes (which prevent folding because +/// it would induce a cycle) and whether we have a TokenFactor node sandwiched +/// between pattern nodes (in which case the TF becomes part of the pattern). +/// +/// The walk we do here is guaranteed to be small because we quickly get down to +/// already selected nodes "below" us. +static ChainResult +WalkChainUsers(SDNode *ChainedNode, + SmallVectorImpl &ChainedNodesInPattern, + SmallVectorImpl &InteriorChainedNodes) { + ChainResult Result = CR_Simple; + + for (SDNode::use_iterator UI = ChainedNode->use_begin(), + E = ChainedNode->use_end(); UI != E; ++UI) { + // Make sure the use is of the chain, not some other value we produce. + if (UI.getUse().getValueType() != MVT::Other) continue; + + SDNode *User = *UI; + + // If we see an already-selected machine node, then we've gone beyond the + // pattern that we're selecting down into the already selected chunk of the + // DAG. + if (User->isMachineOpcode() || + User->getOpcode() == ISD::HANDLENODE) // Root of the graph. + continue; + + if (User->getOpcode() == ISD::CopyToReg || + User->getOpcode() == ISD::CopyFromReg || + User->getOpcode() == ISD::INLINEASM) { + // If their node ID got reset to -1 then they've already been selected. + // Treat them like a MachineOpcode. + if (User->getNodeId() == -1) + continue; + } + + // If we have a TokenFactor, we handle it specially. + if (User->getOpcode() != ISD::TokenFactor) { + // If the node isn't a token factor and isn't part of our pattern, then it + // must be a random chained node in between two nodes we're selecting. + // This happens when we have something like: + // x = load ptr + // call + // y = x+4 + // store y -> ptr + // Because we structurally match the load/store as a read/modify/write, + // but the call is chained between them. We cannot fold in this case + // because it would induce a cycle in the graph. + if (!std::count(ChainedNodesInPattern.begin(), + ChainedNodesInPattern.end(), User)) + return CR_InducesCycle; + + // Otherwise we found a node that is part of our pattern. For example in: + // x = load ptr + // y = x+4 + // store y -> ptr + // This would happen when we're scanning down from the load and see the + // store as a user. Record that there is a use of ChainedNode that is + // part of the pattern and keep scanning uses. + Result = CR_LeadsToInteriorNode; + InteriorChainedNodes.push_back(User); + continue; + } + + // If we found a TokenFactor, there are two cases to consider: first if the + // TokenFactor is just hanging "below" the pattern we're matching (i.e. no + // uses of the TF are in our pattern) we just want to ignore it. Second, + // the TokenFactor can be sandwiched in between two chained nodes, like so: + // [Load chain] + // ^ + // | + // [Load] + // ^ ^ + // | \ DAG's like cheese + // / \ do you? + // / | + // [TokenFactor] [Op] + // ^ ^ + // | | + // \ / + // \ / + // [Store] + // + // In this case, the TokenFactor becomes part of our match and we rewrite it + // as a new TokenFactor. + // + // To distinguish these two cases, do a recursive walk down the uses. + switch (WalkChainUsers(User, ChainedNodesInPattern, InteriorChainedNodes)) { + case CR_Simple: + // If the uses of the TokenFactor are just already-selected nodes, ignore + // it, it is "below" our pattern. + continue; + case CR_InducesCycle: + // If the uses of the TokenFactor lead to nodes that are not part of our + // pattern that are not selected, folding would turn this into a cycle, + // bail out now. + return CR_InducesCycle; + case CR_LeadsToInteriorNode: + break; // Otherwise, keep processing. + } + + // Okay, we know we're in the interesting interior case. The TokenFactor + // is now going to be considered part of the pattern so that we rewrite its + // uses (it may have uses that are not part of the pattern) with the + // ultimate chain result of the generated code. We will also add its chain + // inputs as inputs to the ultimate TokenFactor we create. + Result = CR_LeadsToInteriorNode; + ChainedNodesInPattern.push_back(User); + InteriorChainedNodes.push_back(User); + continue; + } + + return Result; +} + +/// HandleMergeInputChains - This implements the OPC_EmitMergeInputChains +/// operation for when the pattern matched at least one node with a chains. The +/// input vector contains a list of all of the chained nodes that we match. We +/// must determine if this is a valid thing to cover (i.e. matching it won't +/// induce cycles in the DAG) and if so, creating a TokenFactor node. that will +/// be used as the input node chain for the generated nodes. +static SDValue +HandleMergeInputChains(SmallVectorImpl &ChainNodesMatched, + SelectionDAG *CurDAG) { + // Walk all of the chained nodes we've matched, recursively scanning down the + // users of the chain result. This adds any TokenFactor nodes that are caught + // in between chained nodes to the chained and interior nodes list. + SmallVector InteriorChainedNodes; + for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { + if (WalkChainUsers(ChainNodesMatched[i], ChainNodesMatched, + InteriorChainedNodes) == CR_InducesCycle) + return SDValue(); // Would induce a cycle. + } + + // Okay, we have walked all the matched nodes and collected TokenFactor nodes + // that we are interested in. Form our input TokenFactor node. + SmallVector InputChains; + for (unsigned i = 0, e = ChainNodesMatched.size(); i != e; ++i) { + // Add the input chain of this node to the InputChains list (which will be + // the operands of the generated TokenFactor) if it's not an interior node. + SDNode *N = ChainNodesMatched[i]; + if (N->getOpcode() != ISD::TokenFactor) { + if (std::count(InteriorChainedNodes.begin(),InteriorChainedNodes.end(),N)) + continue; + + // Otherwise, add the input chain. + SDValue InChain = ChainNodesMatched[i]->getOperand(0); + assert(InChain.getValueType() == MVT::Other && "Not a chain"); + InputChains.push_back(InChain); + continue; + } + + // If we have a token factor, we want to add all inputs of the token factor + // that are not part of the pattern we're matching. + for (unsigned op = 0, e = N->getNumOperands(); op != e; ++op) { + if (!std::count(ChainNodesMatched.begin(), ChainNodesMatched.end(), + N->getOperand(op).getNode())) + InputChains.push_back(N->getOperand(op)); + } + } + + SDValue Res; + if (InputChains.size() == 1) + return InputChains[0]; + return CurDAG->getNode(ISD::TokenFactor, ChainNodesMatched[0]->getDebugLoc(), + MVT::Other, &InputChains[0], InputChains.size()); +} + +/// MorphNode - Handle morphing a node in place for the selector. +SDNode *SelectionDAGISel:: +MorphNode(SDNode *Node, unsigned TargetOpc, SDVTList VTList, + const SDValue *Ops, unsigned NumOps, unsigned EmitNodeInfo) { + // It is possible we're using MorphNodeTo to replace a node with no + // normal results with one that has a normal result (or we could be + // adding a chain) and the input could have flags and chains as well. + // In this case we need to shifting the operands down. + // FIXME: This is a horrible hack and broken in obscure cases, no worse + // than the old isel though. We should sink this into MorphNodeTo. + int OldFlagResultNo = -1, OldChainResultNo = -1; + + unsigned NTMNumResults = Node->getNumValues(); + if (Node->getValueType(NTMNumResults-1) == MVT::Flag) { + OldFlagResultNo = NTMNumResults-1; + if (NTMNumResults != 1 && + Node->getValueType(NTMNumResults-2) == MVT::Other) + OldChainResultNo = NTMNumResults-2; + } else if (Node->getValueType(NTMNumResults-1) == MVT::Other) + OldChainResultNo = NTMNumResults-1; + + // Call the underlying SelectionDAG routine to do the transmogrification. Note + // that this deletes operands of the old node that become dead. + SDNode *Res = CurDAG->MorphNodeTo(Node, ~TargetOpc, VTList, Ops, NumOps); + + // MorphNodeTo can operate in two ways: if an existing node with the + // specified operands exists, it can just return it. Otherwise, it + // updates the node in place to have the requested operands. + if (Res == Node) { + // If we updated the node in place, reset the node ID. To the isel, + // this should be just like a newly allocated machine node. + Res->setNodeId(-1); + } + + unsigned ResNumResults = Res->getNumValues(); + // Move the flag if needed. + if ((EmitNodeInfo & OPFL_FlagOutput) && OldFlagResultNo != -1 && + (unsigned)OldFlagResultNo != ResNumResults-1) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(Node, OldFlagResultNo), + SDValue(Res, ResNumResults-1)); + + if ((EmitNodeInfo & OPFL_FlagOutput) != 0) + --ResNumResults; + + // Move the chain reference if needed. + if ((EmitNodeInfo & OPFL_Chain) && OldChainResultNo != -1 && + (unsigned)OldChainResultNo != ResNumResults-1) + CurDAG->ReplaceAllUsesOfValueWith(SDValue(Node, OldChainResultNo), + SDValue(Res, ResNumResults-1)); + + // Otherwise, no replacement happened because the node already exists. Replace + // Uses of the old node with the new one. + if (Res != Node) + CurDAG->ReplaceAllUsesWith(Node, Res); + + return Res; +} + +/// CheckPatternPredicate - Implements OP_CheckPatternPredicate. +ALWAYS_INLINE static bool +CheckSame(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, const SmallVectorImpl &RecordedNodes) { + // Accept if it is exactly the same as a previously recorded node. + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + return N == RecordedNodes[RecNo]; +} + +/// CheckPatternPredicate - Implements OP_CheckPatternPredicate. +ALWAYS_INLINE static bool +CheckPatternPredicate(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SelectionDAGISel &SDISel) { + return SDISel.CheckPatternPredicate(MatcherTable[MatcherIndex++]); +} + +/// CheckNodePredicate - Implements OP_CheckNodePredicate. +ALWAYS_INLINE static bool +CheckNodePredicate(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SelectionDAGISel &SDISel, SDNode *N) { + return SDISel.CheckNodePredicate(N, MatcherTable[MatcherIndex++]); +} + +ALWAYS_INLINE static bool +CheckOpcode(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDNode *N) { + return N->getOpcode() == MatcherTable[MatcherIndex++]; +} + +ALWAYS_INLINE static bool +CheckType(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, const TargetLowering &TLI) { + MVT::SimpleValueType VT = (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + if (N.getValueType() == VT) return true; + + // Handle the case when VT is iPTR. + return VT == MVT::iPTR && N.getValueType() == TLI.getPointerTy(); +} + +ALWAYS_INLINE static bool +CheckChildType(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, const TargetLowering &TLI, + unsigned ChildNo) { + if (ChildNo >= N.getNumOperands()) + return false; // Match fails if out of range child #. + return ::CheckType(MatcherTable, MatcherIndex, N.getOperand(ChildNo), TLI); +} + + +ALWAYS_INLINE static bool +CheckCondCode(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N) { + return cast(N)->get() == + (ISD::CondCode)MatcherTable[MatcherIndex++]; +} + +ALWAYS_INLINE static bool +CheckValueType(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, const TargetLowering &TLI) { + MVT::SimpleValueType VT = (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + if (cast(N)->getVT() == VT) + return true; + + // Handle the case when VT is iPTR. + return VT == MVT::iPTR && cast(N)->getVT() == TLI.getPointerTy(); +} + +ALWAYS_INLINE static bool +CheckInteger(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N) { + int64_t Val = MatcherTable[MatcherIndex++]; + if (Val & 128) + Val = GetVBR(Val, MatcherTable, MatcherIndex); + + ConstantSDNode *C = dyn_cast(N); + return C != 0 && C->getSExtValue() == Val; +} + +ALWAYS_INLINE static bool +CheckAndImm(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, SelectionDAGISel &SDISel) { + int64_t Val = MatcherTable[MatcherIndex++]; + if (Val & 128) + Val = GetVBR(Val, MatcherTable, MatcherIndex); + + if (N->getOpcode() != ISD::AND) return false; + + ConstantSDNode *C = dyn_cast(N->getOperand(1)); + return C != 0 && SDISel.CheckAndMask(N.getOperand(0), C, Val); +} + +ALWAYS_INLINE static bool +CheckOrImm(const unsigned char *MatcherTable, unsigned &MatcherIndex, + SDValue N, SelectionDAGISel &SDISel) { + int64_t Val = MatcherTable[MatcherIndex++]; + if (Val & 128) + Val = GetVBR(Val, MatcherTable, MatcherIndex); + + if (N->getOpcode() != ISD::OR) return false; + + ConstantSDNode *C = dyn_cast(N->getOperand(1)); + return C != 0 && SDISel.CheckOrMask(N.getOperand(0), C, Val); +} + +/// IsPredicateKnownToFail - If we know how and can do so without pushing a +/// scope, evaluate the current node. If the current predicate is known to +/// fail, set Result=true and return anything. If the current predicate is +/// known to pass, set Result=false and return the MatcherIndex to continue +/// with. If the current predicate is unknown, set Result=false and return the +/// MatcherIndex to continue with. +static unsigned IsPredicateKnownToFail(const unsigned char *Table, + unsigned Index, SDValue N, + bool &Result, SelectionDAGISel &SDISel, + SmallVectorImpl &RecordedNodes){ + switch (Table[Index++]) { + default: + Result = false; + return Index-1; // Could not evaluate this predicate. + case SelectionDAGISel::OPC_CheckSame: + Result = !::CheckSame(Table, Index, N, RecordedNodes); + return Index; + case SelectionDAGISel::OPC_CheckPatternPredicate: + Result = !::CheckPatternPredicate(Table, Index, SDISel); + return Index; + case SelectionDAGISel::OPC_CheckPredicate: + Result = !::CheckNodePredicate(Table, Index, SDISel, N.getNode()); + return Index; + case SelectionDAGISel::OPC_CheckOpcode: + Result = !::CheckOpcode(Table, Index, N.getNode()); + return Index; + case SelectionDAGISel::OPC_CheckType: + Result = !::CheckType(Table, Index, N, SDISel.TLI); + return Index; + case SelectionDAGISel::OPC_CheckChild0Type: + case SelectionDAGISel::OPC_CheckChild1Type: + case SelectionDAGISel::OPC_CheckChild2Type: + case SelectionDAGISel::OPC_CheckChild3Type: + case SelectionDAGISel::OPC_CheckChild4Type: + case SelectionDAGISel::OPC_CheckChild5Type: + case SelectionDAGISel::OPC_CheckChild6Type: + case SelectionDAGISel::OPC_CheckChild7Type: + Result = !::CheckChildType(Table, Index, N, SDISel.TLI, + Table[Index-1] - SelectionDAGISel::OPC_CheckChild0Type); + return Index; + case SelectionDAGISel::OPC_CheckCondCode: + Result = !::CheckCondCode(Table, Index, N); + return Index; + case SelectionDAGISel::OPC_CheckValueType: + Result = !::CheckValueType(Table, Index, N, SDISel.TLI); + return Index; + case SelectionDAGISel::OPC_CheckInteger: + Result = !::CheckInteger(Table, Index, N); + return Index; + case SelectionDAGISel::OPC_CheckAndImm: + Result = !::CheckAndImm(Table, Index, N, SDISel); + return Index; + case SelectionDAGISel::OPC_CheckOrImm: + Result = !::CheckOrImm(Table, Index, N, SDISel); + return Index; + } +} + + +struct MatchScope { + /// FailIndex - If this match fails, this is the index to continue with. + unsigned FailIndex; + + /// NodeStack - The node stack when the scope was formed. + SmallVector NodeStack; + + /// NumRecordedNodes - The number of recorded nodes when the scope was formed. + unsigned NumRecordedNodes; + + /// NumMatchedMemRefs - The number of matched memref entries. + unsigned NumMatchedMemRefs; + + /// InputChain/InputFlag - The current chain/flag + SDValue InputChain, InputFlag; + + /// HasChainNodesMatched - True if the ChainNodesMatched list is non-empty. + bool HasChainNodesMatched, HasFlagResultNodesMatched; +}; + +SDNode *SelectionDAGISel:: +SelectCodeCommon(SDNode *NodeToMatch, const unsigned char *MatcherTable, + unsigned TableSize) { + // FIXME: Should these even be selected? Handle these cases in the caller? + switch (NodeToMatch->getOpcode()) { + default: + break; + case ISD::EntryToken: // These nodes remain the same. + case ISD::BasicBlock: + case ISD::Register: + case ISD::HANDLENODE: + case ISD::TargetConstant: + case ISD::TargetConstantFP: + case ISD::TargetConstantPool: + case ISD::TargetFrameIndex: + case ISD::TargetExternalSymbol: + case ISD::TargetBlockAddress: + case ISD::TargetJumpTable: + case ISD::TargetGlobalTLSAddress: + case ISD::TargetGlobalAddress: + case ISD::TokenFactor: + case ISD::CopyFromReg: + case ISD::CopyToReg: + NodeToMatch->setNodeId(-1); // Mark selected. + return 0; + case ISD::AssertSext: + case ISD::AssertZext: + CurDAG->ReplaceAllUsesOfValueWith(SDValue(NodeToMatch, 0), + NodeToMatch->getOperand(0)); + return 0; + case ISD::INLINEASM: return Select_INLINEASM(NodeToMatch); + case ISD::EH_LABEL: return Select_EH_LABEL(NodeToMatch); + case ISD::UNDEF: return Select_UNDEF(NodeToMatch); + } + + assert(!NodeToMatch->isMachineOpcode() && "Node already selected!"); + + // Set up the node stack with NodeToMatch as the only node on the stack. + SmallVector NodeStack; + SDValue N = SDValue(NodeToMatch, 0); + NodeStack.push_back(N); + + // MatchScopes - Scopes used when matching, if a match failure happens, this + // indicates where to continue checking. + SmallVector MatchScopes; + + // RecordedNodes - This is the set of nodes that have been recorded by the + // state machine. + SmallVector RecordedNodes; + + // MatchedMemRefs - This is the set of MemRef's we've seen in the input + // pattern. + SmallVector MatchedMemRefs; + + // These are the current input chain and flag for use when generating nodes. + // Various Emit operations change these. For example, emitting a copytoreg + // uses and updates these. + SDValue InputChain, InputFlag; + + // ChainNodesMatched - If a pattern matches nodes that have input/output + // chains, the OPC_EmitMergeInputChains operation is emitted which indicates + // which ones they are. The result is captured into this list so that we can + // update the chain results when the pattern is complete. + SmallVector ChainNodesMatched; + SmallVector FlagResultNodesMatched; + + DEBUG(errs() << "ISEL: Starting pattern match on root node: "; + NodeToMatch->dump(CurDAG); + errs() << '\n'); + + // Determine where to start the interpreter. Normally we start at opcode #0, + // but if the state machine starts with an OPC_SwitchOpcode, then we + // accelerate the first lookup (which is guaranteed to be hot) with the + // OpcodeOffset table. + unsigned MatcherIndex = 0; + + if (!OpcodeOffset.empty()) { + // Already computed the OpcodeOffset table, just index into it. + if (N.getOpcode() < OpcodeOffset.size()) + MatcherIndex = OpcodeOffset[N.getOpcode()]; + DEBUG(errs() << " Initial Opcode index to " << MatcherIndex << "\n"); + + } else if (MatcherTable[0] == OPC_SwitchOpcode) { + // Otherwise, the table isn't computed, but the state machine does start + // with an OPC_SwitchOpcode instruction. Populate the table now, since this + // is the first time we're selecting an instruction. + unsigned Idx = 1; + while (1) { + // Get the size of this case. + unsigned CaseSize = MatcherTable[Idx++]; + if (CaseSize & 128) + CaseSize = GetVBR(CaseSize, MatcherTable, Idx); + if (CaseSize == 0) break; + + // Get the opcode, add the index to the table. + unsigned Opc = MatcherTable[Idx++]; + if (Opc >= OpcodeOffset.size()) + OpcodeOffset.resize((Opc+1)*2); + OpcodeOffset[Opc] = Idx; + Idx += CaseSize; + } + + // Okay, do the lookup for the first opcode. + if (N.getOpcode() < OpcodeOffset.size()) + MatcherIndex = OpcodeOffset[N.getOpcode()]; + } + + while (1) { + assert(MatcherIndex < TableSize && "Invalid index"); + BuiltinOpcodes Opcode = (BuiltinOpcodes)MatcherTable[MatcherIndex++]; + switch (Opcode) { + case OPC_Scope: { + // Okay, the semantics of this operation are that we should push a scope + // then evaluate the first child. However, pushing a scope only to have + // the first check fail (which then pops it) is inefficient. If we can + // determine immediately that the first check (or first several) will + // immediately fail, don't even bother pushing a scope for them. + unsigned FailIndex; + + while (1) { + unsigned NumToSkip = MatcherTable[MatcherIndex++]; + if (NumToSkip & 128) + NumToSkip = GetVBR(NumToSkip, MatcherTable, MatcherIndex); + // Found the end of the scope with no match. + if (NumToSkip == 0) { + FailIndex = 0; + break; + } + + FailIndex = MatcherIndex+NumToSkip; + + // If we can't evaluate this predicate without pushing a scope (e.g. if + // it is a 'MoveParent') or if the predicate succeeds on this node, we + // push the scope and evaluate the full predicate chain. + bool Result; + MatcherIndex = IsPredicateKnownToFail(MatcherTable, MatcherIndex, N, + Result, *this, RecordedNodes); + if (!Result) + break; + + DEBUG(errs() << " Skipped scope entry at index " << MatcherIndex + << " continuing at " << FailIndex << "\n"); + + + // Otherwise, we know that this case of the Scope is guaranteed to fail, + // move to the next case. + MatcherIndex = FailIndex; + } + + // If the whole scope failed to match, bail. + if (FailIndex == 0) break; + + // Push a MatchScope which indicates where to go if the first child fails + // to match. + MatchScope NewEntry; + NewEntry.FailIndex = FailIndex; + NewEntry.NodeStack.append(NodeStack.begin(), NodeStack.end()); + NewEntry.NumRecordedNodes = RecordedNodes.size(); + NewEntry.NumMatchedMemRefs = MatchedMemRefs.size(); + NewEntry.InputChain = InputChain; + NewEntry.InputFlag = InputFlag; + NewEntry.HasChainNodesMatched = !ChainNodesMatched.empty(); + NewEntry.HasFlagResultNodesMatched = !FlagResultNodesMatched.empty(); + MatchScopes.push_back(NewEntry); + continue; + } + case OPC_RecordNode: + // Remember this node, it may end up being an operand in the pattern. + RecordedNodes.push_back(N); + continue; + + case OPC_RecordChild0: case OPC_RecordChild1: + case OPC_RecordChild2: case OPC_RecordChild3: + case OPC_RecordChild4: case OPC_RecordChild5: + case OPC_RecordChild6: case OPC_RecordChild7: { + unsigned ChildNo = Opcode-OPC_RecordChild0; + if (ChildNo >= N.getNumOperands()) + break; // Match fails if out of range child #. + + RecordedNodes.push_back(N->getOperand(ChildNo)); + continue; + } + case OPC_RecordMemRef: + MatchedMemRefs.push_back(cast(N)->getMemOperand()); + continue; + + case OPC_CaptureFlagInput: + // If the current node has an input flag, capture it in InputFlag. + if (N->getNumOperands() != 0 && + N->getOperand(N->getNumOperands()-1).getValueType() == MVT::Flag) + InputFlag = N->getOperand(N->getNumOperands()-1); + continue; + + case OPC_MoveChild: { + unsigned ChildNo = MatcherTable[MatcherIndex++]; + if (ChildNo >= N.getNumOperands()) + break; // Match fails if out of range child #. + N = N.getOperand(ChildNo); + NodeStack.push_back(N); + continue; + } + + case OPC_MoveParent: + // Pop the current node off the NodeStack. + NodeStack.pop_back(); + assert(!NodeStack.empty() && "Node stack imbalance!"); + N = NodeStack.back(); + continue; + + case OPC_CheckSame: + if (!::CheckSame(MatcherTable, MatcherIndex, N, RecordedNodes)) break; + continue; + case OPC_CheckPatternPredicate: + if (!::CheckPatternPredicate(MatcherTable, MatcherIndex, *this)) break; + continue; + case OPC_CheckPredicate: + if (!::CheckNodePredicate(MatcherTable, MatcherIndex, *this, + N.getNode())) + break; + continue; + case OPC_CheckComplexPat: { + unsigned CPNum = MatcherTable[MatcherIndex++]; + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckComplexPat"); + if (!CheckComplexPattern(NodeToMatch, RecordedNodes[RecNo], CPNum, + RecordedNodes)) + break; + continue; + } + case OPC_CheckOpcode: + if (!::CheckOpcode(MatcherTable, MatcherIndex, N.getNode())) break; + continue; + + case OPC_CheckType: + if (!::CheckType(MatcherTable, MatcherIndex, N, TLI)) break; + continue; + + case OPC_SwitchOpcode: { + unsigned CurNodeOpcode = N.getOpcode(); + unsigned SwitchStart = MatcherIndex-1; (void)SwitchStart; + unsigned CaseSize; + while (1) { + // Get the size of this case. + CaseSize = MatcherTable[MatcherIndex++]; + if (CaseSize & 128) + CaseSize = GetVBR(CaseSize, MatcherTable, MatcherIndex); + if (CaseSize == 0) break; + + // If the opcode matches, then we will execute this case. + if (CurNodeOpcode == MatcherTable[MatcherIndex++]) + break; + + // Otherwise, skip over this case. + MatcherIndex += CaseSize; + } + + // If no cases matched, bail out. + if (CaseSize == 0) break; + + // Otherwise, execute the case we found. + DEBUG(errs() << " OpcodeSwitch from " << SwitchStart + << " to " << MatcherIndex << "\n"); + continue; + } + + case OPC_SwitchType: { + MVT::SimpleValueType CurNodeVT = N.getValueType().getSimpleVT().SimpleTy; + unsigned SwitchStart = MatcherIndex-1; (void)SwitchStart; + unsigned CaseSize; + while (1) { + // Get the size of this case. + CaseSize = MatcherTable[MatcherIndex++]; + if (CaseSize & 128) + CaseSize = GetVBR(CaseSize, MatcherTable, MatcherIndex); + if (CaseSize == 0) break; + + MVT::SimpleValueType CaseVT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + if (CaseVT == MVT::iPTR) + CaseVT = TLI.getPointerTy().SimpleTy; + + // If the VT matches, then we will execute this case. + if (CurNodeVT == CaseVT) + break; + + // Otherwise, skip over this case. + MatcherIndex += CaseSize; + } + + // If no cases matched, bail out. + if (CaseSize == 0) break; + + // Otherwise, execute the case we found. + DEBUG(errs() << " TypeSwitch[" << EVT(CurNodeVT).getEVTString() + << "] from " << SwitchStart << " to " << MatcherIndex<<'\n'); + continue; + } + case OPC_CheckChild0Type: case OPC_CheckChild1Type: + case OPC_CheckChild2Type: case OPC_CheckChild3Type: + case OPC_CheckChild4Type: case OPC_CheckChild5Type: + case OPC_CheckChild6Type: case OPC_CheckChild7Type: + if (!::CheckChildType(MatcherTable, MatcherIndex, N, TLI, + Opcode-OPC_CheckChild0Type)) + break; + continue; + case OPC_CheckCondCode: + if (!::CheckCondCode(MatcherTable, MatcherIndex, N)) break; + continue; + case OPC_CheckValueType: + if (!::CheckValueType(MatcherTable, MatcherIndex, N, TLI)) break; + continue; + case OPC_CheckInteger: + if (!::CheckInteger(MatcherTable, MatcherIndex, N)) break; + continue; + case OPC_CheckAndImm: + if (!::CheckAndImm(MatcherTable, MatcherIndex, N, *this)) break; + continue; + case OPC_CheckOrImm: + if (!::CheckOrImm(MatcherTable, MatcherIndex, N, *this)) break; + continue; + + case OPC_CheckFoldableChainNode: { + assert(NodeStack.size() != 1 && "No parent node"); + // Verify that all intermediate nodes between the root and this one have + // a single use. + bool HasMultipleUses = false; + for (unsigned i = 1, e = NodeStack.size()-1; i != e; ++i) + if (!NodeStack[i].hasOneUse()) { + HasMultipleUses = true; + break; + } + if (HasMultipleUses) break; + + // Check to see that the target thinks this is profitable to fold and that + // we can fold it without inducing cycles in the graph. + if (!IsProfitableToFold(N, NodeStack[NodeStack.size()-2].getNode(), + NodeToMatch) || + !IsLegalToFold(N, NodeStack[NodeStack.size()-2].getNode(), + NodeToMatch, true/*We validate our own chains*/)) + break; + + continue; + } + case OPC_EmitInteger: { + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + int64_t Val = MatcherTable[MatcherIndex++]; + if (Val & 128) + Val = GetVBR(Val, MatcherTable, MatcherIndex); + RecordedNodes.push_back(CurDAG->getTargetConstant(Val, VT)); + continue; + } + case OPC_EmitRegister: { + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + unsigned RegNo = MatcherTable[MatcherIndex++]; + RecordedNodes.push_back(CurDAG->getRegister(RegNo, VT)); + continue; + } + + case OPC_EmitConvertToTarget: { + // Convert from IMM/FPIMM to target version. + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + SDValue Imm = RecordedNodes[RecNo]; + + if (Imm->getOpcode() == ISD::Constant) { + int64_t Val = cast(Imm)->getZExtValue(); + Imm = CurDAG->getTargetConstant(Val, Imm.getValueType()); + } else if (Imm->getOpcode() == ISD::ConstantFP) { + const ConstantFP *Val=cast(Imm)->getConstantFPValue(); + Imm = CurDAG->getTargetConstantFP(*Val, Imm.getValueType()); + } + + RecordedNodes.push_back(Imm); + continue; + } + + case OPC_EmitMergeInputChains: { + assert(InputChain.getNode() == 0 && + "EmitMergeInputChains should be the first chain producing node"); + // This node gets a list of nodes we matched in the input that have + // chains. We want to token factor all of the input chains to these nodes + // together. However, if any of the input chains is actually one of the + // nodes matched in this pattern, then we have an intra-match reference. + // Ignore these because the newly token factored chain should not refer to + // the old nodes. + unsigned NumChains = MatcherTable[MatcherIndex++]; + assert(NumChains != 0 && "Can't TF zero chains"); + + assert(ChainNodesMatched.empty() && + "Should only have one EmitMergeInputChains per match"); + + // Read all of the chained nodes. + for (unsigned i = 0; i != NumChains; ++i) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + ChainNodesMatched.push_back(RecordedNodes[RecNo].getNode()); + + // FIXME: What if other value results of the node have uses not matched + // by this pattern? + if (ChainNodesMatched.back() != NodeToMatch && + !RecordedNodes[RecNo].hasOneUse()) { + ChainNodesMatched.clear(); + break; + } + } + + // If the inner loop broke out, the match fails. + if (ChainNodesMatched.empty()) + break; + + // Merge the input chains if they are not intra-pattern references. + InputChain = HandleMergeInputChains(ChainNodesMatched, CurDAG); + + if (InputChain.getNode() == 0) + break; // Failed to merge. + + continue; + } + + case OPC_EmitCopyToReg: { + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + unsigned DestPhysReg = MatcherTable[MatcherIndex++]; + + if (InputChain.getNode() == 0) + InputChain = CurDAG->getEntryNode(); + + InputChain = CurDAG->getCopyToReg(InputChain, NodeToMatch->getDebugLoc(), + DestPhysReg, RecordedNodes[RecNo], + InputFlag); + + InputFlag = InputChain.getValue(1); + continue; + } + + case OPC_EmitNodeXForm: { + unsigned XFormNo = MatcherTable[MatcherIndex++]; + unsigned RecNo = MatcherTable[MatcherIndex++]; + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + RecordedNodes.push_back(RunSDNodeXForm(RecordedNodes[RecNo], XFormNo)); + continue; + } + + case OPC_EmitNode: + case OPC_MorphNodeTo: { + uint16_t TargetOpc = MatcherTable[MatcherIndex++]; + TargetOpc |= (unsigned short)MatcherTable[MatcherIndex++] << 8; + unsigned EmitNodeInfo = MatcherTable[MatcherIndex++]; + // Get the result VT list. + unsigned NumVTs = MatcherTable[MatcherIndex++]; + SmallVector VTs; + for (unsigned i = 0; i != NumVTs; ++i) { + MVT::SimpleValueType VT = + (MVT::SimpleValueType)MatcherTable[MatcherIndex++]; + if (VT == MVT::iPTR) VT = TLI.getPointerTy().SimpleTy; + VTs.push_back(VT); + } + + if (EmitNodeInfo & OPFL_Chain) + VTs.push_back(MVT::Other); + if (EmitNodeInfo & OPFL_FlagOutput) + VTs.push_back(MVT::Flag); + + // This is hot code, so optimize the two most common cases of 1 and 2 + // results. + SDVTList VTList; + if (VTs.size() == 1) + VTList = CurDAG->getVTList(VTs[0]); + else if (VTs.size() == 2) + VTList = CurDAG->getVTList(VTs[0], VTs[1]); + else + VTList = CurDAG->getVTList(VTs.data(), VTs.size()); + + // Get the operand list. + unsigned NumOps = MatcherTable[MatcherIndex++]; + SmallVector Ops; + for (unsigned i = 0; i != NumOps; ++i) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + if (RecNo & 128) + RecNo = GetVBR(RecNo, MatcherTable, MatcherIndex); + + assert(RecNo < RecordedNodes.size() && "Invalid EmitNode"); + Ops.push_back(RecordedNodes[RecNo]); + } + + // If there are variadic operands to add, handle them now. + if (EmitNodeInfo & OPFL_VariadicInfo) { + // Determine the start index to copy from. + unsigned FirstOpToCopy = getNumFixedFromVariadicInfo(EmitNodeInfo); + FirstOpToCopy += (EmitNodeInfo & OPFL_Chain) ? 1 : 0; + assert(NodeToMatch->getNumOperands() >= FirstOpToCopy && + "Invalid variadic node"); + // Copy all of the variadic operands, not including a potential flag + // input. + for (unsigned i = FirstOpToCopy, e = NodeToMatch->getNumOperands(); + i != e; ++i) { + SDValue V = NodeToMatch->getOperand(i); + if (V.getValueType() == MVT::Flag) break; + Ops.push_back(V); + } + } + + // If this has chain/flag inputs, add them. + if (EmitNodeInfo & OPFL_Chain) + Ops.push_back(InputChain); + if ((EmitNodeInfo & OPFL_FlagInput) && InputFlag.getNode() != 0) + Ops.push_back(InputFlag); + + // Create the node. + SDNode *Res = 0; + if (Opcode != OPC_MorphNodeTo) { + // If this is a normal EmitNode command, just create the new node and + // add the results to the RecordedNodes list. + Res = CurDAG->getMachineNode(TargetOpc, NodeToMatch->getDebugLoc(), + VTList, Ops.data(), Ops.size()); + + // Add all the non-flag/non-chain results to the RecordedNodes list. + for (unsigned i = 0, e = VTs.size(); i != e; ++i) { + if (VTs[i] == MVT::Other || VTs[i] == MVT::Flag) break; + RecordedNodes.push_back(SDValue(Res, i)); + } + + } else { + Res = MorphNode(NodeToMatch, TargetOpc, VTList, Ops.data(), Ops.size(), + EmitNodeInfo); + } + + // If the node had chain/flag results, update our notion of the current + // chain and flag. + if (EmitNodeInfo & OPFL_FlagOutput) { + InputFlag = SDValue(Res, VTs.size()-1); + if (EmitNodeInfo & OPFL_Chain) + InputChain = SDValue(Res, VTs.size()-2); + } else if (EmitNodeInfo & OPFL_Chain) + InputChain = SDValue(Res, VTs.size()-1); + + // If the OPFL_MemRefs flag is set on this node, slap all of the + // accumulated memrefs onto it. + // + // FIXME: This is vastly incorrect for patterns with multiple outputs + // instructions that access memory and for ComplexPatterns that match + // loads. + if (EmitNodeInfo & OPFL_MemRefs) { + MachineSDNode::mmo_iterator MemRefs = + MF->allocateMemRefsArray(MatchedMemRefs.size()); + std::copy(MatchedMemRefs.begin(), MatchedMemRefs.end(), MemRefs); + cast(Res) + ->setMemRefs(MemRefs, MemRefs + MatchedMemRefs.size()); + } + + DEBUG(errs() << " " + << (Opcode == OPC_MorphNodeTo ? "Morphed" : "Created") + << " node: "; Res->dump(CurDAG); errs() << "\n"); + + // If this was a MorphNodeTo then we're completely done! + if (Opcode == OPC_MorphNodeTo) { + // Update chain and flag uses. + UpdateChainsAndFlags(NodeToMatch, InputChain, ChainNodesMatched, + InputFlag, FlagResultNodesMatched, true); + return Res; + } + + continue; + } + + case OPC_MarkFlagResults: { + unsigned NumNodes = MatcherTable[MatcherIndex++]; + + // Read and remember all the flag-result nodes. + for (unsigned i = 0; i != NumNodes; ++i) { + unsigned RecNo = MatcherTable[MatcherIndex++]; + if (RecNo & 128) + RecNo = GetVBR(RecNo, MatcherTable, MatcherIndex); + + assert(RecNo < RecordedNodes.size() && "Invalid CheckSame"); + FlagResultNodesMatched.push_back(RecordedNodes[RecNo].getNode()); + } + continue; + } + + case OPC_CompleteMatch: { + // The match has been completed, and any new nodes (if any) have been + // created. Patch up references to the matched dag to use the newly + // created nodes. + unsigned NumResults = MatcherTable[MatcherIndex++]; + + for (unsigned i = 0; i != NumResults; ++i) { + unsigned ResSlot = MatcherTable[MatcherIndex++]; + if (ResSlot & 128) + ResSlot = GetVBR(ResSlot, MatcherTable, MatcherIndex); + + assert(ResSlot < RecordedNodes.size() && "Invalid CheckSame"); + SDValue Res = RecordedNodes[ResSlot]; + + // FIXME2: Eliminate this horrible hack by fixing the 'Gen' program + // after (parallel) on input patterns are removed. This would also + // allow us to stop encoding #results in OPC_CompleteMatch's table + // entry. + if (NodeToMatch->getNumValues() <= i || + NodeToMatch->getValueType(i) == MVT::Other || + NodeToMatch->getValueType(i) == MVT::Flag) + break; + assert((NodeToMatch->getValueType(i) == Res.getValueType() || + NodeToMatch->getValueType(i) == MVT::iPTR || + Res.getValueType() == MVT::iPTR || + NodeToMatch->getValueType(i).getSizeInBits() == + Res.getValueType().getSizeInBits()) && + "invalid replacement"); + CurDAG->ReplaceAllUsesOfValueWith(SDValue(NodeToMatch, i), Res); + } + + // If the root node defines a flag, add it to the flag nodes to update + // list. + if (NodeToMatch->getValueType(NodeToMatch->getNumValues()-1) == MVT::Flag) + FlagResultNodesMatched.push_back(NodeToMatch); + + // Update chain and flag uses. + UpdateChainsAndFlags(NodeToMatch, InputChain, ChainNodesMatched, + InputFlag, FlagResultNodesMatched, false); + + assert(NodeToMatch->use_empty() && + "Didn't replace all uses of the node?"); + + // FIXME: We just return here, which interacts correctly with SelectRoot + // above. We should fix this to not return an SDNode* anymore. + return 0; + } + } + + // If the code reached this point, then the match failed. See if there is + // another child to try in the current 'Scope', otherwise pop it until we + // find a case to check. + while (1) { + if (MatchScopes.empty()) { + CannotYetSelect(NodeToMatch); + return 0; + } + + // Restore the interpreter state back to the point where the scope was + // formed. + MatchScope &LastScope = MatchScopes.back(); + RecordedNodes.resize(LastScope.NumRecordedNodes); + NodeStack.clear(); + NodeStack.append(LastScope.NodeStack.begin(), LastScope.NodeStack.end()); + N = NodeStack.back(); + + DEBUG(errs() << " Match failed at index " << MatcherIndex + << " continuing at " << LastScope.FailIndex << "\n"); + + if (LastScope.NumMatchedMemRefs != MatchedMemRefs.size()) + MatchedMemRefs.resize(LastScope.NumMatchedMemRefs); + MatcherIndex = LastScope.FailIndex; + + InputChain = LastScope.InputChain; + InputFlag = LastScope.InputFlag; + if (!LastScope.HasChainNodesMatched) + ChainNodesMatched.clear(); + if (!LastScope.HasFlagResultNodesMatched) + FlagResultNodesMatched.clear(); + + // Check to see what the offset is at the new MatcherIndex. If it is zero + // we have reached the end of this scope, otherwise we have another child + // in the current scope to try. + unsigned NumToSkip = MatcherTable[MatcherIndex++]; + if (NumToSkip & 128) + NumToSkip = GetVBR(NumToSkip, MatcherTable, MatcherIndex); + + // If we have another child in this scope to match, update FailIndex and + // try it. + if (NumToSkip != 0) { + LastScope.FailIndex = MatcherIndex+NumToSkip; + break; + } + + // End of this scope, pop it and try the next child in the containing + // scope. + MatchScopes.pop_back(); + } + } +} + + + void SelectionDAGISel::CannotYetSelect(SDNode *N) { std::string msg; raw_string_ostream Msg(msg); Msg << "Cannot yet select: "; - N->printrFull(Msg, CurDAG); + + if (N->getOpcode() != ISD::INTRINSIC_W_CHAIN && + N->getOpcode() != ISD::INTRINSIC_WO_CHAIN && + N->getOpcode() != ISD::INTRINSIC_VOID) { + N->printrFull(Msg, CurDAG); + } else { + bool HasInputChain = N->getOperand(0).getValueType() == MVT::Other; + unsigned iid = + cast(N->getOperand(HasInputChain))->getZExtValue(); + if (iid < Intrinsic::num_intrinsics) + Msg << "intrinsic %" << Intrinsic::getName((Intrinsic::ID)iid); + else if (const TargetIntrinsicInfo *TII = TM.getIntrinsicInfo()) + Msg << "target intrinsic %" << TII->getName(iid); + else + Msg << "unknown intrinsic #" << iid; + } llvm_report_error(Msg.str()); } -void SelectionDAGISel::CannotYetSelectIntrinsic(SDNode *N) { - dbgs() << "Cannot yet select: "; - unsigned iid = - cast(N->getOperand(N->getOperand(0).getValueType() == - MVT::Other))->getZExtValue(); - if (iid < Intrinsic::num_intrinsics) - llvm_report_error("Cannot yet select: intrinsic %" + - Intrinsic::getName((Intrinsic::ID)iid)); - else if (const TargetIntrinsicInfo *tii = TM.getIntrinsicInfo()) - llvm_report_error(Twine("Cannot yet select: target intrinsic %") + - tii->getName(iid)); -} - char SelectionDAGISel::ID = 0; diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index d74ec7e2e5..8d0d884c81 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -28,6 +28,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include using namespace llvm; namespace llvm { @@ -540,6 +541,24 @@ TargetLowering::~TargetLowering() { delete &TLOF; } +/// canOpTrap - Returns true if the operation can trap for the value type. +/// VT must be a legal type. +bool TargetLowering::canOpTrap(unsigned Op, EVT VT) const { + assert(isTypeLegal(VT)); + switch (Op) { + default: + return false; + case ISD::FDIV: + case ISD::FREM: + case ISD::SDIV: + case ISD::UDIV: + case ISD::SREM: + case ISD::UREM: + return true; + } +} + + static unsigned getVectorTypeBreakdownMVT(MVT VT, MVT &IntermediateVT, unsigned &NumIntermediates, EVT &RegisterVT, @@ -1423,8 +1442,10 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op, case ISD::TRUNCATE: { // Simplify the input, using demanded bit information, and compute the known // zero/one bits live out. + unsigned OperandBitWidth = + Op.getOperand(0).getValueType().getScalarType().getSizeInBits(); APInt TruncMask = NewMask; - TruncMask.zext(Op.getOperand(0).getValueSizeInBits()); + TruncMask.zext(OperandBitWidth); if (SimplifyDemandedBits(Op.getOperand(0), TruncMask, KnownZero, KnownOne, TLO, Depth+1)) return true; @@ -1435,15 +1456,14 @@ bool TargetLowering::SimplifyDemandedBits(SDValue Op, // on the known demanded bits. if (Op.getOperand(0).getNode()->hasOneUse()) { SDValue In = Op.getOperand(0); - unsigned InBitWidth = In.getValueSizeInBits(); switch (In.getOpcode()) { default: break; case ISD::SRL: // Shrink SRL by a constant if none of the high bits shifted in are // demanded. if (ConstantSDNode *ShAmt = dyn_cast(In.getOperand(1))){ - APInt HighBits = APInt::getHighBitsSet(InBitWidth, - InBitWidth - BitWidth); + APInt HighBits = APInt::getHighBitsSet(OperandBitWidth, + OperandBitWidth - BitWidth); HighBits = HighBits.lshr(ShAmt->getZExtValue()); HighBits.trunc(BitWidth); @@ -1589,7 +1609,7 @@ static bool ValueHasExactlyOneBitSet(SDValue Val, const SelectionDAG &DAG) { // Fall back to ComputeMaskedBits to catch other known cases. EVT OpVT = Val.getValueType(); - unsigned BitWidth = OpVT.getSizeInBits(); + unsigned BitWidth = OpVT.getScalarType().getSizeInBits(); APInt Mask = APInt::getAllOnesValue(BitWidth); APInt KnownZero, KnownOne; DAG.ComputeMaskedBits(Val, Mask, KnownZero, KnownOne); @@ -1698,7 +1718,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, SDValue NewLoad = DAG.getLoad(newVT, dl, Lod->getChain(), Ptr, Lod->getSrcValue(), Lod->getSrcValueOffset() + bestOffset, - false, NewAlign); + false, false, NewAlign); return DAG.getSetCC(dl, VT, DAG.getNode(ISD::AND, dl, newVT, NewLoad, DAG.getConstant(bestMask.trunc(bestWidth), @@ -1757,7 +1777,7 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, break; // todo, be more careful with signed comparisons } } else if (N0.getOpcode() == ISD::SIGN_EXTEND_INREG && - (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { + (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { EVT ExtSrcTy = cast(N0.getOperand(1))->getVT(); unsigned ExtSrcTyBits = ExtSrcTy.getSizeInBits(); EVT ExtDstTy = N0.getValueType(); @@ -1791,22 +1811,21 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, Cond); } else if ((N1C->isNullValue() || N1C->getAPIntValue() == 1) && (Cond == ISD::SETEQ || Cond == ISD::SETNE)) { - // SETCC (SETCC), [0|1], [EQ|NE] -> SETCC - if (N0.getOpcode() == ISD::SETCC) { + if (N0.getOpcode() == ISD::SETCC && + isTypeLegal(VT) && VT.bitsLE(N0.getValueType())) { bool TrueWhenTrue = (Cond == ISD::SETEQ) ^ (N1C->getAPIntValue() != 1); if (TrueWhenTrue) - return N0; - + return DAG.getNode(ISD::TRUNCATE, dl, VT, N0); // Invert the condition. ISD::CondCode CC = cast(N0.getOperand(2))->get(); CC = ISD::getSetCCInverse(CC, N0.getOperand(0).getValueType().isInteger()); return DAG.getSetCC(dl, VT, N0.getOperand(0), N0.getOperand(1), CC); } - + if ((N0.getOpcode() == ISD::XOR || - (N0.getOpcode() == ISD::AND && + (N0.getOpcode() == ISD::AND && N0.getOperand(0).getOpcode() == ISD::XOR && N0.getOperand(1) == N0.getOperand(0).getOperand(1))) && isa(N0.getOperand(1)) && @@ -1829,9 +1848,36 @@ TargetLowering::SimplifySetCC(EVT VT, SDValue N0, SDValue N1, N0.getOperand(0).getOperand(0), N0.getOperand(1)); } + return DAG.getSetCC(dl, VT, Val, N1, Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ); } + } else if (N1C->getAPIntValue() == 1 && + (VT == MVT::i1 || + getBooleanContents() == ZeroOrOneBooleanContent)) { + SDValue Op0 = N0; + if (Op0.getOpcode() == ISD::TRUNCATE) + Op0 = Op0.getOperand(0); + + if ((Op0.getOpcode() == ISD::XOR) && + Op0.getOperand(0).getOpcode() == ISD::SETCC && + Op0.getOperand(1).getOpcode() == ISD::SETCC) { + // (xor (setcc), (setcc)) == / != 1 -> (setcc) != / == (setcc) + Cond = (Cond == ISD::SETEQ) ? ISD::SETNE : ISD::SETEQ; + return DAG.getSetCC(dl, VT, Op0.getOperand(0), Op0.getOperand(1), + Cond); + } else if (Op0.getOpcode() == ISD::AND && + isa(Op0.getOperand(1)) && + cast(Op0.getOperand(1))->getAPIntValue() == 1) { + // If this is (X&1) == / != 1, normalize it to (X&1) != / == 0. + if (Op0.getValueType() != VT) + Op0 = DAG.getNode(ISD::AND, dl, VT, + DAG.getNode(ISD::TRUNCATE, dl, VT, Op0.getOperand(0)), + DAG.getConstant(1, VT)); + return DAG.getSetCC(dl, VT, Op0, + DAG.getConstant(0, Op0.getValueType()), + Cond == ISD::SETEQ ? ISD::SETNE : ISD::SETEQ); + } } } diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index 1d9bda4ab0..ce72b2fc14 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -662,7 +662,7 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, if (!tii_->isTriviallyReMaterializable(DefMI, AA)) return false; bool SawStore = false; - if (!DefMI->isSafeToMove(tii_, SawStore, AA)) + if (!DefMI->isSafeToMove(tii_, AA, SawStore)) return false; if (TID.getNumDefs() != 1) return false; @@ -702,7 +702,8 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, for (const unsigned* SR = tri_->getSubRegisters(DstReg); *SR; ++SR) { if (!li_->hasInterval(*SR)) continue; - DLR = li_->getInterval(*SR).getLiveRangeContaining(DefIdx); + const LiveRange *DLR = + li_->getInterval(*SR).getLiveRangeContaining(DefIdx); if (DLR && DLR->valno->getCopy() == CopyMI) DLR->valno->setCopy(0); } @@ -741,9 +742,21 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, NewMI->addOperand(MO); if (MO.isDef() && li_->hasInterval(MO.getReg())) { unsigned Reg = MO.getReg(); - DLR = li_->getInterval(Reg).getLiveRangeContaining(DefIdx); + const LiveRange *DLR = + li_->getInterval(Reg).getLiveRangeContaining(DefIdx); if (DLR && DLR->valno->getCopy() == CopyMI) DLR->valno->setCopy(0); + // Handle subregs as well + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + for (const unsigned* SR = tri_->getSubRegisters(Reg); *SR; ++SR) { + if (!li_->hasInterval(*SR)) + continue; + const LiveRange *DLR = + li_->getInterval(*SR).getLiveRangeContaining(DefIdx); + if (DLR && DLR->valno->getCopy() == CopyMI) + DLR->valno->setCopy(0); + } + } } } @@ -752,6 +765,7 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt, CopyMI->eraseFromParent(); ReMatCopies.insert(CopyMI); ReMatDefs.insert(DefMI); + DEBUG(dbgs() << "Remat: " << *NewMI); ++NumReMats; return true; } @@ -771,11 +785,16 @@ SimpleRegisterCoalescing::UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, SubIdx = 0; } + // Copy the register use-list before traversing it. We may be adding operands + // and invalidating pointers. + SmallVector, 32> reglist; for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg), - E = mri_->reg_end(); I != E; ) { - MachineOperand &O = I.getOperand(); - MachineInstr *UseMI = &*I; - ++I; + E = mri_->reg_end(); I != E; ++I) + reglist.push_back(std::make_pair(&*I, I.getOperandNo())); + + for (unsigned N=0; N != reglist.size(); ++N) { + MachineInstr *UseMI = reglist[N].first; + MachineOperand &O = UseMI->getOperand(reglist[N].second); unsigned OldSubIdx = O.getSubReg(); if (DstIsPhys) { unsigned UseDstReg = DstReg; @@ -796,6 +815,19 @@ SimpleRegisterCoalescing::UpdateRegDefsUses(unsigned SrcReg, unsigned DstReg, O.setReg(UseDstReg); O.setSubReg(0); + if (OldSubIdx) { + // Def and kill of subregister of a virtual register actually defs and + // kills the whole register. Add imp-defs and imp-kills as needed. + if (O.isDef()) { + if(O.isDead()) + UseMI->addRegisterDead(DstReg, tri_, true); + else + UseMI->addRegisterDefined(DstReg, tri_); + } else if (!O.isUndef() && + (O.isKill() || + UseMI->isRegTiedToDefOperand(&O-&UseMI->getOperand(0)))) + UseMI->addRegisterKilled(DstReg, tri_, true); + } continue; } @@ -1148,12 +1180,14 @@ SimpleRegisterCoalescing::isWinToJoinCrossClass(unsigned LargeReg, LiveInterval &SmallInt = li_->getInterval(SmallReg); unsigned LargeSize = li_->getApproximateInstructionCount(LargeInt); unsigned SmallSize = li_->getApproximateInstructionCount(SmallInt); - if (SmallSize > Threshold || LargeSize > Threshold) - if ((float)std::distance(mri_->use_nodbg_begin(SmallReg), - mri_->use_nodbg_end()) / SmallSize < - (float)std::distance(mri_->use_nodbg_begin(LargeReg), - mri_->use_nodbg_end()) / LargeSize) + if (LargeSize > Threshold) { + unsigned SmallUses = std::distance(mri_->use_nodbg_begin(SmallReg), + mri_->use_nodbg_end()); + unsigned LargeUses = std::distance(mri_->use_nodbg_begin(LargeReg), + mri_->use_nodbg_end()); + if (SmallUses*LargeSize < LargeUses*SmallSize) return false; + } return true; } @@ -1173,6 +1207,8 @@ SimpleRegisterCoalescing::HasIncompatibleSubRegDefUse(MachineInstr *CopyMI, for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(VirtReg), E = mri_->reg_end(); I != E; ++I) { MachineOperand &O = I.getOperand(); + if (O.isDebug()) + continue; MachineInstr *MI = &*I; if (MI == CopyMI || JoinedCopies.count(MI)) continue; @@ -1559,7 +1595,10 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { (isExtSubReg || DstRC->isASubClass()) && !isWinToJoinCrossClass(LargeReg, SmallReg, allocatableRCRegs_[NewRC].count())) { - DEBUG(dbgs() << "\tSrc/Dest are different register classes.\n"); + DEBUG(dbgs() << "\tSrc/Dest are different register classes: " + << SrcRC->getName() << "/" + << DstRC->getName() << " -> " + << NewRC->getName() << ".\n"); // Allow the coalescer to try again in case either side gets coalesced to // a physical register that's compatible with the other side. e.g. // r1024 = MOV32to32_ r1025 @@ -1680,6 +1719,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { (AdjustCopiesBackFrom(SrcInt, DstInt, CopyMI) || RemoveCopyByCommutingDef(SrcInt, DstInt, CopyMI))) { JoinedCopies.insert(CopyMI); + DEBUG(dbgs() << "Trivial!\n"); return true; } @@ -1839,7 +1879,7 @@ static unsigned ComputeUltimateVN(VNInfo *VNI, // If the VN has already been computed, just return it. if (ThisValNoAssignments[VN] >= 0) return ThisValNoAssignments[VN]; -// assert(ThisValNoAssignments[VN] != -2 && "Cyclic case?"); + assert(ThisValNoAssignments[VN] != -2 && "Cyclic value numbers"); // If this val is not a copy from the other val, then it must be a new value // number in the destination. diff --git a/lib/CodeGen/SjLjEHPrepare.cpp b/lib/CodeGen/SjLjEHPrepare.cpp index 8d4d1b21dd..059e8d6c19 100644 --- a/lib/CodeGen/SjLjEHPrepare.cpp +++ b/lib/CodeGen/SjLjEHPrepare.cpp @@ -44,7 +44,6 @@ namespace { const Type *FunctionContextTy; Constant *RegisterFn; Constant *UnregisterFn; - Constant *ResumeFn; Constant *BuiltinSetjmpFn; Constant *FrameAddrFn; Constant *LSDAAddrFn; @@ -67,8 +66,8 @@ namespace { } private: - void markInvokeCallSite(InvokeInst *II, unsigned InvokeNo, - Value *CallSite, + void insertCallSiteStore(Instruction *I, int Number, Value *CallSite); + void markInvokeCallSite(InvokeInst *II, int InvokeNo, Value *CallSite, SwitchInst *CatchSwitch); void splitLiveRangesLiveAcrossInvokes(SmallVector &Invokes); bool insertSjLjEHSupport(Function &F); @@ -107,11 +106,6 @@ bool SjLjEHPass::doInitialization(Module &M) { Type::getVoidTy(M.getContext()), PointerType::getUnqual(FunctionContextTy), (Type *)0); - ResumeFn = - M.getOrInsertFunction("_Unwind_SjLj_Resume", - Type::getVoidTy(M.getContext()), - VoidPtrTy, - (Type *)0); FrameAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::frameaddress); BuiltinSetjmpFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_setjmp); LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda); @@ -123,12 +117,22 @@ bool SjLjEHPass::doInitialization(Module &M) { return true; } +/// insertCallSiteStore - Insert a store of the call-site value to the +/// function context +void SjLjEHPass::insertCallSiteStore(Instruction *I, int Number, + Value *CallSite) { + ConstantInt *CallSiteNoC = ConstantInt::get(Type::getInt32Ty(I->getContext()), + Number); + // Insert a store of the call-site number + new StoreInst(CallSiteNoC, CallSite, true, I); // volatile +} + /// markInvokeCallSite - Insert code to mark the call_site for this invoke -void SjLjEHPass::markInvokeCallSite(InvokeInst *II, unsigned InvokeNo, +void SjLjEHPass::markInvokeCallSite(InvokeInst *II, int InvokeNo, Value *CallSite, SwitchInst *CatchSwitch) { ConstantInt *CallSiteNoC= ConstantInt::get(Type::getInt32Ty(II->getContext()), - InvokeNo); + InvokeNo); // The runtime comes back to the dispatcher with the call_site - 1 in // the context. Odd, but there it is. ConstantInt *SwitchValC = ConstantInt::get(Type::getInt32Ty(II->getContext()), @@ -145,8 +149,11 @@ void SjLjEHPass::markInvokeCallSite(InvokeInst *II, unsigned InvokeNo, } } - // Insert a store of the invoke num before the invoke - new StoreInst(CallSiteNoC, CallSite, true, II); // volatile + // Insert the store of the call site value + insertCallSiteStore(II, InvokeNo, CallSite); + + // Record the call site value for the back end so it stays associated with + // the invoke. CallInst::Create(CallSiteFn, CallSiteNoC, "", II); // Add a switch case to our unwind block. @@ -272,8 +279,8 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { SmallVector Invokes; // Look through the terminators of the basic blocks to find invokes, returns - // and unwinds - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + // and unwinds. + for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { // Remember all return instructions in case we insert an invoke into this // function. @@ -283,6 +290,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { } else if (UnwindInst *UI = dyn_cast(BB->getTerminator())) { Unwinds.push_back(UI); } + } // If we don't have any invokes or unwinds, there's nothing to do. if (Unwinds.empty() && Invokes.empty()) return false; @@ -478,24 +486,21 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) { for (unsigned i = 0, e = Invokes.size(); i != e; ++i) markInvokeCallSite(Invokes[i], i+1, CallSite, DispatchSwitch); - // The front end has likely added calls to _Unwind_Resume. We need - // to find those calls and mark the call_site as -1 immediately prior. - // resume is a noreturn function, so any block that has a call to it - // should end in an 'unreachable' instruction with the call immediately - // prior. That's how we'll search. - // ??? There's got to be a better way. this is fugly. - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - if ((dyn_cast(BB->getTerminator()))) { - BasicBlock::iterator I = BB->getTerminator(); - // Check the previous instruction and see if it's a resume call - if (I == BB->begin()) continue; - if (CallInst *CI = dyn_cast(--I)) { - if (CI->getCalledFunction() == ResumeFn) { - Value *NegativeOne = Constant::getAllOnesValue(Int32Ty); - new StoreInst(NegativeOne, CallSite, true, I); // volatile - } + // Mark call instructions that aren't nounwind as no-action + // (call_site == -1). Skip the entry block, as prior to then, no function + // context has been created for this function and any unexpected exceptions + // thrown will go directly to the caller's context, which is what we want + // anyway, so no need to do anything here. + for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) { + for (BasicBlock::iterator I = BB->begin(), end = BB->end(); I != end; ++I) + if (CallInst *CI = dyn_cast(I)) { + // Ignore calls to the EH builtins (eh.selector, eh.exception) + Constant *Callee = CI->getCalledFunction(); + if (Callee != SelectorFn && Callee != ExceptionFn + && !CI->doesNotThrow()) + insertCallSiteStore(CI, -1, CallSite); } - } + } // Replace all unwinds with a branch to the unwind handler. // ??? Should this ever happen with sjlj exceptions? diff --git a/lib/CodeGen/StackProtector.cpp b/lib/CodeGen/StackProtector.cpp index 48bb5af4db..8a6a727a1f 100644 --- a/lib/CodeGen/StackProtector.cpp +++ b/lib/CodeGen/StackProtector.cpp @@ -113,7 +113,7 @@ bool StackProtector::RequiresStackProtector() const { if (const ArrayType *AT = dyn_cast(AI->getAllocatedType())) { // We apparently only care about character arrays. - if (!AT->getElementType()->isInteger(8)) + if (!AT->getElementType()->isIntegerTy(8)) continue; // If an array has more than SSPBufferSize bytes of allocated space, diff --git a/lib/CodeGen/TailDuplication.cpp b/lib/CodeGen/TailDuplication.cpp index 9ab4058b19..3223e53d5d 100644 --- a/lib/CodeGen/TailDuplication.cpp +++ b/lib/CodeGen/TailDuplication.cpp @@ -403,26 +403,45 @@ TailDuplicatePass::UpdateSuccessorsPHIs(MachineBasicBlock *FromBB, bool isDead, II->RemoveOperand(i); } } - II->RemoveOperand(Idx+1); - II->RemoveOperand(Idx); - } + } else + Idx = 0; + + // If Idx is set, the operands at Idx and Idx+1 must be removed. + // We reuse the location to avoid expensive RemoveOperand calls. + DenseMap::iterator LI=SSAUpdateVals.find(Reg); if (LI != SSAUpdateVals.end()) { // This register is defined in the tail block. for (unsigned j = 0, ee = LI->second.size(); j != ee; ++j) { MachineBasicBlock *SrcBB = LI->second[j].first; unsigned SrcReg = LI->second[j].second; - II->addOperand(MachineOperand::CreateReg(SrcReg, false)); - II->addOperand(MachineOperand::CreateMBB(SrcBB)); + if (Idx != 0) { + II->getOperand(Idx).setReg(SrcReg); + II->getOperand(Idx+1).setMBB(SrcBB); + Idx = 0; + } else { + II->addOperand(MachineOperand::CreateReg(SrcReg, false)); + II->addOperand(MachineOperand::CreateMBB(SrcBB)); + } } } else { // Live in tail block, must also be live in predecessors. for (unsigned j = 0, ee = TDBBs.size(); j != ee; ++j) { MachineBasicBlock *SrcBB = TDBBs[j]; - II->addOperand(MachineOperand::CreateReg(Reg, false)); - II->addOperand(MachineOperand::CreateMBB(SrcBB)); + if (Idx != 0) { + II->getOperand(Idx).setReg(Reg); + II->getOperand(Idx+1).setMBB(SrcBB); + Idx = 0; + } else { + II->addOperand(MachineOperand::CreateReg(Reg, false)); + II->addOperand(MachineOperand::CreateMBB(SrcBB)); + } } } + if (Idx != 0) { + II->RemoveOperand(Idx+1); + II->RemoveOperand(Idx); + } } } } diff --git a/lib/CodeGen/TargetInstrInfoImpl.cpp b/lib/CodeGen/TargetInstrInfoImpl.cpp index a0fccabdb5..e9e998f81d 100644 --- a/lib/CodeGen/TargetInstrInfoImpl.cpp +++ b/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -150,6 +150,11 @@ void TargetInstrInfoImpl::reMaterialize(MachineBasicBlock &MBB, MBB.insert(I, MI); } +bool TargetInstrInfoImpl::produceSameValue(const MachineInstr *MI0, + const MachineInstr *MI1) const { + return MI0->isIdenticalTo(MI1, MachineInstr::IgnoreVRegDefs); +} + MachineInstr *TargetInstrInfoImpl::duplicate(MachineInstr *Orig, MachineFunction &MF) const { assert(!Orig->getDesc().isNotDuplicable() && @@ -157,37 +162,6 @@ MachineInstr *TargetInstrInfoImpl::duplicate(MachineInstr *Orig, return MF.CloneMachineInstr(Orig); } -bool -TargetInstrInfoImpl::isIdentical(const MachineInstr *MI, - const MachineInstr *Other, - const MachineRegisterInfo *MRI) const { - if (MI->getOpcode() != Other->getOpcode() || - MI->getNumOperands() != Other->getNumOperands()) - return false; - - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - const MachineOperand &OMO = Other->getOperand(i); - if (MO.isReg() && MO.isDef()) { - assert(OMO.isReg() && OMO.isDef()); - unsigned Reg = MO.getReg(); - if (TargetRegisterInfo::isPhysicalRegister(Reg)) { - if (Reg != OMO.getReg()) - return false; - } else if (MRI->getRegClass(MO.getReg()) != - MRI->getRegClass(OMO.getReg())) - return false; - - continue; - } - - if (!MO.isIdenticalTo(OMO)) - return false; - } - - return true; -} - unsigned TargetInstrInfoImpl::GetFunctionSizeInBytes(const MachineFunction &MF) const { unsigned FnSize = 0; diff --git a/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp new file mode 100644 index 0000000000..d127f53a4e --- /dev/null +++ b/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -0,0 +1,902 @@ +//===-- llvm/CodeGen/TargetLoweringObjectFileImpl.cpp - Object File Info --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements classes used to handle lowerings specific to common +// object file formats. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionMachO.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +using namespace llvm; +using namespace dwarf; + +//===----------------------------------------------------------------------===// +// ELF +//===----------------------------------------------------------------------===// +typedef StringMap ELFUniqueMapTy; + +TargetLoweringObjectFileELF::~TargetLoweringObjectFileELF() { + // If we have the section uniquing map, free it. + delete (ELFUniqueMapTy*)UniquingMap; +} + +const MCSection *TargetLoweringObjectFileELF:: +getELFSection(StringRef Section, unsigned Type, unsigned Flags, + SectionKind Kind, bool IsExplicit) const { + if (UniquingMap == 0) + UniquingMap = new ELFUniqueMapTy(); + ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)UniquingMap; + + // Do the lookup, if we have a hit, return it. + const MCSectionELF *&Entry = Map[Section]; + if (Entry) return Entry; + + return Entry = MCSectionELF::Create(Section, Type, Flags, Kind, IsExplicit, + getContext()); +} + +void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((ELFUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + + BSSSection = + getELFSection(".bss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getBSS()); + + TextSection = + getELFSection(".text", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_EXECINSTR | MCSectionELF::SHF_ALLOC, + SectionKind::getText()); + + DataSection = + getELFSection(".data", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + + ReadOnlySection = + getELFSection(".rodata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, + SectionKind::getReadOnly()); + + TLSDataSection = + getELFSection(".tdata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | + MCSectionELF::SHF_WRITE, SectionKind::getThreadData()); + + TLSBSSSection = + getELFSection(".tbss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | + MCSectionELF::SHF_WRITE, SectionKind::getThreadBSS()); + + DataRelSection = + getELFSection(".data.rel", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + DataRelLocalSection = + getELFSection(".data.rel.local", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRelLocal()); + + DataRelROSection = + getELFSection(".data.rel.ro", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getReadOnlyWithRel()); + + DataRelROLocalSection = + getELFSection(".data.rel.ro.local", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getReadOnlyWithRelLocal()); + + MergeableConst4Section = + getELFSection(".rodata.cst4", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst4()); + + MergeableConst8Section = + getELFSection(".rodata.cst8", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst8()); + + MergeableConst16Section = + getELFSection(".rodata.cst16", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, + SectionKind::getMergeableConst16()); + + StaticCtorSection = + getELFSection(".ctors", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + StaticDtorSection = + getELFSection(".dtors", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + // Exception Handling Sections. + + // FIXME: We're emitting LSDA info into a readonly section on ELF, even though + // it contains relocatable pointers. In PIC mode, this is probably a big + // runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + getELFSection(".gcc_except_table", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC, SectionKind::getReadOnly()); + EHFrameSection = + getELFSection(".eh_frame", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, + SectionKind::getDataRel()); + + // Debug Info Sections. + DwarfAbbrevSection = + getELFSection(".debug_abbrev", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfInfoSection = + getELFSection(".debug_info", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLineSection = + getELFSection(".debug_line", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfFrameSection = + getELFSection(".debug_frame", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getELFSection(".debug_pubnames", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getELFSection(".debug_pubtypes", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfStrSection = + getELFSection(".debug_str", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfLocSection = + getELFSection(".debug_loc", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfARangesSection = + getELFSection(".debug_aranges", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfRangesSection = + getELFSection(".debug_ranges", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getELFSection(".debug_macinfo", MCSectionELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); +} + + +static SectionKind +getELFKindForNamedSection(StringRef Name, SectionKind K) { + if (Name.empty() || Name[0] != '.') return K; + + // Some lame default implementation based on some magic section names. + if (Name == ".bss" || + Name.startswith(".bss.") || + Name.startswith(".gnu.linkonce.b.") || + Name.startswith(".llvm.linkonce.b.") || + Name == ".sbss" || + Name.startswith(".sbss.") || + Name.startswith(".gnu.linkonce.sb.") || + Name.startswith(".llvm.linkonce.sb.")) + return SectionKind::getBSS(); + + if (Name == ".tdata" || + Name.startswith(".tdata.") || + Name.startswith(".gnu.linkonce.td.") || + Name.startswith(".llvm.linkonce.td.")) + return SectionKind::getThreadData(); + + if (Name == ".tbss" || + Name.startswith(".tbss.") || + Name.startswith(".gnu.linkonce.tb.") || + Name.startswith(".llvm.linkonce.tb.")) + return SectionKind::getThreadBSS(); + + return K; +} + + +static unsigned getELFSectionType(StringRef Name, SectionKind K) { + + if (Name == ".init_array") + return MCSectionELF::SHT_INIT_ARRAY; + + if (Name == ".fini_array") + return MCSectionELF::SHT_FINI_ARRAY; + + if (Name == ".preinit_array") + return MCSectionELF::SHT_PREINIT_ARRAY; + + if (K.isBSS() || K.isThreadBSS()) + return MCSectionELF::SHT_NOBITS; + + return MCSectionELF::SHT_PROGBITS; +} + + +static unsigned +getELFSectionFlags(SectionKind K) { + unsigned Flags = 0; + + if (!K.isMetadata()) + Flags |= MCSectionELF::SHF_ALLOC; + + if (K.isText()) + Flags |= MCSectionELF::SHF_EXECINSTR; + + if (K.isWriteable()) + Flags |= MCSectionELF::SHF_WRITE; + + if (K.isThreadLocal()) + Flags |= MCSectionELF::SHF_TLS; + + // K.isMergeableConst() is left out to honour PR4650 + if (K.isMergeableCString() || K.isMergeableConst4() || + K.isMergeableConst8() || K.isMergeableConst16()) + Flags |= MCSectionELF::SHF_MERGE; + + if (K.isMergeableCString()) + Flags |= MCSectionELF::SHF_STRINGS; + + return Flags; +} + + +const MCSection *TargetLoweringObjectFileELF:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + StringRef SectionName = GV->getSection(); + + // Infer section flags from the section name if we can. + Kind = getELFKindForNamedSection(SectionName, Kind); + + return getELFSection(SectionName, + getELFSectionType(SectionName, Kind), + getELFSectionFlags(Kind), Kind, true); +} + +static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) return ".gnu.linkonce.t."; + if (Kind.isReadOnly()) return ".gnu.linkonce.r."; + + if (Kind.isThreadData()) return ".gnu.linkonce.td."; + if (Kind.isThreadBSS()) return ".gnu.linkonce.tb."; + + if (Kind.isDataNoRel()) return ".gnu.linkonce.d."; + if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local."; + if (Kind.isDataRel()) return ".gnu.linkonce.d.rel."; + if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local."; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return ".gnu.linkonce.d.rel.ro."; +} + +const MCSection *TargetLoweringObjectFileELF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (GV->isWeakForLinker() && !Kind.isCommon() && !Kind.isBSS()) { + const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); + SmallString<128> Name; + Name.append(Prefix, Prefix+strlen(Prefix)); + Mang->getNameWithPrefix(Name, GV, false); + return getELFSection(Name.str(), getELFSectionType(Name.str(), Kind), + getELFSectionFlags(Kind), Kind); + } + + if (Kind.isText()) return TextSection; + + if (Kind.isMergeable1ByteCString() || + Kind.isMergeable2ByteCString() || + Kind.isMergeable4ByteCString()) { + + // We also need alignment here. + // FIXME: this is getting the alignment of the character, not the + // alignment of the global! + unsigned Align = + TM.getTargetData()->getPreferredAlignment(cast(GV)); + + const char *SizeSpec = ".rodata.str1."; + if (Kind.isMergeable2ByteCString()) + SizeSpec = ".rodata.str2."; + else if (Kind.isMergeable4ByteCString()) + SizeSpec = ".rodata.str4."; + else + assert(Kind.isMergeable1ByteCString() && "unknown string width"); + + + std::string Name = SizeSpec + utostr(Align); + return getELFSection(Name, MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_ALLOC | + MCSectionELF::SHF_MERGE | + MCSectionELF::SHF_STRINGS, + Kind); + } + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4() && MergeableConst4Section) + return MergeableConst4Section; + if (Kind.isMergeableConst8() && MergeableConst8Section) + return MergeableConst8Section; + if (Kind.isMergeableConst16() && MergeableConst16Section) + return MergeableConst16Section; + return ReadOnlySection; // .const + } + + if (Kind.isReadOnly()) return ReadOnlySection; + + if (Kind.isThreadData()) return TLSDataSection; + if (Kind.isThreadBSS()) return TLSBSSSection; + + // Note: we claim that common symbols are put in BSSSection, but they are + // really emitted with the magic .comm directive, which creates a symbol table + // entry but not a section. + if (Kind.isBSS() || Kind.isCommon()) return BSSSection; + + if (Kind.isDataNoRel()) return DataSection; + if (Kind.isDataRelLocal()) return DataRelLocalSection; + if (Kind.isDataRel()) return DataRelSection; + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +/// getSectionForConstant - Given a mergeable constant with the +/// specified size and relocation information, return a section that it +/// should be placed in. +const MCSection *TargetLoweringObjectFileELF:: +getSectionForConstant(SectionKind Kind) const { + if (Kind.isMergeableConst4() && MergeableConst4Section) + return MergeableConst4Section; + if (Kind.isMergeableConst8() && MergeableConst8Section) + return MergeableConst8Section; + if (Kind.isMergeableConst16() && MergeableConst16Section) + return MergeableConst16Section; + if (Kind.isReadOnly()) + return ReadOnlySection; + + if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; + assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); + return DataRelROSection; +} + +const MCExpr *TargetLoweringObjectFileELF:: +getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding) const { + + if (Encoding & dwarf::DW_EH_PE_indirect) { + MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo(); + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += ".DW.stub"; + + // Add information about the stub reference to ELFMMI so that the stub + // gets emitted by the asmprinter. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); + MCSymbol *&StubSym = ELFMMI.getGVStubEntry(Sym); + if (StubSym == 0) { + Name.clear(); + Mang->getNameWithPrefix(Name, GV, false); + StubSym = getContext().GetOrCreateSymbol(Name.str()); + } + + return TargetLoweringObjectFile:: + getSymbolForDwarfReference(Sym, MMI, + Encoding & ~dwarf::DW_EH_PE_indirect); + } + + return TargetLoweringObjectFile:: + getSymbolForDwarfGlobalReference(GV, Mang, MMI, Encoding); +} + +//===----------------------------------------------------------------------===// +// MachO +//===----------------------------------------------------------------------===// + +typedef StringMap MachOUniqueMapTy; + +TargetLoweringObjectFileMachO::~TargetLoweringObjectFileMachO() { + // If we have the MachO uniquing map, free it. + delete (MachOUniqueMapTy*)UniquingMap; +} + + +const MCSectionMachO *TargetLoweringObjectFileMachO:: +getMachOSection(StringRef Segment, StringRef Section, + unsigned TypeAndAttributes, + unsigned Reserved2, SectionKind Kind) const { + // We unique sections by their segment/section pair. The returned section + // may not have the same flags as the requested section, if so this should be + // diagnosed by the client as an error. + + // Create the map if it doesn't already exist. + if (UniquingMap == 0) + UniquingMap = new MachOUniqueMapTy(); + MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)UniquingMap; + + // Form the name to look up. + SmallString<64> Name; + Name += Segment; + Name.push_back(','); + Name += Section; + + // Do the lookup, if we have a hit, return it. + const MCSectionMachO *&Entry = Map[Name.str()]; + if (Entry) return Entry; + + // Otherwise, return a new section. + return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes, + Reserved2, Kind, getContext()); +} + + +void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((MachOUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + + TextSection // .text + = getMachOSection("__TEXT", "__text", + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + DataSection // .data + = getMachOSection("__DATA", "__data", 0, SectionKind::getDataRel()); + + CStringSection // .cstring + = getMachOSection("__TEXT", "__cstring", MCSectionMachO::S_CSTRING_LITERALS, + SectionKind::getMergeable1ByteCString()); + UStringSection + = getMachOSection("__TEXT","__ustring", 0, + SectionKind::getMergeable2ByteCString()); + FourByteConstantSection // .literal4 + = getMachOSection("__TEXT", "__literal4", MCSectionMachO::S_4BYTE_LITERALS, + SectionKind::getMergeableConst4()); + EightByteConstantSection // .literal8 + = getMachOSection("__TEXT", "__literal8", MCSectionMachO::S_8BYTE_LITERALS, + SectionKind::getMergeableConst8()); + + // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back + // to using it in -static mode. + SixteenByteConstantSection = 0; + if (TM.getRelocationModel() != Reloc::Static && + TM.getTargetData()->getPointerSize() == 32) + SixteenByteConstantSection = // .literal16 + getMachOSection("__TEXT", "__literal16",MCSectionMachO::S_16BYTE_LITERALS, + SectionKind::getMergeableConst16()); + + ReadOnlySection // .const + = getMachOSection("__TEXT", "__const", 0, SectionKind::getReadOnly()); + + TextCoalSection + = getMachOSection("__TEXT", "__textcoal_nt", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, + SectionKind::getText()); + ConstTextCoalSection + = getMachOSection("__TEXT", "__const_coal", MCSectionMachO::S_COALESCED, + SectionKind::getText()); + ConstDataCoalSection + = getMachOSection("__DATA","__const_coal", MCSectionMachO::S_COALESCED, + SectionKind::getText()); + ConstDataSection // .const_data + = getMachOSection("__DATA", "__const", 0, + SectionKind::getReadOnlyWithRel()); + DataCoalSection + = getMachOSection("__DATA","__datacoal_nt", MCSectionMachO::S_COALESCED, + SectionKind::getDataRel()); + DataCommonSection + = getMachOSection("__DATA","__common", MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + DataBSSSection + = getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL, + SectionKind::getBSS()); + + + LazySymbolPointerSection + = getMachOSection("__DATA", "__la_symbol_ptr", + MCSectionMachO::S_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + NonLazySymbolPointerSection + = getMachOSection("__DATA", "__nl_symbol_ptr", + MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, + SectionKind::getMetadata()); + + if (TM.getRelocationModel() == Reloc::Static) { + StaticCtorSection + = getMachOSection("__TEXT", "__constructor", 0,SectionKind::getDataRel()); + StaticDtorSection + = getMachOSection("__TEXT", "__destructor", 0, SectionKind::getDataRel()); + } else { + StaticCtorSection + = getMachOSection("__DATA", "__mod_init_func", + MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, + SectionKind::getDataRel()); + StaticDtorSection + = getMachOSection("__DATA", "__mod_term_func", + MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, + SectionKind::getDataRel()); + } + + // Exception Handling. + LSDASection = getMachOSection("__DATA", "__gcc_except_tab", 0, + SectionKind::getDataRel()); + EHFrameSection = + getMachOSection("__TEXT", "__eh_frame", + MCSectionMachO::S_COALESCED | + MCSectionMachO::S_ATTR_NO_TOC | + MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | + MCSectionMachO::S_ATTR_LIVE_SUPPORT, + SectionKind::getReadOnly()); + + // Debug Information. + DwarfAbbrevSection = + getMachOSection("__DWARF", "__debug_abbrev", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfInfoSection = + getMachOSection("__DWARF", "__debug_info", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLineSection = + getMachOSection("__DWARF", "__debug_line", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfFrameSection = + getMachOSection("__DWARF", "__debug_frame", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubNamesSection = + getMachOSection("__DWARF", "__debug_pubnames", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfPubTypesSection = + getMachOSection("__DWARF", "__debug_pubtypes", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfStrSection = + getMachOSection("__DWARF", "__debug_str", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfLocSection = + getMachOSection("__DWARF", "__debug_loc", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfARangesSection = + getMachOSection("__DWARF", "__debug_aranges", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfRangesSection = + getMachOSection("__DWARF", "__debug_ranges", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfMacroInfoSection = + getMachOSection("__DWARF", "__debug_macinfo", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); + DwarfDebugInlineSection = + getMachOSection("__DWARF", "__debug_inlined", MCSectionMachO::S_ATTR_DEBUG, + SectionKind::getMetadata()); +} + +const MCSection *TargetLoweringObjectFileMachO:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + // Parse the section specifier and create it if valid. + StringRef Segment, Section; + unsigned TAA, StubSize; + std::string ErrorCode = + MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section, + TAA, StubSize); + if (!ErrorCode.empty()) { + // If invalid, report the error with llvm_report_error. + llvm_report_error("Global variable '" + GV->getNameStr() + + "' has an invalid section specifier '" + GV->getSection()+ + "': " + ErrorCode + "."); + // Fall back to dropping it into the data section. + return DataSection; + } + + // Get the section. + const MCSectionMachO *S = + getMachOSection(Segment, Section, TAA, StubSize, Kind); + + // Okay, now that we got the section, verify that the TAA & StubSize agree. + // If the user declared multiple globals with different section flags, we need + // to reject it here. + if (S->getTypeAndAttributes() != TAA || S->getStubSize() != StubSize) { + // If invalid, report the error with llvm_report_error. + llvm_report_error("Global variable '" + GV->getNameStr() + + "' section type or attributes does not match previous" + " section specifier"); + } + + return S; +} + +const MCSection *TargetLoweringObjectFileMachO:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); + + if (Kind.isText()) + return GV->isWeakForLinker() ? TextCoalSection : TextSection; + + // If this is weak/linkonce, put this in a coalescable section, either in text + // or data depending on if it is writable. + if (GV->isWeakForLinker()) { + if (Kind.isReadOnly()) + return ConstTextCoalSection; + return DataCoalSection; + } + + // FIXME: Alignment check should be handled by section classifier. + if (Kind.isMergeable1ByteCString() && + TM.getTargetData()->getPreferredAlignment(cast(GV)) < 32) + return CStringSection; + + // Do not put 16-bit arrays in the UString section if they have an + // externally visible label, this runs into issues with certain linker + // versions. + if (Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage() && + TM.getTargetData()->getPreferredAlignment(cast(GV)) < 32) + return UStringSection; + + if (Kind.isMergeableConst()) { + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16() && SixteenByteConstantSection) + return SixteenByteConstantSection; + } + + // Otherwise, if it is readonly, but not something we can specially optimize, + // just drop it in .const. + if (Kind.isReadOnly()) + return ReadOnlySection; + + // If this is marked const, put it into a const section. But if the dynamic + // linker needs to write to it, put it in the data segment. + if (Kind.isReadOnlyWithRel()) + return ConstDataSection; + + // Put zero initialized globals with strong external linkage in the + // DATA, __common section with the .zerofill directive. + if (Kind.isBSSExtern()) + return DataCommonSection; + + // Put zero initialized globals with local linkage in __DATA,__bss directive + // with the .zerofill directive (aka .lcomm). + if (Kind.isBSSLocal()) + return DataBSSSection; + + // Otherwise, just drop the variable in the normal data section. + return DataSection; +} + +const MCSection * +TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind) const { + // If this constant requires a relocation, we have to put it in the data + // segment, not in the text segment. + if (Kind.isDataRel() || Kind.isReadOnlyWithRel()) + return ConstDataSection; + + if (Kind.isMergeableConst4()) + return FourByteConstantSection; + if (Kind.isMergeableConst8()) + return EightByteConstantSection; + if (Kind.isMergeableConst16() && SixteenByteConstantSection) + return SixteenByteConstantSection; + return ReadOnlySection; // .const +} + +/// shouldEmitUsedDirectiveFor - This hook allows targets to selectively decide +/// not to emit the UsedDirective for some symbols in llvm.used. +// FIXME: REMOVE this (rdar://7071300) +bool TargetLoweringObjectFileMachO:: +shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const { + /// On Darwin, internally linked data beginning with "L" or "l" does not have + /// the directive emitted (this occurs in ObjC metadata). + if (!GV) return false; + + // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix. + if (GV->hasLocalLinkage() && !isa(GV)) { + // FIXME: ObjC metadata is currently emitted as internal symbols that have + // \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and + // this horrible hack can go away. + SmallString<64> Name; + Mang->getNameWithPrefix(Name, GV, false); + if (Name[0] == 'L' || Name[0] == 'l') + return false; + } + + return true; +} + +const MCExpr *TargetLoweringObjectFileMachO:: +getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, + MachineModuleInfo *MMI, unsigned Encoding) const { + // The mach-o version of this method defaults to returning a stub reference. + + if (Encoding & DW_EH_PE_indirect) { + MachineModuleInfoMachO &MachOMMI = + MMI->getObjFileInfo(); + + SmallString<128> Name; + Mang->getNameWithPrefix(Name, GV, true); + Name += "$non_lazy_ptr"; + + // Add information about the stub reference to MachOMMI so that the stub + // gets emitted by the asmprinter. + MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); + MCSymbol *&StubSym = MachOMMI.getGVStubEntry(Sym); + if (StubSym == 0) { + Name.clear(); + Mang->getNameWithPrefix(Name, GV, false); + StubSym = getContext().GetOrCreateSymbol(Name.str()); + } + + return TargetLoweringObjectFile:: + getSymbolForDwarfReference(Sym, MMI, + Encoding & ~dwarf::DW_EH_PE_indirect); + } + + return TargetLoweringObjectFile:: + getSymbolForDwarfGlobalReference(GV, Mang, MMI, Encoding); +} + +unsigned TargetLoweringObjectFileMachO::getPersonalityEncoding() const { + return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; +} + +unsigned TargetLoweringObjectFileMachO::getLSDAEncoding() const { + return DW_EH_PE_pcrel; +} + +unsigned TargetLoweringObjectFileMachO::getFDEEncoding() const { + return DW_EH_PE_pcrel; +} + +unsigned TargetLoweringObjectFileMachO::getTTypeEncoding() const { + return DW_EH_PE_absptr; +} + +//===----------------------------------------------------------------------===// +// COFF +//===----------------------------------------------------------------------===// + +typedef StringMap COFFUniqueMapTy; + +TargetLoweringObjectFileCOFF::~TargetLoweringObjectFileCOFF() { + delete (COFFUniqueMapTy*)UniquingMap; +} + + +const MCSection *TargetLoweringObjectFileCOFF:: +getCOFFSection(StringRef Name, bool isDirective, SectionKind Kind) const { + // Create the map if it doesn't already exist. + if (UniquingMap == 0) + UniquingMap = new MachOUniqueMapTy(); + COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)UniquingMap; + + // Do the lookup, if we have a hit, return it. + const MCSectionCOFF *&Entry = Map[Name]; + if (Entry) return Entry; + + return Entry = MCSectionCOFF::Create(Name, isDirective, Kind, getContext()); +} + +void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx, + const TargetMachine &TM) { + if (UniquingMap != 0) + ((COFFUniqueMapTy*)UniquingMap)->clear(); + TargetLoweringObjectFile::Initialize(Ctx, TM); + TextSection = getCOFFSection("\t.text", true, SectionKind::getText()); + DataSection = getCOFFSection("\t.data", true, SectionKind::getDataRel()); + StaticCtorSection = + getCOFFSection(".ctors", false, SectionKind::getDataRel()); + StaticDtorSection = + getCOFFSection(".dtors", false, SectionKind::getDataRel()); + + // FIXME: We're emitting LSDA info into a readonly section on COFF, even + // though it contains relocatable pointers. In PIC mode, this is probably a + // big runtime hit for C++ apps. Either the contents of the LSDA need to be + // adjusted or this should be a data section. + LSDASection = + getCOFFSection(".gcc_except_table", false, SectionKind::getReadOnly()); + EHFrameSection = + getCOFFSection(".eh_frame", false, SectionKind::getDataRel()); + + // Debug info. + // FIXME: Don't use 'directive' mode here. + DwarfAbbrevSection = + getCOFFSection("\t.section\t.debug_abbrev,\"dr\"", + true, SectionKind::getMetadata()); + DwarfInfoSection = + getCOFFSection("\t.section\t.debug_info,\"dr\"", + true, SectionKind::getMetadata()); + DwarfLineSection = + getCOFFSection("\t.section\t.debug_line,\"dr\"", + true, SectionKind::getMetadata()); + DwarfFrameSection = + getCOFFSection("\t.section\t.debug_frame,\"dr\"", + true, SectionKind::getMetadata()); + DwarfPubNamesSection = + getCOFFSection("\t.section\t.debug_pubnames,\"dr\"", + true, SectionKind::getMetadata()); + DwarfPubTypesSection = + getCOFFSection("\t.section\t.debug_pubtypes,\"dr\"", + true, SectionKind::getMetadata()); + DwarfStrSection = + getCOFFSection("\t.section\t.debug_str,\"dr\"", + true, SectionKind::getMetadata()); + DwarfLocSection = + getCOFFSection("\t.section\t.debug_loc,\"dr\"", + true, SectionKind::getMetadata()); + DwarfARangesSection = + getCOFFSection("\t.section\t.debug_aranges,\"dr\"", + true, SectionKind::getMetadata()); + DwarfRangesSection = + getCOFFSection("\t.section\t.debug_ranges,\"dr\"", + true, SectionKind::getMetadata()); + DwarfMacroInfoSection = + getCOFFSection("\t.section\t.debug_macinfo,\"dr\"", + true, SectionKind::getMetadata()); +} + +const MCSection *TargetLoweringObjectFileCOFF:: +getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + return getCOFFSection(GV->getSection(), false, Kind); +} + +static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { + if (Kind.isText()) + return ".text$linkonce"; + if (Kind.isWriteable()) + return ".data$linkonce"; + return ".rdata$linkonce"; +} + + +const MCSection *TargetLoweringObjectFileCOFF:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + assert(!Kind.isThreadLocal() && "Doesn't support TLS"); + + // If this global is linkonce/weak and the target handles this by emitting it + // into a 'uniqued' section name, create and return the section now. + if (GV->isWeakForLinker()) { + const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind); + SmallString<128> Name(Prefix, Prefix+strlen(Prefix)); + Mang->getNameWithPrefix(Name, GV, false); + return getCOFFSection(Name.str(), false, Kind); + } + + if (Kind.isText()) + return getTextSection(); + + return getDataSection(); +} + diff --git a/lib/CodeGen/TwoAddressInstructionPass.cpp b/lib/CodeGen/TwoAddressInstructionPass.cpp index 6c7c1a1305..c840b3968c 100644 --- a/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -160,7 +160,7 @@ bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, MachineBasicBlock::iterator OldPos) { // Check if it's safe to move this instruction. bool SeenStore = true; // Be conservative. - if (!MI->isSafeToMove(TII, SeenStore, AA)) + if (!MI->isSafeToMove(TII, AA, SeenStore)) return false; unsigned DefReg = 0; @@ -213,6 +213,9 @@ bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB, unsigned NumVisited = 0; for (MachineBasicBlock::iterator I = llvm::next(OldPos); I != KillPos; ++I) { MachineInstr *OtherMI = I; + // DBG_VALUE cannot be counted against the limit. + if (OtherMI->isDebugValue()) + continue; if (NumVisited > 30) // FIXME: Arbitrary limit to reduce compile time cost. return false; ++NumVisited; @@ -451,13 +454,10 @@ MachineInstr *findOnlyInterestingUse(unsigned Reg, MachineBasicBlock *MBB, const TargetInstrInfo *TII, bool &IsCopy, unsigned &DstReg, bool &IsDstPhys) { - MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg); - if (UI == MRI->use_end()) - return 0; - MachineInstr &UseMI = *UI; - if (++UI != MRI->use_end()) - // More than one use. + if (!MRI->hasOneNonDBGUse(Reg)) + // None or more than one use. return 0; + MachineInstr &UseMI = *MRI->use_nodbg_begin(Reg); if (UseMI.getParent() != MBB) return 0; unsigned SrcReg; @@ -923,6 +923,10 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { for (MachineBasicBlock::iterator mi = mbbi->begin(), me = mbbi->end(); mi != me; ) { MachineBasicBlock::iterator nmi = llvm::next(mi); + if (mi->isDebugValue()) { + mi = nmi; + continue; + } const TargetInstrDesc &TID = mi->getDesc(); bool FirstTied = true; @@ -1021,7 +1025,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &MF) { // copying it. if (DefMI && DefMI->getDesc().isAsCheapAsAMove() && - DefMI->isSafeToReMat(TII, regB, AA) && + DefMI->isSafeToReMat(TII, AA, regB) && isProfitableToReMat(regB, rc, mi, DefMI, mbbi, Dist)){ DEBUG(dbgs() << "2addr: REMATTING : " << *DefMI << "\n"); unsigned regASubIdx = mi->getOperand(DstIdx).getSubReg(); diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index 5956b6141c..ed0269695d 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -261,19 +261,21 @@ bool VirtRegMap::FindUnusedRegisters(LiveIntervals* LIs) { void VirtRegMap::print(raw_ostream &OS, const Module* M) const { const TargetRegisterInfo* TRI = MF->getTarget().getRegisterInfo(); + const MachineRegisterInfo &MRI = MF->getRegInfo(); OS << "********** REGISTER MAP **********\n"; for (unsigned i = TargetRegisterInfo::FirstVirtualRegister, e = MF->getRegInfo().getLastVirtReg(); i <= e; ++i) { if (Virt2PhysMap[i] != (unsigned)VirtRegMap::NO_PHYS_REG) OS << "[reg" << i << " -> " << TRI->getName(Virt2PhysMap[i]) - << "]\n"; + << "] " << MRI.getRegClass(i)->getName() << "\n"; } for (unsigned i = TargetRegisterInfo::FirstVirtualRegister, e = MF->getRegInfo().getLastVirtReg(); i <= e; ++i) if (Virt2StackSlotMap[i] != VirtRegMap::NO_STACK_SLOT) - OS << "[reg" << i << " -> fi#" << Virt2StackSlotMap[i] << "]\n"; + OS << "[reg" << i << " -> fi#" << Virt2StackSlotMap[i] + << "] " << MRI.getRegClass(i)->getName() << "\n"; OS << '\n'; } diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp index ce62594842..7aa0a91535 100644 --- a/lib/CodeGen/VirtRegRewriter.cpp +++ b/lib/CodeGen/VirtRegRewriter.cpp @@ -46,7 +46,7 @@ namespace { static cl::opt RewriterOpt("rewriter", - cl::desc("Rewriter to use: (default: local)"), + cl::desc("Rewriter to use (default=local)"), cl::Prefix, cl::values(clEnumVal(local, "local rewriter"), clEnumVal(trivial, "trivial rewriter"), @@ -62,6 +62,7 @@ VirtRegRewriter::~VirtRegRewriter() {} /// substitutePhysReg - Replace virtual register in MachineOperand with a /// physical register. Do the right thing with the sub-register index. +/// Note that operands may be added, so the MO reference is no longer valid. static void substitutePhysReg(MachineOperand &MO, unsigned Reg, const TargetRegisterInfo &TRI) { if (unsigned SubIdx = MO.getSubReg()) { @@ -123,14 +124,15 @@ struct TrivialRewriter : public VirtRegRewriter { continue; unsigned pReg = VRM.getPhys(reg); mri->setPhysRegUsed(pReg); - for (MachineRegisterInfo::reg_iterator regItr = mri->reg_begin(reg), - regEnd = mri->reg_end(); regItr != regEnd;) { - MachineOperand &mop = regItr.getOperand(); - assert(mop.isReg() && mop.getReg() == reg && "reg_iterator broken?"); - ++regItr; - substitutePhysReg(mop, pReg, *tri); - changed = true; - } + // Copy the register use-list before traversing it. + SmallVector, 32> reglist; + for (MachineRegisterInfo::reg_iterator I = mri->reg_begin(reg), + E = mri->reg_end(); I != E; ++I) + reglist.push_back(std::make_pair(&*I, I.getOperandNo())); + for (unsigned N=0; N != reglist.size(); ++N) + substitutePhysReg(reglist[N].first->getOperand(reglist[N].second), + pReg, *tri); + changed |= !reglist.empty(); } } @@ -1850,19 +1852,18 @@ private: KilledMIRegs.clear(); for (unsigned j = 0, e = VirtUseOps.size(); j != e; ++j) { unsigned i = VirtUseOps[j]; - MachineOperand &MO = MI.getOperand(i); - unsigned VirtReg = MO.getReg(); + unsigned VirtReg = MI.getOperand(i).getReg(); assert(TargetRegisterInfo::isVirtualRegister(VirtReg) && "Not a virtual register?"); - unsigned SubIdx = MO.getSubReg(); + unsigned SubIdx = MI.getOperand(i).getSubReg(); if (VRM.isAssignedReg(VirtReg)) { // This virtual register was assigned a physreg! unsigned Phys = VRM.getPhys(VirtReg); RegInfo->setPhysRegUsed(Phys); - if (MO.isDef()) + if (MI.getOperand(i).isDef()) ReusedOperands.markClobbered(Phys); - substitutePhysReg(MO, Phys, *TRI); + substitutePhysReg(MI.getOperand(i), Phys, *TRI); if (VRM.isImplicitlyDefined(VirtReg)) // FIXME: Is this needed? BuildMI(MBB, &MI, MI.getDebugLoc(), @@ -1871,10 +1872,10 @@ private: } // This virtual register is now known to be a spilled value. - if (!MO.isUse()) + if (!MI.getOperand(i).isUse()) continue; // Handle defs in the loop below (handle use&def here though) - bool AvoidReload = MO.isUndef(); + bool AvoidReload = MI.getOperand(i).isUndef(); // Check if it is defined by an implicit def. It should not be spilled. // Note, this is for correctness reason. e.g. // 8 %reg1024 = IMPLICIT_DEF diff --git a/lib/CompilerDriver/Action.cpp b/lib/CompilerDriver/Action.cpp index 7bcd30a8e0..9d07811c89 100644 --- a/lib/CompilerDriver/Action.cpp +++ b/lib/CompilerDriver/Action.cpp @@ -15,6 +15,7 @@ #include "llvm/CompilerDriver/BuiltinOptions.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/SystemUtils.h" #include "llvm/System/Program.h" #include "llvm/System/TimeValue.h" @@ -24,13 +25,23 @@ using namespace llvm; using namespace llvmc; +namespace llvmc { + +extern int Main(int argc, char** argv); +extern const char* ProgramName; + +} + namespace { int ExecuteProgram(const std::string& name, const StrVector& args) { sys::Path prog = sys::Program::FindProgramByName(name); - if (prog.isEmpty()) - throw std::runtime_error("Can't find program '" + name + "'"); + if (prog.isEmpty()) { + prog = FindExecutable(name, ProgramName, (void *)(intptr_t)&Main); + if (prog.isEmpty()) + throw std::runtime_error("Can't find program '" + name + "'"); + } if (!prog.canExecute()) throw std::runtime_error("Program '" + name + "' is not executable."); diff --git a/lib/CompilerDriver/CompilationGraph.cpp b/lib/CompilerDriver/CompilationGraph.cpp index 524607bee7..7d1c7fe4a6 100644 --- a/lib/CompilerDriver/CompilationGraph.cpp +++ b/lib/CompilerDriver/CompilationGraph.cpp @@ -34,7 +34,8 @@ namespace llvmc { const std::string& LanguageMap::GetLanguage(const sys::Path& File) const { StringRef suf = File.getSuffix(); - LanguageMap::const_iterator Lang = this->find(suf); + LanguageMap::const_iterator Lang = + this->find(suf.empty() ? "*empty*" : suf); if (Lang == this->end()) throw std::runtime_error("File '" + File.str() + "' has unknown suffix '" + suf.str() + '\''); @@ -313,7 +314,7 @@ int CompilationGraph::Build (const sys::Path& TempDir, JoinTool* JT = &dynamic_cast(*CurNode->ToolPtr.getPtr()); // Are there any files in the join list? - if (JT->JoinListEmpty()) + if (JT->JoinListEmpty() && !(JT->WorksOnEmpty() && InputFilenames.empty())) continue; Action CurAction = JT->GenerateAction(CurNode->HasChildren(), diff --git a/lib/CompilerDriver/Main.cpp b/lib/CompilerDriver/Main.cpp index 3a3487a0a9..b5e507dfc3 100644 --- a/lib/CompilerDriver/Main.cpp +++ b/lib/CompilerDriver/Main.cpp @@ -100,7 +100,8 @@ int Main(int argc, char** argv) { ProgramName = argv[0]; cl::ParseCommandLineOptions - (argc, argv, "LLVM Compiler Driver (Work In Progress)", true); + (argc, argv, "LLVM Compiler Driver (Work In Progress)", + /* ReadResponseFiles = */ false); PluginLoader Plugins; Plugins.RunInitialization(langMap, graph); @@ -126,10 +127,6 @@ int Main(int argc, char** argv) { return 0; } - if (InputFilenames.empty()) { - throw std::runtime_error("no input files"); - } - if (Time) { GlobalTimeLog = new std::stringstream; GlobalTimeLog->precision(2); diff --git a/lib/CompilerDriver/Tool.cpp b/lib/CompilerDriver/Tool.cpp index 9f4ab49566..5e558ca43c 100644 --- a/lib/CompilerDriver/Tool.cpp +++ b/lib/CompilerDriver/Tool.cpp @@ -17,6 +17,8 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/System/Path.h" +#include + using namespace llvm; using namespace llvmc; @@ -71,3 +73,22 @@ sys::Path Tool::OutFilename(const sys::Path& In, } return Out; } + +namespace { + template + bool CompareFirst (std::pair p1, std::pair p2) { + return std::less()(p1.first, p2.first); + } +} + +StrVector Tool::SortArgs(ArgsVector& Args) const { + StrVector Out; + + // HACK: this won't be needed when we'll migrate away from CommandLine. + std::stable_sort(Args.begin(), Args.end(), &CompareFirst); + for (ArgsVector::iterator B = Args.begin(), E = Args.end(); B != E; ++B) { + Out.push_back(B->second); + } + + return Out; +} diff --git a/lib/ExecutionEngine/ExecutionEngine.cpp b/lib/ExecutionEngine/ExecutionEngine.cpp index 3e684e116d..b2e2a04084 100644 --- a/lib/ExecutionEngine/ExecutionEngine.cpp +++ b/lib/ExecutionEngine/ExecutionEngine.cpp @@ -339,12 +339,12 @@ int ExecutionEngine::runFunctionAsMain(Function *Fn, } // FALLS THROUGH case 1: - if (!FTy->getParamType(0)->isInteger(32)) { + if (!FTy->getParamType(0)->isIntegerTy(32)) { llvm_report_error("Invalid type for first argument of main() supplied"); } // FALLS THROUGH case 0: - if (!isa(FTy->getReturnType()) && + if (!FTy->getReturnType()->isIntegerTy() && !FTy->getReturnType()->isVoidTy()) { llvm_report_error("Invalid return type of main() supplied"); } @@ -599,22 +599,22 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) { switch (Op0->getType()->getTypeID()) { default: llvm_unreachable("Invalid bitcast operand"); case Type::IntegerTyID: - assert(DestTy->isFloatingPoint() && "invalid bitcast"); + assert(DestTy->isFloatingPointTy() && "invalid bitcast"); if (DestTy->isFloatTy()) GV.FloatVal = GV.IntVal.bitsToFloat(); else if (DestTy->isDoubleTy()) GV.DoubleVal = GV.IntVal.bitsToDouble(); break; case Type::FloatTyID: - assert(DestTy->isInteger(32) && "Invalid bitcast"); + assert(DestTy->isIntegerTy(32) && "Invalid bitcast"); GV.IntVal.floatToBits(GV.FloatVal); break; case Type::DoubleTyID: - assert(DestTy->isInteger(64) && "Invalid bitcast"); + assert(DestTy->isIntegerTy(64) && "Invalid bitcast"); GV.IntVal.doubleToBits(GV.DoubleVal); break; case Type::PointerTyID: - assert(isa(DestTy) && "Invalid bitcast"); + assert(DestTy->isPointerTy() && "Invalid bitcast"); break; // getConstantValue(Op0) above already converted it } return GV; diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp index 141cb27a33..c7495d442d 100644 --- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp +++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp @@ -87,11 +87,11 @@ void LLVMDisposeGenericValue(LLVMGenericValueRef GenVal) { /*===-- Operations on execution engines -----------------------------------===*/ -LLVMBool LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, - LLVMModuleProviderRef MP, - char **OutError) { +LLVMBool LLVMCreateExecutionEngineForModule(LLVMExecutionEngineRef *OutEE, + LLVMModuleRef M, + char **OutError) { std::string Error; - EngineBuilder builder(unwrap(MP)); + EngineBuilder builder(unwrap(M)); builder.setEngineKind(EngineKind::Either) .setErrorStr(&Error); if (ExecutionEngine *EE = builder.create()){ @@ -102,11 +102,11 @@ LLVMBool LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, return 1; } -LLVMBool LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, - LLVMModuleProviderRef MP, - char **OutError) { +LLVMBool LLVMCreateInterpreterForModule(LLVMExecutionEngineRef *OutInterp, + LLVMModuleRef M, + char **OutError) { std::string Error; - EngineBuilder builder(unwrap(MP)); + EngineBuilder builder(unwrap(M)); builder.setEngineKind(EngineKind::Interpreter) .setErrorStr(&Error); if (ExecutionEngine *Interp = builder.create()) { @@ -117,12 +117,12 @@ LLVMBool LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, return 1; } -LLVMBool LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, - LLVMModuleProviderRef MP, - unsigned OptLevel, - char **OutError) { +LLVMBool LLVMCreateJITCompilerForModule(LLVMExecutionEngineRef *OutJIT, + LLVMModuleRef M, + unsigned OptLevel, + char **OutError) { std::string Error; - EngineBuilder builder(unwrap(MP)); + EngineBuilder builder(unwrap(M)); builder.setEngineKind(EngineKind::JIT) .setErrorStr(&Error) .setOptLevel((CodeGenOpt::Level)OptLevel); @@ -134,6 +134,35 @@ LLVMBool LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, return 1; } +LLVMBool LLVMCreateExecutionEngine(LLVMExecutionEngineRef *OutEE, + LLVMModuleProviderRef MP, + char **OutError) { + /* The module provider is now actually a module. */ + return LLVMCreateExecutionEngineForModule(OutEE, + reinterpret_cast(MP), + OutError); +} + +LLVMBool LLVMCreateInterpreter(LLVMExecutionEngineRef *OutInterp, + LLVMModuleProviderRef MP, + char **OutError) { + /* The module provider is now actually a module. */ + return LLVMCreateInterpreterForModule(OutInterp, + reinterpret_cast(MP), + OutError); +} + +LLVMBool LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT, + LLVMModuleProviderRef MP, + unsigned OptLevel, + char **OutError) { + /* The module provider is now actually a module. */ + return LLVMCreateJITCompilerForModule(OutJIT, + reinterpret_cast(MP), + OptLevel, OutError); +} + + void LLVMDisposeExecutionEngine(LLVMExecutionEngineRef EE) { delete unwrap(EE); } @@ -173,17 +202,29 @@ void LLVMFreeMachineCodeForFunction(LLVMExecutionEngineRef EE, LLVMValueRef F) { unwrap(EE)->freeMachineCodeForFunction(unwrap(F)); } +void LLVMAddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M){ + unwrap(EE)->addModule(unwrap(M)); +} + void LLVMAddModuleProvider(LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP){ - unwrap(EE)->addModule(unwrap(MP)); + /* The module provider is now actually a module. */ + LLVMAddModule(EE, reinterpret_cast(MP)); +} + +LLVMBool LLVMRemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, + LLVMModuleRef *OutMod, char **OutError) { + Module *Mod = unwrap(M); + unwrap(EE)->removeModule(Mod); + *OutMod = wrap(Mod); + return 0; } LLVMBool LLVMRemoveModuleProvider(LLVMExecutionEngineRef EE, LLVMModuleProviderRef MP, LLVMModuleRef *OutMod, char **OutError) { - Module *M = unwrap(MP); - unwrap(EE)->removeModule(M); - *OutMod = wrap(M); - return 0; + /* The module provider is now actually a module. */ + return LLVMRemoveModule(EE, reinterpret_cast(MP), OutMod, + OutError); } LLVMBool LLVMFindFunction(LLVMExecutionEngineRef EE, const char *Name, diff --git a/lib/ExecutionEngine/Interpreter/Execution.cpp b/lib/ExecutionEngine/Interpreter/Execution.cpp index 73f5558886..a2aad5ac55 100644 --- a/lib/ExecutionEngine/Interpreter/Execution.cpp +++ b/lib/ExecutionEngine/Interpreter/Execution.cpp @@ -591,7 +591,7 @@ void Interpreter::popStackAndReturnValueToCaller(const Type *RetTy, ECStack.pop_back(); if (ECStack.empty()) { // Finished main. Put result into exit code... - if (RetTy && RetTy->isInteger()) { // Nonvoid return type? + if (RetTy && RetTy->isIntegerTy()) { // Nonvoid return type? ExitValue = Result; // Capture the exit value of the program } else { memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped)); @@ -761,7 +761,7 @@ void Interpreter::visitAllocaInst(AllocaInst &I) { GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I, gep_type_iterator E, ExecutionContext &SF) { - assert(isa(Ptr->getType()) && + assert(Ptr->getType()->isPointerTy() && "Cannot getElementOffset of a nonpointer type!"); uint64_t Total = 0; @@ -979,7 +979,7 @@ GenericValue Interpreter::executeFPToUIInst(Value *SrcVal, const Type *DstTy, const Type *SrcTy = SrcVal->getType(); uint32_t DBitWidth = cast(DstTy)->getBitWidth(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(SrcTy->isFloatingPoint() && "Invalid FPToUI instruction"); + assert(SrcTy->isFloatingPointTy() && "Invalid FPToUI instruction"); if (SrcTy->getTypeID() == Type::FloatTyID) Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); @@ -993,7 +993,7 @@ GenericValue Interpreter::executeFPToSIInst(Value *SrcVal, const Type *DstTy, const Type *SrcTy = SrcVal->getType(); uint32_t DBitWidth = cast(DstTy)->getBitWidth(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(SrcTy->isFloatingPoint() && "Invalid FPToSI instruction"); + assert(SrcTy->isFloatingPointTy() && "Invalid FPToSI instruction"); if (SrcTy->getTypeID() == Type::FloatTyID) Dest.IntVal = APIntOps::RoundFloatToAPInt(Src.FloatVal, DBitWidth); @@ -1005,7 +1005,7 @@ GenericValue Interpreter::executeFPToSIInst(Value *SrcVal, const Type *DstTy, GenericValue Interpreter::executeUIToFPInst(Value *SrcVal, const Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(DstTy->isFloatingPoint() && "Invalid UIToFP instruction"); + assert(DstTy->isFloatingPointTy() && "Invalid UIToFP instruction"); if (DstTy->getTypeID() == Type::FloatTyID) Dest.FloatVal = APIntOps::RoundAPIntToFloat(Src.IntVal); @@ -1017,7 +1017,7 @@ GenericValue Interpreter::executeUIToFPInst(Value *SrcVal, const Type *DstTy, GenericValue Interpreter::executeSIToFPInst(Value *SrcVal, const Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(DstTy->isFloatingPoint() && "Invalid SIToFP instruction"); + assert(DstTy->isFloatingPointTy() && "Invalid SIToFP instruction"); if (DstTy->getTypeID() == Type::FloatTyID) Dest.FloatVal = APIntOps::RoundSignedAPIntToFloat(Src.IntVal); @@ -1031,7 +1031,7 @@ GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, const Type *DstTy, ExecutionContext &SF) { uint32_t DBitWidth = cast(DstTy)->getBitWidth(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(isa(SrcVal->getType()) && "Invalid PtrToInt instruction"); + assert(SrcVal->getType()->isPointerTy() && "Invalid PtrToInt instruction"); Dest.IntVal = APInt(DBitWidth, (intptr_t) Src.PointerVal); return Dest; @@ -1040,7 +1040,7 @@ GenericValue Interpreter::executePtrToIntInst(Value *SrcVal, const Type *DstTy, GenericValue Interpreter::executeIntToPtrInst(Value *SrcVal, const Type *DstTy, ExecutionContext &SF) { GenericValue Dest, Src = getOperandValue(SrcVal, SF); - assert(isa(DstTy) && "Invalid PtrToInt instruction"); + assert(DstTy->isPointerTy() && "Invalid PtrToInt instruction"); uint32_t PtrSize = TD.getPointerSizeInBits(); if (PtrSize != Src.IntVal.getBitWidth()) @@ -1055,27 +1055,27 @@ GenericValue Interpreter::executeBitCastInst(Value *SrcVal, const Type *DstTy, const Type *SrcTy = SrcVal->getType(); GenericValue Dest, Src = getOperandValue(SrcVal, SF); - if (isa(DstTy)) { - assert(isa(SrcTy) && "Invalid BitCast"); + if (DstTy->isPointerTy()) { + assert(SrcTy->isPointerTy() && "Invalid BitCast"); Dest.PointerVal = Src.PointerVal; - } else if (DstTy->isInteger()) { + } else if (DstTy->isIntegerTy()) { if (SrcTy->isFloatTy()) { Dest.IntVal.zext(sizeof(Src.FloatVal) * CHAR_BIT); Dest.IntVal.floatToBits(Src.FloatVal); } else if (SrcTy->isDoubleTy()) { Dest.IntVal.zext(sizeof(Src.DoubleVal) * CHAR_BIT); Dest.IntVal.doubleToBits(Src.DoubleVal); - } else if (SrcTy->isInteger()) { + } else if (SrcTy->isIntegerTy()) { Dest.IntVal = Src.IntVal; } else llvm_unreachable("Invalid BitCast"); } else if (DstTy->isFloatTy()) { - if (SrcTy->isInteger()) + if (SrcTy->isIntegerTy()) Dest.FloatVal = Src.IntVal.bitsToFloat(); else Dest.FloatVal = Src.FloatVal; } else if (DstTy->isDoubleTy()) { - if (SrcTy->isInteger()) + if (SrcTy->isIntegerTy()) Dest.DoubleVal = Src.IntVal.bitsToDouble(); else Dest.DoubleVal = Src.DoubleVal; diff --git a/lib/ExecutionEngine/JIT/Android.mk b/lib/ExecutionEngine/JIT/Android.mk new file mode 100644 index 0000000000..1c7e27f1b3 --- /dev/null +++ b/lib/ExecutionEngine/JIT/Android.mk @@ -0,0 +1,32 @@ +LOCAL_PATH:= $(call my-dir) + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + Intercept.cpp \ + JIT.cpp \ + JITDebugRegisterer.cpp \ + JITDwarfEmitter.cpp \ + JITEmitter.cpp \ + JITMemoryManager.cpp \ + OProfileJITEventListener.cpp \ + TargetSelect.cpp + +LOCAL_MODULE:= libLLVMJIT + +include $(LLVM_HOST_BUILD_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + JITMemoryManager.cpp + +LOCAL_MODULE:= libLLVMJIT + +include $(LLVM_DEVICE_BUILD_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index 616a66e18a..dd74d73208 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -18,6 +18,7 @@ #include "llvm/Function.h" #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/CodeGen/JITCodeEmitter.h" #include "llvm/CodeGen/MachineCodeInfo.h" #include "llvm/ExecutionEngine/GenericValue.h" @@ -27,6 +28,7 @@ #include "llvm/Target/TargetJITInfo.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MutexGuard.h" #include "llvm/System/DynamicLibrary.h" #include "llvm/Config/config.h" @@ -237,9 +239,53 @@ ExecutionEngine *JIT::createJIT(Module *M, } } +namespace { +/// This class supports the global getPointerToNamedFunction(), which allows +/// bugpoint or gdb users to search for a function by name without any context. +class JitPool { + SmallPtrSet JITs; // Optimize for process containing just 1 JIT. + mutable sys::Mutex Lock; +public: + void Add(JIT *jit) { + MutexGuard guard(Lock); + JITs.insert(jit); + } + void Remove(JIT *jit) { + MutexGuard guard(Lock); + JITs.erase(jit); + } + void *getPointerToNamedFunction(const char *Name) const { + MutexGuard guard(Lock); + assert(JITs.size() != 0 && "No Jit registered"); + //search function in every instance of JIT + for (SmallPtrSet::const_iterator Jit = JITs.begin(), + end = JITs.end(); + Jit != end; ++Jit) { + if (Function *F = (*Jit)->FindFunctionNamed(Name)) + return (*Jit)->getPointerToFunction(F); + } + // The function is not available : fallback on the first created (will + // search in symbol of the current program/library) + return (*JITs.begin())->getPointerToNamedFunction(Name); + } +}; +ManagedStatic AllJits; +} +extern "C" { + // getPointerToNamedFunction - This function is used as a global wrapper to + // JIT::getPointerToNamedFunction for the purpose of resolving symbols when + // bugpoint is debugging the JIT. In that scenario, we are loading an .so and + // need to resolve function(s) that are being mis-codegenerated, so we need to + // resolve their addresses at runtime, and this is the way to do it. + void *getPointerToNamedFunction(const char *Name) { + return AllJits->getPointerToNamedFunction(Name); + } +} + JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, JITMemoryManager *JMM, CodeGenOpt::Level OptLevel, bool GVsWithCode) - : ExecutionEngine(M), TM(tm), TJI(tji), AllocateGVsWithCode(GVsWithCode) { + : ExecutionEngine(M), TM(tm), TJI(tji), AllocateGVsWithCode(GVsWithCode), + isAlreadyCodeGenerating(false) { setTargetData(TM.getTargetData()); jitstate = new JITState(M); @@ -247,6 +293,9 @@ JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, // Initialize JCE JCE = createEmitter(*this, JMM, TM); + // Register in global list of all JITs. + AllJits->Add(this); + // Add target data MutexGuard locked(lock); FunctionPassManager &PM = jitstate->getPM(locked); @@ -281,6 +330,7 @@ JIT::JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, } JIT::~JIT() { + AllJits->Remove(this); delete jitstate; delete JCE; delete &TM; @@ -361,12 +411,12 @@ GenericValue JIT::runFunction(Function *F, // Handle some common cases first. These cases correspond to common `main' // prototypes. - if (RetTy->isInteger(32) || RetTy->isVoidTy()) { + if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) { switch (ArgValues.size()) { case 3: - if (FTy->getParamType(0)->isInteger(32) && - isa(FTy->getParamType(1)) && - isa(FTy->getParamType(2))) { + if (FTy->getParamType(0)->isIntegerTy(32) && + FTy->getParamType(1)->isPointerTy() && + FTy->getParamType(2)->isPointerTy()) { int (*PF)(int, char **, const char **) = (int(*)(int, char **, const char **))(intptr_t)FPtr; @@ -379,8 +429,8 @@ GenericValue JIT::runFunction(Function *F, } break; case 2: - if (FTy->getParamType(0)->isInteger(32) && - isa(FTy->getParamType(1))) { + if (FTy->getParamType(0)->isIntegerTy(32) && + FTy->getParamType(1)->isPointerTy()) { int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr; // Call the function. @@ -392,7 +442,7 @@ GenericValue JIT::runFunction(Function *F, break; case 1: if (FTy->getNumParams() == 1 && - FTy->getParamType(0)->isInteger(32)) { + FTy->getParamType(0)->isIntegerTy(32)) { GenericValue rv; int (*PF)(int) = (int(*)(int))(intptr_t)FPtr; rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue())); @@ -503,8 +553,12 @@ GenericValue JIT::runFunction(Function *F, else ReturnInst::Create(F->getContext(), StubBB); // Just return void. - // Finally, return the value returned by our nullary stub function. - return runFunction(Stub, std::vector()); + // Finally, call our nullary stub function. + GenericValue Result = runFunction(Stub, std::vector()); + // Erase it, since no other function can have a reference to it. + Stub->eraseFromParent(); + // And return the result. + return Result; } void JIT::RegisterJITEventListener(JITEventListener *L) { @@ -570,7 +624,6 @@ void JIT::runJITOnFunction(Function *F, MachineCodeInfo *MCI) { } void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) { - static bool isAlreadyCodeGenerating = false; assert(!isAlreadyCodeGenerating && "Error: Recursive compilation detected!"); // JIT the function diff --git a/lib/ExecutionEngine/JIT/JIT.h b/lib/ExecutionEngine/JIT/JIT.h index bb8f851a53..edae7191a6 100644 --- a/lib/ExecutionEngine/JIT/JIT.h +++ b/lib/ExecutionEngine/JIT/JIT.h @@ -61,6 +61,10 @@ class JIT : public ExecutionEngine { /// should be set to true. Doing so breaks freeMachineCodeForFunction. bool AllocateGVsWithCode; + /// True while the JIT is generating code. Used to assert against recursive + /// entry. + bool isAlreadyCodeGenerating; + JITState *jitstate; JIT(Module *M, TargetMachine &tm, TargetJITInfo &tji, diff --git a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp b/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp index c1051a9a81..946351bde0 100644 --- a/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp @@ -522,7 +522,11 @@ JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) const { JCE->emitInt64(((intptr_t)Jit.getPointerToGlobal(Personality))); } - JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); + // LSDA encoding: This must match the encoding used in EmitEHFrame () + if (PointerSize == 4) + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); + else + JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8); JCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); } else { JCE->emitULEB128Bytes(1); diff --git a/lib/ExecutionEngine/JIT/JITEmitter.cpp b/lib/ExecutionEngine/JIT/JITEmitter.cpp index 34a9938008..783ebb4deb 100644 --- a/lib/ExecutionEngine/JIT/JITEmitter.cpp +++ b/lib/ExecutionEngine/JIT/JITEmitter.cpp @@ -37,6 +37,7 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MutexGuard.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" @@ -57,7 +58,6 @@ using namespace llvm; STATISTIC(NumBytes, "Number of bytes of machine code compiled"); STATISTIC(NumRelos, "Number of relocations applied"); STATISTIC(NumRetries, "Number of retries with more memory"); -static JIT *TheJIT = 0; // A declaration may stop being a declaration once it's fully read from bitcode. @@ -109,9 +109,13 @@ namespace { /// particular GlobalVariable so that we can reuse them if necessary. GlobalToIndirectSymMapTy GlobalToIndirectSymMap; + /// Instance of the JIT this ResolverState serves. + JIT *TheJIT; + public: - JITResolverState() : FunctionToLazyStubMap(this), - FunctionToCallSitesMap(this) {} + JITResolverState(JIT *jit) : FunctionToLazyStubMap(this), + FunctionToCallSitesMap(this), + TheJIT(jit) {} FunctionToLazyStubMapTy& getFunctionToLazyStubMap( const MutexGuard& locked) { @@ -152,53 +156,18 @@ namespace { // was no stub. This function uses the call-site->function map to find a // relevant function, but asserts that only stubs and not other call sites // will be passed in. - Function *EraseStub(const MutexGuard &locked, void *Stub) { - CallSiteToFunctionMapTy::iterator C2F_I = - CallSiteToFunctionMap.find(Stub); - if (C2F_I == CallSiteToFunctionMap.end()) { - // Not a stub. - return NULL; - } - - Function *const F = C2F_I->second; -#ifndef NDEBUG - void *RealStub = FunctionToLazyStubMap.lookup(F); - assert(RealStub == Stub && - "Call-site that wasn't a stub pass in to EraseStub"); -#endif - FunctionToLazyStubMap.erase(F); - CallSiteToFunctionMap.erase(C2F_I); - - // Remove the stub from the function->call-sites map, and remove the whole - // entry from the map if that was the last call site. - FunctionToCallSitesMapTy::iterator F2C_I = FunctionToCallSitesMap.find(F); - assert(F2C_I != FunctionToCallSitesMap.end() && - "FunctionToCallSitesMap broken"); - bool Erased = F2C_I->second.erase(Stub); - (void)Erased; - assert(Erased && "FunctionToCallSitesMap broken"); - if (F2C_I->second.empty()) - FunctionToCallSitesMap.erase(F2C_I); - - return F; - } + Function *EraseStub(const MutexGuard &locked, void *Stub); - void EraseAllCallSites(const MutexGuard &locked, Function *F) { + void EraseAllCallSitesFor(const MutexGuard &locked, Function *F) { assert(locked.holds(TheJIT->lock)); - EraseAllCallSitesPrelocked(F); - } - void EraseAllCallSitesPrelocked(Function *F) { - FunctionToCallSitesMapTy::iterator F2C = FunctionToCallSitesMap.find(F); - if (F2C == FunctionToCallSitesMap.end()) - return; - for (SmallPtrSet::const_iterator I = F2C->second.begin(), - E = F2C->second.end(); I != E; ++I) { - bool Erased = CallSiteToFunctionMap.erase(*I); - (void)Erased; - assert(Erased && "Missing call site->function mapping"); - } - FunctionToCallSitesMap.erase(F2C); + EraseAllCallSitesForPrelocked(F); } + void EraseAllCallSitesForPrelocked(Function *F); + + // Erases _all_ call sites regardless of their function. This is used to + // unregister the stub addresses from the StubToResolverMap in + // ~JITResolver(). + void EraseAllCallSitesPrelocked(); }; /// JITResolver - Keep track of, and resolve, call sites for functions that @@ -227,19 +196,16 @@ namespace { JITEmitter &JE; - static JITResolver *TheJITResolver; - public: - explicit JITResolver(JIT &jit, JITEmitter &je) : nextGOTIndex(0), JE(je) { - TheJIT = &jit; + /// Instance of JIT corresponding to this Resolver. + JIT *TheJIT; + public: + explicit JITResolver(JIT &jit, JITEmitter &je) + : state(&jit), nextGOTIndex(0), JE(je), TheJIT(&jit) { LazyResolverFn = jit.getJITInfo().getLazyResolverFunction(JITCompilerFn); - assert(TheJITResolver == 0 && "Multiple JIT resolvers?"); - TheJITResolver = this; } - ~JITResolver() { - TheJITResolver = 0; - } + ~JITResolver(); /// getLazyFunctionStubIfAvailable - This returns a pointer to a function's /// lazy-compilation stub if it has already been created. @@ -260,8 +226,6 @@ namespace { void getRelocatableGVs(SmallVectorImpl &GVs, SmallVectorImpl &Ptrs); - GlobalValue *invalidateStub(void *Stub); - /// getGOTIndexForAddress - Return a new or existing index in the GOT for /// an address. This function only manages slots, it does not manage the /// contents of the slots or the memory associated with the GOT. @@ -273,6 +237,55 @@ namespace { static void *JITCompilerFn(void *Stub); }; + class StubToResolverMapTy { + /// Map a stub address to a specific instance of a JITResolver so that + /// lazily-compiled functions can find the right resolver to use. + /// + /// Guarded by Lock. + std::map Map; + + /// Guards Map from concurrent accesses. + mutable sys::Mutex Lock; + + public: + /// Registers a Stub to be resolved by Resolver. + void RegisterStubResolver(void *Stub, JITResolver *Resolver) { + MutexGuard guard(Lock); + Map.insert(std::make_pair(Stub, Resolver)); + } + /// Unregisters the Stub when it's invalidated. + void UnregisterStubResolver(void *Stub) { + MutexGuard guard(Lock); + Map.erase(Stub); + } + /// Returns the JITResolver instance that owns the Stub. + JITResolver *getResolverFromStub(void *Stub) const { + MutexGuard guard(Lock); + // The address given to us for the stub may not be exactly right, it might + // be a little bit after the stub. As such, use upper_bound to find it. + // This is the same trick as in LookupFunctionFromCallSite from + // JITResolverState. + std::map::const_iterator I = Map.upper_bound(Stub); + assert(I != Map.begin() && "This is not a known stub!"); + --I; + return I->second; + } + /// True if any stubs refer to the given resolver. Only used in an assert(). + /// O(N) + bool ResolverHasStubs(JITResolver* Resolver) const { + MutexGuard guard(Lock); + for (std::map::const_iterator I = Map.begin(), + E = Map.end(); I != E; ++I) { + if (I->second == Resolver) + return true; + } + return false; + } + }; + /// This needs to be static so that a lazy call stub can access it with no + /// context except the address of the stub. + ManagedStatic StubToResolverMap; + /// JITEmitter - The JIT implementation of the MachineCodeEmitter, which is /// used to output functions to memory for execution. class JITEmitter : public JITCodeEmitter { @@ -333,9 +346,6 @@ namespace { /// MMI - Machine module info for exception informations MachineModuleInfo* MMI; - // GVSet - a set to keep track of which globals have been seen - SmallPtrSet GVSet; - // CurFn - The llvm function being emitted. Only valid during // finishFunction(). const Function *CurFn; @@ -359,22 +369,15 @@ namespace { ValueMap EmittedFunctions; - // CurFnStubUses - For a given Function, a vector of stubs that it - // references. This facilitates the JIT detecting that a stub is no - // longer used, so that it may be deallocated. - DenseMap, SmallVector > CurFnStubUses; - - // StubFnRefs - For a given pointer to a stub, a set of Functions which - // reference the stub. When the count of a stub's references drops to zero, - // the stub is unused. - DenseMap > StubFnRefs; - DILocation PrevDLT; + /// Instance of the JIT + JIT *TheJIT; + public: JITEmitter(JIT &jit, JITMemoryManager *JMM, TargetMachine &TM) : SizeEstimate(0), Resolver(jit, *this), MMI(0), CurFn(0), - EmittedFunctions(this), PrevDLT(NULL) { + EmittedFunctions(this), PrevDLT(NULL), TheJIT(&jit) { MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager(); if (jit.getJITInfo().needsGOT()) { MemMgr->AllocateGOT(); @@ -454,11 +457,6 @@ namespace { /// function body. void deallocateMemForFunction(const Function *F); - /// AddStubToCurrentFunction - Mark the current function being JIT'd as - /// using the stub at the specified address. Allows - /// deallocateMemForFunction to also remove stubs no longer referenced. - void AddStubToCurrentFunction(void *Stub); - virtual void processDebugLoc(DebugLoc DL, bool BeforePrintingInsn); virtual void emitLabel(uint64_t LabelID) { @@ -489,16 +487,86 @@ namespace { bool MayNeedFarStub); void *getPointerToGVIndirectSym(GlobalValue *V, void *Reference); unsigned addSizeOfGlobal(const GlobalVariable *GV, unsigned Size); - unsigned addSizeOfGlobalsInConstantVal(const Constant *C, unsigned Size); - unsigned addSizeOfGlobalsInInitializer(const Constant *Init, unsigned Size); + unsigned addSizeOfGlobalsInConstantVal( + const Constant *C, unsigned Size, + SmallPtrSet &SeenGlobals, + SmallVectorImpl &Worklist); + unsigned addSizeOfGlobalsInInitializer( + const Constant *Init, unsigned Size, + SmallPtrSet &SeenGlobals, + SmallVectorImpl &Worklist); unsigned GetSizeOfGlobalsInBytes(MachineFunction &MF); }; } -JITResolver *JITResolver::TheJITResolver = 0; - void CallSiteValueMapConfig::onDelete(JITResolverState *JRS, Function *F) { - JRS->EraseAllCallSitesPrelocked(F); + JRS->EraseAllCallSitesForPrelocked(F); +} + +Function *JITResolverState::EraseStub(const MutexGuard &locked, void *Stub) { + CallSiteToFunctionMapTy::iterator C2F_I = + CallSiteToFunctionMap.find(Stub); + if (C2F_I == CallSiteToFunctionMap.end()) { + // Not a stub. + return NULL; + } + + StubToResolverMap->UnregisterStubResolver(Stub); + + Function *const F = C2F_I->second; +#ifndef NDEBUG + void *RealStub = FunctionToLazyStubMap.lookup(F); + assert(RealStub == Stub && + "Call-site that wasn't a stub passed in to EraseStub"); +#endif + FunctionToLazyStubMap.erase(F); + CallSiteToFunctionMap.erase(C2F_I); + + // Remove the stub from the function->call-sites map, and remove the whole + // entry from the map if that was the last call site. + FunctionToCallSitesMapTy::iterator F2C_I = FunctionToCallSitesMap.find(F); + assert(F2C_I != FunctionToCallSitesMap.end() && + "FunctionToCallSitesMap broken"); + bool Erased = F2C_I->second.erase(Stub); + (void)Erased; + assert(Erased && "FunctionToCallSitesMap broken"); + if (F2C_I->second.empty()) + FunctionToCallSitesMap.erase(F2C_I); + + return F; +} + +void JITResolverState::EraseAllCallSitesForPrelocked(Function *F) { + FunctionToCallSitesMapTy::iterator F2C = FunctionToCallSitesMap.find(F); + if (F2C == FunctionToCallSitesMap.end()) + return; + StubToResolverMapTy &S2RMap = *StubToResolverMap; + for (SmallPtrSet::const_iterator I = F2C->second.begin(), + E = F2C->second.end(); I != E; ++I) { + S2RMap.UnregisterStubResolver(*I); + bool Erased = CallSiteToFunctionMap.erase(*I); + (void)Erased; + assert(Erased && "Missing call site->function mapping"); + } + FunctionToCallSitesMap.erase(F2C); +} + +void JITResolverState::EraseAllCallSitesPrelocked() { + StubToResolverMapTy &S2RMap = *StubToResolverMap; + for (CallSiteToFunctionMapTy::const_iterator + I = CallSiteToFunctionMap.begin(), + E = CallSiteToFunctionMap.end(); I != E; ++I) { + S2RMap.UnregisterStubResolver(I->first); + } + CallSiteToFunctionMap.clear(); + FunctionToCallSitesMap.clear(); +} + +JITResolver::~JITResolver() { + // No need to lock because we're in the destructor, and state isn't shared. + state.EraseAllCallSitesPrelocked(); + assert(!StubToResolverMap->ResolverHasStubs(this) && + "Resolver destroyed with stubs still alive."); } /// getLazyFunctionStubIfAvailable - This returns a pointer to a function stub @@ -551,16 +619,22 @@ void *JITResolver::getLazyFunctionStub(Function *F) { DEBUG(dbgs() << "JIT: Lazy stub emitted at [" << Stub << "] for function '" << F->getName() << "'\n"); - // Finally, keep track of the stub-to-Function mapping so that the - // JITCompilerFn knows which function to compile! - state.AddCallSite(locked, Stub, F); - - // If we are JIT'ing non-lazily but need to call a function that does not - // exist yet, add it to the JIT's work list so that we can fill in the stub - // address later. - if (!Actual && !TheJIT->isCompilingLazily()) - if (!isNonGhostDeclaration(F) && !F->hasAvailableExternallyLinkage()) - TheJIT->addPendingFunction(F); + if (TheJIT->isCompilingLazily()) { + // Register this JITResolver as the one corresponding to this call site so + // JITCompilerFn will be able to find it. + StubToResolverMap->RegisterStubResolver(Stub, this); + + // Finally, keep track of the stub-to-Function mapping so that the + // JITCompilerFn knows which function to compile! + state.AddCallSite(locked, Stub, F); + } else if (!Actual) { + // If we are JIT'ing non-lazily but need to call a function that does not + // exist yet, add it to the JIT's work list so that we can fill in the + // stub address later. + assert(!isNonGhostDeclaration(F) && !F->hasAvailableExternallyLinkage() && + "'Actual' should have been set above."); + TheJIT->addPendingFunction(F); + } return Stub; } @@ -634,44 +708,12 @@ void JITResolver::getRelocatableGVs(SmallVectorImpl &GVs, } } -GlobalValue *JITResolver::invalidateStub(void *Stub) { - MutexGuard locked(TheJIT->lock); - - GlobalToIndirectSymMapTy &GM = state.getGlobalToIndirectSymMap(locked); - - // Look up the cheap way first, to see if it's a function stub we are - // invalidating. If so, remove it from both the forward and reverse maps. - if (Function *F = state.EraseStub(locked, Stub)) { - return F; - } - - // Otherwise, it might be an indirect symbol stub. Find it and remove it. - for (GlobalToIndirectSymMapTy::iterator i = GM.begin(), e = GM.end(); - i != e; ++i) { - if (i->second != Stub) - continue; - GlobalValue *GV = i->first; - GM.erase(i); - return GV; - } - - // Lastly, check to see if it's in the ExternalFnToStubMap. - for (std::map::iterator i = ExternalFnToStubMap.begin(), - e = ExternalFnToStubMap.end(); i != e; ++i) { - if (i->second != Stub) - continue; - ExternalFnToStubMap.erase(i); - break; - } - - return 0; -} - /// JITCompilerFn - This function is called when a lazy compilation stub has /// been entered. It looks up which function this stub corresponds to, compiles /// it if necessary, then returns the resultant function pointer. void *JITResolver::JITCompilerFn(void *Stub) { - JITResolver &JR = *TheJITResolver; + JITResolver *JR = StubToResolverMap->getResolverFromStub(Stub); + assert(JR && "Unable to find the corresponding JITResolver to the call site"); Function* F = 0; void* ActualPtr = 0; @@ -680,24 +722,24 @@ void *JITResolver::JITCompilerFn(void *Stub) { // Only lock for getting the Function. The call getPointerToFunction made // in this function might trigger function materializing, which requires // JIT lock to be unlocked. - MutexGuard locked(TheJIT->lock); + MutexGuard locked(JR->TheJIT->lock); // The address given to us for the stub may not be exactly right, it might // be a little bit after the stub. As such, use upper_bound to find it. pair I = - JR.state.LookupFunctionFromCallSite(locked, Stub); + JR->state.LookupFunctionFromCallSite(locked, Stub); F = I.second; ActualPtr = I.first; } // If we have already code generated the function, just return the address. - void *Result = TheJIT->getPointerToGlobalIfAvailable(F); + void *Result = JR->TheJIT->getPointerToGlobalIfAvailable(F); if (!Result) { // Otherwise we don't have it, do lazy compilation now. // If lazy compilation is disabled, emit a useful error message and abort. - if (!TheJIT->isCompilingLazily()) { + if (!JR->TheJIT->isCompilingLazily()) { llvm_report_error("LLVM JIT requested to do lazy compilation of function '" + F->getName() + "' when lazy compiles are disabled!"); } @@ -706,11 +748,11 @@ void *JITResolver::JITCompilerFn(void *Stub) { << "' In stub ptr = " << Stub << " actual ptr = " << ActualPtr << "\n"); - Result = TheJIT->getPointerToFunction(F); + Result = JR->TheJIT->getPointerToFunction(F); } // Reacquire the lock to update the GOT map. - MutexGuard locked(TheJIT->lock); + MutexGuard locked(JR->TheJIT->lock); // We might like to remove the call site from the CallSiteToFunction map, but // we can't do that! Multiple threads could be stuck, waiting to acquire the @@ -725,8 +767,8 @@ void *JITResolver::JITCompilerFn(void *Stub) { // if they see it still using the stub address. // Note: this is done so the Resolver doesn't have to manage GOT memory // Do this without allocating map space if the target isn't using a GOT - if(JR.revGOTMap.find(Stub) != JR.revGOTMap.end()) - JR.revGOTMap[Result] = JR.revGOTMap[Stub]; + if(JR->revGOTMap.find(Stub) != JR->revGOTMap.end()) + JR->revGOTMap[Result] = JR->revGOTMap[Stub]; return Result; } @@ -751,7 +793,6 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, // that we're returning the same address for the function as any previous // call. TODO: Yes, this is wrong. The lazy stub isn't guaranteed to be // close enough to call. - AddStubToCurrentFunction(FnStub); return FnStub; } @@ -768,18 +809,10 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference, return TheJIT->getPointerToFunction(F); } - // Otherwise, we may need a to emit a stub, and, conservatively, we - // always do so. - void *StubAddr = Resolver.getLazyFunctionStub(F); - - // Add the stub to the current function's list of referenced stubs, so we can - // deallocate them if the current function is ever freed. It's possible to - // return null from getLazyFunctionStub in the case of a weak extern that - // fails to resolve. - if (StubAddr) - AddStubToCurrentFunction(StubAddr); - - return StubAddr; + // Otherwise, we may need a to emit a stub, and, conservatively, we always do + // so. Note that it's possible to return null from getLazyFunctionStub in the + // case of a weak extern that fails to resolve. + return Resolver.getLazyFunctionStub(F); } void *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference) { @@ -787,24 +820,9 @@ void *JITEmitter::getPointerToGVIndirectSym(GlobalValue *V, void *Reference) { // resolved address. void *GVAddress = getPointerToGlobal(V, Reference, false); void *StubAddr = Resolver.getGlobalValueIndirectSym(V, GVAddress); - - // Add the stub to the current function's list of referenced stubs, so we can - // deallocate them if the current function is ever freed. - AddStubToCurrentFunction(StubAddr); - return StubAddr; } -void JITEmitter::AddStubToCurrentFunction(void *StubAddr) { - assert(CurFn && "Stub added to current function, but current function is 0!"); - - SmallVectorImpl &StubsUsed = CurFnStubUses[CurFn]; - StubsUsed.push_back(StubAddr); - - SmallPtrSet &FnRefs = StubFnRefs[StubAddr]; - FnRefs.insert(CurFn); -} - void JITEmitter::processDebugLoc(DebugLoc DL, bool BeforePrintingInsn) { if (!DL.isUnknown()) { DILocation CurDLT = EmissionDetails.MF->getDILocation(DL); @@ -839,7 +857,7 @@ static unsigned GetConstantPoolSizeInBytes(MachineConstantPool *MCP, return Size; } -static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) { +static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI, JIT *jit) { const std::vector &JT = MJTI->getJumpTables(); if (JT.empty()) return 0; @@ -847,7 +865,7 @@ static unsigned GetJumpTableSizeInBytes(MachineJumpTableInfo *MJTI) { for (unsigned i = 0, e = JT.size(); i != e; ++i) NumEntries += JT[i].MBBs.size(); - return NumEntries * MJTI->getEntrySize(*TheJIT->getTargetData()); + return NumEntries * MJTI->getEntrySize(*jit->getTargetData()); } static uintptr_t RoundUpToAlign(uintptr_t Size, unsigned Alignment) { @@ -876,11 +894,14 @@ unsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) { } /// addSizeOfGlobalsInConstantVal - find any globals that we haven't seen yet -/// but are referenced from the constant; put them in GVSet and add their -/// size into the running total Size. - -unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, - unsigned Size) { +/// but are referenced from the constant; put them in SeenGlobals and the +/// Worklist, and add their size into the running total Size. + +unsigned JITEmitter::addSizeOfGlobalsInConstantVal( + const Constant *C, + unsigned Size, + SmallPtrSet &SeenGlobals, + SmallVectorImpl &Worklist) { // If its undefined, return the garbage. if (isa(C)) return Size; @@ -902,7 +923,7 @@ unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, case Instruction::PtrToInt: case Instruction::IntToPtr: case Instruction::BitCast: { - Size = addSizeOfGlobalsInConstantVal(Op0, Size); + Size = addSizeOfGlobalsInConstantVal(Op0, Size, SeenGlobals, Worklist); break; } case Instruction::Add: @@ -918,8 +939,9 @@ unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, case Instruction::And: case Instruction::Or: case Instruction::Xor: { - Size = addSizeOfGlobalsInConstantVal(Op0, Size); - Size = addSizeOfGlobalsInConstantVal(CE->getOperand(1), Size); + Size = addSizeOfGlobalsInConstantVal(Op0, Size, SeenGlobals, Worklist); + Size = addSizeOfGlobalsInConstantVal(CE->getOperand(1), Size, + SeenGlobals, Worklist); break; } default: { @@ -933,8 +955,10 @@ unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, if (C->getType()->getTypeID() == Type::PointerTyID) if (const GlobalVariable* GV = dyn_cast(C)) - if (GVSet.insert(GV)) + if (SeenGlobals.insert(GV)) { + Worklist.push_back(GV); Size = addSizeOfGlobal(GV, Size); + } return Size; } @@ -942,15 +966,18 @@ unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C, /// addSizeOfGLobalsInInitializer - handle any globals that we haven't seen yet /// but are referenced from the given initializer. -unsigned JITEmitter::addSizeOfGlobalsInInitializer(const Constant *Init, - unsigned Size) { +unsigned JITEmitter::addSizeOfGlobalsInInitializer( + const Constant *Init, + unsigned Size, + SmallPtrSet &SeenGlobals, + SmallVectorImpl &Worklist) { if (!isa(Init) && !isa(Init) && !isa(Init) && !isa(Init) && !isa(Init) && Init->getType()->isFirstClassType()) - Size = addSizeOfGlobalsInConstantVal(Init, Size); + Size = addSizeOfGlobalsInConstantVal(Init, Size, SeenGlobals, Worklist); return Size; } @@ -961,7 +988,7 @@ unsigned JITEmitter::addSizeOfGlobalsInInitializer(const Constant *Init, unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) { unsigned Size = 0; - GVSet.clear(); + SmallPtrSet SeenGlobals; for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); MBB != E; ++MBB) { @@ -985,7 +1012,7 @@ unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) { // assuming the addresses of the new globals in this module // start at 0 (or something) and adjusting them after codegen // complete. Another possibility is to grab a marker bit in GV. - if (GVSet.insert(GV)) + if (SeenGlobals.insert(GV)) // A variable as yet unseen. Add in its size. Size = addSizeOfGlobal(GV, Size); } @@ -994,12 +1021,14 @@ unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) { } DEBUG(dbgs() << "JIT: About to look through initializers\n"); // Look for more globals that are referenced only from initializers. - // GVSet.end is computed each time because the set can grow as we go. - for (SmallPtrSet::iterator I = GVSet.begin(); - I != GVSet.end(); I++) { - const GlobalVariable* GV = *I; + SmallVector Worklist( + SeenGlobals.begin(), SeenGlobals.end()); + while (!Worklist.empty()) { + const GlobalVariable* GV = Worklist.back(); + Worklist.pop_back(); if (GV->hasInitializer()) - Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size); + Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size, + SeenGlobals, Worklist); } return Size; @@ -1032,7 +1061,7 @@ void JITEmitter::startFunction(MachineFunction &F) { MJTI->getEntryAlignment(*TheJIT->getTargetData())); // Add the jump table size - ActualSize += GetJumpTableSizeInBytes(MJTI); + ActualSize += GetJumpTableSizeInBytes(MJTI, TheJIT); } // Add the alignment for the function @@ -1301,40 +1330,6 @@ void JITEmitter::deallocateMemForFunction(const Function *F) { if (JITEmitDebugInfo) { DR->UnregisterFunction(F); } - - // If the function did not reference any stubs, return. - if (CurFnStubUses.find(F) == CurFnStubUses.end()) - return; - - // For each referenced stub, erase the reference to this function, and then - // erase the list of referenced stubs. - SmallVectorImpl &StubList = CurFnStubUses[F]; - for (unsigned i = 0, e = StubList.size(); i != e; ++i) { - void *Stub = StubList[i]; - - // If we already invalidated this stub for this function, continue. - if (StubFnRefs.count(Stub) == 0) - continue; - - SmallPtrSet &FnRefs = StubFnRefs[Stub]; - FnRefs.erase(F); - - // If this function was the last reference to the stub, invalidate the stub - // in the JITResolver. Were there a memory manager deallocateStub routine, - // we could call that at this point too. - if (FnRefs.empty()) { - DEBUG(dbgs() << "\nJIT: Invalidated Stub at [" << Stub << "]\n"); - StubFnRefs.erase(Stub); - - // Invalidate the stub. If it is a GV stub, update the JIT's global - // mapping for that GV to zero. - GlobalValue *GV = Resolver.invalidateStub(Stub); - if (GV) { - TheJIT->updateGlobalMapping(GV, 0); - } - } - } - CurFnStubUses.erase(F); } @@ -1552,19 +1547,6 @@ JITCodeEmitter *JIT::createEmitter(JIT &jit, JITMemoryManager *JMM, return new JITEmitter(jit, JMM, tm); } -// getPointerToNamedFunction - This function is used as a global wrapper to -// JIT::getPointerToNamedFunction for the purpose of resolving symbols when -// bugpoint is debugging the JIT. In that scenario, we are loading an .so and -// need to resolve function(s) that are being mis-codegenerated, so we need to -// resolve their addresses at runtime, and this is the way to do it. -extern "C" { - void *getPointerToNamedFunction(const char *Name) { - if (Function *F = TheJIT->FindFunctionNamed(Name)) - return TheJIT->getPointerToFunction(F); - return TheJIT->getPointerToNamedFunction(Name); - } -} - // getPointerToFunctionOrStub - If the specified function has been // code-gen'd, return a pointer to the function. If not, compile it, or use // a stub to implement lazy compilation if available. diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 7f441b0a47..8487c83ce3 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -159,7 +159,7 @@ static bool RecursiveResolveTypesI(const Type *DstTy, const Type *SrcTy, if (DstTy == SrcTy) return false; // If already equal, noop // If we found our opaque type, resolve it now! - if (isa(DstTy) || isa(SrcTy)) + if (DstTy->isOpaqueTy() || SrcTy->isOpaqueTy()) return ResolveTypes(DstTy, SrcTy); // Two types cannot be resolved together if they are of different primitive diff --git a/lib/MC/Android.mk b/lib/MC/Android.mk new file mode 100644 index 0000000000..dac5a54073 --- /dev/null +++ b/lib/MC/Android.mk @@ -0,0 +1,45 @@ +LOCAL_PATH:= $(call my-dir) + +mc_SRC_FILES := \ + MCAsmInfo.cpp \ + MCAsmInfoCOFF.cpp \ + MCAsmInfoDarwin.cpp \ + MCAsmStreamer.cpp \ + MCAssembler.cpp \ + MCCodeEmitter.cpp \ + MCContext.cpp \ + MCDisassembler.cpp \ + MCExpr.cpp \ + MCInst.cpp \ + MCInstPrinter.cpp \ + MCMachOStreamer.cpp \ + MCNullStreamer.cpp \ + MCSection.cpp \ + MCSectionELF.cpp \ + MCSectionMachO.cpp \ + MCStreamer.cpp \ + MCSymbol.cpp \ + MCValue.cpp \ + TargetAsmBackend.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(mc_SRC_FILES) + +LOCAL_MODULE:= libLLVMMC + +include $(LLVM_HOST_BUILD_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(mc_SRC_FILES) + +LOCAL_MODULE:= libLLVMMC + +include $(LLVM_DEVICE_BUILD_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index 9ead33b481..4cf71dcabe 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -18,4 +18,5 @@ add_llvm_library(LLVMMC MCStreamer.cpp MCSymbol.cpp MCValue.cpp + TargetAsmBackend.cpp ) diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 828377f42c..1b66900514 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include using namespace llvm; namespace { @@ -134,6 +135,9 @@ public: unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); + virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0); @@ -513,6 +517,13 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value, EmitEOL(); } +void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) { + // Emit with a text fill value. + EmitValueToAlignment(ByteAlignment, MAI.getTextAlignFillValue(), + 1, MaxBytesToEmit); +} + void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset, unsigned char Value) { // FIXME: Verify that Offset is associated with the current section. @@ -552,7 +563,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { MCFixup &F = Fixups[i]; - MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); + const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); for (unsigned j = 0; j != Info.TargetSize; ++j) { unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j; assert(Index < Code.size() * 8 && "Invalid offset in fixup!"); @@ -599,7 +610,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { MCFixup &F = Fixups[i]; - MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); + const MCFixupKindInfo &Info = Emitter->getFixupKindInfo(F.getKind()); OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset() << ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n"; } @@ -617,6 +628,12 @@ void MCAsmStreamer::EmitInstruction(const MCInst &Inst) { raw_ostream &OS = GetCommentOS(); OS << "getOpcodeName(Inst.getOpcode()); + if (!InstName.empty()) + OS << ' ' << InstName; + for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) { OS << "\n "; Inst.getOperand(i).print(OS, &MAI); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index bdc886bc67..96227dbee5 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -16,11 +16,17 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MachO.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" + +// FIXME: Gross. +#include "../Target/X86/X86FixupKinds.h" + #include using namespace llvm; @@ -36,6 +42,8 @@ STATISTIC(EmittedFragments, "Number of emitted assembler fragments"); static void WriteFileData(raw_ostream &OS, const MCSectionData &SD, MachObjectWriter &MOW); +static uint64_t WriteNopData(uint64_t Count, MachObjectWriter &MOW); + /// isVirtualSection - Check if this is a section which does not actually exist /// in the object file. static bool isVirtualSection(const MCSection &Section) { @@ -45,6 +53,30 @@ static bool isVirtualSection(const MCSection &Section) { return (Type == MCSectionMachO::S_ZEROFILL); } +static unsigned getFixupKindLog2Size(unsigned Kind) { + switch (Kind) { + default: llvm_unreachable("invalid fixup kind!"); + case X86::reloc_pcrel_1byte: + case FK_Data_1: return 0; + case FK_Data_2: return 1; + case X86::reloc_pcrel_4byte: + case X86::reloc_riprel_4byte: + case FK_Data_4: return 2; + case FK_Data_8: return 3; + } +} + +static bool isFixupKindPCRel(unsigned Kind) { + switch (Kind) { + default: + return false; + case X86::reloc_pcrel_1byte: + case X86::reloc_pcrel_4byte: + case X86::reloc_riprel_4byte: + return true; + } +} + class MachObjectWriter { // See . enum { @@ -402,13 +434,14 @@ public: uint32_t Word0; uint32_t Word1; }; - void ComputeScatteredRelocationInfo(MCAssembler &Asm, - MCSectionData::Fixup &Fixup, + void ComputeScatteredRelocationInfo(MCAssembler &Asm, MCFragment &Fragment, + MCAsmFixup &Fixup, const MCValue &Target, DenseMap &SymbolMap, std::vector &Relocs) { - uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset; + uint32_t Address = Fragment.getOffset() + Fixup.Offset; unsigned IsPCRel = 0; + unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); unsigned Type = RIT_Vanilla; // See . @@ -424,11 +457,12 @@ public: Value2 = SD->getFragment()->getAddress() + SD->getOffset(); } - unsigned Log2Size = Log2_32(Fixup.Size); - assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!"); - // The value which goes in the fixup is current value of the expression. Fixup.FixedValue = Value - Value2 + Target.getConstant(); + if (isFixupKindPCRel(Fixup.Kind)) { + Fixup.FixedValue -= Address; + IsPCRel = 1; + } MachRelocationEntry MRE; MRE.Word0 = ((Address << 0) | @@ -453,8 +487,8 @@ public: } } - void ComputeRelocationInfo(MCAssembler &Asm, - MCSectionData::Fixup &Fixup, + void ComputeRelocationInfo(MCAssembler &Asm, MCDataFragment &Fragment, + MCAsmFixup &Fixup, DenseMap &SymbolMap, std::vector &Relocs) { MCValue Target; @@ -466,19 +500,22 @@ public: if (Target.getSymB() || (Target.getSymA() && !Target.getSymA()->isUndefined() && Target.getConstant())) - return ComputeScatteredRelocationInfo(Asm, Fixup, Target, + return ComputeScatteredRelocationInfo(Asm, Fragment, Fixup, Target, SymbolMap, Relocs); // See . - uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset; + uint32_t Address = Fragment.getOffset() + Fixup.Offset; uint32_t Value = 0; unsigned Index = 0; unsigned IsPCRel = 0; + unsigned Log2Size = getFixupKindLog2Size(Fixup.Kind); unsigned IsExtern = 0; unsigned Type = 0; if (Target.isAbsolute()) { // constant // SymbolNum of 0 indicates the absolute section. + // + // FIXME: When is this generated? Type = RIT_Vanilla; Value = 0; llvm_unreachable("FIXME: Not yet implemented!"); @@ -495,10 +532,11 @@ public: // // FIXME: O(N) Index = 1; - for (MCAssembler::iterator it = Asm.begin(), - ie = Asm.end(); it != ie; ++it, ++Index) + MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); + for (; it != ie; ++it, ++Index) if (&*it == SD->getFragment()->getParent()) break; + assert(it != ie && "Unable to find section index!"); Value = SD->getFragment()->getAddress() + SD->getOffset(); } @@ -508,8 +546,10 @@ public: // The value which goes in the fixup is current value of the expression. Fixup.FixedValue = Value + Target.getConstant(); - unsigned Log2Size = Log2_32(Fixup.Size); - assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!"); + if (isFixupKindPCRel(Fixup.Kind)) { + Fixup.FixedValue -= Address; + IsPCRel = 1; + } // struct relocation_info (8 bytes) MachRelocationEntry MRE; @@ -766,17 +806,20 @@ public: // is written. std::vector RelocInfos; uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; - for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; - ++it) { + for (MCAssembler::iterator it = Asm.begin(), + ie = Asm.end(); it != ie; ++it) { MCSectionData &SD = *it; // The assembler writes relocations in the reverse order they were seen. // // FIXME: It is probably more complicated than this. unsigned NumRelocsStart = RelocInfos.size(); - for (unsigned i = 0, e = SD.fixup_size(); i != e; ++i) - ComputeRelocationInfo(Asm, SD.getFixups()[e - i - 1], SymbolMap, - RelocInfos); + for (MCSectionData::reverse_iterator it2 = SD.rbegin(), + ie2 = SD.rend(); it2 != ie2; ++it2) + if (MCDataFragment *DF = dyn_cast(&*it2)) + for (unsigned i = 0, e = DF->fixup_size(); i != e; ++i) + ComputeRelocationInfo(Asm, *DF, DF->getFixups()[e - i - 1], + SymbolMap, RelocInfos); unsigned NumRelocs = RelocInfos.size() - NumRelocsStart; uint64_t SectionStart = SectionDataStart + SD.getAddress(); @@ -871,6 +914,16 @@ public: OS << StringTable.str(); } } + + void ApplyFixup(const MCAsmFixup &Fixup, MCDataFragment &DF) { + unsigned Size = 1 << getFixupKindLog2Size(Fixup.Kind); + + // FIXME: Endianness assumption. + assert(Fixup.Offset + Size <= DF.getContents().size() && + "Invalid fixup offset!"); + for (unsigned i = 0; i != Size; ++i) + DF.getContents()[Fixup.Offset + i] = uint8_t(Fixup.FixedValue >> (i * 8)); + } }; /* *** */ @@ -905,35 +958,12 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) Address(~UINT64_C(0)), Size(~UINT64_C(0)), FileSize(~UINT64_C(0)), - LastFixupLookup(~0), HasInstructions(false) { if (A) A->getSectionList().push_back(this); } -const MCSectionData::Fixup * -MCSectionData::LookupFixup(const MCFragment *Fragment, uint64_t Offset) const { - // Use a one level cache to turn the common case of accessing the fixups in - // order into O(1) instead of O(N). - unsigned i = LastFixupLookup, Count = Fixups.size(), End = Fixups.size(); - if (i >= End) - i = 0; - while (Count--) { - const Fixup &F = Fixups[i]; - if (F.Fragment == Fragment && F.Offset == Offset) { - LastFixupLookup = i; - return &F; - } - - ++i; - if (i == End) - i = 0; - } - - return 0; -} - /* *** */ MCSymbolData::MCSymbolData() : Symbol(0) {} @@ -980,31 +1010,10 @@ void MCAssembler::LayoutSection(MCSectionData &SD) { } case MCFragment::FT_Data: + case MCFragment::FT_Fill: F.setFileSize(F.getMaxFileSize()); break; - case MCFragment::FT_Fill: { - MCFillFragment &FF = cast(F); - - F.setFileSize(F.getMaxFileSize()); - - MCValue Target; - if (!FF.getValue().EvaluateAsRelocatable(Target)) - llvm_report_error("expected relocatable expression"); - - // If the fill value is constant, thats it. - if (Target.isAbsolute()) - break; - - // Otherwise, add fixups for the values. - for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) { - MCSectionData::Fixup Fix(F, i * FF.getValueSize(), - FF.getValue(),FF.getValueSize()); - SD.getFixups().push_back(Fix); - } - break; - } - case MCFragment::FT_Org: { MCOrgFragment &OF = cast(F); @@ -1051,6 +1060,64 @@ void MCAssembler::LayoutSection(MCSectionData &SD) { SD.setFileSize(Address - SD.getAddress()); } +/// WriteNopData - Write optimal nops to the output file for the \arg Count +/// bytes. This returns the number of bytes written. It may return 0 if +/// the \arg Count is more than the maximum optimal nops. +/// +/// FIXME this is X86 32-bit specific and should move to a better place. +static uint64_t WriteNopData(uint64_t Count, MachObjectWriter &MOW) { + static const uint8_t Nops[16][16] = { + // nop + {0x90}, + // xchg %ax,%ax + {0x66, 0x90}, + // nopl (%[re]ax) + {0x0f, 0x1f, 0x00}, + // nopl 0(%[re]ax) + {0x0f, 0x1f, 0x40, 0x00}, + // nopl 0(%[re]ax,%[re]ax,1) + {0x0f, 0x1f, 0x44, 0x00, 0x00}, + // nopw 0(%[re]ax,%[re]ax,1) + {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, + // nopl 0L(%[re]ax) + {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, + // nopl 0L(%[re]ax,%[re]ax,1) + {0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + // nopw 0L(%[re]ax,%[re]ax,1) + {0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + // nopw %cs:0L(%[re]ax,%[re]ax,1) + {0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + // nopl 0(%[re]ax,%[re]ax,1) + // nopw 0(%[re]ax,%[re]ax,1) + {0x0f, 0x1f, 0x44, 0x00, 0x00, + 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, + // nopw 0(%[re]ax,%[re]ax,1) + // nopw 0(%[re]ax,%[re]ax,1) + {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, + 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00}, + // nopw 0(%[re]ax,%[re]ax,1) + // nopl 0L(%[re]ax) */ + {0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, + 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, + // nopl 0L(%[re]ax) + // nopl 0L(%[re]ax) + {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00}, + // nopl 0L(%[re]ax) + // nopl 0L(%[re]ax,%[re]ax,1) + {0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00} + }; + + if (Count > 15) + return 0; + + for (uint64_t i = 0; i < Count; i++) + MOW.Write8 (uint8_t(Nops[Count - 1][i])); + + return Count; +} + /// WriteFileData - Write the \arg F data to the output file. static void WriteFileData(raw_ostream &OS, const MCFragment &F, MachObjectWriter &MOW) { @@ -1074,6 +1141,14 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F, "' is not a divisor of padding size '" + Twine(AF.getFileSize()) + "'"); + // See if we are aligning with nops, and if so do that first to try to fill + // the Count bytes. Then if that did not fill any bytes or there are any + // bytes left to fill use the the Value and ValueSize to fill the rest. + if (AF.getEmitNops()) { + uint64_t NopByteCount = WriteNopData(Count, MOW); + Count -= NopByteCount; + } + for (uint64_t i = 0; i != Count; ++i) { switch (AF.getValueSize()) { default: @@ -1087,39 +1162,30 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F, break; } - case MCFragment::FT_Data: + case MCFragment::FT_Data: { + MCDataFragment &DF = cast(F); + + // Apply the fixups. + // + // FIXME: Move elsewhere. + for (MCDataFragment::const_fixup_iterator it = DF.fixup_begin(), + ie = DF.fixup_end(); it != ie; ++it) + MOW.ApplyFixup(*it, DF); + OS << cast(F).getContents().str(); break; + } case MCFragment::FT_Fill: { MCFillFragment &FF = cast(F); - - int64_t Value = 0; - - MCValue Target; - if (!FF.getValue().EvaluateAsRelocatable(Target)) - llvm_report_error("expected relocatable expression"); - - if (Target.isAbsolute()) - Value = Target.getConstant(); for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) { - if (!Target.isAbsolute()) { - // Find the fixup. - // - // FIXME: Find a better way to write in the fixes. - const MCSectionData::Fixup *Fixup = - F.getParent()->LookupFixup(&F, i * FF.getValueSize()); - assert(Fixup && "Missing fixup for fill value!"); - Value = Fixup->FixedValue; - } - switch (FF.getValueSize()) { default: assert(0 && "Invalid size!"); - case 1: MOW.Write8 (uint8_t (Value)); break; - case 2: MOW.Write16(uint16_t(Value)); break; - case 4: MOW.Write32(uint32_t(Value)); break; - case 8: MOW.Write64(uint64_t(Value)); break; + case 1: MOW.Write8 (uint8_t (FF.getValue())); break; + case 2: MOW.Write16(uint16_t(FF.getValue())); break; + case 4: MOW.Write32(uint32_t(FF.getValue())); break; + case 8: MOW.Write64(uint64_t(FF.getValue())); break; } } break; @@ -1167,6 +1233,10 @@ static void WriteFileData(raw_ostream &OS, const MCSectionData &SD, } void MCAssembler::Finish() { + DEBUG_WITH_TYPE("mc-dump", { + llvm::errs() << "assembler backend - pre-layout\n--\n"; + dump(); }); + // Layout the concrete sections and fragments. uint64_t Address = 0; MCSectionData *Prev = 0; @@ -1205,9 +1275,149 @@ void MCAssembler::Finish() { Address += SD.getSize(); } + DEBUG_WITH_TYPE("mc-dump", { + llvm::errs() << "assembler backend - post-layout\n--\n"; + dump(); }); + // Write the object file. MachObjectWriter MOW(OS); MOW.WriteObject(*this); OS.flush(); } + + +// Debugging methods + +namespace llvm { + +raw_ostream &operator<<(raw_ostream &OS, const MCAsmFixup &AF) { + OS << ""; + return OS; +} + +} + +void MCFragment::dump() { + raw_ostream &OS = llvm::errs(); + + OS << ""; +} + +void MCAlignFragment::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "MCFragment::dump(); + OS << "\n "; + OS << " Alignment:" << getAlignment() + << " Value:" << getValue() << " ValueSize:" << getValueSize() + << " MaxBytesToEmit:" << getMaxBytesToEmit() << ">"; +} + +void MCDataFragment::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "MCFragment::dump(); + OS << "\n "; + OS << " Contents:["; + for (unsigned i = 0, e = getContents().size(); i != e; ++i) { + if (i) OS << ","; + OS << hexdigit((Contents[i] >> 4) & 0xF) << hexdigit(Contents[i] & 0xF); + } + OS << "] (" << getContents().size() << " bytes)"; + + if (!getFixups().empty()) { + OS << ",\n "; + OS << " Fixups:["; + for (fixup_iterator it = fixup_begin(), ie = fixup_end(); it != ie; ++it) { + if (it != fixup_begin()) OS << ",\n "; + OS << *it; + } + OS << "]"; + } + + OS << ">"; +} + +void MCFillFragment::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "MCFragment::dump(); + OS << "\n "; + OS << " Value:" << getValue() << " ValueSize:" << getValueSize() + << " Count:" << getCount() << ">"; +} + +void MCOrgFragment::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "MCFragment::dump(); + OS << "\n "; + OS << " Offset:" << getOffset() << " Value:" << getValue() << ">"; +} + +void MCZeroFillFragment::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "MCFragment::dump(); + OS << "\n "; + OS << " Size:" << getSize() << " Alignment:" << getAlignment() << ">"; +} + +void MCSectionData::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "dump(); + } + OS << "]>"; +} + +void MCSymbolData::dump() { + raw_ostream &OS = llvm::errs(); + + OS << ""; +} + +void MCAssembler::dump() { + raw_ostream &OS = llvm::errs(); + + OS << "dump(); + } + OS << "],\n"; + OS << " Symbols:["; + + for (symbol_iterator it = symbol_begin(), ie = symbol_end(); it != ie; ++it) { + if (it != symbol_begin()) OS << ",\n "; + it->dump(); + } + OS << "]>\n"; +} diff --git a/lib/MC/MCCodeEmitter.cpp b/lib/MC/MCCodeEmitter.cpp index c122763b2f..accb06c8af 100644 --- a/lib/MC/MCCodeEmitter.cpp +++ b/lib/MC/MCCodeEmitter.cpp @@ -16,3 +16,15 @@ MCCodeEmitter::MCCodeEmitter() { MCCodeEmitter::~MCCodeEmitter() { } + +const MCFixupKindInfo &MCCodeEmitter::getFixupKindInfo(MCFixupKind Kind) const { + static const MCFixupKindInfo Builtins[] = { + { "FK_Data_1", 0, 8 }, + { "FK_Data_2", 0, 16 }, + { "FK_Data_4", 0, 32 }, + { "FK_Data_8", 0, 64 } + }; + + assert(Kind <= 3 && "Unknown fixup kind"); + return Builtins[Kind]; +} diff --git a/lib/MC/MCInstPrinter.cpp b/lib/MC/MCInstPrinter.cpp index e90c03c0cf..92a71541f5 100644 --- a/lib/MC/MCInstPrinter.cpp +++ b/lib/MC/MCInstPrinter.cpp @@ -8,7 +8,14 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCInstPrinter.h" +#include "llvm/ADT/StringRef.h" using namespace llvm; MCInstPrinter::~MCInstPrinter() { } + +/// getOpcodeName - Return the name of the specified opcode enum (e.g. +/// "MOV32ri") or empty if we can't resolve it. +StringRef MCInstPrinter::getOpcodeName(unsigned Opcode) const { + return ""; +} diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 99a819f719..a7a8a5daed 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -137,6 +137,8 @@ public: virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0); + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0); virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0); @@ -333,7 +335,22 @@ void MCMachOStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { void MCMachOStreamer::EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace) { - new MCFillFragment(*AddValueSymbols(Value), Size, 1, CurSectionData); + MCDataFragment *DF = dyn_cast_or_null(getCurrentFragment()); + if (!DF) + DF = new MCDataFragment(CurSectionData); + + // Avoid fixups when possible. + int64_t AbsValue; + if (AddValueSymbols(Value)->EvaluateAsAbsolute(AbsValue)) { + // FIXME: Endianness assumption. + for (unsigned i = 0; i != Size; ++i) + DF->getContents().push_back(uint8_t(AbsValue >> (i * 8))); + } else { + DF->getFixups().push_back(MCAsmFixup(DF->getContents().size(), + *AddValueSymbols(Value), + MCFixup::getKindForSize(Size))); + DF->getContents().resize(DF->getContents().size() + Size, 0); + } } void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, @@ -342,7 +359,20 @@ void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment, if (MaxBytesToEmit == 0) MaxBytesToEmit = ByteAlignment; new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit, - CurSectionData); + false /* EmitNops */, CurSectionData); + + // Update the maximum alignment on the current section if necessary. + if (ByteAlignment > CurSectionData->getAlignment()) + CurSectionData->setAlignment(ByteAlignment); +} + +void MCMachOStreamer::EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit) { + if (MaxBytesToEmit == 0) + MaxBytesToEmit = ByteAlignment; + // FIXME the 0x90 is the default x86 1 byte nop opcode. + new MCAlignFragment(ByteAlignment, 0x90, 1, MaxBytesToEmit, + true /* EmitNops */, CurSectionData); // Update the maximum alignment on the current section if necessary. if (ByteAlignment > CurSectionData->getAlignment()) @@ -365,12 +395,23 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) { CurSectionData->setHasInstructions(true); - // FIXME: Relocations! SmallVector Fixups; SmallString<256> Code; raw_svector_ostream VecOS(Code); Emitter->EncodeInstruction(Inst, VecOS, Fixups); - EmitBytes(VecOS.str(), 0); + VecOS.flush(); + + // Add the fixups and data. + MCDataFragment *DF = dyn_cast_or_null(getCurrentFragment()); + if (!DF) + DF = new MCDataFragment(CurSectionData); + for (unsigned i = 0, e = Fixups.size(); i != e; ++i) { + MCFixup &F = Fixups[i]; + DF->getFixups().push_back(MCAsmFixup(DF->getContents().size()+F.getOffset(), + *F.getValue(), + F.getKind())); + } + DF->getContents().append(Code.begin(), Code.end()); } void MCMachOStreamer::Finish() { diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index 46e9ebfa88..ab6179907e 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -55,6 +55,9 @@ namespace { unsigned ValueSize = 1, unsigned MaxBytesToEmit = 0) {} + virtual void EmitCodeAlignment(unsigned ByteAlignment, + unsigned MaxBytesToEmit = 0) {} + virtual void EmitValueToOffset(const MCExpr *Offset, unsigned char Value = 0) {} diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index d5bc396103..6185c30f52 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -146,7 +146,7 @@ bool AsmParser::Run() { // FIXME: Target hook & command line option for initial section. Out.SwitchSection(getMachOSection("__TEXT", "__text", MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - 0, SectionKind())); + 0, SectionKind::getText())); // Prime the lexer. @@ -325,9 +325,17 @@ bool AsmParser::ParseExpression(const MCExpr *&Res) { /// expr ::= primaryexpr /// bool AsmParser::ParseExpression(const MCExpr *&Res, SMLoc &EndLoc) { + // Parse the expression. Res = 0; - return ParsePrimaryExpr(Res, EndLoc) || - ParseBinOpRHS(1, Res, EndLoc); + if (ParsePrimaryExpr(Res, EndLoc) || ParseBinOpRHS(1, Res, EndLoc)) + return true; + + // Try to constant fold it up front, if possible. + int64_t Value; + if (Res->EvaluateAsAbsolute(Value)) + Res = MCConstantExpr::Create(Value, getContext()); + + return false; } bool AsmParser::ParseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) { @@ -906,8 +914,10 @@ bool AsmParser::ParseDirectiveDarwinSection() { return Error(Loc, ErrorStr.c_str()); // FIXME: Arch specific. + bool isText = Segment == "__TEXT"; // FIXME: Hack. Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, - SectionKind())); + isText ? SectionKind::getText() + : SectionKind::getDataRel())); return false; } @@ -921,8 +931,10 @@ bool AsmParser::ParseDirectiveSectionSwitch(const char *Segment, Lex(); // FIXME: Arch specific. + bool isText = StringRef(Segment) == "__TEXT"; // FIXME: Hack. Out.SwitchSection(getMachOSection(Segment, Section, TAA, StubSize, - SectionKind())); + isText ? SectionKind::getText() + : SectionKind::getDataRel())); // Set the implicit alignment, if any. // @@ -1229,8 +1241,14 @@ bool AsmParser::ParseDirectiveAlign(bool IsPow2, unsigned ValueSize) { } } - // FIXME: Target specific behavior about how the "extra" bytes are filled. - Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill); + // FIXME: hard code the parser to use EmitCodeAlignment for text when using + // the TextAlignFillValue. + if(Out.getCurrentSection()->getKind().isText() && + Lexer.getMAI().getTextAlignFillValue() == FillExpr) + Out.EmitCodeAlignment(Alignment, MaxBytesToFill); + else + // FIXME: Target specific behavior about how the "extra" bytes are filled. + Out.EmitValueToAlignment(Alignment, FillExpr, ValueSize, MaxBytesToFill); return false; } @@ -1354,7 +1372,7 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { if (IsLocal) { Out.EmitZerofill(getMachOSection("__DATA", "__bss", MCSectionMachO::S_ZEROFILL, 0, - SectionKind()), + SectionKind::getBSS()), Sym, Size, 1 << Pow2Alignment); return false; } @@ -1390,7 +1408,7 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { // Create the zerofill section but no symbol Out.EmitZerofill(getMachOSection(Segment, Section, MCSectionMachO::S_ZEROFILL, 0, - SectionKind())); + SectionKind::getBSS())); return false; } @@ -1448,7 +1466,7 @@ bool AsmParser::ParseDirectiveDarwinZerofill() { // FIXME: Arch specific. Out.EmitZerofill(getMachOSection(Segment, Section, MCSectionMachO::S_ZEROFILL, 0, - SectionKind()), + SectionKind::getBSS()), Sym, Size, 1 << Pow2Alignment); return false; diff --git a/lib/MC/MCSectionMachO.cpp b/lib/MC/MCSectionMachO.cpp index 6cc67a2225..370aad160b 100644 --- a/lib/MC/MCSectionMachO.cpp +++ b/lib/MC/MCSectionMachO.cpp @@ -10,6 +10,7 @@ #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCContext.h" #include "llvm/Support/raw_ostream.h" +#include using namespace llvm; /// SectionTypeDescriptors - These are strings that describe the various section diff --git a/lib/MC/TargetAsmBackend.cpp b/lib/MC/TargetAsmBackend.cpp new file mode 100644 index 0000000000..918d2727da --- /dev/null +++ b/lib/MC/TargetAsmBackend.cpp @@ -0,0 +1,19 @@ +//===-- TargetAsmBackend.cpp - Target Assembly Backend ---------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetAsmBackend.h" +using namespace llvm; + +TargetAsmBackend::TargetAsmBackend(const Target &T) + : TheTarget(T) +{ +} + +TargetAsmBackend::~TargetAsmBackend() { +} diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 1e6d22f18e..8f860a6467 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" +#include #include using namespace llvm; @@ -625,17 +626,58 @@ APFloat::copySignificand(const APFloat &rhs) /* Make this number a NaN, with an arbitrary but deterministic value for the significand. If double or longer, this is a signalling NaN, which may not be ideal. If float, this is QNaN(0). */ -void -APFloat::makeNaN(unsigned type) +void APFloat::makeNaN(bool SNaN, bool Negative, const APInt *fill) { category = fcNaN; - // FIXME: Add double and long double support for QNaN(0). - if (semantics->precision == 24 && semantics->maxExponent == 127) { - type |= 0x7fc00000U; - type &= ~0x80000000U; - } else - type = ~0U; - APInt::tcSet(significandParts(), type, partCount()); + sign = Negative; + + integerPart *significand = significandParts(); + unsigned numParts = partCount(); + + // Set the significand bits to the fill. + if (!fill || fill->getNumWords() < numParts) + APInt::tcSet(significand, 0, numParts); + if (fill) { + APInt::tcAssign(significand, fill->getRawData(), + std::min(fill->getNumWords(), numParts)); + + // Zero out the excess bits of the significand. + unsigned bitsToPreserve = semantics->precision - 1; + unsigned part = bitsToPreserve / 64; + bitsToPreserve %= 64; + significand[part] &= ((1ULL << bitsToPreserve) - 1); + for (part++; part != numParts; ++part) + significand[part] = 0; + } + + unsigned QNaNBit = semantics->precision - 2; + + if (SNaN) { + // We always have to clear the QNaN bit to make it an SNaN. + APInt::tcClearBit(significand, QNaNBit); + + // If there are no bits set in the payload, we have to set + // *something* to make it a NaN instead of an infinity; + // conventionally, this is the next bit down from the QNaN bit. + if (APInt::tcIsZero(significand, numParts)) + APInt::tcSetBit(significand, QNaNBit - 1); + } else { + // We always have to set the QNaN bit to make it a QNaN. + APInt::tcSetBit(significand, QNaNBit); + } + + // For x87 extended precision, we want to make a NaN, not a + // pseudo-NaN. Maybe we should expose the ability to make + // pseudo-NaNs? + if (semantics == &APFloat::x87DoubleExtended) + APInt::tcSetBit(significand, QNaNBit + 1); +} + +APFloat APFloat::makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, + const APInt *fill) { + APFloat value(Sem, uninitialized); + value.makeNaN(SNaN, Negative, fill); + return value; } APFloat & @@ -700,9 +742,14 @@ APFloat::APFloat(const fltSemantics &ourSemantics) { sign = false; } +APFloat::APFloat(const fltSemantics &ourSemantics, uninitializedTag tag) { + assertArithmeticOK(ourSemantics); + // Allocates storage if necessary but does not initialize it. + initialize(&ourSemantics); +} APFloat::APFloat(const fltSemantics &ourSemantics, - fltCategory ourCategory, bool negative, unsigned type) + fltCategory ourCategory, bool negative) { assertArithmeticOK(ourSemantics); initialize(&ourSemantics); @@ -711,7 +758,7 @@ APFloat::APFloat(const fltSemantics &ourSemantics, if (category == fcNormal) category = fcZero; else if (ourCategory == fcNaN) - makeNaN(type); + makeNaN(); } APFloat::APFloat(const fltSemantics &ourSemantics, const StringRef& text) @@ -2345,11 +2392,24 @@ APFloat::convertFromDecimalString(const StringRef &str, roundingMode rounding_mo if (decDigitValue(*D.firstSigDigit) >= 10U) { category = fcZero; fs = opOK; - } else if ((D.normalizedExponent + 1) * 28738 - <= 8651 * (semantics->minExponent - (int) semantics->precision)) { + + /* Check whether the normalized exponent is high enough to overflow + max during the log-rebasing in the max-exponent check below. */ + } else if (D.normalizedExponent - 1 > INT_MAX / 42039) { + fs = handleOverflow(rounding_mode); + + /* If it wasn't, then it also wasn't high enough to overflow max + during the log-rebasing in the min-exponent check. Check that it + won't overflow min in either check, then perform the min-exponent + check. */ + } else if (D.normalizedExponent - 1 < INT_MIN / 42039 || + (D.normalizedExponent + 1) * 28738 <= + 8651 * (semantics->minExponent - (int) semantics->precision)) { /* Underflow to zero and round. */ zeroSignificand(); fs = normalize(rounding_mode, lfLessThanHalf); + + /* We can finally safely perform the max-exponent check. */ } else if ((D.normalizedExponent - 1) * 42039 >= 12655 * semantics->maxExponent) { /* Overflow and round. */ @@ -3306,7 +3366,7 @@ namespace { void APFloat::toString(SmallVectorImpl &Str, unsigned FormatPrecision, - unsigned FormatMaxPadding) { + unsigned FormatMaxPadding) const { switch (category) { case fcInfinity: if (isNegative()) diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index 3bce3f3ed3..6a6384aa3f 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -2344,13 +2344,21 @@ APInt::tcExtractBit(const integerPart *parts, unsigned int bit) & ((integerPart) 1 << bit % integerPartWidth)) != 0; } -/* Set the given bit of a bignum. */ +/* Set the given bit of a bignum. */ void APInt::tcSetBit(integerPart *parts, unsigned int bit) { parts[bit / integerPartWidth] |= (integerPart) 1 << (bit % integerPartWidth); } +/* Clears the given bit of a bignum. */ +void +APInt::tcClearBit(integerPart *parts, unsigned int bit) +{ + parts[bit / integerPartWidth] &= + ~((integerPart) 1 << (bit % integerPartWidth)); +} + /* Returns the bit number of the least significant set bit of a number. If the input number has no bits set -1U is returned. */ unsigned int diff --git a/lib/Support/Android.mk b/lib/Support/Android.mk new file mode 100644 index 0000000000..e97275381c --- /dev/null +++ b/lib/Support/Android.mk @@ -0,0 +1,72 @@ +LOCAL_PATH:= $(call my-dir) + +support_SRC_FILES := \ + APFloat.cpp \ + APInt.cpp \ + APSInt.cpp \ + Allocator.cpp \ + CommandLine.cpp \ + ConstantRange.cpp \ + Debug.cpp \ + DeltaAlgorithm.cpp \ + Dwarf.cpp \ + ErrorHandling.cpp \ + FileUtilities.cpp \ + FoldingSet.cpp \ + FormattedStream.cpp \ + GraphWriter.cpp \ + IsInf.cpp \ + IsNAN.cpp \ + ManagedStatic.cpp \ + MemoryBuffer.cpp \ + MemoryObject.cpp \ + PluginLoader.cpp \ + PrettyStackTrace.cpp \ + Regex.cpp \ + SlowOperationInformer.cpp \ + SmallPtrSet.cpp \ + SmallVector.cpp \ + SourceMgr.cpp \ + Statistic.cpp \ + StringExtras.cpp \ + StringMap.cpp \ + StringPool.cpp \ + StringRef.cpp \ + SystemUtils.cpp \ + TargetRegistry.cpp \ + Timer.cpp \ + Triple.cpp \ + Twine.cpp \ + circular_raw_ostream.cpp \ + raw_os_ostream.cpp \ + raw_ostream.cpp \ + regcomp.c \ + regerror.c \ + regexec.c \ + regfree.c \ + regstrlcpy.c + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +# FIXME: This only requires RTTI because tblgen uses it. Fix that. +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(support_SRC_FILES) + +LOCAL_MODULE:= libLLVMSupport + +include $(LLVM_HOST_BUILD_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(support_SRC_FILES) + +LOCAL_MODULE:= libLLVMSupport + +include $(LLVM_DEVICE_BUILD_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 961dc1fef9..2ab4103de2 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -650,7 +650,7 @@ void cl::ParseCommandLineOptions(int argc, char **argv, if (Handler == 0) { if (SinkOpts.empty()) { errs() << ProgramName << ": Unknown command line argument '" - << argv[i] << "'. Try: '" << argv[0] << " --help'\n"; + << argv[i] << "'. Try: '" << argv[0] << " -help'\n"; ErrorParsing = true; } else { for (SmallVectorImpl::iterator I = SinkOpts.begin(), @@ -673,7 +673,7 @@ void cl::ParseCommandLineOptions(int argc, char **argv, errs() << ProgramName << ": Not enough positional command line arguments specified!\n" << "Must specify at least " << NumPositionalRequired - << " positional arguments: See: " << argv[0] << " --help\n"; + << " positional arguments: See: " << argv[0] << " -help\n"; ErrorParsing = true; } else if (!HasUnlimitedPositionals @@ -681,7 +681,7 @@ void cl::ParseCommandLineOptions(int argc, char **argv, errs() << ProgramName << ": Too many positional arguments specified!\n" << "Can specify at most " << PositionalOpts.size() - << " positional arguments: See: " << argv[0] << " --help\n"; + << " positional arguments: See: " << argv[0] << " -help\n"; ErrorParsing = true; } else if (ConsumeAfterOpt == 0) { @@ -1029,7 +1029,7 @@ void generic_parser_base::printOptionInfo(const Option &O, //===----------------------------------------------------------------------===// -// --help and --help-hidden option implementation +// -help and -help-hidden option implementation // static int OptNameCompare(const void *LHS, const void *RHS) { @@ -1134,7 +1134,7 @@ static HelpPrinter NormalPrinter(false); static HelpPrinter HiddenPrinter(true); static cl::opt > -HOp("help", cl::desc("Display available options (--help-hidden for more)"), +HOp("help", cl::desc("Display available options (-help-hidden for more)"), cl::location(NormalPrinter), cl::ValueDisallowed); static cl::opt > @@ -1222,8 +1222,8 @@ void cl::PrintHelpMessage() { // NormalPrinter variable is a HelpPrinter and the help gets printed when // its operator= is invoked. That's because the "normal" usages of the // help printer is to be assigned true/false depending on whether the - // --help option was given or not. Since we're circumventing that we have - // to make it look like --help was given, so we assign true. + // -help option was given or not. Since we're circumventing that we have + // to make it look like -help was given, so we assign true. NormalPrinter = true; } diff --git a/lib/Support/FormattedStream.cpp b/lib/Support/FormattedStream.cpp index 9ab3666340..c72b5a1751 100644 --- a/lib/Support/FormattedStream.cpp +++ b/lib/Support/FormattedStream.cpp @@ -56,15 +56,14 @@ void formatted_raw_ostream::ComputeColumn(const char *Ptr, size_t Size) { /// PadToColumn - Align the output to some column number. /// /// \param NewCol - The column to move to. -/// \param MinPad - The minimum space to give after the most recent -/// I/O, even if the current column + minpad > newcol. /// -void formatted_raw_ostream::PadToColumn(unsigned NewCol) { +formatted_raw_ostream &formatted_raw_ostream::PadToColumn(unsigned NewCol) { // Figure out what's in the buffer and add it to the column count. ComputeColumn(getBufferStart(), GetNumBytesInBuffer()); // Output spaces until we reach the desired column. indent(std::max(int(NewCol - ColumnScanned), 1)); + return *this; } void formatted_raw_ostream::write_impl(const char *Ptr, size_t Size) { diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp index c8bca6ef88..ec84f9beca 100644 --- a/lib/Support/GraphWriter.cpp +++ b/lib/Support/GraphWriter.cpp @@ -137,7 +137,7 @@ void llvm::DisplayGraph(const sys::Path &Filename, bool wait, args.clear(); args.push_back(gv.c_str()); args.push_back(PSFilename.c_str()); - args.push_back("-spartan"); + args.push_back("--spartan"); args.push_back(0); ErrMsg.clear(); diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp index 9253b01d58..eb046d0eaf 100644 --- a/lib/Support/MemoryBuffer.cpp +++ b/lib/Support/MemoryBuffer.cpp @@ -174,7 +174,8 @@ MemoryBuffer *MemoryBuffer::getFile(StringRef Filename, std::string *ErrStr, #ifdef O_BINARY OpenFlags |= O_BINARY; // Open input file in binary mode on win32. #endif - int FD = ::open(Filename.str().c_str(), O_RDONLY|OpenFlags); + SmallString<256> PathBuf(Filename.begin(), Filename.end()); + int FD = ::open(PathBuf.c_str(), O_RDONLY|OpenFlags); if (FD == -1) { if (ErrStr) *ErrStr = strerror(errno); return 0; diff --git a/lib/Support/Regex.cpp b/lib/Support/Regex.cpp index 618ca0524a..a7631de9d8 100644 --- a/lib/Support/Regex.cpp +++ b/lib/Support/Regex.cpp @@ -90,3 +90,79 @@ bool Regex::match(const StringRef &String, SmallVectorImpl *Matches){ return true; } + +std::string Regex::sub(StringRef Repl, StringRef String, + std::string *Error) { + SmallVector Matches; + + // Reset error, if given. + if (Error && !Error->empty()) *Error = ""; + + // Return the input if there was no match. + if (!match(String, &Matches)) + return String; + + // Otherwise splice in the replacement string, starting with the prefix before + // the match. + std::string Res(String.begin(), Matches[0].begin()); + + // Then the replacement string, honoring possible substitutions. + while (!Repl.empty()) { + // Skip to the next escape. + std::pair Split = Repl.split('\\'); + + // Add the skipped substring. + Res += Split.first; + + // Check for terminimation and trailing backslash. + if (Split.second.empty()) { + if (Repl.size() != Split.first.size() && + Error && Error->empty()) + *Error = "replacement string contained trailing backslash"; + break; + } + + // Otherwise update the replacement string and interpret escapes. + Repl = Split.second; + + // FIXME: We should have a StringExtras function for mapping C99 escapes. + switch (Repl[0]) { + // Treat all unrecognized characters as self-quoting. + default: + Res += Repl[0]; + Repl = Repl.substr(1); + break; + + // Single character escapes. + case 't': + Res += '\t'; + Repl = Repl.substr(1); + break; + case 'n': + Res += '\n'; + Repl = Repl.substr(1); + break; + + // Decimal escapes are backreferences. + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + // Extract the backreference number. + StringRef Ref = Repl.slice(0, Repl.find_first_not_of("0123456789")); + Repl = Repl.substr(Ref.size()); + + unsigned RefValue; + if (!Ref.getAsInteger(10, RefValue) && + RefValue < Matches.size()) + Res += Matches[RefValue]; + else if (Error && Error->empty()) + *Error = "invalid backreference string '" + Ref.str() + "'"; + break; + } + } + } + + // And finally the suffix. + Res += StringRef(Matches[0].end(), String.end() - Matches[0].end()); + + return Res; +} diff --git a/lib/Support/StringRef.cpp b/lib/Support/StringRef.cpp index ae2640b5b9..2b262dcd3f 100644 --- a/lib/Support/StringRef.cpp +++ b/lib/Support/StringRef.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/APInt.h" using namespace llvm; @@ -172,23 +173,28 @@ size_t StringRef::count(StringRef Str) const { return Count; } +static unsigned GetAutoSenseRadix(StringRef &Str) { + if (Str.startswith("0x")) { + Str = Str.substr(2); + return 16; + } else if (Str.startswith("0b")) { + Str = Str.substr(2); + return 2; + } else if (Str.startswith("0")) { + return 8; + } else { + return 10; + } +} + + /// GetAsUnsignedInteger - Workhorse method that converts a integer character /// sequence of radix up to 36 to an unsigned long long value. static bool GetAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long &Result) { // Autosense radix if not specified. - if (Radix == 0) { - if (Str.startswith("0x")) { - Str = Str.substr(2); - Radix = 16; - } else if (Str.startswith("0b")) { - Str = Str.substr(2); - Radix = 2; - } else if (Str.startswith("0")) - Radix = 8; - else - Radix = 10; - } + if (Radix == 0) + Radix = GetAutoSenseRadix(Str); // Empty strings (after the radix autosense) are invalid. if (Str.empty()) return true; @@ -272,3 +278,78 @@ bool StringRef::getAsInteger(unsigned Radix, unsigned &Result) const { Result = Val; return false; } + +bool StringRef::getAsInteger(unsigned Radix, APInt &Result) const { + StringRef Str = *this; + + // Autosense radix if not specified. + if (Radix == 0) + Radix = GetAutoSenseRadix(Str); + + assert(Radix > 1 && Radix <= 36); + + // Empty strings (after the radix autosense) are invalid. + if (Str.empty()) return true; + + // Skip leading zeroes. This can be a significant improvement if + // it means we don't need > 64 bits. + while (!Str.empty() && Str.front() == '0') + Str = Str.substr(1); + + // If it was nothing but zeroes.... + if (Str.empty()) { + Result = APInt(64, 0); + return false; + } + + // (Over-)estimate the required number of bits. + unsigned Log2Radix = 0; + while ((1U << Log2Radix) < Radix) Log2Radix++; + bool IsPowerOf2Radix = ((1U << Log2Radix) == Radix); + + unsigned BitWidth = Log2Radix * Str.size(); + if (BitWidth < Result.getBitWidth()) + BitWidth = Result.getBitWidth(); // don't shrink the result + else + Result.zext(BitWidth); + + APInt RadixAP, CharAP; // unused unless !IsPowerOf2Radix + if (!IsPowerOf2Radix) { + // These must have the same bit-width as Result. + RadixAP = APInt(BitWidth, Radix); + CharAP = APInt(BitWidth, 0); + } + + // Parse all the bytes of the string given this radix. + Result = 0; + while (!Str.empty()) { + unsigned CharVal; + if (Str[0] >= '0' && Str[0] <= '9') + CharVal = Str[0]-'0'; + else if (Str[0] >= 'a' && Str[0] <= 'z') + CharVal = Str[0]-'a'+10; + else if (Str[0] >= 'A' && Str[0] <= 'Z') + CharVal = Str[0]-'A'+10; + else + return true; + + // If the parsed value is larger than the integer radix, the string is + // invalid. + if (CharVal >= Radix) + return true; + + // Add in this character. + if (IsPowerOf2Radix) { + Result <<= Log2Radix; + Result |= CharVal; + } else { + Result *= RadixAP; + CharAP = CharVal; + Result += CharAP; + } + + Str = Str.substr(1); + } + + return false; +} diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp index 5a76184caa..61bf0a73c9 100644 --- a/lib/Support/Triple.cpp +++ b/lib/Support/Triple.cpp @@ -40,6 +40,7 @@ const char *Triple::getArchTypeName(ArchType Kind) { case x86: return "i386"; case x86_64: return "x86_64"; case xcore: return "xcore"; + case mblaze: return "mblaze"; } return ""; @@ -62,6 +63,8 @@ const char *Triple::getArchTypePrefix(ArchType Kind) { case ppc64: case ppc: return "ppc"; + case mblaze: return "mblaze"; + case sparcv9: case sparc: return "sparc"; @@ -127,6 +130,8 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { return ppc64; if (Name == "ppc") return ppc; + if (Name == "mblaze") + return mblaze; if (Name == "sparc") return sparc; if (Name == "sparcv9") @@ -198,6 +203,8 @@ const char *Triple::getArchNameForAssembler() { return "ppc"; if (Str == "powerpc64") return "ppc64"; + if (Str == "mblaze" || Str == "microblaze") + return "mblaze"; if (Str == "arm") return "arm"; if (Str == "armv4t" || Str == "thumbv4t") @@ -234,6 +241,8 @@ void Triple::Parse() const { Arch = ppc; else if ((ArchName == "powerpc64") || (ArchName == "ppu")) Arch = ppc64; + else if (ArchName == "mblaze") + Arch = mblaze; else if (ArchName == "arm" || ArchName.startswith("armv") || ArchName == "xscale") diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp index af6dc7cf48..071c924d91 100644 --- a/lib/Support/raw_ostream.cpp +++ b/lib/Support/raw_ostream.cpp @@ -368,6 +368,7 @@ void format_object_base::home() { /// if no error occurred. raw_fd_ostream::raw_fd_ostream(const char *Filename, std::string &ErrorInfo, unsigned Flags) : pos(0) { + assert(Filename != 0 && "Filename is null"); // Verify that we don't have both "append" and "excl". assert((!(Flags & F_Excl) || !(Flags & F_Append)) && "Cannot specify both 'excl' and 'append' file creation flags!"); @@ -574,12 +575,18 @@ void raw_svector_ostream::resync() { } void raw_svector_ostream::write_impl(const char *Ptr, size_t Size) { - assert(Ptr == OS.end() && OS.size() + Size <= OS.capacity() && - "Invalid write_impl() call!"); - - // We don't need to copy the bytes, just commit the bytes to the - // SmallVector. - OS.set_size(OS.size() + Size); + // If we're writing bytes from the end of the buffer into the smallvector, we + // don't need to copy the bytes, just commit the bytes because they are + // already in the right place. + if (Ptr == OS.end()) { + assert(OS.size() + Size <= OS.capacity() && "Invalid write_impl() call!"); + OS.set_size(OS.size() + Size); + } else { + assert(GetNumBytesInBuffer() == 0 && + "Should be writing from buffer if some bytes in it"); + // Otherwise, do copy the bytes. + OS.append(Ptr, Ptr+Size); + } // Grow the vector if necessary. if (OS.capacity() - OS.size() < 64) diff --git a/lib/System/Android.mk b/lib/System/Android.mk new file mode 100644 index 0000000000..3f11fc74a7 --- /dev/null +++ b/lib/System/Android.mk @@ -0,0 +1,46 @@ +LOCAL_PATH:= $(call my-dir) + +system_SRC_FILES := \ + Alarm.cpp \ + Atomic.cpp \ + Disassembler.cpp \ + Errno.cpp \ + Host.cpp \ + IncludeFile.cpp \ + Memory.cpp \ + Mutex.cpp \ + Path.cpp \ + Process.cpp \ + Program.cpp \ + RWMutex.cpp \ + Signals.cpp \ + ThreadLocal.cpp \ + Threading.cpp \ + TimeValue.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(system_SRC_FILES) +LOCAL_CFLAGS += -march=i686 + +LOCAL_MODULE:= libLLVMSystem + +include $(LLVM_HOST_BUILD_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(system_SRC_FILES) + +LOCAL_MODULE:= libLLVMSystem + +include $(LLVM_DEVICE_BUILD_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/System/Unix/Host.inc b/lib/System/Unix/Host.inc index c76d6a4e18..5b1187602e 100644 --- a/lib/System/Unix/Host.inc +++ b/lib/System/Unix/Host.inc @@ -21,6 +21,7 @@ #include "Unix.h" #include #include +#include using namespace llvm; diff --git a/lib/System/Unix/Program.inc b/lib/System/Unix/Program.inc index e8c2806247..c10498a375 100644 --- a/lib/System/Unix/Program.inc +++ b/lib/System/Unix/Program.inc @@ -126,7 +126,7 @@ static void TimeOutHandler(int Sig) { static void SetMemoryLimits (unsigned size) { -#if HAVE_SYS_RESOURCE_H +#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT struct rlimit r; __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576; diff --git a/lib/System/Unix/Signals.inc b/lib/System/Unix/Signals.inc index 676e1e5356..c8ec68aab1 100644 --- a/lib/System/Unix/Signals.inc +++ b/lib/System/Unix/Signals.inc @@ -52,7 +52,16 @@ static const int *const IntSigsEnd = // KillSigs - Signals that are synchronous with the program that will cause it // to die. static const int KillSigs[] = { - SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ + SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV +#ifdef SIGSYS + , SIGSYS +#endif +#ifdef SIGXCPU + , SIGXCPU +#endif +#ifdef SIGXFSZ + , SIGXFSZ +#endif #ifdef SIGEMT , SIGEMT #endif diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 6fe7c2c8c6..8e537d8b62 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -643,6 +643,13 @@ ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB, DebugLoc DL = DebugLoc::getUnknownLoc(); if (I != MBB.end()) DL = I->getDebugLoc(); + // tGPR is used sometimes in ARM instructions that need to avoid using + // certain registers. Just treat it as GPR here. + if (DestRC == ARM::tGPRRegisterClass) + DestRC = ARM::GPRRegisterClass; + if (SrcRC == ARM::tGPRRegisterClass) + SrcRC = ARM::GPRRegisterClass; + if (DestRC != SrcRC) { if (DestRC->getSize() != SrcRC->getSize()) return false; @@ -697,6 +704,11 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MFI.getObjectSize(FI), Align); + // tGPR is used sometimes in ARM instructions that need to avoid using + // certain registers. Just treat it as GPR here. + if (RC == ARM::tGPRRegisterClass) + RC = ARM::GPRRegisterClass; + if (RC == ARM::GPRRegisterClass) { AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STR)) .addReg(SrcReg, getKillRegState(isKill)) @@ -745,6 +757,11 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MFI.getObjectSize(FI), Align); + // tGPR is used sometimes in ARM instructions that need to avoid using + // certain registers. Just treat it as GPR here. + if (RC == ARM::tGPRRegisterClass) + RC = ARM::GPRRegisterClass; + if (RC == ARM::GPRRegisterClass) { AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDR), DestReg) .addFrameIndex(FI).addReg(0).addImm(0).addMemOperand(MMO)); @@ -1020,9 +1037,8 @@ ARMBaseInstrInfo::duplicate(MachineInstr *Orig, MachineFunction &MF) const { return MI; } -bool ARMBaseInstrInfo::isIdentical(const MachineInstr *MI0, - const MachineInstr *MI1, - const MachineRegisterInfo *MRI) const { +bool ARMBaseInstrInfo::produceSameValue(const MachineInstr *MI0, + const MachineInstr *MI1) const { int Opcode = MI0->getOpcode(); if (Opcode == ARM::t2LDRpci || Opcode == ARM::t2LDRpci_pic || @@ -1051,7 +1067,7 @@ bool ARMBaseInstrInfo::isIdentical(const MachineInstr *MI0, return ACPV0->hasSameValue(ACPV1); } - return TargetInstrInfoImpl::isIdentical(MI0, MI1, MRI); + return MI0->isIdenticalTo(MI1, MachineInstr::IgnoreVRegDefs); } /// getInstrPredicate - If instruction is predicated, returns its predicate diff --git a/lib/Target/ARM/ARMBaseInstrInfo.h b/lib/Target/ARM/ARMBaseInstrInfo.h index 0d9d4a755b..01942319b2 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.h +++ b/lib/Target/ARM/ARMBaseInstrInfo.h @@ -289,8 +289,8 @@ public: MachineInstr *duplicate(MachineInstr *Orig, MachineFunction &MF) const; - virtual bool isIdentical(const MachineInstr *MI, const MachineInstr *Other, - const MachineRegisterInfo *MRI) const; + virtual bool produceSameValue(const MachineInstr *MI0, + const MachineInstr *MI1) const; }; static inline @@ -332,7 +332,7 @@ bool isJumpTableBranchOpcode(int Opc) { static inline bool isIndirectBranchOpcode(int Opc) { - return Opc == ARM::BRIND || Opc == ARM::tBRIND; + return Opc == ARM::BRIND || Opc == ARM::MOVPCRX || Opc == ARM::tBRIND; } /// getInstrPredicate - If instruction is predicated, returns its predicate diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp index cb0bd1dbd2..577c36318f 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp +++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp @@ -513,7 +513,7 @@ cannotEliminateFrame(const MachineFunction &MF) const { } /// estimateStackSize - Estimate and return the size of the frame. -static unsigned estimateStackSize(MachineFunction &MF, MachineFrameInfo *MFI) { +static unsigned estimateStackSize(MachineFunction &MF) { const MachineFrameInfo *FFI = MF.getFrameInfo(); int Offset = 0; for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) { @@ -583,14 +583,6 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, SmallVector UnspilledCS2GPRs; ARMFunctionInfo *AFI = MF.getInfo(); - - // Calculate and set max stack object alignment early, so we can decide - // whether we will need stack realignment (and thus FP). - if (RealignStack) { - MachineFrameInfo *MFI = MF.getFrameInfo(); - MFI->calculateMaxStackAlignment(); - } - // Spill R4 if Thumb2 function requires stack realignment - it will be used as // scratch register. // FIXME: It will be better just to find spare register here. @@ -679,8 +671,16 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, } } + // If any of the stack slot references may be out of range of an immediate + // offset, make sure a register (or a spill slot) is available for the + // register scavenger. Note that if we're indexing off the frame pointer, the + // effective stack size is 4 bytes larger since the FP points to the stack + // slot of the previous FP. + bool BigStack = RS && + estimateStackSize(MF) + (hasFP(MF) ? 4 : 0) >= estimateRSStackSizeLimit(MF); + bool ExtraCSSpill = false; - if (!CanEliminateFrame || cannotEliminateFrame(MF)) { + if (BigStack || !CanEliminateFrame || cannotEliminateFrame(MF)) { AFI->setHasStackFrame(true); // If LR is not spilled, but at least one of R4, R5, R6, and R7 is spilled. @@ -735,51 +735,43 @@ ARMBaseRegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, // callee-saved register or reserve a special spill slot to facilitate // register scavenging. Thumb1 needs a spill slot for stack pointer // adjustments also, even when the frame itself is small. - if (RS && !ExtraCSSpill) { - MachineFrameInfo *MFI = MF.getFrameInfo(); - // If any of the stack slot references may be out of range of an - // immediate offset, make sure a register (or a spill slot) is - // available for the register scavenger. Note that if we're indexing - // off the frame pointer, the effective stack size is 4 bytes larger - // since the FP points to the stack slot of the previous FP. - if (estimateStackSize(MF, MFI) + (hasFP(MF) ? 4 : 0) - >= estimateRSStackSizeLimit(MF)) { - // If any non-reserved CS register isn't spilled, just spill one or two - // extra. That should take care of it! - unsigned NumExtras = TargetAlign / 4; - SmallVector Extras; - while (NumExtras && !UnspilledCS1GPRs.empty()) { - unsigned Reg = UnspilledCS1GPRs.back(); - UnspilledCS1GPRs.pop_back(); + if (BigStack && !ExtraCSSpill) { + // If any non-reserved CS register isn't spilled, just spill one or two + // extra. That should take care of it! + unsigned NumExtras = TargetAlign / 4; + SmallVector Extras; + while (NumExtras && !UnspilledCS1GPRs.empty()) { + unsigned Reg = UnspilledCS1GPRs.back(); + UnspilledCS1GPRs.pop_back(); + if (!isReservedReg(MF, Reg)) { + Extras.push_back(Reg); + NumExtras--; + } + } + // For non-Thumb1 functions, also check for hi-reg CS registers + if (!AFI->isThumb1OnlyFunction()) { + while (NumExtras && !UnspilledCS2GPRs.empty()) { + unsigned Reg = UnspilledCS2GPRs.back(); + UnspilledCS2GPRs.pop_back(); if (!isReservedReg(MF, Reg)) { Extras.push_back(Reg); NumExtras--; } } - // For non-Thumb1 functions, also check for hi-reg CS registers - if (!AFI->isThumb1OnlyFunction()) { - while (NumExtras && !UnspilledCS2GPRs.empty()) { - unsigned Reg = UnspilledCS2GPRs.back(); - UnspilledCS2GPRs.pop_back(); - if (!isReservedReg(MF, Reg)) { - Extras.push_back(Reg); - NumExtras--; - } - } - } - if (Extras.size() && NumExtras == 0) { - for (unsigned i = 0, e = Extras.size(); i != e; ++i) { - MF.getRegInfo().setPhysRegUsed(Extras[i]); - AFI->setCSRegisterIsSpilled(Extras[i]); - } - } else if (!AFI->isThumb1OnlyFunction()) { - // note: Thumb1 functions spill to R12, not the stack. - // Reserve a slot closest to SP or frame pointer. - const TargetRegisterClass *RC = ARM::GPRRegisterClass; - RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), - RC->getAlignment(), - false)); + } + if (Extras.size() && NumExtras == 0) { + for (unsigned i = 0, e = Extras.size(); i != e; ++i) { + MF.getRegInfo().setPhysRegUsed(Extras[i]); + AFI->setCSRegisterIsSpilled(Extras[i]); } + } else if (!AFI->isThumb1OnlyFunction()) { + // note: Thumb1 functions spill to R12, not the stack. Reserve a slot + // closest to SP or frame pointer. + const TargetRegisterClass *RC = ARM::GPRRegisterClass; + MachineFrameInfo *MFI = MF.getFrameInfo(); + RS->setScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(), + RC->getAlignment(), + false)); } } } @@ -1093,6 +1085,15 @@ hasReservedCallFrame(MachineFunction &MF) const { return !MF.getFrameInfo()->hasVarSizedObjects(); } +// canSimplifyCallFramePseudos - If there is a reserved call frame, the +// call frame pseudos can be simplified. Unlike most targets, having a FP +// is not sufficient here since we still may reference some objects via SP +// even when FP is available in Thumb2 mode. +bool ARMBaseRegisterInfo:: +canSimplifyCallFramePseudos(MachineFunction &MF) const { + return hasReservedCallFrame(MF) || MF.getFrameInfo()->hasVarSizedObjects(); +} + static void emitSPUpdate(bool isARM, MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, @@ -1127,13 +1128,14 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, ARMFunctionInfo *AFI = MF.getInfo(); assert(!AFI->isThumb1OnlyFunction() && - "This eliminateCallFramePseudoInstr does not suppor Thumb1!"); + "This eliminateCallFramePseudoInstr does not support Thumb1!"); bool isARM = !AFI->isThumbFunction(); // Replace the pseudo instruction with a new instruction... unsigned Opc = Old->getOpcode(); - ARMCC::CondCodes Pred = (ARMCC::CondCodes)Old->getOperand(1).getImm(); - // FIXME: Thumb2 version of ADJCALLSTACKUP and ADJCALLSTACKDOWN? + int PIdx = Old->findFirstPredOperandIdx(); + ARMCC::CondCodes Pred = (PIdx == -1) + ? ARMCC::AL : (ARMCC::CondCodes)Old->getOperand(PIdx).getImm(); if (Opc == ARM::ADJCALLSTACKDOWN || Opc == ARM::tADJCALLSTACKDOWN) { // Note: PredReg is operand 2 for ADJCALLSTACKDOWN. unsigned PredReg = Old->getOperand(2).getReg(); @@ -1157,7 +1159,6 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MachineInstr &MI = *II; MachineBasicBlock &MBB = *MI.getParent(); MachineFunction &MF = *MBB.getParent(); - const MachineFrameInfo *MFI = MF.getFrameInfo(); ARMFunctionInfo *AFI = MF.getInfo(); assert(!AFI->isThumb1OnlyFunction() && "This eliminateFrameIndex does not support Thumb1!"); @@ -1168,12 +1169,12 @@ ARMBaseRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, } int FrameIndex = MI.getOperand(i).getIndex(); - int Offset = MFI->getObjectOffset(FrameIndex) + MFI->getStackSize() + SPAdj; unsigned FrameReg; - Offset = getFrameIndexReference(MF, FrameIndex, FrameReg); + int Offset = getFrameIndexReference(MF, FrameIndex, FrameReg); if (FrameReg != ARM::SP) SPAdj = 0; + Offset += SPAdj; // Modify MI as necessary to handle as much of 'Offset' as possible bool Done = false; @@ -1264,7 +1265,7 @@ emitPrologue(MachineFunction &MF) const { MachineFrameInfo *MFI = MF.getFrameInfo(); ARMFunctionInfo *AFI = MF.getInfo(); assert(!AFI->isThumb1OnlyFunction() && - "This emitPrologue does not suppor Thumb1!"); + "This emitPrologue does not support Thumb1!"); bool isARM = !AFI->isThumbFunction(); unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); unsigned NumBytes = MFI->getStackSize(); @@ -1349,7 +1350,9 @@ emitPrologue(MachineFunction &MF) const { unsigned DPRCSOffset = NumBytes - (GPRCS1Size + GPRCS2Size + DPRCSSize); unsigned GPRCS2Offset = DPRCSOffset + DPRCSSize; unsigned GPRCS1Offset = GPRCS2Offset + GPRCS2Size; - AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + NumBytes); + if (STI.isTargetDarwin() || hasFP(MF)) + AFI->setFramePtrSpillOffset(MFI->getObjectOffset(FramePtrSpillFI) + + NumBytes); AFI->setGPRCalleeSavedArea1Offset(GPRCS1Offset); AFI->setGPRCalleeSavedArea2Offset(GPRCS2Offset); AFI->setDPRCalleeSavedAreaOffset(DPRCSOffset); @@ -1425,7 +1428,7 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineFrameInfo *MFI = MF.getFrameInfo(); ARMFunctionInfo *AFI = MF.getInfo(); assert(!AFI->isThumb1OnlyFunction() && - "This emitEpilogue does not suppor Thumb1!"); + "This emitEpilogue does not support Thumb1!"); bool isARM = !AFI->isThumbFunction(); unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.h b/lib/Target/ARM/ARMBaseRegisterInfo.h index 33ba21dcb8..64f6ff1cb3 100644 --- a/lib/Target/ARM/ARMBaseRegisterInfo.h +++ b/lib/Target/ARM/ARMBaseRegisterInfo.h @@ -138,6 +138,7 @@ public: virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const; virtual bool hasReservedCallFrame(MachineFunction &MF) const; + virtual bool canSimplifyCallFramePseudos(MachineFunction &MF) const; virtual void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp index bd703f4f41..21c6cb397d 100644 --- a/lib/Target/ARM/ARMCodeEmitter.cpp +++ b/lib/Target/ARM/ARMCodeEmitter.cpp @@ -86,6 +86,7 @@ namespace { void emitWordLE(unsigned Binary); void emitDWordLE(uint64_t Binary); void emitConstPoolInstruction(const MachineInstr &MI); + void emitMOVi32immInstruction(const MachineInstr &MI); void emitMOVi2piecesInstruction(const MachineInstr &MI); void emitLEApcrelJTInstruction(const MachineInstr &MI); void emitPseudoMoveInstruction(const MachineInstr &MI); @@ -143,6 +144,15 @@ namespace { return getMachineOpValue(MI, MI.getOperand(OpIdx)); } + /// getMovi32Value - Return binary encoding of operand for movw/movt. If the + /// machine operand requires relocation, record the relocation and return zero. + unsigned getMovi32Value(const MachineInstr &MI,const MachineOperand &MO, + unsigned Reloc); + unsigned getMovi32Value(const MachineInstr &MI, unsigned OpIdx, + unsigned Reloc) { + return getMovi32Value(MI, MI.getOperand(OpIdx), Reloc); + } + /// getShiftOp - Return the shift opcode (bit[6:5]) of the immediate value. /// unsigned getShiftOp(unsigned Imm) const ; @@ -214,6 +224,54 @@ unsigned ARMCodeEmitter::getShiftOp(unsigned Imm) const { return 0; } +/// getMovi32Value - Return binary encoding of operand for movw/movt. If the +/// machine operand requires relocation, record the relocation and return zero. +unsigned ARMCodeEmitter::getMovi32Value(const MachineInstr &MI, + const MachineOperand &MO, + unsigned Reloc) { + assert(((Reloc == ARM::reloc_arm_movt) || (Reloc == ARM::reloc_arm_movw)) + && "Relocation to this function should be for movt or movw"); + switch(MO.getType()) { + case MachineOperand::MO_Register: + return ARMRegisterInfo::getRegisterNumbering(MO.getReg()); + break; + + case MachineOperand::MO_Immediate: + return static_cast(MO.getImm()); + break; + + case MachineOperand::MO_FPImmediate: + return static_cast( + MO.getFPImm()->getValueAPF().bitcastToAPInt().getLimitedValue()); + break; + + case MachineOperand::MO_MachineBasicBlock: + emitMachineBasicBlock(MO.getMBB(), Reloc); + break; + + case MachineOperand::MO_ConstantPoolIndex: + emitConstPoolAddress(MO.getIndex(), Reloc); + break; + + case MachineOperand::MO_JumpTableIndex: + emitJumpTableAddress(MO.getIndex(), Reloc); + break; + + case MachineOperand::MO_ExternalSymbol: + emitExternalSymbolAddress(MO.getSymbolName(), Reloc); + break; + + case MachineOperand::MO_GlobalAddress: + emitGlobalAddress(MO.getGlobal(), Reloc, true, false); + break; + + default: + llvm_unreachable("Unsupported immediate operand type for movw/movt"); + break; + } + return 0; +} + /// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI, @@ -433,6 +491,41 @@ void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) { } } +void ARMCodeEmitter::emitMOVi32immInstruction(const MachineInstr &MI) { + const MachineOperand &MO0 = MI.getOperand(0); + const MachineOperand &MO1 = MI.getOperand(1); + + unsigned Lo16 = getMovi32Value(MI, MO1, ARM::reloc_arm_movw) & 0xFFFF; + + // Emit the 'mov' instruction. + unsigned Binary = 0x30 << 20; // mov: Insts{27-20} = 0b00110000 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + // Encode imm. + Binary |= Lo16 & 0xFFF; + Binary |= ((Lo16 >> 12) & 0xF) << 16; // imm4:imm12, Insts[19-16] = imm4, Insts[11-0] = imm12 + emitWordLE(Binary); + + unsigned Hi16 = (getMovi32Value(MI, MO1, ARM::reloc_arm_movt) >> 16) & 0xFFFF; + // Emit the 'mov' instruction. + Binary = 0x34 << 20; // movt: Insts[27-20] = 0b00110100 + + // Set the conditional execution predicate. + Binary |= II->getPredicate(&MI) << ARMII::CondShift; + + // Encode Rd. + Binary |= getMachineOpValue(MI, MO0) << ARMII::RegRdShift; + + Binary |= Hi16 & 0xFFF; + Binary |= ((Hi16 >> 12) & 0xF) << 16; + emitWordLE(Binary); +} + void ARMCodeEmitter::emitMOVi2piecesInstruction(const MachineInstr &MI) { const MachineOperand &MO0 = MI.getOperand(0); const MachineOperand &MO1 = MI.getOperand(1); @@ -552,7 +645,6 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { switch (Opcode) { default: llvm_unreachable("ARMCodeEmitter::emitPseudoInstruction"); - // FIXME: Add support for MOVimm32. case TargetOpcode::INLINEASM: { // We allow inline assembler nodes with empty bodies - they can // implicitly define registers, which is ok for JIT. @@ -599,6 +691,11 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) { emitMiscLoadStoreInstruction(MI, ARM::PC); break; } + + case ARM::MOVi32imm: + emitMOVi32immInstruction(MI); + break; + case ARM::MOVi2pieces: // Two instructions to materialize a constant. emitMOVi2piecesInstruction(MI); @@ -1138,7 +1235,7 @@ void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) { // Set the conditional execution predicate Binary |= II->getPredicate(&MI) << ARMII::CondShift; - if (TID.Opcode == ARM::BX_RET) + if (TID.Opcode == ARM::BX_RET || TID.Opcode == ARM::MOVPCLR) // The return register is LR. Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR); else diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index a458269b7c..013e00ade7 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -65,7 +65,7 @@ public: } SDNode *Select(SDNode *N); - virtual void InstructionSelect(); + bool SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &A, SDValue &B, SDValue &C); bool SelectAddrMode2(SDNode *Op, SDValue N, SDValue &Base, @@ -201,11 +201,6 @@ static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { } -void ARMDAGToDAGISel::InstructionSelect() { - SelectRoot(*CurDAG); - CurDAG->RemoveDeadNodes(); -} - bool ARMDAGToDAGISel::SelectShifterOperandReg(SDNode *Op, SDValue N, SDValue &BaseReg, diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 614e684345..6a2c6bbbb7 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -294,6 +294,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM) setTargetDAGCombine(ISD::SIGN_EXTEND); setTargetDAGCombine(ISD::ZERO_EXTEND); setTargetDAGCombine(ISD::ANY_EXTEND); + setTargetDAGCombine(ISD::SELECT_CC); } computeRegisterProperties(); @@ -544,6 +545,8 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const { case ARMISD::VZIP: return "ARMISD::VZIP"; case ARMISD::VUZP: return "ARMISD::VUZP"; case ARMISD::VTRN: return "ARMISD::VTRN"; + case ARMISD::FMAX: return "ARMISD::FMAX"; + case ARMISD::FMIN: return "ARMISD::FMIN"; } } @@ -863,7 +866,8 @@ ARMTargetLowering::LowerMemOpCallTo(SDValue Chain, return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, dl); } return DAG.getStore(Chain, dl, Arg, PtrOff, - PseudoSourceValue::getStack(), LocMemOffset); + PseudoSourceValue::getStack(), LocMemOffset, + false, false, 0); } void ARMTargetLowering::PassF64ArgInRegs(DebugLoc dl, SelectionDAG &DAG, @@ -920,7 +924,7 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // These operations are automatically eliminated by the prolog/epilog pass Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); - SDValue StackPtr = DAG.getRegister(ARM::SP, MVT::i32); + SDValue StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy()); RegsToPassVector RegsToPass; SmallVector MemOpChains; @@ -969,8 +973,6 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, VA, ArgLocs[++i], StackPtr, MemOpChains, Flags); } else { assert(VA.isMemLoc()); - if (StackPtr.getNode() == 0) - StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy()); MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Op1, dl, DAG, VA, Flags)); @@ -983,8 +985,6 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); } else { assert(VA.isMemLoc()); - if (StackPtr.getNode() == 0) - StackPtr = DAG.getCopyFromReg(Chain, dl, ARM::SP, getPointerTy()); MemOpChains.push_back(LowerMemOpCallTo(Chain, StackPtr, Arg, dl, DAG, VA, Flags)); @@ -1031,7 +1031,8 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); Callee = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), CPAddr, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); Callee = DAG.getNode(ARMISD::PIC_ADD, dl, getPointerTy(), Callee, PICLabel); @@ -1052,7 +1053,8 @@ ARMTargetLowering::LowerCall(SDValue Chain, SDValue Callee, CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); Callee = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), CPAddr, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); Callee = DAG.getNode(ARMISD::PIC_ADD, dl, getPointerTy(), Callee, PICLabel); @@ -1238,7 +1240,8 @@ SDValue ARMTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) { } CPAddr = DAG.getNode(ARMISD::Wrapper, DL, PtrVT, CPAddr); SDValue Result = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), CPAddr, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); if (RelocM == Reloc::Static) return Result; SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); @@ -1261,7 +1264,8 @@ ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, SDValue Argument = DAG.getTargetConstantPool(CPV, PtrVT, 4); Argument = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Argument); Argument = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Argument, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); SDValue Chain = Argument.getValue(1); SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); @@ -1278,8 +1282,7 @@ ARMTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, LowerCallTo(Chain, (const Type *) Type::getInt32Ty(*DAG.getContext()), false, false, false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/true, - DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, dl, - DAG.GetOrdering(Chain.getNode())); + DAG.getExternalSymbol("__tls_get_addr", PtrVT), Args, DAG, dl); return CallResult.first; } @@ -1308,21 +1311,24 @@ ARMTargetLowering::LowerToTLSExecModels(GlobalAddressSDNode *GA, Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4); Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset); Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); Chain = Offset.getValue(1); SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); Offset = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Offset, PICLabel); Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); } else { // local exec model ARMConstantPoolValue *CPV = new ARMConstantPoolValue(GV, "tpoff"); Offset = DAG.getTargetConstantPool(CPV, PtrVT, 4); Offset = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, Offset); Offset = DAG.getLoad(PtrVT, dl, Chain, Offset, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); } // The address of the thread local variable is the add of the thread @@ -1358,13 +1364,15 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); SDValue Chain = Result.getValue(1); SDValue GOT = DAG.getGLOBAL_OFFSET_TABLE(PtrVT); Result = DAG.getNode(ISD::ADD, dl, PtrVT, Result, GOT); if (!UseGOTOFF) Result = DAG.getLoad(PtrVT, dl, Chain, Result, - PseudoSourceValue::getGOT(), 0); + PseudoSourceValue::getGOT(), 0, + false, false, 0); return Result; } else { // If we have T2 ops, we can materialize the address directly via movt/movw @@ -1376,7 +1384,8 @@ SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, SDValue CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); } } } @@ -1403,7 +1412,8 @@ SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op, CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); SDValue Chain = Result.getValue(1); if (RelocM == Reloc::PIC_) { @@ -1413,7 +1423,8 @@ SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op, if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) Result = DAG.getLoad(PtrVT, dl, Chain, Result, - PseudoSourceValue::getGOT(), 0); + PseudoSourceValue::getGOT(), 0, + false, false, 0); return Result; } @@ -1434,7 +1445,8 @@ SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op, SDValue CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 4); CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); SDValue PICLabel = DAG.getConstant(ARMPCLabelIndex, MVT::i32); return DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); } @@ -1467,7 +1479,8 @@ ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG, CPAddr = DAG.getNode(ARMISD::Wrapper, dl, MVT::i32, CPAddr); SDValue Result = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), CPAddr, - PseudoSourceValue::getConstantPool(), 0); + PseudoSourceValue::getConstantPool(), 0, + false, false, 0); SDValue Chain = Result.getValue(1); if (RelocM == Reloc::PIC_) { @@ -1515,7 +1528,8 @@ static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); const Value *SV = cast(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0); + return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0, + false, false, 0); } SDValue @@ -1592,7 +1606,8 @@ ARMTargetLowering::GetF64FormalArgument(CCValAssign &VA, CCValAssign &NextVA, // Create load node to retrieve arguments from the stack. SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); ArgValue2 = DAG.getLoad(MVT::i32, dl, Root, FIN, - PseudoSourceValue::getFixedStack(FI), 0); + PseudoSourceValue::getFixedStack(FI), 0, + false, false, 0); } else { Reg = MF.addLiveIn(NextVA.getLocReg(), RC); ArgValue2 = DAG.getCopyFromReg(Root, dl, Reg, MVT::i32); @@ -1707,7 +1722,8 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, // Create load nodes to retrieve arguments from the stack. SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, - PseudoSourceValue::getFixedStack(FI), 0)); + PseudoSourceValue::getFixedStack(FI), 0, + false, false, 0)); } } @@ -1745,7 +1761,8 @@ ARMTargetLowering::LowerFormalArguments(SDValue Chain, unsigned VReg = MF.addLiveIn(GPRArgRegs[NumGPRs], RC); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, - PseudoSourceValue::getFixedStack(VarArgsFrameIndex), 0); + PseudoSourceValue::getFixedStack(VarArgsFrameIndex), 0, + false, false, 0); MemOps.push_back(Store); FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN, DAG.getConstant(4, getPointerTy())); @@ -1939,13 +1956,14 @@ SDValue ARMTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) { } if (getTargetMachine().getRelocationModel() == Reloc::PIC_) { Addr = DAG.getLoad((EVT)MVT::i32, dl, Chain, Addr, - PseudoSourceValue::getJumpTable(), 0); + PseudoSourceValue::getJumpTable(), 0, + false, false, 0); Chain = Addr.getValue(1); Addr = DAG.getNode(ISD::ADD, dl, PTy, Addr, Table); return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI, UId); } else { Addr = DAG.getLoad(PTy, dl, Chain, Addr, - PseudoSourceValue::getJumpTable(), 0); + PseudoSourceValue::getJumpTable(), 0, false, false, 0); Chain = Addr.getValue(1); return DAG.getNode(ARMISD::BR_JT, dl, MVT::Other, Chain, Addr, JTI, UId); } @@ -1993,7 +2011,8 @@ SDValue ARMTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { ? ARM::R7 : ARM::R11; SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); while (Depth--) - FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0); + FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0, + false, false, 0); return FrameAddr; } @@ -2038,7 +2057,7 @@ ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, Loads[i] = DAG.getLoad(VT, dl, Chain, DAG.getNode(ISD::ADD, dl, MVT::i32, Src, DAG.getConstant(SrcOff, MVT::i32)), - SrcSV, SrcSVOff + SrcOff); + SrcSV, SrcSVOff + SrcOff, false, false, 0); TFOps[i] = Loads[i].getValue(1); SrcOff += VTSize; } @@ -2047,9 +2066,9 @@ ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, for (i = 0; i < MAX_LOADS_IN_LDM && EmittedNumMemOps + i < NumMemOps; ++i) { TFOps[i] = DAG.getStore(Chain, dl, Loads[i], - DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, - DAG.getConstant(DstOff, MVT::i32)), - DstSV, DstSVOff + DstOff); + DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, + DAG.getConstant(DstOff, MVT::i32)), + DstSV, DstSVOff + DstOff, false, false, 0); DstOff += VTSize; } Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &TFOps[0], i); @@ -2075,7 +2094,7 @@ ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, Loads[i] = DAG.getLoad(VT, dl, Chain, DAG.getNode(ISD::ADD, dl, MVT::i32, Src, DAG.getConstant(SrcOff, MVT::i32)), - SrcSV, SrcSVOff + SrcOff); + SrcSV, SrcSVOff + SrcOff, false, false, 0); TFOps[i] = Loads[i].getValue(1); ++i; SrcOff += VTSize; @@ -2097,7 +2116,7 @@ ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, TFOps[i] = DAG.getStore(Chain, dl, Loads[i], DAG.getNode(ISD::ADD, dl, MVT::i32, Dst, DAG.getConstant(DstOff, MVT::i32)), - DstSV, DstSVOff + DstOff); + DstSV, DstSVOff + DstOff, false, false, 0); ++i; DstOff += VTSize; BytesLeft -= VTSize; @@ -3835,23 +3854,106 @@ static SDValue PerformExtendCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } +/// PerformSELECT_CCCombine - Target-specific DAG combining for ISD::SELECT_CC +/// to match f32 max/min patterns to use NEON vmax/vmin instructions. +static SDValue PerformSELECT_CCCombine(SDNode *N, SelectionDAG &DAG, + const ARMSubtarget *ST) { + // If the target supports NEON, try to use vmax/vmin instructions for f32 + // selects like "x < y ? x : y". Unless the FiniteOnlyFPMath option is set, + // be careful about NaNs: NEON's vmax/vmin return NaN if either operand is + // a NaN; only do the transformation when it matches that behavior. + + // For now only do this when using NEON for FP operations; if using VFP, it + // is not obvious that the benefit outweighs the cost of switching to the + // NEON pipeline. + if (!ST->hasNEON() || !ST->useNEONForSinglePrecisionFP() || + N->getValueType(0) != MVT::f32) + return SDValue(); + + SDValue CondLHS = N->getOperand(0); + SDValue CondRHS = N->getOperand(1); + SDValue LHS = N->getOperand(2); + SDValue RHS = N->getOperand(3); + ISD::CondCode CC = cast(N->getOperand(4))->get(); + + unsigned Opcode = 0; + bool IsReversed; + if (DAG.isEqualTo(LHS, CondLHS) && DAG.isEqualTo(RHS, CondRHS)) { + IsReversed = false; // x CC y ? x : y + } else if (DAG.isEqualTo(LHS, CondRHS) && DAG.isEqualTo(RHS, CondLHS)) { + IsReversed = true ; // x CC y ? y : x + } else { + return SDValue(); + } + + bool IsUnordered; + switch (CC) { + default: break; + case ISD::SETOLT: + case ISD::SETOLE: + case ISD::SETLT: + case ISD::SETLE: + case ISD::SETULT: + case ISD::SETULE: + // If LHS is NaN, an ordered comparison will be false and the result will + // be the RHS, but vmin(NaN, RHS) = NaN. Avoid this by checking that LHS + // != NaN. Likewise, for unordered comparisons, check for RHS != NaN. + IsUnordered = (CC == ISD::SETULT || CC == ISD::SETULE); + if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS)) + break; + // For less-than-or-equal comparisons, "+0 <= -0" will be true but vmin + // will return -0, so vmin can only be used for unsafe math or if one of + // the operands is known to be nonzero. + if ((CC == ISD::SETLE || CC == ISD::SETOLE || CC == ISD::SETULE) && + !UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) + break; + Opcode = IsReversed ? ARMISD::FMAX : ARMISD::FMIN; + break; + + case ISD::SETOGT: + case ISD::SETOGE: + case ISD::SETGT: + case ISD::SETGE: + case ISD::SETUGT: + case ISD::SETUGE: + // If LHS is NaN, an ordered comparison will be false and the result will + // be the RHS, but vmax(NaN, RHS) = NaN. Avoid this by checking that LHS + // != NaN. Likewise, for unordered comparisons, check for RHS != NaN. + IsUnordered = (CC == ISD::SETUGT || CC == ISD::SETUGE); + if (!DAG.isKnownNeverNaN(IsUnordered ? RHS : LHS)) + break; + // For greater-than-or-equal comparisons, "-0 >= +0" will be true but vmax + // will return +0, so vmax can only be used for unsafe math or if one of + // the operands is known to be nonzero. + if ((CC == ISD::SETGE || CC == ISD::SETOGE || CC == ISD::SETUGE) && + !UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) + break; + Opcode = IsReversed ? ARMISD::FMIN : ARMISD::FMAX; + break; + } + + if (!Opcode) + return SDValue(); + return DAG.getNode(Opcode, N->getDebugLoc(), N->getValueType(0), LHS, RHS); +} + SDValue ARMTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { switch (N->getOpcode()) { default: break; - case ISD::ADD: return PerformADDCombine(N, DCI); - case ISD::SUB: return PerformSUBCombine(N, DCI); + case ISD::ADD: return PerformADDCombine(N, DCI); + case ISD::SUB: return PerformSUBCombine(N, DCI); case ARMISD::VMOVRRD: return PerformVMOVRRDCombine(N, DCI); - case ISD::INTRINSIC_WO_CHAIN: - return PerformIntrinsicCombine(N, DCI.DAG); + case ISD::INTRINSIC_WO_CHAIN: return PerformIntrinsicCombine(N, DCI.DAG); case ISD::SHL: case ISD::SRA: - case ISD::SRL: - return PerformShiftCombine(N, DCI.DAG, Subtarget); + case ISD::SRL: return PerformShiftCombine(N, DCI.DAG, Subtarget); case ISD::SIGN_EXTEND: case ISD::ZERO_EXTEND: - case ISD::ANY_EXTEND: - return PerformExtendCombine(N, DCI.DAG, Subtarget); + case ISD::ANY_EXTEND: return PerformExtendCombine(N, DCI.DAG, Subtarget); + case ISD::SELECT_CC: return PerformSELECT_CCCombine(N, DCI.DAG, Subtarget); } return SDValue(); } diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h index 3c5df45dc5..f8f8adc70a 100644 --- a/lib/Target/ARM/ARMISelLowering.h +++ b/lib/Target/ARM/ARMISelLowering.h @@ -131,7 +131,11 @@ namespace llvm { VREV16, // reverse elements within 16-bit halfwords VZIP, // zip (interleave) VUZP, // unzip (deinterleave) - VTRN // transpose + VTRN, // transpose + + // Floating-point max and min: + FMAX, + FMIN }; } diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 169eeed525..76595fa295 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -56,6 +56,9 @@ def NEONGetLnFrm : Format<25>; def NEONSetLnFrm : Format<26>; def NEONDupFrm : Format<27>; +def MiscFrm : Format<29>; +def ThumbMiscFrm : Format<30>; + // Misc flags. // the instruction has a Rn register operand. @@ -705,6 +708,20 @@ class AI3ldsbpr pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 0; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} + // Pre-indexed stores class AI3sthpr pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 1; // W bit + let Inst{24} = 1; // P bit + let Inst{27-25} = 0b000; +} // Post-indexed loads class AI3ldhpo pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 0; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit let Inst{24} = 0; // P bit let Inst{27-25} = 0b000; } @@ -772,7 +815,20 @@ class AI3sthpo pattern> + : I { + let Inst{4} = 1; + let Inst{5} = 1; // H bit + let Inst{6} = 1; // S bit + let Inst{7} = 1; + let Inst{20} = 0; // L bit + let Inst{21} = 0; // W bit let Inst{24} = 0; // P bit let Inst{27-25} = 0b000; } @@ -1147,6 +1203,19 @@ class T2Iidxldst opcod, bit load, bit pre, let Inst{8} = 1; // The W bit. } +// Helper class for disassembly only +// A6.3.16 & A6.3.17 +// T2Imac - Thumb2 multiply [accumulate, and absolute difference] instructions. +class T2I_mac op22_20, bits<4> op7_4, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> + : T2I { + let Inst{31-27} = 0b11111; + let Inst{26-24} = 0b011; + let Inst{23} = long; + let Inst{22-20} = op22_20; + let Inst{7-4} = op7_4; +} + // Tv5Pat - Same as Pat<>, but requires V5T Thumb mode. class Tv5Pat : Pat { list Predicates = [IsThumb1Only, HasV5T]; @@ -1324,6 +1393,15 @@ class AVConv1I opcod1, bits<2> opcod2, bits<4> opcod3, bits<4> opcod4, let Inst{4} = 0; } +// VFP conversion between floating-point and fixed-point +class AVConv1XI op1, bits<2> op2, bits<4> op3, bits<4> op4, bit op5, + dag oops, dag iops, InstrItinClass itin, string opc, string asm, + list pattern> + : AVConv1I { + // size (fixed-point number): sx == 0 ? 16 : 32 + let Inst{7} = op5; // sx +} + // VFP conversion instructions, if no NEON class AVConv1In opcod1, bits<2> opcod2, bits<4> opcod3, bits<4> opcod4, dag oops, dag iops, InstrItinClass itin, diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 852c74e3b8..3812abaee1 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -113,6 +113,8 @@ def ARMrbit : SDNode<"ARMISD::RBIT", SDTIntUnaryOp>; //===----------------------------------------------------------------------===// // ARM Instruction Predicate Definitions. // +def HasV4T : Predicate<"Subtarget->hasV4TOps()">; +def NoV4T : Predicate<"!Subtarget->hasV4TOps()">; def HasV5T : Predicate<"Subtarget->hasV5TOps()">; def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">; def HasV6 : Predicate<"Subtarget->hasV6Ops()">; @@ -130,8 +132,6 @@ def IsThumb2 : Predicate<"Subtarget->isThumb2()">; def IsARM : Predicate<"!Subtarget->isThumb()">; def IsDarwin : Predicate<"Subtarget->isTargetDarwin()">; def IsNotDarwin : Predicate<"!Subtarget->isTargetDarwin()">; -def CarryDefIsUnused : Predicate<"!N->hasAnyUseOfValue(1)">; -def CarryDefIsUsed : Predicate<"N->hasAnyUseOfValue(1)">; // FIXME: Eventually this will be just "hasV6T2Ops". def UseMovt : Predicate<"Subtarget->useMovt()">; @@ -176,7 +176,7 @@ def imm16_31 : PatLeaf<(i32 imm), [{ return (int32_t)N->getZExtValue() >= 16 && (int32_t)N->getZExtValue() < 32; }]>; -def so_imm_neg : +def so_imm_neg : PatLeaf<(imm), [{ return ARM_AM::getSOImmVal(-(int)N->getZExtValue()) != -1; }], so_imm_neg_XFORM>; @@ -194,7 +194,7 @@ def sext_16_node : PatLeaf<(i32 GPR:$a), [{ /// bf_inv_mask_imm predicate - An AND mask to clear an arbitrary width bitfield /// e.g., 0xf000ffff def bf_inv_mask_imm : Operand, - PatLeaf<(imm), [{ + PatLeaf<(imm), [{ uint32_t v = (uint32_t)N->getZExtValue(); if (v == 0xffffffff) return 0; @@ -227,7 +227,7 @@ def lo16AllZero : PatLeaf<(i32 imm), [{ return (((uint32_t)N->getZExtValue()) & 0xFFFFUL) == 0; }], hi16>; -/// imm0_65535 predicate - True if the 32-bit immediate is in the range +/// imm0_65535 predicate - True if the 32-bit immediate is in the range /// [0.65535]. def imm0_65535 : PatLeaf<(i32 imm), [{ return (uint32_t)N->getZExtValue() < 65536; @@ -236,6 +236,21 @@ def imm0_65535 : PatLeaf<(i32 imm), [{ class BinOpFrag : PatFrag<(ops node:$LHS, node:$RHS), res>; class UnOpFrag : PatFrag<(ops node:$Src), res>; +/// adde and sube predicates - True based on whether the carry flag output +/// will be needed or not. +def adde_dead_carry : + PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS), + [{return !N->hasAnyUseOfValue(1);}]>; +def sube_dead_carry : + PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS), + [{return !N->hasAnyUseOfValue(1);}]>; +def adde_live_carry : + PatFrag<(ops node:$LHS, node:$RHS), (adde node:$LHS, node:$RHS), + [{return N->hasAnyUseOfValue(1);}]>; +def sube_live_carry : + PatFrag<(ops node:$LHS, node:$RHS), (sube node:$LHS, node:$RHS), + [{return N->hasAnyUseOfValue(1);}]>; + //===----------------------------------------------------------------------===// // Operand Definitions. // @@ -501,6 +516,22 @@ multiclass AI_unary_rrot opcod, string opc, PatFrag opnode> { } } +multiclass AI_unary_rrot_np opcod, string opc> { + def r : AExtI, + Requires<[IsARM, HasV6]> { + let Inst{11-10} = 0b00; + let Inst{19-16} = 0b1111; + } + def r_rot : AExtI, + Requires<[IsARM, HasV6]> { + let Inst{19-16} = 0b1111; + } +} + /// AI_bin_rrot - A binary operation with two forms: one whose operand is a /// register and one whose operand is a register rotated by 8/16/24. multiclass AI_bin_rrot opcod, string opc, PatFrag opnode> { @@ -510,13 +541,29 @@ multiclass AI_bin_rrot opcod, string opc, PatFrag opnode> { Requires<[IsARM, HasV6]> { let Inst{11-10} = 0b00; } - def rr_rot : AExtI, Requires<[IsARM, HasV6]>; } +// For disassembly only. +multiclass AI_bin_rrot_np opcod, string opc> { + def rr : AExtI, + Requires<[IsARM, HasV6]> { + let Inst{11-10} = 0b00; + } + def rr_rot : AExtI, + Requires<[IsARM, HasV6]>; +} + /// AI1_adde_sube_irs - Define instructions and patterns for adde and sube. let Uses = [CPSR] in { multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, @@ -524,13 +571,13 @@ multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, def ri : AsI1, - Requires<[IsARM, CarryDefIsUnused]> { + Requires<[IsARM]> { let Inst{25} = 1; } def rr : AsI1, - Requires<[IsARM, CarryDefIsUnused]> { + Requires<[IsARM]> { let isCommutable = Commutable; let Inst{11-4} = 0b00000000; let Inst{25} = 0; @@ -538,7 +585,7 @@ multiclass AI1_adde_sube_irs opcod, string opc, PatFrag opnode, def rs : AsI1, - Requires<[IsARM, CarryDefIsUnused]> { + Requires<[IsARM]> { let Inst{25} = 0; } } @@ -549,16 +596,14 @@ multiclass AI1_adde_sube_s_irs opcod, string opc, PatFrag opnode, def Sri : AXI1, - Requires<[IsARM, CarryDefIsUsed]> { - let Defs = [CPSR]; + Requires<[IsARM]> { let Inst{20} = 1; let Inst{25} = 1; } def Srr : AXI1, - Requires<[IsARM, CarryDefIsUsed]> { - let Defs = [CPSR]; + Requires<[IsARM]> { let Inst{11-4} = 0b00000000; let Inst{20} = 1; let Inst{25} = 0; @@ -566,8 +611,7 @@ multiclass AI1_adde_sube_s_irs opcod, string opc, PatFrag opnode, def Srs : AXI1, - Requires<[IsARM, CarryDefIsUsed]> { - let Defs = [CPSR]; + Requires<[IsARM]> { let Inst{20} = 1; let Inst{25} = 0; } @@ -593,18 +637,153 @@ PseudoInst<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size), NoItinerary, "${instid:label} ${cpidx:cpentry}", []>; -let Defs = [SP], Uses = [SP] in { +// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE +// from removing one half of the matched pairs. That breaks PEI, which assumes +// these will always be in pairs, and asserts if it finds otherwise. Better way? +let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { def ADJCALLSTACKUP : PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2, pred:$p), NoItinerary, "@ ADJCALLSTACKUP $amt1", [(ARMcallseq_end timm:$amt1, timm:$amt2)]>; -def ADJCALLSTACKDOWN : +def ADJCALLSTACKDOWN : PseudoInst<(outs), (ins i32imm:$amt, pred:$p), NoItinerary, "@ ADJCALLSTACKDOWN $amt", [(ARMcallseq_start timm:$amt)]>; } +def NOP : AI<(outs), (ins), MiscFrm, NoItinerary, "nop", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{7-0} = 0b00000000; +} + +def YIELD : AI<(outs), (ins), MiscFrm, NoItinerary, "yield", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{7-0} = 0b00000001; +} + +def WFE : AI<(outs), (ins), MiscFrm, NoItinerary, "wfe", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{7-0} = 0b00000010; +} + +def WFI : AI<(outs), (ins), MiscFrm, NoItinerary, "wfi", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{7-0} = 0b00000011; +} + +def SEL : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm, NoItinerary, "sel", + "\t$dst, $a, $b", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6]> { + let Inst{27-20} = 0b01101000; + let Inst{7-4} = 0b1011; +} + +def SEV : AI<(outs), (ins), MiscFrm, NoItinerary, "sev", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-16} = 0b001100100000; + let Inst{7-0} = 0b00000100; +} + +// The i32imm operand $val can be used by a debugger to store more information +// about the breakpoint. +def BKPT : AI<(outs), (ins i32imm:$val), MiscFrm, NoItinerary, "bkpt", "\t$val", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM]> { + let Inst{27-20} = 0b00010010; + let Inst{7-4} = 0b0111; +} + +// Change Processor State is a system instruction -- for disassembly only. +// The singleton $opt operand contains the following information: +// opt{4-0} = mode from Inst{4-0} +// opt{5} = changemode from Inst{17} +// opt{8-6} = AIF from Inst{8-6} +// opt{10-9} = imod from Inst{19-18} with 0b10 as enable and 0b11 as disable +def CPS : AXI<(outs),(ins i32imm:$opt), MiscFrm, NoItinerary, "cps${opt:cps}", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM]> { + let Inst{31-28} = 0b1111; + let Inst{27-20} = 0b00010000; + let Inst{16} = 0; + let Inst{5} = 0; +} + +// Preload signals the memory system of possible future data/instruction access. +// These are for disassembly only. +multiclass APreLoad { + + def i : AXI<(outs), (ins GPR:$base, i32imm:$imm), MiscFrm, NoItinerary, + !strconcat(opc, "\t[$base, $imm]"), []> { + let Inst{31-26} = 0b111101; + let Inst{25} = 0; // 0 for immediate form + let Inst{24} = data; + let Inst{22} = read; + let Inst{21-20} = 0b01; + } + + def r : AXI<(outs), (ins addrmode2:$addr), MiscFrm, NoItinerary, + !strconcat(opc, "\t$addr"), []> { + let Inst{31-26} = 0b111101; + let Inst{25} = 1; // 1 for register form + let Inst{24} = data; + let Inst{22} = read; + let Inst{21-20} = 0b01; + let Inst{4} = 0; + } +} + +defm PLD : APreLoad<1, 1, "pld">; +defm PLDW : APreLoad<1, 0, "pldw">; +defm PLI : APreLoad<0, 1, "pli">; + +def SETENDBE : AXI<(outs),(ins), MiscFrm, NoItinerary, "setend\tbe", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM]> { + let Inst{31-28} = 0b1111; + let Inst{27-20} = 0b00010000; + let Inst{16} = 1; + let Inst{9} = 1; + let Inst{7-4} = 0b0000; +} + +def SETENDLE : AXI<(outs),(ins), MiscFrm, NoItinerary, "setend\tle", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM]> { + let Inst{31-28} = 0b1111; + let Inst{27-20} = 0b00010000; + let Inst{16} = 1; + let Inst{9} = 0; + let Inst{7-4} = 0b0000; +} + +def DBG : AI<(outs), (ins i32imm:$opt), MiscFrm, NoItinerary, "dbg", "\t$opt", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV7]> { + let Inst{27-16} = 0b001100100000; + let Inst{7-4} = 0b1111; +} + +// A5.4 Permanently UNDEFINED instructions. +def TRAP : AI<(outs), (ins), MiscFrm, NoItinerary, "trap", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM]> { + let Inst{27-25} = 0b011; + let Inst{24-20} = 0b11111; + let Inst{7-5} = 0b111; + let Inst{4} = 0b1; +} + // Address computation and loads and stores in PIC mode. let isNotDuplicable = 1 in { def PICADD : AXI1<0b0100, (outs GPR:$dst), (ins GPR:$a, pclabel:$cp, pred:$p), @@ -665,7 +844,7 @@ def LEApcrelJT : AXI1<0x0, (outs GPR:$dst), "(${label}_${id}-(", "${:private}PCRELL${:uid}+8))\n"), !strconcat("${:private}PCRELL${:uid}:\n\t", - "add$p\t$dst, pc, #${:private}PCRELV${:uid}")), + "add$p\t$dst, pc, #${:private}PCRELV${:uid}")), []> { let Inst{25} = 1; } @@ -674,24 +853,50 @@ def LEApcrelJT : AXI1<0x0, (outs GPR:$dst), // Control Flow Instructions. // -let isReturn = 1, isTerminator = 1, isBarrier = 1 in - def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br, - "bx", "\tlr", [(ARMretflag)]> { - let Inst{3-0} = 0b1110; - let Inst{7-4} = 0b0001; - let Inst{19-8} = 0b111111111111; - let Inst{27-20} = 0b00010010; +let isReturn = 1, isTerminator = 1, isBarrier = 1 in { + // ARMV4T and above + def BX_RET : AI<(outs), (ins), BrMiscFrm, IIC_Br, + "bx", "\tlr", [(ARMretflag)]>, + Requires<[IsARM, HasV4T]> { + let Inst{3-0} = 0b1110; + let Inst{7-4} = 0b0001; + let Inst{19-8} = 0b111111111111; + let Inst{27-20} = 0b00010010; + } + + // ARMV4 only + def MOVPCLR : AI<(outs), (ins), BrMiscFrm, IIC_Br, + "mov", "\tpc, lr", [(ARMretflag)]>, + Requires<[IsARM, NoV4T]> { + let Inst{11-0} = 0b000000001110; + let Inst{15-12} = 0b1111; + let Inst{19-16} = 0b0000; + let Inst{27-20} = 0b00011010; + } } // Indirect branches let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { + // ARMV4T and above def BRIND : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "bx\t$dst", - [(brind GPR:$dst)]> { + [(brind GPR:$dst)]>, + Requires<[IsARM, HasV4T]> { let Inst{7-4} = 0b0001; let Inst{19-8} = 0b111111111111; let Inst{27-20} = 0b00010010; let Inst{31-28} = 0b1110; } + + // ARMV4 only + def MOVPCRX : AXI<(outs), (ins GPR:$dst), BrMiscFrm, IIC_Br, "mov\tpc, $dst", + [(brind GPR:$dst)]>, + Requires<[IsARM, NoV4T]> { + let Inst{11-4} = 0b00000000; + let Inst{15-12} = 0b1111; + let Inst{19-16} = 0b0000; + let Inst{27-20} = 0b00011010; + let Inst{31-28} = 0b1110; + } } // FIXME: remove when we have a way to marking a MI with these properties. @@ -732,14 +937,26 @@ let isCall = 1, } // ARMv4T - def BX : ABXIx2<(outs), (ins GPR:$func, variable_ops), + // Note: Restrict $func to the tGPR regclass to prevent it being in LR. + def BX : ABXIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", - [(ARMcall_nolink GPR:$func)]>, - Requires<[IsARM, IsNotDarwin]> { + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, HasV4T, IsNotDarwin]> { let Inst{7-4} = 0b0001; let Inst{19-8} = 0b111111111111; let Inst{27-20} = 0b00010010; } + + // ARMv4 + def BMOVPCRX : ABXIx2<(outs), (ins tGPR:$func, variable_ops), + IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func", + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, NoV4T, IsNotDarwin]> { + let Inst{11-4} = 0b00000000; + let Inst{15-12} = 0b1111; + let Inst{19-16} = 0b0000; + let Inst{27-20} = 0b00011010; + } } // On Darwin R9 is call-clobbered. @@ -769,13 +986,26 @@ let isCall = 1, } // ARMv4T - def BXr9 : ABXIx2<(outs), (ins GPR:$func, variable_ops), + // Note: Restrict $func to the tGPR regclass to prevent it being in LR. + def BXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", - [(ARMcall_nolink GPR:$func)]>, Requires<[IsARM, IsDarwin]> { + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, HasV4T, IsDarwin]> { let Inst{7-4} = 0b0001; let Inst{19-8} = 0b111111111111; let Inst{27-20} = 0b00010010; } + + // ARMv4 + def BMOVPCRXr9 : ABXIx2<(outs), (ins tGPR:$func, variable_ops), + IIC_Br, "mov\tlr, pc\n\tmov\tpc, $func", + [(ARMcall_nolink tGPR:$func)]>, + Requires<[IsARM, NoV4T, IsDarwin]> { + let Inst{11-4} = 0b00000000; + let Inst{15-12} = 0b1111; + let Inst{19-16} = 0b0000; + let Inst{27-20} = 0b00011010; + } } let isBranch = 1, isTerminator = 1 in { @@ -821,25 +1051,75 @@ let isBranch = 1, isTerminator = 1 in { } // isBarrier = 1 // FIXME: should be able to write a pattern for ARMBrcond, but can't use - // a two-value operand where a dag node expects two operands. :( + // a two-value operand where a dag node expects two operands. :( def Bcc : ABI<0b1010, (outs), (ins brtarget:$target), IIC_Br, "b", "\t$target", [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]>; } +// Branch and Exchange Jazelle -- for disassembly only +def BXJ : ABI<0b0001, (outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0010; + //let Inst{19-8} = 0xfff; + let Inst{7-4} = 0b0010; +} + +// Secure Monitor Call is a system instruction -- for disassembly only +def SMC : ABI<0b0001, (outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0110; + let Inst{7-4} = 0b0111; +} + +// Supervisor Call (Software Interrupt) -- for disassembly only +let isCall = 1 in { +def SVC : ABI<0b1111, (outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", + [/* For disassembly only; pattern left blank */]>; +} + +// Store Return State is a system instruction -- for disassembly only +def SRSW : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, i32imm:$mode), + NoItinerary, "srs${addr:submode}\tsp!, $mode", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{22-20} = 0b110; // W = 1 +} + +def SRS : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, i32imm:$mode), + NoItinerary, "srs${addr:submode}\tsp, $mode", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{22-20} = 0b100; // W = 0 +} + +// Return From Exception is a system instruction -- for disassembly only +def RFEW : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, GPR:$base), + NoItinerary, "rfe${addr:submode}\t$base!", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{22-20} = 0b011; // W = 1 +} + +def RFE : ABXI<{1,0,0,?}, (outs), (ins addrmode4:$addr, GPR:$base), + NoItinerary, "rfe${addr:submode}\t$base", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{22-20} = 0b001; // W = 0 +} + //===----------------------------------------------------------------------===// // Load / store Instructions. // // Load -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def LDR : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoadr, "ldr", "\t$dst, $addr", [(set GPR:$dst, (load addrmode2:$addr))]>; // Special LDR for loads from non-pc-relative constpools. -let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, - mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in def LDRcp : AI2ldw<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoadr, "ldr", "\t$dst, $addr", []>; @@ -848,7 +1128,7 @@ def LDRH : AI3ldh<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm, IIC_iLoadr, "ldrh", "\t$dst, $addr", [(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>; -def LDRB : AI2ldb<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, +def LDRB : AI2ldb<(outs GPR:$dst), (ins addrmode2:$addr), LdFrm, IIC_iLoadr, "ldrb", "\t$dst, $addr", [(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>; @@ -907,6 +1187,51 @@ def LDRSB_PRE : AI3ldsbpr<(outs GPR:$dst, GPR:$base_wb), def LDRSB_POST: AI3ldsbpo<(outs GPR:$dst, GPR:$base_wb), (ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoadru, "ldrsb", "\t$dst, [$base], $offset", "$base = $base_wb", []>; + +// For disassembly only +def LDRD_PRE : AI3lddpr<(outs GPR:$dst1, GPR:$dst2, GPR:$base_wb), + (ins addrmode3:$addr), LdMiscFrm, IIC_iLoadr, + "ldrd", "\t$dst1, $dst2, $addr!", "$addr.base = $base_wb", []>, + Requires<[IsARM, HasV5TE]>; + +// For disassembly only +def LDRD_POST : AI3lddpo<(outs GPR:$dst1, GPR:$dst2, GPR:$base_wb), + (ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoadr, + "ldrd", "\t$dst1, $dst2, [$base], $offset", "$base = $base_wb", []>, + Requires<[IsARM, HasV5TE]>; + +} + +// LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only. + +def LDRT : AI2ldwpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, am2offset:$offset), LdFrm, IIC_iLoadru, + "ldrt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} + +def LDRBT : AI2ldbpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base,am2offset:$offset), LdFrm, IIC_iLoadru, + "ldrbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} + +def LDRSBT : AI3ldsbpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base,am2offset:$offset), LdMiscFrm, IIC_iLoadru, + "ldrsbt", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} + +def LDRHT : AI3ldhpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base, am3offset:$offset), LdMiscFrm, IIC_iLoadru, + "ldrht", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite +} + +def LDRSHT : AI3ldshpo<(outs GPR:$dst, GPR:$base_wb), + (ins GPR:$base,am3offset:$offset), LdMiscFrm, IIC_iLoadru, + "ldrsht", "\t$dst, [$base], $offset", "$base = $base_wb", []> { + let Inst{21} = 1; // overwrite } // Store @@ -915,8 +1240,8 @@ def STR : AI2stw<(outs), (ins GPR:$src, addrmode2:$addr), StFrm, IIC_iStorer, [(store GPR:$src, addrmode2:$addr)]>; // Stores with truncate -def STRH : AI3sth<(outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm, IIC_iStorer, - "strh", "\t$src, $addr", +def STRH : AI3sth<(outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm, + IIC_iStorer, "strh", "\t$src, $addr", [(truncstorei16 GPR:$src, addrmode3:$addr)]>; def STRB : AI2stb<(outs), (ins GPR:$src, addrmode2:$addr), StFrm, IIC_iStorer, @@ -931,47 +1256,87 @@ def STRD : AI3std<(outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr), // Indexed stores def STR_PRE : AI2stwpr<(outs GPR:$base_wb), - (ins GPR:$src, GPR:$base, am2offset:$offset), + (ins GPR:$src, GPR:$base, am2offset:$offset), StFrm, IIC_iStoreru, "str", "\t$src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_store GPR:$src, GPR:$base, am2offset:$offset))]>; def STR_POST : AI2stwpo<(outs GPR:$base_wb), - (ins GPR:$src, GPR:$base,am2offset:$offset), + (ins GPR:$src, GPR:$base,am2offset:$offset), StFrm, IIC_iStoreru, "str", "\t$src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_store GPR:$src, GPR:$base, am2offset:$offset))]>; def STRH_PRE : AI3sthpr<(outs GPR:$base_wb), - (ins GPR:$src, GPR:$base,am3offset:$offset), + (ins GPR:$src, GPR:$base,am3offset:$offset), StMiscFrm, IIC_iStoreru, "strh", "\t$src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>; def STRH_POST: AI3sthpo<(outs GPR:$base_wb), - (ins GPR:$src, GPR:$base,am3offset:$offset), + (ins GPR:$src, GPR:$base,am3offset:$offset), StMiscFrm, IIC_iStoreru, "strh", "\t$src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_truncsti16 GPR:$src, GPR:$base, am3offset:$offset))]>; def STRB_PRE : AI2stbpr<(outs GPR:$base_wb), - (ins GPR:$src, GPR:$base,am2offset:$offset), + (ins GPR:$src, GPR:$base,am2offset:$offset), StFrm, IIC_iStoreru, "strb", "\t$src, [$base, $offset]!", "$base = $base_wb", [(set GPR:$base_wb, (pre_truncsti8 GPR:$src, GPR:$base, am2offset:$offset))]>; def STRB_POST: AI2stbpo<(outs GPR:$base_wb), - (ins GPR:$src, GPR:$base,am2offset:$offset), + (ins GPR:$src, GPR:$base,am2offset:$offset), StFrm, IIC_iStoreru, "strb", "\t$src, [$base], $offset", "$base = $base_wb", [(set GPR:$base_wb, (post_truncsti8 GPR:$src, GPR:$base, am2offset:$offset))]>; +// For disassembly only +def STRD_PRE : AI3stdpr<(outs GPR:$base_wb), + (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), + StMiscFrm, IIC_iStoreru, + "strd", "\t$src1, $src2, [$base, $offset]!", + "$base = $base_wb", []>; + +// For disassembly only +def STRD_POST: AI3stdpo<(outs GPR:$base_wb), + (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), + StMiscFrm, IIC_iStoreru, + "strd", "\t$src1, $src2, [$base], $offset", + "$base = $base_wb", []>; + +// STRT, STRBT, and STRHT are for disassembly only. + +def STRT : AI2stwpo<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am2offset:$offset), + StFrm, IIC_iStoreru, + "strt", "\t$src, [$base], $offset", "$base = $base_wb", + [/* For disassembly only; pattern left blank */]> { + let Inst{21} = 1; // overwrite +} + +def STRBT : AI2stbpo<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am2offset:$offset), + StFrm, IIC_iStoreru, + "strbt", "\t$src, [$base], $offset", "$base = $base_wb", + [/* For disassembly only; pattern left blank */]> { + let Inst{21} = 1; // overwrite +} + +def STRHT: AI3sthpo<(outs GPR:$base_wb), + (ins GPR:$src, GPR:$base,am3offset:$offset), + StMiscFrm, IIC_iStoreru, + "strht", "\t$src, [$base], $offset", "$base = $base_wb", + [/* For disassembly only; pattern left blank */]> { + let Inst{21} = 1; // overwrite +} + //===----------------------------------------------------------------------===// // Load / store multiple Instructions. // @@ -999,7 +1364,7 @@ def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm, IIC_iMOVr, let Inst{25} = 0; } -def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src), +def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src), DPSoRegFrm, IIC_iMOVsr, "mov", "\t$dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP { let Inst{25} = 0; @@ -1012,7 +1377,7 @@ def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPFrm, IIC_iMOVi, } let isReMaterializable = 1, isAsCheapAsAMove = 1 in -def MOVi16 : AI1<0b1000, (outs GPR:$dst), (ins i32imm:$src), +def MOVi16 : AI1<0b1000, (outs GPR:$dst), (ins i32imm:$src), DPFrm, IIC_iMOVi, "movw", "\t$dst, $src", [(set GPR:$dst, imm0_65535:$src)]>, @@ -1026,7 +1391,7 @@ def MOVTi16 : AI1<0b1010, (outs GPR:$dst), (ins GPR:$src, i32imm:$imm), DPFrm, IIC_iMOVi, "movt", "\t$dst, $imm", [(set GPR:$dst, - (or (and GPR:$src, 0xffff), + (or (and GPR:$src, 0xffff), lo16AllZero:$imm))]>, UnaryDP, Requires<[IsARM, HasV6T2]> { let Inst{20} = 0; @@ -1045,7 +1410,7 @@ def MOVrx : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo, IIC_iMOVsi, // due to flag operands. let Defs = [CPSR] in { -def MOVsrl_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo, +def MOVsrl_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo, IIC_iMOVsi, "movs", "\t$dst, $src, lsr #1", [(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, UnaryDP; def MOVsra_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), Pseudo, @@ -1069,7 +1434,11 @@ defm SXTAB : AI_bin_rrot<0b01101010, defm SXTAH : AI_bin_rrot<0b01101011, "sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>; -// TODO: SXT(A){B|H}16 +// For disassembly only +defm SXTB16 : AI_unary_rrot_np<0b01101000, "sxtb16">; + +// For disassembly only +defm SXTAB16 : AI_bin_rrot_np<0b01101000, "sxtab16">; // Zero extenders @@ -1093,9 +1462,9 @@ defm UXTAH : AI_bin_rrot<0b01101111, "uxtah", } // This isn't safe in general, the add is two 16-bit units, not a 32-bit add. -//defm UXTAB16 : xxx<"uxtab16", 0xff00ff>; +// For disassembly only +defm UXTAB16 : AI_bin_rrot_np<0b01101100, "uxtab16">; -// TODO: UXT(A){B|H}16 def SBFX : I<(outs GPR:$dst), (ins GPR:$src, imm0_31:$lsb, imm0_31:$width), @@ -1131,13 +1500,13 @@ defm SUBS : AI1_bin_s_irs<0b0010, "subs", BinOpFrag<(subc node:$LHS, node:$RHS)>>; defm ADC : AI1_adde_sube_irs<0b0101, "adc", - BinOpFrag<(adde node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>; defm SBC : AI1_adde_sube_irs<0b0110, "sbc", - BinOpFrag<(sube node:$LHS, node:$RHS)>>; + BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; defm ADCS : AI1_adde_sube_s_irs<0b0101, "adcs", - BinOpFrag<(adde node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; defm SBCS : AI1_adde_sube_s_irs<0b0110, "sbcs", - BinOpFrag<(sube node:$LHS, node:$RHS)>>; + BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>; // These don't define reg/reg forms, because they are handled above. def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm, @@ -1171,14 +1540,14 @@ def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, let Uses = [CPSR] in { def RSCri : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm, IIC_iALUi, "rsc", "\t$dst, $a, $b", - [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>, - Requires<[IsARM, CarryDefIsUnused]> { + [(set GPR:$dst, (sube_dead_carry so_imm:$b, GPR:$a))]>, + Requires<[IsARM]> { let Inst{25} = 1; } def RSCrs : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, IIC_iALUsr, "rsc", "\t$dst, $a, $b", - [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>, - Requires<[IsARM, CarryDefIsUnused]> { + [(set GPR:$dst, (sube_dead_carry so_reg:$b, GPR:$a))]>, + Requires<[IsARM]> { let Inst{25} = 0; } } @@ -1187,15 +1556,15 @@ def RSCrs : AsI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), let Defs = [CPSR], Uses = [CPSR] in { def RSCSri : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm, IIC_iALUi, "rscs\t$dst, $a, $b", - [(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>, - Requires<[IsARM, CarryDefIsUnused]> { + [(set GPR:$dst, (sube_dead_carry so_imm:$b, GPR:$a))]>, + Requires<[IsARM]> { let Inst{20} = 1; let Inst{25} = 1; } def RSCSrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm, IIC_iALUsr, "rscs\t$dst, $a, $b", - [(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>, - Requires<[IsARM, CarryDefIsUnused]> { + [(set GPR:$dst, (sube_dead_carry so_reg:$b, GPR:$a))]>, + Requires<[IsARM]> { let Inst{20} = 1; let Inst{25} = 0; } @@ -1216,6 +1585,126 @@ def : ARMPat<(add GPR:$src, so_imm_neg:$imm), // (mul X, 2^n+1) -> (add (X << n), X) // (mul X, 2^n-1) -> (rsb X, (X << n)) +// ARM Arithmetic Instruction -- for disassembly only +// GPR:$dst = GPR:$a op GPR:$b +class AAI op27_20, bits<4> op7_4, string opc> + : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm, IIC_iALUr, + opc, "\t$dst, $a, $b", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-20} = op27_20; + let Inst{7-4} = op7_4; +} + +// Saturating add/subtract -- for disassembly only + +def QADD : AAI<0b00010000, 0b0101, "qadd">; +def QADD16 : AAI<0b01100010, 0b0001, "qadd16">; +def QADD8 : AAI<0b01100010, 0b1001, "qadd8">; +def QASX : AAI<0b01100010, 0b0011, "qasx">; +def QDADD : AAI<0b00010100, 0b0101, "qdadd">; +def QDSUB : AAI<0b00010110, 0b0101, "qdsub">; +def QSAX : AAI<0b01100010, 0b0101, "qsax">; +def QSUB : AAI<0b00010010, 0b0101, "qsub">; +def QSUB16 : AAI<0b01100010, 0b0111, "qsub16">; +def QSUB8 : AAI<0b01100010, 0b1111, "qsub8">; +def UQADD16 : AAI<0b01100110, 0b0001, "uqadd16">; +def UQADD8 : AAI<0b01100110, 0b1001, "uqadd8">; +def UQASX : AAI<0b01100110, 0b0011, "uqasx">; +def UQSAX : AAI<0b01100110, 0b0101, "uqsax">; +def UQSUB16 : AAI<0b01100110, 0b0111, "uqsub16">; +def UQSUB8 : AAI<0b01100110, 0b1111, "uqsub8">; + +// Signed/Unsigned add/subtract -- for disassembly only + +def SASX : AAI<0b01100001, 0b0011, "sasx">; +def SADD16 : AAI<0b01100001, 0b0001, "sadd16">; +def SADD8 : AAI<0b01100001, 0b1001, "sadd8">; +def SSAX : AAI<0b01100001, 0b0101, "ssax">; +def SSUB16 : AAI<0b01100001, 0b0111, "ssub16">; +def SSUB8 : AAI<0b01100001, 0b1111, "ssub8">; +def UASX : AAI<0b01100101, 0b0011, "uasx">; +def UADD16 : AAI<0b01100101, 0b0001, "uadd16">; +def UADD8 : AAI<0b01100101, 0b1001, "uadd8">; +def USAX : AAI<0b01100101, 0b0101, "usax">; +def USUB16 : AAI<0b01100101, 0b0111, "usub16">; +def USUB8 : AAI<0b01100101, 0b1111, "usub8">; + +// Signed/Unsigned halving add/subtract -- for disassembly only + +def SHASX : AAI<0b01100011, 0b0011, "shasx">; +def SHADD16 : AAI<0b01100011, 0b0001, "shadd16">; +def SHADD8 : AAI<0b01100011, 0b1001, "shadd8">; +def SHSAX : AAI<0b01100011, 0b0101, "shsax">; +def SHSUB16 : AAI<0b01100011, 0b0111, "shsub16">; +def SHSUB8 : AAI<0b01100011, 0b1111, "shsub8">; +def UHASX : AAI<0b01100111, 0b0011, "uhasx">; +def UHADD16 : AAI<0b01100111, 0b0001, "uhadd16">; +def UHADD8 : AAI<0b01100111, 0b1001, "uhadd8">; +def UHSAX : AAI<0b01100111, 0b0101, "uhsax">; +def UHSUB16 : AAI<0b01100111, 0b0111, "uhsub16">; +def UHSUB8 : AAI<0b01100111, 0b1111, "uhsub8">; + +// Unsigned Sum of Absolute Differences [and Accumulate] -- for disassembly only + +def USAD8 : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b), + MulFrm /* for convenience */, NoItinerary, "usad8", + "\t$dst, $a, $b", []>, + Requires<[IsARM, HasV6]> { + let Inst{27-20} = 0b01111000; + let Inst{15-12} = 0b1111; + let Inst{7-4} = 0b0001; +} +def USADA8 : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + MulFrm /* for convenience */, NoItinerary, "usada8", + "\t$dst, $a, $b, $acc", []>, + Requires<[IsARM, HasV6]> { + let Inst{27-20} = 0b01111000; + let Inst{7-4} = 0b0001; +} + +// Signed/Unsigned saturate -- for disassembly only + +def SSATlsl : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt), + DPFrm, NoItinerary, "ssat", "\t$dst, $bit_pos, $a, lsl $shamt", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-21} = 0b0110101; + let Inst{6-4} = 0b001; +} + +def SSATasr : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt), + DPFrm, NoItinerary, "ssat", "\t$dst, $bit_pos, $a, asr $shamt", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-21} = 0b0110101; + let Inst{6-4} = 0b101; +} + +def SSAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), DPFrm, + NoItinerary, "ssat16", "\t$dst, $bit_pos, $a", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-20} = 0b01101010; + let Inst{7-4} = 0b0011; +} + +def USATlsl : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt), + DPFrm, NoItinerary, "usat", "\t$dst, $bit_pos, $a, lsl $shamt", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-21} = 0b0110111; + let Inst{6-4} = 0b001; +} + +def USATasr : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt), + DPFrm, NoItinerary, "usat", "\t$dst, $bit_pos, $a, asr $shamt", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-21} = 0b0110111; + let Inst{6-4} = 0b101; +} + +def USAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), DPFrm, + NoItinerary, "usat16", "\t$dst, $bit_pos, $a", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-20} = 0b01101110; + let Inst{7-4} = 0b0011; +} //===----------------------------------------------------------------------===// // Bitwise Instructions. @@ -1239,6 +1728,17 @@ def BFC : I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm), let Inst{6-0} = 0b0011111; } +// A8.6.18 BFI - Bitfield insert (Encoding A1) +// Added for disassembler with the pattern field purposely left blank. +def BFI : I<(outs GPR:$dst), (ins GPR:$src, bf_inv_mask_imm:$imm), + AddrMode1, Size4Bytes, IndexModeNone, DPFrm, IIC_iUNAsi, + "bfi", "\t$dst, $src, $imm", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6T2]> { + let Inst{27-21} = 0b0111110; + let Inst{6-4} = 0b001; // Rn: Inst{3-0} != 15 +} + def MVNr : AsI1<0b1111, (outs GPR:$dst), (ins GPR:$src), DPFrm, IIC_iMOVr, "mvn", "\t$dst, $src", [(set GPR:$dst, (not GPR:$src))]>, UnaryDP { @@ -1251,7 +1751,7 @@ def MVNs : AsI1<0b1111, (outs GPR:$dst), (ins so_reg:$src), DPSoRegFrm, let Inst{25} = 0; } let isReMaterializable = 1, isAsCheapAsAMove = 1 in -def MVNi : AsI1<0b1111, (outs GPR:$dst), (ins so_imm:$imm), DPFrm, +def MVNi : AsI1<0b1111, (outs GPR:$dst), (ins so_imm:$imm), DPFrm, IIC_iMOVi, "mvn", "\t$dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>,UnaryDP { let Inst{25} = 1; @@ -1314,6 +1814,14 @@ def SMMUL : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b), let Inst{15-12} = 0b1111; } +def SMMULR : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMUL32, "smmulr", "\t$dst, $a, $b", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b0011; // R = 1 + let Inst{15-12} = 0b1111; +} + def SMMLA : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, "smmla", "\t$dst, $a, $b, $c", [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>, @@ -1321,6 +1829,12 @@ def SMMLA : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), let Inst{7-4} = 0b0001; } +def SMMLAR : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), + IIC_iMAC32, "smmlar", "\t$dst, $a, $b, $c", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b0011; // R = 1 +} def SMMLS : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, "smmls", "\t$dst, $a, $b, $c", @@ -1329,6 +1843,13 @@ def SMMLS : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), let Inst{7-4} = 0b1101; } +def SMMLSR : AMul2I <0b0111010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), + IIC_iMAC32, "smmlsr", "\t$dst, $a, $b, $c", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV6]> { + let Inst{7-4} = 0b1111; // R = 1 +} + multiclass AI_smul { def BB : AMulxyI<0b0001011, (outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, !strconcat(opc, "bb"), "\t$dst, $a, $b", @@ -1400,7 +1921,7 @@ multiclass AI_smla { def BT : AMulxyI<0b0001000, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "bt"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16), - (sra GPR:$b, (i32 16)))))]>, + (sra GPR:$b, (i32 16)))))]>, Requires<[IsARM, HasV5TE]> { let Inst{5} = 0; let Inst{6} = 1; @@ -1446,8 +1967,87 @@ multiclass AI_smla { defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; -// TODO: Halfword multiple accumulate long: SMLAL -// TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD +// Halfword multiply accumulate long: SMLAL -- for disassembly only +def SMLALBB : AMulxyI<0b0001010,(outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b), + IIC_iMAC64, "smlalbb", "\t$ldst, $hdst, $a, $b", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 0; + let Inst{6} = 0; +} + +def SMLALBT : AMulxyI<0b0001010,(outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b), + IIC_iMAC64, "smlalbt", "\t$ldst, $hdst, $a, $b", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 0; + let Inst{6} = 1; +} + +def SMLALTB : AMulxyI<0b0001010,(outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b), + IIC_iMAC64, "smlaltb", "\t$ldst, $hdst, $a, $b", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 1; + let Inst{6} = 0; +} + +def SMLALTT : AMulxyI<0b0001010,(outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b), + IIC_iMAC64, "smlaltt", "\t$ldst, $hdst, $a, $b", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV5TE]> { + let Inst{5} = 1; + let Inst{6} = 1; +} + +// Helper class for AI_smld -- for disassembly only +class AMulDualI + : AI, Requires<[IsARM, HasV6]> { + let Inst{4} = 1; + let Inst{5} = swap; + let Inst{6} = sub; + let Inst{7} = 0; + let Inst{21-20} = 0b00; + let Inst{22} = long; + let Inst{27-23} = 0b01110; +} + +multiclass AI_smld { + + def D : AMulDualI<0, sub, 0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + NoItinerary, !strconcat(opc, "d"), "\t$dst, $a, $b, $acc">; + + def DX : AMulDualI<0, sub, 1, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), + NoItinerary, !strconcat(opc, "dx"), "\t$dst, $a, $b, $acc">; + + def LD : AMulDualI<1, sub, 0, (outs GPR:$ldst,GPR:$hdst), (ins GPR:$a,GPR:$b), + NoItinerary, !strconcat(opc, "ld"), "\t$ldst, $hdst, $a, $b">; + + def LDX : AMulDualI<1, sub, 1, (outs GPR:$ldst,GPR:$hdst),(ins GPR:$a,GPR:$b), + NoItinerary, !strconcat(opc, "ldx"),"\t$ldst, $hdst, $a, $b">; + +} + +defm SMLA : AI_smld<0, "smla">; +defm SMLS : AI_smld<1, "smls">; + +multiclass AI_sdml { + + def D : AMulDualI<0, sub, 0, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + NoItinerary, !strconcat(opc, "d"), "\t$dst, $a, $b"> { + let Inst{15-12} = 0b1111; + } + + def DX : AMulDualI<0, sub, 1, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + NoItinerary, !strconcat(opc, "dx"), "\t$dst, $a, $b"> { + let Inst{15-12} = 0b1111; + } + +} + +defm SMUA : AI_sdml<0, "smua">; +defm SMUS : AI_sdml<1, "smus">; //===----------------------------------------------------------------------===// // Misc. Arithmetic Instructions. @@ -1505,7 +2105,7 @@ def REVSH : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, def PKHBT : AMiscA1I<0b01101000, (outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt), - IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, LSL $shamt", + IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, lsl $shamt", [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF), (and (shl GPR:$src2, (i32 imm:$shamt)), 0xFFFF0000)))]>, @@ -1522,7 +2122,7 @@ def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)), def PKHTB : AMiscA1I<0b01101000, (outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt), - IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, ASR $shamt", + IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, asr $shamt", [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000), (and (sra GPR:$src2, imm16_31:$shamt), 0xFFFF)))]>, Requires<[IsARM, HasV6]> { @@ -1568,7 +2168,7 @@ def : ARMPat<(ARMcmpZ GPR:$src, so_imm_neg:$imm), // Conditional moves // FIXME: should be able to write a pattern for ARMcmov, but can't use -// a two-value operand where a dag node expects two operands. :( +// a two-value operand where a dag node expects two operands. :( def MOVCCr : AI1<0b1101, (outs GPR:$dst), (ins GPR:$false, GPR:$true), DPFrm, IIC_iCMOVr, "mov", "\t$dst, $true", [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>, @@ -1606,6 +2206,7 @@ def Int_MemBarrierV7 : AInoP<(outs), (ins), Requires<[IsARM, HasV7]> { let Inst{31-4} = 0xf57ff05; // FIXME: add support for options other than a full system DMB + // See DMB disassembly-only variants below. let Inst{3-0} = 0b1111; } @@ -1616,6 +2217,7 @@ def Int_SyncBarrierV7 : AInoP<(outs), (ins), Requires<[IsARM, HasV7]> { let Inst{31-4} = 0xf57ff04; // FIXME: add support for options other than a full system DSB + // See DSB disassembly-only variants below. let Inst{3-0} = 0b1111; } @@ -1638,6 +2240,64 @@ def Int_SyncBarrierV6 : AInoP<(outs), (ins GPR:$zero), } } +// Helper class for multiclass MemB -- for disassembly only +class AMBI + : AInoP<(outs), (ins), MiscFrm, NoItinerary, opc, asm, + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV7]> { + let Inst{31-20} = 0xf57; +} + +multiclass MemB op7_4, string opc> { + + def st : AMBI { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b1110; + } + + def ish : AMBI { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b1011; + } + + def ishst : AMBI { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b1010; + } + + def nsh : AMBI { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b0111; + } + + def nshst : AMBI { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b0110; + } + + def osh : AMBI { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b0011; + } + + def oshst : AMBI { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b0010; + } +} + +// These DMB variants are for disassembly only. +defm DMB : MemB<0b0101, "dmb">; + +// These DSB variants are for disassembly only. +defm DSB : MemB<0b0100, "dsb">; + +// ISB has only full system option -- for disassembly only +def ISBsy : AMBI<"isb", ""> { + let Inst{7-4} = 0b0110; + let Inst{3-0} = 0b1111; +} + let usesCustomInserter = 1 in { let Uses = [CPSR] in { def ATOMIC_LOAD_ADD_I8 : PseudoInst< @@ -1777,6 +2437,35 @@ def STREXD : AIstrex<0b01, (outs GPR:$success), []>; } +// Clear-Exclusive is for disassembly only. +def CLREX : AXI<(outs), (ins), MiscFrm, NoItinerary, "clrex", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV7]> { + let Inst{31-20} = 0xf57; + let Inst{7-4} = 0b0001; +} + +// SWP/SWPB are deprecated in V6/V7 and for disassembly only. +let mayLoad = 1 in { +def SWP : AI<(outs GPR:$dst), (ins GPR:$src, GPR:$ptr), LdStExFrm, NoItinerary, + "swp", "\t$dst, $src, [$ptr]", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-23} = 0b00010; + let Inst{22} = 0; // B = 0 + let Inst{21-20} = 0b00; + let Inst{7-4} = 0b1001; +} + +def SWPB : AI<(outs GPR:$dst), (ins GPR:$src, GPR:$ptr), LdStExFrm, NoItinerary, + "swpb", "\t$dst, $src, [$ptr]", + [/* For disassembly only; pattern left blank */]> { + let Inst{27-23} = 0b00010; + let Inst{22} = 1; // B = 1 + let Inst{21-20} = 0b00; + let Inst{7-4} = 0b1001; +} +} + //===----------------------------------------------------------------------===// // TLS Instructions // @@ -1827,7 +2516,7 @@ let Defs = // Two piece so_imms. let isReMaterializable = 1 in -def MOVi2pieces : AI1x2<(outs GPR:$dst), (ins so_imm2part:$src), +def MOVi2pieces : AI1x2<(outs GPR:$dst), (ins so_imm2part:$src), Pseudo, IIC_iMOVi, "mov", "\t$dst, $src", [(set GPR:$dst, so_imm2part:$src)]>, @@ -1852,7 +2541,7 @@ def : ARMPat<(add GPR:$LHS, so_neg_imm2part:$RHS), // FIXME: Remove this when we can do generalized remat. let isReMaterializable = 1 in def MOVi32imm : AI1x2<(outs GPR:$dst), (ins i32imm:$src), Pseudo, IIC_iMOVi, - "movw", "\t$dst, ${src:lo16}\n\tmovt${p}\t$dst, ${src:hi16}", + "movw", "\t$dst, ${src:lo16}\n\tmovt${p}\t$dst, ${src:hi16}", [(set GPR:$dst, (i32 imm:$src))]>, Requires<[IsARM, HasV6T2]>; @@ -1959,3 +2648,226 @@ include "ARMInstrVFP.td" // include "ARMInstrNEON.td" + +//===----------------------------------------------------------------------===// +// Coprocessor Instructions. For disassembly only. +// + +def CDP : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1, + nohash_imm:$CRd, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2), + NoItinerary, "cdp", "\tp$cop, $opc1, cr$CRd, cr$CRn, cr$CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{4} = 0; +} + +def CDP2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1, + nohash_imm:$CRd, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2), + NoItinerary, "cdp2\tp$cop, $opc1, cr$CRd, cr$CRn, cr$CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{4} = 0; +} + +class ACI + : I { + let Inst{27-25} = 0b110; +} + +multiclass LdStCop op31_28, bit load, string opc> { + + def _OFFSET : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), + opc, "\tp$cop, cr$CRd, $addr"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _PRE : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), + opc, "\tp$cop, cr$CRd, $addr!"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 1; // W = 1 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _POST : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset), + opc, "\tp$cop, cr$CRd, [$base], $offset"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{21} = 1; // W = 1 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def _OPTION : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, i32imm:$option), + opc, "\tp$cop, cr$CRd, [$base], $option"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{23} = 1; // U = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 0; // D = 0 + let Inst{20} = load; + } + + def L_OFFSET : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), + opc, "l\tp$cop, cr$CRd, $addr"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_PRE : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), + opc, "l\tp$cop, cr$CRd, $addr!"> { + let Inst{31-28} = op31_28; + let Inst{24} = 1; // P = 1 + let Inst{21} = 1; // W = 1 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_POST : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, am2offset:$offset), + opc, "l\tp$cop, cr$CRd, [$base], $offset"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{21} = 1; // W = 1 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } + + def L_OPTION : ACI<(outs), + (ins nohash_imm:$cop, nohash_imm:$CRd, GPR:$base, nohash_imm:$option), + opc, "l\tp$cop, cr$CRd, [$base], $option"> { + let Inst{31-28} = op31_28; + let Inst{24} = 0; // P = 0 + let Inst{23} = 1; // U = 1 + let Inst{21} = 0; // W = 0 + let Inst{22} = 1; // D = 1 + let Inst{20} = load; + } +} + +defm LDC : LdStCop<{?,?,?,?}, 1, "ldc">; +defm LDC2 : LdStCop<0b1111, 1, "ldc2">; +defm STC : LdStCop<{?,?,?,?}, 0, "stc">; +defm STC2 : LdStCop<0b1111, 0, "stc2">; + +def MCR : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1, + GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2), + NoItinerary, "mcr", "\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{20} = 0; + let Inst{4} = 1; +} + +def MCR2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1, + GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2), + NoItinerary, "mcr2\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{20} = 0; + let Inst{4} = 1; +} + +def MRC : ABI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1, + GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2), + NoItinerary, "mrc", "\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{20} = 1; + let Inst{4} = 1; +} + +def MRC2 : ABXI<0b1110, (outs), (ins nohash_imm:$cop, i32imm:$opc1, + GPR:$Rt, nohash_imm:$CRn, nohash_imm:$CRm, i32imm:$opc2), + NoItinerary, "mrc2\tp$cop, $opc1, $Rt, cr$CRn, cr$CRm, $opc2", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{20} = 1; + let Inst{4} = 1; +} + +def MCRR : ABI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc, + GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm), + NoItinerary, "mcrr", "\tp$cop, $opc, $Rt, $Rt2, cr$CRm", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0100; +} + +def MCRR2 : ABXI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc, + GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm), + NoItinerary, "mcrr2\tp$cop, $opc, $Rt, $Rt2, cr$CRm", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{23-20} = 0b0100; +} + +def MRRC : ABI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc, + GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm), + NoItinerary, "mrrc", "\tp$cop, $opc, $Rt, $Rt2, cr$CRm", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0101; +} + +def MRRC2 : ABXI<0b1100, (outs), (ins nohash_imm:$cop, i32imm:$opc, + GPR:$Rt, GPR:$Rt2, nohash_imm:$CRm), + NoItinerary, "mrrc2\tp$cop, $opc, $Rt, $Rt2, cr$CRm", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-28} = 0b1111; + let Inst{23-20} = 0b0101; +} + +//===----------------------------------------------------------------------===// +// Move between special register and ARM core register -- for disassembly only +// + +def MRS : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary, "mrs", "\t$dst, cpsr", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0000; + let Inst{7-4} = 0b0000; +} + +def MRSsys : ABI<0b0001,(outs GPR:$dst),(ins), NoItinerary,"mrs","\t$dst, spsr", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0100; + let Inst{7-4} = 0b0000; +} + +// FIXME: mask is ignored for the time being. +def MSR : ABI<0b0001,(outs),(ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0010; + let Inst{7-4} = 0b0000; +} + +// FIXME: mask is ignored for the time being. +def MSRi : ABI<0b0011,(outs),(ins so_imm:$a), NoItinerary, "msr", "\tcpsr, $a", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0010; + let Inst{7-4} = 0b0000; +} + +// FIXME: mask is ignored for the time being. +def MSRsys : ABI<0b0001,(outs),(ins GPR:$src),NoItinerary,"msr","\tspsr, $src", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0110; + let Inst{7-4} = 0b0000; +} + +// FIXME: mask is ignored for the time being. +def MSRsysi : ABI<0b0011,(outs),(ins so_imm:$a),NoItinerary,"msr","\tspsr, $a", + [/* For disassembly only; pattern left blank */]> { + let Inst{23-20} = 0b0110; + let Inst{7-4} = 0b0000; +} diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index e2be7ba601..3aa0810683 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -83,11 +83,17 @@ def NEONvrev32 : SDNode<"ARMISD::VREV32", SDTARMVSHUF>; def NEONvrev16 : SDNode<"ARMISD::VREV16", SDTARMVSHUF>; def SDTARMVSHUF2 : SDTypeProfile<2, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>, - SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>]>; + SDTCisSameAs<0, 2>, + SDTCisSameAs<0, 3>]>; def NEONzip : SDNode<"ARMISD::VZIP", SDTARMVSHUF2>; def NEONuzp : SDNode<"ARMISD::VUZP", SDTARMVSHUF2>; def NEONtrn : SDNode<"ARMISD::VTRN", SDTARMVSHUF2>; +def SDTARMFMAX : SDTypeProfile<1, 2, [SDTCisVT<0, f32>, SDTCisSameAs<0, 1>, + SDTCisSameAs<0, 2>]>; +def NEONfmax : SDNode<"ARMISD::FMAX", SDTARMFMAX>; +def NEONfmin : SDNode<"ARMISD::FMIN", SDTARMFMAX>; + //===----------------------------------------------------------------------===// // NEON operand definitions //===----------------------------------------------------------------------===// @@ -123,9 +129,7 @@ def h64imm : Operand { let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { def VLDMD : NI<(outs), (ins addrmode_neonldstm:$addr, reglist:$dst1, variable_ops), - IIC_fpLoadm, - "vldm", "${addr:submode} ${addr:base}, $dst1", - []> { + IIC_fpLoadm, "vldm", "${addr:submode} ${addr:base}, $dst1", []> { let Inst{27-25} = 0b110; let Inst{20} = 1; let Inst{11-9} = 0b101; @@ -133,9 +137,7 @@ def VLDMD : NI<(outs), def VLDMS : NI<(outs), (ins addrmode_neonldstm:$addr, reglist:$dst1, variable_ops), - IIC_fpLoadm, - "vldm", "${addr:submode} ${addr:base}, $dst1", - []> { + IIC_fpLoadm, "vldm", "${addr:submode} ${addr:base}, $dst1", []> { let Inst{27-25} = 0b110; let Inst{20} = 1; let Inst{11-9} = 0b101; @@ -144,10 +146,9 @@ def VLDMS : NI<(outs), */ // Use vldmia to load a Q register as a D register pair. -def VLDRQ : NI4<(outs QPR:$dst), (ins addrmode4:$addr), - IIC_fpLoadm, - "vldmia", "$addr, ${dst:dregpair}", - [(set QPR:$dst, (v2f64 (load addrmode4:$addr)))]> { +def VLDRQ : NI4<(outs QPR:$dst), (ins addrmode4:$addr), IIC_fpLoadm, + "vldmia", "$addr, ${dst:dregpair}", + [(set QPR:$dst, (v2f64 (load addrmode4:$addr)))]> { let Inst{27-25} = 0b110; let Inst{24} = 0; // P bit let Inst{23} = 1; // U bit @@ -156,10 +157,9 @@ def VLDRQ : NI4<(outs QPR:$dst), (ins addrmode4:$addr), } // Use vstmia to store a Q register as a D register pair. -def VSTRQ : NI4<(outs), (ins QPR:$src, addrmode4:$addr), - IIC_fpStorem, - "vstmia", "$addr, ${src:dregpair}", - [(store (v2f64 QPR:$src), addrmode4:$addr)]> { +def VSTRQ : NI4<(outs), (ins QPR:$src, addrmode4:$addr), IIC_fpStorem, + "vstmia", "$addr, ${src:dregpair}", + [(store (v2f64 QPR:$src), addrmode4:$addr)]> { let Inst{27-25} = 0b110; let Inst{24} = 0; // P bit let Inst{23} = 1; // U bit @@ -191,6 +191,29 @@ def VLD1q32 : VLD1Q<0b1000, "vld1", "32", v4i32, int_arm_neon_vld1>; def VLD1qf : VLD1Q<0b1000, "vld1", "32", v4f32, int_arm_neon_vld1>; def VLD1q64 : VLD1Q<0b1100, "vld1", "64", v2i64, int_arm_neon_vld1>; +// These (dreg triple/quadruple) are for disassembly only. +class VLD1D3 op7_4, string OpcodeStr, string Dt> + : NLdSt<0, 0b10, 0b0110, op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3), + (ins addrmode6:$addr), IIC_VLD1, OpcodeStr, Dt, + "\\{$dst1, $dst2, $dst3\\}, $addr", "", + [/* For disassembly only; pattern left blank */]>; +class VLD1D4 op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b10,0b0010,op7_4,(outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), + (ins addrmode6:$addr), IIC_VLD1, OpcodeStr, Dt, + "\\{$dst1, $dst2, $dst3, $dst4\\}, $addr", "", + [/* For disassembly only; pattern left blank */]>; + +def VLD1d8T : VLD1D3<0b0000, "vld1", "8">; +def VLD1d16T : VLD1D3<0b0100, "vld1", "16">; +def VLD1d32T : VLD1D3<0b1000, "vld1", "32">; +//def VLD1d64T : VLD1D3<0b1100, "vld1", "64">; + +def VLD1d8Q : VLD1D4<0b0000, "vld1", "8">; +def VLD1d16Q : VLD1D4<0b0100, "vld1", "16">; +def VLD1d32Q : VLD1D4<0b1000, "vld1", "32">; +//def VLD1d64Q : VLD1D4<0b1100, "vld1", "64">; + + let mayLoad = 1, hasExtraDefRegAllocReq = 1 in { // VLD2 : Vector Load (multiple 2-element structures) @@ -216,6 +239,16 @@ def VLD2q8 : VLD2Q<0b0000, "vld2", "8">; def VLD2q16 : VLD2Q<0b0100, "vld2", "16">; def VLD2q32 : VLD2Q<0b1000, "vld2", "32">; +// These (double-spaced dreg pair) are for disassembly only. +class VLD2Ddbl op7_4, string OpcodeStr, string Dt> + : NLdSt<0,0b10,0b1001,op7_4, (outs DPR:$dst1, DPR:$dst2), + (ins addrmode6:$addr), IIC_VLD2, + OpcodeStr, Dt, "\\{$dst1, $dst2\\}, $addr", "", []>; + +def VLD2d8D : VLD2Ddbl<0b0000, "vld2", "8">; +def VLD2d16D : VLD2Ddbl<0b0100, "vld2", "16">; +def VLD2d32D : VLD2Ddbl<0b1000, "vld2", "32">; + // VLD3 : Vector Load (multiple 3-element structures) class VLD3D op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b10,0b0100,op7_4, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3), @@ -285,105 +318,64 @@ def VLD4q32b : VLD4WB<0b1000, "vld4", "32">; class VLD2LN op11_8, string OpcodeStr, string Dt> : NLdSt<1,0b10,op11_8,{?,?,?,?}, (outs DPR:$dst1, DPR:$dst2), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane), - IIC_VLD2, - OpcodeStr, Dt, "\\{$dst1[$lane], $dst2[$lane]\\}, $addr", + IIC_VLD2, OpcodeStr, Dt, "\\{$dst1[$lane], $dst2[$lane]\\}, $addr", "$src1 = $dst1, $src2 = $dst2", []>; // vld2 to single-spaced registers. def VLD2LNd8 : VLD2LN<0b0001, "vld2", "8">; -def VLD2LNd16 : VLD2LN<0b0101, "vld2", "16"> { - let Inst{5} = 0; -} -def VLD2LNd32 : VLD2LN<0b1001, "vld2", "32"> { - let Inst{6} = 0; -} +def VLD2LNd16 : VLD2LN<0b0101, "vld2", "16"> { let Inst{5} = 0; } +def VLD2LNd32 : VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 0; } // vld2 to double-spaced even registers. -def VLD2LNq16a: VLD2LN<0b0101, "vld2", "16"> { - let Inst{5} = 1; -} -def VLD2LNq32a: VLD2LN<0b1001, "vld2", "32"> { - let Inst{6} = 1; -} +def VLD2LNq16a: VLD2LN<0b0101, "vld2", "16"> { let Inst{5} = 1; } +def VLD2LNq32a: VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 1; } // vld2 to double-spaced odd registers. -def VLD2LNq16b: VLD2LN<0b0101, "vld2", "16"> { - let Inst{5} = 1; -} -def VLD2LNq32b: VLD2LN<0b1001, "vld2", "32"> { - let Inst{6} = 1; -} +def VLD2LNq16b: VLD2LN<0b0101, "vld2", "16"> { let Inst{5} = 1; } +def VLD2LNq32b: VLD2LN<0b1001, "vld2", "32"> { let Inst{6} = 1; } // VLD3LN : Vector Load (single 3-element structure to one lane) class VLD3LN op11_8, string OpcodeStr, string Dt> : NLdSt<1,0b10,op11_8,{?,?,?,?}, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, - nohash_imm:$lane), IIC_VLD3, - OpcodeStr, Dt, + nohash_imm:$lane), IIC_VLD3, OpcodeStr, Dt, "\\{$dst1[$lane], $dst2[$lane], $dst3[$lane]\\}, $addr", "$src1 = $dst1, $src2 = $dst2, $src3 = $dst3", []>; // vld3 to single-spaced registers. -def VLD3LNd8 : VLD3LN<0b0010, "vld3", "8"> { - let Inst{4} = 0; -} -def VLD3LNd16 : VLD3LN<0b0110, "vld3", "16"> { - let Inst{5-4} = 0b00; -} -def VLD3LNd32 : VLD3LN<0b1010, "vld3", "32"> { - let Inst{6-4} = 0b000; -} +def VLD3LNd8 : VLD3LN<0b0010, "vld3", "8"> { let Inst{4} = 0; } +def VLD3LNd16 : VLD3LN<0b0110, "vld3", "16"> { let Inst{5-4} = 0b00; } +def VLD3LNd32 : VLD3LN<0b1010, "vld3", "32"> { let Inst{6-4} = 0b000; } // vld3 to double-spaced even registers. -def VLD3LNq16a: VLD3LN<0b0110, "vld3", "16"> { - let Inst{5-4} = 0b10; -} -def VLD3LNq32a: VLD3LN<0b1010, "vld3", "32"> { - let Inst{6-4} = 0b100; -} +def VLD3LNq16a: VLD3LN<0b0110, "vld3", "16"> { let Inst{5-4} = 0b10; } +def VLD3LNq32a: VLD3LN<0b1010, "vld3", "32"> { let Inst{6-4} = 0b100; } // vld3 to double-spaced odd registers. -def VLD3LNq16b: VLD3LN<0b0110, "vld3", "16"> { - let Inst{5-4} = 0b10; -} -def VLD3LNq32b: VLD3LN<0b1010, "vld3", "32"> { - let Inst{6-4} = 0b100; -} +def VLD3LNq16b: VLD3LN<0b0110, "vld3", "16"> { let Inst{5-4} = 0b10; } +def VLD3LNq32b: VLD3LN<0b1010, "vld3", "32"> { let Inst{6-4} = 0b100; } // VLD4LN : Vector Load (single 4-element structure to one lane) class VLD4LN op11_8, string OpcodeStr, string Dt> : NLdSt<1,0b10,op11_8,{?,?,?,?}, (outs DPR:$dst1, DPR:$dst2, DPR:$dst3, DPR:$dst4), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, - nohash_imm:$lane), IIC_VLD4, - OpcodeStr, Dt, + nohash_imm:$lane), IIC_VLD4, OpcodeStr, Dt, "\\{$dst1[$lane], $dst2[$lane], $dst3[$lane], $dst4[$lane]\\}, $addr", "$src1 = $dst1, $src2 = $dst2, $src3 = $dst3, $src4 = $dst4", []>; // vld4 to single-spaced registers. def VLD4LNd8 : VLD4LN<0b0011, "vld4", "8">; -def VLD4LNd16 : VLD4LN<0b0111, "vld4", "16"> { - let Inst{5} = 0; -} -def VLD4LNd32 : VLD4LN<0b1011, "vld4", "32"> { - let Inst{6} = 0; -} +def VLD4LNd16 : VLD4LN<0b0111, "vld4", "16"> { let Inst{5} = 0; } +def VLD4LNd32 : VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 0; } // vld4 to double-spaced even registers. -def VLD4LNq16a: VLD4LN<0b0111, "vld4", "16"> { - let Inst{5} = 1; -} -def VLD4LNq32a: VLD4LN<0b1011, "vld4", "32"> { - let Inst{6} = 1; -} +def VLD4LNq16a: VLD4LN<0b0111, "vld4", "16"> { let Inst{5} = 1; } +def VLD4LNq32a: VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 1; } // vld4 to double-spaced odd registers. -def VLD4LNq16b: VLD4LN<0b0111, "vld4", "16"> { - let Inst{5} = 1; -} -def VLD4LNq32b: VLD4LN<0b1011, "vld4", "32"> { - let Inst{6} = 1; -} +def VLD4LNq16b: VLD4LN<0b0111, "vld4", "16"> { let Inst{5} = 1; } +def VLD4LNq32b: VLD4LN<0b1011, "vld4", "32"> { let Inst{6} = 1; } // VLD1DUP : Vector Load (single element to all lanes) // VLD2DUP : Vector Load (single 2-element structure to all lanes) @@ -418,6 +410,31 @@ def VST1qf : VST1Q<0b1000, "vst1", "32", v4f32, int_arm_neon_vst1>; def VST1q64 : VST1Q<0b1100, "vst1", "64", v2i64, int_arm_neon_vst1>; } // hasExtraSrcRegAllocReq +// These (dreg triple/quadruple) are for disassembly only. +class VST1D3 op7_4, string OpcodeStr, string Dt> + : NLdSt<0, 0b00, 0b0110, op7_4, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3), IIC_VST, + OpcodeStr, Dt, + "\\{$src1, $src2, $src3\\}, $addr", "", + [/* For disassembly only; pattern left blank */]>; +class VST1D4 op7_4, string OpcodeStr, string Dt> + : NLdSt<0, 0b00, 0b0010, op7_4, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), + IIC_VST, OpcodeStr, Dt, + "\\{$src1, $src2, $src3, $src4\\}, $addr", "", + [/* For disassembly only; pattern left blank */]>; + +def VST1d8T : VST1D3<0b0000, "vst1", "8">; +def VST1d16T : VST1D3<0b0100, "vst1", "16">; +def VST1d32T : VST1D3<0b1000, "vst1", "32">; +//def VST1d64T : VST1D3<0b1100, "vst1", "64">; + +def VST1d8Q : VST1D4<0b0000, "vst1", "8">; +def VST1d16Q : VST1D4<0b0100, "vst1", "16">; +def VST1d32Q : VST1D4<0b1000, "vst1", "32">; +//def VST1d64Q : VST1D4<0b1100, "vst1", "64">; + + let mayStore = 1, hasExtraSrcRegAllocReq = 1 in { // VST2 : Vector Store (multiple 2-element structures) @@ -428,8 +445,7 @@ class VST2D op7_4, string OpcodeStr, string Dt> class VST2Q op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0011,op7_4, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), - IIC_VST, - OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", + IIC_VST, OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", "", []>; def VST2d8 : VST2D<0b0000, "vst2", "8">; @@ -443,6 +459,16 @@ def VST2q8 : VST2Q<0b0000, "vst2", "8">; def VST2q16 : VST2Q<0b0100, "vst2", "16">; def VST2q32 : VST2Q<0b1000, "vst2", "32">; +// These (double-spaced dreg pair) are for disassembly only. +class VST2Ddbl op7_4, string OpcodeStr, string Dt> + : NLdSt<0, 0b00, 0b1001, op7_4, (outs), + (ins addrmode6:$addr, DPR:$src1, DPR:$src2), IIC_VST, + OpcodeStr, Dt, "\\{$src1, $src2\\}, $addr", "", []>; + +def VST2d8D : VST2Ddbl<0b0000, "vst2", "8">; +def VST2d16D : VST2Ddbl<0b0100, "vst2", "16">; +def VST2d32D : VST2Ddbl<0b1000, "vst2", "32">; + // VST3 : Vector Store (multiple 3-element structures) class VST3D op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0100,op7_4, (outs), @@ -476,14 +502,12 @@ def VST3q32b : VST3WB<0b1000, "vst3", "32">; class VST4D op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0000,op7_4, (outs), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), - IIC_VST, - OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", + IIC_VST, OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", "", []>; class VST4WB op7_4, string OpcodeStr, string Dt> : NLdSt<0,0b00,0b0001,op7_4, (outs GPR:$wb), (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4), - IIC_VST, - OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", + IIC_VST, OpcodeStr, Dt, "\\{$src1, $src2, $src3, $src4\\}, $addr", "$addr.addr = $wb", []>; def VST4d8 : VST4D<0b0000, "vst4", "8">; @@ -511,104 +535,63 @@ def VST4q32b : VST4WB<0b1000, "vst4", "32">; // VST2LN : Vector Store (single 2-element structure from one lane) class VST2LN op11_8, string OpcodeStr, string Dt> : NLdSt<1,0b00,op11_8,{?,?,?,?}, (outs), - (ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane), - IIC_VST, - OpcodeStr, Dt, "\\{$src1[$lane], $src2[$lane]\\}, $addr", - "", []>; + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, nohash_imm:$lane), + IIC_VST, OpcodeStr, Dt, "\\{$src1[$lane], $src2[$lane]\\}, $addr", + "", []>; // vst2 to single-spaced registers. def VST2LNd8 : VST2LN<0b0001, "vst2", "8">; -def VST2LNd16 : VST2LN<0b0101, "vst2", "16"> { - let Inst{5} = 0; -} -def VST2LNd32 : VST2LN<0b1001, "vst2", "32"> { - let Inst{6} = 0; -} +def VST2LNd16 : VST2LN<0b0101, "vst2", "16"> { let Inst{5} = 0; } +def VST2LNd32 : VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 0; } // vst2 to double-spaced even registers. -def VST2LNq16a: VST2LN<0b0101, "vst2", "16"> { - let Inst{5} = 1; -} -def VST2LNq32a: VST2LN<0b1001, "vst2", "32"> { - let Inst{6} = 1; -} +def VST2LNq16a: VST2LN<0b0101, "vst2", "16"> { let Inst{5} = 1; } +def VST2LNq32a: VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 1; } // vst2 to double-spaced odd registers. -def VST2LNq16b: VST2LN<0b0101, "vst2", "16"> { - let Inst{5} = 1; -} -def VST2LNq32b: VST2LN<0b1001, "vst2", "32"> { - let Inst{6} = 1; -} +def VST2LNq16b: VST2LN<0b0101, "vst2", "16"> { let Inst{5} = 1; } +def VST2LNq32b: VST2LN<0b1001, "vst2", "32"> { let Inst{6} = 1; } // VST3LN : Vector Store (single 3-element structure from one lane) class VST3LN op11_8, string OpcodeStr, string Dt> : NLdSt<1,0b00,op11_8,{?,?,?,?}, (outs), - (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, - nohash_imm:$lane), IIC_VST, - OpcodeStr, Dt, - "\\{$src1[$lane], $src2[$lane], $src3[$lane]\\}, $addr", "", []>; + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, + nohash_imm:$lane), IIC_VST, OpcodeStr, Dt, + "\\{$src1[$lane], $src2[$lane], $src3[$lane]\\}, $addr", "", []>; // vst3 to single-spaced registers. -def VST3LNd8 : VST3LN<0b0010, "vst3", "8"> { - let Inst{4} = 0; -} -def VST3LNd16 : VST3LN<0b0110, "vst3", "16"> { - let Inst{5-4} = 0b00; -} -def VST3LNd32 : VST3LN<0b1010, "vst3", "32"> { - let Inst{6-4} = 0b000; -} +def VST3LNd8 : VST3LN<0b0010, "vst3", "8"> { let Inst{4} = 0; } +def VST3LNd16 : VST3LN<0b0110, "vst3", "16"> { let Inst{5-4} = 0b00; } +def VST3LNd32 : VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b000; } // vst3 to double-spaced even registers. -def VST3LNq16a: VST3LN<0b0110, "vst3", "16"> { - let Inst{5-4} = 0b10; -} -def VST3LNq32a: VST3LN<0b1010, "vst3", "32"> { - let Inst{6-4} = 0b100; -} +def VST3LNq16a: VST3LN<0b0110, "vst3", "16"> { let Inst{5-4} = 0b10; } +def VST3LNq32a: VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b100; } // vst3 to double-spaced odd registers. -def VST3LNq16b: VST3LN<0b0110, "vst3", "16"> { - let Inst{5-4} = 0b10; -} -def VST3LNq32b: VST3LN<0b1010, "vst3", "32"> { - let Inst{6-4} = 0b100; -} +def VST3LNq16b: VST3LN<0b0110, "vst3", "16"> { let Inst{5-4} = 0b10; } +def VST3LNq32b: VST3LN<0b1010, "vst3", "32"> { let Inst{6-4} = 0b100; } // VST4LN : Vector Store (single 4-element structure from one lane) class VST4LN op11_8, string OpcodeStr, string Dt> : NLdSt<1,0b00,op11_8,{?,?,?,?}, (outs), - (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, - nohash_imm:$lane), IIC_VST, - OpcodeStr, Dt, + (ins addrmode6:$addr, DPR:$src1, DPR:$src2, DPR:$src3, DPR:$src4, + nohash_imm:$lane), IIC_VST, OpcodeStr, Dt, "\\{$src1[$lane], $src2[$lane], $src3[$lane], $src4[$lane]\\}, $addr", - "", []>; + "", []>; // vst4 to single-spaced registers. def VST4LNd8 : VST4LN<0b0011, "vst4", "8">; -def VST4LNd16 : VST4LN<0b0111, "vst4", "16"> { - let Inst{5} = 0; -} -def VST4LNd32 : VST4LN<0b1011, "vst4", "32"> { - let Inst{6} = 0; -} +def VST4LNd16 : VST4LN<0b0111, "vst4", "16"> { let Inst{5} = 0; } +def VST4LNd32 : VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 0; } // vst4 to double-spaced even registers. -def VST4LNq16a: VST4LN<0b0111, "vst4", "16"> { - let Inst{5} = 1; -} -def VST4LNq32a: VST4LN<0b1011, "vst4", "32"> { - let Inst{6} = 1; -} +def VST4LNq16a: VST4LN<0b0111, "vst4", "16"> { let Inst{5} = 1; } +def VST4LNq32a: VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 1; } // vst4 to double-spaced odd registers. -def VST4LNq16b: VST4LN<0b0111, "vst4", "16"> { - let Inst{5} = 1; -} -def VST4LNq32b: VST4LN<0b1011, "vst4", "32"> { - let Inst{6} = 1; -} +def VST4LNq16b: VST4LN<0b0111, "vst4", "16"> { let Inst{5} = 1; } +def VST4LNq32b: VST4LN<0b1011, "vst4", "32"> { let Inst{6} = 1; } } // mayStore = 1, hasExtraSrcRegAllocReq = 1 @@ -656,34 +639,26 @@ def SubReg_i32_lane : SDNodeXForm op24_23, bits<2> op21_20, bits<2> op19_18, + bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr, + string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode> + : N2V; class N2VD op24_23, bits<2> op21_20, bits<2> op19_18, - bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,string Dt, - ValueType ResTy, ValueType OpTy, SDNode OpNode> + bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr, + string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode> : N2V; class N2VQ op24_23, bits<2> op21_20, bits<2> op19_18, - bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,string Dt, - ValueType ResTy, ValueType OpTy, SDNode OpNode> + bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr, + string Dt, ValueType ResTy, ValueType OpTy, SDNode OpNode> : N2V; -// Basic 2-register operations, scalar single-precision. -class N2VDs op24_23, bits<2> op21_20, bits<2> op19_18, - bits<2> op17_16, bits<5> op11_7, bit op4, string OpcodeStr,string Dt, - ValueType ResTy, ValueType OpTy, SDNode OpNode> - : N2V; - -class N2VDsPat - : NEONFPPat<(ResTy (OpNode SPR:$a)), - (EXTRACT_SUBREG - (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)), SPR:$a, arm_ssubreg_0)), - arm_ssubreg_0)>; - // Basic 2-register intrinsics, both double- and quad-register. class N2VDInt op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16, bits<5> op11_7, bit op4, @@ -700,21 +675,6 @@ class N2VQInt op24_23, bits<2> op21_20, bits<2> op19_18, (ins QPR:$src), itin, OpcodeStr, Dt, "$dst, $src", "", [(set QPR:$dst, (ResTy (IntOp (OpTy QPR:$src))))]>; -// Basic 2-register intrinsics, scalar single-precision -class N2VDInts op24_23, bits<2> op21_20, bits<2> op19_18, - bits<2> op17_16, bits<5> op11_7, bit op4, - InstrItinClass itin, string OpcodeStr, string Dt, - ValueType ResTy, ValueType OpTy, Intrinsic IntOp> - : N2V; - -class N2VDIntsPat - : NEONFPPat<(f32 (OpNode SPR:$a)), - (EXTRACT_SUBREG - (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$a, arm_ssubreg_0)), - arm_ssubreg_0)>; - // Narrow 2-register intrinsics. class N2VNInt op24_23, bits<2> op21_20, bits<2> op19_18, bits<2> op17_16, bits<5> op11_7, bit op6, bit op4, @@ -742,15 +702,22 @@ class N2VDShuffle op19_18, bits<5> op11_7, string OpcodeStr, string Dt> class N2VQShuffle op19_18, bits<5> op11_7, InstrItinClass itin, string OpcodeStr, string Dt> : N2V<0b11, 0b11, op19_18, 0b10, op11_7, 1, 0, (outs QPR:$dst1, QPR:$dst2), - (ins QPR:$src1, QPR:$src2), itin, - OpcodeStr, Dt, "$dst1, $dst2", + (ins QPR:$src1, QPR:$src2), itin, OpcodeStr, Dt, "$dst1, $dst2", "$src1 = $dst1, $src2 = $dst2", []>; -// Basic 3-register operations, both double- and quad-register. +// Basic 3-register operations: single-, double- and quad-register. +class N3VS op21_20, bits<4> op11_8, bit op4, + string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, + SDNode OpNode, bit Commutable> + : N3V { + let isCommutable = Commutable; +} + class N3VD op21_20, bits<4> op11_8, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, - ValueType ResTy, ValueType OpTy, - SDNode OpNode, bit Commutable> + ValueType ResTy, ValueType OpTy, SDNode OpNode, bit Commutable> : N3V op21_20, bits<4> op11_8, bit op4, ValueType ResTy, ValueType OpTy, SDNode OpNode, bit Commutable> : N3VX { + (outs DPR:$dst), (ins DPR:$src1, DPR:$src2), itin, + OpcodeStr, "$dst, $src1, $src2", "", + [(set DPR:$dst, (ResTy (OpNode (OpTy DPR:$src1), (OpTy DPR:$src2))))]>{ let isCommutable = Commutable; } class N3VDSL op21_20, bits<4> op11_8, @@ -776,27 +743,23 @@ class N3VDSL op21_20, bits<4> op11_8, itin, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", [(set (Ty DPR:$dst), (Ty (ShOp (Ty DPR:$src1), - (Ty (NEONvduplane (Ty DPR_VFP2:$src2), - imm:$lane)))))]> { + (Ty (NEONvduplane (Ty DPR_VFP2:$src2), imm:$lane)))))]>{ let isCommutable = 0; } class N3VDSL16 op21_20, bits<4> op11_8, string OpcodeStr, string Dt, ValueType Ty, SDNode ShOp> : N3V<0, 1, op21_20, op11_8, 1, 0, (outs DPR:$dst), (ins DPR:$src1, DPR_8:$src2, nohash_imm:$lane), - IIC_VMULi16D, - OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + IIC_VMULi16D, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", [(set (Ty DPR:$dst), (Ty (ShOp (Ty DPR:$src1), - (Ty (NEONvduplane (Ty DPR_8:$src2), - imm:$lane)))))]> { + (Ty (NEONvduplane (Ty DPR_8:$src2), imm:$lane)))))]> { let isCommutable = 0; } class N3VQ op21_20, bits<4> op11_8, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, - ValueType ResTy, ValueType OpTy, - SDNode OpNode, bit Commutable> + ValueType ResTy, ValueType OpTy, SDNode OpNode, bit Commutable> : N3V op21_20, bits<4> op11_8, bit op4, } class N3VQX op21_20, bits<4> op11_8, bit op4, InstrItinClass itin, string OpcodeStr, - ValueType ResTy, ValueType OpTy, - SDNode OpNode, bit Commutable> + ValueType ResTy, ValueType OpTy, SDNode OpNode, bit Commutable> : N3VX { + (outs QPR:$dst), (ins QPR:$src1, QPR:$src2), itin, + OpcodeStr, "$dst, $src1, $src2", "", + [(set QPR:$dst, (ResTy (OpNode (OpTy QPR:$src1), (OpTy QPR:$src2))))]>{ let isCommutable = Commutable; } class N3VQSL op21_20, bits<4> op11_8, @@ -825,13 +787,11 @@ class N3VQSL op21_20, bits<4> op11_8, imm:$lane)))))]> { let isCommutable = 0; } -class N3VQSL16 op21_20, bits<4> op11_8, - string OpcodeStr, string Dt, +class N3VQSL16 op21_20, bits<4> op11_8, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, SDNode ShOp> : N3V<1, 1, op21_20, op11_8, 1, 0, (outs QPR:$dst), (ins QPR:$src1, DPR_8:$src2, nohash_imm:$lane), - IIC_VMULi16Q, - OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", + IIC_VMULi16Q, OpcodeStr, Dt, "$dst, $src1, $src2[$lane]", "", [(set (ResTy QPR:$dst), (ResTy (ShOp (ResTy QPR:$src1), (ResTy (NEONvduplane (OpTy DPR_8:$src2), @@ -839,27 +799,10 @@ class N3VQSL16 op21_20, bits<4> op11_8, let isCommutable = 0; } -// Basic 3-register operations, scalar single-precision -class N3VDs op21_20, bits<4> op11_8, bit op4, - string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, - SDNode OpNode, bit Commutable> - : N3V { - let isCommutable = Commutable; -} -class N3VDsPat - : NEONFPPat<(f32 (OpNode SPR:$a, SPR:$b)), - (EXTRACT_SUBREG - (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$a, arm_ssubreg_0), - (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$b, arm_ssubreg_0)), - arm_ssubreg_0)>; - // Basic 3-register intrinsics, both double- and quad-register. class N3VDInt op21_20, bits<4> op11_8, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, - ValueType ResTy, ValueType OpTy, - Intrinsic IntOp, bit Commutable> + ValueType ResTy, ValueType OpTy, Intrinsic IntOp, bit Commutable> : N3V op21_20, bits<4> op11_8, InstrItinClass itin, class N3VQInt op21_20, bits<4> op11_8, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, - ValueType ResTy, ValueType OpTy, - Intrinsic IntOp, bit Commutable> + ValueType ResTy, ValueType OpTy, Intrinsic IntOp, bit Commutable> : N3V op21_20, bits<4> op11_8, InstrItinClass itin, let isCommutable = 0; } -// Multiply-Add/Sub operations, both double- and quad-register. +// Multiply-Add/Sub operations: single-, double- and quad-register. +class N3VSMulOp op21_20, bits<4> op11_8, bit op4, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType Ty, SDNode MulOp, SDNode OpNode> + : N3V; + class N3VDMulOp op21_20, bits<4> op11_8, bit op4, InstrItinClass itin, string OpcodeStr, string Dt, ValueType Ty, SDNode MulOp, SDNode OpNode> @@ -976,8 +926,8 @@ class N3VQMulOpSL op21_20, bits<4> op11_8, InstrItinClass itin, [(set (ResTy QPR:$dst), (ResTy (ShOp (ResTy QPR:$src1), (ResTy (MulOp QPR:$src2, - (ResTy (NEONvduplane (OpTy DPR_VFP2:$src3), - imm:$lane)))))))]>; + (ResTy (NEONvduplane (OpTy DPR_VFP2:$src3), + imm:$lane)))))))]>; class N3VQMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, @@ -989,25 +939,8 @@ class N3VQMulOpSL16 op21_20, bits<4> op11_8, InstrItinClass itin, [(set (ResTy QPR:$dst), (ResTy (ShOp (ResTy QPR:$src1), (ResTy (MulOp QPR:$src2, - (ResTy (NEONvduplane (OpTy DPR_8:$src3), - imm:$lane)))))))]>; - -// Multiply-Add/Sub operations, scalar single-precision -class N3VDMulOps op21_20, bits<4> op11_8, bit op4, - InstrItinClass itin, string OpcodeStr, string Dt, - ValueType Ty, SDNode MulOp, SDNode OpNode> - : N3V; - -class N3VDMulOpsPat - : NEONFPPat<(f32 (OpNode SPR:$acc, (f32 (MulNode SPR:$a, SPR:$b)))), - (EXTRACT_SUBREG - (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$acc, arm_ssubreg_0), - (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$a, arm_ssubreg_0), - (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), SPR:$b, arm_ssubreg_0)), - arm_ssubreg_0)>; + (ResTy (NEONvduplane (OpTy DPR_8:$src3), + imm:$lane)))))))]>; // Neon 3-argument intrinsics, both double- and quad-register. // The destination register is also used as the first source operand register. @@ -1050,9 +983,9 @@ class N3VLInt3SL op21_20, bits<4> op11_8, InstrItinClass itin, (OpTy DPR:$src2), (OpTy (NEONvduplane (OpTy DPR_VFP2:$src3), imm:$lane)))))]>; -class N3VLInt3SL16 op21_20, bits<4> op11_8, InstrItinClass itin, - string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, - Intrinsic IntOp> +class N3VLInt3SL16 op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> : N3V op21_20, bits<4> op11_8, InstrItinClass iti (OpTy (NEONvduplane (OpTy DPR_8:$src3), imm:$lane)))))]>; - // Narrowing 3-register intrinsics. class N3VNInt op21_20, bits<4> op11_8, bit op4, string OpcodeStr, string Dt, ValueType TyD, ValueType TyQ, @@ -1095,9 +1027,9 @@ class N3VLIntSL op21_20, bits<4> op11_8, InstrItinClass itin, (ResTy (IntOp (OpTy DPR:$src1), (OpTy (NEONvduplane (OpTy DPR_VFP2:$src2), imm:$lane)))))]>; -class N3VLIntSL16 op21_20, bits<4> op11_8, InstrItinClass itin, - string OpcodeStr, string Dt, ValueType ResTy, ValueType OpTy, - Intrinsic IntOp> +class N3VLIntSL16 op21_20, bits<4> op11_8, + InstrItinClass itin, string OpcodeStr, string Dt, + ValueType ResTy, ValueType OpTy, Intrinsic IntOp> : N3V op11_8, bit op7, bit op4, // S = single int (32 bit) elements // D = double int (64 bit) elements +// Neon 2-register vector operations -- for disassembly only. + +// First with only element sizes of 8, 16 and 32 bits: +multiclass N2V_QHS_cmp op24_23, bits<2> op21_20, bits<2> op17_16, + bits<5> op11_7, bit op4, string opc, string Dt, + string asm> { + // 64-bit vector types. + def v8i8 : N2V; + def v4i16 : N2V; + def v2i32 : N2V; + def v2f32 : N2V { + let Inst{10} = 1; // overwrite F = 1 + } + + // 128-bit vector types. + def v16i8 : N2V; + def v8i16 : N2V; + def v4i32 : N2V; + def v4f32 : N2V { + let Inst{10} = 1; // overwrite F = 1 + } +} + // Neon 3-register vector operations. // First with only element sizes of 8, 16 and 32 bits: @@ -1262,22 +1233,22 @@ multiclass N3V_QHS op11_8, bit op4, OpcodeStr, !strconcat(Dt, "8"), v8i8, v8i8, OpNode, Commutable>; def v4i16 : N3VD; + OpcodeStr, !strconcat(Dt, "16"), + v4i16, v4i16, OpNode, Commutable>; def v2i32 : N3VD; + OpcodeStr, !strconcat(Dt, "32"), + v2i32, v2i32, OpNode, Commutable>; // 128-bit vector types. def v16i8 : N3VQ; + OpcodeStr, !strconcat(Dt, "8"), + v16i8, v16i8, OpNode, Commutable>; def v8i16 : N3VQ; + OpcodeStr, !strconcat(Dt, "16"), + v8i16, v8i16, OpNode, Commutable>; def v4i32 : N3VQ; + OpcodeStr, !strconcat(Dt, "32"), + v4i32, v4i32, OpNode, Commutable>; } multiclass N3VSL_HS op11_8, string OpcodeStr, string Dt, SDNode ShOp> { @@ -1372,7 +1343,7 @@ multiclass N3VIntSL_HS op11_8, def v2i32 : N3VDIntSL<0b10, op11_8, itinD32, OpcodeStr, !strconcat(Dt, "32"), v2i32, IntOp>; def v8i16 : N3VQIntSL16<0b01, op11_8, itinQ16, - OpcodeStr, !strconcat(Dt, "16"), v8i16, v4i16, IntOp>; + OpcodeStr, !strconcat(Dt, "16"), v8i16, v4i16, IntOp>; def v4i32 : N3VQIntSL<0b10, op11_8, itinQ32, OpcodeStr, !strconcat(Dt, "32"), v4i32, v2i32, IntOp>; } @@ -1386,8 +1357,8 @@ multiclass N3VInt_QHS op11_8, bit op4, : N3VInt_HS { def v8i8 : N3VDInt; + OpcodeStr, !strconcat(Dt, "8"), + v8i8, v8i8, IntOp, Commutable>; def v16i8 : N3VQInt; @@ -1402,11 +1373,11 @@ multiclass N3VInt_QHSD op11_8, bit op4, : N3VInt_QHS { def v1i64 : N3VDInt; + OpcodeStr, !strconcat(Dt, "64"), + v1i64, v1i64, IntOp, Commutable>; def v2i64 : N3VQInt; + OpcodeStr, !strconcat(Dt, "64"), + v2i64, v2i64, IntOp, Commutable>; } @@ -1511,9 +1482,11 @@ multiclass N3VMulOpSL_HS op11_8, def v2i32 : N3VDMulOpSL<0b10, op11_8, itinD32, OpcodeStr, !strconcat(Dt, "32"), v2i32, mul, ShOp>; def v8i16 : N3VQMulOpSL16<0b01, op11_8, itinQ16, - OpcodeStr, !strconcat(Dt, "16"), v8i16, v4i16, mul, ShOp>; + OpcodeStr, !strconcat(Dt, "16"), v8i16, v4i16, + mul, ShOp>; def v4i32 : N3VQMulOpSL<0b10, op11_8, itinQ32, - OpcodeStr, !strconcat(Dt, "32"), v4i32, v2i32, mul, ShOp>; + OpcodeStr, !strconcat(Dt, "32"), v4i32, v2i32, + mul, ShOp>; } // Neon 3-argument intrinsics, @@ -1522,19 +1495,19 @@ multiclass N3VInt3_QHS op11_8, bit op4, string OpcodeStr, string Dt, Intrinsic IntOp> { // 64-bit vector types. def v8i8 : N3VDInt3; + OpcodeStr, !strconcat(Dt, "8"), v8i8, v8i8, IntOp>; def v4i16 : N3VDInt3; + OpcodeStr, !strconcat(Dt, "16"), v4i16, v4i16, IntOp>; def v2i32 : N3VDInt3; + OpcodeStr, !strconcat(Dt, "32"), v2i32, v2i32, IntOp>; // 128-bit vector types. def v16i8 : N3VQInt3; + OpcodeStr, !strconcat(Dt, "8"), v16i8, v16i8, IntOp>; def v8i16 : N3VQInt3; + OpcodeStr, !strconcat(Dt, "16"), v8i16, v8i16, IntOp>; def v4i32 : N3VQInt3; + OpcodeStr, !strconcat(Dt, "32"), v4i32, v4i32, IntOp>; } @@ -1576,17 +1549,17 @@ multiclass N2VInt_QHS op24_23, bits<2> op21_20, bits<2> op17_16, def v8i8 : N2VDInt; def v4i16 : N2VDInt; + itinD, OpcodeStr, !strconcat(Dt, "16"),v4i16,v4i16,IntOp>; def v2i32 : N2VDInt; + itinD, OpcodeStr, !strconcat(Dt, "32"),v2i32,v2i32,IntOp>; // 128-bit vector types. def v16i8 : N2VQInt; + itinQ, OpcodeStr, !strconcat(Dt, "8"), v16i8,v16i8,IntOp>; def v8i16 : N2VQInt; + itinQ, OpcodeStr, !strconcat(Dt, "16"),v8i16,v8i16,IntOp>; def v4i32 : N2VQInt; + itinQ, OpcodeStr, !strconcat(Dt, "32"),v4i32,v4i32,IntOp>; } @@ -1846,29 +1819,31 @@ def VMULpd : N3VDInt<1, 0, 0b00, 0b1001, 1, IIC_VMULi16D, "vmul", "p8", def VMULpq : N3VQInt<1, 0, 0b00, 0b1001, 1, IIC_VMULi16Q, "vmul", "p8", v16i8, v16i8, int_arm_neon_vmulp, 1>; def VMULfd : N3VD<1, 0, 0b00, 0b1101, 1, IIC_VBIND, "vmul", "f32", - v2f32, v2f32, fmul, 1>; + v2f32, v2f32, fmul, 1>; def VMULfq : N3VQ<1, 0, 0b00, 0b1101, 1, IIC_VBINQ, "vmul", "f32", - v4f32, v4f32, fmul, 1>; -defm VMULsl : N3VSL_HS<0b1000, "vmul", "i", mul>; -def VMULslfd : N3VDSL<0b10, 0b1001, IIC_VBIND, "vmul", "f32", v2f32, fmul>; -def VMULslfq : N3VQSL<0b10, 0b1001, IIC_VBINQ, "vmul", "f32", v4f32, v2f32, fmul>; + v4f32, v4f32, fmul, 1>; +defm VMULsl : N3VSL_HS<0b1000, "vmul", "i", mul>; +def VMULslfd : N3VDSL<0b10, 0b1001, IIC_VBIND, "vmul", "f32", v2f32, fmul>; +def VMULslfq : N3VQSL<0b10, 0b1001, IIC_VBINQ, "vmul", "f32", v4f32, + v2f32, fmul>; + def : Pat<(v8i16 (mul (v8i16 QPR:$src1), (v8i16 (NEONvduplane (v8i16 QPR:$src2), imm:$lane)))), (v8i16 (VMULslv8i16 (v8i16 QPR:$src1), (v4i16 (EXTRACT_SUBREG QPR:$src2, - (DSubReg_i16_reg imm:$lane))), + (DSubReg_i16_reg imm:$lane))), (SubReg_i16_lane imm:$lane)))>; def : Pat<(v4i32 (mul (v4i32 QPR:$src1), (v4i32 (NEONvduplane (v4i32 QPR:$src2), imm:$lane)))), (v4i32 (VMULslv4i32 (v4i32 QPR:$src1), (v2i32 (EXTRACT_SUBREG QPR:$src2, - (DSubReg_i32_reg imm:$lane))), + (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; def : Pat<(v4f32 (fmul (v4f32 QPR:$src1), (v4f32 (NEONvduplane (v4f32 QPR:$src2), imm:$lane)))), (v4f32 (VMULslfq (v4f32 QPR:$src1), (v2f32 (EXTRACT_SUBREG QPR:$src2, - (DSubReg_i32_reg imm:$lane))), + (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; // VQDMULH : Vector Saturating Doubling Multiply Returning High Half @@ -1883,14 +1858,14 @@ def : Pat<(v8i16 (int_arm_neon_vqdmulh (v8i16 QPR:$src1), imm:$lane)))), (v8i16 (VQDMULHslv8i16 (v8i16 QPR:$src1), (v4i16 (EXTRACT_SUBREG QPR:$src2, - (DSubReg_i16_reg imm:$lane))), + (DSubReg_i16_reg imm:$lane))), (SubReg_i16_lane imm:$lane)))>; def : Pat<(v4i32 (int_arm_neon_vqdmulh (v4i32 QPR:$src1), (v4i32 (NEONvduplane (v4i32 QPR:$src2), imm:$lane)))), (v4i32 (VQDMULHslv4i32 (v4i32 QPR:$src1), (v2i32 (EXTRACT_SUBREG QPR:$src2, - (DSubReg_i32_reg imm:$lane))), + (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; // VQRDMULH : Vector Rounding Saturating Doubling Multiply Returning High Half @@ -1905,14 +1880,14 @@ def : Pat<(v8i16 (int_arm_neon_vqrdmulh (v8i16 QPR:$src1), imm:$lane)))), (v8i16 (VQRDMULHslv8i16 (v8i16 QPR:$src1), (v4i16 (EXTRACT_SUBREG QPR:$src2, - (DSubReg_i16_reg imm:$lane))), + (DSubReg_i16_reg imm:$lane))), (SubReg_i16_lane imm:$lane)))>; def : Pat<(v4i32 (int_arm_neon_vqrdmulh (v4i32 QPR:$src1), (v4i32 (NEONvduplane (v4i32 QPR:$src2), imm:$lane)))), (v4i32 (VQRDMULHslv4i32 (v4i32 QPR:$src1), (v2i32 (EXTRACT_SUBREG QPR:$src2, - (DSubReg_i32_reg imm:$lane))), + (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; // VMULL : Vector Multiply Long (integer and polynomial) (Q = D * D) @@ -1950,30 +1925,28 @@ def VMLAslfq : N3VQMulOpSL<0b10, 0b0001, IIC_VMACQ, "vmla", "f32", v4f32, v2f32, fmul, fadd>; def : Pat<(v8i16 (add (v8i16 QPR:$src1), - (mul (v8i16 QPR:$src2), - (v8i16 (NEONvduplane (v8i16 QPR:$src3), imm:$lane))))), - (v8i16 (VMLAslv8i16 (v8i16 QPR:$src1), - (v8i16 QPR:$src2), + (mul (v8i16 QPR:$src2), + (v8i16 (NEONvduplane (v8i16 QPR:$src3), imm:$lane))))), + (v8i16 (VMLAslv8i16 (v8i16 QPR:$src1), (v8i16 QPR:$src2), (v4i16 (EXTRACT_SUBREG QPR:$src3, - (DSubReg_i16_reg imm:$lane))), + (DSubReg_i16_reg imm:$lane))), (SubReg_i16_lane imm:$lane)))>; def : Pat<(v4i32 (add (v4i32 QPR:$src1), - (mul (v4i32 QPR:$src2), - (v4i32 (NEONvduplane (v4i32 QPR:$src3), imm:$lane))))), - (v4i32 (VMLAslv4i32 (v4i32 QPR:$src1), - (v4i32 QPR:$src2), + (mul (v4i32 QPR:$src2), + (v4i32 (NEONvduplane (v4i32 QPR:$src3), imm:$lane))))), + (v4i32 (VMLAslv4i32 (v4i32 QPR:$src1), (v4i32 QPR:$src2), (v2i32 (EXTRACT_SUBREG QPR:$src3, - (DSubReg_i32_reg imm:$lane))), + (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; def : Pat<(v4f32 (fadd (v4f32 QPR:$src1), - (fmul (v4f32 QPR:$src2), - (v4f32 (NEONvduplane (v4f32 QPR:$src3), imm:$lane))))), + (fmul (v4f32 QPR:$src2), + (v4f32 (NEONvduplane (v4f32 QPR:$src3), imm:$lane))))), (v4f32 (VMLAslfq (v4f32 QPR:$src1), (v4f32 QPR:$src2), (v2f32 (EXTRACT_SUBREG QPR:$src3, - (DSubReg_i32_reg imm:$lane))), + (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; // VMLAL : Vector Multiply Accumulate Long (Q += D * D) @@ -2003,30 +1976,27 @@ def VMLSslfq : N3VQMulOpSL<0b10, 0b0101, IIC_VMACQ, "vmls", "f32", v4f32, v2f32, fmul, fsub>; def : Pat<(v8i16 (sub (v8i16 QPR:$src1), - (mul (v8i16 QPR:$src2), - (v8i16 (NEONvduplane (v8i16 QPR:$src3), imm:$lane))))), - (v8i16 (VMLSslv8i16 (v8i16 QPR:$src1), - (v8i16 QPR:$src2), + (mul (v8i16 QPR:$src2), + (v8i16 (NEONvduplane (v8i16 QPR:$src3), imm:$lane))))), + (v8i16 (VMLSslv8i16 (v8i16 QPR:$src1), (v8i16 QPR:$src2), (v4i16 (EXTRACT_SUBREG QPR:$src3, - (DSubReg_i16_reg imm:$lane))), + (DSubReg_i16_reg imm:$lane))), (SubReg_i16_lane imm:$lane)))>; def : Pat<(v4i32 (sub (v4i32 QPR:$src1), - (mul (v4i32 QPR:$src2), - (v4i32 (NEONvduplane (v4i32 QPR:$src3), imm:$lane))))), - (v4i32 (VMLSslv4i32 (v4i32 QPR:$src1), - (v4i32 QPR:$src2), + (mul (v4i32 QPR:$src2), + (v4i32 (NEONvduplane (v4i32 QPR:$src3), imm:$lane))))), + (v4i32 (VMLSslv4i32 (v4i32 QPR:$src1), (v4i32 QPR:$src2), (v2i32 (EXTRACT_SUBREG QPR:$src3, - (DSubReg_i32_reg imm:$lane))), + (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; def : Pat<(v4f32 (fsub (v4f32 QPR:$src1), - (fmul (v4f32 QPR:$src2), - (v4f32 (NEONvduplane (v4f32 QPR:$src3), imm:$lane))))), - (v4f32 (VMLSslfq (v4f32 QPR:$src1), - (v4f32 QPR:$src2), + (fmul (v4f32 QPR:$src2), + (v4f32 (NEONvduplane (v4f32 QPR:$src3), imm:$lane))))), + (v4f32 (VMLSslfq (v4f32 QPR:$src1), (v4f32 QPR:$src2), (v2f32 (EXTRACT_SUBREG QPR:$src3, - (DSubReg_i32_reg imm:$lane))), + (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane)))>; // VMLSL : Vector Multiply Subtract Long (Q -= D * D) @@ -2088,6 +2058,10 @@ def VCEQfd : N3VD<0,0,0b00,0b1110,0, IIC_VBIND, "vceq", "f32", v2i32, v2f32, NEONvceq, 1>; def VCEQfq : N3VQ<0,0,0b00,0b1110,0, IIC_VBINQ, "vceq", "f32", v4i32, v4f32, NEONvceq, 1>; +// For disassembly only. +defm VCEQz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00010, 0, "vceq", "i", + "$dst, $src, #0">; + // VCGE : Vector Compare Greater Than or Equal defm VCGEs : N3V_QHS<0, 0, 0b0011, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, "vcge", "s", NEONvcge, 0>; @@ -2097,6 +2071,13 @@ def VCGEfd : N3VD<1,0,0b00,0b1110,0, IIC_VBIND, "vcge", "f32", v2i32, v2f32, NEONvcge, 0>; def VCGEfq : N3VQ<1,0,0b00,0b1110,0, IIC_VBINQ, "vcge", "f32", v4i32, v4f32, NEONvcge, 0>; +// For disassembly only. +defm VCGEz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00001, 0, "vcge", "s", + "$dst, $src, #0">; +// For disassembly only. +defm VCLEz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00011, 0, "vcle", "s", + "$dst, $src, #0">; + // VCGT : Vector Compare Greater Than defm VCGTs : N3V_QHS<0, 0, 0b0011, 0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, "vcgt", "s", NEONvcgt, 0>; @@ -2106,6 +2087,13 @@ def VCGTfd : N3VD<1,0,0b10,0b1110,0, IIC_VBIND, "vcgt", "f32", v2i32, v2f32, NEONvcgt, 0>; def VCGTfq : N3VQ<1,0,0b10,0b1110,0, IIC_VBINQ, "vcgt", "f32", v4i32, v4f32, NEONvcgt, 0>; +// For disassembly only. +defm VCGTz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00000, 0, "vcgt", "s", + "$dst, $src, #0">; +// For disassembly only. +defm VCLTz : N2V_QHS_cmp<0b11, 0b11, 0b01, 0b00100, 0, "vclt", "s", + "$dst, $src, #0">; + // VACGE : Vector Absolute Compare Greater Than or Equal (aka VCAGE) def VACGEd : N3VDInt<1, 0, 0b00, 0b1110, 1, IIC_VBIND, "vacge", "f32", v2i32, v2f32, int_arm_neon_vacged, 0>; @@ -2247,9 +2235,9 @@ defm VABALu : N3VLInt3_QHS<1,1,0b0101,0, "vabal", "u", int_arm_neon_vabalu>; // Vector Maximum and Minimum. // VMAX : Vector Maximum -defm VMAXs : N3VInt_QHS<0, 0, 0b0110, 0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, +defm VMAXs : N3VInt_QHS<0,0,0b0110,0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, "vmax", "s", int_arm_neon_vmaxs, 1>; -defm VMAXu : N3VInt_QHS<1, 0, 0b0110, 0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, +defm VMAXu : N3VInt_QHS<1,0,0b0110,0, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, "vmax", "u", int_arm_neon_vmaxu, 1>; def VMAXfd : N3VDInt<0, 0, 0b00, 0b1111, 0, IIC_VBIND, "vmax", "f32", v2f32, v2f32, int_arm_neon_vmaxs, 1>; @@ -2257,9 +2245,9 @@ def VMAXfq : N3VQInt<0, 0, 0b00, 0b1111, 0, IIC_VBINQ, "vmax", "f32", v4f32, v4f32, int_arm_neon_vmaxs, 1>; // VMIN : Vector Minimum -defm VMINs : N3VInt_QHS<0, 0, 0b0110, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, +defm VMINs : N3VInt_QHS<0,0,0b0110,1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, "vmin", "s", int_arm_neon_vmins, 1>; -defm VMINu : N3VInt_QHS<1, 0, 0b0110, 1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, +defm VMINu : N3VInt_QHS<1,0,0b0110,1, IIC_VBINi4D, IIC_VBINi4D, IIC_VBINi4Q, IIC_VBINi4Q, "vmin", "u", int_arm_neon_vminu, 1>; def VMINfd : N3VDInt<0, 0, 0b10, 0b1111, 0, IIC_VBIND, "vmin", "f32", v2f32, v2f32, int_arm_neon_vmins, 1>; @@ -2401,16 +2389,17 @@ def VSHLLi32 : N2VLShMax<1, 1, 0b111010, 0b0011, 0, 0, 0, "vshll", "i32", v2i64, v2i32, NEONvshlli>; // VSHRN : Vector Shift Right and Narrow -defm VSHRN : N2VNSh_HSD<0,1,0b1000,0,0,1, IIC_VSHLiD, "vshrn", "i", NEONvshrn>; +defm VSHRN : N2VNSh_HSD<0,1,0b1000,0,0,1, IIC_VSHLiD, "vshrn", "i", + NEONvshrn>; // VRSHL : Vector Rounding Shift defm VRSHLs : N3VInt_QHSD<0,0,0b0101,0, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, - IIC_VSHLi4Q, "vrshl", "s", int_arm_neon_vrshifts, 0>; + IIC_VSHLi4Q, "vrshl", "s", int_arm_neon_vrshifts,0>; defm VRSHLu : N3VInt_QHSD<1,0,0b0101,0, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, - IIC_VSHLi4Q, "vrshl", "u", int_arm_neon_vrshiftu, 0>; + IIC_VSHLi4Q, "vrshl", "u", int_arm_neon_vrshiftu,0>; // VRSHR : Vector Rounding Shift Right -defm VRSHRs : N2VSh_QHSD<0, 1, 0b0010, 1, IIC_VSHLi4D, "vrshr", "s", NEONvrshrs>; -defm VRSHRu : N2VSh_QHSD<1, 1, 0b0010, 1, IIC_VSHLi4D, "vrshr", "u", NEONvrshru>; +defm VRSHRs : N2VSh_QHSD<0,1,0b0010,1, IIC_VSHLi4D, "vrshr", "s", NEONvrshrs>; +defm VRSHRu : N2VSh_QHSD<1,1,0b0010,1, IIC_VSHLi4D, "vrshr", "u", NEONvrshru>; // VRSHRN : Vector Rounding Shift Right and Narrow defm VRSHRN : N2VNSh_HSD<0, 1, 0b1000, 0, 1, 1, IIC_VSHLi4D, "vrshrn", "i", @@ -2418,14 +2407,14 @@ defm VRSHRN : N2VNSh_HSD<0, 1, 0b1000, 0, 1, 1, IIC_VSHLi4D, "vrshrn", "i", // VQSHL : Vector Saturating Shift defm VQSHLs : N3VInt_QHSD<0,0,0b0100,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, - IIC_VSHLi4Q, "vqshl", "s", int_arm_neon_vqshifts, 0>; + IIC_VSHLi4Q, "vqshl", "s", int_arm_neon_vqshifts,0>; defm VQSHLu : N3VInt_QHSD<1,0,0b0100,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, - IIC_VSHLi4Q, "vqshl", "u", int_arm_neon_vqshiftu, 0>; + IIC_VSHLi4Q, "vqshl", "u", int_arm_neon_vqshiftu,0>; // VQSHL : Vector Saturating Shift Left (Immediate) -defm VQSHLsi : N2VSh_QHSD<0, 1, 0b0111, 1, IIC_VSHLi4D, "vqshl", "s", NEONvqshls>; -defm VQSHLui : N2VSh_QHSD<1, 1, 0b0111, 1, IIC_VSHLi4D, "vqshl", "u", NEONvqshlu>; +defm VQSHLsi : N2VSh_QHSD<0,1,0b0111,1, IIC_VSHLi4D, "vqshl", "s", NEONvqshls>; +defm VQSHLui : N2VSh_QHSD<1,1,0b0111,1, IIC_VSHLi4D, "vqshl", "u", NEONvqshlu>; // VQSHLU : Vector Saturating Shift Left (Immediate, Unsigned) -defm VQSHLsu : N2VSh_QHSD<1, 1, 0b0110, 1, IIC_VSHLi4D, "vqshlu", "s", NEONvqshlsu>; +defm VQSHLsu : N2VSh_QHSD<1,1,0b0110,1, IIC_VSHLi4D, "vqshlu","s",NEONvqshlsu>; // VQSHRN : Vector Saturating Shift Right and Narrow defm VQSHRNs : N2VNSh_HSD<0, 1, 0b1001, 0, 0, 1, IIC_VSHLi4D, "vqshrn", "s", @@ -2438,10 +2427,10 @@ defm VQSHRUN : N2VNSh_HSD<1, 1, 0b1000, 0, 0, 1, IIC_VSHLi4D, "vqshrun", "s", NEONvqshrnsu>; // VQRSHL : Vector Saturating Rounding Shift -defm VQRSHLs : N3VInt_QHSD<0, 0, 0b0101, 1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, +defm VQRSHLs : N3VInt_QHSD<0,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, "vqrshl", "s", int_arm_neon_vqrshifts, 0>; -defm VQRSHLu : N3VInt_QHSD<1, 0, 0b0101, 1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, +defm VQRSHLu : N3VInt_QHSD<1,0,0b0101,1, IIC_VSHLi4D, IIC_VSHLi4D, IIC_VSHLi4Q, IIC_VSHLi4Q, "vqrshl", "u", int_arm_neon_vqrshiftu, 0>; @@ -2508,7 +2497,7 @@ def VNEGs16q : VNEGQ<0b01, "vneg", "s16", v8i16>; def VNEGs32q : VNEGQ<0b10, "vneg", "s32", v4i32>; // VNEG : Vector Negate (floating-point) -def VNEGf32d : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 0, 0, +def VNEGfd : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 0, 0, (outs DPR:$dst), (ins DPR:$src), IIC_VUNAD, "vneg", "f32", "$dst, $src", "", [(set DPR:$dst, (v2f32 (fneg DPR:$src)))]>; @@ -2547,6 +2536,14 @@ def VCNTq : N2VQInt<0b11, 0b11, 0b00, 0b00, 0b01010, 0, IIC_VCNTiQ, "vcnt", "8", v16i8, v16i8, int_arm_neon_vcnt>; +// Vector Swap -- for disassembly only. +def VSWPd : N2VX<0b11, 0b11, 0b00, 0b10, 0b00000, 0, 0, + (outs DPR:$dst), (ins DPR:$src), NoItinerary, + "vswp", "$dst, $src", "", []>; +def VSWPq : N2VX<0b11, 0b11, 0b00, 0b10, 0b00000, 1, 0, + (outs QPR:$dst), (ins QPR:$src), NoItinerary, + "vswp", "$dst, $src", "", []>; + // Vector Move Operations. // VMOV : Vector Move (Register) @@ -2678,10 +2675,10 @@ def : Pat<(extractelt (v4i32 QPR:$src), imm:$lane), (DSubReg_i32_reg imm:$lane))), (SubReg_i32_lane imm:$lane))>; def : Pat<(extractelt (v2f32 DPR:$src1), imm:$src2), - (EXTRACT_SUBREG (v2f32 (COPY_TO_REGCLASS (v2f32 DPR:$src1), DPR_VFP2)), + (EXTRACT_SUBREG (v2f32 (COPY_TO_REGCLASS (v2f32 DPR:$src1),DPR_VFP2)), (SSubReg_f32_reg imm:$src2))>; def : Pat<(extractelt (v4f32 QPR:$src1), imm:$src2), - (EXTRACT_SUBREG (v4f32 (COPY_TO_REGCLASS (v4f32 QPR:$src1), QPR_VFP2)), + (EXTRACT_SUBREG (v4f32 (COPY_TO_REGCLASS (v4f32 QPR:$src1),QPR_VFP2)), (SSubReg_f32_reg imm:$src2))>; //def : Pat<(extractelt (v2i64 QPR:$src1), imm:$src2), // (EXTRACT_SUBREG QPR:$src1, (DSubReg_f64_reg imm:$src2))>; @@ -2849,11 +2846,13 @@ def VDUPfqf : N2V<0b11, 0b11, {?,1}, {0,0}, 0b11000, 1, 0, def : Pat<(v2i64 (NEONvduplane (v2i64 QPR:$src), imm:$lane)), (INSERT_SUBREG QPR:$src, - (i64 (EXTRACT_SUBREG QPR:$src, (DSubReg_f64_reg imm:$lane))), + (i64 (EXTRACT_SUBREG QPR:$src, + (DSubReg_f64_reg imm:$lane))), (DSubReg_f64_other_reg imm:$lane))>; def : Pat<(v2f64 (NEONvduplane (v2f64 QPR:$src), imm:$lane)), (INSERT_SUBREG QPR:$src, - (f64 (EXTRACT_SUBREG QPR:$src, (DSubReg_f64_reg imm:$lane))), + (f64 (EXTRACT_SUBREG QPR:$src, + (DSubReg_f64_reg imm:$lane))), (DSubReg_f64_other_reg imm:$lane))>; // VMOVN : Vector Narrowing Move @@ -3092,70 +3091,110 @@ def VTBX4 // NEON instructions for single-precision FP math //===----------------------------------------------------------------------===// +class N2VSPat + : NEONFPPat<(ResTy (OpNode SPR:$a)), + (EXTRACT_SUBREG (Inst (INSERT_SUBREG (OpTy (IMPLICIT_DEF)), + SPR:$a, arm_ssubreg_0)), + arm_ssubreg_0)>; + +class N3VSPat + : NEONFPPat<(f32 (OpNode SPR:$a, SPR:$b)), + (EXTRACT_SUBREG (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), + SPR:$a, arm_ssubreg_0), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), + SPR:$b, arm_ssubreg_0)), + arm_ssubreg_0)>; + +class N3VSMulOpPat + : NEONFPPat<(f32 (OpNode SPR:$acc, (f32 (MulNode SPR:$a, SPR:$b)))), + (EXTRACT_SUBREG (Inst (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), + SPR:$acc, arm_ssubreg_0), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), + SPR:$a, arm_ssubreg_0), + (INSERT_SUBREG (v2f32 (IMPLICIT_DEF)), + SPR:$b, arm_ssubreg_0)), + arm_ssubreg_0)>; + // These need separate instructions because they must use DPR_VFP2 register // class which have SPR sub-registers. // Vector Add Operations used for single-precision FP let neverHasSideEffects = 1 in -def VADDfd_sfp : N3VDs<0, 0, 0b00, 0b1101, 0, "vadd", "f32", v2f32, v2f32, fadd,1>; -def : N3VDsPat; +def VADDfd_sfp : N3VS<0,0,0b00,0b1101,0, "vadd", "f32", v2f32, v2f32, fadd, 1>; +def : N3VSPat; // Vector Sub Operations used for single-precision FP let neverHasSideEffects = 1 in -def VSUBfd_sfp : N3VDs<0, 0, 0b10, 0b1101, 0, "vsub", "f32", v2f32, v2f32, fsub,0>; -def : N3VDsPat; +def VSUBfd_sfp : N3VS<0,0,0b10,0b1101,0, "vsub", "f32", v2f32, v2f32, fsub, 0>; +def : N3VSPat; // Vector Multiply Operations used for single-precision FP let neverHasSideEffects = 1 in -def VMULfd_sfp : N3VDs<1, 0, 0b00, 0b1101, 1, "vmul", "f32", v2f32, v2f32, fmul,1>; -def : N3VDsPat; +def VMULfd_sfp : N3VS<1,0,0b00,0b1101,1, "vmul", "f32", v2f32, v2f32, fmul, 1>; +def : N3VSPat; // Vector Multiply-Accumulate/Subtract used for single-precision FP // vml[as].f32 can cause 4-8 cycle stalls in following ASIMD instructions, so // we want to avoid them for now. e.g., alternating vmla/vadd instructions. //let neverHasSideEffects = 1 in -//def VMLAfd_sfp : N3VDMulOps<0, 0, 0b00, 0b1101, 1, IIC_VMACD, "vmla", "f32", v2f32,fmul,fadd>; -//def : N3VDMulOpsPat; +//def VMLAfd_sfp : N3VSMulOp<0,0,0b00,0b1101,1, IIC_VMACD, "vmla", "f32", +// v2f32, fmul, fadd>; +//def : N3VSMulOpPat; //let neverHasSideEffects = 1 in -//def VMLSfd_sfp : N3VDMulOps<0, 0, 0b10, 0b1101, 1, IIC_VMACD, "vmls", "f32", v2f32,fmul,fsub>; -//def : N3VDMulOpsPat; +//def VMLSfd_sfp : N3VSMulOp<0,0,0b10,0b1101,1, IIC_VMACD, "vmls", "f32", +// v2f32, fmul, fsub>; +//def : N3VSMulOpPat; // Vector Absolute used for single-precision FP let neverHasSideEffects = 1 in -def VABSfd_sfp : N2VDInts<0b11, 0b11, 0b10, 0b01, 0b01110, 0, - IIC_VUNAD, "vabs", "f32", - v2f32, v2f32, int_arm_neon_vabs>; -def : N2VDIntsPat; +def VABSfd_sfp : N2V<0b11, 0b11, 0b10, 0b01, 0b01110, 0, 0, + (outs DPR_VFP2:$dst), (ins DPR_VFP2:$src), IIC_VUNAD, + "vabs", "f32", "$dst, $src", "", []>; +def : N2VSPat; // Vector Negate used for single-precision FP let neverHasSideEffects = 1 in -def VNEGf32d_sfp : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 0, 0, - (outs DPR_VFP2:$dst), (ins DPR_VFP2:$src), IIC_VUNAD, - "vneg", "f32", "$dst, $src", "", []>; -def : N2VDIntsPat; +def VNEGfd_sfp : N2V<0b11, 0b11, 0b10, 0b01, 0b01111, 0, 0, + (outs DPR_VFP2:$dst), (ins DPR_VFP2:$src), IIC_VUNAD, + "vneg", "f32", "$dst, $src", "", []>; +def : N2VSPat; + +// Vector Maximum used for single-precision FP +let neverHasSideEffects = 1 in +def VMAXfd_sfp : N3V<0, 0, 0b00, 0b1111, 0, 0, (outs DPR_VFP2:$dst), + (ins DPR_VFP2:$src1, DPR_VFP2:$src2), IIC_VBIND, + "vmax", "f32", "$dst, $src1, $src2", "", []>; +def : N3VSPat; + +// Vector Minimum used for single-precision FP +let neverHasSideEffects = 1 in +def VMINfd_sfp : N3V<0, 0, 0b00, 0b1111, 0, 0, (outs DPR_VFP2:$dst), + (ins DPR_VFP2:$src1, DPR_VFP2:$src2), IIC_VBIND, + "vmin", "f32", "$dst, $src1, $src2", "", []>; +def : N3VSPat; // Vector Convert between single-precision FP and integer let neverHasSideEffects = 1 in -def VCVTf2sd_sfp : N2VDs<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32", - v2i32, v2f32, fp_to_sint>; -def : N2VDsPat; +def VCVTf2sd_sfp : N2VS<0b11, 0b11, 0b10, 0b11, 0b01110, 0, "vcvt", "s32.f32", + v2i32, v2f32, fp_to_sint>; +def : N2VSPat; let neverHasSideEffects = 1 in -def VCVTf2ud_sfp : N2VDs<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32", - v2i32, v2f32, fp_to_uint>; -def : N2VDsPat; +def VCVTf2ud_sfp : N2VS<0b11, 0b11, 0b10, 0b11, 0b01111, 0, "vcvt", "u32.f32", + v2i32, v2f32, fp_to_uint>; +def : N2VSPat; let neverHasSideEffects = 1 in -def VCVTs2fd_sfp : N2VDs<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32", - v2f32, v2i32, sint_to_fp>; -def : N2VDsPat; +def VCVTs2fd_sfp : N2VS<0b11, 0b11, 0b10, 0b11, 0b01100, 0, "vcvt", "f32.s32", + v2f32, v2i32, sint_to_fp>; +def : N2VSPat; let neverHasSideEffects = 1 in -def VCVTu2fd_sfp : N2VDs<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32", - v2f32, v2i32, uint_to_fp>; -def : N2VDsPat; +def VCVTu2fd_sfp : N2VS<0b11, 0b11, 0b10, 0b11, 0b01101, 0, "vcvt", "f32.u32", + v2f32, v2i32, uint_to_fp>; +def : N2VSPat; //===----------------------------------------------------------------------===// // Non-Instruction Patterns diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 1dcea26bc5..786dd65b87 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -120,7 +120,10 @@ def t_addrmode_sp : Operand, // Miscellaneous Instructions. // -let Defs = [SP], Uses = [SP] in { +// FIXME: Marking these as hasSideEffects is necessary to prevent machine DCE +// from removing one half of the matched pairs. That breaks PEI, which assumes +// these will always be in pairs, and asserts if it finds otherwise. Better way? +let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { def tADJCALLSTACKUP : PseudoInst<(outs), (ins i32imm:$amt1, i32imm:$amt2), NoItinerary, "@ tADJCALLSTACKUP $amt1", @@ -132,6 +135,76 @@ PseudoInst<(outs), (ins i32imm:$amt), NoItinerary, [(ARMcallseq_start imm:$amt)]>, Requires<[IsThumb1Only]>; } +def tNOP : T1pI<(outs), (ins), NoItinerary, "nop", "", + [/* For disassembly only; pattern left blank */]>, + T1Encoding<0b101111> { + let Inst{9-8} = 0b11; + let Inst{7-0} = 0b00000000; +} + +def tYIELD : T1pI<(outs), (ins), NoItinerary, "yield", "", + [/* For disassembly only; pattern left blank */]>, + T1Encoding<0b101111> { + let Inst{9-8} = 0b11; + let Inst{7-0} = 0b00010000; +} + +def tWFE : T1pI<(outs), (ins), NoItinerary, "wfe", "", + [/* For disassembly only; pattern left blank */]>, + T1Encoding<0b101111> { + let Inst{9-8} = 0b11; + let Inst{7-0} = 0b00100000; +} + +def tWFI : T1pI<(outs), (ins), NoItinerary, "wfi", "", + [/* For disassembly only; pattern left blank */]>, + T1Encoding<0b101111> { + let Inst{9-8} = 0b11; + let Inst{7-0} = 0b00110000; +} + +def tSEV : T1pI<(outs), (ins), NoItinerary, "sev", "", + [/* For disassembly only; pattern left blank */]>, + T1Encoding<0b101111> { + let Inst{9-8} = 0b11; + let Inst{7-0} = 0b01000000; +} + +def tSETENDBE : T1I<(outs), (ins), NoItinerary, "setend\tbe", + [/* For disassembly only; pattern left blank */]>, + T1Encoding<0b101101> { + let Inst{9-5} = 0b10010; + let Inst{3} = 1; +} + +def tSETENDLE : T1I<(outs), (ins), NoItinerary, "setend\tle", + [/* For disassembly only; pattern left blank */]>, + T1Encoding<0b101101> { + let Inst{9-5} = 0b10010; + let Inst{3} = 0; +} + +// The i32imm operand $val can be used by a debugger to store more information +// about the breakpoint. +def tBKPT : T1I<(outs), (ins i32imm:$val), NoItinerary, "bkpt\t$val", + [/* For disassembly only; pattern left blank */]>, + T1Encoding<0b101111> { + let Inst{9-8} = 0b10; +} + +// Change Processor State is a system instruction -- for disassembly only. +// The singleton $opt operand contains the following information: +// opt{4-0} = mode ==> don't care +// opt{5} = changemode ==> 0 (false for 16-bit Thumb instr) +// opt{8-6} = AIF from Inst{2-0} +// opt{10-9} = 1:imod from Inst{4} with 0b10 as enable and 0b11 as disable +// +// The opt{4-0} and opt{5} sub-fields are to accommodate 32-bit Thumb and ARM +// CPS which has more options. +def tCPS : T1I<(outs), (ins i32imm:$opt), NoItinerary, "cps${opt:cps}", + [/* For disassembly only; pattern left blank */]>, + T1Misc<0b0110011>; + // For both thumb1 and thumb2. let isNotDuplicable = 1 in def tPICADD : TIt<(outs GPR:$dst), (ins GPR:$lhs, pclabel:$cp), IIC_iALUr, @@ -200,7 +273,7 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1 in { let Inst{6-3} = 0b1110; // Rm = lr } // Alternative return instruction used by vararg functions. - def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target", []>, + def tBX_RET_vararg : TI<(outs), (ins tGPR:$target), IIC_Br, "bx\t$target",[]>, T1Special<{1,1,0,?}>; // A6.2.3 & A8.6.25 } @@ -228,20 +301,20 @@ let isCall = 1, D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { // Also used for Thumb2 def tBL : TIx2<0b11110, 0b11, 1, - (outs), (ins i32imm:$func, variable_ops), IIC_Br, + (outs), (ins i32imm:$func, variable_ops), IIC_Br, "bl\t${func:call}", [(ARMtcall tglobaladdr:$func)]>, Requires<[IsThumb, IsNotDarwin]>; // ARMv5T and above, also used for Thumb2 def tBLXi : TIx2<0b11110, 0b11, 0, - (outs), (ins i32imm:$func, variable_ops), IIC_Br, + (outs), (ins i32imm:$func, variable_ops), IIC_Br, "blx\t${func:call}", [(ARMcall tglobaladdr:$func)]>, Requires<[IsThumb, HasV5T, IsNotDarwin]>; // Also used for Thumb2 - def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, + def tBLXr : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, "blx\t$func", [(ARMtcall GPR:$func)]>, Requires<[IsThumb, HasV5T, IsNotDarwin]>, @@ -249,7 +322,7 @@ let isCall = 1, // ARMv4T def tBX : TIx2<{?,?,?,?,?}, {?,?}, ?, - (outs), (ins tGPR:$func, variable_ops), IIC_Br, + (outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", [(ARMcall_nolink tGPR:$func)]>, Requires<[IsThumb1Only, IsNotDarwin]>; @@ -263,20 +336,20 @@ let isCall = 1, D24, D25, D26, D27, D28, D29, D30, D31, CPSR, FPSCR] in { // Also used for Thumb2 def tBLr9 : TIx2<0b11110, 0b11, 1, - (outs), (ins i32imm:$func, variable_ops), IIC_Br, + (outs), (ins i32imm:$func, variable_ops), IIC_Br, "bl\t${func:call}", [(ARMtcall tglobaladdr:$func)]>, Requires<[IsThumb, IsDarwin]>; // ARMv5T and above, also used for Thumb2 def tBLXi_r9 : TIx2<0b11110, 0b11, 0, - (outs), (ins i32imm:$func, variable_ops), IIC_Br, + (outs), (ins i32imm:$func, variable_ops), IIC_Br, "blx\t${func:call}", [(ARMcall tglobaladdr:$func)]>, Requires<[IsThumb, HasV5T, IsDarwin]>; // Also used for Thumb2 - def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, + def tBLXr_r9 : TI<(outs), (ins GPR:$func, variable_ops), IIC_Br, "blx\t$func", [(ARMtcall GPR:$func)]>, Requires<[IsThumb, HasV5T, IsDarwin]>, @@ -284,7 +357,7 @@ let isCall = 1, // ARMv4T def tBXr9 : TIx2<{?,?,?,?,?}, {?,?}, ?, - (outs), (ins tGPR:$func, variable_ops), IIC_Br, + (outs), (ins tGPR:$func, variable_ops), IIC_Br, "mov\tlr, pc\n\tbx\t$func", [(ARMcall_nolink tGPR:$func)]>, Requires<[IsThumb1Only, IsDarwin]>; @@ -299,7 +372,7 @@ let isBranch = 1, isTerminator = 1 in { // Far jump let Defs = [LR] in - def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br, + def tBfar : TIx2<0b11110, 0b11, 1, (outs), (ins brtarget:$target), IIC_Br, "bl\t$target\t@ far jump",[]>; def tBR_JTr : T1JTI<(outs), @@ -332,16 +405,34 @@ let isBranch = 1, isTerminator = 1 in { T1Misc<{1,0,?,1,?,?,?}>; } +// A8.6.218 Supervisor Call (Software Interrupt) -- for disassembly only +// A8.6.16 B: Encoding T1 +// If Inst{11-8} == 0b1111 then SEE SVC +let isCall = 1 in { +def tSVC : T1pI<(outs), (ins i32imm:$svc), IIC_Br, "svc", "\t$svc", []>, + Encoding16 { + let Inst{15-12} = 0b1101; + let Inst{11-8} = 0b1111; +} +} + +// A8.6.16 B: Encoding T1 -- for disassembly only +// If Inst{11-8} == 0b1110 then UNDEFINED +def tTRAP : T1I<(outs), (ins), IIC_Br, "trap", []>, Encoding16 { + let Inst{15-12} = 0b1101; + let Inst{11-8} = 0b1110; +} + //===----------------------------------------------------------------------===// // Load Store Instructions. // -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in -def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, +let canFoldAsLoad = 1, isReMaterializable = 1 in +def tLDR : T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, "ldr", "\t$dst, $addr", [(set tGPR:$dst, (load t_addrmode_s4:$addr))]>, T1LdSt<0b100>; -def tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, +def tLDRi: T1pI4<(outs tGPR:$dst), (ins t_addrmode_s4:$addr), IIC_iLoadr, "ldr", "\t$dst, $addr", []>, T1LdSt4Imm<{1,?,?}>; @@ -391,15 +482,14 @@ def tRestore : T1pIs<(outs tGPR:$dst), (ins t_addrmode_sp:$addr), IIC_iLoadi, // Load tconstpool // FIXME: Use ldr.n to work around a Darwin assembler bug. -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def tLDRpci : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, "ldr", ".n\t$dst, $addr", [(set tGPR:$dst, (load (ARMWrapper tconstpool:$addr)))]>, T1Encoding<{0,1,0,0,1,?}>; // A6.2 & A8.6.59 // Special LDR for loads from non-pc-relative constpools. -let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1, - mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, mayLoad = 1, isReMaterializable = 1 in def tLDRcp : T1pIs<(outs tGPR:$dst), (ins i32imm:$addr), IIC_iLoadi, "ldr", "\t$dst, $addr", []>, T1LdStSP<{1,?,?}>; @@ -644,7 +734,7 @@ def tMOVgpr2gpr : T1I<(outs GPR:$dst), (ins GPR:$src), IIC_iMOVr, // multiply register let isCommutable = 1 in def tMUL : T1sIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs), IIC_iMUL32, - "mul", "\t$dst, $rhs", + "mul", "\t$dst, $rhs, $dst", /* A8.6.105 MUL Encoding T1 */ [(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>, T1DataProcessing<0b1101>; @@ -761,7 +851,7 @@ def tUXTH : T1pI<(outs tGPR:$dst), (ins tGPR:$src), IIC_iUNAr, T1Misc<{0,0,1,0,1,0,?}>; -// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC DAG operation. +// Conditional move tMOVCCr - Used to implement the Thumb SELECT_CC operation. // Expanded after instruction selection into a branch sequence. let usesCustomInserter = 1 in // Expanded after instruction selection. def tMOVCCr_pseudo : diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 55c7aa2bd8..6241766a32 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -13,7 +13,7 @@ // IT block predicate field def it_pred : Operand { - let PrintMethod = "printPredicateOperand"; + let PrintMethod = "printMandatoryPredicateOperand"; } // IT block condition mask @@ -53,10 +53,10 @@ def t2_so_imm_neg_XFORM : SDNodeXForm, PatLeaf<(imm), [{ - return ARM_AM::getT2SOImmVal((uint32_t)N->getZExtValue()) != -1; + return ARM_AM::getT2SOImmVal((uint32_t)N->getZExtValue()) != -1; }]>; -// t2_so_imm_not - Match an immediate that is a complement +// t2_so_imm_not - Match an immediate that is a complement // of a t2_so_imm. def t2_so_imm_not : Operand, PatLeaf<(imm), [{ @@ -114,13 +114,13 @@ def imm0_4095 : Operand, return (uint32_t)N->getZExtValue() < 4096; }]>; -def imm0_4095_neg : PatLeaf<(i32 imm), [{ - return (uint32_t)(-N->getZExtValue()) < 4096; -}], imm_neg_XFORM>; +def imm0_4095_neg : PatLeaf<(i32 imm), [{ + return (uint32_t)(-N->getZExtValue()) < 4096; +}], imm_neg_XFORM>; def imm0_255_neg : PatLeaf<(i32 imm), [{ return (uint32_t)(-N->getZExtValue()) < 255; -}], imm_neg_XFORM>; +}], imm_neg_XFORM>; // Define Thumb2 specific addressing modes. @@ -131,7 +131,7 @@ def t2addrmode_imm12 : Operand, let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } -// t2addrmode_imm8 := reg - imm8 +// t2addrmode_imm8 := reg +/- imm8 def t2addrmode_imm8 : Operand, ComplexPattern { let PrintMethod = "printT2AddrModeImm8Operand"; @@ -208,7 +208,7 @@ multiclass T2I_un_irs opcod, string opc, PatFrag opnode, /// T2I_bin_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns for a // binary operation that produces a value. These are predicable and can be /// changed to modify CPSR. -multiclass T2I_bin_irs opcod, string opc, PatFrag opnode, +multiclass T2I_bin_irs opcod, string opc, PatFrag opnode, bit Commutable = 0, string wide =""> { // shifted imm def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, @@ -368,15 +368,16 @@ multiclass T2I_bin_ii12rs op23_21, string opc, PatFrag opnode, } /// T2I_adde_sube_irs - Defines a set of (op reg, {so_imm|r|so_reg}) patterns -/// for a binary operation that produces a value and use and define the carry +/// for a binary operation that produces a value and use the carry /// bit. It's not predicable. let Uses = [CPSR] in { -multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, bit Commutable = 0> { +multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { // shifted imm def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, opc, "\t$dst, $lhs, $rhs", [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, - Requires<[IsThumb2, CarryDefIsUnused]> { + Requires<[IsThumb2]> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = opcod; @@ -387,7 +388,7 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, bit Comm def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, opc, ".w\t$dst, $lhs, $rhs", [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, - Requires<[IsThumb2, CarryDefIsUnused]> { + Requires<[IsThumb2]> { let isCommutable = Commutable; let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; @@ -401,19 +402,23 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, bit Comm def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, opc, ".w\t$dst, $lhs, $rhs", [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, - Requires<[IsThumb2, CarryDefIsUnused]> { + Requires<[IsThumb2]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; let Inst{20} = 0; // The S bit. } - // Carry setting variants +} + +// Carry setting variants +let Defs = [CPSR] in { +multiclass T2I_adde_sube_s_irs opcod, string opc, PatFrag opnode, + bit Commutable = 0> { // shifted imm - def Sri : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, - !strconcat(opc, "s\t$dst, $lhs, $rhs"), - [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, - Requires<[IsThumb2, CarryDefIsUsed]> { - let Defs = [CPSR]; + def ri : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_imm:$rhs), IIC_iALUi, + opc, "\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>, + Requires<[IsThumb2]> { let Inst{31-27} = 0b11110; let Inst{25} = 0; let Inst{24-21} = opcod; @@ -421,11 +426,10 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, bit Comm let Inst{15} = 0; } // register - def Srr : T2XI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, - !strconcat(opc, "s.w\t$dst, $lhs, $rhs"), - [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, - Requires<[IsThumb2, CarryDefIsUsed]> { - let Defs = [CPSR]; + def rr : T2sI<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs), IIC_iALUr, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>, + Requires<[IsThumb2]> { let isCommutable = Commutable; let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; @@ -436,11 +440,10 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, bit Comm let Inst{5-4} = 0b00; // type } // shifted register - def Srs : T2XI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, - !strconcat(opc, "s.w\t$dst, $lhs, $rhs"), - [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, - Requires<[IsThumb2, CarryDefIsUsed]> { - let Defs = [CPSR]; + def rs : T2sI<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs), IIC_iALUsi, + opc, ".w\t$dst, $lhs, $rhs", + [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>, + Requires<[IsThumb2]> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b01; let Inst{24-21} = opcod; @@ -448,6 +451,7 @@ multiclass T2I_adde_sube_irs opcod, string opc, PatFrag opnode, bit Comm } } } +} /// T2I_rbin_s_is - Same as T2I_rbin_is except sets 's' bit. let Defs = [CPSR] in { @@ -626,19 +630,6 @@ multiclass T2I_st opcod, string opc, PatFrag opnode> { } } -/// T2I_picld - Defines the PIC load pattern. -class T2I_picld : - T2I<(outs GPR:$dst), (ins addrmodepc:$addr), IIC_iLoadi, - !strconcat("\n${addr:label}:\n\t", opc), "\t$dst, $addr", - [(set GPR:$dst, (opnode addrmodepc:$addr))]>; - -/// T2I_picst - Defines the PIC store pattern. -class T2I_picst : - T2I<(outs), (ins GPR:$src, addrmodepc:$addr), IIC_iStorer, - !strconcat("\n${addr:label}:\n\t", opc), "\t$src, $addr", - [(opnode GPR:$src, addrmodepc:$addr)]>; - - /// T2I_unary_rrot - A unary operation with two forms: one whose operand is a /// register and one whose operand is a register rotated by 8/16/24. multiclass T2I_unary_rrot opcod, string opc, PatFrag opnode> { @@ -666,6 +657,57 @@ multiclass T2I_unary_rrot opcod, string opc, PatFrag opnode> { } } +// SXTB16 and UXTB16 do not need the .w qualifier. +multiclass T2I_unary_rrot_nw opcod, string opc, PatFrag opnode> { + def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + opc, "\t$dst, $src", + [(set GPR:$dst, (opnode GPR:$src))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{19-16} = 0b1111; // Rn + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = 0b00; // rotate + } + def r_rot : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$rot), IIC_iUNAsi, + opc, "\t$dst, $src, ror $rot", + [(set GPR:$dst, (opnode (rotr GPR:$src, rot_imm:$rot)))]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{19-16} = 0b1111; // Rn + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = {?,?}; // rotate + } +} + +// DO variant - disassembly only, no pattern + +multiclass T2I_unary_rrot_DO opcod, string opc> { + def r : T2I<(outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, + opc, "\t$dst, $src", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{19-16} = 0b1111; // Rn + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = 0b00; // rotate + } + def r_rot : T2I<(outs GPR:$dst), (ins GPR:$src, i32imm:$rot), IIC_iUNAsi, + opc, "\t$dst, $src, ror $rot", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{19-16} = 0b1111; // Rn + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = {?,?}; // rotate + } +} + /// T2I_bin_rrot - A binary operation with two forms: one whose operand is a /// register and one whose operand is a register rotated by 8/16/24. multiclass T2I_bin_rrot opcod, string opc, PatFrag opnode> { @@ -692,6 +734,29 @@ multiclass T2I_bin_rrot opcod, string opc, PatFrag opnode> { } } +// DO variant - disassembly only, no pattern + +multiclass T2I_bin_rrot_DO opcod, string opc> { + def rr : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS), IIC_iALUr, + opc, "\t$dst, $LHS, $RHS", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = 0b00; // rotate + } + def rr_rot : T2I<(outs GPR:$dst), (ins GPR:$LHS, GPR:$RHS, i32imm:$rot), + IIC_iALUsr, opc, "\t$dst, $LHS, $RHS, ror $rot", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0100; + let Inst{22-20} = opcod; + let Inst{15-12} = 0b1111; + let Inst{7} = 1; + let Inst{5-4} = {?,?}; // rotate + } +} + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -734,7 +799,7 @@ def t2ADDrSPi : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), let Inst{19-16} = 0b1101; // Rn = sp let Inst{15} = 0; } -def t2ADDrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm), +def t2ADDrSPi12 : T2I<(outs GPR:$dst), (ins GPR:$sp, imm0_4095:$imm), IIC_iALUi, "addw", "\t$dst, $sp, $imm", []> { let Inst{31-27} = 0b11110; let Inst{25} = 1; @@ -787,6 +852,25 @@ def t2SUBrSPs : T2sI<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), let Inst{15} = 0; } +// Signed and unsigned division, for disassembly only +def t2SDIV : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iALUi, + "sdiv", "\t$dst, $a, $b", []> { + let Inst{31-27} = 0b11111; + let Inst{26-21} = 0b011100; + let Inst{20} = 0b1; + let Inst{15-12} = 0b1111; + let Inst{7-4} = 0b1111; +} + +def t2UDIV : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iALUi, + "udiv", "\t$dst, $a, $b", []> { + let Inst{31-27} = 0b11111; + let Inst{26-21} = 0b011101; + let Inst{20} = 0b1; + let Inst{15-12} = 0b1111; + let Inst{7-4} = 0b1111; +} + // Pseudo instruction that will expand into a t2SUBrSPi + a copy. let usesCustomInserter = 1 in { // Expanded after instruction selection. def t2SUBrSPi_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_imm:$imm), @@ -803,7 +887,7 @@ def t2SUBrSPs_ : PseudoInst<(outs GPR:$dst), (ins GPR:$sp, t2_so_reg:$rhs), // // Load -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in defm t2LDR : T2I_ld<0, 0b10, "ldr", UnOpFrag<(load node:$Src)>>; // Loads with zero extension @@ -925,10 +1009,32 @@ def t2LDRSH_POST : T2Iidxldst<1, 0b01, 1, 0, (outs GPR:$dst, GPR:$base_wb), []>; } +// LDRT, LDRBT, LDRHT, LDRSBT, LDRSHT all have offset mode (PUW=0b110) and are +// for disassembly only. +// Ref: A8.6.57 LDR (immediate, Thumb) Encoding T4 +class T2IldT type, string opc> + : T2Ii8<(outs GPR:$dst), (ins t2addrmode_imm8:$addr), IIC_iLoadi, opc, + "\t$dst, $addr", []> { + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = signed; + let Inst{23} = 0; + let Inst{22-21} = type; + let Inst{20} = 1; // load + let Inst{11} = 1; + let Inst{10-8} = 0b110; // PUW. +} + +def t2LDRT : T2IldT<0, 0b10, "ldrt">; +def t2LDRBT : T2IldT<0, 0b00, "ldrbt">; +def t2LDRHT : T2IldT<0, 0b01, "ldrht">; +def t2LDRSBT : T2IldT<1, 0b00, "ldrsbt">; +def t2LDRSHT : T2IldT<1, 0b01, "ldrsht">; + // Store -defm t2STR : T2I_st<0b10, "str", BinOpFrag<(store node:$LHS, node:$RHS)>>; -defm t2STRB : T2I_st<0b00, "strb", BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; -defm t2STRH : T2I_st<0b01, "strh", BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; +defm t2STR :T2I_st<0b10,"str", BinOpFrag<(store node:$LHS, node:$RHS)>>; +defm t2STRB:T2I_st<0b00,"strb",BinOpFrag<(truncstorei8 node:$LHS, node:$RHS)>>; +defm t2STRH:T2I_st<0b01,"strh",BinOpFrag<(truncstorei16 node:$LHS, node:$RHS)>>; // Store doubleword let mayLoad = 1, hasExtraSrcRegAllocReq = 1 in @@ -979,9 +1085,98 @@ def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb), [(set GPR:$base_wb, (post_truncsti8 GPR:$src, GPR:$base, t2am_imm8_offset:$offset))]>; +// STRT, STRBT, STRHT all have offset mode (PUW=0b110) and are for disassembly +// only. +// Ref: A8.6.193 STR (immediate, Thumb) Encoding T4 +class T2IstT type, string opc> + : T2Ii8<(outs GPR:$src), (ins t2addrmode_imm8:$addr), IIC_iStorei, opc, + "\t$src, $addr", []> { + let Inst{31-27} = 0b11111; + let Inst{26-25} = 0b00; + let Inst{24} = 0; // not signed + let Inst{23} = 0; + let Inst{22-21} = type; + let Inst{20} = 0; // store + let Inst{11} = 1; + let Inst{10-8} = 0b110; // PUW +} + +def t2STRT : T2IstT<0b10, "strt">; +def t2STRBT : T2IstT<0b00, "strbt">; +def t2STRHT : T2IstT<0b01, "strht">; // FIXME: ldrd / strd pre / post variants +// T2Ipl (Preload Data/Instruction) signals the memory system of possible future +// data/instruction access. These are for disassembly only. +multiclass T2Ipl { + + def i12 : T2I<(outs), (ins t2addrmode_imm12:$addr), IIC_iLoadi, opc, + "\t$addr", []> { + let Inst{31-25} = 0b1111100; + let Inst{24} = instr; + let Inst{23} = 1; // U = 1 + let Inst{22} = 0; + let Inst{21} = write; + let Inst{20} = 1; + let Inst{15-12} = 0b1111; + } + + def i8 : T2I<(outs), (ins t2addrmode_imm8:$addr), IIC_iLoadi, opc, + "\t$addr", []> { + let Inst{31-25} = 0b1111100; + let Inst{24} = instr; + let Inst{23} = 0; // U = 0 + let Inst{22} = 0; + let Inst{21} = write; + let Inst{20} = 1; + let Inst{15-12} = 0b1111; + let Inst{11-8} = 0b1100; + } + + // A8.6.118 #0 and #-0 differs. Translates -0 to -1, -1 to -2, ..., etc. + def pci : T2I<(outs), (ins GPR:$base, i32imm:$imm), IIC_iLoadi, opc, + "\t[pc, ${imm:negzero}]", []> { + let Inst{31-25} = 0b1111100; + let Inst{24} = instr; + let Inst{23} = ?; // add = (U == 1) + let Inst{22} = 0; + let Inst{21} = write; + let Inst{20} = 1; + let Inst{19-16} = 0b1111; // Rn = 0b1111 + let Inst{15-12} = 0b1111; + } + + def r : T2I<(outs), (ins GPR:$base, GPR:$a), IIC_iLoadi, opc, + "\t[$base, $a]", []> { + let Inst{31-25} = 0b1111100; + let Inst{24} = instr; + let Inst{23} = 0; // add = TRUE for T1 + let Inst{22} = 0; + let Inst{21} = write; + let Inst{20} = 1; + let Inst{15-12} = 0b1111; + let Inst{11-6} = 0000000; + let Inst{5-4} = 0b00; // no shift is applied + } + + def s : T2I<(outs), (ins GPR:$base, GPR:$a, i32imm:$shamt), IIC_iLoadi, opc, + "\t[$base, $a, lsl $shamt]", []> { + let Inst{31-25} = 0b1111100; + let Inst{24} = instr; + let Inst{23} = 0; // add = TRUE for T1 + let Inst{22} = 0; + let Inst{21} = write; + let Inst{20} = 1; + let Inst{15-12} = 0b1111; + let Inst{11-6} = 0000000; + } +} + +defm t2PLD : T2Ipl<0, 0, "pld">; +defm t2PLDW : T2Ipl<0, 1, "pldw">; +defm t2PLI : T2Ipl<1, 0, "pli">; + //===----------------------------------------------------------------------===// // Load / store multiple Instructions. // @@ -989,7 +1184,7 @@ def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb), let mayLoad = 1, hasExtraDefRegAllocReq = 1 in def t2LDM : T2XI<(outs), (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), - IIC_iLoadm, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", []> { + IIC_iLoadm, "ldm${addr:submode}${p}${addr:wide}\t$addr, $wb", []> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b00; let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' @@ -1001,7 +1196,7 @@ def t2LDM : T2XI<(outs), let mayStore = 1, hasExtraSrcRegAllocReq = 1 in def t2STM : T2XI<(outs), (ins addrmode4:$addr, pred:$p, reglist:$wb, variable_ops), - IIC_iStorem, "stm${addr:submode}${p}${addr:wide}\t$addr, $wb", []> { + IIC_iStorem, "stm${addr:submode}${p}${addr:wide}\t$addr, $wb", []> { let Inst{31-27} = 0b11101; let Inst{26-25} = 0b00; let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' @@ -1074,13 +1269,15 @@ defm t2SXTB : T2I_unary_rrot<0b100, "sxtb", UnOpFrag<(sext_inreg node:$Src, i8)>>; defm t2SXTH : T2I_unary_rrot<0b000, "sxth", UnOpFrag<(sext_inreg node:$Src, i16)>>; +defm t2SXTB16 : T2I_unary_rrot_DO<0b010, "sxtb16">; defm t2SXTAB : T2I_bin_rrot<0b100, "sxtab", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS, i8))>>; defm t2SXTAH : T2I_bin_rrot<0b000, "sxtah", BinOpFrag<(add node:$LHS, (sext_inreg node:$RHS,i16))>>; +defm t2SXTAB16 : T2I_bin_rrot_DO<0b010, "sxtab16">; -// TODO: SXT(A){B|H}16 +// TODO: SXT(A){B|H}16 - done for disassembly only // Zero extenders @@ -1089,7 +1286,7 @@ defm t2UXTB : T2I_unary_rrot<0b101, "uxtb", UnOpFrag<(and node:$Src, 0x000000FF)>>; defm t2UXTH : T2I_unary_rrot<0b001, "uxth", UnOpFrag<(and node:$Src, 0x0000FFFF)>>; -defm t2UXTB16 : T2I_unary_rrot<0b011, "uxtb16", +defm t2UXTB16 : T2I_unary_rrot_nw<0b011, "uxtb16", UnOpFrag<(and node:$Src, 0x00FF00FF)>>; def : T2Pat<(and (shl GPR:$Src, (i32 8)), 0xFF00FF), @@ -1101,6 +1298,7 @@ defm t2UXTAB : T2I_bin_rrot<0b101, "uxtab", BinOpFrag<(add node:$LHS, (and node:$RHS, 0x00FF))>>; defm t2UXTAH : T2I_bin_rrot<0b001, "uxtah", BinOpFrag<(add node:$LHS, (and node:$RHS, 0xFFFF))>>; +defm t2UXTAB16 : T2I_bin_rrot_DO<0b011, "uxtab16">; } //===----------------------------------------------------------------------===// @@ -1119,9 +1317,13 @@ defm t2SUBS : T2I_bin_s_irs <0b1101, "sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>; defm t2ADC : T2I_adde_sube_irs<0b1010, "adc", - BinOpFrag<(adde node:$LHS, node:$RHS)>, 1>; + BinOpFrag<(adde_dead_carry node:$LHS, node:$RHS)>, 1>; defm t2SBC : T2I_adde_sube_irs<0b1011, "sbc", - BinOpFrag<(sube node:$LHS, node:$RHS)>>; + BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; +defm t2ADCS : T2I_adde_sube_s_irs<0b1010, "adc", + BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; +defm t2SBCS : T2I_adde_sube_s_irs<0b1011, "sbc", + BinOpFrag<(sube_live_carry node:$LHS, node:$RHS)>>; // RSB defm t2RSB : T2I_rbin_is <0b1110, "rsb", @@ -1138,6 +1340,155 @@ def : T2Pat<(add GPR:$src, t2_so_imm_neg:$imm), def : T2Pat<(add GPR:$src, imm0_4095_neg:$imm), (t2SUBri12 GPR:$src, imm0_4095_neg:$imm)>; +// Select Bytes -- for disassembly only + +def t2SEL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), NoItinerary, "sel", + "\t$dst, $a, $b", []> { + let Inst{31-27} = 0b11111; + let Inst{26-24} = 0b010; + let Inst{23} = 0b1; + let Inst{22-20} = 0b010; + let Inst{15-12} = 0b1111; + let Inst{7} = 0b1; + let Inst{6-4} = 0b000; +} + +// A6.3.13, A6.3.14, A6.3.15 Parallel addition and subtraction (signed/unsigned) +// And Miscellaneous operations -- for disassembly only +class T2I_pam op22_20, bits<4> op7_4, string opc> + : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), NoItinerary, opc, + "\t$dst, $a, $b", [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0101; + let Inst{22-20} = op22_20; + let Inst{15-12} = 0b1111; + let Inst{7-4} = op7_4; +} + +// Saturating add/subtract -- for disassembly only + +def t2QADD : T2I_pam<0b000, 0b1000, "qadd">; +def t2QADD16 : T2I_pam<0b001, 0b0001, "qadd16">; +def t2QADD8 : T2I_pam<0b000, 0b0001, "qadd8">; +def t2QASX : T2I_pam<0b010, 0b0001, "qasx">; +def t2QDADD : T2I_pam<0b000, 0b1001, "qdadd">; +def t2QDSUB : T2I_pam<0b000, 0b1011, "qdsub">; +def t2QSAX : T2I_pam<0b110, 0b0001, "qsax">; +def t2QSUB : T2I_pam<0b000, 0b1010, "qsub">; +def t2QSUB16 : T2I_pam<0b101, 0b0001, "qsub16">; +def t2QSUB8 : T2I_pam<0b100, 0b0001, "qsub8">; +def t2UQADD16 : T2I_pam<0b001, 0b0101, "uqadd16">; +def t2UQADD8 : T2I_pam<0b000, 0b0101, "uqadd8">; +def t2UQASX : T2I_pam<0b010, 0b0101, "uqasx">; +def t2UQSAX : T2I_pam<0b110, 0b0101, "uqsax">; +def t2UQSUB16 : T2I_pam<0b101, 0b0101, "uqsub16">; +def t2UQSUB8 : T2I_pam<0b100, 0b0101, "uqsub8">; + +// Signed/Unsigned add/subtract -- for disassembly only + +def t2SASX : T2I_pam<0b010, 0b0000, "sasx">; +def t2SADD16 : T2I_pam<0b001, 0b0000, "sadd16">; +def t2SADD8 : T2I_pam<0b000, 0b0000, "sadd8">; +def t2SSAX : T2I_pam<0b110, 0b0000, "ssax">; +def t2SSUB16 : T2I_pam<0b101, 0b0000, "ssub16">; +def t2SSUB8 : T2I_pam<0b100, 0b0000, "ssub8">; +def t2UASX : T2I_pam<0b010, 0b0100, "uasx">; +def t2UADD16 : T2I_pam<0b001, 0b0100, "uadd16">; +def t2UADD8 : T2I_pam<0b000, 0b0100, "uadd8">; +def t2USAX : T2I_pam<0b110, 0b0100, "usax">; +def t2USUB16 : T2I_pam<0b101, 0b0100, "usub16">; +def t2USUB8 : T2I_pam<0b100, 0b0100, "usub8">; + +// Signed/Unsigned halving add/subtract -- for disassembly only + +def t2SHASX : T2I_pam<0b010, 0b0010, "shasx">; +def t2SHADD16 : T2I_pam<0b001, 0b0010, "shadd16">; +def t2SHADD8 : T2I_pam<0b000, 0b0010, "shadd8">; +def t2SHSAX : T2I_pam<0b110, 0b0010, "shsax">; +def t2SHSUB16 : T2I_pam<0b101, 0b0010, "shsub16">; +def t2SHSUB8 : T2I_pam<0b100, 0b0010, "shsub8">; +def t2UHASX : T2I_pam<0b010, 0b0110, "uhasx">; +def t2UHADD16 : T2I_pam<0b001, 0b0110, "uhadd16">; +def t2UHADD8 : T2I_pam<0b000, 0b0110, "uhadd8">; +def t2UHSAX : T2I_pam<0b110, 0b0110, "uhsax">; +def t2UHSUB16 : T2I_pam<0b101, 0b0110, "uhsub16">; +def t2UHSUB8 : T2I_pam<0b100, 0b0110, "uhsub8">; + +// Unsigned Sum of Absolute Differences [and Accumulate] -- for disassembly only + +def t2USAD8 : T2I_mac<0, 0b111, 0b0000, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + NoItinerary, "usad8", "\t$dst, $a, $b", []> { + let Inst{15-12} = 0b1111; +} +def t2USADA8 : T2I_mac<0, 0b111, 0b0000, (outs GPR:$dst), + (ins GPR:$a, GPR:$b, GPR:$acc), NoItinerary, "usada8", + "\t$dst, $a, $b, $acc", []>; + +// Signed/Unsigned saturate -- for disassembly only + +def t2SSATlsl : T2I<(outs GPR:$dst), (ins i32imm:$bit_pos,GPR:$a,i32imm:$shamt), + NoItinerary, "ssat", "\t$dst, $bit_pos, $a, lsl $shamt", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{25-22} = 0b1100; + let Inst{20} = 0; + let Inst{15} = 0; + let Inst{21} = 0; // sh = '0' +} + +def t2SSATasr : T2I<(outs GPR:$dst), (ins i32imm:$bit_pos,GPR:$a,i32imm:$shamt), + NoItinerary, "ssat", "\t$dst, $bit_pos, $a, asr $shamt", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{25-22} = 0b1100; + let Inst{20} = 0; + let Inst{15} = 0; + let Inst{21} = 1; // sh = '1' +} + +def t2SSAT16 : T2I<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), NoItinerary, + "ssat16", "\t$dst, $bit_pos, $a", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{25-22} = 0b1100; + let Inst{20} = 0; + let Inst{15} = 0; + let Inst{21} = 1; // sh = '1' + let Inst{14-12} = 0b000; // imm3 = '000' + let Inst{7-6} = 0b00; // imm2 = '00' +} + +def t2USATlsl : T2I<(outs GPR:$dst), (ins i32imm:$bit_pos,GPR:$a,i32imm:$shamt), + NoItinerary, "usat", "\t$dst, $bit_pos, $a, lsl $shamt", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{25-22} = 0b1110; + let Inst{20} = 0; + let Inst{15} = 0; + let Inst{21} = 0; // sh = '0' +} + +def t2USATasr : T2I<(outs GPR:$dst), (ins i32imm:$bit_pos,GPR:$a,i32imm:$shamt), + NoItinerary, "usat", "\t$dst, $bit_pos, $a, asr $shamt", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{25-22} = 0b1110; + let Inst{20} = 0; + let Inst{15} = 0; + let Inst{21} = 1; // sh = '1' +} + +def t2USAT16 : T2I<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), NoItinerary, + "usat16", "\t$dst, $bit_pos, $a", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{25-22} = 0b1110; + let Inst{20} = 0; + let Inst{15} = 0; + let Inst{21} = 1; // sh = '1' + let Inst{14-12} = 0b000; // imm3 = '000' + let Inst{7-6} = 0b00; // imm2 = '00' +} //===----------------------------------------------------------------------===// // Shift and rotate Instructions. @@ -1342,6 +1693,8 @@ def t2UMAAL : T2I<(outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b), IIC_iMAC64, } } // neverHasSideEffects +// Rounding variants of the below included for disassembly only + // Most significant word multiply def t2SMMUL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, "smmul", "\t$dst, $a, $b", @@ -1353,6 +1706,15 @@ def t2SMMUL : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0) } +def t2SMMULR : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, + "smmulr", "\t$dst, $a, $b", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b101; + let Inst{15-12} = 0b1111; // Ra = 0b1111 (no accumulate) + let Inst{7-4} = 0b0001; // Rounding (Inst{4} = 1) +} + def t2SMMLA : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, "smmla", "\t$dst, $a, $b, $c", [(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]> { @@ -1363,6 +1725,14 @@ def t2SMMLA : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0) } +def t2SMMLAR : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, + "smmlar", "\t$dst, $a, $b, $c", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b101; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-4} = 0b0001; // Rounding (Inst{4} = 1) +} def t2SMMLS : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, "smmls", "\t$dst, $a, $b, $c", @@ -1374,6 +1744,15 @@ def t2SMMLS : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0) } +def t2SMMLSR : T2I <(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), IIC_iMAC32, + "smmlsr", "\t$dst, $a, $b, $c", []> { + let Inst{31-27} = 0b11111; + let Inst{26-23} = 0b0110; + let Inst{22-20} = 0b110; + let Inst{15-12} = {?, ?, ?, ?}; // Ra + let Inst{7-4} = 0b0001; // Rounding (Inst{4} = 1) +} + multiclass T2I_smul { def BB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b), IIC_iMUL32, !strconcat(opc, "bb"), "\t$dst, $a, $b", @@ -1466,7 +1845,7 @@ multiclass T2I_smla { def BT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "bt"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (opnode (sext_inreg GPR:$a, i16), - (sra GPR:$b, (i32 16)))))]> { + (sra GPR:$b, (i32 16)))))]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -1490,7 +1869,7 @@ multiclass T2I_smla { def TT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "tt"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (opnode (sra GPR:$a, (i32 16)), - (sra GPR:$b, (i32 16)))))]> { + (sra GPR:$b, (i32 16)))))]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b001; @@ -1502,7 +1881,7 @@ multiclass T2I_smla { def WB : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "wb"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, - (sext_inreg GPR:$b, i16)), (i32 16))))]> { + (sext_inreg GPR:$b, i16)), (i32 16))))]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b011; @@ -1514,7 +1893,7 @@ multiclass T2I_smla { def WT : T2I<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC16, !strconcat(opc, "wt"), "\t$dst, $a, $b, $acc", [(set GPR:$dst, (add GPR:$acc, (sra (opnode GPR:$a, - (sra GPR:$b, (i32 16))), (i32 16))))]> { + (sra GPR:$b, (i32 16))), (i32 16))))]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b011; @@ -1527,16 +1906,70 @@ multiclass T2I_smla { defm t2SMUL : T2I_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; defm t2SMLA : T2I_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>; -// TODO: Halfword multiple accumulate long: SMLAL -// TODO: Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD - +// Halfword multiple accumulate long: SMLAL -- for disassembly only +def t2SMLALBB : T2I_mac<1, 0b100, 0b1000, (outs GPR:$ldst,GPR:$hdst), + (ins GPR:$a,GPR:$b), IIC_iMAC64, "smlalbb", "\t$ldst, $hdst, $a, $b", + [/* For disassembly only; pattern left blank */]>; +def t2SMLALBT : T2I_mac<1, 0b100, 0b1001, (outs GPR:$ldst,GPR:$hdst), + (ins GPR:$a,GPR:$b), IIC_iMAC64, "smlalbt", "\t$ldst, $hdst, $a, $b", + [/* For disassembly only; pattern left blank */]>; +def t2SMLALTB : T2I_mac<1, 0b100, 0b1010, (outs GPR:$ldst,GPR:$hdst), + (ins GPR:$a,GPR:$b), IIC_iMAC64, "smlaltb", "\t$ldst, $hdst, $a, $b", + [/* For disassembly only; pattern left blank */]>; +def t2SMLALTT : T2I_mac<1, 0b100, 0b1011, (outs GPR:$ldst,GPR:$hdst), + (ins GPR:$a,GPR:$b), IIC_iMAC64, "smlaltt", "\t$ldst, $hdst, $a, $b", + [/* For disassembly only; pattern left blank */]>; + +// Dual halfword multiple: SMUAD, SMUSD, SMLAD, SMLSD, SMLALD, SMLSLD +// These are for disassembly only. + +def t2SMUAD : T2I_mac<0, 0b010, 0b0000, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMAC32, "smuad", "\t$dst, $a, $b", []> { + let Inst{15-12} = 0b1111; +} +def t2SMUADX : T2I_mac<0, 0b010, 0b0001, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMAC32, "smuadx", "\t$dst, $a, $b", []> { + let Inst{15-12} = 0b1111; +} +def t2SMUSD : T2I_mac<0, 0b100, 0b0000, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMAC32, "smusd", "\t$dst, $a, $b", []> { + let Inst{15-12} = 0b1111; +} +def t2SMUSDX : T2I_mac<0, 0b100, 0b0001, (outs GPR:$dst), (ins GPR:$a, GPR:$b), + IIC_iMAC32, "smusdx", "\t$dst, $a, $b", []> { + let Inst{15-12} = 0b1111; +} +def t2SMLAD : T2I_mac<0, 0b010, 0b0000, (outs GPR:$dst), + (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC32, "smlad", + "\t$dst, $a, $b, $acc", []>; +def t2SMLADX : T2I_mac<0, 0b010, 0b0001, (outs GPR:$dst), + (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC32, "smladx", + "\t$dst, $a, $b, $acc", []>; +def t2SMLSD : T2I_mac<0, 0b100, 0b0000, (outs GPR:$dst), + (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC32, "smlsd", + "\t$dst, $a, $b, $acc", []>; +def t2SMLSDX : T2I_mac<0, 0b100, 0b0001, (outs GPR:$dst), + (ins GPR:$a, GPR:$b, GPR:$acc), IIC_iMAC32, "smlsdx", + "\t$dst, $a, $b, $acc", []>; +def t2SMLALD : T2I_mac<1, 0b100, 0b1100, (outs GPR:$ldst,GPR:$hdst), + (ins GPR:$a,GPR:$b), IIC_iMAC64, "smlald", + "\t$ldst, $hdst, $a, $b", []>; +def t2SMLALDX : T2I_mac<1, 0b100, 0b1101, (outs GPR:$ldst,GPR:$hdst), + (ins GPR:$a,GPR:$b), IIC_iMAC64, "smlaldx", + "\t$ldst, $hdst, $a, $b", []>; +def t2SMLSLD : T2I_mac<1, 0b101, 0b1100, (outs GPR:$ldst,GPR:$hdst), + (ins GPR:$a,GPR:$b), IIC_iMAC64, "smlsld", + "\t$ldst, $hdst, $a, $b", []>; +def t2SMLSLDX : T2I_mac<1, 0b101, 0b1101, (outs GPR:$ldst,GPR:$hdst), + (ins GPR:$a,GPR:$b), IIC_iMAC64, "smlsldx", + "\t$ldst, $hdst, $a, $b", []>; //===----------------------------------------------------------------------===// // Misc. Arithmetic Instructions. // -class T2I_misc op1, bits<2> op2, dag oops, dag iops, InstrItinClass itin, - string opc, string asm, list pattern> +class T2I_misc op1, bits<2> op2, dag oops, dag iops, + InstrItinClass itin, string opc, string asm, list pattern> : T2I { let Inst{31-27} = 0b11111; let Inst{26-22} = 0b01010; @@ -1572,7 +2005,7 @@ def t2REVSH : T2I_misc<0b01, 0b11, (outs GPR:$dst), (ins GPR:$src), IIC_iUNAr, (shl GPR:$src, (i32 8))), i16))]>; def t2PKHBT : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt), - IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, LSL $shamt", + IIC_iALUsi, "pkhbt", "\t$dst, $src1, $src2, lsl $shamt", [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF), (and (shl GPR:$src2, (i32 imm:$shamt)), 0xFFFF0000)))]> { @@ -1590,7 +2023,7 @@ def : T2Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)), (t2PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>; def t2PKHTB : T2I<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt), - IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, ASR $shamt", + IIC_iALUsi, "pkhtb", "\t$dst, $src1, $src2, asr $shamt", [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000), (and (sra GPR:$src2, imm16_31:$shamt), 0xFFFF)))]> { @@ -1643,7 +2076,7 @@ defm t2TEQ : T2I_cmp_irs<0b0100, "teq", // Conditional moves // FIXME: should be able to write a pattern for ARMcmov, but can't use -// a two-value operand where a dag node expects two operands. :( +// a two-value operand where a dag node expects two operands. :( def t2MOVCCr : T2I<(outs GPR:$dst), (ins GPR:$false, GPR:$true), IIC_iCMOVr, "mov", ".w\t$dst, $true", [/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>, @@ -1723,6 +2156,66 @@ def t2Int_SyncBarrierV7 : AInoP<(outs), (ins), } } +// Helper class for multiclass T2MemB -- for disassembly only +class T2I_memb + : T2I<(outs), (ins), NoItinerary, opc, asm, + [/* For disassembly only; pattern left blank */]>, + Requires<[IsThumb2, HasV7]> { + let Inst{31-20} = 0xf3b; + let Inst{15-14} = 0b10; + let Inst{12} = 0; +} + +multiclass T2MemB op7_4, string opc> { + + def st : T2I_memb { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b1110; + } + + def ish : T2I_memb { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b1011; + } + + def ishst : T2I_memb { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b1010; + } + + def nsh : T2I_memb { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b0111; + } + + def nshst : T2I_memb { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b0110; + } + + def osh : T2I_memb { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b0011; + } + + def oshst : T2I_memb { + let Inst{7-4} = op7_4; + let Inst{3-0} = 0b0010; + } +} + +// These DMB variants are for disassembly only. +defm t2DMB : T2MemB<0b0101, "dmb">; + +// These DSB variants are for disassembly only. +defm t2DSB : T2MemB<0b0100, "dsb">; + +// ISB has only full system option -- for disassembly only +def t2ISBsy : T2I_memb<"isb", ""> { + let Inst{7-4} = 0b0110; + let Inst{3-0} = 0b1111; +} + class T2I_ldrex opcod, dag oops, dag iops, AddrMode am, SizeFlagVal sz, InstrItinClass itin, string opc, string asm, string cstr, list pattern, bits<4> rt2 = 0b1111> @@ -1789,6 +2282,16 @@ def t2STREXD : T2I_strex<0b11, (outs GPR:$success), {?, ?, ?, ?}>; } +// Clear-Exclusive is for disassembly only. +def t2CLREX : T2I<(outs), (ins), NoItinerary, "clrex", "", + [/* For disassembly only; pattern left blank */]>, + Requires<[IsARM, HasV7]> { + let Inst{31-20} = 0xf3b; + let Inst{15-14} = 0b10; + let Inst{12} = 0; + let Inst{7-4} = 0b0010; +} + //===----------------------------------------------------------------------===// // TLS Instructions // @@ -1906,6 +2409,24 @@ def t2TBH : let Inst{15-8} = 0b11110000; let Inst{7-4} = 0b0001; // H form } + +// Generic versions of the above two instructions, for disassembly only + +def t2TBBgen : T2I<(outs), (ins GPR:$a, GPR:$b), IIC_Br, + "tbb", "\t[$a, $b]", []>{ + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0001101; + let Inst{15-8} = 0b11110000; + let Inst{7-4} = 0b0000; // B form +} + +def t2TBHgen : T2I<(outs), (ins GPR:$a, GPR:$b), IIC_Br, + "tbh", "\t[$a, $b, lsl #1]", []> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0001101; + let Inst{15-8} = 0b11110000; + let Inst{7-4} = 0b0001; // H form +} } // isNotDuplicable, isIndirectBranch } // isBranch, isTerminator, isBarrier @@ -1931,6 +2452,119 @@ def t2IT : Thumb2XI<(outs), (ins it_pred:$cc, it_mask:$mask), let Inst{15-8} = 0b10111111; } +// Branch and Exchange Jazelle -- for disassembly only +// Rm = Inst{19-16} +def t2BXJ : T2I<(outs), (ins GPR:$func), NoItinerary, "bxj", "\t$func", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{26} = 0; + let Inst{25-20} = 0b111100; + let Inst{15-14} = 0b10; + let Inst{12} = 0; +} + +// Change Processor State is a system instruction -- for disassembly only. +// The singleton $opt operand contains the following information: +// opt{4-0} = mode from Inst{4-0} +// opt{5} = changemode from Inst{17} +// opt{8-6} = AIF from Inst{8-6} +// opt{10-9} = imod from Inst{19-18} with 0b10 as enable and 0b11 as disable +def t2CPS : T2XI<(outs),(ins i32imm:$opt), NoItinerary, "cps${opt:cps}", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{26} = 0; + let Inst{25-20} = 0b111010; + let Inst{15-14} = 0b10; + let Inst{12} = 0; +} + +// A6.3.4 Branches and miscellaneous control +// Table A6-14 Change Processor State, and hint instructions +// Helper class for disassembly only. +class T2I_hint op7_0, string opc, string asm> + : T2I<(outs), (ins), NoItinerary, opc, asm, + [/* For disassembly only; pattern left blank */]> { + let Inst{31-20} = 0xf3a; + let Inst{15-14} = 0b10; + let Inst{12} = 0; + let Inst{10-8} = 0b000; + let Inst{7-0} = op7_0; +} + +def t2NOP : T2I_hint<0b00000000, "nop", ".w">; +def t2YIELD : T2I_hint<0b00000001, "yield", ".w">; +def t2WFE : T2I_hint<0b00000010, "wfe", ".w">; +def t2WFI : T2I_hint<0b00000011, "wfi", ".w">; +def t2SEV : T2I_hint<0b00000100, "sev", ".w">; + +def t2DBG : T2I<(outs),(ins i32imm:$opt), NoItinerary, "dbg", "\t$opt", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-20} = 0xf3a; + let Inst{15-14} = 0b10; + let Inst{12} = 0; + let Inst{10-8} = 0b000; + let Inst{7-4} = 0b1111; +} + +// Secure Monitor Call is a system instruction -- for disassembly only +// Option = Inst{19-16} +def t2SMC : T2I<(outs), (ins i32imm:$opt), NoItinerary, "smc", "\t$opt", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{26-20} = 0b1111111; + let Inst{15-12} = 0b1000; +} + +// Store Return State is a system instruction -- for disassembly only +def t2SRSDBW : T2I<(outs),(ins i32imm:$mode),NoItinerary,"srsdb","\tsp!, $mode", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0000010; // W = 1 +} + +def t2SRSDB : T2I<(outs),(ins i32imm:$mode),NoItinerary,"srsdb","\tsp, $mode", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0000000; // W = 0 +} + +def t2SRSIAW : T2I<(outs),(ins i32imm:$mode),NoItinerary,"srsia","\tsp!, $mode", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0011010; // W = 1 +} + +def t2SRSIA : T2I<(outs), (ins i32imm:$mode),NoItinerary,"srsia","\tsp, $mode", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0011000; // W = 0 +} + +// Return From Exception is a system instruction -- for disassembly only +def t2RFEDBW : T2I<(outs), (ins GPR:$base), NoItinerary, "rfedb", "\t$base!", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0000011; // W = 1 +} + +def t2RFEDB : T2I<(outs), (ins GPR:$base), NoItinerary, "rfeab", "\t$base", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0000001; // W = 0 +} + +def t2RFEIAW : T2I<(outs), (ins GPR:$base), NoItinerary, "rfeia", "\t$base!", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0011011; // W = 1 +} + +def t2RFEIA : T2I<(outs), (ins GPR:$base), NoItinerary, "rfeia", "\t$base", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11101; + let Inst{26-20} = 0b0011001; // W = 0 +} + //===----------------------------------------------------------------------===// // Non-Instruction Patterns // @@ -1970,9 +2604,59 @@ def : T2Pat<(ARMWrapperJT tjumptable:$dst, imm:$id), // Pseudo instruction that combines ldr from constpool and add pc. This should // be expanded into two instructions late to allow if-conversion and // scheduling. -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def t2LDRpci_pic : PseudoInst<(outs GPR:$dst), (ins i32imm:$addr, pclabel:$cp), NoItinerary, "@ ldr.w\t$dst, $addr\n$cp:\n\tadd\t$dst, pc", [(set GPR:$dst, (ARMpic_add (load (ARMWrapper tconstpool:$addr)), imm:$cp))]>, Requires<[IsThumb2]>; + +//===----------------------------------------------------------------------===// +// Move between special register and ARM core register -- for disassembly only +// + +// Rd = Instr{11-8} +def t2MRS : T2I<(outs GPR:$dst), (ins), NoItinerary, "mrs", "\t$dst, cpsr", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{26} = 0; + let Inst{25-21} = 0b11111; + let Inst{20} = 0; // The R bit. + let Inst{15-14} = 0b10; + let Inst{12} = 0; +} + +// Rd = Instr{11-8} +def t2MRSsys : T2I<(outs GPR:$dst), (ins), NoItinerary, "mrs", "\t$dst, spsr", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{26} = 0; + let Inst{25-21} = 0b11111; + let Inst{20} = 1; // The R bit. + let Inst{15-14} = 0b10; + let Inst{12} = 0; +} + +// FIXME: mask is ignored for the time being. +// Rn = Inst{19-16} +def t2MSR : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tcpsr, $src", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{26} = 0; + let Inst{25-21} = 0b11100; + let Inst{20} = 0; // The R bit. + let Inst{15-14} = 0b10; + let Inst{12} = 0; +} + +// FIXME: mask is ignored for the time being. +// Rn = Inst{19-16} +def t2MSRsys : T2I<(outs), (ins GPR:$src), NoItinerary, "msr", "\tspsr, $src", + [/* For disassembly only; pattern left blank */]> { + let Inst{31-27} = 0b11110; + let Inst{26} = 0; + let Inst{25-21} = 0b11100; + let Inst{20} = 1; // The R bit. + let Inst{15-14} = 0b10; + let Inst{12} = 0; +} diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index 365e1e33ba..7c117edb00 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -54,7 +54,7 @@ def vfp_f64imm : Operand, // Load / store Instructions. // -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +let canFoldAsLoad = 1, isReMaterializable = 1 in { def VLDRD : ADI5<0b1101, 0b01, (outs DPR:$dst), (ins addrmode5:$addr), IIC_fpLoad64, "vldr", ".64\t$dst, $addr", [(set DPR:$dst, (load addrmode5:$addr))]>; @@ -412,6 +412,101 @@ def VTOUIRS : AVConv1In<0b11101, 0b11, 0b1100, 0b1010, let Inst{7} = 0; // Z bit } +// Convert between floating-point and fixed-point +// Data type for fixed-point naming convention: +// S16 (U=0, sx=0) -> SH +// U16 (U=1, sx=0) -> UH +// S32 (U=0, sx=1) -> SL +// U32 (U=1, sx=1) -> UL + +let Constraints = "$a = $dst" in { + +// FP to Fixed-Point: + +def VTOSHS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 0, + (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), + IIC_fpCVTSI, "vcvt", ".s16.f32\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VTOUHS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 0, + (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), + IIC_fpCVTSI, "vcvt", ".u16.f32\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VTOSLS : AVConv1XI<0b11101, 0b11, 0b1110, 0b1010, 1, + (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), + IIC_fpCVTSI, "vcvt", ".s32.f32\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VTOULS : AVConv1XI<0b11101, 0b11, 0b1111, 0b1010, 1, + (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), + IIC_fpCVTSI, "vcvt", ".u32.f32\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VTOSHD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 0, + (outs DPR:$dst), (ins DPR:$a, i32imm:$fbits), + IIC_fpCVTDI, "vcvt", ".s16.f64\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VTOUHD : AVConv1XI<0b11101, 0b11, 0b1111, 0b1011, 0, + (outs DPR:$dst), (ins DPR:$a, i32imm:$fbits), + IIC_fpCVTDI, "vcvt", ".u16.f64\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VTOSLD : AVConv1XI<0b11101, 0b11, 0b1110, 0b1011, 1, + (outs DPR:$dst), (ins DPR:$a, i32imm:$fbits), + IIC_fpCVTDI, "vcvt", ".s32.f64\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VTOULD : AVConv1XI<0b11101, 0b11, 0b1111, 0b1011, 1, + (outs DPR:$dst), (ins DPR:$a, i32imm:$fbits), + IIC_fpCVTDI, "vcvt", ".u32.f64\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +// Fixed-Point to FP: + +def VSHTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 0, + (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), + IIC_fpCVTIS, "vcvt", ".f32.s16\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VUHTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 0, + (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), + IIC_fpCVTIS, "vcvt", ".f32.u16\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VSLTOS : AVConv1XI<0b11101, 0b11, 0b1010, 0b1010, 1, + (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), + IIC_fpCVTIS, "vcvt", ".f32.s32\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VULTOS : AVConv1XI<0b11101, 0b11, 0b1011, 0b1010, 1, + (outs SPR:$dst), (ins SPR:$a, i32imm:$fbits), + IIC_fpCVTIS, "vcvt", ".f32.u32\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VSHTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 0, + (outs DPR:$dst), (ins DPR:$a, i32imm:$fbits), + IIC_fpCVTID, "vcvt", ".f64.s16\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VUHTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 0, + (outs DPR:$dst), (ins DPR:$a, i32imm:$fbits), + IIC_fpCVTID, "vcvt", ".f64.u16\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VSLTOD : AVConv1XI<0b11101, 0b11, 0b1010, 0b1011, 1, + (outs DPR:$dst), (ins DPR:$a, i32imm:$fbits), + IIC_fpCVTID, "vcvt", ".f64.s32\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +def VULTOD : AVConv1XI<0b11101, 0b11, 0b1011, 0b1011, 1, + (outs DPR:$dst), (ins DPR:$a, i32imm:$fbits), + IIC_fpCVTID, "vcvt", ".f64.u32\t$dst, $a, $fbits", + [/* For disassembly only; pattern left blank */]>; + +} // End of 'let Constraints = "$src = $dst" in' + //===----------------------------------------------------------------------===// // FP FMA Operations. // diff --git a/lib/Target/ARM/ARMJITInfo.cpp b/lib/Target/ARM/ARMJITInfo.cpp index bef5a0612f..6db6ba4b1e 100644 --- a/lib/Target/ARM/ARMJITInfo.cpp +++ b/lib/Target/ARM/ARMJITInfo.cpp @@ -48,7 +48,13 @@ static TargetJITInfo::JITCompilerFn JITCompilerFunction; // write our own wrapper, which does things our way, so we have complete // control over register saving and restoring. extern "C" { -#if defined(__arm__) + // We don't need this on Android (generally on hand-held devices). This + // function is for the purpose of supporting "lazy symbol lookup" (lookup + // undefined symbol at runtime) (Actually, if you tried to remove the + // !defined(ANDROID) guard, you'll get compilation error since Android's + // toolchain choose armv5te as its CPU architecture which does not support + // instruction 'stmdb' and 'ldmia' within the function) +#if defined(__arm__) && !defined(ANDROID) void ARMCompilationCallback(); asm( ".text\n" @@ -60,7 +66,7 @@ extern "C" { // whole compilation callback doesn't exist as far as the caller is // concerned, so we can't just preserve the callee saved regs. "stmdb sp!, {r0, r1, r2, r3, lr}\n" -#ifndef __SOFTFP__ +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) "fstmfdd sp!, {d0, d1, d2, d3, d4, d5, d6, d7}\n" #endif // The LR contains the address of the stub function on entry. @@ -83,7 +89,7 @@ extern "C" { // 6-20 | D0..D7 | Saved VFP registers // +--------+ // -#ifndef __SOFTFP__ +#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) // Restore VFP caller-saved registers. "fldmfdd sp!, {d0, d1, d2, d3, d4, d5, d6, d7}\n" #endif @@ -318,6 +324,18 @@ void ARMJITInfo::relocate(void *Function, MachineRelocation *MR, *((intptr_t*)RelocPos) |= ResultPtr; break; } + case ARM::reloc_arm_movw: { + ResultPtr = ResultPtr & 0xFFFF; + *((intptr_t*)RelocPos) |= ResultPtr & 0xFFF; + *((intptr_t*)RelocPos) |= ((ResultPtr >> 12) & 0xF) << 16; // imm4:imm12, Insts[19-16] = imm4, Insts[11-0] = imm12 + break; + } + case ARM::reloc_arm_movt: { + ResultPtr = (ResultPtr >> 16) & 0xFFFF; + *((intptr_t*)RelocPos) |= ResultPtr & 0xFFF; + *((intptr_t*)RelocPos) |= ((ResultPtr >> 12) & 0xF) << 16; // imm4:imm12, Insts[19-16] = imm4, Insts[11-0] = imm12 + break; + } } } } diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index b78b95b22e..19f1e3ba12 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -350,7 +350,8 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, : ARMRegisterInfo::getRegisterNumbering(Reg); // AM4 - register numbers in ascending order. // AM5 - consecutive register numbers in ascending order. - if (NewOffset == Offset + (int)Size && + if (Reg != ARM::SP && + NewOffset == Offset + (int)Size && ((isAM4 && RegNum > PRegNum) || RegNum == PRegNum+1)) { Offset += Size; PRegNum = RegNum; @@ -747,11 +748,24 @@ static bool isMemoryOp(const MachineInstr *MI) { if (MMO->isVolatile()) return false; - // Unaligned ldr/str is emulated by some kernels, but unaligned ldm/stm is not. + // Unaligned ldr/str is emulated by some kernels, but unaligned ldm/stm is + // not. if (MMO->getAlignment() < 4) return false; } + // str could probably be eliminated entirely, but for now we just want + // to avoid making a mess of it. + // FIXME: Use str as a wildcard to enable better stm folding. + if (MI->getNumOperands() > 0 && MI->getOperand(0).isReg() && + MI->getOperand(0).isUndef()) + return false; + + // Likewise don't mess with references to undefined addresses. + if (MI->getNumOperands() > 1 && MI->getOperand(1).isReg() && + MI->getOperand(1).isUndef()) + return false; + int Opcode = MI->getOpcode(); switch (Opcode) { default: break; diff --git a/lib/Target/ARM/ARMRelocations.h b/lib/Target/ARM/ARMRelocations.h index 2cc295085b..86e7206f2c 100644 --- a/lib/Target/ARM/ARMRelocations.h +++ b/lib/Target/ARM/ARMRelocations.h @@ -47,7 +47,13 @@ namespace llvm { reloc_arm_pic_jt, // reloc_arm_branch - Branch address relocation. - reloc_arm_branch + reloc_arm_branch, + + // reloc_arm_movt - MOVT immediate relocation. + reloc_arm_movt, + + // reloc_arm_movw - MOVW immediate relocation. + reloc_arm_movw }; } } diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index 426862c499..622034bd2d 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -33,7 +33,7 @@ UseMOVT("arm-use-movt", ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, bool isT) - : ARMArchVersion(V4T) + : ARMArchVersion(V4) , ARMFPUType(None) , UseNEONForSinglePrecisionFP(UseNEONFP) , IsThumb(isT) @@ -54,6 +54,11 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, // Parse features string. CPUString = ParseSubtargetFeatures(FS, CPUString); + // When no arch is specified either by CPU or by attributes, make the default + // ARMv4T. + if (CPUString == "generic" && (FS.empty() || FS == "generic")) + ARMArchVersion = V4T; + // Set the boolean corresponding to the current target triple, or the default // if one cannot be determined, to true. unsigned Len = TT.length(); @@ -68,25 +73,28 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, } if (Idx) { unsigned SubVer = TT[Idx]; - if (SubVer > '4' && SubVer <= '9') { - if (SubVer >= '7') { - ARMArchVersion = V7A; - } else if (SubVer == '6') { - ARMArchVersion = V6; - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') - ARMArchVersion = V6T2; - } else if (SubVer == '5') { - ARMArchVersion = V5T; - if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') - ARMArchVersion = V5TE; - } - if (ARMArchVersion >= V6T2) - ThumbMode = Thumb2; + if (SubVer >= '7' && SubVer <= '9') { + ARMArchVersion = V7A; + } else if (SubVer == '6') { + ARMArchVersion = V6; + if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == '2') + ARMArchVersion = V6T2; + } else if (SubVer == '5') { + ARMArchVersion = V5T; + if (Len >= Idx+3 && TT[Idx+1] == 't' && TT[Idx+2] == 'e') + ARMArchVersion = V5TE; + } else if (SubVer == '4') { + if (Len >= Idx+2 && TT[Idx+1] == 't') + ARMArchVersion = V4T; + else + ARMArchVersion = V4; } } // Thumb2 implies at least V6T2. - if (ARMArchVersion < V6T2 && ThumbMode >= Thumb2) + if (ARMArchVersion >= V6T2) + ThumbMode = Thumb2; + else if (ThumbMode >= Thumb2) ARMArchVersion = V6T2; if (Len >= 10) { diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 3f06b7b7f1..69808511fb 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -26,7 +26,7 @@ class GlobalValue; class ARMSubtarget : public TargetSubtarget { protected: enum ARMArchEnum { - V4T, V5T, V5TE, V6, V6T2, V7A + V4, V4T, V5T, V5TE, V6, V6T2, V7A }; enum ARMFPEnum { @@ -38,7 +38,7 @@ protected: Thumb2 }; - /// ARMArchVersion - ARM architecture version: V4T (base), V5T, V5TE, + /// ARMArchVersion - ARM architecture version: V4, V4T (base), V5T, V5TE, /// V6, V6T2, V7A. ARMArchEnum ARMArchVersion; diff --git a/lib/Target/ARM/ARMTargetObjectFile.h b/lib/Target/ARM/ARMTargetObjectFile.h index 9703403db2..a488c0a21f 100644 --- a/lib/Target/ARM/ARMTargetObjectFile.h +++ b/lib/Target/ARM/ARMTargetObjectFile.h @@ -10,7 +10,7 @@ #ifndef LLVM_TARGET_ARM_TARGETOBJECTFILE_H #define LLVM_TARGET_ARM_TARGETOBJECTFILE_H -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/MC/MCSectionELF.h" namespace llvm { @@ -24,7 +24,7 @@ namespace llvm { if (TM.getSubtarget().isAAPCS_ABI()) { StaticCtorSection = - getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY, + getELFSection(".init_array", MCSectionELF::SHT_INIT_ARRAY, MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, SectionKind::getDataRel()); StaticDtorSection = diff --git a/lib/Target/ARM/Android.mk b/lib/Target/ARM/Android.mk new file mode 100644 index 0000000000..ea796af34f --- /dev/null +++ b/lib/Target/ARM/Android.mk @@ -0,0 +1,49 @@ +LOCAL_PATH := $(call my-dir) + +# For the device only +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +TBLGEN_TABLES := \ + ARMGenRegisterInfo.h.inc \ + ARMGenRegisterNames.inc \ + ARMGenRegisterInfo.inc \ + ARMGenInstrNames.inc \ + ARMGenInstrInfo.inc \ + ARMGenDAGISel.inc \ + ARMGenSubtarget.inc \ + ARMGenCodeEmitter.inc \ + ARMGenCallingConv.inc + +LOCAL_SRC_FILES := \ + ARMBaseInstrInfo.cpp \ + ARMBaseRegisterInfo.cpp \ + ARMCodeEmitter.cpp \ + ARMConstantIslandPass.cpp \ + ARMConstantPoolValue.cpp \ + ARMExpandPseudoInsts.cpp \ + ARMISelDAGToDAG.cpp \ + ARMISelLowering.cpp \ + ARMInstrInfo.cpp \ + ARMJITInfo.cpp \ + ARMLoadStoreOptimizer.cpp \ + ARMMCAsmInfo.cpp \ + ARMRegisterInfo.cpp \ + ARMSubtarget.cpp \ + ARMTargetMachine.cpp \ + NEONMoveFix.cpp \ + NEONPreAllocPass.cpp \ + Thumb1InstrInfo.cpp \ + Thumb1RegisterInfo.cpp \ + Thumb2ITBlockPass.cpp \ + Thumb2InstrInfo.cpp \ + Thumb2RegisterInfo.cpp \ + Thumb2SizeReduction.cpp + +LOCAL_MODULE:= libLLVMARMCodeGen + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 0a75c092e2..d6d595cd54 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -30,6 +30,7 @@ #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" @@ -37,7 +38,6 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" @@ -122,6 +122,7 @@ namespace { void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum); void printPredicateOperand(const MachineInstr *MI, int OpNum); + void printMandatoryPredicateOperand(const MachineInstr *MI, int OpNum); void printSBitModifierOperand(const MachineInstr *MI, int OpNum); void printPCLabel(const MachineInstr *MI, int OpNum); void printRegisterList(const MachineInstr *MI, int OpNum); @@ -786,6 +787,12 @@ void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum) { O << ARMCondCodeToString(CC); } +void ARMAsmPrinter::printMandatoryPredicateOperand(const MachineInstr *MI, + int OpNum) { + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); + O << ARMCondCodeToString(CC); +} + void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum){ unsigned Reg = MI->getOperand(OpNum).getReg(); if (Reg) { diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp index d7d8e09e12..a2084b0c4a 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp @@ -325,6 +325,12 @@ void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) { O << ARMCondCodeToString(CC); } +void ARMInstPrinter::printMandatoryPredicateOperand(const MCInst *MI, + unsigned OpNum) { + ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm(); + O << ARMCondCodeToString(CC); +} + void ARMInstPrinter::printSBitModifierOperand(const MCInst *MI, unsigned OpNum){ if (MI->getOperand(OpNum).getReg()) { assert(MI->getOperand(OpNum).getReg() == ARM::CPSR && diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h index 23a7f05dbd..b7964c9071 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.h @@ -71,6 +71,7 @@ public: void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum) {} void printPredicateOperand(const MCInst *MI, unsigned OpNum); + void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum); void printSBitModifierOperand(const MCInst *MI, unsigned OpNum); void printRegisterList(const MCInst *MI, unsigned OpNum); void printCPInstOperand(const MCInst *MI, unsigned OpNum, diff --git a/lib/Target/ARM/README.txt b/lib/Target/ARM/README.txt index 9efb5a1426..57b65cf15d 100644 --- a/lib/Target/ARM/README.txt +++ b/lib/Target/ARM/README.txt @@ -10,6 +10,8 @@ Reimplement 'select' in terms of 'SEL'. * Implement pre/post increment support. (e.g. PR935) * Implement smarter constant generation for binops with large immediates. +A few ARMv6T2 ops should be pattern matched: BFI, SBFX, and UBFX + //===---------------------------------------------------------------------===// Crazy idea: Consider code that uses lots of 8-bit or 16-bit values. By the diff --git a/lib/Target/ARM/TargetInfo/Android.mk b/lib/Target/ARM/TargetInfo/Android.mk new file mode 100644 index 0000000000..c1998a17cd --- /dev/null +++ b/lib/Target/ARM/TargetInfo/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH := $(call my-dir) + +# For the device only +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +TBLGEN_TABLES := \ + ARMGenRegisterNames.inc \ + ARMGenInstrNames.inc + +TBLGEN_TD_DIR := $(LOCAL_PATH)/.. + +LOCAL_SRC_FILES := \ + ARMTargetInfo.cpp + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/.. + +LOCAL_MODULE:= libLLVMARMInfo + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index d6630ce29c..163d1e9a0d 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -450,9 +450,9 @@ Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, Offset -= AFI->getGPRCalleeSavedArea1Offset(); else if (AFI->isGPRCalleeSavedArea2Frame(FrameIndex)) Offset -= AFI->getGPRCalleeSavedArea2Offset(); - else if (hasFP(MF)) { - assert(SPAdj == 0 && "Unexpected"); - // There is alloca()'s in this function, must reference off the frame + else if (MF.getFrameInfo()->hasVarSizedObjects()) { + assert(SPAdj == 0 && hasFP(MF) && "Unexpected"); + // There are alloca()'s in this function, must reference off the frame // pointer instead. FrameReg = getFrameRegister(MF); Offset -= AFI->getFramePtrSpillOffset(); @@ -778,9 +778,19 @@ static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) { } static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) { - return (MI->getOpcode() == ARM::tRestore && - MI->getOperand(1).isFI() && - isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)); + if (MI->getOpcode() == ARM::tRestore && + MI->getOperand(1).isFI() && + isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs)) + return true; + else if (MI->getOpcode() == ARM::tPOP) { + // The first three operands are predicates and such. The last two are + // imp-def and imp-use of SP. Check everything in between. + for (int i = 3, e = MI->getNumOperands() - 2; i != e; ++i) + if (!isCalleeSavedRegister(MI->getOperand(i).getReg(), CSRegs)) + return false; + return true; + } + return false; } void Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF, @@ -794,13 +804,13 @@ void Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF, ARMFunctionInfo *AFI = MF.getInfo(); unsigned VARegSaveSize = AFI->getVarArgsRegSaveSize(); int NumBytes = (int)MFI->getStackSize(); + const unsigned *CSRegs = getCalleeSavedRegs(); if (!AFI->hasStackFrame()) { if (NumBytes != 0) emitSPUpdate(MBB, MBBI, TII, dl, *this, NumBytes); } else { // Unwind MBBI to point to first LDR / VLDRD. - const unsigned *CSRegs = getCalleeSavedRegs(); if (MBBI != MBB.begin()) { do --MBBI; @@ -836,6 +846,9 @@ void Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF, } if (VARegSaveSize) { + // Move back past the callee-saved register restoration + while (MBBI != MBB.end() && isCSRestore(MBBI, CSRegs)) + ++MBBI; // Epilogue for vararg functions: pop LR to R3 and branch off it. AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tPOP))) .addReg(0) // No write back. @@ -845,6 +858,7 @@ void Thumb1RegisterInfo::emitEpilogue(MachineFunction &MF, BuildMI(MBB, MBBI, dl, TII.get(ARM::tBX_RET_vararg)) .addReg(ARM::R3, RegState::Kill); + // erase the old tBX_RET instruction MBB.erase(MBBI); } } diff --git a/lib/Target/Alpha/AlphaCallingConv.td b/lib/Target/Alpha/AlphaCallingConv.td index 38ada69c24..bde8819f46 100644 --- a/lib/Target/Alpha/AlphaCallingConv.td +++ b/lib/Target/Alpha/AlphaCallingConv.td @@ -14,7 +14,8 @@ //===----------------------------------------------------------------------===// def RetCC_Alpha : CallingConv<[ // i64 is returned in register R0 - CCIfType<[i64], CCAssignToReg<[R0]>>, + // R1 is an llvm extension, I don't know what gcc does + CCIfType<[i64], CCAssignToReg<[R0,R1]>>, // f32 / f64 are returned in F0/F1 CCIfType<[f32, f64], CCAssignToReg<[F0, F1]>> diff --git a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp index eaefef9c8b..5303d853cc 100644 --- a/lib/Target/Alpha/AlphaISelDAGToDAG.cpp +++ b/lib/Target/Alpha/AlphaISelDAGToDAG.cpp @@ -64,7 +64,7 @@ namespace { /// that the bits 1-7 of LHS are already zero. If LHS is non-null, we are /// in checking mode. If LHS is null, we assume that the mask has already /// been validated before. - uint64_t get_zapImm(SDValue LHS, uint64_t Constant) { + uint64_t get_zapImm(SDValue LHS, uint64_t Constant) const { uint64_t BitsToCheck = 0; unsigned Result = 0; for (unsigned i = 0; i != 8; ++i) { @@ -159,10 +159,6 @@ namespace { // target-specific node if it hasn't already been changed. SDNode *Select(SDNode *N); - /// InstructionSelect - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelect(); - virtual const char *getPassName() const { return "Alpha DAG->DAG Pattern Instruction Selection"; } @@ -222,20 +218,11 @@ SDNode *AlphaDAGToDAGISel::getGlobalRetAddr() { return CurDAG->getRegister(GlobalRetAddr, TLI.getPointerTy()).getNode(); } -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void AlphaDAGToDAGISel::InstructionSelect() { - // Select target instructions for the DAG. - SelectRoot(*CurDAG); - CurDAG->RemoveDeadNodes(); -} - // Select - Convert the specified operand from a target-independent to a // target-specific node if it hasn't already been changed. SDNode *AlphaDAGToDAGISel::Select(SDNode *N) { - if (N->isMachineOpcode()) { + if (N->isMachineOpcode()) return NULL; // Already selected. - } DebugLoc dl = N->getDebugLoc(); switch (N->getOpcode()) { diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp index 0bbe567104..5d8310ec84 100644 --- a/lib/Target/Alpha/AlphaISelLowering.cpp +++ b/lib/Target/Alpha/AlphaISelLowering.cpp @@ -21,7 +21,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Module.h" @@ -282,7 +282,8 @@ AlphaTargetLowering::LowerCall(SDValue Chain, SDValue Callee, DAG.getIntPtrConstant(VA.getLocMemOffset())); MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, - PseudoSourceValue::getStack(), 0)); + PseudoSourceValue::getStack(), 0, + false, false, 0)); } } @@ -426,7 +427,8 @@ AlphaTargetLowering::LowerFormalArguments(SDValue Chain, // Create the SelectionDAG nodes corresponding to a load //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i64); - ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0); + ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0, + false, false, 0); } InVals.push_back(ArgVal); } @@ -442,14 +444,16 @@ AlphaTargetLowering::LowerFormalArguments(SDValue Chain, int FI = MFI->CreateFixedObject(8, -8 * (6 - i), true, false); if (i == 0) VarArgsBase = FI; SDValue SDFI = DAG.getFrameIndex(FI, MVT::i64); - LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0)); + LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0, + false, false, 0)); if (TargetRegisterInfo::isPhysicalRegister(args_float[i])) args_float[i] = AddLiveIn(MF, args_float[i], &Alpha::F8RCRegClass); argt = DAG.getCopyFromReg(Chain, dl, args_float[i], MVT::f64); FI = MFI->CreateFixedObject(8, - 8 * (12 - i), true, false); SDFI = DAG.getFrameIndex(FI, MVT::i64); - LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0)); + LS.push_back(DAG.getStore(Chain, dl, argt, SDFI, NULL, 0, + false, false, 0)); } //Set up a token factor with all the stack traffic @@ -528,11 +532,12 @@ void AlphaTargetLowering::LowerVAARG(SDNode *N, SDValue &Chain, const Value *VAListS = cast(N->getOperand(2))->getValue(); DebugLoc dl = N->getDebugLoc(); - SDValue Base = DAG.getLoad(MVT::i64, dl, Chain, VAListP, VAListS, 0); + SDValue Base = DAG.getLoad(MVT::i64, dl, Chain, VAListP, VAListS, 0, + false, false, 0); SDValue Tmp = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); SDValue Offset = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Base.getValue(1), - Tmp, NULL, 0, MVT::i32); + Tmp, NULL, 0, MVT::i32, false, false, 0); DataPtr = DAG.getNode(ISD::ADD, dl, MVT::i64, Base, Offset); if (N->getValueType(0).isFloatingPoint()) { @@ -547,7 +552,7 @@ void AlphaTargetLowering::LowerVAARG(SDNode *N, SDValue &Chain, SDValue NewOffset = DAG.getNode(ISD::ADD, dl, MVT::i64, Offset, DAG.getConstant(8, MVT::i64)); Chain = DAG.getTruncStore(Offset.getValue(1), dl, NewOffset, Tmp, NULL, 0, - MVT::i32); + MVT::i32, false, false, 0); } /// LowerOperation - Provide custom lowering hooks for some operations. @@ -694,9 +699,10 @@ SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { SDValue Result; if (Op.getValueType() == MVT::i32) Result = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Chain, DataPtr, - NULL, 0, MVT::i32); + NULL, 0, MVT::i32, false, false, 0); else - Result = DAG.getLoad(Op.getValueType(), dl, Chain, DataPtr, NULL, 0); + Result = DAG.getLoad(Op.getValueType(), dl, Chain, DataPtr, NULL, 0, + false, false, 0); return Result; } case ISD::VACOPY: { @@ -706,15 +712,18 @@ SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { const Value *DestS = cast(Op.getOperand(3))->getValue(); const Value *SrcS = cast(Op.getOperand(4))->getValue(); - SDValue Val = DAG.getLoad(getPointerTy(), dl, Chain, SrcP, SrcS, 0); - SDValue Result = DAG.getStore(Val.getValue(1), dl, Val, DestP, DestS, 0); + SDValue Val = DAG.getLoad(getPointerTy(), dl, Chain, SrcP, SrcS, 0, + false, false, 0); + SDValue Result = DAG.getStore(Val.getValue(1), dl, Val, DestP, DestS, 0, + false, false, 0); SDValue NP = DAG.getNode(ISD::ADD, dl, MVT::i64, SrcP, DAG.getConstant(8, MVT::i64)); Val = DAG.getExtLoad(ISD::SEXTLOAD, dl, MVT::i64, Result, - NP, NULL,0, MVT::i32); + NP, NULL,0, MVT::i32, false, false, 0); SDValue NPD = DAG.getNode(ISD::ADD, dl, MVT::i64, DestP, DAG.getConstant(8, MVT::i64)); - return DAG.getTruncStore(Val.getValue(1), dl, Val, NPD, NULL, 0, MVT::i32); + return DAG.getTruncStore(Val.getValue(1), dl, Val, NPD, NULL, 0, MVT::i32, + false, false, 0); } case ISD::VASTART: { SDValue Chain = Op.getOperand(0); @@ -723,11 +732,12 @@ SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { // vastart stores the address of the VarArgsBase and VarArgsOffset SDValue FR = DAG.getFrameIndex(VarArgsBase, MVT::i64); - SDValue S1 = DAG.getStore(Chain, dl, FR, VAListP, VAListS, 0); + SDValue S1 = DAG.getStore(Chain, dl, FR, VAListP, VAListS, 0, + false, false, 0); SDValue SA2 = DAG.getNode(ISD::ADD, dl, MVT::i64, VAListP, DAG.getConstant(8, MVT::i64)); return DAG.getTruncStore(S1, dl, DAG.getConstant(VarArgsOffset, MVT::i64), - SA2, NULL, 0, MVT::i32); + SA2, NULL, 0, MVT::i32, false, false, 0); } case ISD::RETURNADDR: return DAG.getNode(AlphaISD::GlobalRetAddr, DebugLoc::getUnknownLoc(), @@ -749,7 +759,8 @@ void AlphaTargetLowering::ReplaceNodeResults(SDNode *N, SDValue Chain, DataPtr; LowerVAARG(N, Chain, DataPtr, DAG); - SDValue Res = DAG.getLoad(N->getValueType(0), dl, Chain, DataPtr, NULL, 0); + SDValue Res = DAG.getLoad(N->getValueType(0), dl, Chain, DataPtr, NULL, 0, + false, false, 0); Results.push_back(Res); Results.push_back(SDValue(Res.getNode(), 1)); } diff --git a/lib/Target/Alpha/AlphaInstrInfo.td b/lib/Target/Alpha/AlphaInstrInfo.td index 8917e86fe7..341c4a72a9 100644 --- a/lib/Target/Alpha/AlphaInstrInfo.td +++ b/lib/Target/Alpha/AlphaInstrInfo.td @@ -92,7 +92,7 @@ def immSExt16int : PatLeaf<(imm), [{ //(int)imm fits in a 16 bit sign extended ((int64_t)N->getZExtValue() << 32) >> 32; }], SExt16>; -def zappat : PatFrag<(ops node:$LHS), (and node:$LHS, imm:$L), [{ +def zappat : PatFrag<(ops node:$LHS), (and node:$LHS, imm), [{ ConstantSDNode *RHS = dyn_cast(N->getOperand(1)); if (!RHS) return 0; uint64_t build = get_zapImm(N->getOperand(0), (uint64_t)RHS->getZExtValue()); @@ -602,9 +602,9 @@ def RPCC : MfcForm<0x18, 0xC000, "rpcc $RA", s_rpcc>; //Read process cycle count def MB : MfcPForm<0x18, 0x4000, "mb", s_imisc>; //memory barrier def WMB : MfcPForm<0x18, 0x4400, "wmb", s_imisc>; //write memory barrier -def : Pat<(membarrier (i64 imm:$ll), (i64 imm:$ls), (i64 imm:$sl), (i64 1), (i64 imm:$dev)), +def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 1), (i64 imm)), (WMB)>; -def : Pat<(membarrier (i64 imm:$ll), (i64 imm:$ls), (i64 imm:$sl), (i64 imm:$ss), (i64 imm:$dev)), +def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 imm), (i64 imm)), (MB)>; //Basic Floating point ops diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index 64bdd621c5..ba662fb7f7 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -251,7 +251,7 @@ void AlphaRegisterInfo::emitPrologue(MachineFunction &MF) const { } else { std::string msg; raw_string_ostream Msg(msg); - Msg << "Too big a stack frame at " + NumBytes; + Msg << "Too big a stack frame at " << NumBytes; llvm_report_error(Msg.str()); } @@ -303,15 +303,14 @@ void AlphaRegisterInfo::emitEpilogue(MachineFunction &MF, } else { std::string msg; raw_string_ostream Msg(msg); - Msg << "Too big a stack frame at " + NumBytes; + Msg << "Too big a stack frame at " << NumBytes; llvm_report_error(Msg.str()); } } } unsigned AlphaRegisterInfo::getRARegister() const { - llvm_unreachable("What is the return address register"); - return 0; + return Alpha::R26; } unsigned AlphaRegisterInfo::getFrameRegister(const MachineFunction &MF) const { diff --git a/lib/Target/Android.mk b/lib/Target/Android.mk new file mode 100644 index 0000000000..8bf4340a2c --- /dev/null +++ b/lib/Target/Android.mk @@ -0,0 +1,38 @@ +LOCAL_PATH:= $(call my-dir) + +target_SRC_FILES := \ + Mangler.cpp \ + SubtargetFeature.cpp \ + Target.cpp \ + TargetAsmLexer.cpp \ + TargetData.cpp \ + TargetELFWriterInfo.cpp \ + TargetFrameInfo.cpp \ + TargetInstrInfo.cpp \ + TargetIntrinsicInfo.cpp \ + TargetLoweringObjectFile.cpp \ + TargetMachine.cpp \ + TargetRegisterInfo.cpp \ + TargetSubtarget.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(target_SRC_FILES) + +LOCAL_MODULE:= libLLVMTarget + +include $(LLVM_HOST_BUILD_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(target_SRC_FILES) + +LOCAL_MODULE:= libLLVMTarget + +include $(LLVM_DEVICE_BUILD_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp index 2c9cc6019f..c8d71aabd1 100644 --- a/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp +++ b/lib/Target/Blackfin/BlackfinISelDAGToDAG.cpp @@ -41,7 +41,7 @@ namespace { BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel) : SelectionDAGISel(TM, OptLevel) {} - virtual void InstructionSelect(); + virtual void PostprocessISelDAG(); virtual const char *getPassName() const { return "Blackfin DAG->DAG Pattern Instruction Selection"; @@ -72,13 +72,7 @@ FunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM, return new BlackfinDAGToDAGISel(TM, OptLevel); } -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void BlackfinDAGToDAGISel::InstructionSelect() { - // Select target instructions for the DAG. - SelectRoot(*CurDAG); - DEBUG(errs() << "Selected selection DAG before regclass fixup:\n"); - DEBUG(CurDAG->dump()); +void BlackfinDAGToDAGISel::PostprocessISelDAG() { FixRegisterClasses(*CurDAG); } diff --git a/lib/Target/Blackfin/BlackfinISelLowering.cpp b/lib/Target/Blackfin/BlackfinISelLowering.cpp index 269707a8e8..5ce201347d 100644 --- a/lib/Target/Blackfin/BlackfinISelLowering.cpp +++ b/lib/Target/Blackfin/BlackfinISelLowering.cpp @@ -22,7 +22,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/ADT/VectorExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -206,7 +206,8 @@ BlackfinTargetLowering::LowerFormalArguments(SDValue Chain, int FI = MFI->CreateFixedObject(ObjSize, VA.getLocMemOffset(), true, false); SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); - InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0)); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0, + false, false, 0)); } } @@ -329,7 +330,7 @@ BlackfinTargetLowering::LowerCall(SDValue Chain, SDValue Callee, OffsetN = DAG.getNode(ISD::ADD, dl, MVT::i32, SPN, OffsetN); MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, OffsetN, PseudoSourceValue::getStack(), - Offset)); + Offset, false, false, 0)); } } diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp index fd4c4e7571..10f873ffcb 100644 --- a/lib/Target/CBackend/CBackend.cpp +++ b/lib/Target/CBackend/CBackend.cpp @@ -49,7 +49,6 @@ #include "llvm/System/Host.h" #include "llvm/Config/config.h" #include -#include using namespace llvm; extern "C" void LLVMInitializeCBackendTarget() { @@ -153,26 +152,16 @@ namespace { return false; } - raw_ostream &printType(formatted_raw_ostream &Out, - const Type *Ty, + raw_ostream &printType(raw_ostream &Out, const Type *Ty, bool isSigned = false, const std::string &VariableName = "", bool IgnoreName = false, const AttrListPtr &PAL = AttrListPtr()); - std::ostream &printType(std::ostream &Out, const Type *Ty, - bool isSigned = false, - const std::string &VariableName = "", - bool IgnoreName = false, - const AttrListPtr &PAL = AttrListPtr()); - raw_ostream &printSimpleType(formatted_raw_ostream &Out, - const Type *Ty, - bool isSigned, - const std::string &NameSoFar = ""); - std::ostream &printSimpleType(std::ostream &Out, const Type *Ty, - bool isSigned, + raw_ostream &printSimpleType(raw_ostream &Out, const Type *Ty, + bool isSigned, const std::string &NameSoFar = ""); - void printStructReturnPointerFunctionType(formatted_raw_ostream &Out, + void printStructReturnPointerFunctionType(raw_ostream &Out, const AttrListPtr &PAL, const PointerType *Ty); @@ -385,8 +374,8 @@ bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) { // If this isn't a struct or array type, remove it from our set of types // to name. This simplifies emission later. - if (!isa(I->second) && !isa(I->second) && - !isa(I->second)) { + if (!I->second->isStructTy() && !I->second->isOpaqueTy() && + !I->second->isArrayTy()) { TST.remove(I); } else { // If this is not used, remove it from the symbol table. @@ -405,7 +394,7 @@ bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) { unsigned RenameCounter = 0; for (std::set::const_iterator I = UT.begin(), E = UT.end(); I != E; ++I) - if (isa(*I) || isa(*I)) { + if ((*I)->isStructTy() || (*I)->isArrayTy()) { while (M.addTypeName("unnamed"+utostr(RenameCounter), *I)) ++RenameCounter; Changed = true; @@ -454,11 +443,12 @@ bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) { /// printStructReturnPointerFunctionType - This is like printType for a struct /// return type, except, instead of printing the type as void (*)(Struct*, ...) /// print it as "Struct (*)(...)", for struct return functions. -void CWriter::printStructReturnPointerFunctionType(formatted_raw_ostream &Out, +void CWriter::printStructReturnPointerFunctionType(raw_ostream &Out, const AttrListPtr &PAL, const PointerType *TheTy) { const FunctionType *FTy = cast(TheTy->getElementType()); - std::stringstream FunctionInnards; + std::string tstr; + raw_string_ostream FunctionInnards(tstr); FunctionInnards << " (*) ("; bool PrintedType = false; @@ -470,7 +460,7 @@ void CWriter::printStructReturnPointerFunctionType(formatted_raw_ostream &Out, FunctionInnards << ", "; const Type *ArgTy = *I; if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { - assert(isa(ArgTy)); + assert(ArgTy->isPointerTy()); ArgTy = cast(ArgTy)->getElementType(); } printType(FunctionInnards, ArgTy, @@ -484,63 +474,14 @@ void CWriter::printStructReturnPointerFunctionType(formatted_raw_ostream &Out, FunctionInnards << "void"; } FunctionInnards << ')'; - std::string tstr = FunctionInnards.str(); printType(Out, RetTy, - /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), tstr); + /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), FunctionInnards.str()); } raw_ostream & -CWriter::printSimpleType(formatted_raw_ostream &Out, const Type *Ty, - bool isSigned, +CWriter::printSimpleType(raw_ostream &Out, const Type *Ty, bool isSigned, const std::string &NameSoFar) { - assert((Ty->isPrimitiveType() || Ty->isInteger() || isa(Ty)) && - "Invalid type for printSimpleType"); - switch (Ty->getTypeID()) { - case Type::VoidTyID: return Out << "void " << NameSoFar; - case Type::IntegerTyID: { - unsigned NumBits = cast(Ty)->getBitWidth(); - if (NumBits == 1) - return Out << "bool " << NameSoFar; - else if (NumBits <= 8) - return Out << (isSigned?"signed":"unsigned") << " char " << NameSoFar; - else if (NumBits <= 16) - return Out << (isSigned?"signed":"unsigned") << " short " << NameSoFar; - else if (NumBits <= 32) - return Out << (isSigned?"signed":"unsigned") << " int " << NameSoFar; - else if (NumBits <= 64) - return Out << (isSigned?"signed":"unsigned") << " long long "<< NameSoFar; - else { - assert(NumBits <= 128 && "Bit widths > 128 not implemented yet"); - return Out << (isSigned?"llvmInt128":"llvmUInt128") << " " << NameSoFar; - } - } - case Type::FloatTyID: return Out << "float " << NameSoFar; - case Type::DoubleTyID: return Out << "double " << NameSoFar; - // Lacking emulation of FP80 on PPC, etc., we assume whichever of these is - // present matches host 'long double'. - case Type::X86_FP80TyID: - case Type::PPC_FP128TyID: - case Type::FP128TyID: return Out << "long double " << NameSoFar; - - case Type::VectorTyID: { - const VectorType *VTy = cast(Ty); - return printSimpleType(Out, VTy->getElementType(), isSigned, - " __attribute__((vector_size(" + - utostr(TD->getTypeAllocSize(VTy)) + " ))) " + NameSoFar); - } - - default: -#ifndef NDEBUG - errs() << "Unknown primitive type: " << *Ty << "\n"; -#endif - llvm_unreachable(0); - } -} - -std::ostream & -CWriter::printSimpleType(std::ostream &Out, const Type *Ty, bool isSigned, - const std::string &NameSoFar) { - assert((Ty->isPrimitiveType() || Ty->isInteger() || isa(Ty)) && + assert((Ty->isPrimitiveType() || Ty->isIntegerTy() || Ty->isVectorTy()) && "Invalid type for printSimpleType"); switch (Ty->getTypeID()) { case Type::VoidTyID: return Out << "void " << NameSoFar; @@ -587,120 +528,16 @@ CWriter::printSimpleType(std::ostream &Out, const Type *Ty, bool isSigned, // Pass the Type* and the variable name and this prints out the variable // declaration. // -raw_ostream &CWriter::printType(formatted_raw_ostream &Out, - const Type *Ty, +raw_ostream &CWriter::printType(raw_ostream &Out, const Type *Ty, bool isSigned, const std::string &NameSoFar, bool IgnoreName, const AttrListPtr &PAL) { - if (Ty->isPrimitiveType() || Ty->isInteger() || isa(Ty)) { - printSimpleType(Out, Ty, isSigned, NameSoFar); - return Out; - } - - // Check to see if the type is named. - if (!IgnoreName || isa(Ty)) { - std::map::iterator I = TypeNames.find(Ty); - if (I != TypeNames.end()) return Out << I->second << ' ' << NameSoFar; - } - - switch (Ty->getTypeID()) { - case Type::FunctionTyID: { - const FunctionType *FTy = cast(Ty); - std::stringstream FunctionInnards; - FunctionInnards << " (" << NameSoFar << ") ("; - unsigned Idx = 1; - for (FunctionType::param_iterator I = FTy->param_begin(), - E = FTy->param_end(); I != E; ++I) { - const Type *ArgTy = *I; - if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { - assert(isa(ArgTy)); - ArgTy = cast(ArgTy)->getElementType(); - } - if (I != FTy->param_begin()) - FunctionInnards << ", "; - printType(FunctionInnards, ArgTy, - /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), ""); - ++Idx; - } - if (FTy->isVarArg()) { - if (FTy->getNumParams()) - FunctionInnards << ", ..."; - } else if (!FTy->getNumParams()) { - FunctionInnards << "void"; - } - FunctionInnards << ')'; - std::string tstr = FunctionInnards.str(); - printType(Out, FTy->getReturnType(), - /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), tstr); - return Out; - } - case Type::StructTyID: { - const StructType *STy = cast(Ty); - Out << NameSoFar + " {\n"; - unsigned Idx = 0; - for (StructType::element_iterator I = STy->element_begin(), - E = STy->element_end(); I != E; ++I) { - Out << " "; - printType(Out, *I, false, "field" + utostr(Idx++)); - Out << ";\n"; - } - Out << '}'; - if (STy->isPacked()) - Out << " __attribute__ ((packed))"; - return Out; - } - - case Type::PointerTyID: { - const PointerType *PTy = cast(Ty); - std::string ptrName = "*" + NameSoFar; - - if (isa(PTy->getElementType()) || - isa(PTy->getElementType())) - ptrName = "(" + ptrName + ")"; - - if (!PAL.isEmpty()) - // Must be a function ptr cast! - return printType(Out, PTy->getElementType(), false, ptrName, true, PAL); - return printType(Out, PTy->getElementType(), false, ptrName); - } - - case Type::ArrayTyID: { - const ArrayType *ATy = cast(Ty); - unsigned NumElements = ATy->getNumElements(); - if (NumElements == 0) NumElements = 1; - // Arrays are wrapped in structs to allow them to have normal - // value semantics (avoiding the array "decay"). - Out << NameSoFar << " { "; - printType(Out, ATy->getElementType(), false, - "array[" + utostr(NumElements) + "]"); - return Out << "; }"; - } - - case Type::OpaqueTyID: { - std::string TyName = "struct opaque_" + itostr(OpaqueCounter++); - assert(TypeNames.find(Ty) == TypeNames.end()); - TypeNames[Ty] = TyName; - return Out << TyName << ' ' << NameSoFar; - } - default: - llvm_unreachable("Unhandled case in getTypeProps!"); - } - - return Out; -} - -// Pass the Type* and the variable name and this prints out the variable -// declaration. -// -std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, - bool isSigned, const std::string &NameSoFar, - bool IgnoreName, const AttrListPtr &PAL) { - if (Ty->isPrimitiveType() || Ty->isInteger() || isa(Ty)) { + if (Ty->isPrimitiveType() || Ty->isIntegerTy() || Ty->isVectorTy()) { printSimpleType(Out, Ty, isSigned, NameSoFar); return Out; } // Check to see if the type is named. - if (!IgnoreName || isa(Ty)) { + if (!IgnoreName || Ty->isOpaqueTy()) { std::map::iterator I = TypeNames.find(Ty); if (I != TypeNames.end()) return Out << I->second << ' ' << NameSoFar; } @@ -708,14 +545,15 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, switch (Ty->getTypeID()) { case Type::FunctionTyID: { const FunctionType *FTy = cast(Ty); - std::stringstream FunctionInnards; + std::string tstr; + raw_string_ostream FunctionInnards(tstr); FunctionInnards << " (" << NameSoFar << ") ("; unsigned Idx = 1; for (FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end(); I != E; ++I) { const Type *ArgTy = *I; if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { - assert(isa(ArgTy)); + assert(ArgTy->isPointerTy()); ArgTy = cast(ArgTy)->getElementType(); } if (I != FTy->param_begin()) @@ -731,9 +569,8 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, FunctionInnards << "void"; } FunctionInnards << ')'; - std::string tstr = FunctionInnards.str(); printType(Out, FTy->getReturnType(), - /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), tstr); + /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), FunctionInnards.str()); return Out; } case Type::StructTyID: { @@ -756,8 +593,8 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, const PointerType *PTy = cast(Ty); std::string ptrName = "*" + NameSoFar; - if (isa(PTy->getElementType()) || - isa(PTy->getElementType())) + if (PTy->getElementType()->isArrayTy() || + PTy->getElementType()->isVectorTy()) ptrName = "(" + ptrName + ")"; if (!PAL.isEmpty()) @@ -1144,7 +981,7 @@ void CWriter::printConstant(Constant *CPV, bool Static) { Out << "(("; printType(Out, CPV->getType()); // sign doesn't matter Out << ")/*UNDEF*/"; - if (!isa(CPV->getType())) { + if (!CPV->getType()->isVectorTy()) { Out << "0)"; } else { Out << "{})"; @@ -1396,7 +1233,7 @@ bool CWriter::printConstExprCast(const ConstantExpr* CE, bool Static) { } if (NeedsExplicitCast) { Out << "(("; - if (Ty->isInteger() && Ty != Type::getInt1Ty(Ty->getContext())) + if (Ty->isIntegerTy() && Ty != Type::getInt1Ty(Ty->getContext())) printSimpleType(Out, Ty, TypeIsSigned); else printType(Out, Ty); // not integer, sign doesn't matter @@ -1497,7 +1334,7 @@ void CWriter::writeInstComputationInline(Instruction &I) { // We can't currently support integer types other than 1, 8, 16, 32, 64. // Validate this. const Type *Ty = I.getType(); - if (Ty->isInteger() && (Ty!=Type::getInt1Ty(I.getContext()) && + if (Ty->isIntegerTy() && (Ty!=Type::getInt1Ty(I.getContext()) && Ty!=Type::getInt8Ty(I.getContext()) && Ty!=Type::getInt16Ty(I.getContext()) && Ty!=Type::getInt32Ty(I.getContext()) && @@ -1660,7 +1497,7 @@ void CWriter::writeOperandWithCast(Value* Operand, const ICmpInst &Cmp) { // If the operand was a pointer, convert to a large integer type. const Type* OpTy = Operand->getType(); - if (isa(OpTy)) + if (OpTy->isPointerTy()) OpTy = TD->getIntPtrType(Operand->getContext()); Out << "(("; @@ -2102,10 +1939,10 @@ bool CWriter::doInitialization(Module &M) { // complete. If the value is an aggregate, print out { 0 }, and let // the compiler figure out the rest of the zeros. Out << " = " ; - if (isa(I->getInitializer()->getType()) || - isa(I->getInitializer()->getType())) { + if (I->getInitializer()->getType()->isStructTy() || + I->getInitializer()->getType()->isVectorTy()) { Out << "{ 0 }"; - } else if (isa(I->getInitializer()->getType())) { + } else if (I->getInitializer()->getType()->isArrayTy()) { // As with structs and vectors, but with an extra set of braces // because arrays are wrapped in structs. Out << "{ { 0 } }"; @@ -2274,7 +2111,7 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) { // Out << "/* Structure contents */\n"; for (I = TST.begin(); I != End; ++I) - if (isa(I->second) || isa(I->second)) + if (I->second->isStructTy() || I->second->isArrayTy()) // Only print out used types! printContainedStructs(I->second, StructPrinted); } @@ -2287,14 +2124,15 @@ void CWriter::printModuleTypes(const TypeSymbolTable &TST) { void CWriter::printContainedStructs(const Type *Ty, std::set &StructPrinted) { // Don't walk through pointers. - if (isa(Ty) || Ty->isPrimitiveType() || Ty->isInteger()) return; + if (Ty->isPointerTy() || Ty->isPrimitiveType() || Ty->isIntegerTy()) + return; // Print all contained types first. for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); I != E; ++I) printContainedStructs(*I, StructPrinted); - if (isa(Ty) || isa(Ty)) { + if (Ty->isStructTy() || Ty->isArrayTy()) { // Check to see if we have already printed this struct. if (StructPrinted.insert(Ty).second) { // Print structure type out. @@ -2327,7 +2165,8 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { const FunctionType *FT = cast(F->getFunctionType()); const AttrListPtr &PAL = F->getAttributes(); - std::stringstream FunctionInnards; + std::string tstr; + raw_string_ostream FunctionInnards(tstr); // Print out the name... FunctionInnards << GetValueName(F) << '('; @@ -2382,7 +2221,7 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { if (PrintedArg) FunctionInnards << ", "; const Type *ArgTy = *I; if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { - assert(isa(ArgTy)); + assert(ArgTy->isPointerTy()); ArgTy = cast(ArgTy)->getElementType(); } printType(FunctionInnards, ArgTy, @@ -2423,8 +2262,8 @@ static inline bool isFPIntBitCast(const Instruction &I) { return false; const Type *SrcTy = I.getOperand(0)->getType(); const Type *DstTy = I.getType(); - return (SrcTy->isFloatingPoint() && DstTy->isInteger()) || - (DstTy->isFloatingPoint() && SrcTy->isInteger()); + return (SrcTy->isFloatingPointTy() && DstTy->isIntegerTy()) || + (DstTy->isFloatingPointTy() && SrcTy->isIntegerTy()); } void CWriter::printFunction(Function &F) { @@ -2713,7 +2552,7 @@ void CWriter::visitPHINode(PHINode &I) { void CWriter::visitBinaryOperator(Instruction &I) { // binary instructions, shift instructions, setCond instructions. - assert(!isa(I.getType())); + assert(!I.getType()->isPointerTy()); // We must cast the results of binary operations which might be promoted. bool needsCast = false; @@ -3489,7 +3328,7 @@ void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I, // exposed, like a global, avoid emitting (&foo)[0], just emit foo instead. if (isAddressExposed(Ptr)) { writeOperandInternal(Ptr, Static); - } else if (I != E && isa(*I)) { + } else if (I != E && (*I)->isStructTy()) { // If we didn't already emit the first operand, see if we can print it as // P->f instead of "P[0].f" writeOperand(Ptr); @@ -3504,13 +3343,13 @@ void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I, } for (; I != E; ++I) { - if (isa(*I)) { + if ((*I)->isStructTy()) { Out << ".field" << cast(I.getOperand())->getZExtValue(); - } else if (isa(*I)) { + } else if ((*I)->isArrayTy()) { Out << ".array["; writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); Out << ']'; - } else if (!isa(*I)) { + } else if (!(*I)->isVectorTy()) { Out << '['; writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); Out << ']'; @@ -3668,7 +3507,7 @@ void CWriter::visitInsertValueInst(InsertValueInst &IVI) { i != e; ++i) { const Type *IndexedTy = ExtractValueInst::getIndexedType(IVI.getOperand(0)->getType(), b, i+1); - if (isa(IndexedTy)) + if (IndexedTy->isArrayTy()) Out << ".array[" << *i << "]"; else Out << ".field" << *i; @@ -3689,7 +3528,7 @@ void CWriter::visitExtractValueInst(ExtractValueInst &EVI) { i != e; ++i) { const Type *IndexedTy = ExtractValueInst::getIndexedType(EVI.getOperand(0)->getType(), b, i+1); - if (isa(IndexedTy)) + if (IndexedTy->isArrayTy()) Out << ".array[" << *i << "]"; else Out << ".field" << *i; @@ -3705,7 +3544,8 @@ void CWriter::visitExtractValueInst(ExtractValueInst &EVI) { bool CTargetMachine::addPassesToEmitWholeFile(PassManager &PM, formatted_raw_ostream &o, CodeGenFileType FileType, - CodeGenOpt::Level OptLevel) { + CodeGenOpt::Level OptLevel, + bool DisableVerify) { if (FileType != TargetMachine::CGFT_AssemblyFile) return true; PM.add(createGCLoweringPass()); diff --git a/lib/Target/CBackend/CTargetMachine.h b/lib/Target/CBackend/CTargetMachine.h index 715bbdaf0c..d178e7f2d0 100644 --- a/lib/Target/CBackend/CTargetMachine.h +++ b/lib/Target/CBackend/CTargetMachine.h @@ -27,7 +27,8 @@ struct CTargetMachine : public TargetMachine { virtual bool addPassesToEmitWholeFile(PassManager &PM, formatted_raw_ostream &Out, CodeGenFileType FileType, - CodeGenOpt::Level OptLevel); + CodeGenOpt::Level OptLevel, + bool DisableVerify); virtual const TargetData *getTargetData() const { return 0; } }; diff --git a/lib/Target/CellSPU/SPU64InstrInfo.td b/lib/Target/CellSPU/SPU64InstrInfo.td index 06eb1496de..47cb579d9d 100644 --- a/lib/Target/CellSPU/SPU64InstrInfo.td +++ b/lib/Target/CellSPU/SPU64InstrInfo.td @@ -123,8 +123,8 @@ multiclass CompareLogicalGreaterThan64 { defm I64LGT: CompareLogicalGreaterThan64; def : Pat<(setugt R64C:$rA, R64C:$rB), I64LGTr64.Fragment>; -def : Pat<(setugt (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)), - I64LGTv2i64.Fragment>; +//def : Pat<(setugt (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)), +// I64LGTv2i64.Fragment>; // i64 setult: def : I64SETCCNegCond; @@ -201,8 +201,8 @@ multiclass CompareGreaterThan64 { defm I64GT: CompareLogicalGreaterThan64; def : Pat<(setgt R64C:$rA, R64C:$rB), I64GTr64.Fragment>; -def : Pat<(setgt (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)), - I64GTv2i64.Fragment>; +//def : Pat<(setgt (v2i64 VECREG:$rA), (v2i64 VECREG:$rB)), +// I64GTv2i64.Fragment>; // i64 setult: def : I64SETCCNegCond; diff --git a/lib/Target/CellSPU/SPUISelDAGToDAG.cpp b/lib/Target/CellSPU/SPUISelDAGToDAG.cpp index 80693e1801..396a921590 100644 --- a/lib/Target/CellSPU/SPUISelDAGToDAG.cpp +++ b/lib/Target/CellSPU/SPUISelDAGToDAG.cpp @@ -294,15 +294,19 @@ namespace { ((vecVT == MVT::v2i64) && ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i64).getNode() != 0) || (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i64).getNode() != 0) || - (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i64).getNode() != 0)))) - return Select(bvNode); + (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i64).getNode() != 0)))) { + HandleSDNode Dummy(SDValue(bvNode, 0)); + if (SDNode *N = Select(bvNode)) + return N; + return Dummy.getValue().getNode(); + } // No, need to emit a constant pool spill: std::vector CV; for (size_t i = 0; i < bvNode->getNumOperands(); ++i) { ConstantSDNode *V = dyn_cast (bvNode->getOperand(i)); - CV.push_back(const_cast (V->getConstantIntValue())); + CV.push_back(const_cast(V->getConstantIntValue())); } Constant *CP = ConstantVector::get(CV); @@ -311,10 +315,15 @@ namespace { SDValue CGPoolOffset = SPU::LowerConstantPool(CPIdx, *CurDAG, SPUtli.getSPUTargetMachine()); - return SelectCode(CurDAG->getLoad(vecVT, dl, - CurDAG->getEntryNode(), CGPoolOffset, - PseudoSourceValue::getConstantPool(), 0, - false, Alignment).getNode()); + + HandleSDNode Dummy(CurDAG->getLoad(vecVT, dl, + CurDAG->getEntryNode(), CGPoolOffset, + PseudoSourceValue::getConstantPool(),0, + false, false, Alignment)); + CurDAG->ReplaceAllUsesWith(SDValue(bvNode, 0), Dummy.getValue()); + if (SDNode *N = SelectCode(Dummy.getValue().getNode())) + return N; + return Dummy.getValue().getNode(); } /// Select - Convert the specified operand from a target-independent to a @@ -390,10 +399,6 @@ namespace { return false; } - /// InstructionSelect - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelect(); - virtual const char *getPassName() const { return "Cell SPU DAG->DAG Pattern Instruction Selection"; } @@ -411,16 +416,6 @@ namespace { }; } -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void -SPUDAGToDAGISel::InstructionSelect() -{ - // Select target instructions for the DAG. - SelectRoot(*CurDAG); - CurDAG->RemoveDeadNodes(); -} - /*! \arg Op The ISD instruction operand \arg N The address to be tested @@ -692,9 +687,8 @@ SPUDAGToDAGISel::Select(SDNode *N) { SDValue Ops[8]; DebugLoc dl = N->getDebugLoc(); - if (N->isMachineOpcode()) { + if (N->isMachineOpcode()) return NULL; // Already selected. - } if (Opc == ISD::FrameIndex) { int FI = cast(N)->getIndex(); @@ -759,43 +753,67 @@ SPUDAGToDAGISel::Select(SDNode *N) { } SDNode *shufMaskLoad = emitBuildVector(shufMask.getNode()); - SDNode *PromoteScalar = - SelectCode(CurDAG->getNode(SPUISD::PREFSLOT2VEC, dl, - Op0VecVT, Op0).getNode()); - + + HandleSDNode PromoteScalar(CurDAG->getNode(SPUISD::PREFSLOT2VEC, dl, + Op0VecVT, Op0)); + + SDValue PromScalar; + if (SDNode *N = SelectCode(PromoteScalar.getValue().getNode())) + PromScalar = SDValue(N, 0); + else + PromScalar = PromoteScalar.getValue(); + SDValue zextShuffle = CurDAG->getNode(SPUISD::SHUFB, dl, OpVecVT, - SDValue(PromoteScalar, 0), - SDValue(PromoteScalar, 0), + PromScalar, PromScalar, SDValue(shufMaskLoad, 0)); - // N.B.: BIT_CONVERT replaces and updates the zextShuffle node, so we - // re-use it in the VEC2PREFSLOT selection without needing to explicitly - // call SelectCode (it's already done for us.) - SelectCode(CurDAG->getNode(ISD::BIT_CONVERT, dl, OpVecVT, zextShuffle).getNode()); - return SelectCode(CurDAG->getNode(SPUISD::VEC2PREFSLOT, dl, OpVT, - zextShuffle).getNode()); + HandleSDNode Dummy2(zextShuffle); + if (SDNode *N = SelectCode(Dummy2.getValue().getNode())) + zextShuffle = SDValue(N, 0); + else + zextShuffle = Dummy2.getValue(); + HandleSDNode Dummy(CurDAG->getNode(SPUISD::VEC2PREFSLOT, dl, OpVT, + zextShuffle)); + + CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode()); + SelectCode(Dummy.getValue().getNode()); + return Dummy.getValue().getNode(); } else if (Opc == ISD::ADD && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) { SDNode *CGLoad = emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl).getNode()); - return SelectCode(CurDAG->getNode(SPUISD::ADD64_MARKER, dl, OpVT, - N->getOperand(0), N->getOperand(1), - SDValue(CGLoad, 0)).getNode()); + HandleSDNode Dummy(CurDAG->getNode(SPUISD::ADD64_MARKER, dl, OpVT, + N->getOperand(0), N->getOperand(1), + SDValue(CGLoad, 0))); + + CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode()); + if (SDNode *N = SelectCode(Dummy.getValue().getNode())) + return N; + return Dummy.getValue().getNode(); } else if (Opc == ISD::SUB && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) { SDNode *CGLoad = emitBuildVector(getBorrowGenerateShufMask(*CurDAG, dl).getNode()); - return SelectCode(CurDAG->getNode(SPUISD::SUB64_MARKER, dl, OpVT, - N->getOperand(0), N->getOperand(1), - SDValue(CGLoad, 0)).getNode()); + HandleSDNode Dummy(CurDAG->getNode(SPUISD::SUB64_MARKER, dl, OpVT, + N->getOperand(0), N->getOperand(1), + SDValue(CGLoad, 0))); + + CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode()); + if (SDNode *N = SelectCode(Dummy.getValue().getNode())) + return N; + return Dummy.getValue().getNode(); } else if (Opc == ISD::MUL && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) { SDNode *CGLoad = emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl).getNode()); - return SelectCode(CurDAG->getNode(SPUISD::MUL64_MARKER, dl, OpVT, - N->getOperand(0), N->getOperand(1), - SDValue(CGLoad, 0)).getNode()); + HandleSDNode Dummy(CurDAG->getNode(SPUISD::MUL64_MARKER, dl, OpVT, + N->getOperand(0), N->getOperand(1), + SDValue(CGLoad, 0))); + CurDAG->ReplaceAllUsesWith(N, Dummy.getValue().getNode()); + if (SDNode *N = SelectCode(Dummy.getValue().getNode())) + return N; + return Dummy.getValue().getNode(); } else if (Opc == ISD::TRUNCATE) { SDValue Op0 = N->getOperand(0); if ((Op0.getOpcode() == ISD::SRA || Op0.getOpcode() == ISD::SRL) @@ -832,17 +850,14 @@ SPUDAGToDAGISel::Select(SDNode *N) { } } } else if (Opc == ISD::SHL) { - if (OpVT == MVT::i64) { + if (OpVT == MVT::i64) return SelectSHLi64(N, OpVT); - } } else if (Opc == ISD::SRL) { - if (OpVT == MVT::i64) { + if (OpVT == MVT::i64) return SelectSRLi64(N, OpVT); - } } else if (Opc == ISD::SRA) { - if (OpVT == MVT::i64) { + if (OpVT == MVT::i64) return SelectSRAi64(N, OpVT); - } } else if (Opc == ISD::FNEG && (OpVT == MVT::f64 || OpVT == MVT::v2f64)) { DebugLoc dl = N->getDebugLoc(); @@ -1224,13 +1239,15 @@ SDNode *SPUDAGToDAGISel::SelectI64Constant(uint64_t Value64, EVT OpVT, ? shufmask.getNode() : emitBuildVector(shufmask.getNode())); - SDNode *shufNode = - Select(CurDAG->getNode(SPUISD::SHUFB, dl, OpVecVT, + SDValue shufNode = + CurDAG->getNode(SPUISD::SHUFB, dl, OpVecVT, SDValue(lhsNode, 0), SDValue(rhsNode, 0), - SDValue(shufMaskNode, 0)).getNode()); - - return CurDAG->getMachineNode(SPU::ORi64_v2i64, dl, OpVT, - SDValue(shufNode, 0)); + SDValue(shufMaskNode, 0)); + HandleSDNode Dummy(shufNode); + SDNode *SN = SelectCode(Dummy.getValue().getNode()); + if (SN == 0) SN = Dummy.getValue().getNode(); + + return CurDAG->getMachineNode(SPU::ORi64_v2i64, dl, OpVT, SDValue(SN, 0)); } else if (i64vec.getOpcode() == ISD::BUILD_VECTOR) { return CurDAG->getMachineNode(SPU::ORi64_v2i64, dl, OpVT, SDValue(emitBuildVector(i64vec.getNode()), 0)); diff --git a/lib/Target/CellSPU/SPUISelLowering.cpp b/lib/Target/CellSPU/SPUISelLowering.cpp index fe0f019646..e863ee31e4 100644 --- a/lib/Target/CellSPU/SPUISelLowering.cpp +++ b/lib/Target/CellSPU/SPUISelLowering.cpp @@ -25,7 +25,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/VectorExtras.h" #include "llvm/Support/Debug.h" @@ -118,8 +118,7 @@ namespace { TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, false, 0, TLI.getLibcallCallingConv(LC), false, /*isReturnValueUsed=*/true, - Callee, Args, DAG, Op.getDebugLoc(), - DAG.GetOrdering(InChain.getNode())); + Callee, Args, DAG, Op.getDebugLoc()); return CallInfo.first; } @@ -669,7 +668,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) { // Re-emit as a v16i8 vector load result = DAG.getLoad(MVT::v16i8, dl, the_chain, basePtr, LN->getSrcValue(), LN->getSrcValueOffset(), - LN->isVolatile(), 16); + LN->isVolatile(), LN->isNonTemporal(), 16); // Update the chain the_chain = result.getValue(1); @@ -820,7 +819,7 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) { // Re-emit as a v16i8 vector load alignLoadVec = DAG.getLoad(MVT::v16i8, dl, the_chain, basePtr, SN->getSrcValue(), SN->getSrcValueOffset(), - SN->isVolatile(), 16); + SN->isVolatile(), SN->isNonTemporal(), 16); // Update the chain the_chain = alignLoadVec.getValue(1); @@ -861,7 +860,8 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG, const SPUSubtarget *ST) { result = DAG.getStore(the_chain, dl, result, basePtr, LN->getSrcValue(), LN->getSrcValueOffset(), - LN->isVolatile(), LN->getAlignment()); + LN->isVolatile(), LN->isNonTemporal(), + LN->getAlignment()); #if 0 && !defined(NDEBUG) if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) { @@ -1086,7 +1086,7 @@ SPUTargetLowering::LowerFormalArguments(SDValue Chain, // or we're forced to do vararg int FI = MFI->CreateFixedObject(ObjSize, ArgOffset, true, false); SDValue FIN = DAG.getFrameIndex(FI, PtrVT); - ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0); + ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0, false, false, 0); ArgOffset += StackSlotSize; } @@ -1108,7 +1108,8 @@ SPUTargetLowering::LowerFormalArguments(SDValue Chain, true, false); SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); SDValue ArgVal = DAG.getRegister(ArgRegs[ArgRegIdx], MVT::v16i8); - SDValue Store = DAG.getStore(Chain, dl, ArgVal, FIN, NULL, 0); + SDValue Store = DAG.getStore(Chain, dl, ArgVal, FIN, NULL, 0, + false, false, 0); Chain = Store.getOperand(0); MemOps.push_back(Store); @@ -1190,7 +1191,8 @@ SPUTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (ArgRegIdx != NumArgRegs) { RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg)); } else { - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0)); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + false, false, 0)); ArgOffset += StackSlotSize; } break; @@ -1199,7 +1201,8 @@ SPUTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (ArgRegIdx != NumArgRegs) { RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg)); } else { - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0)); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + false, false, 0)); ArgOffset += StackSlotSize; } break; @@ -1212,7 +1215,8 @@ SPUTargetLowering::LowerCall(SDValue Chain, SDValue Callee, if (ArgRegIdx != NumArgRegs) { RegsToPass.push_back(std::make_pair(ArgRegs[ArgRegIdx++], Arg)); } else { - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0)); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + false, false, 0)); ArgOffset += StackSlotSize; } break; diff --git a/lib/Target/CellSPU/SPUMCAsmInfo.cpp b/lib/Target/CellSPU/SPUMCAsmInfo.cpp index 5ef3c6b24d..3e17a51b50 100644 --- a/lib/Target/CellSPU/SPUMCAsmInfo.cpp +++ b/lib/Target/CellSPU/SPUMCAsmInfo.cpp @@ -34,5 +34,8 @@ SPULinuxMCAsmInfo::SPULinuxMCAsmInfo(const Target &T, const StringRef &TT) { // Exception handling is not supported on CellSPU (think about it: you only // have 256K for code+data. Would you support exception handling?) ExceptionsType = ExceptionHandling::None; + + // SPU assembly requires ".section" before ".bss" + UsesELFSectionDirectiveForBSS = true; } diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 3dd8ca7c71..9c5893cec0 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -221,7 +221,7 @@ namespace { APFloat APF = APFloat(CFP->getValueAPF()); // copy if (CFP->getType() == Type::getFloatTy(CFP->getContext())) APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &ignored); - Out << "ConstantFP::get(getGlobalContext(), "; + Out << "ConstantFP::get(mod->getContext(), "; Out << "APFloat("; #if HAVE_PRINTF_A char Buffer[100]; @@ -344,23 +344,23 @@ namespace { std::string CppWriter::getCppName(const Type* Ty) { // First, handle the primitive types .. easy - if (Ty->isPrimitiveType() || Ty->isInteger()) { + if (Ty->isPrimitiveType() || Ty->isIntegerTy()) { switch (Ty->getTypeID()) { - case Type::VoidTyID: return "Type::getVoidTy(getGlobalContext())"; + case Type::VoidTyID: return "Type::getVoidTy(mod->getContext())"; case Type::IntegerTyID: { unsigned BitWidth = cast(Ty)->getBitWidth(); - return "IntegerType::get(getGlobalContext(), " + utostr(BitWidth) + ")"; + return "IntegerType::get(mod->getContext(), " + utostr(BitWidth) + ")"; } - case Type::X86_FP80TyID: return "Type::getX86_FP80Ty(getGlobalContext())"; - case Type::FloatTyID: return "Type::getFloatTy(getGlobalContext())"; - case Type::DoubleTyID: return "Type::getDoubleTy(getGlobalContext())"; - case Type::LabelTyID: return "Type::getLabelTy(getGlobalContext())"; + case Type::X86_FP80TyID: return "Type::getX86_FP80Ty(mod->getContext())"; + case Type::FloatTyID: return "Type::getFloatTy(mod->getContext())"; + case Type::DoubleTyID: return "Type::getDoubleTy(mod->getContext())"; + case Type::LabelTyID: return "Type::getLabelTy(mod->getContext())"; default: error("Invalid primitive type"); break; } // shouldn't be returned, but make it sensible - return "Type::getVoidTy(getGlobalContext())"; + return "Type::getVoidTy(mod->getContext())"; } // Now, see if we've seen the type before and return that @@ -493,7 +493,7 @@ namespace { bool CppWriter::printTypeInternal(const Type* Ty) { // We don't print definitions for primitive types - if (Ty->isPrimitiveType() || Ty->isInteger()) + if (Ty->isPrimitiveType() || Ty->isIntegerTy()) return false; // If we already defined this type, we don't need to define it again. @@ -514,7 +514,7 @@ namespace { TypeMap::const_iterator I = UnresolvedTypes.find(Ty); if (I == UnresolvedTypes.end()) { Out << "PATypeHolder " << typeName; - Out << "_fwd = OpaqueType::get(getGlobalContext());"; + Out << "_fwd = OpaqueType::get(mod->getContext());"; nl(Out); UnresolvedTypes[Ty] = typeName; } @@ -615,7 +615,7 @@ namespace { } case Type::OpaqueTyID: { Out << "OpaqueType* " << typeName; - Out << " = OpaqueType::get(getGlobalContext());"; + Out << " = OpaqueType::get(mod->getContext());"; nl(Out); break; } @@ -686,7 +686,7 @@ namespace { // For primitive types and types already defined, just add a name TypeMap::const_iterator TNI = TypeNames.find(TI->second); - if (TI->second->isInteger() || TI->second->isPrimitiveType() || + if (TI->second->isIntegerTy() || TI->second->isPrimitiveType() || TNI != TypeNames.end()) { Out << "mod->addTypeName(\""; printEscapedString(TI->first); @@ -751,7 +751,7 @@ namespace { if (const ConstantInt *CI = dyn_cast(CV)) { std::string constValue = CI->getValue().toString(10, true); Out << "ConstantInt* " << constName - << " = ConstantInt::get(getGlobalContext(), APInt(" + << " = ConstantInt::get(mod->getContext(), APInt(" << cast(CI->getType())->getBitWidth() << ", StringRef(\"" << constValue << "\"), 10));"; } else if (isa(CV)) { @@ -769,7 +769,7 @@ namespace { CA->getType()->getElementType() == Type::getInt8Ty(CA->getContext())) { Out << "Constant* " << constName << - " = ConstantArray::get(getGlobalContext(), \""; + " = ConstantArray::get(mod->getContext(), \""; std::string tmp = CA->getAsString(); bool nullTerminate = false; if (tmp[tmp.length()-1] == 0) { @@ -995,7 +995,7 @@ namespace { void CppWriter::printVariableHead(const GlobalVariable *GV) { nl(Out) << "GlobalVariable* " << getCppName(GV); if (is_inline) { - Out << " = mod->getGlobalVariable(getGlobalContext(), "; + Out << " = mod->getGlobalVariable(mod->getContext(), "; printEscapedString(GV->getName()); Out << ", " << getCppName(GV->getType()->getElementType()) << ",true)"; nl(Out) << "if (!" << getCppName(GV) << ") {"; @@ -1094,7 +1094,7 @@ namespace { case Instruction::Ret: { const ReturnInst* ret = cast(I); - Out << "ReturnInst::Create(getGlobalContext(), " + Out << "ReturnInst::Create(mod->getContext(), " << (ret->getReturnValue() ? opNames[0] + ", " : "") << bbname << ");"; break; } @@ -1171,7 +1171,7 @@ namespace { } case Instruction::Unreachable: { Out << "new UnreachableInst(" - << "getGlobalContext(), " + << "mod->getContext(), " << bbname << ");"; break; } @@ -1673,7 +1673,7 @@ namespace { BI != BE; ++BI) { std::string bbname(getCppName(BI)); Out << "BasicBlock* " << bbname << - " = BasicBlock::Create(getGlobalContext(), \""; + " = BasicBlock::Create(mod->getContext(), \""; if (BI->hasName()) printEscapedString(BI->getName()); Out << "\"," << getCppName(BI->getParent()) << ",0);"; @@ -2009,7 +2009,8 @@ char CppWriter::ID = 0; bool CPPTargetMachine::addPassesToEmitWholeFile(PassManager &PM, formatted_raw_ostream &o, CodeGenFileType FileType, - CodeGenOpt::Level OptLevel) { + CodeGenOpt::Level OptLevel, + bool DisableVerify) { if (FileType != TargetMachine::CGFT_AssemblyFile) return true; PM.add(new CppWriter(o)); return false; diff --git a/lib/Target/CppBackend/CPPTargetMachine.h b/lib/Target/CppBackend/CPPTargetMachine.h index 1f74f76b5a..b7aae917ac 100644 --- a/lib/Target/CppBackend/CPPTargetMachine.h +++ b/lib/Target/CppBackend/CPPTargetMachine.h @@ -30,7 +30,8 @@ struct CPPTargetMachine : public TargetMachine { virtual bool addPassesToEmitWholeFile(PassManager &PM, formatted_raw_ostream &Out, CodeGenFileType FileType, - CodeGenOpt::Level OptLevel); + CodeGenOpt::Level OptLevel, + bool DisableVerify); virtual const TargetData *getTargetData() const { return 0; } }; diff --git a/lib/Target/MBlaze/AsmPrinter/CMakeLists.txt b/lib/Target/MBlaze/AsmPrinter/CMakeLists.txt new file mode 100644 index 0000000000..cfb2fc8bf9 --- /dev/null +++ b/lib/Target/MBlaze/AsmPrinter/CMakeLists.txt @@ -0,0 +1,9 @@ +include_directories( + ${CMAKE_CURRENT_BINARY_DIR}/.. + ${CMAKE_CURRENT_SOURCE_DIR}/.. + ) + +add_llvm_library(LLVMMBlazeAsmPrinter + MBlazeAsmPrinter.cpp + ) +add_dependencies(LLVMMBlazeAsmPrinter MBlazeCodeGenTable_gen) \ No newline at end of file diff --git a/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp b/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp new file mode 100644 index 0000000000..6fe102645a --- /dev/null +++ b/lib/Target/MBlaze/AsmPrinter/MBlazeAsmPrinter.cpp @@ -0,0 +1,302 @@ +//===-- MBlazeAsmPrinter.cpp - MBlaze LLVM assembly writer ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a printer that converts from our internal representation +// of machine-dependent LLVM code to GAS-format MBlaze assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mblaze-asm-printer" + +#include "MBlaze.h" +#include "MBlazeSubtarget.h" +#include "MBlazeInstrInfo.h" +#include "MBlazeTargetMachine.h" +#include "MBlazeMachineFunction.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/MathExtras.h" +#include + +using namespace llvm; + +namespace { + class MBlazeAsmPrinter : public AsmPrinter { + const MBlazeSubtarget *Subtarget; + public: + explicit MBlazeAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + MCContext &Ctx, MCStreamer &Streamer, + const MCAsmInfo *T ) + : AsmPrinter(O, TM, Ctx, Streamer, T) { + Subtarget = &TM.getSubtarget(); + } + + virtual const char *getPassName() const { + return "MBlaze Assembly Printer"; + } + + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + void printOperand(const MachineInstr *MI, int opNum); + void printUnsignedImm(const MachineInstr *MI, int opNum); + void printFSLImm(const MachineInstr *MI, int opNum); + void printMemOperand(const MachineInstr *MI, int opNum, + const char *Modifier = 0); + void printFCCOperand(const MachineInstr *MI, int opNum, + const char *Modifier = 0); + void printSavedRegsBitmask(); + void printHex32(unsigned int Value); + + const char *emitCurrentABIString(); + void emitFrameDirective(); + + void printInstruction(const MachineInstr *MI); // autogenerated. + void EmitInstruction(const MachineInstr *MI) { + printInstruction(MI); + O << '\n'; + } + virtual void EmitFunctionBodyStart(); + virtual void EmitFunctionBodyEnd(); + static const char *getRegisterName(unsigned RegNo); + + virtual void EmitFunctionEntryLabel(); + void EmitStartOfAsmFile(Module &M); + }; +} // end of anonymous namespace + +#include "MBlazeGenAsmWriter.inc" + +//===----------------------------------------------------------------------===// +// +// MBlaze Asm Directives +// +// -- Frame directive "frame Stackpointer, Stacksize, RARegister" +// Describe the stack frame. +// +// -- Mask directives "mask bitmask, offset" +// Tells the assembler which registers are saved and where. +// bitmask - contain a little endian bitset indicating which registers are +// saved on function prologue (e.g. with a 0x80000000 mask, the +// assembler knows the register 31 (RA) is saved at prologue. +// offset - the position before stack pointer subtraction indicating where +// the first saved register on prologue is located. (e.g. with a +// +// Consider the following function prologue: +// +// .frame R19,48,R15 +// .mask 0xc0000000,-8 +// addiu R1, R1, -48 +// sw R15, 40(R1) +// sw R19, 36(R1) +// +// With a 0xc0000000 mask, the assembler knows the register 15 (R15) and +// 19 (R19) are saved at prologue. As the save order on prologue is from +// left to right, R15 is saved first. A -8 offset means that after the +// stack pointer subtration, the first register in the mask (R15) will be +// saved at address 48-8=40. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Mask directives +//===----------------------------------------------------------------------===// + +// Create a bitmask with all callee saved registers for CPU or Floating Point +// registers. For CPU registers consider RA, GP and FP for saving if necessary. +void MBlazeAsmPrinter::printSavedRegsBitmask() { + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + const MBlazeFunctionInfo *MBlazeFI = MF->getInfo(); + + // CPU Saved Registers Bitmasks + unsigned int CPUBitmask = 0; + + // Set the CPU Bitmasks + const MachineFrameInfo *MFI = MF->getFrameInfo(); + const std::vector &CSI = MFI->getCalleeSavedInfo(); + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned RegNum = MBlazeRegisterInfo::getRegisterNumbering(CSI[i].getReg()); + if (CSI[i].getRegClass() == MBlaze::CPURegsRegisterClass) + CPUBitmask |= (1 << RegNum); + } + + // Return Address and Frame registers must also be set in CPUBitmask. + if (RI.hasFP(*MF)) + CPUBitmask |= (1 << MBlazeRegisterInfo:: + getRegisterNumbering(RI.getFrameRegister(*MF))); + + if (MFI->hasCalls()) + CPUBitmask |= (1 << MBlazeRegisterInfo:: + getRegisterNumbering(RI.getRARegister())); + + // Print CPUBitmask + O << "\t.mask \t"; printHex32(CPUBitmask); O << ',' + << MBlazeFI->getCPUTopSavedRegOff() << '\n'; +} + +// Print a 32 bit hex number with all numbers. +void MBlazeAsmPrinter::printHex32(unsigned int Value) { + O << "0x"; + for (int i = 7; i >= 0; i--) + O << utohexstr( (Value & (0xF << (i*4))) >> (i*4) ); +} + +//===----------------------------------------------------------------------===// +// Frame and Set directives +//===----------------------------------------------------------------------===// + +/// Frame Directive +void MBlazeAsmPrinter::emitFrameDirective() { + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + + unsigned stackReg = RI.getFrameRegister(*MF); + unsigned returnReg = RI.getRARegister(); + unsigned stackSize = MF->getFrameInfo()->getStackSize(); + + + O << "\t.frame\t" << getRegisterName(stackReg) + << ',' << stackSize << ',' + << getRegisterName(returnReg) + << '\n'; +} + +void MBlazeAsmPrinter::EmitFunctionEntryLabel() { + O << "\t.ent\t" << *CurrentFnSym << '\n'; + OutStreamer.EmitLabel(CurrentFnSym); +} + +/// EmitFunctionBodyStart - Targets can override this to emit stuff before +/// the first basic block in the function. +void MBlazeAsmPrinter::EmitFunctionBodyStart() { + emitFrameDirective(); + printSavedRegsBitmask(); +} + +/// EmitFunctionBodyEnd - Targets can override this to emit stuff after +/// the last basic block in the function. +void MBlazeAsmPrinter::EmitFunctionBodyEnd() { + O << "\t.end\t" << *CurrentFnSym << '\n'; +} + +// Print out an operand for an inline asm expression. +bool MBlazeAsmPrinter:: +PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant,const char *ExtraCode){ + // Does this asm operand have a single letter operand modifier? + if (ExtraCode && ExtraCode[0]) + return true; // Unknown modifier. + + printOperand(MI, OpNo); + return false; +} + +void MBlazeAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { + const MachineOperand &MO = MI->getOperand(opNum); + + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << getRegisterName(MO.getReg()); + break; + + case MachineOperand::MO_Immediate: + O << (int)MO.getImm(); + break; + + case MachineOperand::MO_FPImmediate: { + const ConstantFP* fp = MO.getFPImm(); + printHex32(fp->getValueAPF().bitcastToAPInt().getZExtValue()); + O << ";\t# immediate = " << *fp; + break; + } + + case MachineOperand::MO_MachineBasicBlock: + O << *MO.getMBB()->getSymbol(OutContext); + return; + + case MachineOperand::MO_GlobalAddress: + O << *GetGlobalValueSymbol(MO.getGlobal()); + break; + + case MachineOperand::MO_ExternalSymbol: + O << *GetExternalSymbolSymbol(MO.getSymbolName()); + break; + + case MachineOperand::MO_JumpTableIndex: + O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + + case MachineOperand::MO_ConstantPoolIndex: + O << MAI->getPrivateGlobalPrefix() << "CPI" + << getFunctionNumber() << "_" << MO.getIndex(); + if (MO.getOffset()) + O << "+" << MO.getOffset(); + break; + + default: + llvm_unreachable(""); + } +} + +void MBlazeAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum) { + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.getType() == MachineOperand::MO_Immediate) + O << (unsigned int)MO.getImm(); + else + printOperand(MI, opNum); +} + +void MBlazeAsmPrinter::printFSLImm(const MachineInstr *MI, int opNum) { + const MachineOperand &MO = MI->getOperand(opNum); + if (MO.getType() == MachineOperand::MO_Immediate) + O << "rfsl" << (unsigned int)MO.getImm(); + else + printOperand(MI, opNum); +} + +void MBlazeAsmPrinter:: +printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier) { + printOperand(MI, opNum+1); + O << ", "; + printOperand(MI, opNum); +} + +void MBlazeAsmPrinter:: +printFCCOperand(const MachineInstr *MI, int opNum, const char *Modifier) { + const MachineOperand& MO = MI->getOperand(opNum); + O << MBlaze::MBlazeFCCToString((MBlaze::CondCode)MO.getImm()); +} + +void MBlazeAsmPrinter::EmitStartOfAsmFile(Module &M) { +} + +// Force static initialization. +extern "C" void LLVMInitializeMBlazeAsmPrinter() { + RegisterAsmPrinter X(TheMBlazeTarget); +} diff --git a/lib/Target/MBlaze/AsmPrinter/Makefile b/lib/Target/MBlaze/AsmPrinter/Makefile new file mode 100644 index 0000000000..c8e4d8f644 --- /dev/null +++ b/lib/Target/MBlaze/AsmPrinter/Makefile @@ -0,0 +1,17 @@ +##===- lib/Target/MBlaze/AsmPrinter/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../../.. +LIBRARYNAME = LLVMMBlazeAsmPrinter + +# Hack: we need to include 'main' MBlaze target directory to grab +# private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/MBlaze/CMakeLists.txt b/lib/Target/MBlaze/CMakeLists.txt new file mode 100644 index 0000000000..c93e3dfc78 --- /dev/null +++ b/lib/Target/MBlaze/CMakeLists.txt @@ -0,0 +1,27 @@ +set(LLVM_TARGET_DEFINITIONS MBlaze.td) + +tablegen(MBlazeGenRegisterInfo.h.inc -gen-register-desc-header) +tablegen(MBlazeGenRegisterNames.inc -gen-register-enums) +tablegen(MBlazeGenRegisterInfo.inc -gen-register-desc) +tablegen(MBlazeGenInstrNames.inc -gen-instr-enums) +tablegen(MBlazeGenInstrInfo.inc -gen-instr-desc) +tablegen(MBlazeGenAsmWriter.inc -gen-asm-writer) +tablegen(MBlazeGenDAGISel.inc -gen-dag-isel) +tablegen(MBlazeGenCallingConv.inc -gen-callingconv) +tablegen(MBlazeGenSubtarget.inc -gen-subtarget) +tablegen(MBlazeGenIntrinsics.inc -gen-tgt-intrinsic) + +add_llvm_target(MBlazeCodeGen + MBlazeDelaySlotFiller.cpp + MBlazeInstrInfo.cpp + MBlazeISelDAGToDAG.cpp + MBlazeISelLowering.cpp + MBlazeMCAsmInfo.cpp + MBlazeRegisterInfo.cpp + MBlazeSubtarget.cpp + MBlazeTargetMachine.cpp + MBlazeTargetObjectFile.cpp + MBlazeIntrinsicInfo.cpp + ) + +target_link_libraries (LLVMMBlazeCodeGen LLVMSelectionDAG) diff --git a/lib/Target/MBlaze/MBlaze.h b/lib/Target/MBlaze/MBlaze.h new file mode 100644 index 0000000000..f9d828b266 --- /dev/null +++ b/lib/Target/MBlaze/MBlaze.h @@ -0,0 +1,39 @@ +//===-- MBlaze.h - Top-level interface for MBlaze ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in +// the LLVM MBlaze back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_MBLAZE_H +#define TARGET_MBLAZE_H + +#include "llvm/Target/TargetMachine.h" + +namespace llvm { + class MBlazeTargetMachine; + class FunctionPass; + class MachineCodeEmitter; + class formatted_raw_ostream; + + FunctionPass *createMBlazeISelDag(MBlazeTargetMachine &TM); + FunctionPass *createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &TM); + + extern Target TheMBlazeTarget; +} // end namespace llvm; + +// Defines symbolic names for MBlaze registers. This defines a mapping from +// register name to register number. +#include "MBlazeGenRegisterNames.inc" + +// Defines symbolic names for the MBlaze instructions. +#include "MBlazeGenInstrNames.inc" + +#endif diff --git a/lib/Target/MBlaze/MBlaze.td b/lib/Target/MBlaze/MBlaze.td new file mode 100644 index 0000000000..16797529cb --- /dev/null +++ b/lib/Target/MBlaze/MBlaze.td @@ -0,0 +1,85 @@ +//===- MBlaze.td - Describe the MBlaze Target Machine -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This is the top level entry point for the MBlaze target. +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces +//===----------------------------------------------------------------------===// + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// Register File, Calling Conv, Instruction Descriptions +//===----------------------------------------------------------------------===// + +include "MBlazeRegisterInfo.td" +include "MBlazeSchedule.td" +include "MBlazeIntrinsics.td" +include "MBlazeInstrInfo.td" +include "MBlazeCallingConv.td" + +def MBlazeInstrInfo : InstrInfo { + let TSFlagsFields = []; + let TSFlagsShifts = []; +} + + +//===----------------------------------------------------------------------===// +// Microblaze Subtarget features // +//===----------------------------------------------------------------------===// + +def FeaturePipe3 : SubtargetFeature<"pipe3", "HasPipe3", "true", + "Implements 3-stage pipeline.">; +def FeatureBarrel : SubtargetFeature<"barrel", "HasBarrel", "true", + "Implements barrel shifter.">; +def FeatureDiv : SubtargetFeature<"div", "HasDiv", "true", + "Implements hardware divider.">; +def FeatureMul : SubtargetFeature<"mul", "HasMul", "true", + "Implements hardware multiplier.">; +def FeatureFSL : SubtargetFeature<"fsl", "HasFSL", "true", + "Implements FSL instructions.">; +def FeatureEFSL : SubtargetFeature<"efsl", "HasEFSL", "true", + "Implements extended FSL instructions.">; +def FeatureMSRSet : SubtargetFeature<"msrset", "HasMSRSet", "true", + "Implements MSR register set and clear.">; +def FeatureException : SubtargetFeature<"exception", "HasException", "true", + "Implements hardware exception support.">; +def FeaturePatCmp : SubtargetFeature<"patcmp", "HasPatCmp", "true", + "Implements pattern compare instruction.">; +def FeatureFPU : SubtargetFeature<"fpu", "HasFPU", "true", + "Implements floating point unit.">; +def FeatureESR : SubtargetFeature<"esr", "HasESR", "true", + "Implements ESR and EAR registers">; +def FeaturePVR : SubtargetFeature<"pvr", "HasPVR", "true", + "Implements processor version register.">; +def FeatureMul64 : SubtargetFeature<"mul64", "HasMul64", "true", + "Implements multiplier with 64-bit result">; +def FeatureSqrt : SubtargetFeature<"sqrt", "HasSqrt", "true", + "Implements sqrt and floating point convert.">; +def FeatureMMU : SubtargetFeature<"mmu", "HasMMU", "true", + "Implements memory management unit.">; + +//===----------------------------------------------------------------------===// +// MBlaze processors supported. +//===----------------------------------------------------------------------===// + +class Proc Features> + : Processor; + + +def : Proc<"v400", []>; +def : Proc<"v500", []>; +def : Proc<"v600", []>; +def : Proc<"v700", []>; +def : Proc<"v710", []>; + +def MBlaze : Target { + let InstructionSet = MBlazeInstrInfo; +} diff --git a/lib/Target/MBlaze/MBlazeCallingConv.td b/lib/Target/MBlaze/MBlazeCallingConv.td new file mode 100644 index 0000000000..ddd49980e0 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeCallingConv.td @@ -0,0 +1,26 @@ +//===- MBlazeCallingConv.td - Calling Conventions for MBlaze ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This describes the calling conventions for MBlaze architecture. +//===----------------------------------------------------------------------===// + +/// CCIfSubtarget - Match if the current subtarget has a feature F. +class CCIfSubtarget: + CCIf().", F), A>; + +//===----------------------------------------------------------------------===// +// MBlaze ABI Calling Convention +//===----------------------------------------------------------------------===// + +def RetCC_MBlaze : CallingConv<[ + // i32 are returned in registers R3, R4 + CCIfType<[i32], CCAssignToReg<[R3, R4]>>, + + // f32 are returned in registers F3, F4 + CCIfType<[f32], CCAssignToReg<[F3, F4]>> +]>; diff --git a/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp new file mode 100644 index 0000000000..42fea25073 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp @@ -0,0 +1,75 @@ +//===-- DelaySlotFiller.cpp - MBlaze delay slot filler --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Simple pass to fills delay slots with NOPs. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "delay-slot-filler" + +#include "MBlaze.h" +#include "MBlazeTargetMachine.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/ADT/Statistic.h" + +using namespace llvm; + +STATISTIC(FilledSlots, "Number of delay slots filled"); + +namespace { + struct Filler : public MachineFunctionPass { + + TargetMachine &TM; + const TargetInstrInfo *TII; + + static char ID; + Filler(TargetMachine &tm) + : MachineFunctionPass(&ID), TM(tm), TII(tm.getInstrInfo()) { } + + virtual const char *getPassName() const { + return "MBlaze Delay Slot Filler"; + } + + bool runOnMachineBasicBlock(MachineBasicBlock &MBB); + bool runOnMachineFunction(MachineFunction &F) { + bool Changed = false; + for (MachineFunction::iterator FI = F.begin(), FE = F.end(); + FI != FE; ++FI) + Changed |= runOnMachineBasicBlock(*FI); + return Changed; + } + + }; + char Filler::ID = 0; +} // end of anonymous namespace + +/// runOnMachineBasicBlock - Fill in delay slots for the given basic block. +/// Currently, we fill delay slots with NOPs. We assume there is only one +/// delay slot per delayed instruction. +bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { + bool Changed = false; + for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) + if (I->getDesc().hasDelaySlot()) { + MachineBasicBlock::iterator J = I; + ++J; + BuildMI(MBB, J, I->getDebugLoc(), TII->get(MBlaze::NOP)); + ++FilledSlots; + Changed = true; + } + return Changed; +} + +/// createMBlazeDelaySlotFillerPass - Returns a pass that fills in delay +/// slots in MBlaze MachineFunctions +FunctionPass *llvm::createMBlazeDelaySlotFillerPass(MBlazeTargetMachine &tm) { + return new Filler(tm); +} + diff --git a/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp b/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp new file mode 100644 index 0000000000..7e59c4a164 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeISelDAGToDAG.cpp @@ -0,0 +1,339 @@ +//===-- MBlazeISelDAGToDAG.cpp - A dag to dag inst selector for MBlaze ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an instruction selector for the MBlaze target. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mblaze-isel" +#include "MBlaze.h" +#include "MBlazeISelLowering.h" +#include "MBlazeMachineFunction.h" +#include "MBlazeRegisterInfo.h" +#include "MBlazeSubtarget.h" +#include "MBlazeTargetMachine.h" +#include "llvm/GlobalValue.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/Support/CFG.h" +#include "llvm/Type.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Instruction Selector Implementation +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MBlazeDAGToDAGISel - MBlaze specific code to select MBlaze machine +// instructions for SelectionDAG operations. +//===----------------------------------------------------------------------===// +namespace { + +class MBlazeDAGToDAGISel : public SelectionDAGISel { + + /// TM - Keep a reference to MBlazeTargetMachine. + MBlazeTargetMachine &TM; + + /// Subtarget - Keep a pointer to the MBlazeSubtarget around so that we can + /// make the right decision when generating code for different targets. + const MBlazeSubtarget &Subtarget; + +public: + explicit MBlazeDAGToDAGISel(MBlazeTargetMachine &tm) : + SelectionDAGISel(tm), + TM(tm), Subtarget(tm.getSubtarget()) {} + + // Pass Name + virtual const char *getPassName() const { + return "MBlaze DAG->DAG Pattern Instruction Selection"; + } +private: + // Include the pieces autogenerated from the target description. + #include "MBlazeGenDAGISel.inc" + + /// getTargetMachine - Return a reference to the TargetMachine, casted + /// to the target-specific type. + const MBlazeTargetMachine &getTargetMachine() { + return static_cast(TM); + } + + /// getInstrInfo - Return a reference to the TargetInstrInfo, casted + /// to the target-specific type. + const MBlazeInstrInfo *getInstrInfo() { + return getTargetMachine().getInstrInfo(); + } + + SDNode *getGlobalBaseReg(); + SDNode *Select(SDNode *N); + + // Complex Pattern. + bool SelectAddr(SDNode *Op, SDValue N, + SDValue &Base, SDValue &Offset); + + // Address Selection + bool SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index); + bool SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base); + + // getI32Imm - Return a target constant with the specified value, of type i32. + inline SDValue getI32Imm(unsigned Imm) { + return CurDAG->getTargetConstant(Imm, MVT::i32); + } +}; + +} + +/// isIntS32Immediate - This method tests to see if the node is either a 32-bit +/// or 64-bit immediate, and if the value can be accurately represented as a +/// sign extension from a 32-bit value. If so, this returns true and the +/// immediate. +static bool isIntS32Immediate(SDNode *N, int32_t &Imm) { + unsigned Opc = N->getOpcode(); + if (Opc != ISD::Constant) + return false; + + Imm = (int32_t)cast(N)->getZExtValue(); + if (N->getValueType(0) == MVT::i32) + return Imm == (int32_t)cast(N)->getZExtValue(); + else + return Imm == (int64_t)cast(N)->getZExtValue(); +} + +static bool isIntS32Immediate(SDValue Op, int32_t &Imm) { + return isIntS32Immediate(Op.getNode(), Imm); +} + + +/// SelectAddressRegReg - Given the specified addressed, check to see if it +/// can be represented as an indexed [r+r] operation. Returns false if it +/// can be more efficiently represented with [r+imm]. +bool MBlazeDAGToDAGISel:: +SelectAddrRegReg(SDNode *Op, SDValue N, SDValue &Base, SDValue &Index) { + if (N.getOpcode() == ISD::FrameIndex) return false; + if (N.getOpcode() == ISD::TargetExternalSymbol || + N.getOpcode() == ISD::TargetGlobalAddress) + return false; // direct calls. + + int32_t imm = 0; + if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { + if (isIntS32Immediate(N.getOperand(1), imm)) + return false; // r+i + + if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable || + N.getOperand(1).getOpcode() == ISD::TargetJumpTable) + return false; // jump tables. + + Base = N.getOperand(1); + Index = N.getOperand(0); + return true; + } + + return false; +} + +/// Returns true if the address N can be represented by a base register plus +/// a signed 32-bit displacement [r+imm], and if it is not better +/// represented as reg+reg. +bool MBlazeDAGToDAGISel:: +SelectAddrRegImm(SDNode *Op, SDValue N, SDValue &Disp, SDValue &Base) { + // If this can be more profitably realized as r+r, fail. + if (SelectAddrRegReg(Op, N, Disp, Base)) + return false; + + if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) { + int32_t imm = 0; + if (isIntS32Immediate(N.getOperand(1), imm)) { + Disp = CurDAG->getTargetConstant(imm, MVT::i32); + if (FrameIndexSDNode *FI = dyn_cast(N.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); + } else { + Base = N.getOperand(0); + } + DEBUG( errs() << "WESLEY: Using Operand Immediate\n" ); + return true; // [r+i] + } + } else if (ConstantSDNode *CN = dyn_cast(N)) { + // Loading from a constant address. + uint32_t Imm = CN->getZExtValue(); + Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0)); + Base = CurDAG->getRegister(MBlaze::R0, CN->getValueType(0)); + DEBUG( errs() << "WESLEY: Using Constant Node\n" ); + return true; + } + + Disp = CurDAG->getTargetConstant(0, TM.getTargetLowering()->getPointerTy()); + if (FrameIndexSDNode *FI = dyn_cast(N)) + Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType()); + else + Base = N; + return true; // [r+0] +} + +/// getGlobalBaseReg - Output the instructions required to put the +/// GOT address into a register. +SDNode *MBlazeDAGToDAGISel::getGlobalBaseReg() { + unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF); + return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); +} + +/// ComplexPattern used on MBlazeInstrInfo +/// Used on MBlaze Load/Store instructions +bool MBlazeDAGToDAGISel:: +SelectAddr(SDNode *Op, SDValue Addr, SDValue &Offset, SDValue &Base) { + // if Address is FI, get the TargetFrameIndex. + if (FrameIndexSDNode *FIN = dyn_cast(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; + } + + // on PIC code Load GA + if (TM.getRelocationModel() == Reloc::PIC_) { + if ((Addr.getOpcode() == ISD::TargetGlobalAddress) || + (Addr.getOpcode() == ISD::TargetConstantPool) || + (Addr.getOpcode() == ISD::TargetJumpTable)){ + Base = CurDAG->getRegister(MBlaze::R15, MVT::i32); + Offset = Addr; + return true; + } + } else { + if ((Addr.getOpcode() == ISD::TargetExternalSymbol || + Addr.getOpcode() == ISD::TargetGlobalAddress)) + return false; + } + + // Operand is a result from an ADD. + if (Addr.getOpcode() == ISD::ADD) { + if (ConstantSDNode *CN = dyn_cast(Addr.getOperand(1))) { + if (Predicate_immSExt16(CN)) { + + // If the first operand is a FI, get the TargetFI Node + if (FrameIndexSDNode *FIN = dyn_cast + (Addr.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); + } else { + Base = Addr.getOperand(0); + } + + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32); + return true; + } + } + } + + Base = Addr; + Offset = CurDAG->getTargetConstant(0, MVT::i32); + return true; +} + +/// Select instructions not customized! Used for +/// expanded, promoted and normal instructions +SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) { + unsigned Opcode = Node->getOpcode(); + DebugLoc dl = Node->getDebugLoc(); + + // Dump information about the Node being selected + DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); + + // If we have a custom node, we already have selected! + if (Node->isMachineOpcode()) { + DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); + return NULL; + } + + /// + // Instruction Selection not handled by the auto-generated + // tablegen selection should be handled here. + /// + switch(Opcode) { + default: break; + + // Get target GOT address. + case ISD::GLOBAL_OFFSET_TABLE: + return getGlobalBaseReg(); + + case ISD::FrameIndex: { + SDValue imm = CurDAG->getTargetConstant(0, MVT::i32); + int FI = dyn_cast(Node)->getIndex(); + EVT VT = Node->getValueType(0); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); + unsigned Opc = MBlaze::ADDI; + if (Node->hasOneUse()) + return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm); + return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm); + } + + + /// Handle direct and indirect calls when using PIC. On PIC, when + /// GOT is smaller than about 64k (small code) the GA target is + /// loaded with only one instruction. Otherwise GA's target must + /// be loaded with 3 instructions. + case MBlazeISD::JmpLink: { + if (TM.getRelocationModel() == Reloc::PIC_) { + SDValue Chain = Node->getOperand(0); + SDValue Callee = Node->getOperand(1); + SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32); + SDValue InFlag(0, 0); + + if ( (isa(Callee)) || + (isa(Callee)) ) + { + /// Direct call for global addresses and external symbols + SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32); + + // Use load to get GOT target + SDValue Ops[] = { Callee, GPReg, Chain }; + SDValue Load = SDValue(CurDAG->getMachineNode(MBlaze::LW, dl, + MVT::i32, MVT::Other, Ops, 3), 0); + Chain = Load.getValue(1); + + // Call target must be on T9 + Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag); + } else + /// Indirect call + Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag); + + // Emit Jump and Link Register + SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other, + MVT::Flag, R20Reg, Chain); + Chain = SDValue(ResNode, 0); + InFlag = SDValue(ResNode, 1); + ReplaceUses(SDValue(Node, 0), Chain); + ReplaceUses(SDValue(Node, 1), InFlag); + return ResNode; + } + } + } + + // Select the default instruction + SDNode *ResNode = SelectCode(Node); + + DEBUG(errs() << "=> "); + if (ResNode == NULL || ResNode == Node) + DEBUG(Node->dump(CurDAG)); + else + DEBUG(ResNode->dump(CurDAG)); + DEBUG(errs() << "\n"); + return ResNode; +} + +/// createMBlazeISelDag - This pass converts a legalized DAG into a +/// MBlaze-specific DAG, ready for instruction scheduling. +FunctionPass *llvm::createMBlazeISelDag(MBlazeTargetMachine &TM) { + return new MBlazeDAGToDAGISel(TM); +} diff --git a/lib/Target/MBlaze/MBlazeISelLowering.cpp b/lib/Target/MBlaze/MBlazeISelLowering.cpp new file mode 100644 index 0000000000..f0864d0f49 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeISelLowering.cpp @@ -0,0 +1,975 @@ +//===-- MBlazeISelLowering.cpp - MBlaze DAG Lowering Implementation -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interfaces that MBlaze uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mblaze-lower" +#include "MBlazeISelLowering.h" +#include "MBlazeMachineFunction.h" +#include "MBlazeTargetMachine.h" +#include "MBlazeTargetObjectFile.h" +#include "MBlazeSubtarget.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/Intrinsics.h" +#include "llvm/CallingConv.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +const char *MBlazeTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch (Opcode) { + case MBlazeISD::JmpLink : return "MBlazeISD::JmpLink"; + case MBlazeISD::GPRel : return "MBlazeISD::GPRel"; + case MBlazeISD::Wrap : return "MBlazeISD::Wrap"; + case MBlazeISD::ICmp : return "MBlazeISD::ICmp"; + case MBlazeISD::Ret : return "MBlazeISD::Ret"; + case MBlazeISD::Select_CC : return "MBlazeISD::Select_CC"; + default : return NULL; + } +} + +MBlazeTargetLowering::MBlazeTargetLowering(MBlazeTargetMachine &TM) + : TargetLowering(TM, new MBlazeTargetObjectFile()) { + Subtarget = &TM.getSubtarget(); + + // MBlaze does not have i1 type, so use i32 for + // setcc operations results (slt, sgt, ...). + setBooleanContents(ZeroOrOneBooleanContent); + + // Set up the register classes + addRegisterClass(MVT::i32, MBlaze::CPURegsRegisterClass); + if (Subtarget->hasFPU()) { + addRegisterClass(MVT::f32, MBlaze::FGR32RegisterClass); + setOperationAction(ISD::ConstantFP, MVT::f32, Legal); + } + + // Floating point operations which are not supported + setOperationAction(ISD::FREM, MVT::f32, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i8, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i16, Expand); + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); + setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); + setOperationAction(ISD::FP_ROUND, MVT::f32, Expand); + setOperationAction(ISD::FP_ROUND, MVT::f64, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); + setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); + setOperationAction(ISD::FSIN, MVT::f32, Expand); + setOperationAction(ISD::FCOS, MVT::f32, Expand); + setOperationAction(ISD::FPOWI, MVT::f32, Expand); + setOperationAction(ISD::FPOW, MVT::f32, Expand); + setOperationAction(ISD::FLOG, MVT::f32, Expand); + setOperationAction(ISD::FLOG2, MVT::f32, Expand); + setOperationAction(ISD::FLOG10, MVT::f32, Expand); + setOperationAction(ISD::FEXP, MVT::f32, Expand); + + // Load extented operations for i1 types must be promoted + setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); + setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); + + // MBlaze has no REM or DIVREM operations. + setOperationAction(ISD::UREM, MVT::i32, Expand); + setOperationAction(ISD::SREM, MVT::i32, Expand); + setOperationAction(ISD::SDIVREM, MVT::i32, Expand); + setOperationAction(ISD::UDIVREM, MVT::i32, Expand); + + // If the processor doesn't support multiply then expand it + if (!Subtarget->hasMul()) { + setOperationAction(ISD::MUL, MVT::i32, Expand); + } + + // If the processor doesn't support 64-bit multiply then expand + if (!Subtarget->hasMul() || !Subtarget->hasMul64()) { + setOperationAction(ISD::MULHS, MVT::i32, Expand); + setOperationAction(ISD::MULHS, MVT::i64, Expand); + setOperationAction(ISD::MULHU, MVT::i32, Expand); + setOperationAction(ISD::MULHU, MVT::i64, Expand); + } + + // If the processor doesn't support division then expand + if (!Subtarget->hasDiv()) { + setOperationAction(ISD::UDIV, MVT::i32, Expand); + setOperationAction(ISD::SDIV, MVT::i32, Expand); + } + + // Expand unsupported conversions + setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); + setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); + + // Expand SELECT_CC + setOperationAction(ISD::SELECT_CC, MVT::Other, Expand); + + // MBlaze doesn't have MUL_LOHI + setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); + + // Used by legalize types to correctly generate the setcc result. + // Without this, every float setcc comes with a AND/OR with the result, + // we don't want this, since the fpcmp result goes to a flag register, + // which is used implicitly by brcond and select operations. + AddPromotedToType(ISD::SETCC, MVT::i1, MVT::i32); + AddPromotedToType(ISD::SELECT, MVT::i1, MVT::i32); + AddPromotedToType(ISD::SELECT_CC, MVT::i1, MVT::i32); + + // MBlaze Custom Operations + setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); + setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); + setOperationAction(ISD::JumpTable, MVT::i32, Custom); + setOperationAction(ISD::ConstantPool, MVT::i32, Custom); + + // Variable Argument support + setOperationAction(ISD::VASTART, MVT::Other, Custom); + setOperationAction(ISD::VAEND, MVT::Other, Expand); + setOperationAction(ISD::VAARG, MVT::Other, Expand); + setOperationAction(ISD::VACOPY, MVT::Other, Expand); + + + // Operations not directly supported by MBlaze. + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::Other, Expand); + setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); + setOperationAction(ISD::ROTL, MVT::i32, Expand); + setOperationAction(ISD::ROTR, MVT::i32, Expand); + setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); + setOperationAction(ISD::CTLZ, MVT::i32, Expand); + setOperationAction(ISD::CTTZ, MVT::i32, Expand); + setOperationAction(ISD::CTPOP, MVT::i32, Expand); + setOperationAction(ISD::BSWAP, MVT::i32, Expand); + + // We don't have line number support yet. + setOperationAction(ISD::EH_LABEL, MVT::Other, Expand); + + // Use the default for now + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); + + // MBlaze doesn't have extending float->double load/store + setLoadExtAction(ISD::EXTLOAD, MVT::f32, Expand); + setTruncStoreAction(MVT::f64, MVT::f32, Expand); + + setStackPointerRegisterToSaveRestore(MBlaze::R1); + computeRegisterProperties(); +} + +MVT::SimpleValueType MBlazeTargetLowering::getSetCCResultType(EVT VT) const { + return MVT::i32; +} + +/// getFunctionAlignment - Return the Log2 alignment of this function. +unsigned MBlazeTargetLowering::getFunctionAlignment(const Function *) const { + return 2; +} + +SDValue MBlazeTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { + switch (Op.getOpcode()) + { + case ISD::ConstantPool: return LowerConstantPool(Op, DAG); + case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG); + case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); + case ISD::JumpTable: return LowerJumpTable(Op, DAG); + case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); + case ISD::VASTART: return LowerVASTART(Op, DAG); + } + return SDValue(); +} + +//===----------------------------------------------------------------------===// +// Lower helper functions +//===----------------------------------------------------------------------===// +MachineBasicBlock* MBlazeTargetLowering:: +EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB, + DenseMap *EM) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc dl = MI->getDebugLoc(); + + switch (MI->getOpcode()) { + default: assert(false && "Unexpected instr type to insert"); + case MBlaze::ShiftRL: + case MBlaze::ShiftRA: + case MBlaze::ShiftL: { + // To "insert" a shift left instruction, we actually have to insert a + // simple loop. The incoming instruction knows the destination vreg to + // set, the source vreg to operate over and the shift amount. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + // start: + // andi samt, samt, 31 + // beqid samt, finish + // add dst, src, r0 + // loop: + // addik samt, samt, -1 + // sra dst, dst + // bneid samt, loop + // nop + // finish: + MachineFunction *F = BB->getParent(); + MachineRegisterInfo &R = F->getRegInfo(); + MachineBasicBlock *loop = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *finish = F->CreateMachineBasicBlock(LLVM_BB); + + unsigned IAMT = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); + BuildMI(BB, dl, TII->get(MBlaze::ANDI), IAMT) + .addReg(MI->getOperand(2).getReg()) + .addImm(31); + + unsigned IVAL = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); + BuildMI(BB, dl, TII->get(MBlaze::ADDI), IVAL) + .addReg(MI->getOperand(1).getReg()) + .addImm(0); + + BuildMI(BB, dl, TII->get(MBlaze::BEQID)) + .addReg(IAMT) + .addMBB(finish); + + F->insert(It, loop); + F->insert(It, finish); + + // Update machine-CFG edges by first adding all successors of the current + // block to the new block which will contain the Phi node for the select. + // Also inform sdisel of the edge changes. + for(MachineBasicBlock::succ_iterator i = BB->succ_begin(), + e = BB->succ_end(); i != e; ++i) { + EM->insert(std::make_pair(*i, finish)); + finish->addSuccessor(*i); + } + + // Next, remove all successors of the current block, and add the true + // and fallthrough blocks as its successors. + while(!BB->succ_empty()) + BB->removeSuccessor(BB->succ_begin()); + BB->addSuccessor(loop); + BB->addSuccessor(finish); + + // Next, add the finish block as a successor of the loop block + loop->addSuccessor(finish); + loop->addSuccessor(loop); + + unsigned DST = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); + unsigned NDST = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); + BuildMI(loop, dl, TII->get(MBlaze::PHI), DST) + .addReg(IVAL).addMBB(BB) + .addReg(NDST).addMBB(loop); + + unsigned SAMT = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); + unsigned NAMT = R.createVirtualRegister(MBlaze::CPURegsRegisterClass); + BuildMI(loop, dl, TII->get(MBlaze::PHI), SAMT) + .addReg(IAMT).addMBB(BB) + .addReg(NAMT).addMBB(loop); + + if (MI->getOpcode() == MBlaze::ShiftL) + BuildMI(loop, dl, TII->get(MBlaze::ADD), NDST).addReg(DST).addReg(DST); + else if (MI->getOpcode() == MBlaze::ShiftRA) + BuildMI(loop, dl, TII->get(MBlaze::SRA), NDST).addReg(DST); + else if (MI->getOpcode() == MBlaze::ShiftRL) + BuildMI(loop, dl, TII->get(MBlaze::SRL), NDST).addReg(DST); + else + llvm_unreachable( "Cannot lower unknown shift instruction" ); + + BuildMI(loop, dl, TII->get(MBlaze::ADDI), NAMT) + .addReg(SAMT) + .addImm(-1); + + BuildMI(loop, dl, TII->get(MBlaze::BNEID)) + .addReg(NAMT) + .addMBB(loop); + + BuildMI(finish, dl, TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + .addReg(IVAL).addMBB(BB) + .addReg(NDST).addMBB(loop); + + // The pseudo instruction is no longer needed so remove it + F->DeleteMachineInstr(MI); + return finish; + } + + case MBlaze::Select_FCC: + case MBlaze::Select_CC: { + // To "insert" a SELECT_CC instruction, we actually have to insert the + // diamond control-flow pattern. The incoming instruction knows the + // destination vreg to set, the condition code register to branch on, the + // true/false values to select between, and a branch opcode to use. + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator It = BB; + ++It; + + // thisMBB: + // ... + // TrueVal = ... + // setcc r1, r2, r3 + // bNE r1, r0, copy1MBB + // fallthrough --> copy0MBB + MachineFunction *F = BB->getParent(); + MachineBasicBlock *flsBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *dneBB = F->CreateMachineBasicBlock(LLVM_BB); + + unsigned Opc; + switch (MI->getOperand(4).getImm()) { + default: llvm_unreachable( "Unknown branch condition" ); + case MBlazeCC::EQ: Opc = MBlaze::BNEID; break; + case MBlazeCC::NE: Opc = MBlaze::BEQID; break; + case MBlazeCC::GT: Opc = MBlaze::BLEID; break; + case MBlazeCC::LT: Opc = MBlaze::BGEID; break; + case MBlazeCC::GE: Opc = MBlaze::BLTID; break; + case MBlazeCC::LE: Opc = MBlaze::BGTID; break; + } + + BuildMI(BB, dl, TII->get(Opc)) + .addReg(MI->getOperand(3).getReg()) + .addMBB(dneBB); + + F->insert(It, flsBB); + F->insert(It, dneBB); + + // Update machine-CFG edges by first adding all successors of the current + // block to the new block which will contain the Phi node for the select. + // Also inform sdisel of the edge changes. + for(MachineBasicBlock::succ_iterator i = BB->succ_begin(), + e = BB->succ_end(); i != e; ++i) { + EM->insert(std::make_pair(*i, dneBB)); + dneBB->addSuccessor(*i); + } + + // Next, remove all successors of the current block, and add the true + // and fallthrough blocks as its successors. + while(!BB->succ_empty()) + BB->removeSuccessor(BB->succ_begin()); + BB->addSuccessor(flsBB); + BB->addSuccessor(dneBB); + flsBB->addSuccessor(dneBB); + + // sinkMBB: + // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] + // ... + //BuildMI(dneBB, dl, TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + // .addReg(MI->getOperand(1).getReg()).addMBB(flsBB) + // .addReg(MI->getOperand(2).getReg()).addMBB(BB); + + BuildMI(dneBB, dl, TII->get(MBlaze::PHI), MI->getOperand(0).getReg()) + .addReg(MI->getOperand(2).getReg()).addMBB(flsBB) + .addReg(MI->getOperand(1).getReg()).addMBB(BB); + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return dneBB; + } + } +} + +//===----------------------------------------------------------------------===// +// Misc Lower Operation implementation +//===----------------------------------------------------------------------===// +// + +SDValue MBlazeTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { + SDValue LHS = Op.getOperand(0); + SDValue RHS = Op.getOperand(1); + SDValue TrueVal = Op.getOperand(2); + SDValue FalseVal = Op.getOperand(3); + DebugLoc dl = Op.getDebugLoc(); + unsigned Opc; + + SDValue CompareFlag; + if (LHS.getValueType() == MVT::i32) { + Opc = MBlazeISD::Select_CC; + CompareFlag = DAG.getNode(MBlazeISD::ICmp, dl, MVT::i32, LHS, RHS) + .getValue(1); + } else { + llvm_unreachable( "Cannot lower select_cc with unknown type" ); + } + + return DAG.getNode(Opc, dl, TrueVal.getValueType(), TrueVal, FalseVal, + CompareFlag); +} + +SDValue MBlazeTargetLowering:: +LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { + // FIXME there isn't actually debug info here + DebugLoc dl = Op.getDebugLoc(); + GlobalValue *GV = cast(Op)->getGlobal(); + SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32); + + return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, GA); +} + +SDValue MBlazeTargetLowering:: +LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) { + llvm_unreachable("TLS not implemented for MicroBlaze."); + return SDValue(); // Not reached +} + +SDValue MBlazeTargetLowering:: +LowerJumpTable(SDValue Op, SelectionDAG &DAG) { + SDValue ResNode; + SDValue HiPart; + // FIXME there isn't actually debug info here + DebugLoc dl = Op.getDebugLoc(); + bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; + unsigned char OpFlag = IsPIC ? MBlazeII::MO_GOT : MBlazeII::MO_ABS_HILO; + + EVT PtrVT = Op.getValueType(); + JumpTableSDNode *JT = cast(Op); + + SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OpFlag); + return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, JTI); + //return JTI; +} + +SDValue MBlazeTargetLowering:: +LowerConstantPool(SDValue Op, SelectionDAG &DAG) { + SDValue ResNode; + EVT PtrVT = Op.getValueType(); + ConstantPoolSDNode *N = cast(Op); + Constant *C = N->getConstVal(); + SDValue Zero = DAG.getConstant(0, PtrVT); + DebugLoc dl = Op.getDebugLoc(); + + SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), + N->getOffset(), MBlazeII::MO_ABS_HILO); + return DAG.getNode(MBlazeISD::Wrap, dl, MVT::i32, CP); +} + +SDValue MBlazeTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) { + DebugLoc dl = Op.getDebugLoc(); + SDValue FI = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy()); + + // vastart just stores the address of the VarArgsFrameIndex slot into the + // memory location argument. + const Value *SV = cast(Op.getOperand(2))->getValue(); + return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0, + false, false, 0); +} + +//===----------------------------------------------------------------------===// +// Calling Convention Implementation +//===----------------------------------------------------------------------===// + +#include "MBlazeGenCallingConv.inc" + +static bool CC_MBlaze2(unsigned ValNo, EVT ValVT, + EVT LocVT, CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { + static const unsigned RegsSize=6; + static const unsigned IntRegs[] = { + MBlaze::R5, MBlaze::R6, MBlaze::R7, + MBlaze::R8, MBlaze::R9, MBlaze::R10 + }; + + static const unsigned FltRegs[] = { + MBlaze::F5, MBlaze::F6, MBlaze::F7, + MBlaze::F8, MBlaze::F9, MBlaze::F10 + }; + + unsigned Reg=0; + + // Promote i8 and i16 + if (LocVT == MVT::i8 || LocVT == MVT::i16) { + LocVT = MVT::i32; + if (ArgFlags.isSExt()) + LocInfo = CCValAssign::SExt; + else if (ArgFlags.isZExt()) + LocInfo = CCValAssign::ZExt; + else + LocInfo = CCValAssign::AExt; + } + + if (ValVT == MVT::i32) { + Reg = State.AllocateReg(IntRegs, RegsSize); + LocVT = MVT::i32; + } else if (ValVT == MVT::f32) { + Reg = State.AllocateReg(FltRegs, RegsSize); + LocVT = MVT::f32; + } + + if (!Reg) { + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + unsigned Offset = State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo)); + } else { + unsigned SizeInBytes = ValVT.getSizeInBits() >> 3; + State.AllocateStack(SizeInBytes, SizeInBytes); + State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo)); + } + + return false; // CC must always match +} + +//===----------------------------------------------------------------------===// +// Call Calling Convention Implementation +//===----------------------------------------------------------------------===// + +/// LowerCall - functions arguments are copied from virtual regs to +/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. +/// TODO: isVarArg, isTailCall. +SDValue MBlazeTargetLowering:: +LowerCall(SDValue Chain, SDValue Callee, CallingConv::ID CallConv, + bool isVarArg, bool &isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + // MBlaze does not yet support tail call optimization + isTailCall = false; + + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + + // Analyze operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, + *DAG.getContext()); + CCInfo.AnalyzeCallOperands(Outs, CC_MBlaze2); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = CCInfo.getNextStackOffset(); + Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); + + SmallVector, 8> RegsToPass; + SmallVector MemOpChains; + + // First/LastArgStackLoc contains the first/last + // "at stack" argument location. + int LastArgStackLoc = 0; + unsigned FirstStackArgLoc = 0; + + // Walk the register/memloc assignments, inserting copies/loads. + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + EVT RegVT = VA.getLocVT(); + SDValue Arg = Outs[i].Val; + + // Promote the value if needed. + switch (VA.getLocInfo()) { + default: llvm_unreachable("Unknown loc info!"); + case CCValAssign::Full: break; + case CCValAssign::SExt: + Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, RegVT, Arg); + break; + case CCValAssign::ZExt: + Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, RegVT, Arg); + break; + case CCValAssign::AExt: + Arg = DAG.getNode(ISD::ANY_EXTEND, dl, RegVT, Arg); + break; + } + + // Arguments that can be passed on register must be kept at + // RegsToPass vector + if (VA.isRegLoc()) { + RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + } else { + // Register can't get to this point... + assert(VA.isMemLoc()); + + // Create the frame index object for this incoming parameter + LastArgStackLoc = (FirstStackArgLoc + VA.getLocMemOffset()); + int FI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, + LastArgStackLoc, true, false); + + SDValue PtrOff = DAG.getFrameIndex(FI,getPointerTy()); + + // emit ISD::STORE whichs stores the + // parameter value to a stack Location + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + false, false, 0)); + } + } + + // Transform all store nodes into one single node because all store + // nodes are independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &MemOpChains[0], MemOpChains.size()); + + // Build a sequence of copy-to-reg nodes chained together with token + // chain and flag operands which copy the outgoing args into registers. + // The InFlag in necessary since all emited instructions must be + // stuck together. + SDValue InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, + RegsToPass[i].second, InFlag); + InFlag = Chain.getValue(1); + } + + // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every + // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol + // node so that legalize doesn't hack it. + unsigned char OpFlag = MBlazeII::MO_NO_FLAG; + if (GlobalAddressSDNode *G = dyn_cast(Callee)) + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), + getPointerTy(), 0, OpFlag); + else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), + getPointerTy(), OpFlag); + + // MBlazeJmpLink = #chain, #target_address, #opt_in_flags... + // = Chain, Callee, Reg#1, Reg#2, ... + // + // Returns a chain & a flag for retval copy to use. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are + // known live into the call. + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Ops.push_back(DAG.getRegister(RegsToPass[i].first, + RegsToPass[i].second.getValueType())); + } + + if (InFlag.getNode()) + Ops.push_back(InFlag); + + Chain = DAG.getNode(MBlazeISD::JmpLink, dl, NodeTys, &Ops[0], Ops.size()); + InFlag = Chain.getValue(1); + + // Create the CALLSEQ_END node. + Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), + DAG.getIntPtrConstant(0, true), InFlag); + if (!Ins.empty()) + InFlag = Chain.getValue(1); + + // Handle result values, copying them out of physregs into vregs that we + // return. + return LowerCallResult(Chain, InFlag, CallConv, isVarArg, + Ins, dl, DAG, InVals); +} + +/// LowerCallResult - Lower the result values of a call into the +/// appropriate copies out of appropriate physical registers. +SDValue MBlazeTargetLowering:: +LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, + bool isVarArg, const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + // Assign locations to each value returned by this call. + SmallVector RVLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + + CCInfo.AnalyzeCallResult(Ins, RetCC_MBlaze); + + // Copy all of the result registers out of their specified physreg. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + Chain = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(), + RVLocs[i].getValVT(), InFlag).getValue(1); + InFlag = Chain.getValue(2); + InVals.push_back(Chain.getValue(0)); + } + + return Chain; +} + +//===----------------------------------------------------------------------===// +// Formal Arguments Calling Convention Implementation +//===----------------------------------------------------------------------===// + +/// LowerFormalArguments - transform physical registers into +/// virtual registers and generate load operations for +/// arguments places on the stack. +SDValue MBlazeTargetLowering:: +LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) { + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo(); + + unsigned StackReg = MF.getTarget().getRegisterInfo()->getFrameRegister(MF); + VarArgsFrameIndex = 0; + + // Used with vargs to acumulate store chains. + std::vector OutChains; + + // Keep track of the last register used for arguments + unsigned ArgRegEnd = 0; + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + ArgLocs, *DAG.getContext()); + + CCInfo.AnalyzeFormalArguments(Ins, CC_MBlaze2); + SDValue StackPtr; + + unsigned FirstStackArgLoc = 0; + + for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { + CCValAssign &VA = ArgLocs[i]; + + // Arguments stored on registers + if (VA.isRegLoc()) { + EVT RegVT = VA.getLocVT(); + ArgRegEnd = VA.getLocReg(); + TargetRegisterClass *RC = 0; + + if (RegVT == MVT::i32) + RC = MBlaze::CPURegsRegisterClass; + else if (RegVT == MVT::f32) + RC = MBlaze::FGR32RegisterClass; + else + llvm_unreachable("RegVT not supported by LowerFormalArguments"); + + // Transform the arguments stored on + // physical registers into virtual ones + unsigned Reg = MF.addLiveIn(ArgRegEnd, RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT); + + // If this is an 8 or 16-bit value, it has been passed promoted + // to 32 bits. Insert an assert[sz]ext to capture this, then + // truncate to the right size. If if is a floating point value + // then convert to the correct type. + if (VA.getLocInfo() != CCValAssign::Full) { + unsigned Opcode = 0; + if (VA.getLocInfo() == CCValAssign::SExt) + Opcode = ISD::AssertSext; + else if (VA.getLocInfo() == CCValAssign::ZExt) + Opcode = ISD::AssertZext; + if (Opcode) + ArgValue = DAG.getNode(Opcode, dl, RegVT, ArgValue, + DAG.getValueType(VA.getValVT())); + ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); + } + + InVals.push_back(ArgValue); + + } else { // VA.isRegLoc() + + // sanity check + assert(VA.isMemLoc()); + + // The last argument is not a register + ArgRegEnd = 0; + + // The stack pointer offset is relative to the caller stack frame. + // Since the real stack size is unknown here, a negative SPOffset + // is used so there's a way to adjust these offsets when the stack + // size get known (on EliminateFrameIndex). A dummy SPOffset is + // used instead of a direct negative address (which is recorded to + // be used on emitPrologue) to avoid mis-calc of the first stack + // offset on PEI::calculateFrameObjectOffsets. + // Arguments are always 32-bit. + unsigned ArgSize = VA.getLocVT().getSizeInBits()/8; + int FI = MFI->CreateFixedObject(ArgSize, 0, true, false); + MBlazeFI->recordLoadArgsFI(FI, -(ArgSize+ + (FirstStackArgLoc + VA.getLocMemOffset()))); + + // Create load nodes to retrieve arguments from the stack + SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0, + false, false, 0)); + } + } + + // To meet ABI, when VARARGS are passed on registers, the registers + // must have their values written to the caller stack frame. If the last + // argument was placed in the stack, there's no need to save any register. + if ((isVarArg) && ArgRegEnd) { + if (StackPtr.getNode() == 0) + StackPtr = DAG.getRegister(StackReg, getPointerTy()); + + // The last register argument that must be saved is MBlaze::R10 + TargetRegisterClass *RC = MBlaze::CPURegsRegisterClass; + + unsigned Begin = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R5); + unsigned Start = MBlazeRegisterInfo::getRegisterNumbering(ArgRegEnd+1); + unsigned End = MBlazeRegisterInfo::getRegisterNumbering(MBlaze::R10); + unsigned StackLoc = ArgLocs.size()-1 + (Start - Begin); + + for (; Start <= End; ++Start, ++StackLoc) { + unsigned Reg = MBlazeRegisterInfo::getRegisterFromNumbering(Start); + unsigned LiveReg = MF.addLiveIn(Reg, RC); + SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, LiveReg, MVT::i32); + + int FI = MFI->CreateFixedObject(4, 0, true, false); + MBlazeFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4))); + SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); + OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0, + false, false, 0)); + + // Record the frame index of the first variable argument + // which is a value necessary to VASTART. + if (!VarArgsFrameIndex) + VarArgsFrameIndex = FI; + } + } + + // All stores are grouped in one node to allow the matching between + // the size of Ins and InVals. This only happens when on varg functions + if (!OutChains.empty()) { + OutChains.push_back(Chain); + Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + &OutChains[0], OutChains.size()); + } + + return Chain; +} + +//===----------------------------------------------------------------------===// +// Return Value Calling Convention Implementation +//===----------------------------------------------------------------------===// + +SDValue MBlazeTargetLowering:: +LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG) { + // CCValAssign - represent the assignment of + // the return value to a location + SmallVector RVLocs; + + // CCState - Info about the registers and stack slot. + CCState CCInfo(CallConv, isVarArg, getTargetMachine(), + RVLocs, *DAG.getContext()); + + // Analize return values. + CCInfo.AnalyzeReturn(Outs, RetCC_MBlaze); + + // If this is the first return lowered for this function, add + // the regs to the liveout set for the function. + if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { + for (unsigned i = 0; i != RVLocs.size(); ++i) + if (RVLocs[i].isRegLoc()) + DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); + } + + SDValue Flag; + + // Copy the result values into the output registers. + for (unsigned i = 0; i != RVLocs.size(); ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), + Outs[i].Val, Flag); + + // guarantee that all emitted copies are + // stuck together, avoiding something bad + Flag = Chain.getValue(1); + } + + // Return on MBlaze is always a "rtsd R15, 8" + if (Flag.getNode()) + return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other, + Chain, DAG.getRegister(MBlaze::R15, MVT::i32), Flag); + else // Return Void + return DAG.getNode(MBlazeISD::Ret, dl, MVT::Other, + Chain, DAG.getRegister(MBlaze::R15, MVT::i32)); +} + +//===----------------------------------------------------------------------===// +// MBlaze Inline Assembly Support +//===----------------------------------------------------------------------===// + +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target. +MBlazeTargetLowering::ConstraintType MBlazeTargetLowering:: +getConstraintType(const std::string &Constraint) const +{ + // MBlaze specific constrainy + // + // 'd' : An address register. Equivalent to r. + // 'y' : Equivalent to r; retained for + // backwards compatibility. + // 'f' : Floating Point registers. + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default : break; + case 'd': + case 'y': + case 'f': + return C_RegisterClass; + break; + } + } + return TargetLowering::getConstraintType(Constraint); +} + +/// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), +/// return a list of registers that can be used to satisfy the constraint. +/// This should only be used for C_RegisterClass constraints. +std::pair MBlazeTargetLowering:: +getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + case 'r': + return std::make_pair(0U, MBlaze::CPURegsRegisterClass); + case 'f': + if (VT == MVT::f32) + return std::make_pair(0U, MBlaze::FGR32RegisterClass); + } + } + return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); +} + +/// Given a register class constraint, like 'r', if this corresponds directly +/// to an LLVM register class, return a register of 0 and the register class +/// pointer. +std::vector MBlazeTargetLowering:: +getRegClassForInlineAsmConstraint(const std::string &Constraint, EVT VT) const { + if (Constraint.size() != 1) + return std::vector(); + + switch (Constraint[0]) { + default : break; + case 'r': + // GCC MBlaze Constraint Letters + case 'd': + case 'y': + return make_vector( + MBlaze::R3, MBlaze::R4, MBlaze::R5, MBlaze::R6, + MBlaze::R7, MBlaze::R9, MBlaze::R10, MBlaze::R11, + MBlaze::R12, MBlaze::R19, MBlaze::R20, MBlaze::R21, + MBlaze::R22, MBlaze::R23, MBlaze::R24, MBlaze::R25, + MBlaze::R26, MBlaze::R27, MBlaze::R28, MBlaze::R29, + MBlaze::R30, MBlaze::R31, 0); + + case 'f': + return make_vector( + MBlaze::F3, MBlaze::F4, MBlaze::F5, MBlaze::F6, + MBlaze::F7, MBlaze::F9, MBlaze::F10, MBlaze::F11, + MBlaze::F12, MBlaze::F19, MBlaze::F20, MBlaze::F21, + MBlaze::F22, MBlaze::F23, MBlaze::F24, MBlaze::F25, + MBlaze::F26, MBlaze::F27, MBlaze::F28, MBlaze::F29, + MBlaze::F30, MBlaze::F31, 0); + } + return std::vector(); +} + +bool MBlazeTargetLowering:: +isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { + // The MBlaze target isn't yet aware of offsets. + return false; +} + +bool MBlazeTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { + return VT != MVT::f32; +} diff --git a/lib/Target/MBlaze/MBlazeISelLowering.h b/lib/Target/MBlaze/MBlazeISelLowering.h new file mode 100644 index 0000000000..f8b147024d --- /dev/null +++ b/lib/Target/MBlaze/MBlazeISelLowering.h @@ -0,0 +1,149 @@ +//===-- MBlazeISelLowering.h - MBlaze DAG Lowering 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 interfaces that MBlaze uses to lower LLVM code into a +// selection DAG. +// +//===----------------------------------------------------------------------===// + +#ifndef MBlazeISELLOWERING_H +#define MBlazeISELLOWERING_H + +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/Target/TargetLowering.h" +#include "MBlaze.h" +#include "MBlazeSubtarget.h" + +namespace llvm { + namespace MBlazeCC { + enum CC { + FIRST = 0, + EQ, + NE, + GT, + LT, + GE, + LE + }; + } + + namespace MBlazeISD { + enum NodeType { + // Start the numbering from where ISD NodeType finishes. + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + // Jump and link (call) + JmpLink, + + // Handle gp_rel (small data/bss sections) relocation. + GPRel, + + // Select CC Pseudo Instruction + Select_CC, + + // Wrap up multiple types of instructions + Wrap, + + // Integer Compare + ICmp, + + // Return + Ret + }; + } + + //===--------------------------------------------------------------------===// + // TargetLowering Implementation + //===--------------------------------------------------------------------===// + + class MBlazeTargetLowering : public TargetLowering { + int VarArgsFrameIndex; // FrameIndex for start of varargs area. + + public: + + explicit MBlazeTargetLowering(MBlazeTargetMachine &TM); + + /// LowerOperation - Provide custom lowering hooks for some operations. + virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); + + /// getTargetNodeName - This method returns the name of a target specific + // DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + /// getSetCCResultType - get the ISD::SETCC result ValueType + MVT::SimpleValueType getSetCCResultType(EVT VT) const; + + virtual unsigned getFunctionAlignment(const Function *F) const; + private: + // Subtarget Info + const MBlazeSubtarget *Subtarget; + + + // Lower Operand helpers + SDValue LowerCallResult(SDValue Chain, SDValue InFlag, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + // Lower Operand specifics + SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); + SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG); + SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); + SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG); + + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals); + + virtual SDValue + LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl &Outs, + DebugLoc dl, SelectionDAG &DAG); + + virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *MBB, + DenseMap *EM) const; + + // Inline asm support + ConstraintType getConstraintType(const std::string &Constraint) const; + + std::pair + getRegForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + std::vector + getRegClassForInlineAsmConstraint(const std::string &Constraint, + EVT VT) const; + + virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; + + /// isFPImmLegal - Returns true if the target can instruction select the + /// specified FP immediate natively. If false, the legalizer will + /// materialize the FP immediate as a load from a constant pool. + virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const; + }; +} + +#endif // MBlazeISELLOWERING_H diff --git a/lib/Target/MBlaze/MBlazeInstrFPU.td b/lib/Target/MBlaze/MBlazeInstrFPU.td new file mode 100644 index 0000000000..a48a8c9723 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeInstrFPU.td @@ -0,0 +1,223 @@ +//===- MBlazeInstrFPU.td - MBlaze FPU Instruction defs ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MBlaze profiles and nodes +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MBlaze Operand, Complex Patterns and Transformations Definitions. +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Memory Access Instructions +//===----------------------------------------------------------------------===// +class LoadFM op, string instr_asm, PatFrag OpNode> : + TA; + +class LoadFMI op, string instr_asm, PatFrag OpNode> : + TAI; + +class StoreFM op, string instr_asm, PatFrag OpNode> : + TA; + +class StoreFMI op, string instr_asm, PatFrag OpNode> : + TAI; + +class ArithF op, bits<11> flags, string instr_asm, SDNode OpNode, + InstrItinClass itin> : + TA; + +class CmpFN op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA; + +class ArithFR op, bits<11> flags, string instr_asm, SDNode OpNode, + InstrItinClass itin> : + TA; + +class ArithF2 op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TF; + +class ArithIF op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TF; + +class ArithFI op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TF; + +class LogicF op, string instr_asm> : + TAI; + +class LogicFI op, string instr_asm> : + TAI; + +//===----------------------------------------------------------------------===// +// Pseudo instructions +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// FPU Arithmetic Instructions +//===----------------------------------------------------------------------===// +let Predicates=[HasFPU] in { + def FOR : LogicF<0x28, "or ">; + def FORI : LogicFI<0x28, "ori ">; + def FADD : ArithF<0x16, 0x000, "fadd ", fadd, IIAlu>; + def FRSUB : ArithFR<0x16, 0x080, "frsub ", fsub, IIAlu>; + def FMUL : ArithF<0x16, 0x100, "fmul ", fmul, IIAlu>; + def FDIV : ArithF<0x16, 0x180, "fdiv ", fdiv, IIAlu>; + + def LWF : LoadFM<0x32, "lw ", load>; + def LWFI : LoadFMI<0x32, "lwi ", load>; + + def SWF : StoreFM<0x32, "sw ", store>; + def SWFI : StoreFMI<0x32, "swi ", store>; +} + +let Predicates=[HasFPU,HasSqrt] in { + def FLT : ArithIF<0x16, 0x280, "flt ", IIAlu>; + def FINT : ArithFI<0x16, 0x300, "fint ", IIAlu>; + def FSQRT : ArithF2<0x16, 0x300, "fsqrt ", IIAlu>; +} + +let isAsCheapAsAMove = 1 in { + def FCMP_UN : CmpFN<0x16, 0x200, "fcmp.un", IIAlu>; + def FCMP_LT : CmpFN<0x16, 0x210, "fcmp.lt", IIAlu>; + def FCMP_EQ : CmpFN<0x16, 0x220, "fcmp.eq", IIAlu>; + def FCMP_LE : CmpFN<0x16, 0x230, "fcmp.le", IIAlu>; + def FCMP_GT : CmpFN<0x16, 0x240, "fcmp.gt", IIAlu>; + def FCMP_NE : CmpFN<0x16, 0x250, "fcmp.ne", IIAlu>; + def FCMP_GE : CmpFN<0x16, 0x260, "fcmp.ge", IIAlu>; +} + + +let usesCustomInserter = 1 in { + def Select_FCC : MBlazePseudo<(outs FGR32:$dst), + (ins FGR32:$T, FGR32:$F, CPURegs:$CMP, i32imm:$CC), + "; SELECT_FCC PSEUDO!", + []>; +} + +// Floating point conversions +let Predicates=[HasFPU] in { + def : Pat<(sint_to_fp CPURegs:$V), (FLT CPURegs:$V)>; + def : Pat<(fp_to_sint FGR32:$V), (FINT FGR32:$V)>; + def : Pat<(fsqrt FGR32:$V), (FSQRT FGR32:$V)>; +} + +// SET_CC operations +let Predicates=[HasFPU] in { + def : Pat<(setcc FGR32:$L, FGR32:$R, SETEQ), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_EQ FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETNE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_EQ FGR32:$L, FGR32:$R), 1)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETOEQ), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_EQ FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETONE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (XOR (FCMP_UN FGR32:$L, FGR32:$R), + (FCMP_EQ FGR32:$L, FGR32:$R)), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETONE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (OR (FCMP_UN FGR32:$L, FGR32:$R), + (FCMP_EQ FGR32:$L, FGR32:$R)), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETGT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_GT FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETLT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_LT FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETGE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_GE FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETLE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_LE FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETOGT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_GT FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETOLT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_LT FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETOGE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_GE FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETOLE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_LE FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETUEQ), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (OR (FCMP_UN FGR32:$L, FGR32:$R), + (FCMP_EQ FGR32:$L, FGR32:$R)), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETUNE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_NE FGR32:$L, FGR32:$R), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETUGT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (OR (FCMP_UN FGR32:$L, FGR32:$R), + (FCMP_GT FGR32:$L, FGR32:$R)), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETULT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (OR (FCMP_UN FGR32:$L, FGR32:$R), + (FCMP_LT FGR32:$L, FGR32:$R)), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETUGE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (OR (FCMP_UN FGR32:$L, FGR32:$R), + (FCMP_GE FGR32:$L, FGR32:$R)), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETULE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (OR (FCMP_UN FGR32:$L, FGR32:$R), + (FCMP_LE FGR32:$L, FGR32:$R)), 2)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETO), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_UN FGR32:$L, FGR32:$R), 1)>; + def : Pat<(setcc FGR32:$L, FGR32:$R, SETUO), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (FCMP_UN FGR32:$L, FGR32:$R), 2)>; +} + +// SELECT operations +def : Pat<(select CPURegs:$C, FGR32:$T, FGR32:$F), + (Select_FCC FGR32:$T, FGR32:$F, CPURegs:$C, 2)>; + +//===----------------------------------------------------------------------===// +// Patterns for Floating Point Instructions +//===----------------------------------------------------------------------===// +def : Pat<(f32 fpimm:$imm), (FORI F0, fpimm:$imm)>; diff --git a/lib/Target/MBlaze/MBlazeInstrFSL.td b/lib/Target/MBlaze/MBlazeInstrFSL.td new file mode 100644 index 0000000000..b59999e76a --- /dev/null +++ b/lib/Target/MBlaze/MBlazeInstrFSL.td @@ -0,0 +1,153 @@ +//===- MBlazeInstrFSL.td - MBlaze FSL Instruction defs ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// FSL Instruction Formats +//===----------------------------------------------------------------------===// +class FSLGetD op, bits<11> flags, string instr_asm, Intrinsic OpNode> : + TA; + +class FSLGet op, string instr_asm, Intrinsic OpNode> : + TAI; + +class FSLPutD op, bits<11> flags, string instr_asm, Intrinsic OpNode> : + TA; + +class FSLPut op, string instr_asm, Intrinsic OpNode> : + TAI; + +class FSLPutTD op, bits<11> flags, string instr_asm, Intrinsic OpNode> : + TA; + +class FSLPutT op, string instr_asm, Intrinsic OpNode> : + TAI; + +//===----------------------------------------------------------------------===// +// FSL Get Instructions +//===----------------------------------------------------------------------===// +def GET : FSLGet<0x1B, "get ", int_mblaze_fsl_get>; +def AGET : FSLGet<0x1B, "aget ", int_mblaze_fsl_aget>; +def CGET : FSLGet<0x1B, "cget ", int_mblaze_fsl_cget>; +def CAGET : FSLGet<0x1B, "caget ", int_mblaze_fsl_caget>; +def EGET : FSLGet<0x1B, "eget ", int_mblaze_fsl_eget>; +def EAGET : FSLGet<0x1B, "eaget ", int_mblaze_fsl_eaget>; +def ECGET : FSLGet<0x1B, "ecget ", int_mblaze_fsl_ecget>; +def ECAGET : FSLGet<0x1B, "ecaget ", int_mblaze_fsl_ecaget>; +def NGET : FSLGet<0x1B, "nget ", int_mblaze_fsl_nget>; +def NAGET : FSLGet<0x1B, "naget ", int_mblaze_fsl_naget>; +def NCGET : FSLGet<0x1B, "ncget ", int_mblaze_fsl_ncget>; +def NCAGET : FSLGet<0x1B, "ncaget ", int_mblaze_fsl_ncaget>; +def NEGET : FSLGet<0x1B, "neget ", int_mblaze_fsl_neget>; +def NEAGET : FSLGet<0x1B, "neaget ", int_mblaze_fsl_neaget>; +def NECGET : FSLGet<0x1B, "necget ", int_mblaze_fsl_necget>; +def NECAGET : FSLGet<0x1B, "necaget ", int_mblaze_fsl_necaget>; +def TGET : FSLGet<0x1B, "tget ", int_mblaze_fsl_tget>; +def TAGET : FSLGet<0x1B, "taget ", int_mblaze_fsl_taget>; +def TCGET : FSLGet<0x1B, "tcget ", int_mblaze_fsl_tcget>; +def TCAGET : FSLGet<0x1B, "tcaget ", int_mblaze_fsl_tcaget>; +def TEGET : FSLGet<0x1B, "teget ", int_mblaze_fsl_teget>; +def TEAGET : FSLGet<0x1B, "teaget ", int_mblaze_fsl_teaget>; +def TECGET : FSLGet<0x1B, "tecget ", int_mblaze_fsl_tecget>; +def TECAGET : FSLGet<0x1B, "tecaget ", int_mblaze_fsl_tecaget>; +def TNGET : FSLGet<0x1B, "tnget ", int_mblaze_fsl_tnget>; +def TNAGET : FSLGet<0x1B, "tnaget ", int_mblaze_fsl_tnaget>; +def TNCGET : FSLGet<0x1B, "tncget ", int_mblaze_fsl_tncget>; +def TNCAGET : FSLGet<0x1B, "tncaget ", int_mblaze_fsl_tncaget>; +def TNEGET : FSLGet<0x1B, "tneget ", int_mblaze_fsl_tneget>; +def TNEAGET : FSLGet<0x1B, "tneaget ", int_mblaze_fsl_tneaget>; +def TNECGET : FSLGet<0x1B, "tnecget ", int_mblaze_fsl_tnecget>; +def TNECAGET : FSLGet<0x1B, "tnecaget ", int_mblaze_fsl_tnecaget>; + +//===----------------------------------------------------------------------===// +// FSL Dynamic Get Instructions +//===----------------------------------------------------------------------===// +def GETD : FSLGetD<0x1B, 0x00, "getd ", int_mblaze_fsl_get>; +def AGETD : FSLGetD<0x1B, 0x00, "agetd ", int_mblaze_fsl_aget>; +def CGETD : FSLGetD<0x1B, 0x00, "cgetd ", int_mblaze_fsl_cget>; +def CAGETD : FSLGetD<0x1B, 0x00, "cagetd ", int_mblaze_fsl_caget>; +def EGETD : FSLGetD<0x1B, 0x00, "egetd ", int_mblaze_fsl_eget>; +def EAGETD : FSLGetD<0x1B, 0x00, "eagetd ", int_mblaze_fsl_eaget>; +def ECGETD : FSLGetD<0x1B, 0x00, "ecgetd ", int_mblaze_fsl_ecget>; +def ECAGETD : FSLGetD<0x1B, 0x00, "ecagetd ", int_mblaze_fsl_ecaget>; +def NGETD : FSLGetD<0x1B, 0x00, "ngetd ", int_mblaze_fsl_nget>; +def NAGETD : FSLGetD<0x1B, 0x00, "nagetd ", int_mblaze_fsl_naget>; +def NCGETD : FSLGetD<0x1B, 0x00, "ncgetd ", int_mblaze_fsl_ncget>; +def NCAGETD : FSLGetD<0x1B, 0x00, "ncagetd ", int_mblaze_fsl_ncaget>; +def NEGETD : FSLGetD<0x1B, 0x00, "negetd ", int_mblaze_fsl_neget>; +def NEAGETD : FSLGetD<0x1B, 0x00, "neagetd ", int_mblaze_fsl_neaget>; +def NECGETD : FSLGetD<0x1B, 0x00, "necgetd ", int_mblaze_fsl_necget>; +def NECAGETD : FSLGetD<0x1B, 0x00, "necagetd ", int_mblaze_fsl_necaget>; +def TGETD : FSLGetD<0x1B, 0x00, "tgetd ", int_mblaze_fsl_tget>; +def TAGETD : FSLGetD<0x1B, 0x00, "tagetd ", int_mblaze_fsl_taget>; +def TCGETD : FSLGetD<0x1B, 0x00, "tcgetd ", int_mblaze_fsl_tcget>; +def TCAGETD : FSLGetD<0x1B, 0x00, "tcagetd ", int_mblaze_fsl_tcaget>; +def TEGETD : FSLGetD<0x1B, 0x00, "tegetd ", int_mblaze_fsl_teget>; +def TEAGETD : FSLGetD<0x1B, 0x00, "teagetd ", int_mblaze_fsl_teaget>; +def TECGETD : FSLGetD<0x1B, 0x00, "tecgetd ", int_mblaze_fsl_tecget>; +def TECAGETD : FSLGetD<0x1B, 0x00, "tecagetd ", int_mblaze_fsl_tecaget>; +def TNGETD : FSLGetD<0x1B, 0x00, "tngetd ", int_mblaze_fsl_tnget>; +def TNAGETD : FSLGetD<0x1B, 0x00, "tnagetd ", int_mblaze_fsl_tnaget>; +def TNCGETD : FSLGetD<0x1B, 0x00, "tncgetd ", int_mblaze_fsl_tncget>; +def TNCAGETD : FSLGetD<0x1B, 0x00, "tncagetd ", int_mblaze_fsl_tncaget>; +def TNEGETD : FSLGetD<0x1B, 0x00, "tnegetd ", int_mblaze_fsl_tneget>; +def TNEAGETD : FSLGetD<0x1B, 0x00, "tneagetd ", int_mblaze_fsl_tneaget>; +def TNECGETD : FSLGetD<0x1B, 0x00, "tnecgetd ", int_mblaze_fsl_tnecget>; +def TNECAGETD : FSLGetD<0x1B, 0x00, "tnecagetd", int_mblaze_fsl_tnecaget>; + +//===----------------------------------------------------------------------===// +// FSL Put Instructions +//===----------------------------------------------------------------------===// +def PUT : FSLPut<0x1B, "put ", int_mblaze_fsl_put>; +def APUT : FSLPut<0x1B, "aput ", int_mblaze_fsl_aput>; +def CPUT : FSLPut<0x1B, "cput ", int_mblaze_fsl_cput>; +def CAPUT : FSLPut<0x1B, "caput ", int_mblaze_fsl_caput>; +def NPUT : FSLPut<0x1B, "nput ", int_mblaze_fsl_nput>; +def NAPUT : FSLPut<0x1B, "naput ", int_mblaze_fsl_naput>; +def NCPUT : FSLPut<0x1B, "ncput ", int_mblaze_fsl_ncput>; +def NCAPUT : FSLPut<0x1B, "ncaput ", int_mblaze_fsl_ncaput>; +def TPUT : FSLPutT<0x1B, "tput ", int_mblaze_fsl_tput>; +def TAPUT : FSLPutT<0x1B, "taput ", int_mblaze_fsl_taput>; +def TCPUT : FSLPutT<0x1B, "tcput ", int_mblaze_fsl_tcput>; +def TCAPUT : FSLPutT<0x1B, "tcaput ", int_mblaze_fsl_tcaput>; +def TNPUT : FSLPutT<0x1B, "tnput ", int_mblaze_fsl_tnput>; +def TNAPUT : FSLPutT<0x1B, "tnaput ", int_mblaze_fsl_tnaput>; +def TNCPUT : FSLPutT<0x1B, "tncput ", int_mblaze_fsl_tncput>; +def TNCAPUT : FSLPutT<0x1B, "tncaput ", int_mblaze_fsl_tncaput>; + +//===----------------------------------------------------------------------===// +// FSL Dynamic Put Instructions +//===----------------------------------------------------------------------===// +def PUTD : FSLPutD<0x1B, 0x00, "putd ", int_mblaze_fsl_put>; +def APUTD : FSLPutD<0x1B, 0x00, "aputd ", int_mblaze_fsl_aput>; +def CPUTD : FSLPutD<0x1B, 0x00, "cputd ", int_mblaze_fsl_cput>; +def CAPUTD : FSLPutD<0x1B, 0x00, "caputd ", int_mblaze_fsl_caput>; +def NPUTD : FSLPutD<0x1B, 0x00, "nputd ", int_mblaze_fsl_nput>; +def NAPUTD : FSLPutD<0x1B, 0x00, "naputd ", int_mblaze_fsl_naput>; +def NCPUTD : FSLPutD<0x1B, 0x00, "ncputd ", int_mblaze_fsl_ncput>; +def NCAPUTD : FSLPutD<0x1B, 0x00, "ncaputd ", int_mblaze_fsl_ncaput>; +def TPUTD : FSLPutTD<0x1B, 0x00, "tputd ", int_mblaze_fsl_tput>; +def TAPUTD : FSLPutTD<0x1B, 0x00, "taputd ", int_mblaze_fsl_taput>; +def TCPUTD : FSLPutTD<0x1B, 0x00, "tcputd ", int_mblaze_fsl_tcput>; +def TCAPUTD : FSLPutTD<0x1B, 0x00, "tcaputd ", int_mblaze_fsl_tcaput>; +def TNPUTD : FSLPutTD<0x1B, 0x00, "tnputd ", int_mblaze_fsl_tnput>; +def TNAPUTD : FSLPutTD<0x1B, 0x00, "tnaputd ", int_mblaze_fsl_tnaput>; +def TNCPUTD : FSLPutTD<0x1B, 0x00, "tncputd ", int_mblaze_fsl_tncput>; +def TNCAPUTD : FSLPutTD<0x1B, 0x00, "tncaputd ", int_mblaze_fsl_tncaput>; diff --git a/lib/Target/MBlaze/MBlazeInstrFormats.td b/lib/Target/MBlaze/MBlazeInstrFormats.td new file mode 100644 index 0000000000..7d655433d4 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeInstrFormats.td @@ -0,0 +1,246 @@ +//===- MBlazeInstrFormats.td - MB Instruction defs --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Describe MBlaze instructions format +// +// CPU INSTRUCTION FORMATS +// +// opcode - operation code. +// rd - dst reg. +// ra - first src. reg. +// rb - second src. reg. +// imm16 - 16-bit immediate value. +// +//===----------------------------------------------------------------------===// + +// Generic MBlaze Format +class MBlazeInst pattern, + InstrItinClass itin> : Instruction +{ + field bits<32> Inst; + + let Namespace = "MBlaze"; + + bits<6> opcode; + + // Top 6 bits are the 'opcode' field + let Inst{0-5} = opcode; + + dag OutOperandList = outs; + dag InOperandList = ins; + + let AsmString = asmstr; + let Pattern = pattern; + let Itinerary = itin; +} + +//===----------------------------------------------------------------------===// +// Pseudo instruction class +//===----------------------------------------------------------------------===// +class MBlazePseudo pattern>: + MBlazeInst; + +//===----------------------------------------------------------------------===// +// Type A instruction class in MBlaze : <|opcode|rd|ra|rb|flags|> +//===----------------------------------------------------------------------===// + +class TA op, bits<11> flags, dag outs, dag ins, string asmstr, + list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> rd; + bits<5> ra; + bits<5> rb; + + let opcode = op; + + let Inst{6-10} = rd; + let Inst{11-15} = ra; + let Inst{16-20} = rb; + let Inst{21-31} = flags; +} + +class TAI op, dag outs, dag ins, string asmstr, + list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> rd; + bits<5> ra; + bits<16> imm16; + + let opcode = op; + + let Inst{6-10} = rd; + let Inst{11-15} = ra; + let Inst{16-31} = imm16; +} + +class TIMM op, dag outs, dag ins, string asmstr, + list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> ra; + bits<16> imm16; + + let opcode = op; + + let Inst{6-15} = 0; + let Inst{16-31} = imm16; +} + +class TADDR op, dag outs, dag ins, string asmstr, + list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<26> addr; + + let opcode = op; + + let Inst{6-31} = addr; +} + +//===----------------------------------------------------------------------===// +// Type B instruction class in MBlaze : <|opcode|rd|ra|immediate|> +//===----------------------------------------------------------------------===// + +class TB op, dag outs, dag ins, string asmstr, list pattern, + InstrItinClass itin> : + MBlazeInst +{ + bits<5> rd; + bits<5> ra; + bits<16> imm16; + + let opcode = op; + + let Inst{6-10} = rd; + let Inst{11-15} = ra; + let Inst{16-31} = imm16; +} + +//===----------------------------------------------------------------------===// +// Float instruction class in MBlaze : <|opcode|rd|ra|flags|> +//===----------------------------------------------------------------------===// + +class TF op, bits<11> flags, dag outs, dag ins, string asmstr, + list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> rd; + bits<5> ra; + + let opcode = op; + + let Inst{6-10} = rd; + let Inst{11-15} = ra; + let Inst{16-20} = 0; + let Inst{21-31} = flags; +} + +//===----------------------------------------------------------------------===// +// Branch instruction class in MBlaze : <|opcode|rd|br|ra|flags|> +//===----------------------------------------------------------------------===// + +class TBR op, bits<5> br, bits<11> flags, dag outs, dag ins, + string asmstr, list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> ra; + + let opcode = op; + + let Inst{6-10} = 0; + let Inst{11-15} = br; + let Inst{16-20} = ra; + let Inst{21-31} = flags; +} + +class TBRC op, bits<5> br, bits<11> flags, dag outs, dag ins, + string asmstr, list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> ra; + bits<5> rb; + + let opcode = op; + + let Inst{6-10} = br; + let Inst{11-15} = ra; + let Inst{16-20} = rb; + let Inst{21-31} = flags; +} + +class TBRL op, bits<5> br, bits<11> flags, dag outs, dag ins, + string asmstr, list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> ra; + + let opcode = op; + + let Inst{6-10} = 0xF; + let Inst{11-15} = br; + let Inst{16-20} = ra; + let Inst{21-31} = flags; +} + +class TBRI op, bits<5> br, dag outs, dag ins, + string asmstr, list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<16> imm16; + + let opcode = op; + + let Inst{6-10} = 0; + let Inst{11-15} = br; + let Inst{16-31} = imm16; +} + +class TBRLI op, bits<5> br, dag outs, dag ins, + string asmstr, list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<16> imm16; + + let opcode = op; + + let Inst{6-10} = 0xF; + let Inst{11-15} = br; + let Inst{16-31} = imm16; +} + +class TBRCI op, bits<5> br, dag outs, dag ins, + string asmstr, list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> ra; + bits<16> imm16; + + let opcode = op; + + let Inst{6-10} = br; + let Inst{11-15} = ra; + let Inst{16-31} = imm16; +} + +class TRET op, dag outs, dag ins, + string asmstr, list pattern, InstrItinClass itin> : + MBlazeInst +{ + bits<5> ra; + bits<16> imm16; + + let opcode = op; + + let Inst{6-10} = 0x10; + let Inst{11-15} = ra; + let Inst{16-31} = imm16; +} diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.cpp b/lib/Target/MBlaze/MBlazeInstrInfo.cpp new file mode 100644 index 0000000000..a7e8eb7d55 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeInstrInfo.cpp @@ -0,0 +1,222 @@ +//===- MBlazeInstrInfo.cpp - MBlaze Instruction Information -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the MBlaze implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeInstrInfo.h" +#include "MBlazeTargetMachine.h" +#include "MBlazeMachineFunction.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "MBlazeGenInstrInfo.inc" + +using namespace llvm; + +MBlazeInstrInfo::MBlazeInstrInfo(MBlazeTargetMachine &tm) + : TargetInstrInfoImpl(MBlazeInsts, array_lengthof(MBlazeInsts)), + TM(tm), RI(*TM.getSubtargetImpl(), *this) {} + +static bool isZeroImm(const MachineOperand &op) { + return op.isImm() && op.getImm() == 0; +} + +/// Return true if the instruction is a register to register move and +/// leave the source and dest operands in the passed parameters. +bool MBlazeInstrInfo:: +isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DstReg, + unsigned &SrcSubIdx, unsigned &DstSubIdx) const { + SrcSubIdx = DstSubIdx = 0; // No sub-registers. + + // add $dst, $src, $zero || addu $dst, $zero, $src + // or $dst, $src, $zero || or $dst, $zero, $src + if ((MI.getOpcode() == MBlaze::ADD) || (MI.getOpcode() == MBlaze::OR)) { + if (MI.getOperand(1).isReg() && MI.getOperand(1).getReg() == MBlaze::R0) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(2).getReg(); + return true; + } else if (MI.getOperand(2).isReg() && + MI.getOperand(2).getReg() == MBlaze::R0) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + return true; + } + } + + // addi $dst, $src, 0 + // ori $dst, $src, 0 + if ((MI.getOpcode() == MBlaze::ADDI) || (MI.getOpcode() == MBlaze::ORI)) { + if ((MI.getOperand(1).isReg()) && (isZeroImm(MI.getOperand(2)))) { + DstReg = MI.getOperand(0).getReg(); + SrcReg = MI.getOperand(1).getReg(); + return true; + } + } + + return false; +} + +/// isLoadFromStackSlot - If the specified machine instruction is a direct +/// load from a stack slot, return the virtual or physical register number of +/// the destination along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than loading from the stack slot. +unsigned MBlazeInstrInfo:: +isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const { + if (MI->getOpcode() == MBlaze::LWI) { + if ((MI->getOperand(2).isFI()) && // is a stack slot + (MI->getOperand(1).isImm()) && // the imm is zero + (isZeroImm(MI->getOperand(1)))) { + FrameIndex = MI->getOperand(2).getIndex(); + return MI->getOperand(0).getReg(); + } + } + + return 0; +} + +/// isStoreToStackSlot - If the specified machine instruction is a direct +/// store to a stack slot, return the virtual or physical register number of +/// the source reg along with the FrameIndex of the loaded stack slot. If +/// not, return 0. This predicate must return 0 if the instruction has +/// any side effects other than storing to the stack slot. +unsigned MBlazeInstrInfo:: +isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const { + if (MI->getOpcode() == MBlaze::SWI) { + if ((MI->getOperand(2).isFI()) && // is a stack slot + (MI->getOperand(1).isImm()) && // the imm is zero + (isZeroImm(MI->getOperand(1)))) { + FrameIndex = MI->getOperand(2).getIndex(); + return MI->getOperand(0).getReg(); + } + } + return 0; +} + +/// insertNoop - If data hazard condition is found insert the target nop +/// instruction. +void MBlazeInstrInfo:: +insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { + DebugLoc DL = DebugLoc::getUnknownLoc(); + if (MI != MBB.end()) DL = MI->getDebugLoc(); + BuildMI(MBB, MI, DL, get(MBlaze::NOP)); +} + +bool MBlazeInstrInfo:: +copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const { + DebugLoc dl = DebugLoc::getUnknownLoc(); + llvm::BuildMI(MBB, I, dl, get(MBlaze::ADD), DestReg) + .addReg(SrcReg).addReg(MBlaze::R0); + return true; +} + +void MBlazeInstrInfo:: +storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned SrcReg, bool isKill, int FI, + const TargetRegisterClass *RC) const { + DebugLoc dl = DebugLoc::getUnknownLoc(); + BuildMI(MBB, I, dl, get(MBlaze::SWI)).addReg(SrcReg,getKillRegState(isKill)) + .addImm(0).addFrameIndex(FI); +} + +void MBlazeInstrInfo:: +loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + unsigned DestReg, int FI, + const TargetRegisterClass *RC) const { + DebugLoc dl = DebugLoc::getUnknownLoc(); + BuildMI(MBB, I, dl, get(MBlaze::LWI), DestReg) + .addImm(0).addFrameIndex(FI); +} + +MachineInstr *MBlazeInstrInfo:: +foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, int FI) const { + if (Ops.size() != 1) return NULL; + + MachineInstr *NewMI = NULL; + + switch (MI->getOpcode()) { + case MBlaze::OR: + case MBlaze::ADD: + if ((MI->getOperand(0).isReg()) && + (MI->getOperand(2).isReg()) && + (MI->getOperand(2).getReg() == MBlaze::R0) && + (MI->getOperand(1).isReg())) { + if (Ops[0] == 0) { // COPY -> STORE + unsigned SrcReg = MI->getOperand(1).getReg(); + bool isKill = MI->getOperand(1).isKill(); + bool isUndef = MI->getOperand(1).isUndef(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(MBlaze::SW)) + .addReg(SrcReg, getKillRegState(isKill) | getUndefRegState(isUndef)) + .addImm(0).addFrameIndex(FI); + } else { // COPY -> LOAD + unsigned DstReg = MI->getOperand(0).getReg(); + bool isDead = MI->getOperand(0).isDead(); + bool isUndef = MI->getOperand(0).isUndef(); + NewMI = BuildMI(MF, MI->getDebugLoc(), get(MBlaze::LW)) + .addReg(DstReg, RegState::Define | getDeadRegState(isDead) | + getUndefRegState(isUndef)) + .addImm(0).addFrameIndex(FI); + } + } + break; + } + + return NewMI; +} + +//===----------------------------------------------------------------------===// +// Branch Analysis +//===----------------------------------------------------------------------===// +unsigned MBlazeInstrInfo:: +InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const { + DebugLoc dl = DebugLoc::getUnknownLoc(); + + // Can only insert uncond branches so far. + assert(Cond.empty() && !FBB && TBB && "Can only handle uncond branches!"); + BuildMI(&MBB, dl, get(MBlaze::BRI)).addMBB(TBB); + return 1; +} + +/// getGlobalBaseReg - Return a virtual register initialized with the +/// the global base register value. Output instructions required to +/// initialize the register in the function entry block, if necessary. +/// +unsigned MBlazeInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { + MBlazeFunctionInfo *MBlazeFI = MF->getInfo(); + unsigned GlobalBaseReg = MBlazeFI->getGlobalBaseReg(); + if (GlobalBaseReg != 0) + return GlobalBaseReg; + + // Insert the set of GlobalBaseReg into the first MBB of the function + MachineBasicBlock &FirstMBB = MF->front(); + MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + MachineRegisterInfo &RegInfo = MF->getRegInfo(); + const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); + + GlobalBaseReg = RegInfo.createVirtualRegister(MBlaze::CPURegsRegisterClass); + bool Ok = TII->copyRegToReg(FirstMBB, MBBI, GlobalBaseReg, MBlaze::R20, + MBlaze::CPURegsRegisterClass, + MBlaze::CPURegsRegisterClass); + assert(Ok && "Couldn't assign to global base register!"); + Ok = Ok; // Silence warning when assertions are turned off. + RegInfo.addLiveIn(MBlaze::R20); + + MBlazeFI->setGlobalBaseReg(GlobalBaseReg); + return GlobalBaseReg; +} diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.h b/lib/Target/MBlaze/MBlazeInstrInfo.h new file mode 100644 index 0000000000..4f79f1caf9 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeInstrInfo.h @@ -0,0 +1,242 @@ +//===- MBlazeInstrInfo.h - MBlaze Instruction Information -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the MBlaze implementation of the TargetInstrInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZEINSTRUCTIONINFO_H +#define MBLAZEINSTRUCTIONINFO_H + +#include "MBlaze.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "MBlazeRegisterInfo.h" + +namespace llvm { + +namespace MBlaze { + + // MBlaze Branch Codes + enum FPBranchCode { + BRANCH_F, + BRANCH_T, + BRANCH_FL, + BRANCH_TL, + BRANCH_INVALID + }; + + // MBlaze Condition Codes + enum CondCode { + // To be used with float branch True + FCOND_F, + FCOND_UN, + FCOND_EQ, + FCOND_UEQ, + FCOND_OLT, + FCOND_ULT, + FCOND_OLE, + FCOND_ULE, + FCOND_SF, + FCOND_NGLE, + FCOND_SEQ, + FCOND_NGL, + FCOND_LT, + FCOND_NGE, + FCOND_LE, + FCOND_NGT, + + // To be used with float branch False + // This conditions have the same mnemonic as the + // above ones, but are used with a branch False; + FCOND_T, + FCOND_OR, + FCOND_NEQ, + FCOND_OGL, + FCOND_UGE, + FCOND_OGE, + FCOND_UGT, + FCOND_OGT, + FCOND_ST, + FCOND_GLE, + FCOND_SNE, + FCOND_GL, + FCOND_NLT, + FCOND_GE, + FCOND_NLE, + FCOND_GT, + + // Only integer conditions + COND_E, + COND_GZ, + COND_GEZ, + COND_LZ, + COND_LEZ, + COND_NE, + COND_INVALID + }; + + // Turn condition code into conditional branch opcode. + unsigned GetCondBranchFromCond(CondCode CC); + + /// GetOppositeBranchCondition - Return the inverse of the specified cond, + /// e.g. turning COND_E to COND_NE. + CondCode GetOppositeBranchCondition(MBlaze::CondCode CC); + + /// MBlazeCCToString - Map each FP condition code to its string + inline static const char *MBlazeFCCToString(MBlaze::CondCode CC) + { + switch (CC) { + default: llvm_unreachable("Unknown condition code"); + case FCOND_F: + case FCOND_T: return "f"; + case FCOND_UN: + case FCOND_OR: return "un"; + case FCOND_EQ: + case FCOND_NEQ: return "eq"; + case FCOND_UEQ: + case FCOND_OGL: return "ueq"; + case FCOND_OLT: + case FCOND_UGE: return "olt"; + case FCOND_ULT: + case FCOND_OGE: return "ult"; + case FCOND_OLE: + case FCOND_UGT: return "ole"; + case FCOND_ULE: + case FCOND_OGT: return "ule"; + case FCOND_SF: + case FCOND_ST: return "sf"; + case FCOND_NGLE: + case FCOND_GLE: return "ngle"; + case FCOND_SEQ: + case FCOND_SNE: return "seq"; + case FCOND_NGL: + case FCOND_GL: return "ngl"; + case FCOND_LT: + case FCOND_NLT: return "lt"; + case FCOND_NGE: + case FCOND_GE: return "ge"; + case FCOND_LE: + case FCOND_NLE: return "nle"; + case FCOND_NGT: + case FCOND_GT: return "gt"; + } + } +} + +/// MBlazeII - This namespace holds all of the target specific flags that +/// instruction info tracks. +/// +namespace MBlazeII { + /// Target Operand Flag enum. + enum TOF { + //===------------------------------------------------------------------===// + // MBlaze Specific MachineOperand flags. + MO_NO_FLAG, + + /// MO_GOT - Represents the offset into the global offset table at which + /// the address the relocation entry symbol resides during execution. + MO_GOT, + + /// MO_GOT_CALL - Represents the offset into the global offset table at + /// which the address of a call site relocation entry symbol resides + /// during execution. This is different from the above since this flag + /// can only be present in call instructions. + MO_GOT_CALL, + + /// MO_GPREL - Represents the offset from the current gp value to be used + /// for the relocatable object file being produced. + MO_GPREL, + + /// MO_ABS_HILO - Represents the hi or low part of an absolute symbol + /// address. + MO_ABS_HILO + + }; +} + +class MBlazeInstrInfo : public TargetInstrInfoImpl { + MBlazeTargetMachine &TM; + const MBlazeRegisterInfo RI; +public: + explicit MBlazeInstrInfo(MBlazeTargetMachine &TM); + + /// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As + /// such, whenever a client has an instance of instruction info, it should + /// always be able to get register info as well (through this method). + /// + virtual const MBlazeRegisterInfo &getRegisterInfo() const { return RI; } + + /// Return true if the instruction is a register to register move and return + /// the source and dest operands and their sub-register indices by reference. + virtual bool isMoveInstr(const MachineInstr &MI, + unsigned &SrcReg, unsigned &DstReg, + unsigned &SrcSubIdx, unsigned &DstSubIdx) const; + + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than loading from the stack slot. + virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// the source reg along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than storing to the stack slot. + virtual unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const; + + /// Branch Analysis + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl &Cond) const; + virtual bool copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *DestRC, + const TargetRegisterClass *SrcRC) const; + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC) const; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const; + + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + int FrameIndex) const; + + virtual MachineInstr* foldMemoryOperandImpl(MachineFunction &MF, + MachineInstr* MI, + const SmallVectorImpl &Ops, + MachineInstr* LoadMI) const { + return 0; + } + + /// Insert nop instruction when hazard condition is found + virtual void insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const; + + /// getGlobalBaseReg - Return a virtual register initialized with the + /// the global base register value. Output instructions required to + /// initialize the register in the function entry block, if necessary. + /// + unsigned getGlobalBaseReg(MachineFunction *MF) const; +}; + +} + +#endif diff --git a/lib/Target/MBlaze/MBlazeInstrInfo.td b/lib/Target/MBlaze/MBlazeInstrInfo.td new file mode 100644 index 0000000000..3c406dda05 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeInstrInfo.td @@ -0,0 +1,672 @@ +//===- MBlazeInstrInfo.td - MBlaze Instruction defs -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Instruction format superclass +//===----------------------------------------------------------------------===// +include "MBlazeInstrFormats.td" + +//===----------------------------------------------------------------------===// +// MBlaze profiles and nodes +//===----------------------------------------------------------------------===// +def SDT_MBlazeRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; +def SDT_MBlazeJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; + +// Call +def MBlazeJmpLink : SDNode<"MBlazeISD::JmpLink",SDT_MBlazeJmpLink, + [SDNPHasChain,SDNPOptInFlag,SDNPOutFlag]>; + +// Return +def MBlazeRet : SDNode<"MBlazeISD::Ret", SDT_MBlazeRet, + [SDNPHasChain, SDNPOptInFlag]>; + +// Hi and Lo nodes are used to handle global addresses. Used on +// MBlazeISelLowering to lower stuff like GlobalAddress, ExternalSymbol +// static model. +def MBWrapper : SDNode<"MBlazeISD::Wrap", SDTIntUnaryOp>; +def MBlazeGPRel : SDNode<"MBlazeISD::GPRel", SDTIntUnaryOp>; + +def SDT_MBCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; +def SDT_MBCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; + +// These are target-independent nodes, but have target-specific formats. +def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_MBCallSeqStart, + [SDNPHasChain, SDNPOutFlag]>; +def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MBCallSeqEnd, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + +def SDTMBlazeSelectCC : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>]>; + +//===----------------------------------------------------------------------===// +// MBlaze Instruction Predicate Definitions. +//===----------------------------------------------------------------------===// +def HasPipe3 : Predicate<"Subtarget.hasPipe3()">; +def HasBarrel : Predicate<"Subtarget.hasBarrel()">; +def NoBarrel : Predicate<"!Subtarget.hasBarrel()">; +def HasDiv : Predicate<"Subtarget.hasDiv()">; +def HasMul : Predicate<"Subtarget.hasMul()">; +def HasFSL : Predicate<"Subtarget.hasFSL()">; +def HasEFSL : Predicate<"Subtarget.hasEFSL()">; +def HasMSRSet : Predicate<"Subtarget.hasMSRSet()">; +def HasException : Predicate<"Subtarget.hasException()">; +def HasPatCmp : Predicate<"Subtarget.hasPatCmp()">; +def HasFPU : Predicate<"Subtarget.hasFPU()">; +def HasESR : Predicate<"Subtarget.hasESR()">; +def HasPVR : Predicate<"Subtarget.hasPVR()">; +def HasMul64 : Predicate<"Subtarget.hasMul64()">; +def HasSqrt : Predicate<"Subtarget.hasSqrt()">; +def HasMMU : Predicate<"Subtarget.hasMMU()">; + +//===----------------------------------------------------------------------===// +// MBlaze Operand, Complex Patterns and Transformations Definitions. +//===----------------------------------------------------------------------===// + +// Instruction operand types +def brtarget : Operand; +def calltarget : Operand; +def simm16 : Operand; +def uimm5 : Operand; +def fimm : Operand; + +// Unsigned Operand +def uimm16 : Operand { + let PrintMethod = "printUnsignedImm"; +} + +// FSL Operand +def fslimm : Operand { + let PrintMethod = "printFSLImm"; +} + +// Address operand +def memri : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops simm16, CPURegs); +} + +def memrr : Operand { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops CPURegs, CPURegs); +} + +// Transformation Function - get the lower 16 bits. +def LO16 : SDNodeXFormgetZExtValue() & 0xFFFF); +}]>; + +// Transformation Function - get the higher 16 bits. +def HI16 : SDNodeXFormgetZExtValue() >> 16); +}]>; + +// Node immediate fits as 16-bit sign extended on target immediate. +// e.g. addi, andi +def immSExt16 : PatLeaf<(imm), [{ + return (N->getZExtValue() >> 16) == 0; +}]>; + +// Node immediate fits as 16-bit zero extended on target immediate. +// The LO16 param means that only the lower 16 bits of the node +// immediate are caught. +// e.g. addiu, sltiu +def immZExt16 : PatLeaf<(imm), [{ + return (N->getZExtValue() >> 16) == 0; +}], LO16>; + +// FSL immediate field must fit in 4 bits. +def immZExt4 : PatLeaf<(imm), [{ + return N->getZExtValue() == ((N->getZExtValue()) & 0xf) ; +}]>; + +// shamt field must fit in 5 bits. +def immZExt5 : PatLeaf<(imm), [{ + return N->getZExtValue() == ((N->getZExtValue()) & 0x1f) ; +}]>; + +// MBlaze Address Mode! SDNode frameindex could possibily be a match +// since load and store instructions from stack used it. +def iaddr : ComplexPattern; +def xaddr : ComplexPattern; + +//===----------------------------------------------------------------------===// +// Pseudo instructions +//===----------------------------------------------------------------------===// + +// As stack alignment is always done with addiu, we need a 16-bit immediate +let Defs = [R1], Uses = [R1] in { +def ADJCALLSTACKDOWN : MBlazePseudo<(outs), (ins simm16:$amt), + "${:comment} ADJCALLSTACKDOWN $amt", + [(callseq_start timm:$amt)]>; +def ADJCALLSTACKUP : MBlazePseudo<(outs), + (ins uimm16:$amt1, simm16:$amt2), + "${:comment} ADJCALLSTACKUP $amt1", + [(callseq_end timm:$amt1, timm:$amt2)]>; +} + +// Some assembly macros need to avoid pseudoinstructions and assembler +// automatic reodering, we should reorder ourselves. +def MACRO : MBlazePseudo<(outs), (ins), ".set macro", []>; +def REORDER : MBlazePseudo<(outs), (ins), ".set reorder", []>; +def NOMACRO : MBlazePseudo<(outs), (ins), ".set nomacro", []>; +def NOREORDER : MBlazePseudo<(outs), (ins), ".set noreorder", []>; + +// When handling PIC code the assembler needs .cpload and .cprestore +// directives. If the real instructions corresponding these directives +// are used, we have the same behavior, but get also a bunch of warnings +// from the assembler. +def CPLOAD : MBlazePseudo<(outs), (ins CPURegs:$reg), ".cpload $reg", []>; +def CPRESTORE : MBlazePseudo<(outs), (ins uimm16:$l), ".cprestore $l\n", []>; + +//===----------------------------------------------------------------------===// +// Instructions specific format +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Arithmetic Instructions +//===----------------------------------------------------------------------===// +class Arith op, bits<11> flags, string instr_asm, SDNode OpNode, + InstrItinClass itin> : + TA; + +class ArithI op, string instr_asm, SDNode OpNode, + Operand Od, PatLeaf imm_type> : + TAI; + +class ArithR op, bits<11> flags, string instr_asm, SDNode OpNode, + InstrItinClass itin> : + TA; + +class ArithRI op, string instr_asm, SDNode OpNode, + Operand Od, PatLeaf imm_type> : + TAI; + +class ArithN op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA; + +class ArithNI op, string instr_asm,Operand Od, PatLeaf imm_type> : + TAI; + +class ArithRN op, bits<11> flags, string instr_asm, + InstrItinClass itin> : + TA; + +class ArithRNI op, string instr_asm,Operand Od, PatLeaf imm_type> : + TAI; + +//===----------------------------------------------------------------------===// +// Misc Arithmetic Instructions +//===----------------------------------------------------------------------===// + +class Logic op, bits<11> flags, string instr_asm, SDNode OpNode> : + TA; + +class LogicI op, string instr_asm, SDNode OpNode> : + TAI; + +class EffectiveAddress : + TAI<0x08, (outs CPURegs:$dst), (ins memri:$addr), + instr_asm, [(set CPURegs:$dst, iaddr:$addr)], IIAlu>; + +//===----------------------------------------------------------------------===// +// Memory Access Instructions +//===----------------------------------------------------------------------===// +class LoadM op, string instr_asm, PatFrag OpNode> : + TA; + +class LoadMI op, string instr_asm, PatFrag OpNode> : + TAI; + +class StoreM op, string instr_asm, PatFrag OpNode> : + TA; + +class StoreMI op, string instr_asm, PatFrag OpNode> : + TAI; + +//===----------------------------------------------------------------------===// +// Branch Instructions +//===----------------------------------------------------------------------===// +class Branch op, bits<5> br, bits<11> flags, string instr_asm> : + TBR; + +class BranchI op, bits<5> brf, string instr_asm> : + TBRI; + +//===----------------------------------------------------------------------===// +// Branch and Link Instructions +//===----------------------------------------------------------------------===// +class BranchL op, bits<5> br, bits<11> flags, string instr_asm> : + TBRL; + +class BranchLI op, bits<5> br, string instr_asm> : + TBRLI; + +//===----------------------------------------------------------------------===// +// Conditional Branch Instructions +//===----------------------------------------------------------------------===// +class BranchC op, bits<5> br, bits<11> flags, string instr_asm, + PatFrag cond_op> : + TBRC; + //(brcond (cond_op CPURegs:$a, CPURegs:$b), bb:$offset)], + //IIBranch>; + +class BranchCI op, bits<5> br, string instr_asm, PatFrag cond_op> : + TBRCI; + +//===----------------------------------------------------------------------===// +// MBlaze arithmetic instructions +//===----------------------------------------------------------------------===// + +let isCommutable = 1, isAsCheapAsAMove = 1 in { + def ADD : Arith<0x00, 0x000, "add ", add, IIAlu>; + def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; + def ADDK : Arith<0x04, 0x000, "addk ", addc, IIAlu>; + def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>; + def AND : Logic<0x21, 0x000, "and ", and>; + def OR : Logic<0x20, 0x000, "or ", or>; + def XOR : Logic<0x22, 0x000, "xor ", xor>; +} + +let isAsCheapAsAMove = 1 in { + def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>; + def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>; + def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>; + def RSUB : ArithR<0x01, 0x000, "rsub ", sub, IIAlu>; + def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; + def RSUBK : ArithR<0x05, 0x000, "rsubk ", subc, IIAlu>; + def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>; +} + +let isCommutable = 1, Predicates=[HasMul] in { + def MUL : Arith<0x10, 0x000, "mul ", mul, IIAlu>; +} + +let isCommutable = 1, Predicates=[HasMul,HasMul64] in { + def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIAlu>; + def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIAlu>; +} + +let Predicates=[HasMul,HasMul64] in { + def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIAlu>; +} + +let Predicates=[HasBarrel] in { + def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIAlu>; + def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIAlu>; + def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIAlu>; + def BSRLI : ArithI<0x11, "bsrli ", srl, uimm5, immZExt5>; + def BSRAI : ArithI<0x11, "bsrai ", sra, uimm5, immZExt5>; + def BSLLI : ArithI<0x11, "bslli ", shl, uimm5, immZExt5>; +} + +let Predicates=[HasDiv] in { + def IDIV : Arith<0x12, 0x000, "idiv ", sdiv, IIAlu>; + def IDIVU : Arith<0x12, 0x002, "idivu ", udiv, IIAlu>; +} + +//===----------------------------------------------------------------------===// +// MBlaze immediate mode arithmetic instructions +//===----------------------------------------------------------------------===// + +let isAsCheapAsAMove = 1 in { + def ADDI : ArithI<0x08, "addi ", add, simm16, immSExt16>; + def ADDIC : ArithNI<0x0A, "addic ", simm16, immSExt16>; + def ADDIK : ArithNI<0x0C, "addik ", simm16, immSExt16>; + def ADDIKC : ArithI<0x0E, "addikc ", addc, simm16, immSExt16>; + def RSUBI : ArithRI<0x09, "rsubi ", sub, simm16, immSExt16>; + def RSUBIC : ArithRNI<0x0B, "rsubi ", simm16, immSExt16>; + def RSUBIK : ArithRNI<0x0E, "rsubic ", simm16, immSExt16>; + def RSUBIKC : ArithRI<0x0F, "rsubikc", subc, simm16, immSExt16>; + def ANDNI : ArithNI<0x2B, "andni ", uimm16, immZExt16>; + def ANDI : LogicI<0x29, "andi ", and>; + def ORI : LogicI<0x28, "ori ", or>; + def XORI : LogicI<0x2A, "xori ", xor>; +} + +let Predicates=[HasMul] in { + def MULI : ArithI<0x18, "muli ", mul, simm16, immSExt16>; +} + +//===----------------------------------------------------------------------===// +// MBlaze memory access instructions +//===----------------------------------------------------------------------===// + +let canFoldAsLoad = 1, isReMaterializable = 1 in { + def LBU : LoadM<0x30, "lbu ", zextloadi8>; + def LHU : LoadM<0x31, "lhu ", zextloadi16>; + def LW : LoadM<0x32, "lw ", load>; + + def LBUI : LoadMI<0x30, "lbui ", zextloadi8>; + def LHUI : LoadMI<0x31, "lhui ", zextloadi16>; + def LWI : LoadMI<0x32, "lwi ", load>; +} + + def SB : StoreM<0x34, "sb ", truncstorei8>; + def SH : StoreM<0x35, "sh ", truncstorei16>; + def SW : StoreM<0x36, "sw ", store>; + + def SBI : StoreMI<0x34, "sbi ", truncstorei8>; + def SHI : StoreMI<0x35, "shi ", truncstorei16>; + def SWI : StoreMI<0x36, "swi ", store>; + +//===----------------------------------------------------------------------===// +// MBlaze branch instructions +//===----------------------------------------------------------------------===// + +let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { + def BRI : BranchI<0x2E, 0x00, "bri ">; + def BRAI : BranchI<0x2E, 0x08, "brai ">; + def BEQI : BranchCI<0x2F, 0x00, "beqi ", seteq>; + def BNEI : BranchCI<0x2F, 0x01, "bnei ", setne>; + def BLTI : BranchCI<0x2F, 0x02, "blti ", setlt>; + def BLEI : BranchCI<0x2F, 0x03, "blei ", setle>; + def BGTI : BranchCI<0x2F, 0x04, "bgti ", setgt>; + def BGEI : BranchCI<0x2F, 0x05, "bgei ", setge>; +} + +let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, hasCtrlDep = 1 in { + def BR : Branch<0x26, 0x00, 0x000, "br ">; + def BRA : Branch<0x26, 0x08, 0x000, "bra ">; + def BEQ : BranchC<0x27, 0x00, 0x000, "beq ", seteq>; + def BNE : BranchC<0x27, 0x01, 0x000, "bne ", setne>; + def BLT : BranchC<0x27, 0x02, 0x000, "blt ", setlt>; + def BLE : BranchC<0x27, 0x03, 0x000, "ble ", setle>; + def BGT : BranchC<0x27, 0x04, 0x000, "bgt ", setgt>; + def BGE : BranchC<0x27, 0x05, 0x000, "bge ", setge>; +} + +let isBranch = 1, isTerminator = 1, hasDelaySlot = 1, hasCtrlDep = 1 in { + def BRID : BranchI<0x2E, 0x10, "brid ">; + def BRAID : BranchI<0x2E, 0x18, "braid ">; + def BEQID : BranchCI<0x2F, 0x10, "beqid ", seteq>; + def BNEID : BranchCI<0x2F, 0x11, "bneid ", setne>; + def BLTID : BranchCI<0x2F, 0x12, "bltid ", setlt>; + def BLEID : BranchCI<0x2F, 0x13, "bleid ", setle>; + def BGTID : BranchCI<0x2F, 0x14, "bgtid ", setgt>; + def BGEID : BranchCI<0x2F, 0x15, "bgeid ", setge>; +} + +let isBranch = 1, isIndirectBranch = 1, isTerminator = 1, + hasDelaySlot = 1, hasCtrlDep = 1 in { + def BRD : Branch<0x26, 0x10, 0x000, "brd ">; + def BRAD : Branch<0x26, 0x18, 0x000, "brad ">; + def BEQD : BranchC<0x27, 0x10, 0x000, "beqd ", seteq>; + def BNED : BranchC<0x27, 0x11, 0x000, "bned ", setne>; + def BLTD : BranchC<0x27, 0x12, 0x000, "bltd ", setlt>; + def BLED : BranchC<0x27, 0x13, 0x000, "bled ", setle>; + def BGTD : BranchC<0x27, 0x14, 0x000, "bgtd ", setgt>; + def BGED : BranchC<0x27, 0x15, 0x000, "bged ", setge>; +} + +let isCall = 1, hasCtrlDep = 1, isIndirectBranch = 1, + Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], + Uses = [R1,R5,R6,R7,R8,R9,R10] in { + def BRL : BranchL<0x26, 0x04, 0x000, "brl ">; + def BRAL : BranchL<0x26, 0x0C, 0x000, "bral ">; +} + +let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, + Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], + Uses = [R1,R5,R6,R7,R8,R9,R10] in { + def BRLID : BranchLI<0x2E, 0x14, "brlid ">; + def BRALID : BranchLI<0x2E, 0x1C, "bralid ">; +} + +let isCall = 1, hasDelaySlot = 1, hasCtrlDep = 1, isIndirectBranch = 1, + Defs = [R3,R4,R5,R6,R7,R8,R9,R10,R11,R12], + Uses = [R1,R5,R6,R7,R8,R9,R10] in { + def BRLD : BranchL<0x26, 0x14, 0x000, "brld ">; + def BRALD : BranchL<0x26, 0x1C, 0x000, "brald ">; +} + +let isReturn=1, isTerminator=1, hasDelaySlot=1, + isBarrier=1, hasCtrlDep=1, imm16=0x8 in { + def RTSD : TRET<0x2D, (outs), (ins CPURegs:$target), + "rtsd $target, 8", + [(MBlazeRet CPURegs:$target)], + IIBranch>; +} + +//===----------------------------------------------------------------------===// +// MBlaze misc instructions +//===----------------------------------------------------------------------===// + +let addr = 0 in { + def NOP : TADDR<0x00, (outs), (ins), "nop ", [], IIAlu>; +} + +let usesCustomInserter = 1 in { + //class PseudoSelCC: + // MBlazePseudo<(outs RC:$D), (ins RC:$T, RC:$F, CPURegs:$CMP), asmstr, + // [(set RC:$D, (MBlazeSelectCC RC:$T, RC:$F, CPURegs:$CMP))]>; + //def Select_CC : PseudoSelCC; + + def Select_CC : MBlazePseudo<(outs CPURegs:$dst), + (ins CPURegs:$T, CPURegs:$F, CPURegs:$CMP, i32imm:$CC), + "; SELECT_CC PSEUDO!", + []>; + + def ShiftL : MBlazePseudo<(outs CPURegs:$dst), + (ins CPURegs:$L, CPURegs:$R), + "; ShiftL PSEUDO!", + []>; + + def ShiftRA : MBlazePseudo<(outs CPURegs:$dst), + (ins CPURegs:$L, CPURegs:$R), + "; ShiftRA PSEUDO!", + []>; + + def ShiftRL : MBlazePseudo<(outs CPURegs:$dst), + (ins CPURegs:$L, CPURegs:$R), + "; ShiftRL PSEUDO!", + []>; +} + + +let rb = 0 in { + def SEXT16 : TA<0x24, 0x061, (outs CPURegs:$dst), (ins CPURegs:$src), + "sext16 $dst, $src", [], IIAlu>; + def SEXT8 : TA<0x24, 0x060, (outs CPURegs:$dst), (ins CPURegs:$src), + "sext8 $dst, $src", [], IIAlu>; + def SRL : TA<0x24, 0x041, (outs CPURegs:$dst), (ins CPURegs:$src), + "srl $dst, $src", [], IIAlu>; + def SRA : TA<0x24, 0x001, (outs CPURegs:$dst), (ins CPURegs:$src), + "sra $dst, $src", [], IIAlu>; + def SRC : TA<0x24, 0x021, (outs CPURegs:$dst), (ins CPURegs:$src), + "src $dst, $src", [], IIAlu>; +} + +def LEA_ADDI : EffectiveAddress<"addi $dst, ${addr:stackloc}">; + +//===----------------------------------------------------------------------===// +// Arbitrary patterns that map to one or more instructions +//===----------------------------------------------------------------------===// + +// Small immediates +def : Pat<(i32 0), (ADD R0, R0)>; +def : Pat<(i32 immSExt16:$imm), (ADDI R0, imm:$imm)>; +def : Pat<(i32 immZExt16:$imm), (ORI R0, imm:$imm)>; + +// Arbitrary immediates +def : Pat<(i32 imm:$imm), (ADDI R0, imm:$imm)>; + +// In register sign extension +def : Pat<(sext_inreg CPURegs:$src, i16), (SEXT16 CPURegs:$src)>; +def : Pat<(sext_inreg CPURegs:$src, i8), (SEXT8 CPURegs:$src)>; + +// Call +def : Pat<(MBlazeJmpLink (i32 tglobaladdr:$dst)), (BRLID tglobaladdr:$dst)>; +def : Pat<(MBlazeJmpLink (i32 texternalsym:$dst)),(BRLID texternalsym:$dst)>; +def : Pat<(MBlazeJmpLink CPURegs:$dst), (BRLD CPURegs:$dst)>; + +// Shift Instructions +def : Pat<(shl CPURegs:$L, CPURegs:$R), (ShiftL CPURegs:$L, CPURegs:$R)>; +def : Pat<(sra CPURegs:$L, CPURegs:$R), (ShiftRA CPURegs:$L, CPURegs:$R)>; +def : Pat<(srl CPURegs:$L, CPURegs:$R), (ShiftRL CPURegs:$L, CPURegs:$R)>; + +// SET_CC operations +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETEQ), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMP CPURegs:$L, CPURegs:$R), 1)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETNE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMP CPURegs:$L, CPURegs:$R), 2)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETGT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMP CPURegs:$L, CPURegs:$R), 3)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETLT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMP CPURegs:$L, CPURegs:$R), 4)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETGE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMP CPURegs:$L, CPURegs:$R), 5)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETLE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMP CPURegs:$L, CPURegs:$R), 6)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETUGT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMPU CPURegs:$L, CPURegs:$R), 3)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETULT), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMPU CPURegs:$L, CPURegs:$R), 4)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETUGE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMPU CPURegs:$L, CPURegs:$R), 5)>; +def : Pat<(setcc CPURegs:$L, CPURegs:$R, SETULE), + (Select_CC (ADDI R0, 1), (ADDI R0, 0), + (CMPU CPURegs:$L, CPURegs:$R), 6)>; + +// SELECT operations +def : Pat<(select CPURegs:$C, CPURegs:$T, CPURegs:$F), + (Select_CC CPURegs:$T, CPURegs:$F, CPURegs:$C, 2)>; + +// SELECT_CC +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETEQ), + (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 1)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETNE), + (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 2)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETGT), + (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 3)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETLT), + (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 4)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETGE), + (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 5)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETLE), + (Select_CC CPURegs:$T, CPURegs:$F, (CMP CPURegs:$L, CPURegs:$R), 6)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETUGT), + (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 3)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETULT), + (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 4)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETUGE), + (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 5)>; +def : Pat<(selectcc CPURegs:$L, CPURegs:$R, CPURegs:$T, CPURegs:$F, SETULE), + (Select_CC CPURegs:$T, CPURegs:$F, (CMPU CPURegs:$L, CPURegs:$R), 6)>; + +// BRCOND instructions +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETEQ), bb:$T), + (BEQID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETNE), bb:$T), + (BNEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETGT), bb:$T), + (BGTID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETLT), bb:$T), + (BLTID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETGE), bb:$T), + (BGEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETLE), bb:$T), + (BLEID (CMP CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETUGT), bb:$T), + (BGTID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETULT), bb:$T), + (BLTID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETUGE), bb:$T), + (BGEID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond (setcc CPURegs:$L, CPURegs:$R, SETULE), bb:$T), + (BLEID (CMPU CPURegs:$R, CPURegs:$L), bb:$T)>; +def : Pat<(brcond CPURegs:$C, bb:$T), + (BNEID CPURegs:$C, bb:$T)>; + +// Jump tables, global addresses, and constant pools +def : Pat<(MBWrapper tglobaladdr:$in), (ORI R0, tglobaladdr:$in)>; +def : Pat<(MBWrapper tjumptable:$in), (ORI R0, tjumptable:$in)>; +def : Pat<(MBWrapper tconstpool:$in), (ORI R0, tconstpool:$in)>; + +// Misc instructions +def : Pat<(and CPURegs:$lh, (not CPURegs:$rh)),(ANDN CPURegs:$lh, CPURegs:$rh)>; + +// Arithmetic with immediates +def : Pat<(add CPURegs:$in, imm:$imm),(ADDI CPURegs:$in, imm:$imm)>; +def : Pat<(or CPURegs:$in, imm:$imm),(ORI CPURegs:$in, imm:$imm)>; +def : Pat<(xor CPURegs:$in, imm:$imm),(XORI CPURegs:$in, imm:$imm)>; + +// extended load and stores +def : Pat<(extloadi1 iaddr:$src), (LBUI iaddr:$src)>; +def : Pat<(extloadi8 iaddr:$src), (LBUI iaddr:$src)>; +def : Pat<(extloadi16 iaddr:$src), (LHUI iaddr:$src)>; +def : Pat<(extloadi1 xaddr:$src), (LBU xaddr:$src)>; +def : Pat<(extloadi8 xaddr:$src), (LBU xaddr:$src)>; +def : Pat<(extloadi16 xaddr:$src), (LHU xaddr:$src)>; + +def : Pat<(sextloadi1 iaddr:$src), (SEXT8 (LBUI iaddr:$src))>; +def : Pat<(sextloadi8 iaddr:$src), (SEXT8 (LBUI iaddr:$src))>; +def : Pat<(sextloadi16 iaddr:$src), (SEXT16 (LHUI iaddr:$src))>; +def : Pat<(sextloadi1 xaddr:$src), (SEXT8 (LBU xaddr:$src))>; +def : Pat<(sextloadi8 xaddr:$src), (SEXT8 (LBU xaddr:$src))>; +def : Pat<(sextloadi16 xaddr:$src), (SEXT16 (LHU xaddr:$src))>; + +// peepholes +def : Pat<(store (i32 0), iaddr:$dst), (SWI R0, iaddr:$dst)>; + +//===----------------------------------------------------------------------===// +// Floating Point Support +//===----------------------------------------------------------------------===// +include "MBlazeInstrFSL.td" +include "MBlazeInstrFPU.td" diff --git a/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp b/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp new file mode 100644 index 0000000000..c8faffc845 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp @@ -0,0 +1,109 @@ +//===- MBlazeIntrinsicInfo.cpp - Intrinsic Information -00-------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the MBlaze implementation of TargetIntrinsicInfo. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeIntrinsicInfo.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Intrinsics.h" +#include "llvm/Module.h" +#include "llvm/Type.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +namespace mblazeIntrinsic { + + enum ID { + last_non_mblaze_intrinsic = Intrinsic::num_intrinsics-1, +#define GET_INTRINSIC_ENUM_VALUES +#include "MBlazeGenIntrinsics.inc" +#undef GET_INTRINSIC_ENUM_VALUES + , num_mblaze_intrinsics + }; + +#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN +#include "MBlazeGenIntrinsics.inc" +#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN +} + +std::string MBlazeIntrinsicInfo::getName(unsigned IntrID, const Type **Tys, + unsigned numTys) const { + static const char *const names[] = { +#define GET_INTRINSIC_NAME_TABLE +#include "MBlazeGenIntrinsics.inc" +#undef GET_INTRINSIC_NAME_TABLE + }; + + assert(!isOverloaded(IntrID) && "MBlaze intrinsics are not overloaded"); + if (IntrID < Intrinsic::num_intrinsics) + return 0; + assert(IntrID < mblazeIntrinsic::num_mblaze_intrinsics && + "Invalid intrinsic ID"); + + std::string Result(names[IntrID - Intrinsic::num_intrinsics]); + return Result; +} + +unsigned MBlazeIntrinsicInfo:: +lookupName(const char *Name, unsigned Len) const { +#define GET_FUNCTION_RECOGNIZER +#include "MBlazeGenIntrinsics.inc" +#undef GET_FUNCTION_RECOGNIZER + return 0; +} + +unsigned MBlazeIntrinsicInfo:: +lookupGCCName(const char *Name) const { + return mblazeIntrinsic::getIntrinsicForGCCBuiltin("mblaze",Name); +} + +bool MBlazeIntrinsicInfo::isOverloaded(unsigned IntrID) const { + // Overload Table + const bool OTable[] = { +#define GET_INTRINSIC_OVERLOAD_TABLE +#include "MBlazeGenIntrinsics.inc" +#undef GET_INTRINSIC_OVERLOAD_TABLE + }; + if (IntrID == 0) + return false; + else + return OTable[IntrID - Intrinsic::num_intrinsics]; +} + +/// This defines the "getAttributes(ID id)" method. +#define GET_INTRINSIC_ATTRIBUTES +#include "MBlazeGenIntrinsics.inc" +#undef GET_INTRINSIC_ATTRIBUTES + +static const FunctionType *getType(LLVMContext &Context, unsigned id) { + const Type *ResultTy = NULL; + std::vector ArgTys; + bool IsVarArg = false; + +#define GET_INTRINSIC_GENERATOR +#include "MBlazeGenIntrinsics.inc" +#undef GET_INTRINSIC_GENERATOR + + return FunctionType::get(ResultTy, ArgTys, IsVarArg); +} + +Function *MBlazeIntrinsicInfo::getDeclaration(Module *M, unsigned IntrID, + const Type **Tys, + unsigned numTy) const { + assert(!isOverloaded(IntrID) && "MBlaze intrinsics are not overloaded"); + AttrListPtr AList = getAttributes((mblazeIntrinsic::ID) IntrID); + return cast(M->getOrInsertFunction(getName(IntrID), + getType(M->getContext(), IntrID), + AList)); +} diff --git a/lib/Target/MBlaze/MBlazeIntrinsicInfo.h b/lib/Target/MBlaze/MBlazeIntrinsicInfo.h new file mode 100644 index 0000000000..9804c7723b --- /dev/null +++ b/lib/Target/MBlaze/MBlazeIntrinsicInfo.h @@ -0,0 +1,33 @@ +//===- MBlazeIntrinsicInfo.h - MBlaze Intrinsic Information -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the MBlaze implementation of TargetIntrinsicInfo. +// +//===----------------------------------------------------------------------===// +#ifndef MBLAZEINTRINSICS_H +#define MBLAZEINTRINSICS_H + +#include "llvm/Target/TargetIntrinsicInfo.h" + +namespace llvm { + + class MBlazeIntrinsicInfo : public TargetIntrinsicInfo { + public: + std::string getName(unsigned IntrID, const Type **Tys = 0, + unsigned numTys = 0) const; + unsigned lookupName(const char *Name, unsigned Len) const; + unsigned lookupGCCName(const char *Name) const; + bool isOverloaded(unsigned IID) const; + Function *getDeclaration(Module *M, unsigned ID, const Type **Tys = 0, + unsigned numTys = 0) const; + }; + +} + +#endif diff --git a/lib/Target/MBlaze/MBlazeIntrinsics.td b/lib/Target/MBlaze/MBlazeIntrinsics.td new file mode 100644 index 0000000000..76eb56367a --- /dev/null +++ b/lib/Target/MBlaze/MBlazeIntrinsics.td @@ -0,0 +1,137 @@ +//===- IntrinsicsMBlaze.td - Defines MBlaze intrinsics -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the MicroBlaze-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Definitions for all MBlaze intrinsics. +// + +// MBlaze intrinsic classes. +let TargetPrefix = "mblaze", isTarget = 1 in { + class MBFSL_Get_Intrinsic : Intrinsic<[llvm_i32_ty], + [llvm_i32_ty], + [IntrWriteMem]>; + + class MBFSL_Put_Intrinsic : Intrinsic<[llvm_void_ty], + [llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + + class MBFSL_PutT_Intrinsic : Intrinsic<[llvm_void_ty], + [llvm_i32_ty], + [IntrWriteMem]>; +} + +//===----------------------------------------------------------------------===// +// MicroBlaze FSL Get Intrinsic Definitions. +// + +def int_mblaze_fsl_get : GCCBuiltin<"__builtin_mblaze_fsl_get">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_aget : GCCBuiltin<"__builtin_mblaze_fsl_aget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_cget : GCCBuiltin<"__builtin_mblaze_fsl_cget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_caget : GCCBuiltin<"__builtin_mblaze_fsl_caget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_eget : GCCBuiltin<"__builtin_mblaze_fsl_eget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_eaget : GCCBuiltin<"__builtin_mblaze_fsl_eaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_ecget : GCCBuiltin<"__builtin_mblaze_fsl_ecget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_ecaget : GCCBuiltin<"__builtin_mblaze_fsl_ecaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_nget : GCCBuiltin<"__builtin_mblaze_fsl_nget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_naget : GCCBuiltin<"__builtin_mblaze_fsl_naget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_ncget : GCCBuiltin<"__builtin_mblaze_fsl_ncget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_ncaget : GCCBuiltin<"__builtin_mblaze_fsl_ncaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_neget : GCCBuiltin<"__builtin_mblaze_fsl_neget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_neaget : GCCBuiltin<"__builtin_mblaze_fsl_neaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_necget : GCCBuiltin<"__builtin_mblaze_fsl_necget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_necaget : GCCBuiltin<"__builtin_mblaze_fsl_necaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tget : GCCBuiltin<"__builtin_mblaze_fsl_tget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_taget : GCCBuiltin<"__builtin_mblaze_fsl_taget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tcget : GCCBuiltin<"__builtin_mblaze_fsl_tcget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tcaget : GCCBuiltin<"__builtin_mblaze_fsl_tcaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_teget : GCCBuiltin<"__builtin_mblaze_fsl_teget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_teaget : GCCBuiltin<"__builtin_mblaze_fsl_teaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tecget : GCCBuiltin<"__builtin_mblaze_fsl_tecget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tecaget : GCCBuiltin<"__builtin_mblaze_fsl_tecaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tnget : GCCBuiltin<"__builtin_mblaze_fsl_tnget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tnaget : GCCBuiltin<"__builtin_mblaze_fsl_tnaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tncget : GCCBuiltin<"__builtin_mblaze_fsl_tncget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tncaget : GCCBuiltin<"__builtin_mblaze_fsl_tncaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tneget : GCCBuiltin<"__builtin_mblaze_fsl_tneget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tneaget : GCCBuiltin<"__builtin_mblaze_fsl_tneaget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tnecget : GCCBuiltin<"__builtin_mblaze_fsl_tnecget">, + MBFSL_Get_Intrinsic; +def int_mblaze_fsl_tnecaget : GCCBuiltin<"__builtin_mblaze_fsl_tnecaget">, + MBFSL_Get_Intrinsic; + +//===----------------------------------------------------------------------===// +// MicroBlaze FSL Put Intrinsic Definitions. +// + +def int_mblaze_fsl_put : GCCBuiltin<"__builtin_mblaze_fsl_put">, + MBFSL_Put_Intrinsic; +def int_mblaze_fsl_aput : GCCBuiltin<"__builtin_mblaze_fsl_aput">, + MBFSL_Put_Intrinsic; +def int_mblaze_fsl_cput : GCCBuiltin<"__builtin_mblaze_fsl_cput">, + MBFSL_Put_Intrinsic; +def int_mblaze_fsl_caput : GCCBuiltin<"__builtin_mblaze_fsl_caput">, + MBFSL_Put_Intrinsic; +def int_mblaze_fsl_nput : GCCBuiltin<"__builtin_mblaze_fsl_nput">, + MBFSL_Put_Intrinsic; +def int_mblaze_fsl_naput : GCCBuiltin<"__builtin_mblaze_fsl_naput">, + MBFSL_Put_Intrinsic; +def int_mblaze_fsl_ncput : GCCBuiltin<"__builtin_mblaze_fsl_ncput">, + MBFSL_Put_Intrinsic; +def int_mblaze_fsl_ncaput : GCCBuiltin<"__builtin_mblaze_fsl_ncaput">, + MBFSL_Put_Intrinsic; +def int_mblaze_fsl_tput : GCCBuiltin<"__builtin_mblaze_fsl_tput">, + MBFSL_PutT_Intrinsic; +def int_mblaze_fsl_taput : GCCBuiltin<"__builtin_mblaze_fsl_taput">, + MBFSL_PutT_Intrinsic; +def int_mblaze_fsl_tcput : GCCBuiltin<"__builtin_mblaze_fsl_tcput">, + MBFSL_PutT_Intrinsic; +def int_mblaze_fsl_tcaput : GCCBuiltin<"__builtin_mblaze_fsl_tcaput">, + MBFSL_PutT_Intrinsic; +def int_mblaze_fsl_tnput : GCCBuiltin<"__builtin_mblaze_fsl_tnput">, + MBFSL_PutT_Intrinsic; +def int_mblaze_fsl_tnaput : GCCBuiltin<"__builtin_mblaze_fsl_tnaput">, + MBFSL_PutT_Intrinsic; +def int_mblaze_fsl_tncput : GCCBuiltin<"__builtin_mblaze_fsl_tncput">, + MBFSL_PutT_Intrinsic; +def int_mblaze_fsl_tncaput : GCCBuiltin<"__builtin_mblaze_fsl_tncaput">, + MBFSL_PutT_Intrinsic; diff --git a/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp b/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp new file mode 100644 index 0000000000..7ae465dbc5 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeMCAsmInfo.cpp @@ -0,0 +1,27 @@ +//===-- MBlazeMCAsmInfo.cpp - MBlaze asm properties -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of the MBlazeMCAsmInfo properties. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeMCAsmInfo.h" +using namespace llvm; + +MBlazeMCAsmInfo::MBlazeMCAsmInfo(const Target &T, const StringRef &TT) { + AlignmentIsInBytes = false; + Data16bitsDirective = "\t.half\t"; + Data32bitsDirective = "\t.word\t"; + Data64bitsDirective = 0; + PrivateGlobalPrefix = "$"; + CommentString = "#"; + ZeroDirective = "\t.space\t"; + GPRel32Directive = "\t.gpword\t"; + HasSetDirective = false; +} diff --git a/lib/Target/MBlaze/MBlazeMCAsmInfo.h b/lib/Target/MBlaze/MBlazeMCAsmInfo.h new file mode 100644 index 0000000000..bccb418673 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeMCAsmInfo.h @@ -0,0 +1,30 @@ +//=====-- MBlazeMCAsmInfo.h - MBlaze asm properties -----------*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MBlazeMCAsmInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZETARGETASMINFO_H +#define MBLAZETARGETASMINFO_H + +#include "llvm/MC/MCAsmInfo.h" + +namespace llvm { + class Target; + class StringRef; + + class MBlazeMCAsmInfo : public MCAsmInfo { + public: + explicit MBlazeMCAsmInfo(const Target &T, const StringRef &TT); + }; + +} // namespace llvm + +#endif diff --git a/lib/Target/MBlaze/MBlazeMachineFunction.h b/lib/Target/MBlaze/MBlazeMachineFunction.h new file mode 100644 index 0000000000..08d4dcad6e --- /dev/null +++ b/lib/Target/MBlaze/MBlazeMachineFunction.h @@ -0,0 +1,136 @@ +//===-- MBlazeMachineFunctionInfo.h - Private data ----------------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MBlaze specific subclass of MachineFunctionInfo. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZE_MACHINE_FUNCTION_INFO_H +#define MBLAZE_MACHINE_FUNCTION_INFO_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/VectorExtras.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" + +namespace llvm { + +/// MBlazeFunctionInfo - This class is derived from MachineFunction private +/// MBlaze target-specific information for each MachineFunction. +class MBlazeFunctionInfo : public MachineFunctionInfo { + +private: + /// Holds for each function where on the stack the Frame Pointer must be + /// saved. This is used on Prologue and Epilogue to emit FP save/restore + int FPStackOffset; + + /// Holds for each function where on the stack the Return Address must be + /// saved. This is used on Prologue and Epilogue to emit RA save/restore + int RAStackOffset; + + /// At each function entry a special bitmask directive must be emitted + /// to help in debugging CPU callee saved registers. It needs a negative + /// offset from the final stack size and its higher register location on + /// the stack. + int CPUTopSavedRegOff; + + /// MBlazeFIHolder - Holds a FrameIndex and it's Stack Pointer Offset + struct MBlazeFIHolder { + + int FI; + int SPOffset; + + MBlazeFIHolder(int FrameIndex, int StackPointerOffset) + : FI(FrameIndex), SPOffset(StackPointerOffset) {} + }; + + /// When PIC is used the GP must be saved on the stack on the function + /// prologue and must be reloaded from this stack location after every + /// call. A reference to its stack location and frame index must be kept + /// to be used on emitPrologue and processFunctionBeforeFrameFinalized. + MBlazeFIHolder GPHolder; + + /// On LowerFormalArguments the stack size is unknown, so the Stack + /// Pointer Offset calculation of "not in register arguments" must be + /// postponed to emitPrologue. + SmallVector FnLoadArgs; + bool HasLoadArgs; + + // When VarArgs, we must write registers back to caller stack, preserving + // on register arguments. Since the stack size is unknown on + // LowerFormalArguments, the Stack Pointer Offset calculation must be + // postponed to emitPrologue. + SmallVector FnStoreVarArgs; + bool HasStoreVarArgs; + + /// SRetReturnReg - Some subtargets require that sret lowering includes + /// returning the value of the returned struct in a register. This field + /// holds the virtual register into which the sret argument is passed. + unsigned SRetReturnReg; + + /// GlobalBaseReg - keeps track of the virtual register initialized for + /// use as the global base register. This is used for PIC in some PIC + /// relocation models. + unsigned GlobalBaseReg; + +public: + MBlazeFunctionInfo(MachineFunction& MF) + : FPStackOffset(0), RAStackOffset(0), CPUTopSavedRegOff(0), + GPHolder(-1,-1), HasLoadArgs(false), HasStoreVarArgs(false), + SRetReturnReg(0), GlobalBaseReg(0) + {} + + int getFPStackOffset() const { return FPStackOffset; } + void setFPStackOffset(int Off) { FPStackOffset = Off; } + + int getRAStackOffset() const { return RAStackOffset; } + void setRAStackOffset(int Off) { RAStackOffset = Off; } + + int getCPUTopSavedRegOff() const { return CPUTopSavedRegOff; } + void setCPUTopSavedRegOff(int Off) { CPUTopSavedRegOff = Off; } + + int getGPStackOffset() const { return GPHolder.SPOffset; } + int getGPFI() const { return GPHolder.FI; } + void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; } + void setGPFI(int FI) { GPHolder.FI = FI; } + bool needGPSaveRestore() const { return GPHolder.SPOffset != -1; } + + bool hasLoadArgs() const { return HasLoadArgs; } + bool hasStoreVarArgs() const { return HasStoreVarArgs; } + + void recordLoadArgsFI(int FI, int SPOffset) { + if (!HasLoadArgs) HasLoadArgs=true; + FnLoadArgs.push_back(MBlazeFIHolder(FI, SPOffset)); + } + void recordStoreVarArgsFI(int FI, int SPOffset) { + if (!HasStoreVarArgs) HasStoreVarArgs=true; + FnStoreVarArgs.push_back(MBlazeFIHolder(FI, SPOffset)); + } + + void adjustLoadArgsFI(MachineFrameInfo *MFI) const { + if (!hasLoadArgs()) return; + for (unsigned i = 0, e = FnLoadArgs.size(); i != e; ++i) + MFI->setObjectOffset( FnLoadArgs[i].FI, FnLoadArgs[i].SPOffset ); + } + void adjustStoreVarArgsFI(MachineFrameInfo *MFI) const { + if (!hasStoreVarArgs()) return; + for (unsigned i = 0, e = FnStoreVarArgs.size(); i != e; ++i) + MFI->setObjectOffset( FnStoreVarArgs[i].FI, FnStoreVarArgs[i].SPOffset ); + } + + unsigned getSRetReturnReg() const { return SRetReturnReg; } + void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } + + unsigned getGlobalBaseReg() const { return GlobalBaseReg; } + void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } +}; + +} // end of namespace llvm + +#endif // MBLAZE_MACHINE_FUNCTION_INFO_H diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.cpp b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp new file mode 100644 index 0000000000..8dfca81fb2 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.cpp @@ -0,0 +1,421 @@ +//===- MBlazeRegisterInfo.cpp - MBlaze Register Information -== -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the MBlaze implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "mblaze-reg-info" + +#include "MBlaze.h" +#include "MBlazeSubtarget.h" +#include "MBlazeRegisterInfo.h" +#include "MBlazeMachineFunction.h" +#include "llvm/Constants.h" +#include "llvm/Type.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Target/TargetFrameInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/STLExtras.h" + +using namespace llvm; + +MBlazeRegisterInfo:: +MBlazeRegisterInfo(const MBlazeSubtarget &ST, const TargetInstrInfo &tii) + : MBlazeGenRegisterInfo(MBlaze::ADJCALLSTACKDOWN, MBlaze::ADJCALLSTACKUP), + Subtarget(ST), TII(tii) {} + +/// getRegisterNumbering - Given the enum value for some register, e.g. +/// MBlaze::R0, return the number that it corresponds to (e.g. 0). +unsigned MBlazeRegisterInfo::getRegisterNumbering(unsigned RegEnum) { + switch (RegEnum) { + case MBlaze::R0 : case MBlaze::F0 : return 0; + case MBlaze::R1 : case MBlaze::F1 : return 1; + case MBlaze::R2 : case MBlaze::F2 : return 2; + case MBlaze::R3 : case MBlaze::F3 : return 3; + case MBlaze::R4 : case MBlaze::F4 : return 4; + case MBlaze::R5 : case MBlaze::F5 : return 5; + case MBlaze::R6 : case MBlaze::F6 : return 6; + case MBlaze::R7 : case MBlaze::F7 : return 7; + case MBlaze::R8 : case MBlaze::F8 : return 8; + case MBlaze::R9 : case MBlaze::F9 : return 9; + case MBlaze::R10 : case MBlaze::F10 : return 10; + case MBlaze::R11 : case MBlaze::F11 : return 11; + case MBlaze::R12 : case MBlaze::F12 : return 12; + case MBlaze::R13 : case MBlaze::F13 : return 13; + case MBlaze::R14 : case MBlaze::F14 : return 14; + case MBlaze::R15 : case MBlaze::F15 : return 15; + case MBlaze::R16 : case MBlaze::F16 : return 16; + case MBlaze::R17 : case MBlaze::F17 : return 17; + case MBlaze::R18 : case MBlaze::F18 : return 18; + case MBlaze::R19 : case MBlaze::F19 : return 19; + case MBlaze::R20 : case MBlaze::F20 : return 20; + case MBlaze::R21 : case MBlaze::F21 : return 21; + case MBlaze::R22 : case MBlaze::F22 : return 22; + case MBlaze::R23 : case MBlaze::F23 : return 23; + case MBlaze::R24 : case MBlaze::F24 : return 24; + case MBlaze::R25 : case MBlaze::F25 : return 25; + case MBlaze::R26 : case MBlaze::F26 : return 26; + case MBlaze::R27 : case MBlaze::F27 : return 27; + case MBlaze::R28 : case MBlaze::F28 : return 28; + case MBlaze::R29 : case MBlaze::F29 : return 29; + case MBlaze::R30 : case MBlaze::F30 : return 30; + case MBlaze::R31 : case MBlaze::F31 : return 31; + default: llvm_unreachable("Unknown register number!"); + } + return 0; // Not reached +} + +/// getRegisterFromNumbering - Given the enum value for some register, e.g. +/// MBlaze::R0, return the number that it corresponds to (e.g. 0). +unsigned MBlazeRegisterInfo::getRegisterFromNumbering(unsigned Reg) { + switch (Reg) { + case 0 : return MBlaze::R0; + case 1 : return MBlaze::R1; + case 2 : return MBlaze::R2; + case 3 : return MBlaze::R3; + case 4 : return MBlaze::R4; + case 5 : return MBlaze::R5; + case 6 : return MBlaze::R6; + case 7 : return MBlaze::R7; + case 8 : return MBlaze::R8; + case 9 : return MBlaze::R9; + case 10 : return MBlaze::R10; + case 11 : return MBlaze::R11; + case 12 : return MBlaze::R12; + case 13 : return MBlaze::R13; + case 14 : return MBlaze::R14; + case 15 : return MBlaze::R15; + case 16 : return MBlaze::R16; + case 17 : return MBlaze::R17; + case 18 : return MBlaze::R18; + case 19 : return MBlaze::R19; + case 20 : return MBlaze::R20; + case 21 : return MBlaze::R21; + case 22 : return MBlaze::R22; + case 23 : return MBlaze::R23; + case 24 : return MBlaze::R24; + case 25 : return MBlaze::R25; + case 26 : return MBlaze::R26; + case 27 : return MBlaze::R27; + case 28 : return MBlaze::R28; + case 29 : return MBlaze::R29; + case 30 : return MBlaze::R30; + case 31 : return MBlaze::R31; + default: llvm_unreachable("Unknown register number!"); + } + return 0; // Not reached +} + +unsigned MBlazeRegisterInfo::getPICCallReg() { + return MBlaze::R20; +} + +//===----------------------------------------------------------------------===// +// Callee Saved Registers methods +//===----------------------------------------------------------------------===// + +/// MBlaze Callee Saved Registers +const unsigned* MBlazeRegisterInfo:: +getCalleeSavedRegs(const MachineFunction *MF) const { + // MBlaze callee-save register range is R20 - R31 + static const unsigned CalleeSavedRegs[] = { + MBlaze::R20, MBlaze::R21, MBlaze::R22, MBlaze::R23, + MBlaze::R24, MBlaze::R25, MBlaze::R26, MBlaze::R27, + MBlaze::R28, MBlaze::R29, MBlaze::R30, MBlaze::R31, + 0 + }; + + return CalleeSavedRegs; +} + +/// MBlaze Callee Saved Register Classes +const TargetRegisterClass* const* MBlazeRegisterInfo:: +getCalleeSavedRegClasses(const MachineFunction *MF) const { + static const TargetRegisterClass * const CalleeSavedRC[] = { + &MBlaze::CPURegsRegClass, &MBlaze::CPURegsRegClass, + &MBlaze::CPURegsRegClass, &MBlaze::CPURegsRegClass, + &MBlaze::CPURegsRegClass, &MBlaze::CPURegsRegClass, + &MBlaze::CPURegsRegClass, &MBlaze::CPURegsRegClass, + &MBlaze::CPURegsRegClass, &MBlaze::CPURegsRegClass, + &MBlaze::CPURegsRegClass, &MBlaze::CPURegsRegClass, + 0 + }; + + return CalleeSavedRC; +} + +BitVector MBlazeRegisterInfo:: +getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + Reserved.set(MBlaze::R0); + Reserved.set(MBlaze::R1); + Reserved.set(MBlaze::R2); + Reserved.set(MBlaze::R13); + Reserved.set(MBlaze::R14); + Reserved.set(MBlaze::R15); + Reserved.set(MBlaze::R16); + Reserved.set(MBlaze::R17); + Reserved.set(MBlaze::R18); + Reserved.set(MBlaze::R19); + return Reserved; +} + +//===----------------------------------------------------------------------===// +// +// Stack Frame Processing methods +// +----------------------------+ +// +// The stack is allocated decrementing the stack pointer on +// the first instruction of a function prologue. Once decremented, +// all stack references are are done through a positive offset +// from the stack/frame pointer, so the stack is considered +// to grow up. +// +//===----------------------------------------------------------------------===// + +void MBlazeRegisterInfo::adjustMBlazeStackFrame(MachineFunction &MF) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo(); + + // See the description at MicroBlazeMachineFunction.h + int TopCPUSavedRegOff = -1; + + // Adjust CPU Callee Saved Registers Area. Registers RA and FP must + // be saved in this CPU Area there is the need. This whole Area must + // be aligned to the default Stack Alignment requirements. + unsigned StackOffset = MFI->getStackSize(); + unsigned RegSize = 4; + + // Replace the dummy '0' SPOffset by the negative offsets, as explained on + // LowerFORMAL_ARGUMENTS. Leaving '0' for while is necessary to avoid + // the approach done by calculateFrameObjectOffsets to the stack frame. + MBlazeFI->adjustLoadArgsFI(MFI); + MBlazeFI->adjustStoreVarArgsFI(MFI); + + if (hasFP(MF)) { + MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), + StackOffset); + MBlazeFI->setFPStackOffset(StackOffset); + TopCPUSavedRegOff = StackOffset; + StackOffset += RegSize; + } + + if (MFI->hasCalls()) { + MBlazeFI->setRAStackOffset(0); + MFI->setObjectOffset(MFI->CreateStackObject(RegSize, RegSize, true), + StackOffset); + TopCPUSavedRegOff = StackOffset; + StackOffset += RegSize; + } + + // Update frame info + MFI->setStackSize(StackOffset); + + // Recalculate the final tops offset. The final values must be '0' + // if there isn't a callee saved register for CPU or FPU, otherwise + // a negative offset is needed. + if (TopCPUSavedRegOff >= 0) + MBlazeFI->setCPUTopSavedRegOff(TopCPUSavedRegOff-StackOffset); +} + +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +bool MBlazeRegisterInfo::hasFP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + return NoFramePointerElim || MFI->hasVarSizedObjects(); +} + +// This function eliminate ADJCALLSTACKDOWN, +// ADJCALLSTACKUP pseudo instructions +void MBlazeRegisterInfo:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + // Simply discard ADJCALLSTACKDOWN, ADJCALLSTACKUP instructions. + MBB.erase(I); +} + +// FrameIndex represent objects inside a abstract stack. +// We must replace FrameIndex with an stack/frame pointer +// direct reference. +unsigned MBlazeRegisterInfo:: +eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, + int *Value, RegScavenger *RS) const { + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); + + unsigned i = 0; + while (!MI.getOperand(i).isFI()) { + ++i; + assert(i < MI.getNumOperands() && + "Instr doesn't have FrameIndex operand!"); + } + + unsigned oi = i == 2 ? 1 : 2; + + DEBUG(errs() << "\nFunction : " << MF.getFunction()->getName() << "\n"; + errs() << "<--------->\n" << MI); + + int FrameIndex = MI.getOperand(i).getIndex(); + int stackSize = MF.getFrameInfo()->getStackSize(); + int spOffset = MF.getFrameInfo()->getObjectOffset(FrameIndex); + + DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" + << "spOffset : " << spOffset << "\n" + << "stackSize : " << stackSize << "\n"); + + // as explained on LowerFormalArguments, detect negative offsets + // and adjust SPOffsets considering the final stack size. + int Offset = (spOffset < 0) ? (stackSize - spOffset) : (spOffset + 4); + Offset += MI.getOperand(oi).getImm(); + + DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); + + MI.getOperand(oi).ChangeToImmediate(Offset); + MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false); + return 0; +} + +void MBlazeRegisterInfo:: +emitPrologue(MachineFunction &MF) const { + MachineBasicBlock &MBB = MF.front(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + DebugLoc dl = (MBBI != MBB.end() ? + MBBI->getDebugLoc() : DebugLoc::getUnknownLoc()); + + // Get the right frame order for MBlaze. + adjustMBlazeStackFrame(MF); + + // Get the number of bytes to allocate from the FrameInfo. + unsigned StackSize = MFI->getStackSize(); + + // No need to allocate space on the stack. + if (StackSize == 0 && !MFI->hasCalls()) return; + if (StackSize < 28 && MFI->hasCalls()) StackSize = 28; + + int FPOffset = MBlazeFI->getFPStackOffset(); + int RAOffset = MBlazeFI->getRAStackOffset(); + + // Adjust stack : addi R1, R1, -imm + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1) + .addReg(MBlaze::R1).addImm(-StackSize); + + // Save the return address only if the function isnt a leaf one. + // swi R15, R1, stack_loc + if (MFI->hasCalls()) { + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::SWI)) + .addReg(MBlaze::R15).addImm(RAOffset).addReg(MBlaze::R1); + } + + // if framepointer enabled, save it and set it + // to point to the stack pointer + if (hasFP(MF)) { + // swi R19, R1, stack_loc + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::SWI)) + .addReg(MBlaze::R19).addImm(FPOffset).addReg(MBlaze::R1); + + // add R19, R1, R0 + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R19) + .addReg(MBlaze::R1).addReg(MBlaze::R0); + } +} + +void MBlazeRegisterInfo:: +emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { + MachineBasicBlock::iterator MBBI = prior(MBB.end()); + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo(); + DebugLoc dl = MBBI->getDebugLoc(); + + // Get the FI's where RA and FP are saved. + int FPOffset = MBlazeFI->getFPStackOffset(); + int RAOffset = MBlazeFI->getRAStackOffset(); + + // if framepointer enabled, restore it and restore the + // stack pointer + if (hasFP(MF)) { + // add R1, R19, R0 + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADD), MBlaze::R1) + .addReg(MBlaze::R19).addReg(MBlaze::R0); + + // lwi R19, R1, stack_loc + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R19) + .addImm(FPOffset).addReg(MBlaze::R1); + } + + // Restore the return address only if the function isnt a leaf one. + // lwi R15, R1, stack_loc + if (MFI->hasCalls()) { + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::LWI), MBlaze::R15) + .addImm(RAOffset).addReg(MBlaze::R1); + } + + // Get the number of bytes from FrameInfo + int StackSize = (int) MFI->getStackSize(); + if (StackSize < 28 && MFI->hasCalls()) StackSize = 28; + + // adjust stack. + // addi R1, R1, imm + if (StackSize) { + BuildMI(MBB, MBBI, dl, TII.get(MBlaze::ADDI), MBlaze::R1) + .addReg(MBlaze::R1).addImm(StackSize); + } +} + + +void MBlazeRegisterInfo:: +processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + // Set the stack offset where GP must be saved/loaded from. + MachineFrameInfo *MFI = MF.getFrameInfo(); + MBlazeFunctionInfo *MBlazeFI = MF.getInfo(); + if (MBlazeFI->needGPSaveRestore()) + MFI->setObjectOffset(MBlazeFI->getGPFI(), MBlazeFI->getGPStackOffset()); +} + +unsigned MBlazeRegisterInfo::getRARegister() const { + return MBlaze::R15; +} + +unsigned MBlazeRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + return hasFP(MF) ? MBlaze::R19 : MBlaze::R1; +} + +unsigned MBlazeRegisterInfo::getEHExceptionRegister() const { + llvm_unreachable("What is the exception register"); + return 0; +} + +unsigned MBlazeRegisterInfo::getEHHandlerRegister() const { + llvm_unreachable("What is the exception handler register"); + return 0; +} + +int MBlazeRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const { + llvm_unreachable("What is the dwarf register number"); + return -1; +} + +#include "MBlazeGenRegisterInfo.inc" + diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.h b/lib/Target/MBlaze/MBlazeRegisterInfo.h new file mode 100644 index 0000000000..cde7d3967a --- /dev/null +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.h @@ -0,0 +1,96 @@ +//===- MBlazeRegisterInfo.h - MBlaze Register Information Impl --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the MBlaze implementation of the TargetRegisterInfo +// class. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZEREGISTERINFO_H +#define MBLAZEREGISTERINFO_H + +#include "MBlaze.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "MBlazeGenRegisterInfo.h.inc" + +namespace llvm { +class MBlazeSubtarget; +class TargetInstrInfo; +class Type; + +namespace MBlaze { + /// SubregIndex - The index of various sized subregister classes. Note that + /// these indices must be kept in sync with the class indices in the + /// MBlazeRegisterInfo.td file. + enum SubregIndex { + SUBREG_FPEVEN = 1, SUBREG_FPODD = 2 + }; +} + +struct MBlazeRegisterInfo : public MBlazeGenRegisterInfo { + const MBlazeSubtarget &Subtarget; + const TargetInstrInfo &TII; + + MBlazeRegisterInfo(const MBlazeSubtarget &Subtarget, + const TargetInstrInfo &tii); + + /// getRegisterNumbering - Given the enum value for some register, e.g. + /// MBlaze::RA, return the number that it corresponds to (e.g. 31). + static unsigned getRegisterNumbering(unsigned RegEnum); + static unsigned getRegisterFromNumbering(unsigned RegEnum); + + /// Get PIC indirect call register + static unsigned getPICCallReg(); + + /// Adjust the MBlaze stack frame. + void adjustMBlazeStackFrame(MachineFunction &MF) const; + + /// Code Generation virtual methods... + const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; + + const TargetRegisterClass* const* + getCalleeSavedRegClasses(const MachineFunction* MF = 0) const; + + BitVector getReservedRegs(const MachineFunction &MF) const; + + bool hasFP(const MachineFunction &MF) const; + + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const; + + /// Stack Frame Processing Methods + unsigned eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, int *Value = NULL, + RegScavenger *RS = NULL) const; + + void processFunctionBeforeFrameFinalized(MachineFunction &MF) const; + + void emitPrologue(MachineFunction &MF) const; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const; + + /// Debug information queries. + unsigned getRARegister() const; + unsigned getFrameRegister(const MachineFunction &MF) const; + + /// Exception handling queries. + unsigned getEHExceptionRegister() const; + unsigned getEHHandlerRegister() const; + + /// targetHandlesStackFrameRounding - Returns true if the target is + /// responsible for rounding up the stack frame (probably at emitPrologue + /// time). + bool targetHandlesStackFrameRounding() const { return true; } + + int getDwarfRegNum(unsigned RegNum, bool isEH) const; +}; + +} // end namespace llvm + +#endif diff --git a/lib/Target/MBlaze/MBlazeRegisterInfo.td b/lib/Target/MBlaze/MBlazeRegisterInfo.td new file mode 100644 index 0000000000..96a5c98019 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeRegisterInfo.td @@ -0,0 +1,186 @@ +//===- MBlazeRegisterInfo.td - MBlaze Register defs -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Declarations that describe the MicroBlaze register file +//===----------------------------------------------------------------------===// + +// We have banks of 32 registers each. +class MBlazeReg : Register { + field bits<5> Num; + let Namespace = "MBlaze"; +} + +class MBlazeRegWithSubRegs subregs> + : RegisterWithSubRegs { + field bits<5> Num; + let Namespace = "MBlaze"; +} + +// MBlaze CPU Registers +class MBlazeGPRReg num, string n> : MBlazeReg { + let Num = num; +} + +// MBlaze 32-bit (aliased) FPU Registers +class FPR num, string n, list subregs> + : MBlazeRegWithSubRegs { + let Num = num; +} + +//===----------------------------------------------------------------------===// +// Registers +//===----------------------------------------------------------------------===// + +let Namespace = "MBlaze" in { + + // General Purpose Registers + def R0 : MBlazeGPRReg< 0, "r0">, DwarfRegNum<[0]>; + def R1 : MBlazeGPRReg< 1, "r1">, DwarfRegNum<[1]>; + def R2 : MBlazeGPRReg< 2, "r2">, DwarfRegNum<[2]>; + def R3 : MBlazeGPRReg< 3, "r3">, DwarfRegNum<[3]>; + def R4 : MBlazeGPRReg< 4, "r4">, DwarfRegNum<[5]>; + def R5 : MBlazeGPRReg< 5, "r5">, DwarfRegNum<[5]>; + def R6 : MBlazeGPRReg< 6, "r6">, DwarfRegNum<[6]>; + def R7 : MBlazeGPRReg< 7, "r7">, DwarfRegNum<[7]>; + def R8 : MBlazeGPRReg< 8, "r8">, DwarfRegNum<[8]>; + def R9 : MBlazeGPRReg< 9, "r9">, DwarfRegNum<[9]>; + def R10 : MBlazeGPRReg< 10, "r10">, DwarfRegNum<[10]>; + def R11 : MBlazeGPRReg< 11, "r11">, DwarfRegNum<[11]>; + def R12 : MBlazeGPRReg< 12, "r12">, DwarfRegNum<[12]>; + def R13 : MBlazeGPRReg< 13, "r13">, DwarfRegNum<[13]>; + def R14 : MBlazeGPRReg< 14, "r14">, DwarfRegNum<[14]>; + def R15 : MBlazeGPRReg< 15, "r15">, DwarfRegNum<[15]>; + def R16 : MBlazeGPRReg< 16, "r16">, DwarfRegNum<[16]>; + def R17 : MBlazeGPRReg< 17, "r17">, DwarfRegNum<[17]>; + def R18 : MBlazeGPRReg< 18, "r18">, DwarfRegNum<[18]>; + def R19 : MBlazeGPRReg< 19, "r19">, DwarfRegNum<[19]>; + def R20 : MBlazeGPRReg< 20, "r20">, DwarfRegNum<[20]>; + def R21 : MBlazeGPRReg< 21, "r21">, DwarfRegNum<[21]>; + def R22 : MBlazeGPRReg< 22, "r22">, DwarfRegNum<[22]>; + def R23 : MBlazeGPRReg< 23, "r23">, DwarfRegNum<[23]>; + def R24 : MBlazeGPRReg< 24, "r24">, DwarfRegNum<[24]>; + def R25 : MBlazeGPRReg< 25, "r25">, DwarfRegNum<[25]>; + def R26 : MBlazeGPRReg< 26, "r26">, DwarfRegNum<[26]>; + def R27 : MBlazeGPRReg< 27, "r27">, DwarfRegNum<[27]>; + def R28 : MBlazeGPRReg< 28, "r28">, DwarfRegNum<[28]>; + def R29 : MBlazeGPRReg< 29, "r29">, DwarfRegNum<[29]>; + def R30 : MBlazeGPRReg< 30, "r30">, DwarfRegNum<[30]>; + def R31 : MBlazeGPRReg< 31, "r31">, DwarfRegNum<[31]>; + + /// MBlaze Single point precision FPU Registers + def F0 : FPR< 0, "r0", [R0]>, DwarfRegNum<[32]>; + def F1 : FPR< 1, "r1", [R1]>, DwarfRegNum<[33]>; + def F2 : FPR< 2, "r2", [R2]>, DwarfRegNum<[34]>; + def F3 : FPR< 3, "r3", [R3]>, DwarfRegNum<[35]>; + def F4 : FPR< 4, "r4", [R4]>, DwarfRegNum<[36]>; + def F5 : FPR< 5, "r5", [R5]>, DwarfRegNum<[37]>; + def F6 : FPR< 6, "r6", [R6]>, DwarfRegNum<[38]>; + def F7 : FPR< 7, "r7", [R7]>, DwarfRegNum<[39]>; + def F8 : FPR< 8, "r8", [R8]>, DwarfRegNum<[40]>; + def F9 : FPR< 9, "r9", [R9]>, DwarfRegNum<[41]>; + def F10 : FPR<10, "r10", [R10]>, DwarfRegNum<[42]>; + def F11 : FPR<11, "r11", [R11]>, DwarfRegNum<[43]>; + def F12 : FPR<12, "r12", [R12]>, DwarfRegNum<[44]>; + def F13 : FPR<13, "r13", [R13]>, DwarfRegNum<[45]>; + def F14 : FPR<14, "r14", [R14]>, DwarfRegNum<[46]>; + def F15 : FPR<15, "r15", [R15]>, DwarfRegNum<[47]>; + def F16 : FPR<16, "r16", [R16]>, DwarfRegNum<[48]>; + def F17 : FPR<17, "r17", [R17]>, DwarfRegNum<[49]>; + def F18 : FPR<18, "r18", [R18]>, DwarfRegNum<[50]>; + def F19 : FPR<19, "r19", [R19]>, DwarfRegNum<[51]>; + def F20 : FPR<20, "r20", [R20]>, DwarfRegNum<[52]>; + def F21 : FPR<21, "r21", [R21]>, DwarfRegNum<[53]>; + def F22 : FPR<22, "r22", [R22]>, DwarfRegNum<[54]>; + def F23 : FPR<23, "r23", [R23]>, DwarfRegNum<[55]>; + def F24 : FPR<24, "r24", [R24]>, DwarfRegNum<[56]>; + def F25 : FPR<25, "r25", [R25]>, DwarfRegNum<[57]>; + def F26 : FPR<26, "r26", [R26]>, DwarfRegNum<[58]>; + def F27 : FPR<27, "r27", [R27]>, DwarfRegNum<[59]>; + def F28 : FPR<28, "r28", [R28]>, DwarfRegNum<[60]>; + def F29 : FPR<29, "r29", [R29]>, DwarfRegNum<[61]>; + def F30 : FPR<30, "r30", [R30]>, DwarfRegNum<[62]>; + def F31 : FPR<31, "r31", [R31]>, DwarfRegNum<[63]>; +} + +//===----------------------------------------------------------------------===// +// Register Classes +//===----------------------------------------------------------------------===// + +def CPURegs : RegisterClass<"MBlaze", [i32], 32, + [ + // Return Values and Arguments + R3, R4, R5, R6, R7, R8, R9, R10, + + // Not preserved across procedure calls + R11, R12, + + // Callee save + R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, + + // Reserved + R0, // Always zero + R1, // The stack pointer + R2, // Read-only small data area anchor + R13, // Read-write small data area anchor + R14, // Return address for interrupts + R15, // Return address for sub-routines + R16, // Return address for trap + R17, // Return address for exceptions + R18, // Reserved for assembler + R19 // The frame-pointer + ]> +{ + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + CPURegsClass::iterator + CPURegsClass::allocation_order_end(const MachineFunction &MF) const { + // The last 10 registers on the list above are reserved + return end()-10; + } + }]; +} + +def FGR32 : RegisterClass<"MBlaze", [f32], 32, + [ + // Return Values and Arguments + F3, F4, F5, F6, F7, F8, F9, F10, + + // Not preserved across procedure calls + F11, F12, + + // Callee save + F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30, F31, + + // Reserved + F0, // Always zero + F1, // The stack pointer + F2, // Read-only small data area anchor + F13, // Read-write small data area anchor + F14, // Return address for interrupts + F15, // Return address for sub-routines + F16, // Return address for trap + F17, // Return address for exceptions + F18, // Reserved for assembler + F19 // The frame pointer + ]> +{ + let MethodProtos = [{ + iterator allocation_order_end(const MachineFunction &MF) const; + }]; + let MethodBodies = [{ + FGR32Class::iterator + FGR32Class::allocation_order_end(const MachineFunction &MF) const { + // The last 10 registers on the list above are reserved + return end()-10; + } + }]; +} diff --git a/lib/Target/MBlaze/MBlazeSchedule.td b/lib/Target/MBlaze/MBlazeSchedule.td new file mode 100644 index 0000000000..6a94491db4 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeSchedule.td @@ -0,0 +1,63 @@ +//===- MBlazeSchedule.td - MBlaze Scheduling Definitions --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Functional units across MBlaze chips sets. Based on GCC/MBlaze backend files. +//===----------------------------------------------------------------------===// +def ALU : FuncUnit; +def IMULDIV : FuncUnit; + +//===----------------------------------------------------------------------===// +// Instruction Itinerary classes used for MBlaze +//===----------------------------------------------------------------------===// +def IIAlu : InstrItinClass; +def IILoad : InstrItinClass; +def IIStore : InstrItinClass; +def IIXfer : InstrItinClass; +def IIBranch : InstrItinClass; +def IIHiLo : InstrItinClass; +def IIImul : InstrItinClass; +def IIIdiv : InstrItinClass; +def IIFcvt : InstrItinClass; +def IIFmove : InstrItinClass; +def IIFcmp : InstrItinClass; +def IIFadd : InstrItinClass; +def IIFmulSingle : InstrItinClass; +def IIFmulDouble : InstrItinClass; +def IIFdivSingle : InstrItinClass; +def IIFdivDouble : InstrItinClass; +def IIFsqrtSingle : InstrItinClass; +def IIFsqrtDouble : InstrItinClass; +def IIFrecipFsqrtStep : InstrItinClass; +def IIPseudo : InstrItinClass; + +//===----------------------------------------------------------------------===// +// MBlaze Generic instruction itineraries. +//===----------------------------------------------------------------------===// +def MBlazeGenericItineraries : ProcessorItineraries<[ + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]>, + InstrItinData]> +]>; diff --git a/lib/Target/MBlaze/MBlazeSubtarget.cpp b/lib/Target/MBlaze/MBlazeSubtarget.cpp new file mode 100644 index 0000000000..3440521568 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeSubtarget.cpp @@ -0,0 +1,31 @@ +//===- MBlazeSubtarget.cpp - MBlaze Subtarget Information -------*- 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 MBlaze specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeSubtarget.h" +#include "MBlaze.h" +#include "MBlazeGenSubtarget.inc" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, const std::string &FS): + HasPipe3(false), HasBarrel(false), HasDiv(false), HasMul(false), + HasFSL(false), HasEFSL(false), HasMSRSet(false), HasException(false), + HasPatCmp(false), HasFPU(false), HasESR(false), HasPVR(false), + HasMul64(false), HasSqrt(false), HasMMU(false) +{ + std::string CPU = "v400"; + MBlazeArchVersion = V400; + + // Parse features string. + ParseSubtargetFeatures(FS, CPU); +} diff --git a/lib/Target/MBlaze/MBlazeSubtarget.h b/lib/Target/MBlaze/MBlazeSubtarget.h new file mode 100644 index 0000000000..bebb3f773e --- /dev/null +++ b/lib/Target/MBlaze/MBlazeSubtarget.h @@ -0,0 +1,79 @@ +//=====-- MBlazeSubtarget.h - Define Subtarget for the MBlaze -*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MBlaze specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZESUBTARGET_H +#define MBLAZESUBTARGET_H + +#include "llvm/Target/TargetSubtarget.h" +#include "llvm/Target/TargetMachine.h" + +#include + +namespace llvm { + +class MBlazeSubtarget : public TargetSubtarget { + +protected: + + enum MBlazeArchEnum { + V400, V500, V600, V700, V710 + }; + + // MBlaze architecture version + MBlazeArchEnum MBlazeArchVersion; + + bool HasPipe3; + bool HasBarrel; + bool HasDiv; + bool HasMul; + bool HasFSL; + bool HasEFSL; + bool HasMSRSet; + bool HasException; + bool HasPatCmp; + bool HasFPU; + bool HasESR; + bool HasPVR; + bool HasMul64; + bool HasSqrt; + bool HasMMU; + + InstrItineraryData InstrItins; + +public: + + /// This constructor initializes the data members to match that + /// of the specified triple. + MBlazeSubtarget(const std::string &TT, const std::string &FS); + + /// ParseSubtargetFeatures - Parses features string setting specified + /// subtarget options. Definition of function is auto generated by tblgen. + std::string ParseSubtargetFeatures(const std::string &FS, + const std::string &CPU); + + bool hasFPU() const { return HasFPU; } + bool hasSqrt() const { return HasSqrt; } + bool hasMul() const { return HasMul; } + bool hasMul64() const { return HasMul64; } + bool hasDiv() const { return HasDiv; } + bool hasBarrel() const { return HasBarrel; } + + bool isV400() const { return MBlazeArchVersion == V400; } + bool isV500() const { return MBlazeArchVersion == V500; } + bool isV600() const { return MBlazeArchVersion == V600; } + bool isV700() const { return MBlazeArchVersion == V700; } + bool isV710() const { return MBlazeArchVersion == V710; } +}; +} // End llvm namespace + +#endif diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.cpp b/lib/Target/MBlaze/MBlazeTargetMachine.cpp new file mode 100644 index 0000000000..9eba2b3c47 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeTargetMachine.cpp @@ -0,0 +1,66 @@ +//===-- MBlazeTargetMachine.cpp - Define TargetMachine for MBlaze ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implements the info about MBlaze target spec. +// +//===----------------------------------------------------------------------===// + +#include "MBlaze.h" +#include "MBlazeMCAsmInfo.h" +#include "MBlazeTargetMachine.h" +#include "llvm/PassManager.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +extern "C" void LLVMInitializeMBlazeTarget() { + // Register the target. + RegisterTargetMachine X(TheMBlazeTarget); + RegisterAsmInfo A(TheMBlazeTarget); +} + +// DataLayout --> Big-endian, 32-bit pointer/ABI/alignment +// The stack is always 8 byte aligned +// On function prologue, the stack is created by decrementing +// its pointer. Once decremented, all references are done with positive +// offset from the stack/frame pointer, using StackGrowsUp enables +// an easier handling. +MBlazeTargetMachine:: +MBlazeTargetMachine(const Target &T, const std::string &TT, + const std::string &FS): + LLVMTargetMachine(T, TT), + Subtarget(TT, FS), + DataLayout("E-p:32:32-i8:8:8-i16:16:16-i64:32:32-" + "f64:32:32-v64:32:32-v128:32:32-n32"), + InstrInfo(*this), + FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0), + TLInfo(*this) { + if (getRelocationModel() == Reloc::Default) { + setRelocationModel(Reloc::Static); + } + + if (getCodeModel() == CodeModel::Default) + setCodeModel(CodeModel::Small); +} + +// Install an instruction selector pass using +// the ISelDag to gen MBlaze code. +bool MBlazeTargetMachine:: +addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { + PM.add(createMBlazeISelDag(*this)); + return false; +} + +// Implemented by targets that want to run passes immediately before +// machine code is emitted. return true if -print-machineinstrs should +// print out the code after the passes. +bool MBlazeTargetMachine:: +addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { + PM.add(createMBlazeDelaySlotFillerPass(*this)); + return true; +} diff --git a/lib/Target/MBlaze/MBlazeTargetMachine.h b/lib/Target/MBlaze/MBlazeTargetMachine.h new file mode 100644 index 0000000000..85c975cae9 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeTargetMachine.h @@ -0,0 +1,69 @@ +//===-- MBlazeTargetMachine.h - Define TargetMachine for MBlaze --- C++ ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MBlaze specific subclass of TargetMachine. +// +//===----------------------------------------------------------------------===// + +#ifndef MBLAZE_TARGETMACHINE_H +#define MBLAZE_TARGETMACHINE_H + +#include "MBlazeSubtarget.h" +#include "MBlazeInstrInfo.h" +#include "MBlazeISelLowering.h" +#include "MBlazeIntrinsicInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameInfo.h" + +namespace llvm { + class formatted_raw_ostream; + + class MBlazeTargetMachine : public LLVMTargetMachine { + MBlazeSubtarget Subtarget; + const TargetData DataLayout; // Calculates type size & alignment + MBlazeInstrInfo InstrInfo; + TargetFrameInfo FrameInfo; + MBlazeTargetLowering TLInfo; + MBlazeIntrinsicInfo IntrinsicInfo; + public: + MBlazeTargetMachine(const Target &T, const std::string &TT, + const std::string &FS); + + virtual const MBlazeInstrInfo *getInstrInfo() const + { return &InstrInfo; } + + virtual const TargetFrameInfo *getFrameInfo() const + { return &FrameInfo; } + + virtual const MBlazeSubtarget *getSubtargetImpl() const + { return &Subtarget; } + + virtual const TargetData *getTargetData() const + { return &DataLayout;} + + virtual const MBlazeRegisterInfo *getRegisterInfo() const + { return &InstrInfo.getRegisterInfo(); } + + virtual MBlazeTargetLowering *getTargetLowering() const + { return const_cast(&TLInfo); } + + const TargetIntrinsicInfo *getIntrinsicInfo() const + { return &IntrinsicInfo; } + + // Pass Pipeline Configuration + virtual bool addInstSelector(PassManagerBase &PM, + CodeGenOpt::Level OptLevel); + + virtual bool addPreEmitPass(PassManagerBase &PM, + CodeGenOpt::Level OptLevel); + }; +} // End llvm namespace + +#endif diff --git a/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp b/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp new file mode 100644 index 0000000000..79c9494c4d --- /dev/null +++ b/lib/Target/MBlaze/MBlazeTargetObjectFile.cpp @@ -0,0 +1,88 @@ +//===-- MBlazeTargetObjectFile.cpp - MBlaze object files ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MBlazeTargetObjectFile.h" +#include "MBlazeSubtarget.h" +#include "llvm/DerivedTypes.h" +#include "llvm/GlobalVariable.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Support/CommandLine.h" +using namespace llvm; + +void MBlazeTargetObjectFile:: +Initialize(MCContext &Ctx, const TargetMachine &TM) { + TargetLoweringObjectFileELF::Initialize(Ctx, TM); + + SmallDataSection = + getELFSection(".sdata", MCSectionELF::SHT_PROGBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getDataRel()); + + SmallBSSSection = + getELFSection(".sbss", MCSectionELF::SHT_NOBITS, + MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, + SectionKind::getBSS()); + +} + +// A address must be loaded from a small section if its size is less than the +// small section size threshold. Data in this section must be addressed using +// gp_rel operator. +static bool IsInSmallSection(uint64_t Size) { + return Size > 0 && Size <= 8; +} + +bool MBlazeTargetObjectFile:: +IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM) const { + if (GV->isDeclaration() || GV->hasAvailableExternallyLinkage()) + return false; + + return IsGlobalInSmallSection(GV, TM, getKindForGlobal(GV, TM)); +} + +/// IsGlobalInSmallSection - Return true if this global address should be +/// placed into small data/bss section. +bool MBlazeTargetObjectFile:: +IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, + SectionKind Kind) const { + // Only global variables, not functions. + const GlobalVariable *GVA = dyn_cast(GV); + if (!GVA) + return false; + + // We can only do this for datarel or BSS objects for now. + if (!Kind.isBSS() && !Kind.isDataRel()) + return false; + + // If this is a internal constant string, there is a special + // section for it, but not in small data/bss. + if (Kind.isMergeable1ByteCString()) + return false; + + const Type *Ty = GV->getType()->getElementType(); + return IsInSmallSection(TM.getTargetData()->getTypeAllocSize(Ty)); +} + +const MCSection *MBlazeTargetObjectFile:: +SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const { + // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" + // sections? + + // Handle Small Section classification here. + if (Kind.isBSS() && IsGlobalInSmallSection(GV, TM, Kind)) + return SmallBSSSection; + if (Kind.isDataNoRel() && IsGlobalInSmallSection(GV, TM, Kind)) + return SmallDataSection; + + // Otherwise, we work the same as ELF. + return TargetLoweringObjectFileELF::SelectSectionForGlobal(GV, Kind, Mang,TM); +} diff --git a/lib/Target/MBlaze/MBlazeTargetObjectFile.h b/lib/Target/MBlaze/MBlazeTargetObjectFile.h new file mode 100644 index 0000000000..20e77026c6 --- /dev/null +++ b/lib/Target/MBlaze/MBlazeTargetObjectFile.h @@ -0,0 +1,41 @@ +//===-- llvm/Target/MBlazeTargetObjectFile.h - MBlaze Obj. Info -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_MBLAZE_TARGETOBJECTFILE_H +#define LLVM_TARGET_MBLAZE_TARGETOBJECTFILE_H + +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" + +namespace llvm { + + class MBlazeTargetObjectFile : public TargetLoweringObjectFileELF { + const MCSection *SmallDataSection; + const MCSection *SmallBSSSection; + public: + + void Initialize(MCContext &Ctx, const TargetMachine &TM); + + + /// IsGlobalInSmallSection - Return true if this global address should be + /// placed into small data/bss section. + bool IsGlobalInSmallSection(const GlobalValue *GV, + const TargetMachine &TM, + SectionKind Kind) const; + + bool IsGlobalInSmallSection(const GlobalValue *GV, + const TargetMachine &TM) const; + + const MCSection *SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, + Mangler *Mang, + const TargetMachine &TM) const; + }; +} // end namespace llvm + +#endif diff --git a/lib/Target/MBlaze/Makefile b/lib/Target/MBlaze/Makefile new file mode 100644 index 0000000000..19e508c532 --- /dev/null +++ b/lib/Target/MBlaze/Makefile @@ -0,0 +1,23 @@ +##===- lib/Target/MBlaze/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMMBlazeCodeGen +TARGET = MBlaze + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = MBlazeGenRegisterInfo.h.inc MBlazeGenRegisterNames.inc \ + MBlazeGenRegisterInfo.inc MBlazeGenInstrNames.inc \ + MBlazeGenInstrInfo.inc MBlazeGenAsmWriter.inc \ + MBlazeGenDAGISel.inc MBlazeGenCallingConv.inc \ + MBlazeGenSubtarget.inc MBlazeGenIntrinsics.inc + +DIRS = AsmPrinter TargetInfo + +include $(LEVEL)/Makefile.common + diff --git a/lib/Target/MBlaze/TargetInfo/CMakeLists.txt b/lib/Target/MBlaze/TargetInfo/CMakeLists.txt new file mode 100644 index 0000000000..5afb14d09a --- /dev/null +++ b/lib/Target/MBlaze/TargetInfo/CMakeLists.txt @@ -0,0 +1,7 @@ +include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) + +add_llvm_library(LLVMMBlazeInfo + MBlazeTargetInfo.cpp + ) + +add_dependencies(LLVMMBlazeInfo MBlazeCodeGenTable_gen) diff --git a/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp b/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp new file mode 100644 index 0000000000..16e01dbfde --- /dev/null +++ b/lib/Target/MBlaze/TargetInfo/MBlazeTargetInfo.cpp @@ -0,0 +1,19 @@ +//===-- MBlazeTargetInfo.cpp - MBlaze Target Implementation ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MBlaze.h" +#include "llvm/Module.h" +#include "llvm/Target/TargetRegistry.h" +using namespace llvm; + +Target llvm::TheMBlazeTarget; + +extern "C" void LLVMInitializeMBlazeTargetInfo() { + RegisterTarget X(TheMBlazeTarget, "mblaze", "MBlaze"); +} diff --git a/lib/Target/MBlaze/TargetInfo/Makefile b/lib/Target/MBlaze/TargetInfo/Makefile new file mode 100644 index 0000000000..fb7ea118a6 --- /dev/null +++ b/lib/Target/MBlaze/TargetInfo/Makefile @@ -0,0 +1,15 @@ +##===- lib/Target/MBlaze/TargetInfo/Makefile ---------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = LLVMMBlazeInfo + +# Hack: we need to include 'main' target directory to grab private headers +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp index a96ee49a8d..ac41cc8d03 100644 --- a/lib/Target/MSIL/MSILWriter.cpp +++ b/lib/Target/MSIL/MSILWriter.cpp @@ -38,7 +38,8 @@ namespace llvm { virtual bool addPassesToEmitWholeFile(PassManager &PM, formatted_raw_ostream &Out, CodeGenFileType FileType, - CodeGenOpt::Level OptLevel); + CodeGenOpt::Level OptLevel, + bool DisableVerify); virtual const TargetData *getTargetData() const { return 0; } }; @@ -57,7 +58,7 @@ bool MSILModule::runOnModule(Module &M) { TypeSymbolTable& Table = M.getTypeSymbolTable(); std::set Types = getAnalysis().getTypes(); for (TypeSymbolTable::iterator I = Table.begin(), E = Table.end(); I!=E; ) { - if (!isa(I->second) && !isa(I->second)) + if (!I->second->isStructTy() && !I->second->isOpaqueTy()) Table.remove(I++); else { std::set::iterator T = Types.find(I->second); @@ -187,7 +188,7 @@ void MSILWriter::printModuleStartup() { break; case 1: Arg1 = F->arg_begin(); - if (Arg1->getType()->isInteger()) { + if (Arg1->getType()->isIntegerTy()) { Out << "\tldloc\targc\n"; Args = getTypeName(Arg1->getType()); BadSig = false; @@ -195,7 +196,7 @@ void MSILWriter::printModuleStartup() { break; case 2: Arg1 = Arg2 = F->arg_begin(); ++Arg2; - if (Arg1->getType()->isInteger() && + if (Arg1->getType()->isIntegerTy() && Arg2->getType()->getTypeID() == Type::PointerTyID) { Out << "\tldloc\targc\n\tldloc\targv\n"; Args = getTypeName(Arg1->getType())+","+getTypeName(Arg2->getType()); @@ -207,7 +208,7 @@ void MSILWriter::printModuleStartup() { } bool RetVoid = (F->getReturnType()->getTypeID() == Type::VoidTyID); - if (BadSig || (!F->getReturnType()->isInteger() && !RetVoid)) { + if (BadSig || (!F->getReturnType()->isIntegerTy() && !RetVoid)) { Out << "\tldc.i4.0\n"; } else { Out << "\tcall\t" << getTypeName(F->getReturnType()) << @@ -334,7 +335,7 @@ std::string MSILWriter::getPrimitiveTypeName(const Type* Ty, bool isSigned) { std::string MSILWriter::getTypeName(const Type* Ty, bool isSigned, bool isNested) { - if (Ty->isPrimitiveType() || Ty->isInteger()) + if (Ty->isPrimitiveType() || Ty->isIntegerTy()) return getPrimitiveTypeName(Ty,isSigned); // FIXME: "OpaqueType" support switch (Ty->getTypeID()) { @@ -1459,7 +1460,7 @@ void MSILWriter::printDeclarations(const TypeSymbolTable& ST) { for (std::set::const_iterator UI = UsedTypes->begin(), UE = UsedTypes->end(); UI!=UE; ++UI) { const Type* Ty = *UI; - if (isa(Ty) || isa(Ty) || isa(Ty)) + if (Ty->isArrayTy() || Ty->isVectorTy() || Ty->isStructTy()) Name = getTypeName(Ty, false, true); // Type with no need to declare. else continue; @@ -1688,7 +1689,8 @@ void MSILWriter::printExternals() { bool MSILTarget::addPassesToEmitWholeFile(PassManager &PM, formatted_raw_ostream &o, CodeGenFileType FileType, - CodeGenOpt::Level OptLevel) + CodeGenOpt::Level OptLevel, + bool DisableVerify) { if (FileType != TargetMachine::CGFT_AssemblyFile) return true; MSILWriter* Writer = new MSILWriter(o); diff --git a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp index def5fc6587..7a35eb092a 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430AsmPrinter.cpp @@ -98,12 +98,19 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum, bool isMemOp = Modifier && !strcmp(Modifier, "mem"); uint64_t Offset = MO.getOffset(); - O << (isMemOp ? '&' : '#'); + // If the global address expression is a part of displacement field with a + // register base, we should not emit any prefix symbol here, e.g. + // mov.w &foo, r1 + // vs + // mov.w glb(r1), r2 + // Otherwise (!) msp430-as will silently miscompile the output :( + if (!Modifier || strcmp(Modifier, "nohash")) + O << (isMemOp ? '&' : '#'); if (Offset) O << '(' << Offset << '+'; O << *GetGlobalValueSymbol(MO.getGlobal()); - + if (Offset) O << ')'; @@ -124,15 +131,11 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum, const MachineOperand &Disp = MI->getOperand(OpNum+1); // Print displacement first - if (!Disp.isImm()) { - printOperand(MI, OpNum+1, "mem"); - } else { - if (!Base.getReg()) - O << '&'; - - printOperand(MI, OpNum+1, "nohash"); - } + // Imm here is in fact global address - print extra modifier. + if (Disp.isImm() && !Base.getReg()) + O << '&'; + printOperand(MI, OpNum+1, "nohash"); // Print register base field if (Base.getReg()) { diff --git a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp index f6565bdec6..d7636e68a0 100644 --- a/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp +++ b/lib/Target/MSP430/AsmPrinter/MSP430InstPrinter.cpp @@ -62,21 +62,26 @@ void MSP430InstPrinter::printSrcMemOperand(const MCInst *MI, unsigned OpNo, const MCOperand &Disp = MI->getOperand(OpNo+1); // Print displacement first - if (Disp.isExpr()) { - O << '&' << *Disp.getExpr(); - } else { - assert(Disp.isImm() && "Expected immediate in displacement field"); - if (!Base.getReg()) - O << '&'; + // If the global address expression is a part of displacement field with a + // register base, we should not emit any prefix symbol here, e.g. + // mov.w &foo, r1 + // vs + // mov.w glb(r1), r2 + // Otherwise (!) msp430-as will silently miscompile the output :( + if (!Base.getReg()) + O << '&'; + + if (Disp.isExpr()) + O << *Disp.getExpr(); + else { + assert(Disp.isImm() && "Expected immediate in displacement field"); O << Disp.getImm(); } - // Print register base field - if (Base.getReg()) { + if (Base.getReg()) O << '(' << getRegisterName(Base.getReg()) << ')'; - } } void MSP430InstPrinter::printCCOperand(const MCInst *MI, unsigned OpNo) { diff --git a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp index 4eec757297..911cfcbe6d 100644 --- a/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp +++ b/lib/Target/MSP430/MSP430ISelDAGToDAG.cpp @@ -26,26 +26,12 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Target/TargetLowering.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/Statistic.h" - using namespace llvm; -#ifndef NDEBUG -static cl::opt -ViewRMWDAGs("view-msp430-rmw-dags", cl::Hidden, - cl::desc("Pop up a window to show isel dags after RMW preprocess")); -#else -static const bool ViewRMWDAGs = false; -#endif - -STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor"); - - namespace { struct MSP430ISelAddressMode { enum { @@ -123,8 +109,6 @@ namespace { Lowering(*TM.getTargetLowering()), Subtarget(*TM.getSubtargetImpl()) { } - virtual void InstructionSelect(); - virtual const char *getPassName() const { return "MSP430 DAG->DAG Pattern Instruction Selection"; } @@ -133,9 +117,6 @@ namespace { bool MatchWrapper(SDValue N, MSP430ISelAddressMode &AM); bool MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM); - bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U, - SDNode *Root) const; - virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, std::vector &OutOps); @@ -144,18 +125,12 @@ namespace { #include "MSP430GenDAGISel.inc" private: - DenseMap RMWStores; - void PreprocessForRMW(); SDNode *Select(SDNode *N); SDNode *SelectIndexedLoad(SDNode *Op); SDNode *SelectIndexedBinOp(SDNode *Op, SDValue N1, SDValue N2, unsigned Opc8, unsigned Opc16); bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Disp); - - #ifndef NDEBUG - unsigned Indent; - #endif }; } // end anonymous namespace @@ -217,10 +192,7 @@ bool MSP430DAGToDAGISel::MatchAddressBase(SDValue N, MSP430ISelAddressMode &AM) } bool MSP430DAGToDAGISel::MatchAddress(SDValue N, MSP430ISelAddressMode &AM) { - DEBUG({ - errs() << "MatchAddress: "; - AM.dump(); - }); + DEBUG(errs() << "MatchAddress: "; AM.dump()); switch (N.getOpcode()) { default: break; @@ -336,270 +308,6 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, return false; } -bool MSP430DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, - SDNode *Root) const { - if (OptLevel == CodeGenOpt::None) return false; - - /// RMW preprocessing creates the following code: - /// [Load1] - /// ^ ^ - /// / | - /// / | - /// [Load2] | - /// ^ ^ | - /// | | | - /// | \-| - /// | | - /// | [Op] - /// | ^ - /// | | - /// \ / - /// \ / - /// [Store] - /// - /// The path Store => Load2 => Load1 is via chain. Note that in general it is - /// not allowed to fold Load1 into Op (and Store) since it will creates a - /// cycle. However, this is perfectly legal for the loads moved below the - /// TokenFactor by PreprocessForRMW. Query the map Store => Load1 (created - /// during preprocessing) to determine whether it's legal to introduce such - /// "cycle" for a moment. - DenseMap::const_iterator I = RMWStores.find(Root); - if (I != RMWStores.end() && I->second == N) - return true; - - // Proceed to 'generic' cycle finder code - return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root); -} - - -/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand -/// and move load below the TokenFactor. Replace store's chain operand with -/// load's chain result. -static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load, - SDValue Store, SDValue TF) { - SmallVector Ops; - for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) - if (Load.getNode() == TF.getOperand(i).getNode()) - Ops.push_back(Load.getOperand(0)); - else - Ops.push_back(TF.getOperand(i)); - SDValue NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size()); - SDValue NewLoad = CurDAG->UpdateNodeOperands(Load, NewTF, - Load.getOperand(1), - Load.getOperand(2)); - CurDAG->UpdateNodeOperands(Store, NewLoad.getValue(1), Store.getOperand(1), - Store.getOperand(2), Store.getOperand(3)); -} - -/// MoveBelowTokenFactor2 - Replace TokenFactor operand with load's chain operand -/// and move load below the TokenFactor. Replace store's chain operand with -/// load's chain result. This a version which sinks two loads below token factor. -/// Look into PreprocessForRMW comments for explanation of transform. -static void MoveBelowTokenFactor2(SelectionDAG *CurDAG, - SDValue Load1, SDValue Load2, - SDValue Store, SDValue TF) { - SmallVector Ops; - for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) { - SDNode* N = TF.getOperand(i).getNode(); - if (Load2.getNode() == N) - Ops.push_back(Load2.getOperand(0)); - else if (Load1.getNode() != N) - Ops.push_back(TF.getOperand(i)); - } - - SDValue NewTF = SDValue(CurDAG->MorphNodeTo(TF.getNode(), - TF.getOpcode(), - TF.getNode()->getVTList(), - &Ops[0], Ops.size()), TF.getResNo()); - SDValue NewLoad2 = CurDAG->UpdateNodeOperands(Load2, NewTF, - Load2.getOperand(1), - Load2.getOperand(2)); - - SDValue NewLoad1 = CurDAG->UpdateNodeOperands(Load1, NewLoad2.getValue(1), - Load1.getOperand(1), - Load1.getOperand(2)); - - CurDAG->UpdateNodeOperands(Store, - NewLoad1.getValue(1), - Store.getOperand(1), - Store.getOperand(2), Store.getOperand(3)); -} - -/// isAllowedToSink - return true if N a load which can be moved below token -/// factor. Basically, the load should be non-volatile and has single use. -static bool isLoadAllowedToSink(SDValue N, SDValue Chain) { - if (N.getOpcode() == ISD::BIT_CONVERT) - N = N.getOperand(0); - - LoadSDNode *LD = dyn_cast(N); - if (!LD || LD->isVolatile()) - return false; - if (LD->getAddressingMode() != ISD::UNINDEXED) - return false; - - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD) - return false; - - return (N.hasOneUse() && - LD->hasNUsesOfValue(1, 1) && - LD->isOperandOf(Chain.getNode())); -} - - -/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG. -/// The chain produced by the load must only be used by the store's chain -/// operand, otherwise this may produce a cycle in the DAG. -static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address, - SDValue &Load) { - if (isLoadAllowedToSink(N, Chain) && - N.getOperand(1) == Address) { - Load = N; - return true; - } - return false; -} - -/// PreprocessForRMW - Preprocess the DAG to make instruction selection better. -/// This is only run if not in -O0 mode. -/// This allows the instruction selector to pick more read-modify-write -/// instructions. This is a common case: -/// -/// [Load chain] -/// ^ -/// | -/// [Load] -/// ^ ^ -/// | | -/// / \- -/// / | -/// [TokenFactor] [Op] -/// ^ ^ -/// | | -/// \ / -/// \ / -/// [Store] -/// -/// The fact the store's chain operand != load's chain will prevent the -/// (store (op (load))) instruction from being selected. We can transform it to: -/// -/// [Load chain] -/// ^ -/// | -/// [TokenFactor] -/// ^ -/// | -/// [Load] -/// ^ ^ -/// | | -/// | \- -/// | | -/// | [Op] -/// | ^ -/// | | -/// \ / -/// \ / -/// [Store] -/// -/// We also recognize the case where second operand of Op is load as well and -/// move it below token factor as well creating DAG as follows: -/// -/// [Load chain] -/// ^ -/// | -/// [TokenFactor] -/// ^ -/// | -/// [Load1] -/// ^ ^ -/// / | -/// / | -/// [Load2] | -/// ^ ^ | -/// | | | -/// | \-| -/// | | -/// | [Op] -/// | ^ -/// | | -/// \ / -/// \ / -/// [Store] -/// -/// This allows selection of mem-mem instructions. Yay! - -void MSP430DAGToDAGISel::PreprocessForRMW() { - for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), - E = CurDAG->allnodes_end(); I != E; ++I) { - if (!ISD::isNON_TRUNCStore(I)) - continue; - SDValue Chain = I->getOperand(0); - - if (Chain.getNode()->getOpcode() != ISD::TokenFactor) - continue; - - SDValue N1 = I->getOperand(1); - SDValue N2 = I->getOperand(2); - if ((N1.getValueType().isFloatingPoint() && - !N1.getValueType().isVector()) || - !N1.hasOneUse()) - continue; - - unsigned RModW = 0; - SDValue Load1, Load2; - unsigned Opcode = N1.getNode()->getOpcode(); - switch (Opcode) { - case ISD::ADD: - case ISD::AND: - case ISD::OR: - case ISD::XOR: - case ISD::ADDC: - case ISD::ADDE: { - SDValue N10 = N1.getOperand(0); - SDValue N11 = N1.getOperand(1); - if (isRMWLoad(N10, Chain, N2, Load1)) { - if (isLoadAllowedToSink(N11, Chain)) { - Load2 = N11; - RModW = 2; - } else - RModW = 1; - } else if (isRMWLoad(N11, Chain, N2, Load1)) { - if (isLoadAllowedToSink(N10, Chain)) { - Load2 = N10; - RModW = 2; - } else - RModW = 1; - } - break; - } - case ISD::SUB: - case ISD::SUBC: - case ISD::SUBE: { - SDValue N10 = N1.getOperand(0); - SDValue N11 = N1.getOperand(1); - if (isRMWLoad(N10, Chain, N2, Load1)) { - if (isLoadAllowedToSink(N11, Chain)) { - Load2 = N11; - RModW = 2; - } else - RModW = 1; - } - break; - } - } - - NumLoadMoved += RModW; - if (RModW == 1) - MoveBelowTokenFactor(CurDAG, Load1, SDValue(I, 0), Chain); - else if (RModW == 2) { - MoveBelowTokenFactor2(CurDAG, Load1, Load2, SDValue(I, 0), Chain); - SDNode* Store = I; - RMWStores[Store] = Load2.getNode(); - } - } -} - - static bool isValidIndexedLoad(const LoadSDNode *LD) { ISD::MemIndexedMode AM = LD->getAddressingMode(); if (AM != ISD::POST_INC || LD->getExtensionType() != ISD::NON_EXTLOAD) @@ -656,7 +364,7 @@ SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op, unsigned Opc8, unsigned Opc16) { if (N1.getOpcode() == ISD::LOAD && N1.hasOneUse() && - IsLegalAndProfitableToFold(N1.getNode(), Op, Op)) { + IsLegalToFold(N1, Op, Op)) { LoadSDNode *LD = cast(N1); if (!isValidIndexedLoad(LD)) return NULL; @@ -682,46 +390,19 @@ SDNode *MSP430DAGToDAGISel::SelectIndexedBinOp(SDNode *Op, } -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void MSP430DAGToDAGISel::InstructionSelect() { - std::string BlockName; - if (ViewRMWDAGs) - BlockName = MF->getFunction()->getNameStr() + ":" + - BB->getBasicBlock()->getNameStr(); - - PreprocessForRMW(); - - if (ViewRMWDAGs) CurDAG->viewGraph("RMW preprocessed:" + BlockName); - - DEBUG(errs() << "Selection DAG after RMW preprocessing:\n"); - DEBUG(CurDAG->dump()); - - // Codegen the basic block. - DEBUG(errs() << "===== Instruction selection begins:\n"); - DEBUG(Indent = 0); - SelectRoot(*CurDAG); - DEBUG(errs() << "===== Instruction selection ends:\n"); - - CurDAG->RemoveDeadNodes(); - RMWStores.clear(); -} - SDNode *MSP430DAGToDAGISel::Select(SDNode *Node) { DebugLoc dl = Node->getDebugLoc(); // Dump information about the Node being selected - DEBUG(errs().indent(Indent) << "Selecting: "); + DEBUG(errs() << "Selecting: "); DEBUG(Node->dump(CurDAG)); DEBUG(errs() << "\n"); - DEBUG(Indent += 2); // If we have a custom node, we already have selected! if (Node->isMachineOpcode()) { - DEBUG(errs().indent(Indent-2) << "== "; + DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); - DEBUG(Indent -= 2); return NULL; } @@ -809,13 +490,12 @@ SDNode *MSP430DAGToDAGISel::Select(SDNode *Node) { // Select the default instruction SDNode *ResNode = SelectCode(Node); - DEBUG(errs() << std::string(Indent-2, ' ') << "=> "); + DEBUG(errs() << "=> "); if (ResNode == NULL || ResNode == Node) DEBUG(Node->dump(CurDAG)); else DEBUG(ResNode->dump(CurDAG)); DEBUG(errs() << "\n"); - DEBUG(Indent -= 2); return ResNode; } diff --git a/lib/Target/MSP430/MSP430ISelLowering.cpp b/lib/Target/MSP430/MSP430ISelLowering.cpp index ef81f51229..e6c7e1ecd8 100644 --- a/lib/Target/MSP430/MSP430ISelLowering.cpp +++ b/lib/Target/MSP430/MSP430ISelLowering.cpp @@ -31,8 +31,8 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/CodeGen/ValueTypes.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -371,7 +371,8 @@ MSP430TargetLowering::LowerCCCArguments(SDValue Chain, //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, - PseudoSourceValue::getFixedStack(FI), 0)); + PseudoSourceValue::getFixedStack(FI), 0, + false, false, 0)); } } @@ -500,7 +501,7 @@ MSP430TargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, PseudoSourceValue::getStack(), - VA.getLocMemOffset())); + VA.getLocMemOffset(), false, false, 0)); } } @@ -794,18 +795,15 @@ SDValue MSP430TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { if (andCC) { // C = ~Z, thus Res = SRW & 1, no processing is required } else { - // Res = (SRW >> 1) & 1 + // Res = ~((SRW >> 1) & 1) Shift = true; + Invert = true; } break; case MSP430CC::COND_E: - if (andCC) { - // C = ~Z, thus Res = ~(SRW & 1) - } else { - // Res = ~((SRW >> 1) & 1) - Shift = true; - } - Invert = true; + Shift = true; + // C = ~Z for AND instruction, thus we can put Res = ~(SRW & 1), however, + // Res = (SRW >> 1) & 1 is 1 word shorter. break; } EVT VT = Op.getValueType(); @@ -893,13 +891,13 @@ SDValue MSP430TargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), DAG.getNode(ISD::ADD, dl, getPointerTy(), FrameAddr, Offset), - NULL, 0); + NULL, 0, false, false, 0); } // Just load the return address. SDValue RetAddrFI = getReturnAddressFrameIndex(DAG); return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), - RetAddrFI, NULL, 0); + RetAddrFI, NULL, 0, false, false, 0); } SDValue MSP430TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { @@ -911,7 +909,8 @@ SDValue MSP430TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, MSP430::FPW, VT); while (Depth--) - FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0); + FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0, + false, false, 0); return FrameAddr; } @@ -971,7 +970,7 @@ const char *MSP430TargetLowering::getTargetNodeName(unsigned Opcode) const { bool MSP430TargetLowering::isTruncateFree(const Type *Ty1, const Type *Ty2) const { - if (!Ty1->isInteger() || !Ty2->isInteger()) + if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy()) return false; return (Ty1->getPrimitiveSizeInBits() > Ty2->getPrimitiveSizeInBits()); @@ -986,7 +985,7 @@ bool MSP430TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { bool MSP430TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const { // MSP430 implicitly zero-extends 8-bit results in 16-bit registers. - return 0 && Ty1->isInteger(8) && Ty2->isInteger(16); + return 0 && Ty1->isIntegerTy(8) && Ty2->isIntegerTy(16); } bool MSP430TargetLowering::isZExtFree(EVT VT1, EVT VT2) const { diff --git a/lib/Target/MSP430/MSP430InstrInfo.td b/lib/Target/MSP430/MSP430InstrInfo.td index bb06f7bfd5..144ba26cfe 100644 --- a/lib/Target/MSP430/MSP430InstrInfo.td +++ b/lib/Target/MSP430/MSP430InstrInfo.td @@ -250,7 +250,7 @@ def MOV16ri : I16ri<0x0, [(set GR16:$dst, imm:$src)]>; } -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +let canFoldAsLoad = 1, isReMaterializable = 1 in { def MOV8rm : I8rm<0x0, (outs GR8:$dst), (ins memsrc:$src), "mov.b\t{$src, $dst}", diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index f1d4a67c81..c4746dba32 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -59,8 +59,6 @@ public: SelectionDAGISel(tm), TM(tm), Subtarget(tm.getSubtarget()) {} - virtual void InstructionSelect(); - // Pass Name virtual const char *getPassName() const { return "MIPS DAG->DAG Pattern Instruction Selection"; @@ -98,29 +96,10 @@ private: inline SDValue getI32Imm(unsigned Imm) { return CurDAG->getTargetConstant(Imm, MVT::i32); } - - - #ifndef NDEBUG - unsigned Indent; - #endif }; } -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void MipsDAGToDAGISel::InstructionSelect() { - // Codegen the basic block. - DEBUG(errs() << "===== Instruction selection begins:\n"); - DEBUG(Indent = 0); - - // Select target instructions for the DAG. - SelectRoot(*CurDAG); - - DEBUG(errs() << "===== Instruction selection ends:\n"); - - CurDAG->RemoveDeadNodes(); -} /// getGlobalBaseReg - Output the instructions required to put the /// GOT address into a register. @@ -329,17 +308,11 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { DebugLoc dl = Node->getDebugLoc(); // Dump information about the Node being selected - DEBUG(errs().indent(Indent) << "Selecting: "; - Node->dump(CurDAG); - errs() << "\n"); - DEBUG(Indent += 2); + DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); // If we have a custom node, we already have selected! if (Node->isMachineOpcode()) { - DEBUG(errs().indent(Indent-2) << "== "; - Node->dump(CurDAG); - errs() << "\n"); - DEBUG(Indent -= 2); + DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); return NULL; } @@ -547,14 +520,12 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { // Select the default instruction SDNode *ResNode = SelectCode(Node); - DEBUG(errs().indent(Indent-2) << "=> "); + DEBUG(errs() << "=> "); if (ResNode == NULL || ResNode == Node) DEBUG(Node->dump(CurDAG)); else DEBUG(ResNode->dump(CurDAG)); DEBUG(errs() << "\n"); - DEBUG(Indent -= 2); - return ResNode; } diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index d94944fb37..584b8875ee 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -510,7 +510,8 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) { SDValue GA = DAG.getTargetGlobalAddress(GV, MVT::i32, 0, MipsII::MO_GOT); SDValue ResNode = DAG.getLoad(MVT::i32, dl, - DAG.getEntryNode(), GA, NULL, 0); + DAG.getEntryNode(), GA, NULL, 0, + false, false, 0); // On functions and global targets not internal linked only // a load from got/GP is necessary for PIC to work. if (!GV->hasLocalLinkage() || isa(GV)) @@ -549,7 +550,8 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) SDValue Ops[] = { JTI }; HiPart = DAG.getNode(MipsISD::Hi, dl, DAG.getVTList(MVT::i32), Ops, 1); } else // Emit Load from Global Pointer - HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, NULL, 0); + HiPart = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), JTI, NULL, 0, + false, false, 0); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, JTI); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, HiPart, Lo); @@ -586,7 +588,7 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) SDValue CP = DAG.getTargetConstantPool(C, MVT::i32, N->getAlignment(), N->getOffset(), MipsII::MO_GOT); SDValue Load = DAG.getLoad(MVT::i32, dl, DAG.getEntryNode(), - CP, NULL, 0); + CP, NULL, 0, false, false, 0); SDValue Lo = DAG.getNode(MipsISD::Lo, dl, MVT::i32, CP); ResNode = DAG.getNode(ISD::ADD, dl, MVT::i32, Load, Lo); } @@ -601,7 +603,8 @@ SDValue MipsTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) { // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. const Value *SV = cast(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0); + return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1), SV, 0, + false, false, 0); } //===----------------------------------------------------------------------===// @@ -859,7 +862,8 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // emit ISD::STORE whichs stores the // parameter value to a stack Location - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0)); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + false, false, 0)); } // Transform all store nodes into one single node because all store @@ -933,7 +937,8 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Reload GP value. FI = MipsFI->getGPFI(); SDValue FIN = DAG.getFrameIndex(FI,getPointerTy()); - SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, NULL, 0); + SDValue GPLoad = DAG.getLoad(MVT::i32, dl, Chain, FIN, NULL, 0, + false, false, 0); Chain = GPLoad.getValue(1); Chain = DAG.getCopyToReg(Chain, dl, DAG.getRegister(Mips::GP, MVT::i32), GPLoad, SDValue(0,0)); @@ -1097,7 +1102,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, // Create load nodes to retrieve arguments from the stack SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); - InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0)); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0, + false, false, 0)); } } @@ -1132,7 +1138,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, int FI = MFI->CreateFixedObject(4, 0, true, false); MipsFI->recordStoreVarArgsFI(FI, -(4+(StackLoc*4))); SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy()); - OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0)); + OutChains.push_back(DAG.getStore(Chain, dl, ArgValue, PtrOff, NULL, 0, + false, false, 0)); // Record the frame index of the first variable argument // which is a value necessary to VASTART. diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index e67bcbfc17..cef3697fa8 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -120,7 +120,7 @@ def immZExt5 : PatLeaf<(imm), [{ // Mips Address Mode! SDNode frameindex could possibily be a match // since load and store instructions from stack used it. -def addr : ComplexPattern; +def addr : ComplexPattern; //===----------------------------------------------------------------------===// // Instructions specific format @@ -300,9 +300,8 @@ class JumpFR op, bits<6> func, string instr_asm>: // Jump and Link (Call) let isCall=1, hasDelaySlot=1, // All calls clobber the non-callee saved registers... - Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, - K0, K1, F0, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, - F14, F15, F16, F17, F18, F19], Uses = [GP] in { + Defs = [AT, V0, V1, A0, A1, A2, A3, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, + K0, K1, D0, D1, D2, D3, D4, D5, D6, D7, D8, D9], Uses = [GP] in { class JumpLink op, string instr_asm>: FJ< op, (outs), @@ -593,8 +592,8 @@ def : Pat<(MipsJmpLink (i32 tglobaladdr:$dst)), (JAL tglobaladdr:$dst)>; def : Pat<(MipsJmpLink (i32 texternalsym:$dst)), (JAL texternalsym:$dst)>; -def : Pat<(MipsJmpLink CPURegs:$dst), - (JALR CPURegs:$dst)>; +//def : Pat<(MipsJmpLink CPURegs:$dst), +// (JALR CPURegs:$dst)>; // hi/lo relocs def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; diff --git a/lib/Target/Mips/MipsTargetObjectFile.h b/lib/Target/Mips/MipsTargetObjectFile.h index 32e0436f0c..237b1602cf 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.h +++ b/lib/Target/Mips/MipsTargetObjectFile.h @@ -10,7 +10,7 @@ #ifndef LLVM_TARGET_MIPS_TARGETOBJECTFILE_H #define LLVM_TARGET_MIPS_TARGETOBJECTFILE_H -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" namespace llvm { diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp index 72f7c16c63..44a6cc0acb 100644 --- a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp +++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp @@ -106,8 +106,9 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { DbgInfo.BeginFunction(MF); // Now emit the instructions of function in its code section. - const MCSection *fCodeSection - = getObjFileLowering().SectionForCode(CurrentFnSym->getName()); + const MCSection *fCodeSection = + getObjFileLowering().SectionForCode(CurrentFnSym->getName(), + PAN::isISR(F->getSection())); // Start the Code Section. O << "\n"; @@ -157,6 +158,7 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { // printOperand - print operand of insn. void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { const MachineOperand &MO = MI->getOperand(opNum); + const Function *F = MI->getParent()->getParent()->getFunction(); switch (MO.getType()) { case MachineOperand::MO_Register: @@ -189,19 +191,18 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { } case MachineOperand::MO_ExternalSymbol: { const char *Sname = MO.getSymbolName(); + std::string Printname = Sname; - // If its a libcall name, record it to decls section. - if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) - LibcallDecls.push_back(Sname); - - // Record a call to intrinsic to print the extern declaration for it. - std::string Sym = Sname; - if (PAN::isMemIntrinsic(Sym)) { - Sym = PAN::addPrefix(Sym); - LibcallDecls.push_back(createESName(Sym)); + // Intrinsic stuff needs to be renamed if we are printing IL fn. + if (PAN::isIntrinsicStuff(Printname)) { + if (PAN::isISR(F->getSection())) { + Printname = PAN::Rename(Sname); + } + // Record these decls, we need to print them in asm as extern. + LibcallDecls.push_back(createESName(Printname)); } - O << Sym; + O << Printname; break; } case MachineOperand::MO_MachineBasicBlock: @@ -247,8 +248,6 @@ void PIC16AsmPrinter::printLibcallDecls() { for (std::list::const_iterator I = LibcallDecls.begin(); I != LibcallDecls.end(); I++) { O << MAI->getExternDirective() << *I << "\n"; - O << MAI->getExternDirective() << PAN::getArgsLabel(*I) << "\n"; - O << MAI->getExternDirective() << PAN::getRetvalLabel(*I) << "\n"; } O << MAI->getCommentString() << "External decls for libcalls - END." <<"\n"; } diff --git a/lib/Target/PIC16/PIC16ABINames.h b/lib/Target/PIC16/PIC16ABINames.h index e18ddf158e..4c1a8da286 100644 --- a/lib/Target/PIC16/PIC16ABINames.h +++ b/lib/Target/PIC16/PIC16ABINames.h @@ -178,18 +178,21 @@ namespace llvm { return Func1 + tag; } + // Get the retval label for the given function. static std::string getRetvalLabel(const std::string &Func) { std::string Func1 = addPrefix(Func); std::string tag = getTagName(RET_LABEL); return Func1 + tag; } + // Get the argument label for the given function. static std::string getArgsLabel(const std::string &Func) { std::string Func1 = addPrefix(Func); std::string tag = getTagName(ARGS_LABEL); return Func1 + tag; } + // Get the tempdata label for the given function. static std::string getTempdataLabel(const std::string &Func) { std::string Func1 = addPrefix(Func); std::string tag = getTagName(TEMPS_LABEL); @@ -263,6 +266,7 @@ namespace llvm { return false; } + inline static bool isMemIntrinsic (const std::string &Name) { if (Name.compare("@memcpy") == 0 || Name.compare("@memset") == 0 || Name.compare("@memmove") == 0) { @@ -272,6 +276,41 @@ namespace llvm { return false; } + // Currently names of libcalls are assigned during TargetLowering + // object construction. There is no provision to change the when the + // code for a function IL function being generated. + // So we have to change these names while printing assembly. + // We need to do that mainly for names related to intrinsics. This + // function returns true if a name needs to be cloned. + inline static bool isIntrinsicStuff(const std::string &Name) { + // Return true if the name contains LIBCALL marker, or a MemIntrinisc. + // these are mainly ARGS_LABEL, RET_LABEL, and the LIBCALL name itself. + if ((Name.find(getTagName(LIBCALL)) != std::string::npos) + || isMemIntrinsic(Name)) + return true; + + return false; + } + + // Rename the name for IL. + inline static std::string Rename(const std::string &Name) { + std::string Newname; + // If its a label (LIBCALL+Func+LABEL), change it to + // (LIBCALL+Func+IL+LABEL). + TAGS id = getSymbolTag(Name); + if (id == ARGS_LABEL || id == RET_LABEL) { + std::size_t pos = Name.find(getTagName(id)); + Newname = Name.substr(0, pos) + ".IL" + getTagName(id); + return Newname; + } + + // Else, just append IL to name. + return Name + ".IL"; + } + + + + inline static bool isLocalToFunc (std::string &Func, std::string &Var) { if (! isLocalName(Var)) return false; @@ -325,6 +364,35 @@ namespace llvm { return o.str(); } + + // Return true if the current function is an ISR + inline static bool isISR(const std::string SectName) { + if (SectName.find("interrupt") != std::string::npos) + return true; + + return false; + } + + // Return the address for ISR starts in rom. + inline static std::string getISRAddr(void) { + return "0x4"; + } + + // Returns the name of clone of a function. + static std::string getCloneFnName(const std::string &Func) { + return (Func + ".IL"); + } + + // Returns the name of clone of a variable. + static std::string getCloneVarName(const std::string &Fn, + const std::string &Var) { + std::string cloneVarName = Var; + // These vars are named like fun.auto.var. + // Just replace the function name, with clone function name. + std::string cloneFnName = getCloneFnName(Fn); + cloneVarName.replace(cloneVarName.find(Fn), Fn.length(), cloneFnName); + return cloneVarName; + } }; // class PAN. } // end namespace llvm; diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp index c517b1bff6..877e4ffc6d 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.cpp +++ b/lib/Target/PIC16/PIC16DebugInfo.cpp @@ -419,7 +419,7 @@ void PIC16DbgInfo::EmitAuxEntry(const std::string VarName, int Aux[], int Num, if (TagName != "") O << ", " << TagName; for (int i = 0; iRemoveDeadNodes(); -} - /// Select - Select instructions not customized! Used for /// expanded, promoted and normal instructions. SDNode* PIC16DAGToDAGISel::Select(SDNode *N) { diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.h b/lib/Target/PIC16/PIC16ISelDAGToDAG.h index 813a540fb8..8ed5bf7172 100644 --- a/lib/Target/PIC16/PIC16ISelDAGToDAG.h +++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.h @@ -19,6 +19,8 @@ #include "PIC16TargetMachine.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" #include "llvm/Intrinsics.h" using namespace llvm; @@ -46,8 +48,6 @@ public: return "PIC16 DAG->DAG Pattern Instruction Selection"; } - virtual void InstructionSelect(); - private: // Include the pieces autogenerated from the target description. #include "PIC16GenDAGISel.inc" diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp index 7754a4f145..d17abb9ed0 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.cpp +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -419,8 +419,7 @@ PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/true, - Callee, Args, DAG, dl, - DAG.GetOrdering(DAG.getEntryNode().getNode())); + Callee, Args, DAG, dl); return CallInfo.first; } @@ -622,12 +621,12 @@ SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { ChainHi = Chain.getOperand(1); } SDValue Store1 = DAG.getStore(ChainLo, dl, SrcLo, Ptr, NULL, - 0 + StoreOffset); + 0 + StoreOffset, false, false, 0); Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, DAG.getConstant(4, Ptr.getValueType())); SDValue Store2 = DAG.getStore(ChainHi, dl, SrcHi, Ptr, NULL, - 1 + StoreOffset); + 1 + StoreOffset, false, false, 0); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, Store2); @@ -1513,8 +1512,7 @@ bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp, // Direct load operands are folded in binary operations. But before folding // verify if this folding is legal. Fold only if it is legal otherwise // convert this direct load to a separate memory operation. - if(ISel->IsLegalAndProfitableToFold(Op.getOperand(0).getNode(), - Op.getNode(), Op.getNode())) + if(ISel->IsLegalToFold(Op.getOperand(0), Op.getNode(), Op.getNode())) return false; else MemOp = 0; @@ -1528,10 +1526,24 @@ bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp, return true; if (isDirectLoad(Op.getOperand(1))) { - if (Op.getOperand(1).hasOneUse()) - return false; - else - MemOp = 1; + if (Op.getOperand(1).hasOneUse()) { + // Legal and profitable folding check uses the NodeId of DAG nodes. + // This NodeId is assigned by topological order. Therefore first + // assign topological order then perform legal and profitable check. + // Note:- Though this ordering is done before begining with legalization, + // newly added node during legalization process have NodeId=-1 (NewNode) + // therefore before performing any check proper ordering of the node is + // required. + DAG.AssignTopologicalOrder(); + + // Direct load operands are folded in binary operations. But before folding + // verify if this folding is legal. Fold only if it is legal otherwise + // convert this direct load to a separate memory operation. + if(ISel->IsLegalToFold(Op.getOperand(1), Op.getNode(), Op.getNode())) + return false; + else + MemOp = 1; + } } return true; } diff --git a/lib/Target/PIC16/PIC16MemSelOpt.cpp b/lib/Target/PIC16/PIC16MemSelOpt.cpp index cc71b04cc2..ab81ed1bca 100644 --- a/lib/Target/PIC16/PIC16MemSelOpt.cpp +++ b/lib/Target/PIC16/PIC16MemSelOpt.cpp @@ -59,6 +59,7 @@ namespace { const TargetInstrInfo *TII; // Machine instruction info. MachineBasicBlock *MBB; // Current basic block std::string CurBank; + int PageChanged; }; char MemSelOpt::ID = 0; @@ -93,10 +94,56 @@ bool MemSelOpt::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { // Let us assume that when entering a basic block now bank is selected. // Ideally we should look at the predecessors for this information. CurBank=""; + PageChanged=0; - for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) { + MachineBasicBlock::iterator I; + for (I = BB.begin(); I != BB.end(); ++I) { Changed |= processInstruction(I); + + // if the page has changed insert a page sel before + // any instruction that needs one + if (PageChanged == 1) + { + // Restore the page if it was changed, before leaving the basic block, + // because it may be required by the goto terminator or the fall thru + // basic blcok. + // If the terminator is return, we don't need to restore since there + // is no goto or fall thru basic block. + if ((I->getOpcode() == PIC16::sublw_3) || //macro has goto + (I->getOpcode() == PIC16::sublw_6) || //macro has goto + (I->getOpcode() == PIC16::addlwc) || //macro has goto + (TII->get(I->getOpcode()).isBranch())) + { + DebugLoc dl = I->getDebugLoc(); + BuildMI(*MBB, I, dl, TII->get(PIC16::pagesel)).addExternalSymbol("$"); + Changed = true; + PageChanged = 0; + } + } } + + // The basic block is over, but if we did not find any goto yet, + // we haven't restored the page. + // Restore the page if it was changed, before leaving the basic block, + // because it may be required by fall thru basic blcok. + // If the terminator is return, we don't need to restore since there + // is fall thru basic block. + if (PageChanged == 1) { + // save the end pointer before we move back to last insn. + MachineBasicBlock::iterator J = I; + I--; + const TargetInstrDesc &TID = TII->get(I->getOpcode()); + if (! TID.isReturn()) + { + DebugLoc dl = I->getDebugLoc(); + BuildMI(*MBB, J, dl, + TII->get(PIC16::pagesel)).addExternalSymbol("$"); + Changed = true; + PageChanged = 0; + } + } + + return Changed; } @@ -112,42 +159,74 @@ bool MemSelOpt::processInstruction(MachineInstr *MI) { if (!(TID.isBranch() || TID.isCall() || TID.mayLoad() || TID.mayStore())) return false; + // The first thing we should do is that record if banksel/pagesel are + // changed in an unknown way. This can happend via any type of call. + // We do it here first before scanning of MemOp / BBOp as the indirect + // call insns do not have any operands, but they still may change bank/page. + if (TID.isCall()) { + // Record that we have changed the page, so that we can restore it + // before basic block ends. + // We require to signal that a page anc bank change happened even for + // indirect calls. + PageChanged = 1; + + // When a call is made, there may be banksel for variables in callee. + // Hence the banksel in caller needs to be reset. + CurBank = ""; + } + // Scan for the memory address operand. // FIXME: Should we use standard interfaces like memoperands_iterator, // hasMemOperand() etc ? int MemOpPos = -1; + int BBOpPos = -1; for (unsigned i = 0; i < NumOperands; i++) { MachineOperand Op = MI->getOperand(i); if (Op.getType() == MachineOperand::MO_GlobalAddress || - Op.getType() == MachineOperand::MO_ExternalSymbol || - Op.getType() == MachineOperand::MO_MachineBasicBlock) { + Op.getType() == MachineOperand::MO_ExternalSymbol) { // We found one mem operand. Next one may be BS. MemOpPos = i; - break; + } + if (Op.getType() == MachineOperand::MO_MachineBasicBlock) { + // We found one BB operand. Next one may be pagesel. + BBOpPos = i; } } // If we did not find an insn accessing memory. Continue. - if (MemOpPos == -1) return Changed; + if ((MemOpPos == -1) && + (BBOpPos == -1)) + return false; + assert ((BBOpPos != MemOpPos) && "operand can only be of one type"); - // Get the MemOp. - MachineOperand &Op = MI->getOperand(MemOpPos); // If this is a pagesel material, handle it first. - if (MI->getOpcode() == PIC16::CALL || - MI->getOpcode() == PIC16::br_uncond) { + // CALL and br_ucond insns use MemOp (GA or ES) and not BBOp. + // Pagesel is required only for a direct call. + if ((MI->getOpcode() == PIC16::CALL)) { + // Get the BBOp. + MachineOperand &MemOp = MI->getOperand(MemOpPos); DebugLoc dl = MI->getDebugLoc(); - BuildMI(*MBB, MI, dl, TII->get(PIC16::pagesel)). - addOperand(Op); - return true; + BuildMI(*MBB, MI, dl, TII->get(PIC16::pagesel)).addOperand(MemOp); + + // CALL and br_ucond needs only pagesel. so we are done. + return true; } + // Pagesel is handled. Now, add a Banksel if needed. + if (MemOpPos == -1) return Changed; + // Get the MemOp. + MachineOperand &Op = MI->getOperand(MemOpPos); + // Get the section name(NewBank) for MemOp. // This assumes that the section names for globals are already set by // AsmPrinter->doInitialization. std::string NewBank = CurBank; + bool hasExternalLinkage = false; if (Op.getType() == MachineOperand::MO_GlobalAddress && Op.getGlobal()->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) { + if (Op.getGlobal()->hasExternalLinkage()) + hasExternalLinkage= true; NewBank = Op.getGlobal()->getSection(); } else if (Op.getType() == MachineOperand::MO_ExternalSymbol) { // External Symbol is generated for temp data and arguments. They are @@ -162,7 +241,7 @@ bool MemSelOpt::processInstruction(MachineInstr *MI) { // If the previous and new section names are same, we don't need to // emit banksel. - if (NewBank.compare(CurBank) != 0 ) { + if (NewBank.compare(CurBank) != 0 || hasExternalLinkage) { DebugLoc dl = MI->getDebugLoc(); BuildMI(*MBB, MI, dl, TII->get(PIC16::banksel)). addOperand(Op); diff --git a/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp b/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp new file mode 100644 index 0000000000..865da35de3 --- /dev/null +++ b/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp @@ -0,0 +1,299 @@ +//===-- PIC16Cloner.cpp - PIC16 LLVM Cloner for shared functions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to clone all functions that are shared between +// the main line code (ML) and interrupt line code (IL). It clones all such +// shared functions and their automatic global vars by adding the .IL suffix. +// +// This pass is supposed to be run on the linked .bc module. +// It traveses the module call graph twice. Once starting from the main function +// and marking each reached function as "ML". Again, starting from the ISR +// and cloning any reachable function that was marked as "ML". After cloning +// the function, it remaps all the call sites in IL functions to call the +// cloned functions. +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "PIC16Cloner.h" +#include "../PIC16ABINames.h" +#include + +using namespace llvm; +using std::vector; +using std::string; +using std::map; + +namespace llvm { + char PIC16Cloner::ID = 0; + + ModulePass *createPIC16ClonerPass() { return new PIC16Cloner(); } +} + +// We currently intend to run these passes in opt, which does not have any +// diagnostic support. So use these functions for now. In future +// we will probably write our own driver tool. +// +void PIC16Cloner::reportError(string ErrorString) { + errs() << "ERROR : " << ErrorString << "\n"; + exit(1); +} + +void PIC16Cloner:: +reportError (string ErrorString, vector &Values) { + unsigned ValCount = Values.size(); + string TargetString; + for (unsigned i=0; i(); + + // Search for the "main" and "ISR" functions. + CallGraphNode *mainCGN = NULL, *isrCGN = NULL; + for (CallGraph::iterator it = CG.begin() ; it != CG.end(); it++) + { + // External calling node doesn't have any function associated with it. + if (! it->first) + continue; + + if (it->first->getName().str() == "main") { + mainCGN = it->second; + } + + if (PAN::isISR(it->first->getSection())) { + isrCGN = it->second; + } + + // Don't search further if we've found both. + if (mainCGN && isrCGN) + break; + } + + // We have nothing to do if any of the main or ISR is missing. + if (! mainCGN || ! isrCGN) return false; + + // Time for some diagnostics. + // See if the main itself is interrupt function then report an error. + if (PAN::isISR(mainCGN->getFunction()->getSection())) { + reportError("Function 'main' can't be interrupt function"); + } + + + // Mark all reachable functions from main as ML. + markCallGraph(mainCGN, "ML"); + + // And then all the functions reachable from ISR will be cloned. + cloneSharedFunctions(isrCGN); + + return true; +} + +// Mark all reachable functions from the given node, with the given mark. +// +void PIC16Cloner::markCallGraph(CallGraphNode *CGN, string StringMark) { + // Mark the top node first. + Function *thisF = CGN->getFunction(); + + thisF->setSection(StringMark); + + // Mark all the called functions + for(CallGraphNode::iterator cgn_it = CGN->begin(); + cgn_it != CGN->end(); ++cgn_it) { + Function *CalledF = cgn_it->second->getFunction(); + + // If calling an external function then CallGraphNode + // will not be associated with any function. + if (! CalledF) + continue; + + // Issue diagnostic if interrupt function is being called. + if (PAN::isISR(CalledF->getSection())) { + vector Values; + Values.push_back(CalledF->getName().str()); + reportError("Interrupt function (%0) can't be called", Values); + } + + // Has already been mark + if (CalledF->getSection().find(StringMark) != string::npos) { + // Should we do anything here? + } else { + // Mark now + CalledF->setSection(StringMark); + } + + // Before going any further mark all the called function by current + // function. + markCallGraph(cgn_it->second ,StringMark); + } // end of loop of all called functions. +} + + +// For PIC16, automatic variables of a function are emitted as globals. +// Clone the auto variables of a function and put them in ValueMap, +// this ValueMap will be used while +// Cloning the code of function itself. +// +void PIC16Cloner::CloneAutos(Function *F) { + // We'll need to update module's globals list as well. So keep a reference + // handy. + Module *M = F->getParent(); + Module::GlobalListType &Globals = M->getGlobalList(); + + // Clear the leftovers in ValueMap by any previous cloning. + ValueMap.clear(); + + // Find the auto globls for this function and clone them, and put them + // in ValueMap. + std::string FnName = F->getName().str(); + std::string VarName, ClonedVarName; + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + VarName = I->getName().str(); + if (PAN::isLocalToFunc(FnName, VarName)) { + // Auto variable for current function found. Clone it. + GlobalVariable *GV = I; + + const Type *InitTy = GV->getInitializer()->getType(); + GlobalVariable *ClonedGV = + new GlobalVariable(InitTy, false, GV->getLinkage(), + GV->getInitializer()); + ClonedGV->setName(PAN::getCloneVarName(FnName, VarName)); + // Add these new globals to module's globals list. + Globals.push_back(ClonedGV); + + // Update ValueMap. + ValueMap[GV] = ClonedGV; + } + } +} + + +// Clone all functions that are reachable from ISR and are already +// marked as ML. +// +void PIC16Cloner::cloneSharedFunctions(CallGraphNode *CGN) { + + // Check all the called functions from ISR. + for(CallGraphNode::iterator cgn_it = CGN->begin(); + cgn_it != CGN->end(); ++cgn_it) { + Function *CalledF = cgn_it->second->getFunction(); + + // If calling an external function then CallGraphNode + // will not be associated with any function. + if (!CalledF) + continue; + + // Issue diagnostic if interrupt function is being called. + if (PAN::isISR(CalledF->getSection())) { + vector Values; + Values.push_back(CalledF->getName().str()); + reportError("Interrupt function (%0) can't be called", Values); + } + + if (CalledF->getSection().find("ML") != string::npos) { + // Function is alternatively marked. It should be a shared one. + // Create IL copy. Passing called function as first argument + // and the caller as the second argument. + + // Before making IL copy, first ensure that this function has a + // body. If the function does have a body. It can't be cloned. + // Such a case may occur when the function has been declarated + // in the C source code but its body exists in assembly file. + if (!CalledF->isDeclaration()) { + Function *cf = cloneFunction(CalledF); + remapAllSites(CGN->getFunction(), CalledF, cf); + } else { + // It is called only from ISR. Still mark it as we need this info + // in code gen while calling intrinsics.Function is not marked. + CalledF->setSection("IL"); + } + } + // Before going any further clone all the shared function reachaable + // by current function. + cloneSharedFunctions(cgn_it->second); + } // end of loop of all called functions. +} + +// Clone the given function and return it. +// Note: it uses the ValueMap member of the class, which is already populated +// by cloneAutos by the time we reach here. +// FIXME: Should we just pass ValueMap's ref as a parameter here? rather +// than keeping the ValueMap as a member. +Function * +PIC16Cloner::cloneFunction(Function *OrgF) { + Function *ClonedF; + + // See if we already cloned it. Return that. + cloned_map_iterator cm_it = ClonedFunctionMap.find(OrgF); + if(cm_it != ClonedFunctionMap.end()) { + ClonedF = cm_it->second; + return ClonedF; + } + + // Clone does not exist. + // First clone the autos, and populate ValueMap. + CloneAutos(OrgF); + + // Now create the clone. + ClonedF = CloneFunction(OrgF, ValueMap); + + // The new function should be for interrupt line. Therefore should have + // the name suffixed with IL and section attribute marked with IL. + ClonedF->setName(PAN::getCloneFnName(OrgF->getName())); + ClonedF->setSection("IL"); + + // Add the newly created function to the module. + OrgF->getParent()->getFunctionList().push_back(ClonedF); + + // Update the ClonedFunctionMap to record this cloning activity. + ClonedFunctionMap[OrgF] = ClonedF; + + return ClonedF; +} + + +// Remap the call sites of shared functions, that are in IL. +// Change the IL call site of a shared function to its clone. +// +void PIC16Cloner:: +remapAllSites(Function *Caller, Function *OrgF, Function *Clone) { + // First find the caller to update. If the caller itself is cloned + // then use the cloned caller. Otherwise use it. + cloned_map_iterator cm_it = ClonedFunctionMap.find(Caller); + if (cm_it != ClonedFunctionMap.end()) + Caller = cm_it->second; + + // For the lack of a better call site finding mechanism, iterate over + // all insns to find the uses of original fn. + for (Function::iterator BI = Caller->begin(); BI != Caller->end(); ++BI) { + BasicBlock &BB = *BI; + for (BasicBlock::iterator II = BB.begin(); II != BB.end(); ++II) { + if (II->getNumOperands() > 0 && II->getOperand(0) == OrgF) + II->setOperand(0, Clone); + } + } +} + + + diff --git a/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h b/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h new file mode 100644 index 0000000000..24c11527b0 --- /dev/null +++ b/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h @@ -0,0 +1,83 @@ +//===-- PIC16Cloner.h - PIC16 LLVM Cloner for shared functions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains declaration of a cloner class clone all functions that +// are shared between the main line code (ML) and interrupt line code (IL). +// +//===----------------------------------------------------------------------===// + +#ifndef PIC16CLONER_H +#define PIC16CLONER_H + +#include "llvm/ADT/DenseMap.h" + +using namespace llvm; +using std::vector; +using std::string; +using std::map; + +namespace llvm { + // forward classes. + class Value; + class Function; + class Module; + class ModulePass; + class CallGraph; + class CallGraphNode; + class AnalysisUsage; + + class PIC16Cloner : public ModulePass { + public: + static char ID; // Class identification + PIC16Cloner() : ModulePass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); + } + virtual bool runOnModule(Module &M); + + private: // Functions + // Mark reachable functions for the MainLine or InterruptLine. + void markCallGraph(CallGraphNode *CGN, string StringMark); + + // Clone auto variables of function specified. + void CloneAutos(Function *F); + + // Clone the body of a function. + Function *cloneFunction(Function *F); + + // Clone all shared functions. + void cloneSharedFunctions(CallGraphNode *isrCGN); + + // Remap all call sites to the shared function. + void remapAllSites(Function *Caller, Function *OrgF, Function *Clone); + + // Error reporting for PIC16Pass + void reportError(string ErrorString, vector &Values); + void reportError(string ErrorString); + + private: //data + // Records if the interrupt function has already been found. + // If more than one interrupt function is found then an error + // should be thrown. + bool foundISR; + + // This ValueMap maps the auto variables of the original functions with + // the corresponding cloned auto variable of the cloned function. + // This value map is passed during the function cloning so that all the + // uses of auto variables be updated properly. + DenseMap ValueMap; + + // Map of a already cloned functions. + map ClonedFunctionMap; + typedef map::iterator cloned_map_iterator; + }; +} // End of anonymous namespace + +#endif diff --git a/lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp b/lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp index 197c3987d2..5ecb6aa551 100644 --- a/lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp +++ b/lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp @@ -24,27 +24,27 @@ using namespace llvm; namespace llvm { - char PIC16FrameOverlay::ID = 0; - ModulePass *createPIC16OverlayPass() { return new PIC16FrameOverlay(); } + char PIC16Overlay::ID = 0; + ModulePass *createPIC16OverlayPass() { return new PIC16Overlay(); } } -void PIC16FrameOverlay::getAnalysisUsage(AnalysisUsage &AU) const { +void PIC16Overlay::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired(); } -void PIC16FrameOverlay::DFSTraverse(CallGraphNode *CGN, unsigned Depth) { +void PIC16Overlay::DFSTraverse(CallGraphNode *CGN, unsigned Depth) { // Do not set any color for external calling node. if (Depth != 0 && CGN->getFunction()) { unsigned Color = getColor(CGN->getFunction()); // Handle indirectly called functions - if (Color >= PIC16Overlay::StartIndirectCallColor || - Depth >= PIC16Overlay::StartIndirectCallColor) { + if (Color >= PIC16OVERLAY::StartIndirectCallColor || + Depth >= PIC16OVERLAY::StartIndirectCallColor) { // All functions called from an indirectly called function are given // an unique color. - if (Color < PIC16Overlay::StartIndirectCallColor && - Depth >= PIC16Overlay::StartIndirectCallColor) + if (Color < PIC16OVERLAY::StartIndirectCallColor && + Depth >= PIC16OVERLAY::StartIndirectCallColor) setColor(CGN->getFunction(), Depth); for (unsigned int i = 0; i < CGN->size(); i++) @@ -65,7 +65,7 @@ void PIC16FrameOverlay::DFSTraverse(CallGraphNode *CGN, unsigned Depth) { DFSTraverse((*CGN)[i], Depth+1); } -unsigned PIC16FrameOverlay::ModifyDepthForInterrupt(CallGraphNode *CGN, +unsigned PIC16Overlay::ModifyDepthForInterrupt(CallGraphNode *CGN, unsigned Depth) { Function *Fn = CGN->getFunction(); @@ -81,7 +81,7 @@ unsigned PIC16FrameOverlay::ModifyDepthForInterrupt(CallGraphNode *CGN, return Depth; } -void PIC16FrameOverlay::setColor(Function *Fn, unsigned Color) { +void PIC16Overlay::setColor(Function *Fn, unsigned Color) { std::string Section = ""; if (Fn->hasSection()) Section = Fn->getSection(); @@ -119,7 +119,7 @@ void PIC16FrameOverlay::setColor(Function *Fn, unsigned Color) { Fn->setSection(Section); } -unsigned PIC16FrameOverlay::getColor(Function *Fn) { +unsigned PIC16Overlay::getColor(Function *Fn) { int Color = 0; if (!Fn->hasSection()) return 0; @@ -150,7 +150,7 @@ unsigned PIC16FrameOverlay::getColor(Function *Fn) { return Color; } -bool PIC16FrameOverlay::runOnModule(Module &M) { +bool PIC16Overlay::runOnModule(Module &M) { CallGraph &CG = getAnalysis(); CallGraphNode *ECN = CG.getExternalCallingNode(); @@ -164,7 +164,7 @@ bool PIC16FrameOverlay::runOnModule(Module &M) { return false; } -void PIC16FrameOverlay::MarkIndirectlyCalledFunctions(Module &M) { +void PIC16Overlay::MarkIndirectlyCalledFunctions(Module &M) { // If the use of a function is not a call instruction then this // function might be called indirectly. In that case give it // an unique color. diff --git a/lib/Target/PIC16/PIC16Passes/PIC16Overlay.h b/lib/Target/PIC16/PIC16Passes/PIC16Overlay.h index d70c4e7d52..5a2551fabc 100644 --- a/lib/Target/PIC16/PIC16Passes/PIC16Overlay.h +++ b/lib/Target/PIC16/PIC16Passes/PIC16Overlay.h @@ -1,4 +1,4 @@ -//===-- PIC16FrameOverlay.h - Interface for PIC16 Frame Overlay -*- C++ -*-===// +//===-- PIC16Overlay.h - Interface for PIC16 Frame Overlay -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,30 +14,35 @@ #ifndef PIC16FRAMEOVERLAY_H #define PIC16FRAMEOVERLAY_H -#include "llvm/Analysis/CallGraph.h" -#include "llvm/Pass.h" -#include "llvm/CallGraphSCCPass.h" using std::string; using namespace llvm; namespace llvm { - namespace PIC16Overlay { + // Forward declarations. + class Function; + class Module; + class ModulePass; + class AnalysisUsage; + class CallGraphNode; + class CallGraph; + + namespace PIC16OVERLAY { enum OverlayConsts { StartInterruptColor = 200, StartIndirectCallColor = 300 }; } - class PIC16FrameOverlay : public ModulePass { + class PIC16Overlay : public ModulePass { std::string OverlayStr; unsigned InterruptDepth; unsigned IndirectCallColor; public: static char ID; // Class identification - PIC16FrameOverlay() : ModulePass(&ID) { + PIC16Overlay() : ModulePass(&ID) { OverlayStr = "Overlay="; - InterruptDepth = PIC16Overlay::StartInterruptColor; - IndirectCallColor = PIC16Overlay::StartIndirectCallColor; + InterruptDepth = PIC16OVERLAY::StartInterruptColor; + IndirectCallColor = PIC16OVERLAY::StartIndirectCallColor; } virtual void getAnalysisUsage(AnalysisUsage &AU) const; diff --git a/lib/Target/PIC16/PIC16TargetObjectFile.cpp b/lib/Target/PIC16/PIC16TargetObjectFile.cpp index d7cfe029d3..b891c18c46 100644 --- a/lib/Target/PIC16/PIC16TargetObjectFile.cpp +++ b/lib/Target/PIC16/PIC16TargetObjectFile.cpp @@ -315,8 +315,12 @@ PIC16TargetObjectFile::allocateSHARED(const GlobalVariable *GV, // Interface used by AsmPrinter to get a code section for a function. const PIC16Section * -PIC16TargetObjectFile::SectionForCode(const std::string &FnName) const { +PIC16TargetObjectFile::SectionForCode(const std::string &FnName, + bool isISR) const { const std::string &sec_name = PAN::getCodeSectionName(FnName); + // If it is ISR, its code section starts at a specific address. + if (isISR) + return getPIC16Section(sec_name, CODE, PAN::getISRAddr()); return getPIC16Section(sec_name, CODE); } diff --git a/lib/Target/PIC16/PIC16TargetObjectFile.h b/lib/Target/PIC16/PIC16TargetObjectFile.h index 0b0ad43ff9..cf8bf848e4 100644 --- a/lib/Target/PIC16/PIC16TargetObjectFile.h +++ b/lib/Target/PIC16/PIC16TargetObjectFile.h @@ -137,7 +137,8 @@ namespace llvm { /// Return a code section for a function. - const PIC16Section *SectionForCode (const std::string &FnName) const; + const PIC16Section *SectionForCode (const std::string &FnName, + bool isISR) const; /// Return a frame section for a function. const PIC16Section *SectionForFrame (const std::string &FnName) const; diff --git a/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp b/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp index 46cc81967e..f1bdb1210f 100644 --- a/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp +++ b/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp @@ -15,7 +15,8 @@ using namespace llvm; Target llvm::ThePIC16Target, llvm::TheCooperTarget; extern "C" void LLVMInitializePIC16TargetInfo() { - RegisterTarget<> X(ThePIC16Target, "pic16", "PIC16 14-bit [experimental]"); + RegisterTarget X(ThePIC16Target, "pic16", + "PIC16 14-bit [experimental]"); RegisterTarget<> Y(TheCooperTarget, "cooper", "PIC16 Cooper [experimental]"); } diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp index afc90b1aec..ac901d0114 100644 --- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp @@ -31,13 +31,13 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetOptions.h" diff --git a/lib/Target/PowerPC/PPCCallingConv.td b/lib/Target/PowerPC/PPCCallingConv.td index c7ce171da3..155fba22d9 100644 --- a/lib/Target/PowerPC/PPCCallingConv.td +++ b/lib/Target/PowerPC/PPCCallingConv.td @@ -66,28 +66,13 @@ def CC_PPC : CallingConv<[ // PowerPC System V Release 4 ABI //===----------------------------------------------------------------------===// -// _Complex arguments are never split, thus their two scalars are either -// passed both in argument registers or both on the stack. Also _Complex -// arguments are always passed in general purpose registers, never in -// Floating-point registers or vector registers. Arguments which should go -// on the stack are marked with the inreg parameter attribute. -// Giving inreg this target-dependent (and counter-intuitive) meaning -// simplifies things, because functions calls are not always coming from the -// frontend but are also created implicitly e.g. for libcalls. If inreg would -// actually mean that the argument is passed in a register, then all places -// which create function calls/function definitions implicitly would need to -// be aware of this fact and would need to mark arguments accordingly. With -// inreg meaning that the argument is passed on the stack, this is not an -// issue, except for calls which involve _Complex types. - def CC_PPC_SVR4_Common : CallingConv<[ // The ABI requires i64 to be passed in two adjacent registers with the first // register having an odd register number. CCIfType<[i32], CCIfSplit>>, // The first 8 integer arguments are passed in integer registers. - CCIfType<[i32], CCIf<"!ArgFlags.isInReg()", - CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>>, + CCIfType<[i32], CCAssignToReg<[R3, R4, R5, R6, R7, R8, R9, R10]>>, // Make sure the i64 words from a long double are either both passed in // registers or both passed on the stack. diff --git a/lib/Target/PowerPC/PPCHazardRecognizers.cpp b/lib/Target/PowerPC/PPCHazardRecognizers.cpp index 3a15f7efdf..66dfd4b737 100644 --- a/lib/Target/PowerPC/PPCHazardRecognizers.cpp +++ b/lib/Target/PowerPC/PPCHazardRecognizers.cpp @@ -257,7 +257,7 @@ void PPCHazardRecognizer970::EmitInstruction(SUnit *SU) { case PPC::STWX: case PPC::STWX8: case PPC::STWUX: case PPC::STW: case PPC::STW8: - case PPC::STWU: case PPC::STWU8: + case PPC::STWU: case PPC::STVEWX: case PPC::STFIWX: case PPC::STWBRX: diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 004997fe8c..9d79c0ddb1 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -156,10 +156,6 @@ namespace { SDValue BuildSDIVSequence(SDNode *N); SDValue BuildUDIVSequence(SDNode *N); - /// InstructionSelect - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelect(); - void InsertVRSaveCode(MachineFunction &MF); virtual const char *getPassName() const { @@ -184,14 +180,6 @@ private: }; } -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void PPCDAGToDAGISel::InstructionSelect() { - // Select target instructions for the DAG. - SelectRoot(*CurDAG); - CurDAG->RemoveDeadNodes(); -} - /// InsertVRSaveCode - Once the entire function has been instruction selected, /// all virtual registers are created and all machine instructions are built, /// check to see if we need to save/restore VRSAVE. If so, do it. diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index a11d6240f8..3d81afa450 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -25,13 +25,13 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Intrinsics.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -1243,7 +1243,8 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, // If the global is weak or external, we have to go through the lazy // resolution stub. - return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Lo, NULL, 0); + return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Lo, NULL, 0, + false, false, 0); } SDValue PPCTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { @@ -1333,7 +1334,7 @@ SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) { false, false, false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/true, DAG.getExternalSymbol("__trampoline_setup", PtrVT), - Args, DAG, dl, DAG.GetOrdering(Chain.getNode())); + Args, DAG, dl); SDValue Ops[] = { CallResult.first, CallResult.second }; @@ -1355,7 +1356,8 @@ SDValue PPCTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG, EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); const Value *SV = cast(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0); + return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0, + false, false, 0); } // For the 32-bit SVR4 ABI we follow the layout of the va_list struct. @@ -1405,25 +1407,29 @@ SDValue PPCTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG, // Store first byte : number of int regs SDValue firstStore = DAG.getTruncStore(Op.getOperand(0), dl, ArgGPR, - Op.getOperand(1), SV, 0, MVT::i8); + Op.getOperand(1), SV, 0, MVT::i8, + false, false, 0); uint64_t nextOffset = FPROffset; SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, Op.getOperand(1), ConstFPROffset); // Store second byte : number of float regs SDValue secondStore = - DAG.getTruncStore(firstStore, dl, ArgFPR, nextPtr, SV, nextOffset, MVT::i8); + DAG.getTruncStore(firstStore, dl, ArgFPR, nextPtr, SV, nextOffset, MVT::i8, + false, false, 0); nextOffset += StackOffset; nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, nextPtr, ConstStackOffset); // Store second word : arguments given on stack SDValue thirdStore = - DAG.getStore(secondStore, dl, StackOffsetFI, nextPtr, SV, nextOffset); + DAG.getStore(secondStore, dl, StackOffsetFI, nextPtr, SV, nextOffset, + false, false, 0); nextOffset += FrameOffset; nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, nextPtr, ConstFrameOffset); // Store third word : arguments given in registers - return DAG.getStore(thirdStore, dl, FR, nextPtr, SV, nextOffset); + return DAG.getStore(thirdStore, dl, FR, nextPtr, SV, nextOffset, + false, false, 0); } @@ -1628,7 +1634,8 @@ PPCTargetLowering::LowerFormalArguments_SVR4( // Create load nodes to retrieve arguments from the stack. SDValue FIN = DAG.getFrameIndex(FI, PtrVT); - InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0)); + InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, NULL, 0, + false, false, 0)); } } @@ -1700,7 +1707,8 @@ PPCTargetLowering::LowerFormalArguments_SVR4( unsigned GPRIndex = 0; for (; GPRIndex != VarArgsNumGPR; ++GPRIndex) { SDValue Val = DAG.getRegister(GPArgRegs[GPRIndex], PtrVT); - SDValue Store = DAG.getStore(Chain, dl, Val, FIN, NULL, 0); + SDValue Store = DAG.getStore(Chain, dl, Val, FIN, NULL, 0, + false, false, 0); MemOps.push_back(Store); // Increment the address by four for the next argument to store SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); @@ -1714,7 +1722,8 @@ PPCTargetLowering::LowerFormalArguments_SVR4( unsigned VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); - SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0, + false, false, 0); MemOps.push_back(Store); // Increment the address by four for the next argument to store SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); @@ -1729,7 +1738,8 @@ PPCTargetLowering::LowerFormalArguments_SVR4( unsigned FPRIndex = 0; for (FPRIndex = 0; FPRIndex != VarArgsNumFPR; ++FPRIndex) { SDValue Val = DAG.getRegister(FPArgRegs[FPRIndex], MVT::f64); - SDValue Store = DAG.getStore(Chain, dl, Val, FIN, NULL, 0); + SDValue Store = DAG.getStore(Chain, dl, Val, FIN, NULL, 0, + false, false, 0); MemOps.push_back(Store); // Increment the address by eight for the next argument to store SDValue PtrOff = DAG.getConstant(EVT(MVT::f64).getSizeInBits()/8, @@ -1741,7 +1751,8 @@ PPCTargetLowering::LowerFormalArguments_SVR4( unsigned VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::f64); - SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0, + false, false, 0); MemOps.push_back(Store); // Increment the address by eight for the next argument to store SDValue PtrOff = DAG.getConstant(EVT(MVT::f64).getSizeInBits()/8, @@ -1903,7 +1914,9 @@ PPCTargetLowering::LowerFormalArguments_Darwin( unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN, - NULL, 0, ObjSize==1 ? MVT::i8 : MVT::i16 ); + NULL, 0, + ObjSize==1 ? MVT::i8 : MVT::i16, + false, false, 0); MemOps.push_back(Store); ++GPR_idx; } @@ -1921,7 +1934,8 @@ PPCTargetLowering::LowerFormalArguments_Darwin( int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true, false); SDValue FIN = DAG.getFrameIndex(FI, PtrVT); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); - SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0, + false, false, 0); MemOps.push_back(Store); ++GPR_idx; ArgOffset += PtrByteSize; @@ -2045,7 +2059,8 @@ PPCTargetLowering::LowerFormalArguments_Darwin( CurArgOffset + (ArgSize - ObjSize), isImmutable, false); SDValue FIN = DAG.getFrameIndex(FI, PtrVT); - ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0); + ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, NULL, 0, + false, false, 0); } InVals.push_back(ArgVal); @@ -2091,7 +2106,8 @@ PPCTargetLowering::LowerFormalArguments_Darwin( VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); - SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0, + false, false, 0); MemOps.push_back(Store); // Increment the address by four for the next argument to store SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); @@ -2271,7 +2287,7 @@ StoreTailCallArgumentsToStackSlot(SelectionDAG &DAG, // Store relative to framepointer. MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, FIN, PseudoSourceValue::getFixedStack(FI), - 0)); + 0, false, false, 0)); } } @@ -2297,7 +2313,8 @@ static SDValue EmitTailCallStoreFPAndRetAddr(SelectionDAG &DAG, EVT VT = isPPC64 ? MVT::i64 : MVT::i32; SDValue NewRetAddrFrIdx = DAG.getFrameIndex(NewRetAddr, VT); Chain = DAG.getStore(Chain, dl, OldRetAddr, NewRetAddrFrIdx, - PseudoSourceValue::getFixedStack(NewRetAddr), 0); + PseudoSourceValue::getFixedStack(NewRetAddr), 0, + false, false, 0); // When using the 32/64-bit SVR4 ABI there is no need to move the FP stack // slot as the FP is never overwritten. @@ -2308,7 +2325,8 @@ static SDValue EmitTailCallStoreFPAndRetAddr(SelectionDAG &DAG, true, false); SDValue NewFramePtrIdx = DAG.getFrameIndex(NewFPIdx, VT); Chain = DAG.getStore(Chain, dl, OldFP, NewFramePtrIdx, - PseudoSourceValue::getFixedStack(NewFPIdx), 0); + PseudoSourceValue::getFixedStack(NewFPIdx), 0, + false, false, 0); } } return Chain; @@ -2346,14 +2364,16 @@ SDValue PPCTargetLowering::EmitTailCallLoadFPAndRetAddr(SelectionDAG & DAG, // Load the LR and FP stack slot for later adjusting. EVT VT = PPCSubTarget.isPPC64() ? MVT::i64 : MVT::i32; LROpOut = getReturnAddrFrameIndex(DAG); - LROpOut = DAG.getLoad(VT, dl, Chain, LROpOut, NULL, 0); + LROpOut = DAG.getLoad(VT, dl, Chain, LROpOut, NULL, 0, + false, false, 0); Chain = SDValue(LROpOut.getNode(), 1); // When using the 32/64-bit SVR4 ABI there is no need to load the FP stack // slot as the FP is never overwritten. if (isDarwinABI) { FPOpOut = getFramePointerFrameIndex(DAG); - FPOpOut = DAG.getLoad(VT, dl, Chain, FPOpOut, NULL, 0); + FPOpOut = DAG.getLoad(VT, dl, Chain, FPOpOut, NULL, 0, + false, false, 0); Chain = SDValue(FPOpOut.getNode(), 1); } } @@ -2395,7 +2415,8 @@ LowerMemOpCallTo(SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, DAG.getConstant(ArgOffset, PtrVT)); } - MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0)); + MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + false, false, 0)); // Calculate and remember argument location. } else CalculateTailCallArgDest(DAG, MF, isPPC64, Arg, SPDiff, ArgOffset, TailCallArguments); @@ -2862,7 +2883,8 @@ PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee, PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, - PseudoSourceValue::getStack(), LocMemOffset)); + PseudoSourceValue::getStack(), LocMemOffset, + false, false, 0)); } else { // Calculate and remember argument location. CalculateTailCallArgDest(DAG, MF, false, Arg, SPDiff, LocMemOffset, @@ -3024,7 +3046,7 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, EVT VT = (Size==1) ? MVT::i8 : MVT::i16; if (GPR_idx != NumGPRs) { SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, PtrVT, Chain, Arg, - NULL, 0, VT); + NULL, 0, VT, false, false, 0); MemOpChains.push_back(Load.getValue(1)); RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); @@ -3061,7 +3083,8 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, SDValue Const = DAG.getConstant(j, PtrOff.getValueType()); SDValue AddArg = DAG.getNode(ISD::ADD, dl, PtrVT, Arg, Const); if (GPR_idx != NumGPRs) { - SDValue Load = DAG.getLoad(PtrVT, dl, Chain, AddArg, NULL, 0); + SDValue Load = DAG.getLoad(PtrVT, dl, Chain, AddArg, NULL, 0, + false, false, 0); MemOpChains.push_back(Load.getValue(1)); RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); ArgOffset += PtrByteSize; @@ -3092,19 +3115,22 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, RegsToPass.push_back(std::make_pair(FPR[FPR_idx++], Arg)); if (isVarArg) { - SDValue Store = DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0); + SDValue Store = DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + false, false, 0); MemOpChains.push_back(Store); // Float varargs are always shadowed in available integer registers if (GPR_idx != NumGPRs) { - SDValue Load = DAG.getLoad(PtrVT, dl, Store, PtrOff, NULL, 0); + SDValue Load = DAG.getLoad(PtrVT, dl, Store, PtrOff, NULL, 0, + false, false, 0); MemOpChains.push_back(Load.getValue(1)); RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); } if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && !isPPC64){ SDValue ConstFour = DAG.getConstant(4, PtrOff.getValueType()); PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, ConstFour); - SDValue Load = DAG.getLoad(PtrVT, dl, Store, PtrOff, NULL, 0); + SDValue Load = DAG.getLoad(PtrVT, dl, Store, PtrOff, NULL, 0, + false, false, 0); MemOpChains.push_back(Load.getValue(1)); RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); } @@ -3147,10 +3173,12 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, // entirely in R registers. Maybe later. PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, DAG.getConstant(ArgOffset, PtrVT)); - SDValue Store = DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0); + SDValue Store = DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0, + false, false, 0); MemOpChains.push_back(Store); if (VR_idx != NumVRs) { - SDValue Load = DAG.getLoad(MVT::v4f32, dl, Store, PtrOff, NULL, 0); + SDValue Load = DAG.getLoad(MVT::v4f32, dl, Store, PtrOff, NULL, 0, + false, false, 0); MemOpChains.push_back(Load.getValue(1)); RegsToPass.push_back(std::make_pair(VR[VR_idx++], Load)); } @@ -3160,7 +3188,8 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, break; SDValue Ix = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, DAG.getConstant(i, PtrVT)); - SDValue Load = DAG.getLoad(PtrVT, dl, Store, Ix, NULL, 0); + SDValue Load = DAG.getLoad(PtrVT, dl, Store, Ix, NULL, 0, + false, false, 0); MemOpChains.push_back(Load.getValue(1)); RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); } @@ -3225,7 +3254,8 @@ PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, // TOC save area offset. SDValue PtrOff = DAG.getIntPtrConstant(40); SDValue AddPtr = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff); - Chain = DAG.getStore(Val.getValue(1), dl, Val, AddPtr, NULL, 0); + Chain = DAG.getStore(Val.getValue(1), dl, Val, AddPtr, NULL, 0, + false, false, 0); } // Build a sequence of copy-to-reg nodes chained together with token chain @@ -3300,13 +3330,15 @@ SDValue PPCTargetLowering::LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG, SDValue SaveSP = Op.getOperand(1); // Load the old link SP. - SDValue LoadLinkSP = DAG.getLoad(PtrVT, dl, Chain, StackPtr, NULL, 0); + SDValue LoadLinkSP = DAG.getLoad(PtrVT, dl, Chain, StackPtr, NULL, 0, + false, false, 0); // Restore the stack pointer. Chain = DAG.getCopyToReg(LoadLinkSP.getValue(1), dl, SP, SaveSP); // Store the old link SP. - return DAG.getStore(Chain, dl, LoadLinkSP, StackPtr, NULL, 0); + return DAG.getStore(Chain, dl, LoadLinkSP, StackPtr, NULL, 0, + false, false, 0); } @@ -3483,14 +3515,16 @@ SDValue PPCTargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, SDValue FIPtr = DAG.CreateStackTemporary(MVT::f64); // Emit a store to the stack slot. - SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl, Tmp, FIPtr, NULL, 0); + SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl, Tmp, FIPtr, NULL, 0, + false, false, 0); // Result is a load from the stack slot. If loading 4 bytes, make sure to // add in a bias. if (Op.getValueType() == MVT::i32) FIPtr = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, DAG.getConstant(4, FIPtr.getValueType())); - return DAG.getLoad(Op.getValueType(), dl, Chain, FIPtr, NULL, 0); + return DAG.getLoad(Op.getValueType(), dl, Chain, FIPtr, NULL, 0, + false, false, 0); } SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) { @@ -3533,7 +3567,7 @@ SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) { DAG.getMemIntrinsicNode(PPCISD::STD_32, dl, DAG.getVTList(MVT::Other), Ops, 4, MVT::i64, MMO); // Load the value as a double. - SDValue Ld = DAG.getLoad(MVT::f64, dl, Store, FIdx, NULL, 0); + SDValue Ld = DAG.getLoad(MVT::f64, dl, Store, FIdx, NULL, 0, false, false, 0); // FCFID it and return it. SDValue FP = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Ld); @@ -3578,12 +3612,13 @@ SDValue PPCTargetLowering::LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) { int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8, false); SDValue StackSlot = DAG.getFrameIndex(SSFI, PtrVT); SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Chain, - StackSlot, NULL, 0); + StackSlot, NULL, 0, false, false, 0); // Load FP Control Word from low 32 bits of stack slot. SDValue Four = DAG.getConstant(4, PtrVT); SDValue Addr = DAG.getNode(ISD::ADD, dl, PtrVT, StackSlot, Four); - SDValue CWD = DAG.getLoad(MVT::i32, dl, Store, Addr, NULL, 0); + SDValue CWD = DAG.getLoad(MVT::i32, dl, Store, Addr, NULL, 0, + false, false, 0); // Transform as necessary SDValue CWD1 = @@ -4249,9 +4284,11 @@ SDValue PPCTargetLowering::LowerSCALAR_TO_VECTOR(SDValue Op, // Store the input value into Value#0 of the stack slot. SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, - Op.getOperand(0), FIdx, NULL, 0); + Op.getOperand(0), FIdx, NULL, 0, + false, false, 0); // Load it out. - return DAG.getLoad(Op.getValueType(), dl, Store, FIdx, NULL, 0); + return DAG.getLoad(Op.getValueType(), dl, Store, FIdx, NULL, 0, + false, false, 0); } SDValue PPCTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) { @@ -5460,7 +5497,8 @@ SDValue PPCTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { // to the stack. FuncInfo->setLRStoreRequired(); return DAG.getLoad(getPointerTy(), dl, - DAG.getEntryNode(), RetAddrFI, NULL, 0); + DAG.getEntryNode(), RetAddrFI, NULL, 0, + false, false, 0); } SDValue PPCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td index 219efb994a..a0781b9870 100644 --- a/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/lib/Target/PowerPC/PPCInstr64Bit.td @@ -366,7 +366,7 @@ def ADDE8 : XOForm_1<31, 138, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), [(set G8RC:$rT, (adde G8RC:$rA, G8RC:$rB))]>; def ADDME8 : XOForm_3<31, 234, 0, (outs G8RC:$rT), (ins G8RC:$rA), "addme $rT, $rA", IntGeneral, - [(set G8RC:$rT, (adde G8RC:$rA, immAllOnes))]>; + [(set G8RC:$rT, (adde G8RC:$rA, -1))]>; def ADDZE8 : XOForm_3<31, 202, 0, (outs G8RC:$rT), (ins G8RC:$rA), "addze $rT, $rA", IntGeneral, [(set G8RC:$rT, (adde G8RC:$rA, 0))]>; @@ -375,7 +375,7 @@ def SUBFE8 : XOForm_1<31, 136, 0, (outs G8RC:$rT), (ins G8RC:$rA, G8RC:$rB), [(set G8RC:$rT, (sube G8RC:$rB, G8RC:$rA))]>; def SUBFME8 : XOForm_3<31, 232, 0, (outs G8RC:$rT), (ins G8RC:$rA), "subfme $rT, $rA", IntGeneral, - [(set G8RC:$rT, (sube immAllOnes, G8RC:$rA))]>; + [(set G8RC:$rT, (sube -1, G8RC:$rA))]>; def SUBFZE8 : XOForm_3<31, 200, 0, (outs G8RC:$rT), (ins G8RC:$rA), "subfze $rT, $rA", IntGeneral, [(set G8RC:$rT, (sube 0, G8RC:$rA))]>; @@ -635,13 +635,6 @@ def STHU8 : DForm_1<45, (outs ptr_rc:$ea_res), (ins G8RC:$rS, (pre_truncsti16 G8RC:$rS, ptr_rc:$ptrreg, iaddroff:$ptroff))]>, RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; -def STWU8 : DForm_1<37, (outs ptr_rc:$ea_res), (ins G8RC:$rS, - symbolLo:$ptroff, ptr_rc:$ptrreg), - "stwu $rS, $ptroff($ptrreg)", LdStGeneral, - [(set ptr_rc:$ea_res, (pre_store G8RC:$rS, ptr_rc:$ptrreg, - iaddroff:$ptroff))]>, - RegConstraint<"$ptrreg = $ea_res">, NoEncode<"$ea_res">; - def STDU : DSForm_1<62, 1, (outs ptr_rc:$ea_res), (ins G8RC:$rS, s16immX4:$ptroff, ptr_rc:$ptrreg), diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp b/lib/Target/PowerPC/PPCInstrInfo.cpp index af7d812c04..9895bea122 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -19,6 +19,7 @@ #include "PPCTargetMachine.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -73,8 +74,7 @@ bool PPCInstrInfo::isMoveInstr(const MachineInstr& MI, destReg = MI.getOperand(0).getReg(); return true; } - } else if (oc == PPC::FMRS || oc == PPC::FMRD || - oc == PPC::FMRSD) { // fmr r1, r2 + } else if (oc == PPC::FMR || oc == PPC::FMRSD) { // fmr r1, r2 assert(MI.getNumOperands() >= 2 && MI.getOperand(0).isReg() && MI.getOperand(1).isReg() && @@ -344,10 +344,9 @@ bool PPCInstrInfo::copyRegToReg(MachineBasicBlock &MBB, BuildMI(MBB, MI, DL, get(PPC::OR), DestReg).addReg(SrcReg).addReg(SrcReg); } else if (DestRC == PPC::G8RCRegisterClass) { BuildMI(MBB, MI, DL, get(PPC::OR8), DestReg).addReg(SrcReg).addReg(SrcReg); - } else if (DestRC == PPC::F4RCRegisterClass) { - BuildMI(MBB, MI, DL, get(PPC::FMRS), DestReg).addReg(SrcReg); - } else if (DestRC == PPC::F8RCRegisterClass) { - BuildMI(MBB, MI, DL, get(PPC::FMRD), DestReg).addReg(SrcReg); + } else if (DestRC == PPC::F4RCRegisterClass || + DestRC == PPC::F8RCRegisterClass) { + BuildMI(MBB, MI, DL, get(PPC::FMR), DestReg).addReg(SrcReg); } else if (DestRC == PPC::CRRCRegisterClass) { BuildMI(MBB, MI, DL, get(PPC::MCRF), DestReg).addReg(SrcReg); } else if (DestRC == PPC::VRRCRegisterClass) { @@ -421,22 +420,30 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF, FrameIdx)); return true; } else { - // FIXME: We use R0 here, because it isn't available for RA. We need to - // store the CR in the low 4-bits of the saved value. First, issue a MFCR - // to save all of the CRBits. - NewMIs.push_back(BuildMI(MF, DL, get(PPC::MFCR), PPC::R0)); + // FIXME: We need a scatch reg here. The trouble with using R0 is that + // it's possible for the stack frame to be so big the save location is + // out of range of immediate offsets, necessitating another register. + // We hack this on Darwin by reserving R2. It's probably broken on Linux + // at the moment. + + // We need to store the CR in the low 4-bits of the saved value. First, + // issue a MFCR to save all of the CRBits. + unsigned ScratchReg = TM.getSubtargetImpl()->isDarwinABI() ? + PPC::R2 : PPC::R0; + NewMIs.push_back(BuildMI(MF, DL, get(PPC::MFCR), ScratchReg)); // If the saved register wasn't CR0, shift the bits left so that they are // in CR0's slot. if (SrcReg != PPC::CR0) { unsigned ShiftBits = PPCRegisterInfo::getRegisterNumbering(SrcReg)*4; - // rlwinm r0, r0, ShiftBits, 0, 31. - NewMIs.push_back(BuildMI(MF, DL, get(PPC::RLWINM), PPC::R0) - .addReg(PPC::R0).addImm(ShiftBits).addImm(0).addImm(31)); + // rlwinm scratch, scratch, ShiftBits, 0, 31. + NewMIs.push_back(BuildMI(MF, DL, get(PPC::RLWINM), ScratchReg) + .addReg(ScratchReg).addImm(ShiftBits) + .addImm(0).addImm(31)); } NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::STW)) - .addReg(PPC::R0, + .addReg(ScratchReg, getKillRegState(isKill)), FrameIdx)); } @@ -540,20 +547,28 @@ PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL, NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LFS), DestReg), FrameIdx)); } else if (RC == PPC::CRRCRegisterClass) { - // FIXME: We use R0 here, because it isn't available for RA. - NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ), PPC::R0), - FrameIdx)); + // FIXME: We need a scatch reg here. The trouble with using R0 is that + // it's possible for the stack frame to be so big the save location is + // out of range of immediate offsets, necessitating another register. + // We hack this on Darwin by reserving R2. It's probably broken on Linux + // at the moment. + unsigned ScratchReg = TM.getSubtargetImpl()->isDarwinABI() ? + PPC::R2 : PPC::R0; + NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LWZ), + ScratchReg), FrameIdx)); // If the reloaded register isn't CR0, shift the bits right so that they are // in the right CR's slot. if (DestReg != PPC::CR0) { unsigned ShiftBits = PPCRegisterInfo::getRegisterNumbering(DestReg)*4; // rlwinm r11, r11, 32-ShiftBits, 0, 31. - NewMIs.push_back(BuildMI(MF, DL, get(PPC::RLWINM), PPC::R0) - .addReg(PPC::R0).addImm(32-ShiftBits).addImm(0).addImm(31)); + NewMIs.push_back(BuildMI(MF, DL, get(PPC::RLWINM), ScratchReg) + .addReg(ScratchReg).addImm(32-ShiftBits).addImm(0) + .addImm(31)); } - NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTCRF), DestReg).addReg(PPC::R0)); + NewMIs.push_back(BuildMI(MF, DL, get(PPC::MTCRF), DestReg) + .addReg(ScratchReg)); } else if (RC == PPC::CRBITRCRegisterClass) { unsigned Reg = 0; @@ -672,33 +687,21 @@ MachineInstr *PPCInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, getUndefRegState(isUndef)), FrameIndex); } - } else if (Opc == PPC::FMRD) { - if (OpNum == 0) { // move -> store - unsigned InReg = MI->getOperand(1).getReg(); - bool isKill = MI->getOperand(1).isKill(); - bool isUndef = MI->getOperand(1).isUndef(); - NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::STFD)) - .addReg(InReg, - getKillRegState(isKill) | - getUndefRegState(isUndef)), - FrameIndex); - } else { // move -> load - unsigned OutReg = MI->getOperand(0).getReg(); - bool isDead = MI->getOperand(0).isDead(); - bool isUndef = MI->getOperand(0).isUndef(); - NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::LFD)) - .addReg(OutReg, - RegState::Define | - getDeadRegState(isDead) | - getUndefRegState(isUndef)), - FrameIndex); - } - } else if (Opc == PPC::FMRS) { + } else if (Opc == PPC::FMR || Opc == PPC::FMRSD) { + // The register may be F4RC or F8RC, and that determines the memory op. + unsigned OrigReg = MI->getOperand(OpNum).getReg(); + // We cannot tell the register class from a physreg alone. + if (TargetRegisterInfo::isPhysicalRegister(OrigReg)) + return NULL; + const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(OrigReg); + const bool is64 = RC == PPC::F8RCRegisterClass; + if (OpNum == 0) { // move -> store unsigned InReg = MI->getOperand(1).getReg(); bool isKill = MI->getOperand(1).isKill(); bool isUndef = MI->getOperand(1).isUndef(); - NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::STFS)) + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), + get(is64 ? PPC::STFD : PPC::STFS)) .addReg(InReg, getKillRegState(isKill) | getUndefRegState(isUndef)), @@ -707,7 +710,8 @@ MachineInstr *PPCInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, unsigned OutReg = MI->getOperand(0).getReg(); bool isDead = MI->getOperand(0).isDead(); bool isUndef = MI->getOperand(0).isUndef(); - NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), get(PPC::LFS)) + NewMI = addFrameReference(BuildMI(MF, MI->getDebugLoc(), + get(is64 ? PPC::LFD : PPC::LFS)) .addReg(OutReg, RegState::Define | getDeadRegState(isDead) | @@ -733,7 +737,7 @@ bool PPCInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, else if ((Opc == PPC::OR8 && MI->getOperand(1).getReg() == MI->getOperand(2).getReg())) return true; - else if (Opc == PPC::FMRD || Opc == PPC::FMRS) + else if (Opc == PPC::FMR || Opc == PPC::FMRSD) return true; return false; diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 842f8ee089..845cd8f3a7 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -1019,20 +1019,16 @@ let Uses = [RM] in { } } -/// FMR is split into 3 versions, one for 4/8 byte FP, and one for extending. +/// FMR is split into 2 versions, one for 4/8 byte FP, and one for extending. /// /// Note that these are defined as pseudo-ops on the PPC970 because they are /// often coalesced away and we don't want the dispatch group builder to think /// that they will fill slots (which could cause the load of a LSU reject to /// sneak into a d-group with a store). -def FMRS : XForm_26<63, 72, (outs F4RC:$frD), (ins F4RC:$frB), - "fmr $frD, $frB", FPGeneral, - []>, // (set F4RC:$frD, F4RC:$frB) - PPC970_Unit_Pseudo; -def FMRD : XForm_26<63, 72, (outs F8RC:$frD), (ins F8RC:$frB), - "fmr $frD, $frB", FPGeneral, - []>, // (set F8RC:$frD, F8RC:$frB) - PPC970_Unit_Pseudo; +def FMR : XForm_26<63, 72, (outs F4RC:$frD), (ins F4RC:$frB), + "fmr $frD, $frB", FPGeneral, + []>, // (set F4RC:$frD, F4RC:$frB) + PPC970_Unit_Pseudo; def FMRSD : XForm_26<63, 72, (outs F8RC:$frD), (ins F4RC:$frB), "fmr $frD, $frB", FPGeneral, [(set F8RC:$frD, (fextend F4RC:$frB))]>, @@ -1215,7 +1211,7 @@ def ADDE : XOForm_1<31, 138, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), [(set GPRC:$rT, (adde GPRC:$rA, GPRC:$rB))]>; def ADDME : XOForm_3<31, 234, 0, (outs GPRC:$rT), (ins GPRC:$rA), "addme $rT, $rA", IntGeneral, - [(set GPRC:$rT, (adde GPRC:$rA, immAllOnes))]>; + [(set GPRC:$rT, (adde GPRC:$rA, -1))]>; def ADDZE : XOForm_3<31, 202, 0, (outs GPRC:$rT), (ins GPRC:$rA), "addze $rT, $rA", IntGeneral, [(set GPRC:$rT, (adde GPRC:$rA, 0))]>; @@ -1224,7 +1220,7 @@ def SUBFE : XOForm_1<31, 136, 0, (outs GPRC:$rT), (ins GPRC:$rA, GPRC:$rB), [(set GPRC:$rT, (sube GPRC:$rB, GPRC:$rA))]>; def SUBFME : XOForm_3<31, 232, 0, (outs GPRC:$rT), (ins GPRC:$rA), "subfme $rT, $rA", IntGeneral, - [(set GPRC:$rT, (sube immAllOnes, GPRC:$rA))]>; + [(set GPRC:$rT, (sube -1, GPRC:$rA))]>; def SUBFZE : XOForm_3<31, 200, 0, (outs GPRC:$rT), (ins GPRC:$rA), "subfze $rT, $rA", IntGeneral, [(set GPRC:$rT, (sube 0, GPRC:$rA))]>; @@ -1480,11 +1476,11 @@ def : Pat<(extloadf32 xaddr:$src), (FMRSD (LFSX xaddr:$src))>; // Memory barriers -def : Pat<(membarrier (i32 imm:$ll), - (i32 imm:$ls), - (i32 imm:$sl), - (i32 imm:$ss), - (i32 imm:$device)), +def : Pat<(membarrier (i32 imm /*ll*/), + (i32 imm /*ls*/), + (i32 imm /*sl*/), + (i32 imm /*ss*/), + (i32 imm /*device*/)), (SYNC)>; include "PPCInstrAltivec.td" diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index 20e77e79c5..0b509ac161 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -427,6 +427,12 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const { Reserved.set(PPC::R2); // System-reserved register Reserved.set(PPC::R13); // Small Data Area pointer register } + // Reserve R2 on Darwin to hack around the problem of save/restore of CR + // when the stack frame is too big to address directly; we need two regs. + // This is a hack. + if (Subtarget.isDarwinABI()) { + Reserved.set(PPC::R2); + } // On PPC64, r13 is the thread pointer. Never allocate this register. // Note that this is over conservative, as it also prevents allocation of R31 @@ -447,6 +453,12 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const { if (Subtarget.isSVR4ABI()) { Reserved.set(PPC::X2); } + // Reserve R2 on Darwin to hack around the problem of save/restore of CR + // when the stack frame is too big to address directly; we need two regs. + // This is a hack. + if (Subtarget.isDarwinABI()) { + Reserved.set(PPC::X2); + } } if (needsFP(MF)) diff --git a/lib/Target/PowerPC/PPCRegisterInfo.td b/lib/Target/PowerPC/PPCRegisterInfo.td index 049e893e82..1cb7340c9c 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.td +++ b/lib/Target/PowerPC/PPCRegisterInfo.td @@ -287,10 +287,8 @@ def GPRC : RegisterClass<"PPC", [i32], 32, GPRCClass::allocation_order_begin(const MachineFunction &MF) const { // 32-bit SVR4 ABI: r2 is reserved for the OS. // 64-bit SVR4 ABI: r2 is reserved for the TOC pointer. - if (!MF.getTarget().getSubtarget().isDarwin()) - return begin()+1; - - return begin(); + // Darwin: R2 is reserved for CR save/restore sequence. + return begin()+1; } GPRCClass::iterator GPRCClass::allocation_order_end(const MachineFunction &MF) const { @@ -325,10 +323,8 @@ def G8RC : RegisterClass<"PPC", [i64], 64, G8RCClass::iterator G8RCClass::allocation_order_begin(const MachineFunction &MF) const { // 64-bit SVR4 ABI: r2 is reserved for the TOC pointer. - if (!MF.getTarget().getSubtarget().isDarwin()) - return begin()+1; - - return begin(); + // Darwin: r2 is reserved for CR save/restore sequence. + return begin()+1; } G8RCClass::iterator G8RCClass::allocation_order_end(const MachineFunction &MF) const { diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp index 22eecd4fea..cac69622ca 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -115,32 +115,3 @@ bool PPCTargetMachine::addCodeEmitter(PassManagerBase &PM, return false; } - -/// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are 4-byte, -/// 8-byte, and target default. The CIE is hard-coded to indicate that the LSDA -/// pointer in the FDE section is an "sdata4", and should be encoded as a 4-byte -/// pointer by default. However, some systems may require a different size due -/// to bugs or other conditions. We will default to a 4-byte encoding unless the -/// system tells us otherwise. -/// -/// The issue is when the CIE says their is an LSDA. That mandates that every -/// FDE have an LSDA slot. But if the function does not need an LSDA. There -/// needs to be some way to signify there is none. The LSDA is encoded as -/// pc-rel. But you don't look for some magic value after adding the pc. You -/// have to look for a zero before adding the pc. The problem is that the size -/// of the zero to look for depends on the encoding. The unwinder bug in SL is -/// that it always checks for a pointer-size zero. So on x86_64 it looks for 8 -/// bytes of zero. If you have an LSDA, it works fine since the 8-bytes are -/// non-zero so it goes ahead and then reads the value based on the encoding. -/// But if you use sdata4 and there is no LSDA, then the test for zero gives a -/// false negative and the unwinder thinks there is an LSDA. -/// -/// FIXME: This call-back isn't good! We should be using the correct encoding -/// regardless of the system. However, there are some systems which have bugs -/// that prevent this from occuring. -DwarfLSDAEncoding::Encoding PPCTargetMachine::getLSDAEncoding() const { - if (Subtarget.isDarwin() && Subtarget.getDarwinVers() != 10) - return DwarfLSDAEncoding::Default; - - return DwarfLSDAEncoding::EightByte; -} diff --git a/lib/Target/PowerPC/PPCTargetMachine.h b/lib/Target/PowerPC/PPCTargetMachine.h index a654435684..ac9ae2b43f 100644 --- a/lib/Target/PowerPC/PPCTargetMachine.h +++ b/lib/Target/PowerPC/PPCTargetMachine.h @@ -57,18 +57,6 @@ public: return InstrItins; } - /// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are - /// 4-byte, 8-byte, and target default. The CIE is hard-coded to indicate that - /// the LSDA pointer in the FDE section is an "sdata4", and should be encoded - /// as a 4-byte pointer by default. However, some systems may require a - /// different size due to bugs or other conditions. We will default to a - /// 4-byte encoding unless the system tells us otherwise. - /// - /// FIXME: This call-back isn't good! We should be using the correct encoding - /// regardless of the system. However, there are some systems which have bugs - /// that prevent this from occuring. - virtual DwarfLSDAEncoding::Encoding getLSDAEncoding() const; - // Pass Pipeline Configuration virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); diff --git a/lib/Target/PowerPC/README.txt b/lib/Target/PowerPC/README.txt index 8f265cfc48..3465779e34 100644 --- a/lib/Target/PowerPC/README.txt +++ b/lib/Target/PowerPC/README.txt @@ -889,9 +889,26 @@ entry: ; recognize a more elaborate tree than a simple SETxx. define double @test_FNEG_sel(double %A, double %B, double %C) { - %D = sub double -0.000000e+00, %A ; [#uses=1] + %D = fsub double -0.000000e+00, %A ; [#uses=1] %Cond = fcmp ugt double %D, -0.000000e+00 ; [#uses=1] %E = select i1 %Cond, double %B, double %C ; [#uses=1] ret double %E } +//===----------------------------------------------------------------------===// +The save/restore sequence for CR in prolog/epilog is terrible: +- Each CR subreg is saved individually, rather than doing one save as a unit. +- On Darwin, the save is done after the decrement of SP, which means the offset +from SP of the save slot can be too big for a store instruction, which means we +need an additional register (currently hacked in 96015+96020; the solution there +is correct, but poor). +- On SVR4 the same thing can happen, and I don't think saving before the SP +decrement is safe on that target, as there is no red zone. This is currently +broken AFAIK, although it's not a target I can exercise. +The following demonstrates the problem: +extern void bar(char *p); +void foo() { + char x[100000]; + bar(x); + __asm__("" ::: "cr2"); +} diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp index 9a2ce6bec1..f6753a637c 100644 --- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp +++ b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp @@ -56,6 +56,9 @@ namespace { unsigned AsmVariant, const char *ExtraCode); bool printGetPCX(const MachineInstr *MI, unsigned OpNo); + + virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) + const; }; } // end of anonymous namespace @@ -140,18 +143,19 @@ bool SparcAsmPrinter::printGetPCX(const MachineInstr *MI, unsigned opNum) { break; } + unsigned mfNum = MI->getParent()->getParent()->getFunctionNumber(); unsigned bbNum = MI->getParent()->getNumber(); - O << '\n' << ".LLGETPCH" << bbNum << ":\n"; - O << "\tcall\t.LLGETPC" << bbNum << '\n' ; + O << '\n' << ".LLGETPCH" << mfNum << '_' << bbNum << ":\n"; + O << "\tcall\t.LLGETPC" << mfNum << '_' << bbNum << '\n' ; O << "\t sethi\t" - << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << bbNum << ")), " + << "%hi(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum << ")), " << operand << '\n' ; - O << ".LLGETPC" << bbNum << ":\n" ; + O << ".LLGETPC" << mfNum << '_' << bbNum << ":\n" ; O << "\tor\t" << operand - << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << bbNum << ")), " + << ", %lo(_GLOBAL_OFFSET_TABLE_+(.-.LLGETPCH" << mfNum << '_' << bbNum << ")), " << operand << '\n'; O << "\tadd\t" << operand << ", %o7, " << operand << '\n'; @@ -197,6 +201,39 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, return false; } +/// isBlockOnlyReachableByFallthough - Return true if the basic block has +/// exactly one predecessor and the control transfer mechanism between +/// the predecessor and this block is a fall-through. +/// +/// This overrides AsmPrinter's implementation to handle delay slots. +bool SparcAsmPrinter:: +isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { + // If this is a landing pad, it isn't a fall through. If it has no preds, + // then nothing falls through to it. + if (MBB->isLandingPad() || MBB->pred_empty()) + return false; + + // If there isn't exactly one predecessor, it can't be a fall through. + MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; + ++PI2; + if (PI2 != MBB->pred_end()) + return false; + + // The predecessor has to be immediately before this block. + const MachineBasicBlock *Pred = *PI; + + if (!Pred->isLayoutSuccessor(MBB)) + return false; + + // Check if the last terminator is an unconditional branch. + MachineBasicBlock::const_iterator I = Pred->end(); + while (I != Pred->begin() && !(--I)->getDesc().isTerminator()) + ; // Noop + return I == Pred->end() || !I->getDesc().isBarrier(); +} + + + // Force static initialization. extern "C" void LLVMInitializeSparcAsmPrinter() { RegisterAsmPrinter X(TheSparcTarget); diff --git a/lib/Target/Sparc/README.txt b/lib/Target/Sparc/README.txt index cc24abf728..b4991fe579 100644 --- a/lib/Target/Sparc/README.txt +++ b/lib/Target/Sparc/README.txt @@ -56,3 +56,4 @@ int %t1(int %a, int %b) { leaf fns. * Fill delay slots +* Implement JIT support diff --git a/lib/Target/Sparc/SparcISelDAGToDAG.cpp b/lib/Target/Sparc/SparcISelDAGToDAG.cpp index e1b32998b2..a7d1805e2a 100644 --- a/lib/Target/Sparc/SparcISelDAGToDAG.cpp +++ b/lib/Target/Sparc/SparcISelDAGToDAG.cpp @@ -35,7 +35,6 @@ class SparcDAGToDAGISel : public SelectionDAGISel { /// make the right decision when generating code for different targets. const SparcSubtarget &Subtarget; SparcTargetMachine& TM; - MachineBasicBlock *CurBB; public: explicit SparcDAGToDAGISel(SparcTargetMachine &tm) : SelectionDAGISel(tm), @@ -56,10 +55,6 @@ public: char ConstraintCode, std::vector &OutOps); - /// InstructionSelect - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelect(); - virtual const char *getPassName() const { return "SPARC DAG->DAG Pattern Instruction Selection"; } @@ -72,17 +67,8 @@ private: }; } // end anonymous namespace -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void SparcDAGToDAGISel::InstructionSelect() { - CurBB = BB; - // Select target instructions for the DAG. - SelectRoot(*CurDAG); - CurDAG->RemoveDeadNodes(); -} - SDNode* SparcDAGToDAGISel::getGlobalBaseReg() { - MachineFunction *MF = CurBB->getParent(); + MachineFunction *MF = BB->getParent(); unsigned GlobalBaseReg = TM.getInstrInfo()->getGlobalBaseReg(MF); return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode(); } diff --git a/lib/Target/Sparc/SparcISelLowering.cpp b/lib/Target/Sparc/SparcISelLowering.cpp index e67002a7db..4e93ef05a1 100644 --- a/lib/Target/Sparc/SparcISelLowering.cpp +++ b/lib/Target/Sparc/SparcISelLowering.cpp @@ -21,7 +21,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/ADT/VectorExtras.h" #include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -134,7 +134,8 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain, SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); SDValue Load; if (ObjectVT == MVT::i32) { - Load = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0); + Load = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0, + false, false, 0); } else { ISD::LoadExtType LoadOp = ISD::SEXTLOAD; @@ -143,7 +144,7 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain, FIPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, FIPtr, DAG.getConstant(Offset, MVT::i32)); Load = DAG.getExtLoad(LoadOp, dl, MVT::i32, Chain, FIPtr, - NULL, 0, ObjectVT); + NULL, 0, ObjectVT, false, false, 0); Load = DAG.getNode(ISD::TRUNCATE, dl, ObjectVT, Load); } InVals.push_back(Load); @@ -167,7 +168,8 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain, int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - SDValue Load = DAG.getLoad(MVT::f32, dl, Chain, FIPtr, NULL, 0); + SDValue Load = DAG.getLoad(MVT::f32, dl, Chain, FIPtr, NULL, 0, + false, false, 0); InVals.push_back(Load); } ArgOffset += 4; @@ -189,7 +191,8 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain, int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0); + HiVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0, + false, false, 0); } SDValue LoVal; @@ -201,7 +204,8 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain, int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, ArgOffset+4, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0); + LoVal = DAG.getLoad(MVT::i32, dl, Chain, FIPtr, NULL, 0, + false, false, 0); } // Compose the two halves together into an i64 unit. @@ -235,7 +239,8 @@ SparcTargetLowering::LowerFormalArguments(SDValue Chain, true, false); SDValue FIPtr = DAG.getFrameIndex(FrameIdx, MVT::i32); - OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0)); + OutChains.push_back(DAG.getStore(DAG.getRoot(), dl, Arg, FIPtr, NULL, 0, + false, false, 0)); ArgOffset += 4; } @@ -339,7 +344,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // FIXME: VERIFY THAT 68 IS RIGHT. SDValue PtrOff = DAG.getIntPtrConstant(VA.getLocMemOffset()+68); PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff); - MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0)); + MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0, + false, false, 0)); } #else @@ -385,14 +391,17 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, // out the parts as integers. Top part goes in a reg. SDValue StackPtr = DAG.CreateStackTemporary(MVT::f64, MVT::i32); SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, - Val, StackPtr, NULL, 0); + Val, StackPtr, NULL, 0, + false, false, 0); // Sparc is big-endian, so the high part comes first. - SDValue Hi = DAG.getLoad(MVT::i32, dl, Store, StackPtr, NULL, 0, 0); + SDValue Hi = DAG.getLoad(MVT::i32, dl, Store, StackPtr, NULL, 0, + false, false, 0); // Increment the pointer to the other half. StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr, DAG.getIntPtrConstant(4)); // Load the low part. - SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, NULL, 0, 0); + SDValue Lo = DAG.getLoad(MVT::i32, dl, Store, StackPtr, NULL, 0, + false, false, 0); RegsToPass.push_back(std::make_pair(ArgRegs[RegsToPass.size()], Hi)); @@ -435,7 +444,8 @@ SparcTargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue PtrOff = DAG.getConstant(ArgOffset, MVT::i32); PtrOff = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, PtrOff); MemOpChains.push_back(DAG.getStore(Chain, dl, ValToStore, - PtrOff, NULL, 0)); + PtrOff, NULL, 0, + false, false, 0)); } ArgOffset += ObjSize; } @@ -759,7 +769,7 @@ SDValue SparcTargetLowering::LowerGlobalAddress(SDValue Op, SDValue AbsAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, GlobalBase, RelAddr); return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), - AbsAddr, NULL, 0); + AbsAddr, NULL, 0, false, false, 0); } SDValue SparcTargetLowering::LowerConstantPool(SDValue Op, @@ -780,7 +790,7 @@ SDValue SparcTargetLowering::LowerConstantPool(SDValue Op, SDValue AbsAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, GlobalBase, RelAddr); return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), - AbsAddr, NULL, 0); + AbsAddr, NULL, 0, false, false, 0); } static SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { @@ -872,7 +882,8 @@ static SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG, DAG.getConstant(TLI.getVarArgsFrameOffset(), MVT::i32)); const Value *SV = cast(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, Offset, Op.getOperand(1), SV, 0); + return DAG.getStore(Op.getOperand(0), dl, Offset, Op.getOperand(1), SV, 0, + false, false, 0); } static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { @@ -882,21 +893,23 @@ static SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) { SDValue VAListPtr = Node->getOperand(1); const Value *SV = cast(Node->getOperand(2))->getValue(); DebugLoc dl = Node->getDebugLoc(); - SDValue VAList = DAG.getLoad(MVT::i32, dl, InChain, VAListPtr, SV, 0); + SDValue VAList = DAG.getLoad(MVT::i32, dl, InChain, VAListPtr, SV, 0, + false, false, 0); // Increment the pointer, VAList, to the next vaarg SDValue NextPtr = DAG.getNode(ISD::ADD, dl, MVT::i32, VAList, DAG.getConstant(VT.getSizeInBits()/8, MVT::i32)); // Store the incremented VAList to the legalized pointer InChain = DAG.getStore(VAList.getValue(1), dl, NextPtr, - VAListPtr, SV, 0); + VAListPtr, SV, 0, false, false, 0); // Load the actual argument out of the pointer VAList, unless this is an // f64 load. if (VT != MVT::f64) - return DAG.getLoad(VT, dl, InChain, VAList, NULL, 0); + return DAG.getLoad(VT, dl, InChain, VAList, NULL, 0, false, false, 0); // Otherwise, load it as i64, then do a bitconvert. - SDValue V = DAG.getLoad(MVT::i64, dl, InChain, VAList, NULL, 0); + SDValue V = DAG.getLoad(MVT::i64, dl, InChain, VAList, NULL, 0, + false, false, 0); // Bit-Convert the value to f64. SDValue Ops[2] = { diff --git a/lib/Target/Sparc/SparcMachineFunctionInfo.h b/lib/Target/Sparc/SparcMachineFunctionInfo.h index e457235ff6..56d8708dbe 100644 --- a/lib/Target/Sparc/SparcMachineFunctionInfo.h +++ b/lib/Target/Sparc/SparcMachineFunctionInfo.h @@ -22,7 +22,7 @@ namespace llvm { unsigned GlobalBaseReg; public: SparcMachineFunctionInfo() : GlobalBaseReg(0) {} - SparcMachineFunctionInfo(MachineFunction &MF) : GlobalBaseReg(0) {} + explicit SparcMachineFunctionInfo(MachineFunction &MF) : GlobalBaseReg(0) {} unsigned getGlobalBaseReg() const { return GlobalBaseReg; } void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; } diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index f6f632d576..8152e1dbe1 100644 --- a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -100,8 +100,6 @@ namespace { Lowering(*TM.getTargetLowering()), Subtarget(*TM.getSubtargetImpl()) { } - virtual void InstructionSelect(); - virtual const char *getPassName() const { return "SystemZ DAG->DAG Pattern Instruction Selection"; } @@ -152,10 +150,6 @@ namespace { bool MatchAddressBase(SDValue N, SystemZRRIAddressMode &AM); bool MatchAddressRI(SDValue N, SystemZRRIAddressMode &AM, bool is12Bit); - - #ifndef NDEBUG - unsigned Indent; - #endif }; } // end anonymous namespace @@ -594,41 +588,22 @@ bool SystemZDAGToDAGISel::SelectLAAddr(SDNode *Op, SDValue Addr, bool SystemZDAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N, SDValue &Base, SDValue &Disp, SDValue &Index) { if (ISD::isNON_EXTLoad(N.getNode()) && - N.hasOneUse() && - IsLegalAndProfitableToFold(N.getNode(), P, P)) + IsLegalToFold(N, P, P)) return SelectAddrRRI20(P, N.getOperand(1), Base, Disp, Index); return false; } -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void SystemZDAGToDAGISel::InstructionSelect() { - // Codegen the basic block. - DEBUG(errs() << "===== Instruction selection begins:\n"); - DEBUG(Indent = 0); - SelectRoot(*CurDAG); - DEBUG(errs() << "===== Instruction selection ends:\n"); - - CurDAG->RemoveDeadNodes(); -} - SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { EVT NVT = Node->getValueType(0); DebugLoc dl = Node->getDebugLoc(); unsigned Opcode = Node->getOpcode(); // Dump information about the Node being selected - DEBUG(errs().indent(Indent) << "Selecting: "; - Node->dump(CurDAG); - errs() << "\n"); - DEBUG(Indent += 2); + DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); // If we have a custom node, we already have selected! if (Node->isMachineOpcode()) { - DEBUG(errs().indent(Indent-2) << "== "; - Node->dump(CurDAG); - errs() << "\n"); - DEBUG(Indent -= 2); + DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); return NULL; // Already selected. } @@ -694,9 +669,7 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { MVT::i32)); ReplaceUses(SDValue(Node, 0), SDValue(Div, 0)); - DEBUG(errs().indent(Indent-2) << "=> "; - Result->dump(CurDAG); - errs() << "\n"); + DEBUG(errs() << "=> "; Result->dump(CurDAG); errs() << "\n"); } // Copy the remainder (even subreg) result, if it is needed. @@ -709,15 +682,9 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { MVT::i32)); ReplaceUses(SDValue(Node, 1), SDValue(Rem, 0)); - DEBUG(errs().indent(Indent-2) << "=> "; - Result->dump(CurDAG); - errs() << "\n"); + DEBUG(errs() << "=> "; Result->dump(CurDAG); errs() << "\n"); } -#ifndef NDEBUG - Indent -= 2; -#endif - return NULL; } case ISD::UDIVREM: { @@ -783,9 +750,7 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { CurDAG->getTargetConstant(SubRegIdx, MVT::i32)); ReplaceUses(SDValue(Node, 0), SDValue(Div, 0)); - DEBUG(errs().indent(Indent-2) << "=> "; - Result->dump(CurDAG); - errs() << "\n"); + DEBUG(errs() << "=> "; Result->dump(CurDAG); errs() << "\n"); } // Copy the remainder (even subreg) result, if it is needed. @@ -797,15 +762,9 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { CurDAG->getTargetConstant(SubRegIdx, MVT::i32)); ReplaceUses(SDValue(Node, 1), SDValue(Rem, 0)); - DEBUG(errs().indent(Indent-2) << "=> "; - Result->dump(CurDAG); - errs() << "\n"); + DEBUG(errs() << "=> "; Result->dump(CurDAG); errs() << "\n"); } -#ifndef NDEBUG - Indent -= 2; -#endif - return NULL; } } @@ -813,14 +772,12 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { // Select the default instruction SDNode *ResNode = SelectCode(Node); - DEBUG(errs().indent(Indent-2) << "=> "; + DEBUG(errs() << "=> "; if (ResNode == NULL || ResNode == Node) Node->dump(CurDAG); else ResNode->dump(CurDAG); errs() << "\n"; ); - DEBUG(Indent -= 2); - return ResNode; } diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index f7405a52de..6f4b30faaf 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -30,9 +30,9 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/CodeGen/ValueTypes.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -337,7 +337,8 @@ SystemZTargetLowering::LowerCCCArguments(SDValue Chain, // from this parameter SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); ArgValue = DAG.getLoad(LocVT, dl, Chain, FIN, - PseudoSourceValue::getFixedStack(FI), 0); + PseudoSourceValue::getFixedStack(FI), 0, + false, false, 0); } // If this is an 8/16/32-bit value, it is really passed promoted to 64 @@ -435,7 +436,8 @@ SystemZTargetLowering::LowerCCCCallTo(SDValue Chain, SDValue Callee, DAG.getIntPtrConstant(Offset)); MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, - PseudoSourceValue::getStack(), Offset)); + PseudoSourceValue::getStack(), Offset, + false, false, 0)); } } @@ -738,7 +740,7 @@ SDValue SystemZTargetLowering::LowerGlobalAddress(SDValue Op, if (ExtraLoadRequired) Result = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Result, - PseudoSourceValue::getGOT(), 0); + PseudoSourceValue::getGOT(), 0, false, false, 0); // If there was a non-zero offset that we didn't fold, create an explicit // addition for it. diff --git a/lib/Target/SystemZ/SystemZInstrFP.td b/lib/Target/SystemZ/SystemZInstrFP.td index 336e20ed89..f46840c46c 100644 --- a/lib/Target/SystemZ/SystemZInstrFP.td +++ b/lib/Target/SystemZ/SystemZInstrFP.td @@ -58,7 +58,7 @@ def FMOV64rr : Pseudo<(outs FP64:$dst), (ins FP64:$src), []>; } -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +let canFoldAsLoad = 1, isReMaterializable = 1 in { def FMOV32rm : Pseudo<(outs FP32:$dst), (ins rriaddr12:$src), "le\t{$dst, $src}", [(set FP32:$dst, (load rriaddr12:$src))]>; diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 1891bba2aa..a44f6d9754 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -257,7 +257,7 @@ def MOV64rihi32 : RILI<0xEC0, (outs GR64:$dst), (ins i64imm:$src), [(set GR64:$dst, i64hi32:$src)]>; } -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +let canFoldAsLoad = 1, isReMaterializable = 1 in { def MOV32rm : RXI<0x58, (outs GR32:$dst), (ins rriaddr12:$src), "l\t{$dst, $src}", diff --git a/lib/Target/SystemZ/SystemZMachineFunctionInfo.h b/lib/Target/SystemZ/SystemZMachineFunctionInfo.h index e47d41962e..fd6e330344 100644 --- a/lib/Target/SystemZ/SystemZMachineFunctionInfo.h +++ b/lib/Target/SystemZ/SystemZMachineFunctionInfo.h @@ -33,7 +33,8 @@ class SystemZMachineFunctionInfo : public MachineFunctionInfo { public: SystemZMachineFunctionInfo() : CalleeSavedFrameSize(0) {} - SystemZMachineFunctionInfo(MachineFunction &MF) : CalleeSavedFrameSize(0) {} + explicit SystemZMachineFunctionInfo(MachineFunction &MF) + : CalleeSavedFrameSize(0) {} unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; } void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; } diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp index 295b30fc36..9a168087ae 100644 --- a/lib/Target/TargetData.cpp +++ b/lib/Target/TargetData.cpp @@ -580,7 +580,7 @@ const IntegerType *TargetData::getIntPtrType(LLVMContext &C) const { uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices, unsigned NumIndices) const { const Type *Ty = ptrTy; - assert(isa(Ty) && "Illegal argument for getIndexedOffset()"); + assert(Ty->isPointerTy() && "Illegal argument for getIndexedOffset()"); uint64_t Result = 0; generic_gep_type_iterator diff --git a/lib/Target/TargetInstrInfo.cpp b/lib/Target/TargetInstrInfo.cpp index 094a57edb4..18b0fa435c 100644 --- a/lib/Target/TargetInstrInfo.cpp +++ b/lib/Target/TargetInstrInfo.cpp @@ -15,6 +15,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/ErrorHandling.h" +#include using namespace llvm; //===----------------------------------------------------------------------===// diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index a231ebc560..82619c73e2 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -19,17 +19,15 @@ #include "llvm/GlobalVariable.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCSectionMachO.h" -#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -289,832 +287,54 @@ TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind) const { } /// getSymbolForDwarfGlobalReference - Return an MCExpr to use for a -/// pc-relative reference to the specified global variable from exception -/// handling information. In addition to the symbol, this returns -/// by-reference: -/// -/// IsIndirect - True if the returned symbol is actually a stub that contains -/// the address of the symbol, false if the symbol is the global itself. -/// -/// IsPCRel - True if the symbol reference is already pc-relative, false if -/// the caller needs to subtract off the address of the reference from the -/// symbol. -/// +/// reference to the specified global variable from exception +/// handling information. const MCExpr *TargetLoweringObjectFile:: getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, - bool &IsIndirect, bool &IsPCRel) const { - // The generic implementation of this just returns a direct reference to the - // symbol. - IsIndirect = false; - IsPCRel = false; - + MachineModuleInfo *MMI, unsigned Encoding) const { // FIXME: Use GetGlobalValueSymbol. SmallString<128> Name; Mang->getNameWithPrefix(Name, GV, false); - return MCSymbolRefExpr::Create(Name.str(), getContext()); -} - - -//===----------------------------------------------------------------------===// -// ELF -//===----------------------------------------------------------------------===// -typedef StringMap ELFUniqueMapTy; - -TargetLoweringObjectFileELF::~TargetLoweringObjectFileELF() { - // If we have the section uniquing map, free it. - delete (ELFUniqueMapTy*)UniquingMap; -} - -const MCSection *TargetLoweringObjectFileELF:: -getELFSection(StringRef Section, unsigned Type, unsigned Flags, - SectionKind Kind, bool IsExplicit) const { - if (UniquingMap == 0) - UniquingMap = new ELFUniqueMapTy(); - ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)UniquingMap; - - // Do the lookup, if we have a hit, return it. - const MCSectionELF *&Entry = Map[Section]; - if (Entry) return Entry; - - return Entry = MCSectionELF::Create(Section, Type, Flags, Kind, IsExplicit, - getContext()); -} - -void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx, - const TargetMachine &TM) { - if (UniquingMap != 0) - ((ELFUniqueMapTy*)UniquingMap)->clear(); - TargetLoweringObjectFile::Initialize(Ctx, TM); - - BSSSection = - getELFSection(".bss", MCSectionELF::SHT_NOBITS, - MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, - SectionKind::getBSS()); - - TextSection = - getELFSection(".text", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_EXECINSTR | MCSectionELF::SHF_ALLOC, - SectionKind::getText()); - - DataSection = - getELFSection(".data", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC, - SectionKind::getDataRel()); - - ReadOnlySection = - getELFSection(".rodata", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC, - SectionKind::getReadOnly()); - - TLSDataSection = - getELFSection(".tdata", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | - MCSectionELF::SHF_WRITE, SectionKind::getThreadData()); - - TLSBSSSection = - getELFSection(".tbss", MCSectionELF::SHT_NOBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS | - MCSectionELF::SHF_WRITE, SectionKind::getThreadBSS()); - - DataRelSection = - getELFSection(".data.rel", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, - SectionKind::getDataRel()); - - DataRelLocalSection = - getELFSection(".data.rel.local", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, - SectionKind::getDataRelLocal()); - - DataRelROSection = - getELFSection(".data.rel.ro", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, - SectionKind::getReadOnlyWithRel()); - - DataRelROLocalSection = - getELFSection(".data.rel.ro.local", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, - SectionKind::getReadOnlyWithRelLocal()); - - MergeableConst4Section = - getELFSection(".rodata.cst4", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, - SectionKind::getMergeableConst4()); - - MergeableConst8Section = - getELFSection(".rodata.cst8", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, - SectionKind::getMergeableConst8()); - - MergeableConst16Section = - getELFSection(".rodata.cst16", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE, - SectionKind::getMergeableConst16()); - - StaticCtorSection = - getELFSection(".ctors", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, - SectionKind::getDataRel()); - - StaticDtorSection = - getELFSection(".dtors", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, - SectionKind::getDataRel()); - - // Exception Handling Sections. - - // FIXME: We're emitting LSDA info into a readonly section on ELF, even though - // it contains relocatable pointers. In PIC mode, this is probably a big - // runtime hit for C++ apps. Either the contents of the LSDA need to be - // adjusted or this should be a data section. - LSDASection = - getELFSection(".gcc_except_table", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC, SectionKind::getReadOnly()); - EHFrameSection = - getELFSection(".eh_frame", MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE, - SectionKind::getDataRel()); - - // Debug Info Sections. - DwarfAbbrevSection = - getELFSection(".debug_abbrev", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfInfoSection = - getELFSection(".debug_info", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfLineSection = - getELFSection(".debug_line", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfFrameSection = - getELFSection(".debug_frame", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfPubNamesSection = - getELFSection(".debug_pubnames", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfPubTypesSection = - getELFSection(".debug_pubtypes", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfStrSection = - getELFSection(".debug_str", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfLocSection = - getELFSection(".debug_loc", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfARangesSection = - getELFSection(".debug_aranges", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfRangesSection = - getELFSection(".debug_ranges", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); - DwarfMacroInfoSection = - getELFSection(".debug_macinfo", MCSectionELF::SHT_PROGBITS, 0, - SectionKind::getMetadata()); -} - - -static SectionKind -getELFKindForNamedSection(StringRef Name, SectionKind K) { - if (Name.empty() || Name[0] != '.') return K; - - // Some lame default implementation based on some magic section names. - if (Name == ".bss" || - Name.startswith(".bss.") || - Name.startswith(".gnu.linkonce.b.") || - Name.startswith(".llvm.linkonce.b.") || - Name == ".sbss" || - Name.startswith(".sbss.") || - Name.startswith(".gnu.linkonce.sb.") || - Name.startswith(".llvm.linkonce.sb.")) - return SectionKind::getBSS(); - - if (Name == ".tdata" || - Name.startswith(".tdata.") || - Name.startswith(".gnu.linkonce.td.") || - Name.startswith(".llvm.linkonce.td.")) - return SectionKind::getThreadData(); - - if (Name == ".tbss" || - Name.startswith(".tbss.") || - Name.startswith(".gnu.linkonce.tb.") || - Name.startswith(".llvm.linkonce.tb.")) - return SectionKind::getThreadBSS(); - - return K; -} - - -static unsigned getELFSectionType(StringRef Name, SectionKind K) { - - if (Name == ".init_array") - return MCSectionELF::SHT_INIT_ARRAY; - - if (Name == ".fini_array") - return MCSectionELF::SHT_FINI_ARRAY; + const MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); - if (Name == ".preinit_array") - return MCSectionELF::SHT_PREINIT_ARRAY; - - if (K.isBSS() || K.isThreadBSS()) - return MCSectionELF::SHT_NOBITS; - - return MCSectionELF::SHT_PROGBITS; -} - - -static unsigned -getELFSectionFlags(SectionKind K) { - unsigned Flags = 0; - - if (!K.isMetadata()) - Flags |= MCSectionELF::SHF_ALLOC; - - if (K.isText()) - Flags |= MCSectionELF::SHF_EXECINSTR; - - if (K.isWriteable()) - Flags |= MCSectionELF::SHF_WRITE; - - if (K.isThreadLocal()) - Flags |= MCSectionELF::SHF_TLS; - - // K.isMergeableConst() is left out to honour PR4650 - if (K.isMergeableCString() || K.isMergeableConst4() || - K.isMergeableConst8() || K.isMergeableConst16()) - Flags |= MCSectionELF::SHF_MERGE; - - if (K.isMergeableCString()) - Flags |= MCSectionELF::SHF_STRINGS; - - return Flags; -} - - -const MCSection *TargetLoweringObjectFileELF:: -getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const { - StringRef SectionName = GV->getSection(); - - // Infer section flags from the section name if we can. - Kind = getELFKindForNamedSection(SectionName, Kind); - - return getELFSection(SectionName, - getELFSectionType(SectionName, Kind), - getELFSectionFlags(Kind), Kind, true); -} - -static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { - if (Kind.isText()) return ".gnu.linkonce.t."; - if (Kind.isReadOnly()) return ".gnu.linkonce.r."; - - if (Kind.isThreadData()) return ".gnu.linkonce.td."; - if (Kind.isThreadBSS()) return ".gnu.linkonce.tb."; - - if (Kind.isDataNoRel()) return ".gnu.linkonce.d."; - if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local."; - if (Kind.isDataRel()) return ".gnu.linkonce.d.rel."; - if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local."; - - assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); - return ".gnu.linkonce.d.rel.ro."; + return getSymbolForDwarfReference(Sym, MMI, Encoding); } -const MCSection *TargetLoweringObjectFileELF:: -SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const { - - // If this global is linkonce/weak and the target handles this by emitting it - // into a 'uniqued' section name, create and return the section now. - if (GV->isWeakForLinker() && !Kind.isCommon() && !Kind.isBSS()) { - const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); - SmallString<128> Name; - Name.append(Prefix, Prefix+strlen(Prefix)); - Mang->getNameWithPrefix(Name, GV, false); - return getELFSection(Name.str(), getELFSectionType(Name.str(), Kind), - getELFSectionFlags(Kind), Kind); - } - - if (Kind.isText()) return TextSection; - - if (Kind.isMergeable1ByteCString() || - Kind.isMergeable2ByteCString() || - Kind.isMergeable4ByteCString()) { - - // We also need alignment here. - // FIXME: this is getting the alignment of the character, not the - // alignment of the global! - unsigned Align = - TM.getTargetData()->getPreferredAlignment(cast(GV)); - - const char *SizeSpec = ".rodata.str1."; - if (Kind.isMergeable2ByteCString()) - SizeSpec = ".rodata.str2."; - else if (Kind.isMergeable4ByteCString()) - SizeSpec = ".rodata.str4."; - else - assert(Kind.isMergeable1ByteCString() && "unknown string width"); - - - std::string Name = SizeSpec + utostr(Align); - return getELFSection(Name, MCSectionELF::SHT_PROGBITS, - MCSectionELF::SHF_ALLOC | - MCSectionELF::SHF_MERGE | - MCSectionELF::SHF_STRINGS, - Kind); - } - - if (Kind.isMergeableConst()) { - if (Kind.isMergeableConst4() && MergeableConst4Section) - return MergeableConst4Section; - if (Kind.isMergeableConst8() && MergeableConst8Section) - return MergeableConst8Section; - if (Kind.isMergeableConst16() && MergeableConst16Section) - return MergeableConst16Section; - return ReadOnlySection; // .const - } - - if (Kind.isReadOnly()) return ReadOnlySection; - - if (Kind.isThreadData()) return TLSDataSection; - if (Kind.isThreadBSS()) return TLSBSSSection; - - // Note: we claim that common symbols are put in BSSSection, but they are - // really emitted with the magic .comm directive, which creates a symbol table - // entry but not a section. - if (Kind.isBSS() || Kind.isCommon()) return BSSSection; - - if (Kind.isDataNoRel()) return DataSection; - if (Kind.isDataRelLocal()) return DataRelLocalSection; - if (Kind.isDataRel()) return DataRelSection; - if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; - - assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); - return DataRelROSection; -} - -/// getSectionForConstant - Given a mergeable constant with the -/// specified size and relocation information, return a section that it -/// should be placed in. -const MCSection *TargetLoweringObjectFileELF:: -getSectionForConstant(SectionKind Kind) const { - if (Kind.isMergeableConst4() && MergeableConst4Section) - return MergeableConst4Section; - if (Kind.isMergeableConst8() && MergeableConst8Section) - return MergeableConst8Section; - if (Kind.isMergeableConst16() && MergeableConst16Section) - return MergeableConst16Section; - if (Kind.isReadOnly()) - return ReadOnlySection; - - if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; - assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); - return DataRelROSection; -} - -//===----------------------------------------------------------------------===// -// MachO -//===----------------------------------------------------------------------===// - -typedef StringMap MachOUniqueMapTy; - -TargetLoweringObjectFileMachO::~TargetLoweringObjectFileMachO() { - // If we have the MachO uniquing map, free it. - delete (MachOUniqueMapTy*)UniquingMap; -} - - -const MCSectionMachO *TargetLoweringObjectFileMachO:: -getMachOSection(StringRef Segment, StringRef Section, - unsigned TypeAndAttributes, - unsigned Reserved2, SectionKind Kind) const { - // We unique sections by their segment/section pair. The returned section - // may not have the same flags as the requested section, if so this should be - // diagnosed by the client as an error. - - // Create the map if it doesn't already exist. - if (UniquingMap == 0) - UniquingMap = new MachOUniqueMapTy(); - MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)UniquingMap; - - // Form the name to look up. - SmallString<64> Name; - Name += Segment; - Name.push_back(','); - Name += Section; - - // Do the lookup, if we have a hit, return it. - const MCSectionMachO *&Entry = Map[Name.str()]; - if (Entry) return Entry; - - // Otherwise, return a new section. - return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes, - Reserved2, Kind, getContext()); -} - - -void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx, - const TargetMachine &TM) { - if (UniquingMap != 0) - ((MachOUniqueMapTy*)UniquingMap)->clear(); - TargetLoweringObjectFile::Initialize(Ctx, TM); - - TextSection // .text - = getMachOSection("__TEXT", "__text", - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - SectionKind::getText()); - DataSection // .data - = getMachOSection("__DATA", "__data", 0, SectionKind::getDataRel()); - - CStringSection // .cstring - = getMachOSection("__TEXT", "__cstring", MCSectionMachO::S_CSTRING_LITERALS, - SectionKind::getMergeable1ByteCString()); - UStringSection - = getMachOSection("__TEXT","__ustring", 0, - SectionKind::getMergeable2ByteCString()); - FourByteConstantSection // .literal4 - = getMachOSection("__TEXT", "__literal4", MCSectionMachO::S_4BYTE_LITERALS, - SectionKind::getMergeableConst4()); - EightByteConstantSection // .literal8 - = getMachOSection("__TEXT", "__literal8", MCSectionMachO::S_8BYTE_LITERALS, - SectionKind::getMergeableConst8()); - - // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back - // to using it in -static mode. - SixteenByteConstantSection = 0; - if (TM.getRelocationModel() != Reloc::Static && - TM.getTargetData()->getPointerSize() == 32) - SixteenByteConstantSection = // .literal16 - getMachOSection("__TEXT", "__literal16",MCSectionMachO::S_16BYTE_LITERALS, - SectionKind::getMergeableConst16()); - - ReadOnlySection // .const - = getMachOSection("__TEXT", "__const", 0, SectionKind::getReadOnly()); - - TextCoalSection - = getMachOSection("__TEXT", "__textcoal_nt", - MCSectionMachO::S_COALESCED | - MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS, - SectionKind::getText()); - ConstTextCoalSection - = getMachOSection("__TEXT", "__const_coal", MCSectionMachO::S_COALESCED, - SectionKind::getText()); - ConstDataCoalSection - = getMachOSection("__DATA","__const_coal", MCSectionMachO::S_COALESCED, - SectionKind::getText()); - ConstDataSection // .const_data - = getMachOSection("__DATA", "__const", 0, - SectionKind::getReadOnlyWithRel()); - DataCoalSection - = getMachOSection("__DATA","__datacoal_nt", MCSectionMachO::S_COALESCED, - SectionKind::getDataRel()); - DataCommonSection - = getMachOSection("__DATA","__common", MCSectionMachO::S_ZEROFILL, - SectionKind::getBSS()); - DataBSSSection - = getMachOSection("__DATA","__bss", MCSectionMachO::S_ZEROFILL, - SectionKind::getBSS()); - - - LazySymbolPointerSection - = getMachOSection("__DATA", "__la_symbol_ptr", - MCSectionMachO::S_LAZY_SYMBOL_POINTERS, - SectionKind::getMetadata()); - NonLazySymbolPointerSection - = getMachOSection("__DATA", "__nl_symbol_ptr", - MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS, - SectionKind::getMetadata()); - - if (TM.getRelocationModel() == Reloc::Static) { - StaticCtorSection - = getMachOSection("__TEXT", "__constructor", 0,SectionKind::getDataRel()); - StaticDtorSection - = getMachOSection("__TEXT", "__destructor", 0, SectionKind::getDataRel()); - } else { - StaticCtorSection - = getMachOSection("__DATA", "__mod_init_func", - MCSectionMachO::S_MOD_INIT_FUNC_POINTERS, - SectionKind::getDataRel()); - StaticDtorSection - = getMachOSection("__DATA", "__mod_term_func", - MCSectionMachO::S_MOD_TERM_FUNC_POINTERS, - SectionKind::getDataRel()); - } - - // Exception Handling. - LSDASection = getMachOSection("__DATA", "__gcc_except_tab", 0, - SectionKind::getDataRel()); - EHFrameSection = - getMachOSection("__TEXT", "__eh_frame", - MCSectionMachO::S_COALESCED | - MCSectionMachO::S_ATTR_NO_TOC | - MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS | - MCSectionMachO::S_ATTR_LIVE_SUPPORT, - SectionKind::getReadOnly()); - - // Debug Information. - DwarfAbbrevSection = - getMachOSection("__DWARF", "__debug_abbrev", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfInfoSection = - getMachOSection("__DWARF", "__debug_info", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfLineSection = - getMachOSection("__DWARF", "__debug_line", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfFrameSection = - getMachOSection("__DWARF", "__debug_frame", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfPubNamesSection = - getMachOSection("__DWARF", "__debug_pubnames", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfPubTypesSection = - getMachOSection("__DWARF", "__debug_pubtypes", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfStrSection = - getMachOSection("__DWARF", "__debug_str", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfLocSection = - getMachOSection("__DWARF", "__debug_loc", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfARangesSection = - getMachOSection("__DWARF", "__debug_aranges", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfRangesSection = - getMachOSection("__DWARF", "__debug_ranges", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfMacroInfoSection = - getMachOSection("__DWARF", "__debug_macinfo", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); - DwarfDebugInlineSection = - getMachOSection("__DWARF", "__debug_inlined", MCSectionMachO::S_ATTR_DEBUG, - SectionKind::getMetadata()); -} - -const MCSection *TargetLoweringObjectFileMachO:: -getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const { - // Parse the section specifier and create it if valid. - StringRef Segment, Section; - unsigned TAA, StubSize; - std::string ErrorCode = - MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section, - TAA, StubSize); - if (!ErrorCode.empty()) { - // If invalid, report the error with llvm_report_error. - llvm_report_error("Global variable '" + GV->getNameStr() + - "' has an invalid section specifier '" + GV->getSection()+ - "': " + ErrorCode + "."); - // Fall back to dropping it into the data section. - return DataSection; - } - - // Get the section. - const MCSectionMachO *S = - getMachOSection(Segment, Section, TAA, StubSize, Kind); - - // Okay, now that we got the section, verify that the TAA & StubSize agree. - // If the user declared multiple globals with different section flags, we need - // to reject it here. - if (S->getTypeAndAttributes() != TAA || S->getStubSize() != StubSize) { - // If invalid, report the error with llvm_report_error. - llvm_report_error("Global variable '" + GV->getNameStr() + - "' section type or attributes does not match previous" - " section specifier"); - } - - return S; -} - -const MCSection *TargetLoweringObjectFileMachO:: -SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const { - assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); - - if (Kind.isText()) - return GV->isWeakForLinker() ? TextCoalSection : TextSection; - - // If this is weak/linkonce, put this in a coalescable section, either in text - // or data depending on if it is writable. - if (GV->isWeakForLinker()) { - if (Kind.isReadOnly()) - return ConstTextCoalSection; - return DataCoalSection; - } - - // FIXME: Alignment check should be handled by section classifier. - if (Kind.isMergeable1ByteCString() || - Kind.isMergeable2ByteCString()) { - if (TM.getTargetData()->getPreferredAlignment( - cast(GV)) < 32) { - if (Kind.isMergeable1ByteCString()) - return CStringSection; - assert(Kind.isMergeable2ByteCString()); - return UStringSection; - } - } - - if (Kind.isMergeableConst()) { - if (Kind.isMergeableConst4()) - return FourByteConstantSection; - if (Kind.isMergeableConst8()) - return EightByteConstantSection; - if (Kind.isMergeableConst16() && SixteenByteConstantSection) - return SixteenByteConstantSection; - } - - // Otherwise, if it is readonly, but not something we can specially optimize, - // just drop it in .const. - if (Kind.isReadOnly()) - return ReadOnlySection; - - // If this is marked const, put it into a const section. But if the dynamic - // linker needs to write to it, put it in the data segment. - if (Kind.isReadOnlyWithRel()) - return ConstDataSection; - - // Put zero initialized globals with strong external linkage in the - // DATA, __common section with the .zerofill directive. - if (Kind.isBSSExtern()) - return DataCommonSection; - - // Put zero initialized globals with local linkage in __DATA,__bss directive - // with the .zerofill directive (aka .lcomm). - if (Kind.isBSSLocal()) - return DataBSSSection; - - // Otherwise, just drop the variable in the normal data section. - return DataSection; -} - -const MCSection * -TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind) const { - // If this constant requires a relocation, we have to put it in the data - // segment, not in the text segment. - if (Kind.isDataRel() || Kind.isReadOnlyWithRel()) - return ConstDataSection; - - if (Kind.isMergeableConst4()) - return FourByteConstantSection; - if (Kind.isMergeableConst8()) - return EightByteConstantSection; - if (Kind.isMergeableConst16() && SixteenByteConstantSection) - return SixteenByteConstantSection; - return ReadOnlySection; // .const -} - -/// shouldEmitUsedDirectiveFor - This hook allows targets to selectively decide -/// not to emit the UsedDirective for some symbols in llvm.used. -// FIXME: REMOVE this (rdar://7071300) -bool TargetLoweringObjectFileMachO:: -shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const { - /// On Darwin, internally linked data beginning with "L" or "l" does not have - /// the directive emitted (this occurs in ObjC metadata). - if (!GV) return false; - - // Check whether the mangled name has the "Private" or "LinkerPrivate" prefix. - if (GV->hasLocalLinkage() && !isa(GV)) { - // FIXME: ObjC metadata is currently emitted as internal symbols that have - // \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and - // this horrible hack can go away. - SmallString<64> Name; - Mang->getNameWithPrefix(Name, GV, false); - if (Name[0] == 'L' || Name[0] == 'l') - return false; +const MCExpr *TargetLoweringObjectFile:: +getSymbolForDwarfReference(const MCSymbol *Sym, MachineModuleInfo *MMI, + unsigned Encoding) const { + const MCExpr *Res = MCSymbolRefExpr::Create(Sym, getContext()); + + switch (Encoding & 0xF0) { + default: + llvm_report_error("We do not support this DWARF encoding yet!"); + break; + case dwarf::DW_EH_PE_absptr: + // Do nothing special + break; + case dwarf::DW_EH_PE_pcrel: + // FIXME: PCSymbol + const MCExpr *PC = MCSymbolRefExpr::Create(".", getContext()); + Res = MCBinaryExpr::CreateSub(Res, PC, getContext()); + break; } - return true; + return Res; } -const MCExpr *TargetLoweringObjectFileMachO:: -getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, - bool &IsIndirect, bool &IsPCRel) const { - // The mach-o version of this method defaults to returning a stub reference. - IsIndirect = true; - IsPCRel = false; - - SmallString<128> Name; - Mang->getNameWithPrefix(Name, GV, true); - Name += "$non_lazy_ptr"; - return MCSymbolRefExpr::Create(Name.str(), getContext()); +unsigned TargetLoweringObjectFile::getPersonalityEncoding() const { + return dwarf::DW_EH_PE_absptr; } - -//===----------------------------------------------------------------------===// -// COFF -//===----------------------------------------------------------------------===// - -typedef StringMap COFFUniqueMapTy; - -TargetLoweringObjectFileCOFF::~TargetLoweringObjectFileCOFF() { - delete (COFFUniqueMapTy*)UniquingMap; +unsigned TargetLoweringObjectFile::getLSDAEncoding() const { + return dwarf::DW_EH_PE_absptr; } - -const MCSection *TargetLoweringObjectFileCOFF:: -getCOFFSection(StringRef Name, bool isDirective, SectionKind Kind) const { - // Create the map if it doesn't already exist. - if (UniquingMap == 0) - UniquingMap = new MachOUniqueMapTy(); - COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)UniquingMap; - - // Do the lookup, if we have a hit, return it. - const MCSectionCOFF *&Entry = Map[Name]; - if (Entry) return Entry; - - return Entry = MCSectionCOFF::Create(Name, isDirective, Kind, getContext()); +unsigned TargetLoweringObjectFile::getFDEEncoding() const { + return dwarf::DW_EH_PE_absptr; } -void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx, - const TargetMachine &TM) { - if (UniquingMap != 0) - ((COFFUniqueMapTy*)UniquingMap)->clear(); - TargetLoweringObjectFile::Initialize(Ctx, TM); - TextSection = getCOFFSection("\t.text", true, SectionKind::getText()); - DataSection = getCOFFSection("\t.data", true, SectionKind::getDataRel()); - StaticCtorSection = - getCOFFSection(".ctors", false, SectionKind::getDataRel()); - StaticDtorSection = - getCOFFSection(".dtors", false, SectionKind::getDataRel()); - - // FIXME: We're emitting LSDA info into a readonly section on COFF, even - // though it contains relocatable pointers. In PIC mode, this is probably a - // big runtime hit for C++ apps. Either the contents of the LSDA need to be - // adjusted or this should be a data section. - LSDASection = - getCOFFSection(".gcc_except_table", false, SectionKind::getReadOnly()); - EHFrameSection = - getCOFFSection(".eh_frame", false, SectionKind::getDataRel()); - - // Debug info. - // FIXME: Don't use 'directive' mode here. - DwarfAbbrevSection = - getCOFFSection("\t.section\t.debug_abbrev,\"dr\"", - true, SectionKind::getMetadata()); - DwarfInfoSection = - getCOFFSection("\t.section\t.debug_info,\"dr\"", - true, SectionKind::getMetadata()); - DwarfLineSection = - getCOFFSection("\t.section\t.debug_line,\"dr\"", - true, SectionKind::getMetadata()); - DwarfFrameSection = - getCOFFSection("\t.section\t.debug_frame,\"dr\"", - true, SectionKind::getMetadata()); - DwarfPubNamesSection = - getCOFFSection("\t.section\t.debug_pubnames,\"dr\"", - true, SectionKind::getMetadata()); - DwarfPubTypesSection = - getCOFFSection("\t.section\t.debug_pubtypes,\"dr\"", - true, SectionKind::getMetadata()); - DwarfStrSection = - getCOFFSection("\t.section\t.debug_str,\"dr\"", - true, SectionKind::getMetadata()); - DwarfLocSection = - getCOFFSection("\t.section\t.debug_loc,\"dr\"", - true, SectionKind::getMetadata()); - DwarfARangesSection = - getCOFFSection("\t.section\t.debug_aranges,\"dr\"", - true, SectionKind::getMetadata()); - DwarfRangesSection = - getCOFFSection("\t.section\t.debug_ranges,\"dr\"", - true, SectionKind::getMetadata()); - DwarfMacroInfoSection = - getCOFFSection("\t.section\t.debug_macinfo,\"dr\"", - true, SectionKind::getMetadata()); -} - -const MCSection *TargetLoweringObjectFileCOFF:: -getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const { - return getCOFFSection(GV->getSection(), false, Kind); -} - -static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { - if (Kind.isText()) - return ".text$linkonce"; - if (Kind.isWriteable()) - return ".data$linkonce"; - return ".rdata$linkonce"; -} - - -const MCSection *TargetLoweringObjectFileCOFF:: -SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler *Mang, const TargetMachine &TM) const { - assert(!Kind.isThreadLocal() && "Doesn't support TLS"); - - // If this global is linkonce/weak and the target handles this by emitting it - // into a 'uniqued' section name, create and return the section now. - if (GV->isWeakForLinker()) { - const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind); - SmallString<128> Name(Prefix, Prefix+strlen(Prefix)); - Mang->getNameWithPrefix(Name, GV, false); - return getCOFFSection(Name.str(), false, Kind); - } - - if (Kind.isText()) - return getTextSection(); - - return getDataSection(); +unsigned TargetLoweringObjectFile::getTTypeEncoding() const { + return dwarf::DW_EH_PE_absptr; } diff --git a/lib/Target/X86/Android.mk b/lib/Target/X86/Android.mk new file mode 100644 index 0000000000..f5b8180045 --- /dev/null +++ b/lib/Target/X86/Android.mk @@ -0,0 +1,47 @@ +LOCAL_PATH := $(call my-dir) + +# For the host only +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +TBLGEN_TABLES := \ + X86GenRegisterInfo.h.inc \ + X86GenRegisterNames.inc \ + X86GenRegisterInfo.inc \ + X86GenInstrNames.inc \ + X86GenInstrInfo.inc \ + X86GenAsmMatcher.inc \ + X86GenDAGISel.inc \ + X86GenDisassemblerTables.inc \ + X86GenFastISel.inc \ + X86GenCallingConv.inc \ + X86GenSubtarget.inc \ + X86GenEDInfo.inc + +LOCAL_SRC_FILES := \ + X86AsmBackend.cpp \ + X86COFFMachineModuleInfo.cpp \ + X86CodeEmitter.cpp \ + X86ELFWriterInfo.cpp \ + X86FastISel.cpp \ + X86FloatingPoint.cpp \ + X86FloatingPointRegKill.cpp \ + X86ISelDAGToDAG.cpp \ + X86ISelLowering.cpp \ + X86InstrInfo.cpp \ + X86JITInfo.cpp \ + X86MCAsmInfo.cpp \ + X86MCCodeEmitter.cpp \ + X86MCTargetExpr.cpp \ + X86RegisterInfo.cpp \ + X86Subtarget.cpp \ + X86TargetMachine.cpp \ + X86TargetObjectFile.cpp + +LOCAL_MODULE:= libLLVMX86CodeGen + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index acf497a820..84d7bb7a6f 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -10,6 +10,7 @@ #include "llvm/Target/TargetAsmParser.h" #include "X86.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCExpr.h" @@ -183,6 +184,14 @@ struct X86Operand : public MCParsedAsmOperand { bool isReg() const { return Kind == Register; } + void addExpr(MCInst &Inst, const MCExpr *Expr) const { + // Add as immediates when possible. + if (const MCConstantExpr *CE = dyn_cast(Expr)) + Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + else + Inst.addOperand(MCOperand::CreateExpr(Expr)); + } + void addRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(getReg())); @@ -190,13 +199,13 @@ struct X86Operand : public MCParsedAsmOperand { void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateExpr(getImm())); + addExpr(Inst, getImm()); } void addImmSExt8Operands(MCInst &Inst, unsigned N) const { // FIXME: Support user customization of the render method. assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateExpr(getImm())); + addExpr(Inst, getImm()); } void addMemOperands(MCInst &Inst, unsigned N) const { @@ -204,7 +213,7 @@ struct X86Operand : public MCParsedAsmOperand { Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); Inst.addOperand(MCOperand::CreateImm(getMemScale())); Inst.addOperand(MCOperand::CreateReg(getMemIndexReg())); - Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); + addExpr(Inst, getMemDisp()); Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); } @@ -218,7 +227,7 @@ struct X86Operand : public MCParsedAsmOperand { Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); Inst.addOperand(MCOperand::CreateImm(getMemScale())); Inst.addOperand(MCOperand::CreateReg(getMemIndexReg())); - Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); + addExpr(Inst, getMemDisp()); } static X86Operand *CreateToken(StringRef Str, SMLoc Loc) { @@ -492,24 +501,20 @@ X86Operand *X86ATTAsmParser::ParseMemOperand() { bool X86ATTAsmParser:: ParseInstruction(const StringRef &Name, SMLoc NameLoc, SmallVectorImpl &Operands) { - // FIXME: Hack to recognize "sal..." for now. We need a way to represent - // alternative syntaxes in the .td file, without requiring instruction - // duplication. - if (Name.startswith("sal")) { - std::string Tmp = "shl" + Name.substr(3).str(); - Operands.push_back(X86Operand::CreateToken(Tmp, NameLoc)); - } else { - // FIXME: This is a hack. We eventually want to add a general pattern - // mechanism to be used in the table gen file for these assembly names that - // use the same opcodes. Also we should only allow the "alternate names" - // for rep and repne with the instructions they can only appear with. - StringRef PatchedName = Name; - if (Name == "repe" || Name == "repz") - PatchedName = "rep"; - else if (Name == "repnz") - PatchedName = "repne"; - Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); - } + // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to + // represent alternative syntaxes in the .td file, without requiring + // instruction duplication. + StringRef PatchedName = StringSwitch(Name) + .Case("sal", "shl") + .Case("salb", "shlb") + .Case("sall", "shll") + .Case("salq", "shlq") + .Case("salw", "shlw") + .Case("repe", "rep") + .Case("repz", "rep") + .Case("repnz", "repne") + .Default(Name); + Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); if (getLexer().isNot(AsmToken::EndOfStatement)) { diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp index 38ccbf9d50..734a545555 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp @@ -25,10 +25,15 @@ using namespace llvm; // Include the auto-generated portion of the assembly writer. #define MachineInstr MCInst +#define GET_INSTRUCTION_NAME #include "X86GenAsmWriter.inc" #undef MachineInstr void X86ATTInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); } +StringRef X86ATTInstPrinter::getOpcodeName(unsigned Opcode) const { + return getInstructionName(Opcode); +} + void X86ATTInstPrinter::printSSECC(const MCInst *MI, unsigned Op) { switch (MI->getOperand(Op).getImm()) { @@ -68,7 +73,7 @@ void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo) { O << '$' << Op.getImm(); if (CommentStream && (Op.getImm() > 255 || Op.getImm() < -256)) - *CommentStream << format("imm = 0x%X\n", Op.getImm()); + *CommentStream << format("imm = 0x%llX\n", (long long)Op.getImm()); } else { assert(Op.isExpr() && "unknown operand kind in printOperand"); diff --git a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h index 3180618d12..d109a075b8 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86ATTInstPrinter.h @@ -26,11 +26,12 @@ public: virtual void printInst(const MCInst *MI); - + virtual StringRef getOpcodeName(unsigned Opcode) const; + // Autogenerated by tblgen. void printInstruction(const MCInst *MI); static const char *getRegisterName(unsigned RegNo); - + static const char *getInstructionName(unsigned Opcode); void printOperand(const MCInst *MI, unsigned OpNo); void printMemReference(const MCInst *MI, unsigned Op); diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp index 304306d592..8cab24ca63 100644 --- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp @@ -33,10 +33,11 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/ADT/SmallString.h" @@ -52,40 +53,42 @@ void X86AsmPrinter::PrintPICBaseSymbol() const { OutContext); } +MCSymbol *X86AsmPrinter::GetGlobalValueSymbol(const GlobalValue *GV) const { + SmallString<60> NameStr; + Mang->getNameWithPrefix(NameStr, GV, false); + MCSymbol *Symb = OutContext.GetOrCreateSymbol(NameStr.str()); + + if (Subtarget->isTargetCygMing()) { + X86COFFMachineModuleInfo &COFFMMI = + MMI->getObjFileInfo(); + COFFMMI.DecorateCygMingName(Symb, OutContext, GV, *TM.getTargetData()); + + // Save function name for later type emission. + if (const Function *F = dyn_cast(GV)) + if (F->isDeclaration()) + COFFMMI.addExternalFunction(Symb->getName()); + + } + + return Symb; +} + /// runOnMachineFunction - Emit the function body. /// bool X86AsmPrinter::runOnMachineFunction(MachineFunction &MF) { SetupMachineFunction(MF); - - // COFF and Cygwin specific mangling stuff. This should be moved out to the - // mangler or handled some other way? - if (Subtarget->isTargetCOFF()) { - X86COFFMachineModuleInfo &COFFMMI = - MMI->getObjFileInfo(); - // Populate function information map. Don't want to populate - // non-stdcall or non-fastcall functions' information right now. - const Function *F = MF.getFunction(); - CallingConv::ID CC = F->getCallingConv(); - if (CC == CallingConv::X86_StdCall || CC == CallingConv::X86_FastCall) - COFFMMI.AddFunctionInfo(F, *MF.getInfo()); - } - if (Subtarget->isTargetCygMing()) { + if (Subtarget->isTargetCOFF()) { const Function *F = MF.getFunction(); - X86COFFMachineModuleInfo &COFFMMI = - MMI->getObjFileInfo(); - COFFMMI.DecorateCygMingName(CurrentFnSym, OutContext,F,*TM.getTargetData()); - - O << "\t.def\t " << *CurrentFnSym; - O << ";\t.scl\t" << + O << "\t.def\t " << *CurrentFnSym << ";\t.scl\t" << (F->hasInternalLinkage() ? COFF::C_STAT : COFF::C_EXT) << ";\t.type\t" << (COFF::DT_FCN << COFF::N_BTSHFT) << ";\t.endef\n"; } - + // Have common code print out the function header with linkage info etc. EmitFunctionHeader(); - + // Emit the rest of the function body. EmitFunctionBody(); @@ -119,12 +122,6 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO) { else GVSym = GetGlobalValueSymbol(GV); - if (Subtarget->isTargetCygMing()) { - X86COFFMachineModuleInfo &COFFMMI = - MMI->getObjFileInfo(); - COFFMMI.DecorateCygMingName(GVSym, OutContext, GV, *TM.getTargetData()); - } - // Handle dllimport linkage. if (MO.getTargetFlags() == X86II::MO_DLLIMPORT) GVSym = OutContext.GetOrCreateSymbol(Twine("__imp_") + GVSym->getName()); @@ -585,7 +582,6 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) if (I->hasDLLExportLinkage()) { MCSymbol *Sym = GetGlobalValueSymbol(I); - COFFMMI.DecorateCygMingName(Sym, OutContext, I, *TM.getTargetData()); DLLExportedFns.push_back(Sym); } @@ -607,6 +603,28 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { } } } + + if (Subtarget->isTargetELF()) { + TargetLoweringObjectFileELF &TLOFELF = + static_cast(getObjFileLowering()); + + MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo(); + + // Output stubs for external and common global variables. + MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList(); + if (!Stubs.empty()) { + OutStreamer.SwitchSection(TLOFELF.getDataRelSection()); + const TargetData *TD = TM.getTargetData(); + + for (unsigned i = 0, e = Stubs.size(); i != e; ++i) + O << *Stubs[i].first << ":\n" + << (TD->getPointerSize() == 8 ? + MAI->getData64bitsDirective() : MAI->getData32bitsDirective()) + << *Stubs[i].second << '\n'; + + Stubs.clear(); + } + } } diff --git a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h index 1d32a5f8d8..039214ac29 100644 --- a/lib/Target/X86/AsmPrinter/X86AsmPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86AsmPrinter.h @@ -61,8 +61,7 @@ class VISIBILITY_HIDDEN X86AsmPrinter : public AsmPrinter { virtual void EmitInstruction(const MachineInstr *MI); void printSymbolOperand(const MachineOperand &MO); - - + virtual MCSymbol *GetGlobalValueSymbol(const GlobalValue *GV) const; // These methods are used by the tablegen'erated instruction printer. void printOperand(const MachineInstr *MI, unsigned OpNo, diff --git a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp index 4274d0a436..610beb550b 100644 --- a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.cpp @@ -24,10 +24,14 @@ using namespace llvm; // Include the auto-generated portion of the assembly writer. #define MachineInstr MCInst +#define GET_INSTRUCTION_NAME #include "X86GenAsmWriter1.inc" #undef MachineInstr void X86IntelInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); } +StringRef X86IntelInstPrinter::getOpcodeName(unsigned Opcode) const { + return getInstructionName(Opcode); +} void X86IntelInstPrinter::printSSECC(const MCInst *MI, unsigned Op) { switch (MI->getOperand(Op).getImm()) { diff --git a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h index 1976177eb1..545bf84b91 100644 --- a/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h +++ b/lib/Target/X86/AsmPrinter/X86IntelInstPrinter.h @@ -26,10 +26,12 @@ public: : MCInstPrinter(O, MAI) {} virtual void printInst(const MCInst *MI); + virtual StringRef getOpcodeName(unsigned Opcode) const; // Autogenerated by tblgen. void printInstruction(const MCInst *MI); static const char *getRegisterName(unsigned RegNo); + static const char *getInstructionName(unsigned Opcode); void printOperand(const MCInst *MI, unsigned OpNo, diff --git a/lib/Target/X86/CMakeLists.txt b/lib/Target/X86/CMakeLists.txt index 61f26a7393..eed3b45d74 100644 --- a/lib/Target/X86/CMakeLists.txt +++ b/lib/Target/X86/CMakeLists.txt @@ -15,6 +15,7 @@ tablegen(X86GenCallingConv.inc -gen-callingconv) tablegen(X86GenSubtarget.inc -gen-subtarget) set(sources + X86AsmBackend.cpp X86CodeEmitter.cpp X86COFFMachineModuleInfo.cpp X86ELFWriterInfo.cpp diff --git a/lib/Target/X86/README-SSE.txt b/lib/Target/X86/README-SSE.txt index 19eb05e765..e5f84e8b16 100644 --- a/lib/Target/X86/README-SSE.txt +++ b/lib/Target/X86/README-SSE.txt @@ -67,8 +67,8 @@ no_exit.i7: ; preds = %no_exit.i7, %build_tree.exit [ %tmp.34.i18, %no_exit.i7 ] %tmp.0.0.0.i10 = phi double [ 0.000000e+00, %build_tree.exit ], [ %tmp.28.i16, %no_exit.i7 ] - %tmp.28.i16 = add double %tmp.0.0.0.i10, 0.000000e+00 - %tmp.34.i18 = add double %tmp.0.1.0.i9, 0.000000e+00 + %tmp.28.i16 = fadd double %tmp.0.0.0.i10, 0.000000e+00 + %tmp.34.i18 = fadd double %tmp.0.1.0.i9, 0.000000e+00 br i1 false, label %Compute_Tree.exit23, label %no_exit.i7 Compute_Tree.exit23: ; preds = %no_exit.i7 @@ -97,7 +97,7 @@ pcmp/pand/pandn/por to do a selection instead of a conditional branch: double %X(double %Y, double %Z, double %A, double %B) { %C = setlt double %A, %B - %z = add double %Z, 0.0 ;; select operand is not a load + %z = fadd double %Z, 0.0 ;; select operand is not a load %D = select bool %C, double %Y, double %z ret double %D } @@ -545,7 +545,7 @@ eliminates a constant pool load. For example, consider: define i64 @ccosf(float %z.0, float %z.1) nounwind readonly { entry: - %tmp6 = sub float -0.000000e+00, %z.1 ; [#uses=1] + %tmp6 = fsub float -0.000000e+00, %z.1 ; [#uses=1] %tmp20 = tail call i64 @ccoshf( float %tmp6, float %z.0 ) nounwind readonly ret i64 %tmp20 } diff --git a/lib/Target/X86/README.txt b/lib/Target/X86/README.txt index aa7bb3d978..d4545a6fcf 100644 --- a/lib/Target/X86/README.txt +++ b/lib/Target/X86/README.txt @@ -227,11 +227,6 @@ lambda, siod, optimizer-eval, ackermann, hash2, nestedloop, strcat, and Treesor. //===---------------------------------------------------------------------===// -Teach the coalescer to coalesce vregs of different register classes. e.g. FR32 / -FR64 to VR128. - -//===---------------------------------------------------------------------===// - Adding to the list of cmp / test poor codegen issues: int test(__m128 *A, __m128 *B) { @@ -1868,3 +1863,69 @@ carried over to machine instructions. Asm printer (or JIT) can use this information to add the "lock" prefix. //===---------------------------------------------------------------------===// + +_Bool bar(int *x) { return *x & 1; } + +define zeroext i1 @bar(i32* nocapture %x) nounwind readonly { +entry: + %tmp1 = load i32* %x ; [#uses=1] + %and = and i32 %tmp1, 1 ; [#uses=1] + %tobool = icmp ne i32 %and, 0 ; [#uses=1] + ret i1 %tobool +} + +bar: # @bar +# BB#0: # %entry + movl 4(%esp), %eax + movb (%eax), %al + andb $1, %al + movzbl %al, %eax + ret + +Missed optimization: should be movl+andl. + +//===---------------------------------------------------------------------===// + +Consider the following two functions compiled with clang: +_Bool foo(int *x) { return !(*x & 4); } +unsigned bar(int *x) { return !(*x & 4); } + +foo: + movl 4(%esp), %eax + testb $4, (%eax) + sete %al + movzbl %al, %eax + ret + +bar: + movl 4(%esp), %eax + movl (%eax), %eax + shrl $2, %eax + andl $1, %eax + xorl $1, %eax + ret + +The second function generates more code even though the two functions are +are functionally identical. + +//===---------------------------------------------------------------------===// + +Take the following C code: +int x(int y) { return (y & 63) << 14; } + +Code produced by gcc: + andl $63, %edi + sall $14, %edi + movl %edi, %eax + ret + +Code produced by clang: + shll $14, %edi + movl %edi, %eax + andl $1032192, %eax + ret + +The code produced by gcc is 3 bytes shorter. This sort of construct often +shows up with bitfields. + +//===---------------------------------------------------------------------===// diff --git a/lib/Target/X86/TargetInfo/Android.mk b/lib/Target/X86/TargetInfo/Android.mk new file mode 100644 index 0000000000..ee53f0dec9 --- /dev/null +++ b/lib/Target/X86/TargetInfo/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH := $(call my-dir) + +# For the device only +# ===================================================== +include $(CLEAR_VARS) +include $(CLEAR_TBLGEN_VARS) + +TBLGEN_TABLES := \ + X86GenRegisterNames.inc \ + X86GenInstrNames.inc + +TBLGEN_TD_DIR := $(LOCAL_PATH)/.. + +LOCAL_SRC_FILES := \ + X86TargetInfo.cpp + +LOCAL_C_INCLUDES += \ + $(LOCAL_PATH)/.. + +LOCAL_MODULE:= libLLVMX86Info + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_TBLGEN_RULES_MK) +include $(BUILD_HOST_STATIC_LIBRARY) diff --git a/lib/Target/X86/X86.h b/lib/Target/X86/X86.h index 1d17a05d5b..ba0ee6cedd 100644 --- a/lib/Target/X86/X86.h +++ b/lib/Target/X86/X86.h @@ -19,12 +19,15 @@ namespace llvm { -class X86TargetMachine; class FunctionPass; -class MachineCodeEmitter; -class MCCodeEmitter; class JITCodeEmitter; +class MCAssembler; +class MCCodeEmitter; +class MCContext; +class MachineCodeEmitter; class Target; +class TargetAsmBackend; +class X86TargetMachine; class formatted_raw_ostream; /// createX86ISelDag - This pass converts a legalized DAG into a @@ -49,9 +52,13 @@ FunctionPass *createX87FPRegKillInserterPass(); FunctionPass *createX86JITCodeEmitterPass(X86TargetMachine &TM, JITCodeEmitter &JCE); -MCCodeEmitter *createHeinousX86MCCodeEmitter(const Target &, TargetMachine &TM); -MCCodeEmitter *createX86_32MCCodeEmitter(const Target &, TargetMachine &TM); -MCCodeEmitter *createX86_64MCCodeEmitter(const Target &, TargetMachine &TM); +MCCodeEmitter *createX86_32MCCodeEmitter(const Target &, TargetMachine &TM, + MCContext &Ctx); +MCCodeEmitter *createX86_64MCCodeEmitter(const Target &, TargetMachine &TM, + MCContext &Ctx); + +TargetAsmBackend *createX86_32AsmBackend(const Target &, MCAssembler &); +TargetAsmBackend *createX86_64AsmBackend(const Target &, MCAssembler &); /// createX86EmitCodeToMemory - Returns a pass that converts a register /// allocated function into raw machine code in a dynamically diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp new file mode 100644 index 0000000000..e6654efbbb --- /dev/null +++ b/lib/Target/X86/X86AsmBackend.cpp @@ -0,0 +1,34 @@ +//===-- X86AsmBackend.cpp - X86 Assembler Backend -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetAsmBackend.h" +#include "X86.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetAsmBackend.h" +using namespace llvm; + +namespace { + +class X86AsmBackend : public TargetAsmBackend { +public: + X86AsmBackend(const Target &T, MCAssembler &A) + : TargetAsmBackend(T) {} +}; + +} + +TargetAsmBackend *llvm::createX86_32AsmBackend(const Target &T, + MCAssembler &A) { + return new X86AsmBackend(T, A); +} + +TargetAsmBackend *llvm::createX86_64AsmBackend(const Target &T, + MCAssembler &A) { + return new X86AsmBackend(T, A); +} diff --git a/lib/Target/X86/X86COFFMachineModuleInfo.cpp b/lib/Target/X86/X86COFFMachineModuleInfo.cpp index ea527955e3..ab67acbadb 100644 --- a/lib/Target/X86/X86COFFMachineModuleInfo.cpp +++ b/lib/Target/X86/X86COFFMachineModuleInfo.cpp @@ -27,90 +27,55 @@ X86COFFMachineModuleInfo::X86COFFMachineModuleInfo(const MachineModuleInfo &) { X86COFFMachineModuleInfo::~X86COFFMachineModuleInfo() { } -void X86COFFMachineModuleInfo::AddFunctionInfo(const Function *F, - const X86MachineFunctionInfo &Val) { - FunctionInfoMap[F] = Val; +void X86COFFMachineModuleInfo::addExternalFunction(const StringRef& Name) { + CygMingStubs.insert(Name); } - - -static X86MachineFunctionInfo calculateFunctionInfo(const Function *F, - const TargetData &TD) { - X86MachineFunctionInfo Info; - uint64_t Size = 0; - - switch (F->getCallingConv()) { - case CallingConv::X86_StdCall: - Info.setDecorationStyle(StdCall); - break; - case CallingConv::X86_FastCall: - Info.setDecorationStyle(FastCall); - break; - default: - return Info; - } - - unsigned argNum = 1; - for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); - AI != AE; ++AI, ++argNum) { - const Type* Ty = AI->getType(); - - // 'Dereference' type in case of byval parameter attribute - if (F->paramHasAttr(argNum, Attribute::ByVal)) - Ty = cast(Ty)->getElementType(); - - // Size should be aligned to DWORD boundary - Size += ((TD.getTypeAllocSize(Ty) + 3)/4)*4; - } - - // We're not supporting tooooo huge arguments :) - Info.setBytesToPopOnReturn((unsigned int)Size); - return Info; -} - - -/// DecorateCygMingName - Query FunctionInfoMap and use this information for -/// various name decorations for Cygwin and MingW. +/// DecorateCygMingName - Apply various name decorations if the function uses +/// stdcall or fastcall calling convention. void X86COFFMachineModuleInfo::DecorateCygMingName(SmallVectorImpl &Name, const GlobalValue *GV, const TargetData &TD) { const Function *F = dyn_cast(GV); if (!F) return; - - // Save function name for later type emission. - if (F->isDeclaration()) - CygMingStubs.insert(StringRef(Name.data(), Name.size())); - + // We don't want to decorate non-stdcall or non-fastcall functions right now CallingConv::ID CC = F->getCallingConv(); if (CC != CallingConv::X86_StdCall && CC != CallingConv::X86_FastCall) return; - - const X86MachineFunctionInfo *Info; - - FMFInfoMap::const_iterator info_item = FunctionInfoMap.find(F); - if (info_item == FunctionInfoMap.end()) { - // Calculate apropriate function info and populate map - FunctionInfoMap[F] = calculateFunctionInfo(F, TD); - Info = &FunctionInfoMap[F]; - } else { - Info = &info_item->second; - } - - if (Info->getDecorationStyle() == None) return; + + unsigned ArgWords = 0; + DenseMap::const_iterator item = FnArgWords.find(F); + if (item == FnArgWords.end()) { + // Calculate arguments sizes + for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); + AI != AE; ++AI) { + const Type* Ty = AI->getType(); + + // 'Dereference' type in case of byval parameter attribute + if (AI->hasByValAttr()) + Ty = cast(Ty)->getElementType(); + + // Size should be aligned to DWORD boundary + ArgWords += ((TD.getTypeAllocSize(Ty) + 3)/4)*4; + } + + FnArgWords[F] = ArgWords; + } else + ArgWords = item->second; + const FunctionType *FT = F->getFunctionType(); - // "Pure" variadic functions do not receive @0 suffix. if (!FT->isVarArg() || FT->getNumParams() == 0 || (FT->getNumParams() == 1 && F->hasStructRetAttr())) - raw_svector_ostream(Name) << '@' << Info->getBytesToPopOnReturn(); - - if (Info->getDecorationStyle() == FastCall) { + raw_svector_ostream(Name) << '@' << ArgWords; + + if (CC == CallingConv::X86_FastCall) { if (Name[0] == '_') Name[0] = '@'; else Name.insert(Name.begin(), '@'); - } + } } /// DecorateCygMingName - Query FunctionInfoMap and use this information for @@ -121,6 +86,6 @@ void X86COFFMachineModuleInfo::DecorateCygMingName(MCSymbol *&Name, const TargetData &TD) { SmallString<128> NameStr(Name->getName().begin(), Name->getName().end()); DecorateCygMingName(NameStr, GV, TD); - + Name = Ctx.GetOrCreateSymbol(NameStr.str()); } diff --git a/lib/Target/X86/X86COFFMachineModuleInfo.h b/lib/Target/X86/X86COFFMachineModuleInfo.h index 0e2009e003..9de3dcd634 100644 --- a/lib/Target/X86/X86COFFMachineModuleInfo.h +++ b/lib/Target/X86/X86COFFMachineModuleInfo.h @@ -21,44 +21,25 @@ namespace llvm { class X86MachineFunctionInfo; class TargetData; - + /// X86COFFMachineModuleInfo - This is a MachineModuleInfoImpl implementation /// for X86 COFF targets. class X86COFFMachineModuleInfo : public MachineModuleInfoImpl { StringSet<> CygMingStubs; - - // We have to propagate some information about MachineFunction to - // AsmPrinter. It's ok, when we're printing the function, since we have - // access to MachineFunction and can get the appropriate MachineFunctionInfo. - // Unfortunately, this is not possible when we're printing reference to - // Function (e.g. calling it and so on). Even more, there is no way to get the - // corresponding MachineFunctions: it can even be not created at all. That's - // why we should use additional structure, when we're collecting all necessary - // information. - // - // This structure is using e.g. for name decoration for stdcall & fastcall'ed - // function, since we have to use arguments' size for decoration. - typedef std::map FMFInfoMap; - FMFInfoMap FunctionInfoMap; - + DenseMap FnArgWords; public: X86COFFMachineModuleInfo(const MachineModuleInfo &); ~X86COFFMachineModuleInfo(); - - + void DecorateCygMingName(MCSymbol* &Name, MCContext &Ctx, const GlobalValue *GV, const TargetData &TD); void DecorateCygMingName(SmallVectorImpl &Name, const GlobalValue *GV, const TargetData &TD); - - void AddFunctionInfo(const Function *F, const X86MachineFunctionInfo &Val); - + void addExternalFunction(const StringRef& Name); typedef StringSet<>::const_iterator stub_iterator; stub_iterator stub_begin() const { return CygMingStubs.begin(); } stub_iterator stub_end() const { return CygMingStubs.end(); } - - }; diff --git a/lib/Target/X86/X86CodeEmitter.cpp b/lib/Target/X86/X86CodeEmitter.cpp index f0bceb1483..8deadf628c 100644 --- a/lib/Target/X86/X86CodeEmitter.cpp +++ b/lib/Target/X86/X86CodeEmitter.cpp @@ -387,10 +387,16 @@ void Emitter::emitMemModRMByte(const MachineInstr &MI, // If no BaseReg, issue a RIP relative instruction only if the MCE can // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table // 2-7) and absolute references. + unsigned BaseRegNo = -1U; + if (BaseReg != 0 && BaseReg != X86::RIP) + BaseRegNo = getX86RegNum(BaseReg); + if (// The SIB byte must be used if there is an index register. IndexReg.getReg() == 0 && - // The SIB byte must be used if the base is ESP/RSP. - BaseReg != X86::ESP && BaseReg != X86::RSP && + // The SIB byte must be used if the base is ESP/RSP/R12, all of which + // encode to an R/M value of 4, which indicates that a SIB byte is + // present. + BaseRegNo != N86::ESP && // If there is no base register and we're in 64-bit mode, we need a SIB // byte to emit an addr that is just 'disp32' (the non-RIP relative form). (!Is64BitMode || BaseReg != 0)) { @@ -401,7 +407,6 @@ void Emitter::emitMemModRMByte(const MachineInstr &MI, return; } - unsigned BaseRegNo = getX86RegNum(BaseReg); // If the base is not EBP/ESP and there is no displacement, use simple // indirect register encoding, this handles addresses like [EAX]. The // encoding for [EBP] with no displacement means [disp32] so we handle it @@ -757,27 +762,8 @@ void Emitter::emitInstruction(const MachineInstr &MI, case X86II::MRM4r: case X86II::MRM5r: case X86II::MRM6r: case X86II::MRM7r: { MCE.emitByte(BaseOpcode); - - // Special handling of lfence, mfence, monitor, and mwait. - if (Desc->getOpcode() == X86::LFENCE || - Desc->getOpcode() == X86::MFENCE || - Desc->getOpcode() == X86::MONITOR || - Desc->getOpcode() == X86::MWAIT) { - emitRegModRMByte((Desc->TSFlags & X86II::FormMask)-X86II::MRM0r); - - switch (Desc->getOpcode()) { - default: break; - case X86::MONITOR: - MCE.emitByte(0xC8); - break; - case X86::MWAIT: - MCE.emitByte(0xC9); - break; - } - } else { - emitRegModRMByte(MI.getOperand(CurOp++).getReg(), - (Desc->TSFlags & X86II::FormMask)-X86II::MRM0r); - } + emitRegModRMByte(MI.getOperand(CurOp++).getReg(), + (Desc->TSFlags & X86II::FormMask)-X86II::MRM0r); if (CurOp == NumOps) break; @@ -853,6 +839,27 @@ void Emitter::emitInstruction(const MachineInstr &MI, getX86RegNum(MI.getOperand(CurOp).getReg())); ++CurOp; break; + + case X86II::MRM_C1: + MCE.emitByte(BaseOpcode); + MCE.emitByte(0xC1); + break; + case X86II::MRM_C8: + MCE.emitByte(BaseOpcode); + MCE.emitByte(0xC8); + break; + case X86II::MRM_C9: + MCE.emitByte(BaseOpcode); + MCE.emitByte(0xC9); + break; + case X86II::MRM_E8: + MCE.emitByte(BaseOpcode); + MCE.emitByte(0xE8); + break; + case X86II::MRM_F0: + MCE.emitByte(BaseOpcode); + MCE.emitByte(0xF0); + break; } if (!Desc->isVariadic() && CurOp != NumOps) { @@ -864,335 +871,3 @@ void Emitter::emitInstruction(const MachineInstr &MI, MCE.processDebugLoc(MI.getDebugLoc(), false); } - -// Adapt the Emitter / CodeEmitter interfaces to MCCodeEmitter. -// -// FIXME: This is a total hack designed to allow work on llvm-mc to proceed -// without being blocked on various cleanups needed to support a clean interface -// to instruction encoding. -// -// Look away! - -#include "llvm/DerivedTypes.h" - -namespace { -class MCSingleInstructionCodeEmitter : public MachineCodeEmitter { - uint8_t Data[256]; - const MCInst *CurrentInst; - SmallVectorImpl *FixupList; - -public: - MCSingleInstructionCodeEmitter() { reset(0, 0); } - - void reset(const MCInst *Inst, SmallVectorImpl *Fixups) { - CurrentInst = Inst; - FixupList = Fixups; - BufferBegin = Data; - BufferEnd = array_endof(Data); - CurBufferPtr = Data; - } - - StringRef str() { - return StringRef(reinterpret_cast(BufferBegin), - CurBufferPtr - BufferBegin); - } - - virtual void startFunction(MachineFunction &F) {} - virtual bool finishFunction(MachineFunction &F) { return false; } - virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {} - virtual bool earlyResolveAddresses() const { return false; } - virtual void addRelocation(const MachineRelocation &MR) { - unsigned Offset = 0, OpIndex = 0, Kind = MR.getRelocationType(); - - // This form is only used in one case, for branches. - if (MR.isBasicBlock()) { - Offset = unsigned(MR.getMachineCodeOffset()); - OpIndex = 0; - } else { - assert(MR.isJumpTableIndex() && "Unexpected relocation!"); - - Offset = unsigned(MR.getMachineCodeOffset()); - - // The operand index is encoded as the first byte of the fake operand. - OpIndex = MR.getJumpTableIndex(); - } - - MCOperand Op = CurrentInst->getOperand(OpIndex); - assert(Op.isExpr() && "FIXME: Not yet implemented!"); - FixupList->push_back(MCFixup::Create(Offset, Op.getExpr(), - MCFixupKind(FirstTargetFixupKind + Kind))); - } - virtual void setModuleInfo(MachineModuleInfo* Info) {} - - // Interface functions which should never get called in our usage. - - virtual void emitLabel(uint64_t LabelID) { - assert(0 && "Unexpected code emitter call!"); - } - virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { - assert(0 && "Unexpected code emitter call!"); - return 0; - } - virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { - assert(0 && "Unexpected code emitter call!"); - return 0; - } - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { - assert(0 && "Unexpected code emitter call!"); - return 0; - } - virtual uintptr_t getLabelAddress(uint64_t LabelID) const { - assert(0 && "Unexpected code emitter call!"); - return 0; - } -}; - -class X86MCCodeEmitter : public MCCodeEmitter { - X86MCCodeEmitter(const X86MCCodeEmitter &); // DO NOT IMPLEMENT - void operator=(const X86MCCodeEmitter &); // DO NOT IMPLEMENT - -private: - X86TargetMachine &TM; - llvm::Function *DummyF; - TargetData *DummyTD; - mutable llvm::MachineFunction *DummyMF; - llvm::MachineBasicBlock *DummyMBB; - - MCSingleInstructionCodeEmitter *InstrEmitter; - Emitter *Emit; - -public: - X86MCCodeEmitter(X86TargetMachine &_TM) : TM(_TM) { - // Verily, thou shouldst avert thine eyes. - const llvm::FunctionType *FTy = - FunctionType::get(llvm::Type::getVoidTy(getGlobalContext()), false); - DummyF = Function::Create(FTy, GlobalValue::InternalLinkage); - DummyTD = new TargetData(""); - DummyMF = new MachineFunction(DummyF, TM, 0); - DummyMBB = DummyMF->CreateMachineBasicBlock(); - - InstrEmitter = new MCSingleInstructionCodeEmitter(); - Emit = new Emitter(TM, *InstrEmitter, - *TM.getInstrInfo(), - *DummyTD, false); - } - ~X86MCCodeEmitter() { - delete Emit; - delete InstrEmitter; - delete DummyMF; - delete DummyF; - } - - unsigned getNumFixupKinds() const { - return 5; - } - - MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { - static MCFixupKindInfo Infos[] = { - { "reloc_pcrel_word", 0, 4 * 8 }, - { "reloc_picrel_word", 0, 4 * 8 }, - { "reloc_absolute_word", 0, 4 * 8 }, - { "reloc_absolute_word_sext", 0, 4 * 8 }, - { "reloc_absolute_dword", 0, 8 * 8 } - }; - - assert(Kind >= FirstTargetFixupKind && Kind < MaxTargetFixupKind && - "Invalid kind!"); - return Infos[Kind - FirstTargetFixupKind]; - } - - bool AddRegToInstr(const MCInst &MI, MachineInstr *Instr, - unsigned Start) const { - if (Start + 1 > MI.getNumOperands()) - return false; - - const MCOperand &Op = MI.getOperand(Start); - if (!Op.isReg()) return false; - - Instr->addOperand(MachineOperand::CreateReg(Op.getReg(), false)); - return true; - } - - bool AddImmToInstr(const MCInst &MI, MachineInstr *Instr, - unsigned Start) const { - if (Start + 1 > MI.getNumOperands()) - return false; - - const MCOperand &Op = MI.getOperand(Start); - if (Op.isImm()) { - Instr->addOperand(MachineOperand::CreateImm(Op.getImm())); - return true; - } - if (!Op.isExpr()) - return false; - - const MCExpr *Expr = Op.getExpr(); - if (const MCConstantExpr *CE = dyn_cast(Expr)) { - Instr->addOperand(MachineOperand::CreateImm(CE->getValue())); - return true; - } - - // Fake this as an external symbol to the code emitter to add a relcoation - // entry we will recognize. - Instr->addOperand(MachineOperand::CreateJTI(Start, 0)); - return true; - } - - bool AddLMemToInstr(const MCInst &MI, MachineInstr *Instr, - unsigned Start) const { - return (AddRegToInstr(MI, Instr, Start + 0) && - AddImmToInstr(MI, Instr, Start + 1) && - AddRegToInstr(MI, Instr, Start + 2) && - AddImmToInstr(MI, Instr, Start + 3)); - } - - bool AddMemToInstr(const MCInst &MI, MachineInstr *Instr, - unsigned Start) const { - return (AddRegToInstr(MI, Instr, Start + 0) && - AddImmToInstr(MI, Instr, Start + 1) && - AddRegToInstr(MI, Instr, Start + 2) && - AddImmToInstr(MI, Instr, Start + 3) && - AddRegToInstr(MI, Instr, Start + 4)); - } - - void EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl &Fixups) const { - // Don't look yet! - - // Convert the MCInst to a MachineInstr so we can (ab)use the regular - // emitter. - const X86InstrInfo &II = *TM.getInstrInfo(); - const TargetInstrDesc &Desc = II.get(MI.getOpcode()); - MachineInstr *Instr = DummyMF->CreateMachineInstr(Desc, DebugLoc()); - DummyMBB->push_back(Instr); - - unsigned Opcode = MI.getOpcode(); - unsigned NumOps = MI.getNumOperands(); - unsigned CurOp = 0; - bool AddTied = false; - if (NumOps > 1 && Desc.getOperandConstraint(1, TOI::TIED_TO) != -1) - AddTied = true; - else if (NumOps > 2 && - Desc.getOperandConstraint(NumOps-1, TOI::TIED_TO)== 0) - // Skip the last source operand that is tied_to the dest reg. e.g. LXADD32 - --NumOps; - - bool OK = true; - switch (Desc.TSFlags & X86II::FormMask) { - case X86II::MRMDestReg: - case X86II::MRMSrcReg: - // Matching doesn't fill this in completely, we have to choose operand 0 - // for a tied register. - OK &= AddRegToInstr(MI, Instr, CurOp++); - if (AddTied) - OK &= AddRegToInstr(MI, Instr, CurOp++ - 1); - OK &= AddRegToInstr(MI, Instr, CurOp++); - if (CurOp < NumOps) - OK &= AddImmToInstr(MI, Instr, CurOp); - break; - - case X86II::RawFrm: - if (CurOp < NumOps) { - // Hack to make branches work. - if (!(Desc.TSFlags & X86II::ImmMask) && - MI.getOperand(0).isExpr() && - isa(MI.getOperand(0).getExpr())) - Instr->addOperand(MachineOperand::CreateMBB(DummyMBB)); - else - OK &= AddImmToInstr(MI, Instr, CurOp); - } - break; - - case X86II::AddRegFrm: - // Matching doesn't fill this in completely, we have to choose operand 0 - // for a tied register. - OK &= AddRegToInstr(MI, Instr, CurOp++); - if (AddTied) - OK &= AddRegToInstr(MI, Instr, CurOp++ - 1); - if (CurOp < NumOps) - OK &= AddImmToInstr(MI, Instr, CurOp); - break; - - case X86II::MRM0r: case X86II::MRM1r: - case X86II::MRM2r: case X86II::MRM3r: - case X86II::MRM4r: case X86II::MRM5r: - case X86II::MRM6r: case X86II::MRM7r: - // Matching doesn't fill this in completely, we have to choose operand 0 - // for a tied register. - OK &= AddRegToInstr(MI, Instr, CurOp++); - if (AddTied) - OK &= AddRegToInstr(MI, Instr, CurOp++ - 1); - if (CurOp < NumOps) - OK &= AddImmToInstr(MI, Instr, CurOp); - break; - - case X86II::MRM0m: case X86II::MRM1m: - case X86II::MRM2m: case X86II::MRM3m: - case X86II::MRM4m: case X86II::MRM5m: - case X86II::MRM6m: case X86II::MRM7m: - OK &= AddMemToInstr(MI, Instr, CurOp); CurOp += 5; - if (CurOp < NumOps) - OK &= AddImmToInstr(MI, Instr, CurOp); - break; - - case X86II::MRMSrcMem: - // Matching doesn't fill this in completely, we have to choose operand 0 - // for a tied register. - OK &= AddRegToInstr(MI, Instr, CurOp++); - if (AddTied) - OK &= AddRegToInstr(MI, Instr, CurOp++ - 1); - if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r || - Opcode == X86::LEA16r || Opcode == X86::LEA32r) - OK &= AddLMemToInstr(MI, Instr, CurOp); - else - OK &= AddMemToInstr(MI, Instr, CurOp); - break; - - case X86II::MRMDestMem: - OK &= AddMemToInstr(MI, Instr, CurOp); CurOp += 5; - OK &= AddRegToInstr(MI, Instr, CurOp); - break; - - default: - case X86II::MRMInitReg: - case X86II::Pseudo: - OK = false; - break; - } - - if (!OK) { - dbgs() << "couldn't convert inst '"; - MI.dump(); - dbgs() << "' to machine instr:\n"; - Instr->dump(); - } - - InstrEmitter->reset(&MI, &Fixups); - if (OK) - Emit->emitInstruction(*Instr, &Desc); - OS << InstrEmitter->str(); - - Instr->eraseFromParent(); - } -}; -} - -#include "llvm/Support/CommandLine.h" - -static cl::opt EnableNewEncoder("enable-new-x86-encoder", - cl::ReallyHidden); - - -// Ok, now you can look. -MCCodeEmitter *llvm::createHeinousX86MCCodeEmitter(const Target &T, - TargetMachine &TM) { - - // FIXME: Remove the heinous one when the new one works. - if (EnableNewEncoder) { - if (TM.getTargetData()->getPointerSize() == 4) - return createX86_32MCCodeEmitter(T, TM); - return createX86_64MCCodeEmitter(T, TM); - } - - return new X86MCCodeEmitter(static_cast(TM)); -} diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index ea398e9106..98e3f4efe5 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -388,6 +388,8 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) { } case Instruction::GetElementPtr: { + X86AddressMode SavedAM = AM; + // Pattern-match simple GEPs. uint64_t Disp = (int32_t)AM.Disp; unsigned IndexReg = AM.IndexReg; @@ -428,7 +430,13 @@ bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM) { AM.IndexReg = IndexReg; AM.Scale = Scale; AM.Disp = (uint32_t)Disp; - return X86SelectAddress(U->getOperand(0), AM); + if (X86SelectAddress(U->getOperand(0), AM)) + return true; + + // If we couldn't merge the sub value into this addr mode, revert back to + // our address and just match the value instead of completely failing. + AM = SavedAM; + break; unsupported_gep: // Ok, the GEP indices weren't all covered. break; @@ -786,8 +794,8 @@ bool X86FastISel::X86SelectCmp(Instruction *I) { bool X86FastISel::X86SelectZExt(Instruction *I) { // Handle zero-extension from i1 to i8, which is common. - if (I->getType()->isInteger(8) && - I->getOperand(0)->getType()->isInteger(1)) { + if (I->getType()->isIntegerTy(8) && + I->getOperand(0)->getType()->isIntegerTy(1)) { unsigned ResultReg = getRegForValue(I->getOperand(0)); if (ResultReg == 0) return false; // Set the high bits to zero. @@ -828,30 +836,30 @@ bool X86FastISel::X86SelectBranch(Instruction *I) { std::swap(TrueMBB, FalseMBB); Predicate = CmpInst::FCMP_UNE; // FALL THROUGH - case CmpInst::FCMP_UNE: SwapArgs = false; BranchOpc = X86::JNE; break; - case CmpInst::FCMP_OGT: SwapArgs = false; BranchOpc = X86::JA; break; - case CmpInst::FCMP_OGE: SwapArgs = false; BranchOpc = X86::JAE; break; - case CmpInst::FCMP_OLT: SwapArgs = true; BranchOpc = X86::JA; break; - case CmpInst::FCMP_OLE: SwapArgs = true; BranchOpc = X86::JAE; break; - case CmpInst::FCMP_ONE: SwapArgs = false; BranchOpc = X86::JNE; break; - case CmpInst::FCMP_ORD: SwapArgs = false; BranchOpc = X86::JNP; break; - case CmpInst::FCMP_UNO: SwapArgs = false; BranchOpc = X86::JP; break; - case CmpInst::FCMP_UEQ: SwapArgs = false; BranchOpc = X86::JE; break; - case CmpInst::FCMP_UGT: SwapArgs = true; BranchOpc = X86::JB; break; - case CmpInst::FCMP_UGE: SwapArgs = true; BranchOpc = X86::JBE; break; - case CmpInst::FCMP_ULT: SwapArgs = false; BranchOpc = X86::JB; break; - case CmpInst::FCMP_ULE: SwapArgs = false; BranchOpc = X86::JBE; break; + case CmpInst::FCMP_UNE: SwapArgs = false; BranchOpc = X86::JNE_4; break; + case CmpInst::FCMP_OGT: SwapArgs = false; BranchOpc = X86::JA_4; break; + case CmpInst::FCMP_OGE: SwapArgs = false; BranchOpc = X86::JAE_4; break; + case CmpInst::FCMP_OLT: SwapArgs = true; BranchOpc = X86::JA_4; break; + case CmpInst::FCMP_OLE: SwapArgs = true; BranchOpc = X86::JAE_4; break; + case CmpInst::FCMP_ONE: SwapArgs = false; BranchOpc = X86::JNE_4; break; + case CmpInst::FCMP_ORD: SwapArgs = false; BranchOpc = X86::JNP_4; break; + case CmpInst::FCMP_UNO: SwapArgs = false; BranchOpc = X86::JP_4; break; + case CmpInst::FCMP_UEQ: SwapArgs = false; BranchOpc = X86::JE_4; break; + case CmpInst::FCMP_UGT: SwapArgs = true; BranchOpc = X86::JB_4; break; + case CmpInst::FCMP_UGE: SwapArgs = true; BranchOpc = X86::JBE_4; break; + case CmpInst::FCMP_ULT: SwapArgs = false; BranchOpc = X86::JB_4; break; + case CmpInst::FCMP_ULE: SwapArgs = false; BranchOpc = X86::JBE_4; break; - case CmpInst::ICMP_EQ: SwapArgs = false; BranchOpc = X86::JE; break; - case CmpInst::ICMP_NE: SwapArgs = false; BranchOpc = X86::JNE; break; - case CmpInst::ICMP_UGT: SwapArgs = false; BranchOpc = X86::JA; break; - case CmpInst::ICMP_UGE: SwapArgs = false; BranchOpc = X86::JAE; break; - case CmpInst::ICMP_ULT: SwapArgs = false; BranchOpc = X86::JB; break; - case CmpInst::ICMP_ULE: SwapArgs = false; BranchOpc = X86::JBE; break; - case CmpInst::ICMP_SGT: SwapArgs = false; BranchOpc = X86::JG; break; - case CmpInst::ICMP_SGE: SwapArgs = false; BranchOpc = X86::JGE; break; - case CmpInst::ICMP_SLT: SwapArgs = false; BranchOpc = X86::JL; break; - case CmpInst::ICMP_SLE: SwapArgs = false; BranchOpc = X86::JLE; break; + case CmpInst::ICMP_EQ: SwapArgs = false; BranchOpc = X86::JE_4; break; + case CmpInst::ICMP_NE: SwapArgs = false; BranchOpc = X86::JNE_4; break; + case CmpInst::ICMP_UGT: SwapArgs = false; BranchOpc = X86::JA_4; break; + case CmpInst::ICMP_UGE: SwapArgs = false; BranchOpc = X86::JAE_4; break; + case CmpInst::ICMP_ULT: SwapArgs = false; BranchOpc = X86::JB_4; break; + case CmpInst::ICMP_ULE: SwapArgs = false; BranchOpc = X86::JBE_4; break; + case CmpInst::ICMP_SGT: SwapArgs = false; BranchOpc = X86::JG_4; break; + case CmpInst::ICMP_SGE: SwapArgs = false; BranchOpc = X86::JGE_4; break; + case CmpInst::ICMP_SLT: SwapArgs = false; BranchOpc = X86::JL_4; break; + case CmpInst::ICMP_SLE: SwapArgs = false; BranchOpc = X86::JLE_4; break; default: return false; } @@ -869,7 +877,7 @@ bool X86FastISel::X86SelectBranch(Instruction *I) { if (Predicate == CmpInst::FCMP_UNE) { // X86 requires a second branch to handle UNE (and OEQ, // which is mapped to UNE above). - BuildMI(MBB, DL, TII.get(X86::JP)).addMBB(TrueMBB); + BuildMI(MBB, DL, TII.get(X86::JP_4)).addMBB(TrueMBB); } FastEmitBranch(FalseMBB); @@ -923,7 +931,8 @@ bool X86FastISel::X86SelectBranch(Instruction *I) { unsigned OpCode = SetMI->getOpcode(); if (OpCode == X86::SETOr || OpCode == X86::SETBr) { - BuildMI(MBB, DL, TII.get(OpCode == X86::SETOr ? X86::JO : X86::JB)) + BuildMI(MBB, DL, TII.get(OpCode == X86::SETOr ? + X86::JO_4 : X86::JB_4)) .addMBB(TrueMBB); FastEmitBranch(FalseMBB); MBB->addSuccessor(TrueMBB); @@ -939,7 +948,7 @@ bool X86FastISel::X86SelectBranch(Instruction *I) { if (OpReg == 0) return false; BuildMI(MBB, DL, TII.get(X86::TEST8rr)).addReg(OpReg).addReg(OpReg); - BuildMI(MBB, DL, TII.get(X86::JNE)).addMBB(TrueMBB); + BuildMI(MBB, DL, TII.get(X86::JNE_4)).addMBB(TrueMBB); FastEmitBranch(FalseMBB); MBB->addSuccessor(TrueMBB); return true; @@ -948,7 +957,7 @@ bool X86FastISel::X86SelectBranch(Instruction *I) { bool X86FastISel::X86SelectShift(Instruction *I) { unsigned CReg = 0, OpReg = 0, OpImm = 0; const TargetRegisterClass *RC = NULL; - if (I->getType()->isInteger(8)) { + if (I->getType()->isIntegerTy(8)) { CReg = X86::CL; RC = &X86::GR8RegClass; switch (I->getOpcode()) { @@ -957,7 +966,7 @@ bool X86FastISel::X86SelectShift(Instruction *I) { case Instruction::Shl: OpReg = X86::SHL8rCL; OpImm = X86::SHL8ri; break; default: return false; } - } else if (I->getType()->isInteger(16)) { + } else if (I->getType()->isIntegerTy(16)) { CReg = X86::CX; RC = &X86::GR16RegClass; switch (I->getOpcode()) { @@ -966,7 +975,7 @@ bool X86FastISel::X86SelectShift(Instruction *I) { case Instruction::Shl: OpReg = X86::SHL16rCL; OpImm = X86::SHL16ri; break; default: return false; } - } else if (I->getType()->isInteger(32)) { + } else if (I->getType()->isIntegerTy(32)) { CReg = X86::ECX; RC = &X86::GR32RegClass; switch (I->getOpcode()) { @@ -975,7 +984,7 @@ bool X86FastISel::X86SelectShift(Instruction *I) { case Instruction::Shl: OpReg = X86::SHL32rCL; OpImm = X86::SHL32ri; break; default: return false; } - } else if (I->getType()->isInteger(64)) { + } else if (I->getType()->isIntegerTy(64)) { CReg = X86::RCX; RC = &X86::GR64RegClass; switch (I->getOpcode()) { @@ -1160,6 +1169,8 @@ bool X86FastISel::X86VisitIntrinsicCall(IntrinsicInst &I) { if (!X86SelectAddress(DI->getAddress(), AM)) return false; const TargetInstrDesc &II = TII.get(TargetOpcode::DBG_VALUE); + // FIXME may need to add RegState::Debug to any registers produced, + // although ESP/EBP should be the only ones at the moment. addFullAddress(BuildMI(MBB, DL, II), AM).addImm(0). addMetadata(DI->getVariable()); return true; diff --git a/lib/Target/X86/X86FixupKinds.h b/lib/Target/X86/X86FixupKinds.h new file mode 100644 index 0000000000..c8dac3ce45 --- /dev/null +++ b/lib/Target/X86/X86FixupKinds.h @@ -0,0 +1,25 @@ +//===-- X86/X86FixupKinds.h - X86 Specific Fixup Entries --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_X86_X86FIXUPKINDS_H +#define LLVM_X86_X86FIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +namespace llvm { +namespace X86 { +enum Fixups { + reloc_pcrel_4byte = FirstTargetFixupKind, // 32-bit pcrel, e.g. a branch. + reloc_pcrel_1byte, // 8-bit pcrel, e.g. branch_1 + reloc_riprel_4byte // 32-bit rip-relative +}; +} +} + +#endif diff --git a/lib/Target/X86/X86FloatingPointRegKill.cpp b/lib/Target/X86/X86FloatingPointRegKill.cpp index 34a0045344..6a117dde9b 100644 --- a/lib/Target/X86/X86FloatingPointRegKill.cpp +++ b/lib/Target/X86/X86FloatingPointRegKill.cpp @@ -118,7 +118,7 @@ bool FPRegKiller::runOnMachineFunction(MachineFunction &MF) { for (BasicBlock::const_iterator II = SI->begin(); (PN = dyn_cast(II)); ++II) { if (PN->getType()==Type::getX86_FP80Ty(LLVMBB->getContext()) || - (!Subtarget.hasSSE1() && PN->getType()->isFloatingPoint()) || + (!Subtarget.hasSSE1() && PN->getType()->isFloatingPointTy()) || (!Subtarget.hasSSE2() && PN->getType()==Type::getDoubleTy(LLVMBB->getContext()))) { ContainsFPCode = true; diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index e44ce4210c..3fad8ade41 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -12,15 +12,6 @@ // //===----------------------------------------------------------------------===// -// Force NDEBUG on in any optimized build on Darwin. -// -// FIXME: This is a huge hack, to work around ridiculously awful compile times -// on this file with gcc-4.2 on Darwin, in Release mode. -#if (!defined(__llvm__) && defined(__APPLE__) && \ - defined(__OPTIMIZE__) && !defined(NDEBUG)) -#define NDEBUG -#endif - #define DEBUG_TYPE "x86-isel" #include "X86.h" #include "X86InstrBuilder.h" @@ -177,14 +168,11 @@ namespace { return "X86 DAG->DAG Instruction Selection"; } - /// InstructionSelect - This callback is invoked by - /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. - virtual void InstructionSelect(); - virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF); - virtual - bool IsLegalAndProfitableToFold(SDNode *N, SDNode *U, SDNode *Root) const; + virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const; + + virtual void PreprocessISelDAG(); // Include the pieces autogenerated from the target description. #include "X86GenDAGISel.inc" @@ -208,18 +196,17 @@ namespace { SDValue &Scale, SDValue &Index, SDValue &Disp); bool SelectTLSADDRAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Scale, SDValue &Index, SDValue &Disp); - bool SelectScalarSSELoad(SDNode *Op, SDValue Pred, - SDValue N, SDValue &Base, SDValue &Scale, + bool SelectScalarSSELoad(SDNode *Root, SDValue N, + SDValue &Base, SDValue &Scale, SDValue &Index, SDValue &Disp, SDValue &Segment, - SDValue &InChain, SDValue &OutChain); + SDValue &NodeWithChain); + bool TryFoldLoad(SDNode *P, SDValue N, SDValue &Base, SDValue &Scale, SDValue &Index, SDValue &Disp, SDValue &Segment); - void PreprocessForRMW(); - void PreprocessForFPConvert(); - + /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for /// inline asm expressions. virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, @@ -295,19 +282,22 @@ namespace { const X86InstrInfo *getInstrInfo() { return getTargetMachine().getInstrInfo(); } - -#ifndef NDEBUG - unsigned Indent; -#endif }; } -bool X86DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, - SDNode *Root) const { +bool +X86DAGToDAGISel::IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const { if (OptLevel == CodeGenOpt::None) return false; - if (U == Root) + if (!N.hasOneUse()) + return false; + + if (N.getOpcode() != ISD::LOAD) + return true; + + // If N is a load, do additional profitability checks. + if (U == Root) { switch (U->getOpcode()) { default: break; case X86ISD::ADD: @@ -354,60 +344,9 @@ bool X86DAGToDAGISel::IsLegalAndProfitableToFold(SDNode *N, SDNode *U, } } } - - // Proceed to 'generic' cycle finder code - return SelectionDAGISel::IsLegalAndProfitableToFold(N, U, Root); -} - -/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand -/// and move load below the TokenFactor. Replace store's chain operand with -/// load's chain result. -static void MoveBelowTokenFactor(SelectionDAG *CurDAG, SDValue Load, - SDValue Store, SDValue TF) { - SmallVector Ops; - for (unsigned i = 0, e = TF.getNode()->getNumOperands(); i != e; ++i) - if (Load.getNode() == TF.getOperand(i).getNode()) - Ops.push_back(Load.getOperand(0)); - else - Ops.push_back(TF.getOperand(i)); - SDValue NewTF = CurDAG->UpdateNodeOperands(TF, &Ops[0], Ops.size()); - SDValue NewLoad = CurDAG->UpdateNodeOperands(Load, NewTF, - Load.getOperand(1), - Load.getOperand(2)); - CurDAG->UpdateNodeOperands(Store, NewLoad.getValue(1), Store.getOperand(1), - Store.getOperand(2), Store.getOperand(3)); -} - -/// isRMWLoad - Return true if N is a load that's part of RMW sub-DAG. The -/// chain produced by the load must only be used by the store's chain operand, -/// otherwise this may produce a cycle in the DAG. -/// -static bool isRMWLoad(SDValue N, SDValue Chain, SDValue Address, - SDValue &Load) { - if (N.getOpcode() == ISD::BIT_CONVERT) { - if (!N.hasOneUse()) - return false; - N = N.getOperand(0); } - LoadSDNode *LD = dyn_cast(N); - if (!LD || LD->isVolatile()) - return false; - if (LD->getAddressingMode() != ISD::UNINDEXED) - return false; - - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType != ISD::NON_EXTLOAD && ExtType != ISD::EXTLOAD) - return false; - - if (N.hasOneUse() && - LD->hasNUsesOfValue(1, 1) && - N.getOperand(1) == Address && - LD->isOperandOf(Chain.getNode())) { - Load = N; - return true; - } - return false; + return true; } /// MoveBelowCallSeqStart - Replace CALLSEQ_START operand with load's chain @@ -473,51 +412,15 @@ static bool isCalleeLoad(SDValue Callee, SDValue &Chain) { return false; } - -/// PreprocessForRMW - Preprocess the DAG to make instruction selection better. -/// This is only run if not in -O0 mode. -/// This allows the instruction selector to pick more read-modify-write -/// instructions. This is a common case: -/// -/// [Load chain] -/// ^ -/// | -/// [Load] -/// ^ ^ -/// | | -/// / \- -/// / | -/// [TokenFactor] [Op] -/// ^ ^ -/// | | -/// \ / -/// \ / -/// [Store] -/// -/// The fact the store's chain operand != load's chain will prevent the -/// (store (op (load))) instruction from being selected. We can transform it to: -/// -/// [Load chain] -/// ^ -/// | -/// [TokenFactor] -/// ^ -/// | -/// [Load] -/// ^ ^ -/// | | -/// | \- -/// | | -/// | [Op] -/// | ^ -/// | | -/// \ / -/// \ / -/// [Store] -void X86DAGToDAGISel::PreprocessForRMW() { +void X86DAGToDAGISel::PreprocessISelDAG() { + // OptForSize is used in pattern predicates that isel is matching. + OptForSize = MF->getFunction()->hasFnAttr(Attribute::OptimizeForSize); + for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), - E = CurDAG->allnodes_end(); I != E; ++I) { - if (I->getOpcode() == X86ISD::CALL) { + E = CurDAG->allnodes_end(); I != E; ) { + SDNode *N = I++; // Preincrement iterator to avoid invalidation issues. + + if (OptLevel != CodeGenOpt::None && N->getOpcode() == X86ISD::CALL) { /// Also try moving call address load from outside callseq_start to just /// before the call to allow it to be folded. /// @@ -537,85 +440,23 @@ void X86DAGToDAGISel::PreprocessForRMW() { /// \ / /// \ / /// [CALL] - SDValue Chain = I->getOperand(0); - SDValue Load = I->getOperand(1); + SDValue Chain = N->getOperand(0); + SDValue Load = N->getOperand(1); if (!isCalleeLoad(Load, Chain)) continue; - MoveBelowCallSeqStart(CurDAG, Load, SDValue(I, 0), Chain); + MoveBelowCallSeqStart(CurDAG, Load, SDValue(N, 0), Chain); ++NumLoadMoved; continue; } - - if (!ISD::isNON_TRUNCStore(I)) - continue; - SDValue Chain = I->getOperand(0); - - if (Chain.getNode()->getOpcode() != ISD::TokenFactor) - continue; - - SDValue N1 = I->getOperand(1); - SDValue N2 = I->getOperand(2); - if ((N1.getValueType().isFloatingPoint() && - !N1.getValueType().isVector()) || - !N1.hasOneUse()) - continue; - - bool RModW = false; - SDValue Load; - unsigned Opcode = N1.getNode()->getOpcode(); - switch (Opcode) { - case ISD::ADD: - case ISD::MUL: - case ISD::AND: - case ISD::OR: - case ISD::XOR: - case ISD::ADDC: - case ISD::ADDE: - case ISD::VECTOR_SHUFFLE: { - SDValue N10 = N1.getOperand(0); - SDValue N11 = N1.getOperand(1); - RModW = isRMWLoad(N10, Chain, N2, Load); - if (!RModW) - RModW = isRMWLoad(N11, Chain, N2, Load); - break; - } - case ISD::SUB: - case ISD::SHL: - case ISD::SRA: - case ISD::SRL: - case ISD::ROTL: - case ISD::ROTR: - case ISD::SUBC: - case ISD::SUBE: - case X86ISD::SHLD: - case X86ISD::SHRD: { - SDValue N10 = N1.getOperand(0); - RModW = isRMWLoad(N10, Chain, N2, Load); - break; - } - } - - if (RModW) { - MoveBelowTokenFactor(CurDAG, Load, SDValue(I, 0), Chain); - ++NumLoadMoved; - checkForCycles(I); - } - } -} - - -/// PreprocessForFPConvert - Walk over the dag lowering fpround and fpextend -/// nodes that target the FP stack to be store and load to the stack. This is a -/// gross hack. We would like to simply mark these as being illegal, but when -/// we do that, legalize produces these when it expands calls, then expands -/// these in the same legalize pass. We would like dag combine to be able to -/// hack on these between the call expansion and the node legalization. As such -/// this pass basically does "really late" legalization of these inline with the -/// X86 isel pass. -void X86DAGToDAGISel::PreprocessForFPConvert() { - for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(), - E = CurDAG->allnodes_end(); I != E; ) { - SDNode *N = I++; // Preincrement iterator to avoid invalidation issues. + + // Lower fpround and fpextend nodes that target the FP stack to be store and + // load to the stack. This is a gross hack. We would like to simply mark + // these as being illegal, but when we do that, legalize produces these when + // it expands calls, then expands these in the same legalize pass. We would + // like dag combine to be able to hack on these between the call expansion + // and the node legalization. As such this pass basically does "really + // late" legalization of these inline with the X86 isel pass. + // FIXME: This should only happen when not compiled with -O0. if (N->getOpcode() != ISD::FP_ROUND && N->getOpcode() != ISD::FP_EXTEND) continue; @@ -652,9 +493,10 @@ void X86DAGToDAGISel::PreprocessForFPConvert() { // FIXME: optimize the case where the src/dest is a load or store? SDValue Store = CurDAG->getTruncStore(CurDAG->getEntryNode(), dl, N->getOperand(0), - MemTmp, NULL, 0, MemVT); + MemTmp, NULL, 0, MemVT, + false, false, 0); SDValue Result = CurDAG->getExtLoad(ISD::EXTLOAD, dl, DstVT, Store, MemTmp, - NULL, 0, MemVT); + NULL, 0, MemVT, false, false, 0); // We're about to replace all uses of the FP_ROUND/FP_EXTEND with the // extload we created. This will cause general havok on the dag because @@ -670,30 +512,6 @@ void X86DAGToDAGISel::PreprocessForFPConvert() { } } -/// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel -/// when it has created a SelectionDAG for us to codegen. -void X86DAGToDAGISel::InstructionSelect() { - const Function *F = MF->getFunction(); - OptForSize = F->hasFnAttr(Attribute::OptimizeForSize); - - if (OptLevel != CodeGenOpt::None) - PreprocessForRMW(); - - // FIXME: This should only happen when not compiled with -O0. - PreprocessForFPConvert(); - - // Codegen the basic block. -#ifndef NDEBUG - DEBUG(dbgs() << "===== Instruction selection begins:\n"); - Indent = 0; -#endif - SelectRoot(*CurDAG); -#ifndef NDEBUG - DEBUG(dbgs() << "===== Instruction selection ends:\n"); -#endif - - CurDAG->RemoveDeadNodes(); -} /// EmitSpecialCodeForMain - Emit any code that needs to be executed only in /// the main function. @@ -1300,22 +1118,24 @@ bool X86DAGToDAGISel::SelectAddr(SDNode *Op, SDValue N, SDValue &Base, /// SelectScalarSSELoad - Match a scalar SSE load. In particular, we want to /// match a load whose top elements are either undef or zeros. The load flavor /// is derived from the type of N, which is either v4f32 or v2f64. -bool X86DAGToDAGISel::SelectScalarSSELoad(SDNode *Op, SDValue Pred, +/// +/// We also return: +/// PatternChainNode: this is the matched node that has a chain input and +/// output. +bool X86DAGToDAGISel::SelectScalarSSELoad(SDNode *Root, SDValue N, SDValue &Base, SDValue &Scale, SDValue &Index, SDValue &Disp, SDValue &Segment, - SDValue &InChain, - SDValue &OutChain) { + SDValue &PatternNodeWithChain) { if (N.getOpcode() == ISD::SCALAR_TO_VECTOR) { - InChain = N.getOperand(0).getValue(1); - if (ISD::isNON_EXTLoad(InChain.getNode()) && - InChain.getValue(0).hasOneUse() && - N.hasOneUse() && - IsLegalAndProfitableToFold(N.getNode(), Pred.getNode(), Op)) { - LoadSDNode *LD = cast(InChain); - if (!SelectAddr(Op, LD->getBasePtr(), Base, Scale, Index, Disp, Segment)) + PatternNodeWithChain = N.getOperand(0); + if (ISD::isNON_EXTLoad(PatternNodeWithChain.getNode()) && + PatternNodeWithChain.hasOneUse() && + IsProfitableToFold(N.getOperand(0), N.getNode(), Root) && + IsLegalToFold(N.getOperand(0), N.getNode(), Root)) { + LoadSDNode *LD = cast(PatternNodeWithChain); + if (!SelectAddr(Root, LD->getBasePtr(), Base, Scale, Index, Disp,Segment)) return false; - OutChain = LD->getChain(); return true; } } @@ -1327,13 +1147,14 @@ bool X86DAGToDAGISel::SelectScalarSSELoad(SDNode *Op, SDValue Pred, N.getOperand(0).getOpcode() == ISD::SCALAR_TO_VECTOR && N.getOperand(0).getNode()->hasOneUse() && ISD::isNON_EXTLoad(N.getOperand(0).getOperand(0).getNode()) && - N.getOperand(0).getOperand(0).hasOneUse()) { + N.getOperand(0).getOperand(0).hasOneUse() && + IsProfitableToFold(N.getOperand(0), N.getNode(), Root) && + IsLegalToFold(N.getOperand(0), N.getNode(), Root)) { // Okay, this is a zero extending load. Fold it. LoadSDNode *LD = cast(N.getOperand(0).getOperand(0)); - if (!SelectAddr(Op, LD->getBasePtr(), Base, Scale, Index, Disp, Segment)) + if (!SelectAddr(Root, LD->getBasePtr(), Base, Scale, Index, Disp, Segment)) return false; - OutChain = LD->getChain(); - InChain = SDValue(LD, 1); + PatternNodeWithChain = SDValue(LD, 0); return true; } return false; @@ -1407,7 +1228,6 @@ bool X86DAGToDAGISel::SelectLEAAddr(SDNode *Op, SDValue N, bool X86DAGToDAGISel::SelectTLSADDRAddr(SDNode *Op, SDValue N, SDValue &Base, SDValue &Scale, SDValue &Index, SDValue &Disp) { - assert(Op->getOpcode() == X86ISD::TLSADDR); assert(N.getOpcode() == ISD::TargetGlobalTLSAddress); const GlobalAddressSDNode *GA = cast(N); @@ -1434,11 +1254,12 @@ bool X86DAGToDAGISel::TryFoldLoad(SDNode *P, SDValue N, SDValue &Base, SDValue &Scale, SDValue &Index, SDValue &Disp, SDValue &Segment) { - if (ISD::isNON_EXTLoad(N.getNode()) && - N.hasOneUse() && - IsLegalAndProfitableToFold(N.getNode(), P, P)) - return SelectAddr(P, N.getOperand(1), Base, Scale, Index, Disp, Segment); - return false; + if (!ISD::isNON_EXTLoad(N.getNode()) || + !IsProfitableToFold(N, P, P) || + !IsLegalToFold(N, P, P)) + return false; + + return SelectAddr(P, N.getOperand(1), Base, Scale, Index, Disp, Segment); } /// getGlobalBaseReg - Return an SDNode that returns the value of @@ -1541,7 +1362,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { Opc = X86::LOCK_DEC16m; else if (isSub) { if (isCN) { - if (Predicate_i16immSExt8(Val.getNode())) + if (Predicate_immSext8(Val.getNode())) Opc = X86::LOCK_SUB16mi8; else Opc = X86::LOCK_SUB16mi; @@ -1549,7 +1370,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { Opc = X86::LOCK_SUB16mr; } else { if (isCN) { - if (Predicate_i16immSExt8(Val.getNode())) + if (Predicate_immSext8(Val.getNode())) Opc = X86::LOCK_ADD16mi8; else Opc = X86::LOCK_ADD16mi; @@ -1564,7 +1385,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { Opc = X86::LOCK_DEC32m; else if (isSub) { if (isCN) { - if (Predicate_i32immSExt8(Val.getNode())) + if (Predicate_immSext8(Val.getNode())) Opc = X86::LOCK_SUB32mi8; else Opc = X86::LOCK_SUB32mi; @@ -1572,7 +1393,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { Opc = X86::LOCK_SUB32mr; } else { if (isCN) { - if (Predicate_i32immSExt8(Val.getNode())) + if (Predicate_immSext8(Val.getNode())) Opc = X86::LOCK_ADD32mi8; else Opc = X86::LOCK_ADD32mi; @@ -1588,7 +1409,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { else if (isSub) { Opc = X86::LOCK_SUB64mr; if (isCN) { - if (Predicate_i64immSExt8(Val.getNode())) + if (Predicate_immSext8(Val.getNode())) Opc = X86::LOCK_SUB64mi8; else if (Predicate_i64immSExt32(Val.getNode())) Opc = X86::LOCK_SUB64mi32; @@ -1596,7 +1417,7 @@ SDNode *X86DAGToDAGISel::SelectAtomicLoadAdd(SDNode *Node, EVT NVT) { } else { Opc = X86::LOCK_ADD64mr; if (isCN) { - if (Predicate_i64immSExt8(Val.getNode())) + if (Predicate_immSext8(Val.getNode())) Opc = X86::LOCK_ADD64mi8; else if (Predicate_i64immSExt32(Val.getNode())) Opc = X86::LOCK_ADD64mi32; @@ -1652,8 +1473,8 @@ static bool HasNoSignedComparisonUses(SDNode *N) { case X86::SETEr: case X86::SETNEr: case X86::SETPr: case X86::SETNPr: case X86::SETAm: case X86::SETAEm: case X86::SETBm: case X86::SETBEm: case X86::SETEm: case X86::SETNEm: case X86::SETPm: case X86::SETNPm: - case X86::JA: case X86::JAE: case X86::JB: case X86::JBE: - case X86::JE: case X86::JNE: case X86::JP: case X86::JNP: + case X86::JA_4: case X86::JAE_4: case X86::JB_4: case X86::JBE_4: + case X86::JE_4: case X86::JNE_4: case X86::JP_4: case X86::JNP_4: case X86::CMOVA16rr: case X86::CMOVA16rm: case X86::CMOVA32rr: case X86::CMOVA32rm: case X86::CMOVA64rr: case X86::CMOVA64rm: @@ -1693,24 +1514,10 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) { unsigned Opcode = Node->getOpcode(); DebugLoc dl = Node->getDebugLoc(); -#ifndef NDEBUG - DEBUG({ - dbgs() << std::string(Indent, ' ') << "Selecting: "; - Node->dump(CurDAG); - dbgs() << '\n'; - }); - Indent += 2; -#endif + DEBUG(dbgs() << "Selecting: "; Node->dump(CurDAG); dbgs() << '\n'); if (Node->isMachineOpcode()) { -#ifndef NDEBUG - DEBUG({ - dbgs() << std::string(Indent-2, ' ') << "== "; - Node->dump(CurDAG); - dbgs() << '\n'; - }); - Indent -= 2; -#endif + DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n'); return NULL; // Already selected. } @@ -1806,13 +1613,7 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) { LoReg, NVT, InFlag); InFlag = Result.getValue(2); ReplaceUses(SDValue(Node, 0), Result); -#ifndef NDEBUG - DEBUG({ - dbgs() << std::string(Indent-2, ' ') << "=> "; - Result.getNode()->dump(CurDAG); - dbgs() << '\n'; - }); -#endif + DEBUG(dbgs() << "=> "; Result.getNode()->dump(CurDAG); dbgs() << '\n'); } // Copy the high half of the result, if it is needed. if (!SDValue(Node, 1).use_empty()) { @@ -1835,19 +1636,9 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) { InFlag = Result.getValue(2); } ReplaceUses(SDValue(Node, 1), Result); -#ifndef NDEBUG - DEBUG({ - dbgs() << std::string(Indent-2, ' ') << "=> "; - Result.getNode()->dump(CurDAG); - dbgs() << '\n'; - }); -#endif + DEBUG(dbgs() << "=> "; Result.getNode()->dump(CurDAG); dbgs() << '\n'); } -#ifndef NDEBUG - Indent -= 2; -#endif - return NULL; } @@ -1962,13 +1753,7 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) { LoReg, NVT, InFlag); InFlag = Result.getValue(2); ReplaceUses(SDValue(Node, 0), Result); -#ifndef NDEBUG - DEBUG({ - dbgs() << std::string(Indent-2, ' ') << "=> "; - Result.getNode()->dump(CurDAG); - dbgs() << '\n'; - }); -#endif + DEBUG(dbgs() << "=> "; Result.getNode()->dump(CurDAG); dbgs() << '\n'); } // Copy the remainder (high) result, if it is needed. if (!SDValue(Node, 1).use_empty()) { @@ -1992,19 +1777,8 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) { InFlag = Result.getValue(2); } ReplaceUses(SDValue(Node, 1), Result); -#ifndef NDEBUG - DEBUG({ - dbgs() << std::string(Indent-2, ' ') << "=> "; - Result.getNode()->dump(CurDAG); - dbgs() << '\n'; - }); -#endif + DEBUG(dbgs() << "=> "; Result.getNode()->dump(CurDAG); dbgs() << '\n'); } - -#ifndef NDEBUG - Indent -= 2; -#endif - return NULL; } @@ -2117,17 +1891,12 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) { SDNode *ResNode = SelectCode(Node); -#ifndef NDEBUG - DEBUG({ - dbgs() << std::string(Indent-2, ' ') << "=> "; - if (ResNode == NULL || ResNode == Node) - Node->dump(CurDAG); - else - ResNode->dump(CurDAG); - dbgs() << '\n'; - }); - Indent -= 2; -#endif + DEBUG(dbgs() << "=> "; + if (ResNode == NULL || ResNode == Node) + Node->dump(CurDAG); + else + ResNode->dump(CurDAG); + dbgs() << '\n'); return ResNode; } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 515bc84dad..802bedcf31 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -73,15 +73,16 @@ static TargetLoweringObjectFile *createTLOF(X86TargetMachine &TM) { case X86Subtarget::isDarwin: if (TM.getSubtarget().is64Bit()) return new X8664_MachoTargetObjectFile(); - return new X8632_MachoTargetObjectFile(); + return new TargetLoweringObjectFileMachO(); case X86Subtarget::isELF: - return new TargetLoweringObjectFileELF(); + if (TM.getSubtarget().is64Bit()) + return new X8664_ELFTargetObjectFile(TM); + return new X8632_ELFTargetObjectFile(TM); case X86Subtarget::isMingw: case X86Subtarget::isCygwin: case X86Subtarget::isWindows: return new TargetLoweringObjectFileCOFF(); } - } X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) @@ -1001,19 +1002,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) computeRegisterProperties(); - // Divide and reminder operations have no vector equivalent and can - // trap. Do a custom widening for these operations in which we never - // generate more divides/remainder than the original vector width. - for (unsigned VT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; - VT <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++VT) { - if (!isTypeLegal((MVT::SimpleValueType)VT)) { - setOperationAction(ISD::SDIV, (MVT::SimpleValueType) VT, Custom); - setOperationAction(ISD::UDIV, (MVT::SimpleValueType) VT, Custom); - setOperationAction(ISD::SREM, (MVT::SimpleValueType) VT, Custom); - setOperationAction(ISD::UREM, (MVT::SimpleValueType) VT, Custom); - } - } - // FIXME: These should be based on subtarget info. Plus, the values should // be smaller when we are in optimizing for size mode. maxStoresPerMemset = 16; // For @llvm.memset -> sequence of stores @@ -1411,18 +1399,6 @@ CCAssignFn *X86TargetLowering::CCAssignFnForNode(CallingConv::ID CC) const { return CC_X86_32_C; } -/// NameDecorationForCallConv - Selects the appropriate decoration to -/// apply to a MachineFunction containing a given calling convention. -NameDecorationStyle -X86TargetLowering::NameDecorationForCallConv(CallingConv::ID CallConv) { - if (CallConv == CallingConv::X86_FastCall) - return FastCall; - else if (CallConv == CallingConv::X86_StdCall) - return StdCall; - return None; -} - - /// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified /// by "Src" to address "Dst" with size and alignment information specified by /// the specific parameter attribute. The copy will be passed as a byval @@ -1476,7 +1452,8 @@ X86TargetLowering::LowerMemArgument(SDValue Chain, VA.getLocMemOffset(), isImmutable, false); SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); return DAG.getLoad(ValVT, dl, Chain, FIN, - PseudoSourceValue::getFixedStack(FI), 0); + PseudoSourceValue::getFixedStack(FI), 0, + false, false, 0); } } @@ -1498,9 +1475,6 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, Fn->getName() == "main") FuncInfo->setForceFramePointer(true); - // Decorate the function name. - FuncInfo->setDecorationStyle(NameDecorationForCallConv(CallConv)); - MachineFrameInfo *MFI = MF.getFrameInfo(); bool Is64Bit = Subtarget->is64Bit(); bool IsWin64 = Subtarget->isTargetWin64(); @@ -1573,7 +1547,8 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, // If value is passed via pointer - do a load. if (VA.getLocInfo() == CCValAssign::Indirect) - ArgValue = DAG.getLoad(VA.getValVT(), dl, Chain, ArgValue, NULL, 0); + ArgValue = DAG.getLoad(VA.getValVT(), dl, Chain, ArgValue, NULL, 0, + false, false, 0); InVals.push_back(ArgValue); } @@ -1668,7 +1643,7 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, PseudoSourceValue::getFixedStack(RegSaveFrameIndex), - Offset); + Offset, false, false, 0); MemOps.push_back(Store); Offset += 8; } @@ -1737,7 +1712,8 @@ X86TargetLowering::LowerMemOpCallTo(SDValue Chain, return CreateCopyOfByValArgument(Arg, PtrOff, Chain, Flags, DAG, dl); } return DAG.getStore(Chain, dl, Arg, PtrOff, - PseudoSourceValue::getStack(), LocMemOffset); + PseudoSourceValue::getStack(), LocMemOffset, + false, false, 0); } /// EmitTailCallLoadRetAddr - Emit a load of return address if tail call @@ -1752,7 +1728,7 @@ X86TargetLowering::EmitTailCallLoadRetAddr(SelectionDAG &DAG, OutRetAddr = getReturnAddressFrameIndex(DAG); // Load the "old" Return address. - OutRetAddr = DAG.getLoad(VT, dl, Chain, OutRetAddr, NULL, 0); + OutRetAddr = DAG.getLoad(VT, dl, Chain, OutRetAddr, NULL, 0, false, false, 0); return SDValue(OutRetAddr.getNode(), 1); } @@ -1767,11 +1743,12 @@ EmitTailCallStoreRetAddr(SelectionDAG & DAG, MachineFunction &MF, // Calculate the new stack slot for the return address. int SlotSize = Is64Bit ? 8 : 4; int NewReturnAddrFI = - MF.getFrameInfo()->CreateFixedObject(SlotSize, FPDiff-SlotSize, true,false); + MF.getFrameInfo()->CreateFixedObject(SlotSize, FPDiff-SlotSize, false, false); EVT VT = Is64Bit ? MVT::i64 : MVT::i32; SDValue NewRetAddrFrIdx = DAG.getFrameIndex(NewReturnAddrFI, VT); Chain = DAG.getStore(Chain, dl, RetAddrFrIdx, NewRetAddrFrIdx, - PseudoSourceValue::getFixedStack(NewReturnAddrFI), 0); + PseudoSourceValue::getFixedStack(NewReturnAddrFI), 0, + false, false, 0); return Chain; } @@ -1882,7 +1859,8 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, SDValue SpillSlot = DAG.CreateStackTemporary(VA.getValVT()); int FI = cast(SpillSlot)->getIndex(); Chain = DAG.getStore(Chain, dl, Arg, SpillSlot, - PseudoSourceValue::getFixedStack(FI), 0); + PseudoSourceValue::getFixedStack(FI), 0, + false, false, 0); Arg = SpillSlot; break; } @@ -2013,7 +1991,8 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, // Store relative to framepointer. MemOpChains2.push_back( DAG.getStore(ArgChain, dl, Arg, FIN, - PseudoSourceValue::getFixedStack(FI), 0)); + PseudoSourceValue::getFixedStack(FI), 0, + false, false, 0)); } } } @@ -2256,7 +2235,8 @@ static bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, MachineFrameInfo *MFI, const MachineRegisterInfo *MRI, const X86InstrInfo *TII) { - int FI; + unsigned Bytes = Arg.getValueType().getSizeInBits() / 8; + int FI = INT_MAX; if (Arg.getOpcode() == ISD::CopyFromReg) { unsigned VR = cast(Arg.getOperand(1))->getReg(); if (!VR || TargetRegisterInfo::isPhysicalRegister(VR)) @@ -2272,25 +2252,30 @@ bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags, if ((Opcode == X86::LEA32r || Opcode == X86::LEA64r) && Def->getOperand(1).isFI()) { FI = Def->getOperand(1).getIndex(); - if (MFI->getObjectSize(FI) != Flags.getByValSize()) - return false; + Bytes = Flags.getByValSize(); } else return false; } - } else { - LoadSDNode *Ld = dyn_cast(Arg); - if (!Ld) + } else if (LoadSDNode *Ld = dyn_cast(Arg)) { + if (Flags.isByVal()) + // ByVal argument is passed in as a pointer but it's now being + // dereferenced. e.g. + // define @foo(%struct.X* %A) { + // tail call @bar(%struct.X* byval %A) + // } return false; SDValue Ptr = Ld->getBasePtr(); FrameIndexSDNode *FINode = dyn_cast(Ptr); if (!FINode) return false; FI = FINode->getIndex(); - } + } else + return false; + assert(FI != INT_MAX); if (!MFI->isFixedObjectIndex(FI)) return false; - return Offset == MFI->getObjectOffset(FI); + return Offset == MFI->getObjectOffset(FI) && Bytes == MFI->getObjectSize(FI); } /// IsEligibleForTailCallOptimization - Check whether the call is eligible @@ -2397,7 +2382,7 @@ SDValue X86TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) { // Set up a frame object for the return address. uint64_t SlotSize = TD->getPointerSize(); ReturnAddrIndex = MF.getFrameInfo()->CreateFixedObject(SlotSize, -SlotSize, - true, false); + false, false); FuncInfo->setRAIndex(ReturnAddrIndex); } @@ -3592,7 +3577,8 @@ X86TargetLowering::LowerAsSplatVectorLoad(SDValue SrcOp, EVT VT, DebugLoc dl, int EltNo = (Offset - StartOffset) >> 2; int Mask[4] = { EltNo, EltNo, EltNo, EltNo }; EVT VT = (PVT == MVT::i32) ? MVT::v4i32 : MVT::v4f32; - SDValue V1 = DAG.getLoad(VT, dl, Chain, Ptr,LD->getSrcValue(),0); + SDValue V1 = DAG.getLoad(VT, dl, Chain, Ptr,LD->getSrcValue(),0, + false, false, 0); // Canonicalize it to a v4i32 shuffle. V1 = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v4i32, V1); return DAG.getNode(ISD::BIT_CONVERT, dl, VT, @@ -4836,8 +4822,16 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT_SSE4(SDValue Op, SelectionDAG &DAG){ if ((EltVT.getSizeInBits() == 8 || EltVT.getSizeInBits() == 16) && isa(N2)) { - unsigned Opc = (EltVT.getSizeInBits() == 8) ? X86ISD::PINSRB - : X86ISD::PINSRW; + unsigned Opc; + if (VT == MVT::v8i16) + Opc = X86ISD::PINSRW; + else if (VT == MVT::v4i16) + Opc = X86ISD::MMX_PINSRW; + else if (VT == MVT::v16i8) + Opc = X86ISD::PINSRB; + else + Opc = X86ISD::PINSRB; + // Transform it so it match pinsr{b,w} which expects a GR32 as its second // argument. if (N1.getValueType() != MVT::i32) @@ -4888,7 +4882,8 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) { N1 = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, N1); if (N2.getValueType() != MVT::i32) N2 = DAG.getIntPtrConstant(cast(N2)->getZExtValue()); - return DAG.getNode(X86ISD::PINSRW, dl, VT, N0, N1, N2); + return DAG.getNode(VT == MVT::v8i16 ? X86ISD::PINSRW : X86ISD::MMX_PINSRW, + dl, VT, N0, N1, N2); } return SDValue(); } @@ -5091,7 +5086,7 @@ X86TargetLowering::LowerGlobalAddress(const GlobalValue *GV, DebugLoc dl, // load. if (isGlobalStubReference(OpFlags)) Result = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Result, - PseudoSourceValue::getGOT(), 0); + PseudoSourceValue::getGOT(), 0, false, false, 0); // If there was a non-zero offset that we didn't fold, create an explicit // addition for it. @@ -5171,7 +5166,7 @@ static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, MVT::i32)); SDValue ThreadPointer = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Base, - NULL, 0); + NULL, 0, false, false, 0); unsigned char OperandFlags = 0; // Most TLS accesses are not RIP relative, even on x86-64. One exception is @@ -5196,7 +5191,7 @@ static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG, if (model == TLSModel::InitialExec) Offset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Offset, - PseudoSourceValue::getGOT(), 0); + PseudoSourceValue::getGOT(), 0, false, false, 0); // The address of the thread local variable is the add of the thread // pointer with the offset of the variable. @@ -5264,7 +5259,7 @@ SDValue X86TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) { SDValue AndNode = DAG.getNode(ISD::AND, dl, MVT::i8, ShAmt, DAG.getConstant(VTBits, MVT::i8)); - SDValue Cond = DAG.getNode(X86ISD::CMP, dl, VT, + SDValue Cond = DAG.getNode(X86ISD::CMP, dl, MVT::i32, AndNode, DAG.getConstant(0, MVT::i8)); SDValue Hi, Lo; @@ -5313,7 +5308,8 @@ SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) { SDValue StackSlot = DAG.getFrameIndex(SSFI, getPointerTy()); SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl, Op.getOperand(0), StackSlot, - PseudoSourceValue::getFixedStack(SSFI), 0); + PseudoSourceValue::getFixedStack(SSFI), 0, + false, false, 0); return BuildFILD(Op, SrcVT, Chain, StackSlot, DAG); } @@ -5348,7 +5344,8 @@ SDValue X86TargetLowering::BuildFILD(SDValue Op, EVT SrcVT, SDValue Chain, }; Chain = DAG.getNode(X86ISD::FST, dl, Tys, Ops, array_lengthof(Ops)); Result = DAG.getLoad(Op.getValueType(), dl, Chain, StackSlot, - PseudoSourceValue::getFixedStack(SSFI), 0); + PseudoSourceValue::getFixedStack(SSFI), 0, + false, false, 0); } return Result; @@ -5421,12 +5418,12 @@ SDValue X86TargetLowering::LowerUINT_TO_FP_i64(SDValue Op, SelectionDAG &DAG) { SDValue Unpck1 = getUnpackl(DAG, dl, MVT::v4i32, XR1, XR2); SDValue CLod0 = DAG.getLoad(MVT::v4i32, dl, DAG.getEntryNode(), CPIdx0, PseudoSourceValue::getConstantPool(), 0, - false, 16); + false, false, 16); SDValue Unpck2 = getUnpackl(DAG, dl, MVT::v4i32, Unpck1, CLod0); SDValue XR2F = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v2f64, Unpck2); SDValue CLod1 = DAG.getLoad(MVT::v2f64, dl, CLod0.getValue(1), CPIdx1, PseudoSourceValue::getConstantPool(), 0, - false, 16); + false, false, 16); SDValue Sub = DAG.getNode(ISD::FSUB, dl, MVT::v2f64, XR2F, CLod1); // Add the halves; easiest way is to swap them into another reg first. @@ -5513,9 +5510,9 @@ SDValue X86TargetLowering::LowerUINT_TO_FP(SDValue Op, SelectionDAG &DAG) { SDValue OffsetSlot = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackSlot, WordOff); SDValue Store1 = DAG.getStore(DAG.getEntryNode(), dl, Op.getOperand(0), - StackSlot, NULL, 0); + StackSlot, NULL, 0, false, false, 0); SDValue Store2 = DAG.getStore(Store1, dl, DAG.getConstant(0, MVT::i32), - OffsetSlot, NULL, 0); + OffsetSlot, NULL, 0, false, false, 0); return BuildFILD(Op, MVT::i64, Store2, StackSlot, DAG); } @@ -5563,7 +5560,8 @@ FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG, bool IsSigned) { if (isScalarFPTypeInSSEReg(Op.getOperand(0).getValueType())) { assert(DstTy == MVT::i64 && "Invalid FP_TO_SINT to lower!"); Chain = DAG.getStore(Chain, dl, Value, StackSlot, - PseudoSourceValue::getFixedStack(SSFI), 0); + PseudoSourceValue::getFixedStack(SSFI), 0, + false, false, 0); SDVTList Tys = DAG.getVTList(Op.getOperand(0).getValueType(), MVT::Other); SDValue Ops[] = { Chain, StackSlot, DAG.getValueType(Op.getOperand(0).getValueType()) @@ -5597,7 +5595,7 @@ SDValue X86TargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) { // Load the result. return DAG.getLoad(Op.getValueType(), Op.getDebugLoc(), - FIST, StackSlot, NULL, 0); + FIST, StackSlot, NULL, 0, false, false, 0); } SDValue X86TargetLowering::LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG) { @@ -5607,7 +5605,7 @@ SDValue X86TargetLowering::LowerFP_TO_UINT(SDValue Op, SelectionDAG &DAG) { // Load the result. return DAG.getLoad(Op.getValueType(), Op.getDebugLoc(), - FIST, StackSlot, NULL, 0); + FIST, StackSlot, NULL, 0, false, false, 0); } SDValue X86TargetLowering::LowerFABS(SDValue Op, SelectionDAG &DAG) { @@ -5632,8 +5630,8 @@ SDValue X86TargetLowering::LowerFABS(SDValue Op, SelectionDAG &DAG) { Constant *C = ConstantVector::get(CV); SDValue CPIdx = DAG.getConstantPool(C, getPointerTy(), 16); SDValue Mask = DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0, - false, 16); + PseudoSourceValue::getConstantPool(), 0, + false, false, 16); return DAG.getNode(X86ISD::FAND, dl, VT, Op.getOperand(0), Mask); } @@ -5659,8 +5657,8 @@ SDValue X86TargetLowering::LowerFNEG(SDValue Op, SelectionDAG &DAG) { Constant *C = ConstantVector::get(CV); SDValue CPIdx = DAG.getConstantPool(C, getPointerTy(), 16); SDValue Mask = DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0, - false, 16); + PseudoSourceValue::getConstantPool(), 0, + false, false, 16); if (VT.isVector()) { return DAG.getNode(ISD::BIT_CONVERT, dl, VT, DAG.getNode(ISD::XOR, dl, MVT::v2i64, @@ -5708,8 +5706,8 @@ SDValue X86TargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) { Constant *C = ConstantVector::get(CV); SDValue CPIdx = DAG.getConstantPool(C, getPointerTy(), 16); SDValue Mask1 = DAG.getLoad(SrcVT, dl, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0, - false, 16); + PseudoSourceValue::getConstantPool(), 0, + false, false, 16); SDValue SignBit = DAG.getNode(X86ISD::FAND, dl, SrcVT, Op1, Mask1); // Shift sign bit right or left if the two operands have different types. @@ -5737,8 +5735,8 @@ SDValue X86TargetLowering::LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) { C = ConstantVector::get(CV); CPIdx = DAG.getConstantPool(C, getPointerTy(), 16); SDValue Mask2 = DAG.getLoad(VT, dl, DAG.getEntryNode(), CPIdx, - PseudoSourceValue::getConstantPool(), 0, - false, 16); + PseudoSourceValue::getConstantPool(), 0, + false, false, 16); SDValue Val = DAG.getNode(X86ISD::FAND, dl, VT, Op0, Mask2); // Or the value with the sign bit. @@ -5890,26 +5888,31 @@ SDValue X86TargetLowering::EmitCmp(SDValue Op0, SDValue Op1, unsigned X86CC, /// LowerToBT - Result of 'and' is compared against zero. Turn it into a BT node /// if it's possible. -static SDValue LowerToBT(SDValue Op0, ISD::CondCode CC, +static SDValue LowerToBT(SDValue And, ISD::CondCode CC, DebugLoc dl, SelectionDAG &DAG) { + SDValue Op0 = And.getOperand(0); + SDValue Op1 = And.getOperand(1); + if (Op0.getOpcode() == ISD::TRUNCATE) + Op0 = Op0.getOperand(0); + if (Op1.getOpcode() == ISD::TRUNCATE) + Op1 = Op1.getOperand(0); + SDValue LHS, RHS; - if (Op0.getOperand(1).getOpcode() == ISD::SHL) { - if (ConstantSDNode *Op010C = - dyn_cast(Op0.getOperand(1).getOperand(0))) - if (Op010C->getZExtValue() == 1) { - LHS = Op0.getOperand(0); - RHS = Op0.getOperand(1).getOperand(1); + if (Op1.getOpcode() == ISD::SHL) { + if (ConstantSDNode *And10C = dyn_cast(Op1.getOperand(0))) + if (And10C->getZExtValue() == 1) { + LHS = Op0; + RHS = Op1.getOperand(1); } - } else if (Op0.getOperand(0).getOpcode() == ISD::SHL) { - if (ConstantSDNode *Op000C = - dyn_cast(Op0.getOperand(0).getOperand(0))) - if (Op000C->getZExtValue() == 1) { - LHS = Op0.getOperand(1); - RHS = Op0.getOperand(0).getOperand(1); + } else if (Op0.getOpcode() == ISD::SHL) { + if (ConstantSDNode *And00C = dyn_cast(Op0.getOperand(0))) + if (And00C->getZExtValue() == 1) { + LHS = Op1; + RHS = Op0.getOperand(1); } - } else if (Op0.getOperand(1).getOpcode() == ISD::Constant) { - ConstantSDNode *AndRHS = cast(Op0.getOperand(1)); - SDValue AndLHS = Op0.getOperand(0); + } else if (Op1.getOpcode() == ISD::Constant) { + ConstantSDNode *AndRHS = cast(Op1); + SDValue AndLHS = Op0; if (AndRHS->getZExtValue() == 1 && AndLHS.getOpcode() == ISD::SRL) { LHS = AndLHS.getOperand(0); RHS = AndLHS.getOperand(1); @@ -5959,6 +5962,21 @@ SDValue X86TargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { return NewSetCC; } + // Look for "(setcc) == / != 1" to avoid unncessary setcc. + if (Op0.getOpcode() == X86ISD::SETCC && + Op1.getOpcode() == ISD::Constant && + (cast(Op1)->getZExtValue() == 1 || + cast(Op1)->isNullValue()) && + (CC == ISD::SETEQ || CC == ISD::SETNE)) { + X86::CondCode CCode = (X86::CondCode)Op0.getConstantOperandVal(0); + bool Invert = (CC == ISD::SETNE) ^ + cast(Op1)->isNullValue(); + if (Invert) + CCode = X86::GetOppositeBranchCondition(CCode); + return DAG.getNode(X86ISD::SETCC, dl, MVT::i8, + DAG.getConstant(CCode, MVT::i8), Op0.getOperand(1)); + } + bool isFP = Op.getOperand(1).getValueType().isFloatingPoint(); unsigned X86CC = TranslateX86CC(CC, isFP, Op0, Op1, DAG); if (X86CC == X86::COND_INVALID) @@ -6400,24 +6418,13 @@ X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, EVT IntPtr = getPointerTy(); EVT SPTy = Subtarget->is64Bit() ? MVT::i64 : MVT::i32; - Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true)); - Chain = DAG.getCopyToReg(Chain, dl, X86::EAX, Size, Flag); Flag = Chain.getValue(1); - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); - SDValue Ops[] = { Chain, - DAG.getTargetExternalSymbol("_alloca", IntPtr), - DAG.getRegister(X86::EAX, IntPtr), - DAG.getRegister(X86StackPtr, SPTy), - Flag }; - Chain = DAG.getNode(X86ISD::CALL, dl, NodeTys, Ops, 5); - Flag = Chain.getValue(1); + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); - Chain = DAG.getCALLSEQ_END(Chain, - DAG.getIntPtrConstant(0, true), - DAG.getIntPtrConstant(0, true), - Flag); + Chain = DAG.getNode(X86ISD::MINGW_ALLOCA, dl, NodeTys, Chain, Flag); + Flag = Chain.getValue(1); Chain = DAG.getCopyFromReg(Chain, dl, X86StackPtr, SPTy).getValue(1); @@ -6461,8 +6468,7 @@ X86TargetLowering::EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, LowerCallTo(Chain, Type::getVoidTy(*DAG.getContext()), false, false, false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/false, - DAG.getExternalSymbol(bzeroEntry, IntPtr), Args, DAG, dl, - DAG.GetOrdering(Chain.getNode())); + DAG.getExternalSymbol(bzeroEntry, IntPtr), Args, DAG, dl); return CallResult.second; } @@ -6646,7 +6652,8 @@ SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) { // vastart just stores the address of the VarArgsFrameIndex slot into the // memory location argument. SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy()); - return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0); + return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0, + false, false, 0); } // __va_list_tag: @@ -6658,8 +6665,8 @@ SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) { SDValue FIN = Op.getOperand(1); // Store gp_offset SDValue Store = DAG.getStore(Op.getOperand(0), dl, - DAG.getConstant(VarArgsGPOffset, MVT::i32), - FIN, SV, 0); + DAG.getConstant(VarArgsGPOffset, MVT::i32), + FIN, SV, 0, false, false, 0); MemOps.push_back(Store); // Store fp_offset @@ -6667,21 +6674,23 @@ SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) { FIN, DAG.getIntPtrConstant(4)); Store = DAG.getStore(Op.getOperand(0), dl, DAG.getConstant(VarArgsFPOffset, MVT::i32), - FIN, SV, 0); + FIN, SV, 0, false, false, 0); MemOps.push_back(Store); // Store ptr to overflow_arg_area FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN, DAG.getIntPtrConstant(4)); SDValue OVFIN = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy()); - Store = DAG.getStore(Op.getOperand(0), dl, OVFIN, FIN, SV, 0); + Store = DAG.getStore(Op.getOperand(0), dl, OVFIN, FIN, SV, 0, + false, false, 0); MemOps.push_back(Store); // Store ptr to reg_save_area. FIN = DAG.getNode(ISD::ADD, dl, getPointerTy(), FIN, DAG.getIntPtrConstant(8)); SDValue RSFIN = DAG.getFrameIndex(RegSaveFrameIndex, getPointerTy()); - Store = DAG.getStore(Op.getOperand(0), dl, RSFIN, FIN, SV, 0); + Store = DAG.getStore(Op.getOperand(0), dl, RSFIN, FIN, SV, 0, + false, false, 0); MemOps.push_back(Store); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &MemOps[0], MemOps.size()); @@ -6967,13 +6976,13 @@ SDValue X86TargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), DAG.getNode(ISD::ADD, dl, getPointerTy(), FrameAddr, Offset), - NULL, 0); + NULL, 0, false, false, 0); } // Just load the return address. SDValue RetAddrFI = getReturnAddressFrameIndex(DAG); return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), - RetAddrFI, NULL, 0); + RetAddrFI, NULL, 0, false, false, 0); } SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { @@ -6985,7 +6994,8 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { unsigned FrameReg = Subtarget->is64Bit() ? X86::RBP : X86::EBP; SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT); while (Depth--) - FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0); + FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0, + false, false, 0); return FrameAddr; } @@ -7009,7 +7019,7 @@ SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) SDValue StoreAddr = DAG.getNode(ISD::SUB, dl, getPointerTy(), Frame, DAG.getIntPtrConstant(-TD->getPointerSize())); StoreAddr = DAG.getNode(ISD::ADD, dl, getPointerTy(), StoreAddr, Offset); - Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, NULL, 0); + Chain = DAG.getStore(Chain, dl, Handler, StoreAddr, NULL, 0, false, false, 0); Chain = DAG.getCopyToReg(Chain, dl, StoreAddrReg, StoreAddr); MF.getRegInfo().addLiveOut(StoreAddrReg); @@ -7044,11 +7054,12 @@ SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op, unsigned OpCode = ((MOV64ri | N86R11) << 8) | REX_WB; // movabsq r11 SDValue Addr = Trmp; OutChains[0] = DAG.getStore(Root, dl, DAG.getConstant(OpCode, MVT::i16), - Addr, TrmpAddr, 0); + Addr, TrmpAddr, 0, false, false, 0); Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, DAG.getConstant(2, MVT::i64)); - OutChains[1] = DAG.getStore(Root, dl, FPtr, Addr, TrmpAddr, 2, false, 2); + OutChains[1] = DAG.getStore(Root, dl, FPtr, Addr, TrmpAddr, 2, + false, false, 2); // Load the 'nest' parameter value into R10. // R10 is specified in X86CallingConv.td @@ -7056,24 +7067,25 @@ SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op, Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, DAG.getConstant(10, MVT::i64)); OutChains[2] = DAG.getStore(Root, dl, DAG.getConstant(OpCode, MVT::i16), - Addr, TrmpAddr, 10); + Addr, TrmpAddr, 10, false, false, 0); Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, DAG.getConstant(12, MVT::i64)); - OutChains[3] = DAG.getStore(Root, dl, Nest, Addr, TrmpAddr, 12, false, 2); + OutChains[3] = DAG.getStore(Root, dl, Nest, Addr, TrmpAddr, 12, + false, false, 2); // Jump to the nested function. OpCode = (JMP64r << 8) | REX_WB; // jmpq *... Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, DAG.getConstant(20, MVT::i64)); OutChains[4] = DAG.getStore(Root, dl, DAG.getConstant(OpCode, MVT::i16), - Addr, TrmpAddr, 20); + Addr, TrmpAddr, 20, false, false, 0); unsigned char ModRM = N86R11 | (4 << 3) | (3 << 6); // ...r11 Addr = DAG.getNode(ISD::ADD, dl, MVT::i64, Trmp, DAG.getConstant(22, MVT::i64)); OutChains[5] = DAG.getStore(Root, dl, DAG.getConstant(ModRM, MVT::i8), Addr, - TrmpAddr, 22); + TrmpAddr, 22, false, false, 0); SDValue Ops[] = { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 6) }; @@ -7133,21 +7145,23 @@ SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op, const unsigned char N86Reg = RegInfo->getX86RegNum(NestReg); OutChains[0] = DAG.getStore(Root, dl, DAG.getConstant(MOV32ri|N86Reg, MVT::i8), - Trmp, TrmpAddr, 0); + Trmp, TrmpAddr, 0, false, false, 0); Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, DAG.getConstant(1, MVT::i32)); - OutChains[1] = DAG.getStore(Root, dl, Nest, Addr, TrmpAddr, 1, false, 1); + OutChains[1] = DAG.getStore(Root, dl, Nest, Addr, TrmpAddr, 1, + false, false, 1); const unsigned char JMP = 0xE9; // jmp <32bit dst> opcode. Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, DAG.getConstant(5, MVT::i32)); OutChains[2] = DAG.getStore(Root, dl, DAG.getConstant(JMP, MVT::i8), Addr, - TrmpAddr, 5, false, 1); + TrmpAddr, 5, false, false, 1); Addr = DAG.getNode(ISD::ADD, dl, MVT::i32, Trmp, DAG.getConstant(6, MVT::i32)); - OutChains[3] = DAG.getStore(Root, dl, Disp, Addr, TrmpAddr, 6, false, 1); + OutChains[3] = DAG.getStore(Root, dl, Disp, Addr, TrmpAddr, 6, + false, false, 1); SDValue Ops[] = { Trmp, DAG.getNode(ISD::TokenFactor, dl, MVT::Other, OutChains, 4) }; @@ -7190,7 +7204,8 @@ SDValue X86TargetLowering::LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) { DAG.getEntryNode(), StackSlot); // Load FP Control Word from stack slot - SDValue CWD = DAG.getLoad(MVT::i16, dl, Chain, StackSlot, NULL, 0); + SDValue CWD = DAG.getLoad(MVT::i16, dl, Chain, StackSlot, NULL, 0, + false, false, 0); // Transform as necessary SDValue CWD1 = @@ -7554,7 +7569,8 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N, if (FIST.getNode() != 0) { EVT VT = N->getValueType(0); // Return a load from the stack slot. - Results.push_back(DAG.getLoad(VT, dl, FIST, StackSlot, NULL, 0)); + Results.push_back(DAG.getLoad(VT, dl, FIST, StackSlot, NULL, 0, + false, false, 0)); } return; } @@ -7572,14 +7588,6 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N, Results.push_back(edx.getValue(1)); return; } - case ISD::SDIV: - case ISD::UDIV: - case ISD::SREM: - case ISD::UREM: { - EVT WidenVT = getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); - Results.push_back(DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements())); - return; - } case ISD::ATOMIC_CMP_SWAP: { EVT T = N->getValueType(0); assert (T == MVT::i64 && "Only know how to expand i64 Cmp and Swap"); @@ -7677,6 +7685,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::INSERTPS: return "X86ISD::INSERTPS"; case X86ISD::PINSRB: return "X86ISD::PINSRB"; case X86ISD::PINSRW: return "X86ISD::PINSRW"; + case X86ISD::MMX_PINSRW: return "X86ISD::MMX_PINSRW"; case X86ISD::PSHUFB: return "X86ISD::PSHUFB"; case X86ISD::FMAX: return "X86ISD::FMAX"; case X86ISD::FMIN: return "X86ISD::FMIN"; @@ -7721,6 +7730,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::MUL_IMM: return "X86ISD::MUL_IMM"; case X86ISD::PTEST: return "X86ISD::PTEST"; case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS"; + case X86ISD::MINGW_ALLOCA: return "X86ISD::MINGW_ALLOCA"; } } @@ -7778,13 +7788,13 @@ bool X86TargetLowering::isLegalAddressingMode(const AddrMode &AM, bool X86TargetLowering::isTruncateFree(const Type *Ty1, const Type *Ty2) const { - if (!Ty1->isInteger() || !Ty2->isInteger()) + if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy()) return false; unsigned NumBits1 = Ty1->getPrimitiveSizeInBits(); unsigned NumBits2 = Ty2->getPrimitiveSizeInBits(); if (NumBits1 <= NumBits2) return false; - return Subtarget->is64Bit() || NumBits1 < 64; + return true; } bool X86TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { @@ -7794,12 +7804,12 @@ bool X86TargetLowering::isTruncateFree(EVT VT1, EVT VT2) const { unsigned NumBits2 = VT2.getSizeInBits(); if (NumBits1 <= NumBits2) return false; - return Subtarget->is64Bit() || NumBits1 < 64; + return true; } bool X86TargetLowering::isZExtFree(const Type *Ty1, const Type *Ty2) const { // x86-64 implicitly zero-extends 32-bit results in 64-bit registers. - return Ty1->isInteger(32) && Ty2->isInteger(64) && Subtarget->is64Bit(); + return Ty1->isIntegerTy(32) && Ty2->isIntegerTy(64) && Subtarget->is64Bit(); } bool X86TargetLowering::isZExtFree(EVT VT1, EVT VT2) const { @@ -7955,7 +7965,7 @@ X86TargetLowering::EmitAtomicBitwiseWithCustomInserter(MachineInstr *bInstr, MIB.addReg(EAXreg); // insert branch - BuildMI(newMBB, dl, TII->get(X86::JNE)).addMBB(newMBB); + BuildMI(newMBB, dl, TII->get(X86::JNE_4)).addMBB(newMBB); F->DeleteMachineInstr(bInstr); // The pseudo instruction is gone now. return nextMBB; @@ -8112,7 +8122,7 @@ X86TargetLowering::EmitAtomicBit6432WithCustomInserter(MachineInstr *bInstr, MIB.addReg(X86::EDX); // insert branch - BuildMI(newMBB, dl, TII->get(X86::JNE)).addMBB(newMBB); + BuildMI(newMBB, dl, TII->get(X86::JNE_4)).addMBB(newMBB); F->DeleteMachineInstr(bInstr); // The pseudo instruction is gone now. return nextMBB; @@ -8215,7 +8225,7 @@ X86TargetLowering::EmitAtomicMinMaxWithCustomInserter(MachineInstr *mInstr, MIB.addReg(X86::EAX); // insert branch - BuildMI(newMBB, dl, TII->get(X86::JNE)).addMBB(newMBB); + BuildMI(newMBB, dl, TII->get(X86::JNE_4)).addMBB(newMBB); F->DeleteMachineInstr(mInstr); // The pseudo instruction is gone now. return nextMBB; @@ -8297,7 +8307,7 @@ X86TargetLowering::EmitVAStartSaveXMMRegsWithCustomInserter( if (!Subtarget->isTargetWin64()) { // If %al is 0, branch around the XMM save block. BuildMI(MBB, DL, TII->get(X86::TEST8rr)).addReg(CountReg).addReg(CountReg); - BuildMI(MBB, DL, TII->get(X86::JE)).addMBB(EndMBB); + BuildMI(MBB, DL, TII->get(X86::JE_4)).addMBB(EndMBB); MBB->addSuccessor(EndMBB); } @@ -8390,6 +8400,29 @@ X86TargetLowering::EmitLoweredSelect(MachineInstr *MI, return BB; } +MachineBasicBlock * +X86TargetLowering::EmitLoweredMingwAlloca(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap *EM) const { + const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + MachineFunction *F = BB->getParent(); + + // The lowering is pretty easy: we're just emitting the call to _alloca. The + // non-trivial part is impdef of ESP. + // FIXME: The code should be tweaked as soon as we'll try to do codegen for + // mingw-w64. + + BuildMI(BB, DL, TII->get(X86::CALLpcrel32)) + .addExternalSymbol("_alloca") + .addReg(X86::EAX, RegState::Implicit) + .addReg(X86::ESP, RegState::Implicit) + .addReg(X86::EAX, RegState::Define | RegState::Implicit) + .addReg(X86::ESP, RegState::Define | RegState::Implicit); + + F->DeleteMachineInstr(MI); // The pseudo instruction is gone now. + return BB; +} MachineBasicBlock * X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, @@ -8397,6 +8430,8 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, DenseMap *EM) const { switch (MI->getOpcode()) { default: assert(false && "Unexpected instr type to insert"); + case X86::MINGW_ALLOCA: + return EmitLoweredMingwAlloca(MI, BB, EM); case X86::CMOV_GR8: case X86::CMOV_V1I64: case X86::CMOV_FR32: @@ -8783,10 +8818,11 @@ static SDValue PerformShuffleCombine(SDNode *N, SelectionDAG &DAG, if (DAG.InferPtrAlignment(LD->getBasePtr()) >= 16) return DAG.getLoad(VT, dl, LD->getChain(), LD->getBasePtr(), LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile()); + LD->isVolatile(), LD->isNonTemporal(), 0); return DAG.getLoad(VT, dl, LD->getChain(), LD->getBasePtr(), LD->getSrcValue(), LD->getSrcValueOffset(), - LD->isVolatile(), LD->getAlignment()); + LD->isVolatile(), LD->isNonTemporal(), + LD->getAlignment()); } else if (NumElems == 4 && LastLoadedElt == 1) { SDVTList Tys = DAG.getVTList(MVT::v2i64, MVT::Other); SDValue Ops[] = { LD->getChain(), LD->getBasePtr() }; @@ -8806,10 +8842,9 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, SDValue RHS = N->getOperand(2); // If we have SSE[12] support, try to form min/max nodes. SSE min/max - // instructions have the peculiarity that if either operand is a NaN, - // they chose what we call the RHS operand (and as such are not symmetric). - // It happens that this matches the semantics of the common C idiom - // xhasSSE2() && (LHS.getValueType() == MVT::f32 || LHS.getValueType() == MVT::f64) && Cond.getOpcode() == ISD::SETCC) { @@ -8817,36 +8852,34 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, unsigned Opcode = 0; // Check for x CC y ? x : y. - if (LHS == Cond.getOperand(0) && RHS == Cond.getOperand(1)) { + if (DAG.isEqualTo(LHS, Cond.getOperand(0)) && + DAG.isEqualTo(RHS, Cond.getOperand(1))) { switch (CC) { default: break; case ISD::SETULT: - // This can be a min if we can prove that at least one of the operands - // is not a nan. - if (!FiniteOnlyFPMath()) { - if (DAG.isKnownNeverNaN(RHS)) { - // Put the potential NaN in the RHS so that SSE will preserve it. - std::swap(LHS, RHS); - } else if (!DAG.isKnownNeverNaN(LHS)) + // Converting this to a min would handle NaNs incorrectly, and swapping + // the operands would cause it to handle comparisons between positive + // and negative zero incorrectly. + if (!FiniteOnlyFPMath() && + (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS))) { + if (!UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) break; + std::swap(LHS, RHS); } Opcode = X86ISD::FMIN; break; case ISD::SETOLE: - // This can be a min if we can prove that at least one of the operands - // is not a nan. - if (!FiniteOnlyFPMath()) { - if (DAG.isKnownNeverNaN(LHS)) { - // Put the potential NaN in the RHS so that SSE will preserve it. - std::swap(LHS, RHS); - } else if (!DAG.isKnownNeverNaN(RHS)) - break; - } + // Converting this to a min would handle comparisons between positive + // and negative zero incorrectly. + if (!UnsafeFPMath && + !DAG.isKnownNeverZero(LHS) && !DAG.isKnownNeverZero(RHS)) + break; Opcode = X86ISD::FMIN; break; case ISD::SETULE: - // This can be a min, but if either operand is a NaN we need it to - // preserve the original LHS. + // Converting this to a min would handle both negative zeros and NaNs + // incorrectly, but we can swap the operands to fix both. std::swap(LHS, RHS); case ISD::SETOLT: case ISD::SETLT: @@ -8855,32 +8888,29 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, break; case ISD::SETOGE: - // This can be a max if we can prove that at least one of the operands - // is not a nan. - if (!FiniteOnlyFPMath()) { - if (DAG.isKnownNeverNaN(LHS)) { - // Put the potential NaN in the RHS so that SSE will preserve it. - std::swap(LHS, RHS); - } else if (!DAG.isKnownNeverNaN(RHS)) - break; - } + // Converting this to a max would handle comparisons between positive + // and negative zero incorrectly. + if (!UnsafeFPMath && + !DAG.isKnownNeverZero(LHS) && !DAG.isKnownNeverZero(LHS)) + break; Opcode = X86ISD::FMAX; break; case ISD::SETUGT: - // This can be a max if we can prove that at least one of the operands - // is not a nan. - if (!FiniteOnlyFPMath()) { - if (DAG.isKnownNeverNaN(RHS)) { - // Put the potential NaN in the RHS so that SSE will preserve it. - std::swap(LHS, RHS); - } else if (!DAG.isKnownNeverNaN(LHS)) + // Converting this to a max would handle NaNs incorrectly, and swapping + // the operands would cause it to handle comparisons between positive + // and negative zero incorrectly. + if (!FiniteOnlyFPMath() && + (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS))) { + if (!UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) break; + std::swap(LHS, RHS); } Opcode = X86ISD::FMAX; break; case ISD::SETUGE: - // This can be a max, but if either operand is a NaN we need it to - // preserve the original LHS. + // Converting this to a max would handle both negative zeros and NaNs + // incorrectly, but we can swap the operands to fix both. std::swap(LHS, RHS); case ISD::SETOGT: case ISD::SETGT: @@ -8889,36 +8919,33 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, break; } // Check for x CC y ? y : x -- a min/max with reversed arms. - } else if (LHS == Cond.getOperand(1) && RHS == Cond.getOperand(0)) { + } else if (DAG.isEqualTo(LHS, Cond.getOperand(1)) && + DAG.isEqualTo(RHS, Cond.getOperand(0))) { switch (CC) { default: break; case ISD::SETOGE: - // This can be a min if we can prove that at least one of the operands - // is not a nan. - if (!FiniteOnlyFPMath()) { - if (DAG.isKnownNeverNaN(RHS)) { - // Put the potential NaN in the RHS so that SSE will preserve it. - std::swap(LHS, RHS); - } else if (!DAG.isKnownNeverNaN(LHS)) + // Converting this to a min would handle comparisons between positive + // and negative zero incorrectly, and swapping the operands would + // cause it to handle NaNs incorrectly. + if (!UnsafeFPMath && + !(DAG.isKnownNeverZero(LHS) || DAG.isKnownNeverZero(RHS))) { + if (!FiniteOnlyFPMath() && + (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS))) break; + std::swap(LHS, RHS); } Opcode = X86ISD::FMIN; break; case ISD::SETUGT: - // This can be a min if we can prove that at least one of the operands - // is not a nan. - if (!FiniteOnlyFPMath()) { - if (DAG.isKnownNeverNaN(LHS)) { - // Put the potential NaN in the RHS so that SSE will preserve it. - std::swap(LHS, RHS); - } else if (!DAG.isKnownNeverNaN(RHS)) - break; - } + // Converting this to a min would handle NaNs incorrectly. + if (!UnsafeFPMath && + (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS))) + break; Opcode = X86ISD::FMIN; break; case ISD::SETUGE: - // This can be a min, but if either operand is a NaN we need it to - // preserve the original LHS. + // Converting this to a min would handle both negative zeros and NaNs + // incorrectly, but we can swap the operands to fix both. std::swap(LHS, RHS); case ISD::SETOGT: case ISD::SETGT: @@ -8927,32 +8954,28 @@ static SDValue PerformSELECTCombine(SDNode *N, SelectionDAG &DAG, break; case ISD::SETULT: - // This can be a max if we can prove that at least one of the operands - // is not a nan. - if (!FiniteOnlyFPMath()) { - if (DAG.isKnownNeverNaN(LHS)) { - // Put the potential NaN in the RHS so that SSE will preserve it. - std::swap(LHS, RHS); - } else if (!DAG.isKnownNeverNaN(RHS)) - break; - } + // Converting this to a max would handle NaNs incorrectly. + if (!FiniteOnlyFPMath() && + (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS))) + break; Opcode = X86ISD::FMAX; break; case ISD::SETOLE: - // This can be a max if we can prove that at least one of the operands - // is not a nan. - if (!FiniteOnlyFPMath()) { - if (DAG.isKnownNeverNaN(RHS)) { - // Put the potential NaN in the RHS so that SSE will preserve it. - std::swap(LHS, RHS); - } else if (!DAG.isKnownNeverNaN(LHS)) + // Converting this to a max would handle comparisons between positive + // and negative zero incorrectly, and swapping the operands would + // cause it to handle NaNs incorrectly. + if (!UnsafeFPMath && + !DAG.isKnownNeverZero(LHS) && !DAG.isKnownNeverZero(RHS)) { + if (!FiniteOnlyFPMath() && + (!DAG.isKnownNeverNaN(LHS) || !DAG.isKnownNeverNaN(RHS))) break; + std::swap(LHS, RHS); } Opcode = X86ISD::FMAX; break; case ISD::SETULE: - // This can be a max, but if either operand is a NaN we need it to - // preserve the original LHS. + // Converting this to a max would handle both negative zeros and NaNs + // incorrectly, but we can swap the operands to fix both. std::swap(LHS, RHS); case ISD::SETOLT: case ISD::SETLT: @@ -9177,10 +9200,6 @@ static SDValue PerformCMOVCombine(SDNode *N, SelectionDAG &DAG, /// LEA + SHL, LEA + LEA. static SDValue PerformMulCombine(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI) { - if (DAG.getMachineFunction(). - getFunction()->hasFnAttr(Attribute::OptimizeForSize)) - return SDValue(); - if (DCI.isBeforeLegalize() || DCI.isCalledByLegalizer()) return SDValue(); @@ -9319,7 +9338,7 @@ static SDValue PerformShiftCombine(SDNode* N, SelectionDAG &DAG, } } else if (InVec.getOpcode() == ISD::INSERT_VECTOR_ELT) { if (ConstantSDNode *C = dyn_cast(InVec.getOperand(2))) { - unsigned SplatIdx = cast(ShAmtOp)->getSplatIndex(); + unsigned SplatIdx= cast(ShAmtOp)->getSplatIndex(); if (C->getZExtValue() == SplatIdx) BaseShAmt = InVec.getOperand(1); } @@ -9505,7 +9524,7 @@ static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG, SDValue NewLd = DAG.getLoad(LdVT, LdDL, Ld->getChain(), Ld->getBasePtr(), Ld->getSrcValue(), Ld->getSrcValueOffset(), Ld->isVolatile(), - Ld->getAlignment()); + Ld->isNonTemporal(), Ld->getAlignment()); SDValue NewChain = NewLd.getValue(1); if (TokenFactorIndex != -1) { Ops.push_back(NewChain); @@ -9514,7 +9533,8 @@ static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG, } return DAG.getStore(NewChain, StDL, NewLd, St->getBasePtr(), St->getSrcValue(), St->getSrcValueOffset(), - St->isVolatile(), St->getAlignment()); + St->isVolatile(), St->isNonTemporal(), + St->getAlignment()); } // Otherwise, lower to two pairs of 32-bit loads / stores. @@ -9524,10 +9544,11 @@ static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG, SDValue LoLd = DAG.getLoad(MVT::i32, LdDL, Ld->getChain(), LoAddr, Ld->getSrcValue(), Ld->getSrcValueOffset(), - Ld->isVolatile(), Ld->getAlignment()); + Ld->isVolatile(), Ld->isNonTemporal(), + Ld->getAlignment()); SDValue HiLd = DAG.getLoad(MVT::i32, LdDL, Ld->getChain(), HiAddr, Ld->getSrcValue(), Ld->getSrcValueOffset()+4, - Ld->isVolatile(), + Ld->isVolatile(), Ld->isNonTemporal(), MinAlign(Ld->getAlignment(), 4)); SDValue NewChain = LoLd.getValue(1); @@ -9544,11 +9565,13 @@ static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG, SDValue LoSt = DAG.getStore(NewChain, StDL, LoLd, LoAddr, St->getSrcValue(), St->getSrcValueOffset(), - St->isVolatile(), St->getAlignment()); + St->isVolatile(), St->isNonTemporal(), + St->getAlignment()); SDValue HiSt = DAG.getStore(NewChain, StDL, HiLd, HiAddr, St->getSrcValue(), St->getSrcValueOffset() + 4, St->isVolatile(), + St->isNonTemporal(), MinAlign(St->getAlignment(), 4)); return DAG.getNode(ISD::TokenFactor, StDL, MVT::Other, LoSt, HiSt); } @@ -9731,7 +9754,7 @@ static bool LowerToBSwap(CallInst *CI) { // Verify this is a simple bswap. if (CI->getNumOperands() != 2 || CI->getType() != CI->getOperand(1)->getType() || - !CI->getType()->isInteger()) + !CI->getType()->isIntegerTy()) return false; const IntegerType *Ty = dyn_cast(CI->getType()); @@ -9780,17 +9803,26 @@ bool X86TargetLowering::ExpandInlineAsm(CallInst *CI) const { return LowerToBSwap(CI); } // rorw $$8, ${0:w} --> llvm.bswap.i16 - if (CI->getType()->isInteger(16) && + if (CI->getType()->isIntegerTy(16) && AsmPieces.size() == 3 && - AsmPieces[0] == "rorw" && + (AsmPieces[0] == "rorw" || AsmPieces[0] == "rolw") && AsmPieces[1] == "$$8," && AsmPieces[2] == "${0:w}" && - IA->getConstraintString() == "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}") { - return LowerToBSwap(CI); + IA->getConstraintString().compare(0, 5, "=r,0,") == 0) { + AsmPieces.clear(); + SplitString(IA->getConstraintString().substr(5), AsmPieces, ","); + std::sort(AsmPieces.begin(), AsmPieces.end()); + if (AsmPieces.size() == 4 && + AsmPieces[0] == "~{cc}" && + AsmPieces[1] == "~{dirflag}" && + AsmPieces[2] == "~{flags}" && + AsmPieces[3] == "~{fpsr}") { + return LowerToBSwap(CI); + } } break; case 3: - if (CI->getType()->isInteger(64) && + if (CI->getType()->isIntegerTy(64) && Constraints.size() >= 2 && Constraints[0].Codes.size() == 1 && Constraints[0].Codes[0] == "A" && Constraints[1].Codes.size() == 1 && Constraints[1].Codes[0] == "0") { diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 193ef054c9..4c12fcc32f 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -180,7 +180,7 @@ namespace llvm { /// PINSRW - Insert the lower 16-bits of a 32-bit value to a vector, /// corresponds to X86::PINSRW. - PINSRW, + PINSRW, MMX_PINSRW, /// PSHUFB - Shuffle 16 8-bit values within a vector. PSHUFB, @@ -249,6 +249,9 @@ namespace llvm { // with control flow. VASTART_SAVE_XMM_REGS, + // MINGW_ALLOCA - MingW's __alloca call to do stack probing. + MINGW_ALLOCA, + // ATOMADD64_DAG, ATOMSUB64_DAG, ATOMOR64_DAG, ATOMAND64_DAG, // ATOMXOR64_DAG, ATOMNAND64_DAG, ATOMSWAP64_DAG - // Atomic 64-bit binary operations. @@ -259,6 +262,10 @@ namespace llvm { ATOMAND64_DAG, ATOMNAND64_DAG, ATOMSWAP64_DAG + + // WARNING: Do not add anything in the end unless you want the node to + // have memop! In fact, starting from ATOMADD64_DAG all opcodes will be + // thought as target memory ops! }; } @@ -639,7 +646,6 @@ namespace llvm { int FPDiff, DebugLoc dl); CCAssignFn *CCAssignFnForNode(CallingConv::ID CallConv) const; - NameDecorationStyle NameDecorationForCallConv(CallingConv::ID CallConv); unsigned GetAlignedArgumentStackSize(unsigned StackSize, SelectionDAG &DAG); std::pair FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG, @@ -790,7 +796,11 @@ namespace llvm { MachineBasicBlock *EmitLoweredSelect(MachineInstr *I, MachineBasicBlock *BB, DenseMap *EM) const; - + + MachineBasicBlock *EmitLoweredMingwAlloca(MachineInstr *MI, + MachineBasicBlock *BB, + DenseMap *EM) const; + /// Emit nodes that will be selected as "test Op0,Op0", or something /// equivalent, for use with the given x86 condition code. SDValue EmitTest(SDValue Op0, unsigned X86CC, SelectionDAG &DAG); diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 468dd67026..846225502d 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -59,10 +59,11 @@ def tls64addr : ComplexPatterngetZExtValue() == (int8_t)N->getZExtValue(); +def i64immSExt8 : PatLeaf<(i64 immSext8)>; + +def GetLo32XForm : SDNodeXFormgetZExtValue()); }]>; def i64immSExt32 : PatLeaf<(i64 imm), [{ @@ -71,6 +72,7 @@ def i64immSExt32 : PatLeaf<(i64 imm), [{ return (int64_t)N->getZExtValue() == (int32_t)N->getZExtValue(); }]>; + def i64immZExt32 : PatLeaf<(i64 imm), [{ // i64immZExt32 predicate - True if the 64-bit immediate fits in a 32-bit // unsignedsign extended field. @@ -325,7 +327,7 @@ def MOV64ri32 : RIi32<0xC7, MRM0r, (outs GR64:$dst), (ins i64i32imm:$src), def MOV64rr_REV : RI<0x8B, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), "mov{q}\t{$src, $dst|$dst, $src}", []>; -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def MOV64rm : RI<0x8B, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), "mov{q}\t{$src, $dst|$dst, $src}", [(set GR64:$dst, (load addr:$src))]>; @@ -556,7 +558,7 @@ def ADC64mi8 : RIi8<0x83, MRM2m, (outs), (ins i64mem:$dst, i64i8imm :$src2), addr:$dst)]>; def ADC64mi32 : RIi32<0x81, MRM2m, (outs), (ins i64mem:$dst, i64i32imm:$src2), "adc{q}\t{$src2, $dst|$dst, $src2}", - [(store (adde (load addr:$dst), i64immSExt8:$src2), + [(store (adde (load addr:$dst), i64immSExt32:$src2), addr:$dst)]>; } // Uses = [EFLAGS] @@ -893,35 +895,38 @@ def SAR64m1 : RI<0xD1, MRM7m, (outs), (ins i64mem:$dst), let isTwoAddress = 1 in { def RCL64r1 : RI<0xD1, MRM2r, (outs GR64:$dst), (ins GR64:$src), "rcl{q}\t{1, $dst|$dst, 1}", []>; -def RCL64m1 : RI<0xD1, MRM2m, (outs i64mem:$dst), (ins i64mem:$src), - "rcl{q}\t{1, $dst|$dst, 1}", []>; -let Uses = [CL] in { -def RCL64rCL : RI<0xD3, MRM2r, (outs GR64:$dst), (ins GR64:$src), - "rcl{q}\t{%cl, $dst|$dst, CL}", []>; -def RCL64mCL : RI<0xD3, MRM2m, (outs i64mem:$dst), (ins i64mem:$src), - "rcl{q}\t{%cl, $dst|$dst, CL}", []>; -} def RCL64ri : RIi8<0xC1, MRM2r, (outs GR64:$dst), (ins GR64:$src, i8imm:$cnt), "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCL64mi : RIi8<0xC1, MRM2m, (outs i64mem:$dst), - (ins i64mem:$src, i8imm:$cnt), - "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>; def RCR64r1 : RI<0xD1, MRM3r, (outs GR64:$dst), (ins GR64:$src), "rcr{q}\t{1, $dst|$dst, 1}", []>; -def RCR64m1 : RI<0xD1, MRM3m, (outs i64mem:$dst), (ins i64mem:$src), - "rcr{q}\t{1, $dst|$dst, 1}", []>; +def RCR64ri : RIi8<0xC1, MRM3r, (outs GR64:$dst), (ins GR64:$src, i8imm:$cnt), + "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>; + let Uses = [CL] in { +def RCL64rCL : RI<0xD3, MRM2r, (outs GR64:$dst), (ins GR64:$src), + "rcl{q}\t{%cl, $dst|$dst, CL}", []>; def RCR64rCL : RI<0xD3, MRM3r, (outs GR64:$dst), (ins GR64:$src), "rcr{q}\t{%cl, $dst|$dst, CL}", []>; -def RCR64mCL : RI<0xD3, MRM3m, (outs i64mem:$dst), (ins i64mem:$src), - "rcr{q}\t{%cl, $dst|$dst, CL}", []>; } -def RCR64ri : RIi8<0xC1, MRM3r, (outs GR64:$dst), (ins GR64:$src, i8imm:$cnt), - "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCR64mi : RIi8<0xC1, MRM3m, (outs i64mem:$dst), - (ins i64mem:$src, i8imm:$cnt), +} + +let isTwoAddress = 0 in { +def RCL64m1 : RI<0xD1, MRM2m, (outs), (ins i64mem:$dst), + "rcl{q}\t{1, $dst|$dst, 1}", []>; +def RCL64mi : RIi8<0xC1, MRM2m, (outs), (ins i64mem:$dst, i8imm:$cnt), + "rcl{q}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCR64m1 : RI<0xD1, MRM3m, (outs), (ins i64mem:$dst), + "rcr{q}\t{1, $dst|$dst, 1}", []>; +def RCR64mi : RIi8<0xC1, MRM3m, (outs), (ins i64mem:$dst, i8imm:$cnt), "rcr{q}\t{$cnt, $dst|$dst, $cnt}", []>; + +let Uses = [CL] in { +def RCL64mCL : RI<0xD3, MRM2m, (outs), (ins i64mem:$dst), + "rcl{q}\t{%cl, $dst|$dst, CL}", []>; +def RCR64mCL : RI<0xD3, MRM3m, (outs), (ins i64mem:$dst), + "rcr{q}\t{%cl, $dst|$dst, CL}", []>; +} } let isTwoAddress = 1 in { @@ -1771,7 +1776,7 @@ def LSL64rm : RI<0x03, MRMSrcMem, (outs GR64:$dst), (ins i64mem:$src), def LSL64rr : RI<0x03, MRMSrcReg, (outs GR64:$dst), (ins GR64:$src), "lsl{q}\t{$src, $dst|$dst, $src}", []>, TB; -def SWPGS : I<0x01, RawFrm, (outs), (ins), "swpgs", []>, TB; +def SWAPGS : I<0x01, MRM_F8, (outs), (ins), "swapgs", []>, TB; def PUSHFS64 : I<0xa0, RawFrm, (outs), (ins), "push{q}\t%fs", []>, TB; @@ -1978,7 +1983,7 @@ def : Pat<(and GR64:$src, i64immZExt32:$imm), (i64 0), (AND32ri (EXTRACT_SUBREG GR64:$src, x86_subreg_32bit), - imm:$imm), + (i32 (GetLo32XForm imm:$imm))), x86_subreg_32bit)>; // r & (2^32-1) ==> movz @@ -2102,34 +2107,34 @@ def : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst), def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>; // (shl x (and y, 63)) ==> (shl x, y) -def : Pat<(shl GR64:$src1, (and CL:$amt, 63)), +def : Pat<(shl GR64:$src1, (and CL, 63)), (SHL64rCL GR64:$src1)>; -def : Pat<(store (shl (loadi64 addr:$dst), (and CL:$amt, 63)), addr:$dst), +def : Pat<(store (shl (loadi64 addr:$dst), (and CL, 63)), addr:$dst), (SHL64mCL addr:$dst)>; -def : Pat<(srl GR64:$src1, (and CL:$amt, 63)), +def : Pat<(srl GR64:$src1, (and CL, 63)), (SHR64rCL GR64:$src1)>; -def : Pat<(store (srl (loadi64 addr:$dst), (and CL:$amt, 63)), addr:$dst), +def : Pat<(store (srl (loadi64 addr:$dst), (and CL, 63)), addr:$dst), (SHR64mCL addr:$dst)>; -def : Pat<(sra GR64:$src1, (and CL:$amt, 63)), +def : Pat<(sra GR64:$src1, (and CL, 63)), (SAR64rCL GR64:$src1)>; -def : Pat<(store (sra (loadi64 addr:$dst), (and CL:$amt, 63)), addr:$dst), +def : Pat<(store (sra (loadi64 addr:$dst), (and CL, 63)), addr:$dst), (SAR64mCL addr:$dst)>; // Double shift patterns -def : Pat<(shrd GR64:$src1, (i8 imm:$amt1), GR64:$src2, (i8 imm:$amt2)), +def : Pat<(shrd GR64:$src1, (i8 imm:$amt1), GR64:$src2, (i8 imm)), (SHRD64rri8 GR64:$src1, GR64:$src2, (i8 imm:$amt1))>; def : Pat<(store (shrd (loadi64 addr:$dst), (i8 imm:$amt1), - GR64:$src2, (i8 imm:$amt2)), addr:$dst), + GR64:$src2, (i8 imm)), addr:$dst), (SHRD64mri8 addr:$dst, GR64:$src2, (i8 imm:$amt1))>; -def : Pat<(shld GR64:$src1, (i8 imm:$amt1), GR64:$src2, (i8 imm:$amt2)), +def : Pat<(shld GR64:$src1, (i8 imm:$amt1), GR64:$src2, (i8 imm)), (SHLD64rri8 GR64:$src1, GR64:$src2, (i8 imm:$amt1))>; def : Pat<(store (shld (loadi64 addr:$dst), (i8 imm:$amt1), - GR64:$src2, (i8 imm:$amt2)), addr:$dst), + GR64:$src2, (i8 imm)), addr:$dst), (SHLD64mri8 addr:$dst, GR64:$src2, (i8 imm:$amt1))>; // (or x1, x2) -> (add x1, x2) if two operands are known not to share bits. diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td index e22a903739..ae24bfbb2d 100644 --- a/lib/Target/X86/X86InstrFPStack.td +++ b/lib/Target/X86/X86InstrFPStack.td @@ -397,7 +397,7 @@ def CMOVNP_F : FPI<0xD8, AddRegFrm, (outs RST:$op), (ins), let canFoldAsLoad = 1 in { def LD_Fp32m : FpIf32<(outs RFP32:$dst), (ins f32mem:$src), ZeroArgFP, [(set RFP32:$dst, (loadf32 addr:$src))]>; -let isReMaterializable = 1, mayHaveSideEffects = 1 in +let isReMaterializable = 1 in def LD_Fp64m : FpIf64<(outs RFP64:$dst), (ins f64mem:$src), ZeroArgFP, [(set RFP64:$dst, (loadf64 addr:$src))]>; def LD_Fp80m : FpI_<(outs RFP80:$dst), (ins f80mem:$src), ZeroArgFP, diff --git a/lib/Target/X86/X86InstrFormats.td b/lib/Target/X86/X86InstrFormats.td index a799f165f7..bb81cbf8ac 100644 --- a/lib/Target/X86/X86InstrFormats.td +++ b/lib/Target/X86/X86InstrFormats.td @@ -29,7 +29,16 @@ def MRM0m : Format<24>; def MRM1m : Format<25>; def MRM2m : Format<26>; def MRM3m : Format<27>; def MRM4m : Format<28>; def MRM5m : Format<29>; def MRM6m : Format<30>; def MRM7m : Format<31>; def MRMInitReg : Format<32>; - +def MRM_C1 : Format<33>; +def MRM_C2 : Format<34>; +def MRM_C3 : Format<35>; +def MRM_C4 : Format<36>; +def MRM_C8 : Format<37>; +def MRM_C9 : Format<38>; +def MRM_E8 : Format<39>; +def MRM_F0 : Format<40>; +def MRM_F8 : Format<41>; +def MRM_F9 : Format<42>; // ImmType - This specifies the immediate type used by an instruction. This is // part of the ad-hoc solution used to emit machine instruction encodings by our @@ -37,11 +46,13 @@ def MRMInitReg : Format<32>; class ImmType val> { bits<3> Value = val; } -def NoImm : ImmType<0>; -def Imm8 : ImmType<1>; -def Imm16 : ImmType<2>; -def Imm32 : ImmType<3>; -def Imm64 : ImmType<4>; +def NoImm : ImmType<0>; +def Imm8 : ImmType<1>; +def Imm8PCRel : ImmType<2>; +def Imm16 : ImmType<3>; +def Imm32 : ImmType<4>; +def Imm32PCRel : ImmType<5>; +def Imm64 : ImmType<6>; // FPFormat - This specifies what form this FP instruction has. This is used by // the Floating-Point stackifier pass. @@ -121,6 +132,12 @@ class Ii8 o, Format f, dag outs, dag ins, string asm, let Pattern = pattern; let CodeSize = 3; } +class Ii8PCRel o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} class Ii16 o, Format f, dag outs, dag ins, string asm, list pattern> : X86Inst { @@ -134,6 +151,13 @@ class Ii32 o, Format f, dag outs, dag ins, string asm, let CodeSize = 3; } +class Ii32PCRel o, Format f, dag outs, dag ins, string asm, + list pattern> + : X86Inst { + let Pattern = pattern; + let CodeSize = 3; +} + // FPStack Instruction Templates: // FPI - Floating Point Instruction template. class FPI o, Format F, dag outs, dag ins, string asm> diff --git a/lib/Target/X86/X86InstrInfo.cpp b/lib/Target/X86/X86InstrInfo.cpp index 8d13c0f48f..39bda04b4d 100644 --- a/lib/Target/X86/X86InstrInfo.cpp +++ b/lib/Target/X86/X86InstrInfo.cpp @@ -276,11 +276,8 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::MOVDQArr, X86::MOVDQAmr, 0, 16 }, { X86::MOVPDI2DIrr, X86::MOVPDI2DImr, 0, 0 }, { X86::MOVPQIto64rr,X86::MOVPQI2QImr, 0, 0 }, - { X86::MOVPS2SSrr, X86::MOVPS2SSmr, 0, 0 }, - { X86::MOVSDrr, X86::MOVSDmr, 0, 0 }, { X86::MOVSDto64rr, X86::MOVSDto64mr, 0, 0 }, { X86::MOVSS2DIrr, X86::MOVSS2DImr, 0, 0 }, - { X86::MOVSSrr, X86::MOVSSmr, 0, 0 }, { X86::MOVUPDrr, X86::MOVUPDmr, 0, 0 }, { X86::MOVUPSrr, X86::MOVUPSmr, 0, 0 }, { X86::MUL16r, X86::MUL16m, 1, 0 }, @@ -389,12 +386,8 @@ X86InstrInfo::X86InstrInfo(X86TargetMachine &tm) { X86::MOVDI2PDIrr, X86::MOVDI2PDIrm, 0 }, { X86::MOVDI2SSrr, X86::MOVDI2SSrm, 0 }, { X86::MOVDQArr, X86::MOVDQArm, 16 }, - { X86::MOVSD2PDrr, X86::MOVSD2PDrm, 0 }, - { X86::MOVSDrr, X86::MOVSDrm, 0 }, { X86::MOVSHDUPrr, X86::MOVSHDUPrm, 16 }, { X86::MOVSLDUPrr, X86::MOVSLDUPrm, 16 }, - { X86::MOVSS2PSrr, X86::MOVSS2PSrm, 0 }, - { X86::MOVSSrr, X86::MOVSSrm, 0 }, { X86::MOVSX16rr8, X86::MOVSX16rm8, 0 }, { X86::MOVSX32rr16, X86::MOVSX32rm16, 0 }, { X86::MOVSX32rr8, X86::MOVSX32rm8, 0 }, @@ -682,23 +675,20 @@ bool X86InstrInfo::isMoveInstr(const MachineInstr& MI, case X86::MOV16rr: case X86::MOV32rr: case X86::MOV64rr: - case X86::MOVSSrr: - case X86::MOVSDrr: // FP Stack register class copies case X86::MOV_Fp3232: case X86::MOV_Fp6464: case X86::MOV_Fp8080: case X86::MOV_Fp3264: case X86::MOV_Fp3280: case X86::MOV_Fp6432: case X86::MOV_Fp8032: - + + // Note that MOVSSrr and MOVSDrr are not considered copies. FR32 and FR64 + // copies are done with FsMOVAPSrr and FsMOVAPDrr. + case X86::FsMOVAPSrr: case X86::FsMOVAPDrr: case X86::MOVAPSrr: case X86::MOVAPDrr: case X86::MOVDQArr: - case X86::MOVSS2PSrr: - case X86::MOVSD2PDrr: - case X86::MOVPS2SSrr: - case X86::MOVPD2SDrr: case X86::MMX_MOVQ64rr: assert(MI.getNumOperands() >= 2 && MI.getOperand(0).isReg() && @@ -1083,7 +1073,7 @@ void X86InstrInfo::reMaterialize(MachineBasicBlock &MBB, case X86::MOV8r0: Opc = X86::MOV8ri; break; case X86::MOV16r0: Opc = X86::MOV16ri; break; case X86::MOV32r0: Opc = X86::MOV32ri; break; - case X86::MOV64r0: Opc = X86::MOV64ri; break; + case X86::MOV64r0: Opc = X86::MOV64ri64i32; break; } Clone = false; } @@ -1587,44 +1577,44 @@ X86InstrInfo::commuteInstruction(MachineInstr *MI, bool NewMI) const { static X86::CondCode GetCondFromBranchOpc(unsigned BrOpc) { switch (BrOpc) { default: return X86::COND_INVALID; - case X86::JE: return X86::COND_E; - case X86::JNE: return X86::COND_NE; - case X86::JL: return X86::COND_L; - case X86::JLE: return X86::COND_LE; - case X86::JG: return X86::COND_G; - case X86::JGE: return X86::COND_GE; - case X86::JB: return X86::COND_B; - case X86::JBE: return X86::COND_BE; - case X86::JA: return X86::COND_A; - case X86::JAE: return X86::COND_AE; - case X86::JS: return X86::COND_S; - case X86::JNS: return X86::COND_NS; - case X86::JP: return X86::COND_P; - case X86::JNP: return X86::COND_NP; - case X86::JO: return X86::COND_O; - case X86::JNO: return X86::COND_NO; + case X86::JE_4: return X86::COND_E; + case X86::JNE_4: return X86::COND_NE; + case X86::JL_4: return X86::COND_L; + case X86::JLE_4: return X86::COND_LE; + case X86::JG_4: return X86::COND_G; + case X86::JGE_4: return X86::COND_GE; + case X86::JB_4: return X86::COND_B; + case X86::JBE_4: return X86::COND_BE; + case X86::JA_4: return X86::COND_A; + case X86::JAE_4: return X86::COND_AE; + case X86::JS_4: return X86::COND_S; + case X86::JNS_4: return X86::COND_NS; + case X86::JP_4: return X86::COND_P; + case X86::JNP_4: return X86::COND_NP; + case X86::JO_4: return X86::COND_O; + case X86::JNO_4: return X86::COND_NO; } } unsigned X86::GetCondBranchFromCond(X86::CondCode CC) { switch (CC) { default: llvm_unreachable("Illegal condition code!"); - case X86::COND_E: return X86::JE; - case X86::COND_NE: return X86::JNE; - case X86::COND_L: return X86::JL; - case X86::COND_LE: return X86::JLE; - case X86::COND_G: return X86::JG; - case X86::COND_GE: return X86::JGE; - case X86::COND_B: return X86::JB; - case X86::COND_BE: return X86::JBE; - case X86::COND_A: return X86::JA; - case X86::COND_AE: return X86::JAE; - case X86::COND_S: return X86::JS; - case X86::COND_NS: return X86::JNS; - case X86::COND_P: return X86::JP; - case X86::COND_NP: return X86::JNP; - case X86::COND_O: return X86::JO; - case X86::COND_NO: return X86::JNO; + case X86::COND_E: return X86::JE_4; + case X86::COND_NE: return X86::JNE_4; + case X86::COND_L: return X86::JL_4; + case X86::COND_LE: return X86::JLE_4; + case X86::COND_G: return X86::JG_4; + case X86::COND_GE: return X86::JGE_4; + case X86::COND_B: return X86::JB_4; + case X86::COND_BE: return X86::JBE_4; + case X86::COND_A: return X86::JA_4; + case X86::COND_AE: return X86::JAE_4; + case X86::COND_S: return X86::JS_4; + case X86::COND_NS: return X86::JNS_4; + case X86::COND_P: return X86::JP_4; + case X86::COND_NP: return X86::JNP_4; + case X86::COND_O: return X86::JO_4; + case X86::COND_NO: return X86::JNO_4; } } @@ -1694,7 +1684,7 @@ bool X86InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, return true; // Handle unconditional branches. - if (I->getOpcode() == X86::JMP) { + if (I->getOpcode() == X86::JMP_4) { if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; @@ -1778,7 +1768,7 @@ unsigned X86InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { while (I != MBB.begin()) { --I; - if (I->getOpcode() != X86::JMP && + if (I->getOpcode() != X86::JMP_4 && GetCondFromBranchOpc(I->getOpcode()) == X86::COND_INVALID) break; // Remove the branch. @@ -1804,7 +1794,7 @@ X86InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, if (Cond.empty()) { // Unconditional branch? assert(!FBB && "Unconditional branch with multiple successors!"); - BuildMI(&MBB, dl, get(X86::JMP)).addMBB(TBB); + BuildMI(&MBB, dl, get(X86::JMP_4)).addMBB(TBB); return 1; } @@ -1814,16 +1804,16 @@ X86InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, switch (CC) { case X86::COND_NP_OR_E: // Synthesize NP_OR_E with two branches. - BuildMI(&MBB, dl, get(X86::JNP)).addMBB(TBB); + BuildMI(&MBB, dl, get(X86::JNP_4)).addMBB(TBB); ++Count; - BuildMI(&MBB, dl, get(X86::JE)).addMBB(TBB); + BuildMI(&MBB, dl, get(X86::JE_4)).addMBB(TBB); ++Count; break; case X86::COND_NE_OR_P: // Synthesize NE_OR_P with two branches. - BuildMI(&MBB, dl, get(X86::JNE)).addMBB(TBB); + BuildMI(&MBB, dl, get(X86::JNE_4)).addMBB(TBB); ++Count; - BuildMI(&MBB, dl, get(X86::JP)).addMBB(TBB); + BuildMI(&MBB, dl, get(X86::JP_4)).addMBB(TBB); ++Count; break; default: { @@ -1834,7 +1824,7 @@ X86InstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, } if (FBB) { // Two-way Conditional branch. Insert the second branch. - BuildMI(&MBB, dl, get(X86::JMP)).addMBB(FBB); + BuildMI(&MBB, dl, get(X86::JMP_4)).addMBB(FBB); ++Count; } return Count; @@ -1860,7 +1850,7 @@ bool X86InstrInfo::copyRegToReg(MachineBasicBlock &MBB, CommonRC = SrcRC; else if (!DestRC->hasSubClass(SrcRC)) { // Neither of GR64_NOREX or GR64_NOSP is a superclass of the other, - // but we want to copy then as GR64. Similarly, for GR32_NOREX and + // but we want to copy them as GR64. Similarly, for GR32_NOREX and // GR32_NOSP, copy as GR32. if (SrcRC->hasSuperClass(&X86::GR64RegClass) && DestRC->hasSuperClass(&X86::GR64RegClass)) @@ -3556,6 +3546,14 @@ static unsigned GetInstSizeWithDesc(const MachineInstr &MI, } } break; + + case X86II::MRM_C1: + case X86II::MRM_C8: + case X86II::MRM_C9: + case X86II::MRM_E8: + case X86II::MRM_F0: + FinalSize += 2; + break; } case X86II::MRMInitReg: diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index a6b38637f5..5111719a20 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -268,6 +268,18 @@ namespace X86II { // MRMInitReg - This form is used for instructions whose source and // destinations are the same register. MRMInitReg = 32, + + //// MRM_C1 - A mod/rm byte of exactly 0xC1. + MRM_C1 = 33, + MRM_C2 = 34, + MRM_C3 = 35, + MRM_C4 = 36, + MRM_C8 = 37, + MRM_C9 = 38, + MRM_E8 = 39, + MRM_F0 = 40, + MRM_F8 = 41, + MRM_F9 = 42, FormMask = 63, @@ -331,11 +343,13 @@ namespace X86II { // This three-bit field describes the size of an immediate operand. Zero is // unused so that we can tell if we forgot to set a value. ImmShift = 13, - ImmMask = 7 << ImmShift, - Imm8 = 1 << ImmShift, - Imm16 = 2 << ImmShift, - Imm32 = 3 << ImmShift, - Imm64 = 4 << ImmShift, + ImmMask = 7 << ImmShift, + Imm8 = 1 << ImmShift, + Imm8PCRel = 2 << ImmShift, + Imm16 = 3 << ImmShift, + Imm32 = 4 << ImmShift, + Imm32PCRel = 5 << ImmShift, + Imm64 = 6 << ImmShift, //===------------------------------------------------------------------===// // FP Instruction Classification... Zero is non-fp instruction. @@ -396,15 +410,37 @@ namespace X86II { return TSFlags >> X86II::OpcodeShift; } + static inline bool hasImm(unsigned TSFlags) { + return (TSFlags & X86II::ImmMask) != 0; + } + /// getSizeOfImm - Decode the "size of immediate" field from the TSFlags field /// of the specified instruction. static inline unsigned getSizeOfImm(unsigned TSFlags) { switch (TSFlags & X86II::ImmMask) { default: assert(0 && "Unknown immediate size"); - case X86II::Imm8: return 1; - case X86II::Imm16: return 2; - case X86II::Imm32: return 4; - case X86II::Imm64: return 8; + case X86II::Imm8: + case X86II::Imm8PCRel: return 1; + case X86II::Imm16: return 2; + case X86II::Imm32: + case X86II::Imm32PCRel: return 4; + case X86II::Imm64: return 8; + } + } + + /// isImmPCRel - Return true if the immediate of the specified instruction's + /// TSFlags indicates that it is pc relative. + static inline unsigned isImmPCRel(unsigned TSFlags) { + switch (TSFlags & X86II::ImmMask) { + default: assert(0 && "Unknown immediate size"); + case X86II::Imm8PCRel: + case X86II::Imm32PCRel: + return true; + case X86II::Imm8: + case X86II::Imm16: + case X86II::Imm32: + case X86II::Imm64: + return false; } } } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index f0b423923b..8a6ff54c77 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -65,7 +65,7 @@ def SDT_X86VASTART_SAVE_XMM_REGS : SDTypeProfile<0, -1, [SDTCisVT<0, i8>, def SDTX86RepStr : SDTypeProfile<0, 1, [SDTCisVT<0, OtherVT>]>; -def SDTX86RdTsc : SDTypeProfile<0, 0, []>; +def SDTX86Void : SDTypeProfile<0, 0, []>; def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; @@ -143,7 +143,7 @@ def X86rep_movs: SDNode<"X86ISD::REP_MOVS", SDTX86RepStr, [SDNPHasChain, SDNPInFlag, SDNPOutFlag, SDNPMayStore, SDNPMayLoad]>; -def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc, +def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG", SDTX86Void, [SDNPHasChain, SDNPOutFlag, SDNPSideEffect]>; def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>; @@ -178,6 +178,9 @@ def X86and_flag : SDNode<"X86ISD::AND", SDTBinaryArithWithFlags, def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; +def X86MingwAlloca : SDNode<"X86ISD::MINGW_ALLOCA", SDTX86Void, + [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; + //===----------------------------------------------------------------------===// // X86 Operand Definitions. // @@ -343,18 +346,37 @@ def X86_COND_O : PatLeaf<(i8 13)>; def X86_COND_P : PatLeaf<(i8 14)>; // alt. COND_PE def X86_COND_S : PatLeaf<(i8 15)>; -def i16immSExt8 : PatLeaf<(i16 imm), [{ - // i16immSExt8 predicate - True if the 16-bit immediate fits in a 8-bit - // sign extended field. - return (int16_t)N->getZExtValue() == (int8_t)N->getZExtValue(); +def immSext8 : PatLeaf<(imm), [{ + return N->getSExtValue() == (int8_t)N->getSExtValue(); }]>; -def i32immSExt8 : PatLeaf<(i32 imm), [{ - // i32immSExt8 predicate - True if the 32-bit immediate fits in a 8-bit - // sign extended field. - return (int32_t)N->getZExtValue() == (int8_t)N->getZExtValue(); +def i16immSExt8 : PatLeaf<(i16 immSext8)>; +def i32immSExt8 : PatLeaf<(i32 immSext8)>; + +/// Load patterns: these constraint the match to the right address space. +def dsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + if (PT->getAddressSpace() > 255) + return false; + return true; }]>; +def gsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + return PT->getAddressSpace() == 256; + return false; +}]>; + +def fsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ + if (const Value *Src = cast(N)->getSrcValue()) + if (const PointerType *PT = dyn_cast(Src->getType())) + return PT->getAddressSpace() == 257; + return false; +}]>; + + // Helper fragments for loads. // It's always safe to treat a anyext i16 load as a i32 load if the i16 is // known to be 32-bit aligned or better. Ditto for i8 to i16. @@ -372,8 +394,7 @@ def loadi16 : PatFrag<(ops node:$ptr), (i16 (unindexedload node:$ptr)), [{ return false; }]>; -def loadi16_anyext : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), -[{ +def loadi16_anyext : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)),[{ LoadSDNode *LD = cast(N); if (const Value *Src = LD->getSrcValue()) if (const PointerType *PT = dyn_cast(Src->getType())) @@ -399,72 +420,11 @@ def loadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ return false; }]>; -def nvloadi32 : PatFrag<(ops node:$ptr), (i32 (unindexedload node:$ptr)), [{ - LoadSDNode *LD = cast(N); - if (const Value *Src = LD->getSrcValue()) - if (const PointerType *PT = dyn_cast(Src->getType())) - if (PT->getAddressSpace() > 255) - return false; - if (LD->isVolatile()) - return false; - ISD::LoadExtType ExtType = LD->getExtensionType(); - if (ExtType == ISD::NON_EXTLOAD) - return true; - if (ExtType == ISD::EXTLOAD) - return LD->getAlignment() >= 4; - return false; -}]>; - -def gsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - if (const Value *Src = cast(N)->getSrcValue()) - if (const PointerType *PT = dyn_cast(Src->getType())) - return PT->getAddressSpace() == 256; - return false; -}]>; - -def fsload : PatFrag<(ops node:$ptr), (load node:$ptr), [{ - if (const Value *Src = cast(N)->getSrcValue()) - if (const PointerType *PT = dyn_cast(Src->getType())) - return PT->getAddressSpace() == 257; - return false; -}]>; - -def loadi8 : PatFrag<(ops node:$ptr), (i8 (load node:$ptr)), [{ - if (const Value *Src = cast(N)->getSrcValue()) - if (const PointerType *PT = dyn_cast(Src->getType())) - if (PT->getAddressSpace() > 255) - return false; - return true; -}]>; -def loadi64 : PatFrag<(ops node:$ptr), (i64 (load node:$ptr)), [{ - if (const Value *Src = cast(N)->getSrcValue()) - if (const PointerType *PT = dyn_cast(Src->getType())) - if (PT->getAddressSpace() > 255) - return false; - return true; -}]>; - -def loadf32 : PatFrag<(ops node:$ptr), (f32 (load node:$ptr)), [{ - if (const Value *Src = cast(N)->getSrcValue()) - if (const PointerType *PT = dyn_cast(Src->getType())) - if (PT->getAddressSpace() > 255) - return false; - return true; -}]>; -def loadf64 : PatFrag<(ops node:$ptr), (f64 (load node:$ptr)), [{ - if (const Value *Src = cast(N)->getSrcValue()) - if (const PointerType *PT = dyn_cast(Src->getType())) - if (PT->getAddressSpace() > 255) - return false; - return true; -}]>; -def loadf80 : PatFrag<(ops node:$ptr), (f80 (load node:$ptr)), [{ - if (const Value *Src = cast(N)->getSrcValue()) - if (const PointerType *PT = dyn_cast(Src->getType())) - if (PT->getAddressSpace() > 255) - return false; - return true; -}]>; +def loadi8 : PatFrag<(ops node:$ptr), (i8 (dsload node:$ptr))>; +def loadi64 : PatFrag<(ops node:$ptr), (i64 (dsload node:$ptr))>; +def loadf32 : PatFrag<(ops node:$ptr), (f32 (dsload node:$ptr))>; +def loadf64 : PatFrag<(ops node:$ptr), (f64 (dsload node:$ptr))>; +def loadf80 : PatFrag<(ops node:$ptr), (f80 (dsload node:$ptr))>; def sextloadi16i8 : PatFrag<(ops node:$ptr), (i16 (sextloadi8 node:$ptr))>; def sextloadi32i8 : PatFrag<(ops node:$ptr), (i32 (sextloadi8 node:$ptr))>; @@ -562,7 +522,7 @@ def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), } // x86-64 va_start lowering magic. -let usesCustomInserter = 1 in +let usesCustomInserter = 1 in { def VASTART_SAVE_XMM_REGS : I<0, Pseudo, (outs), (ins GR8:$al, @@ -573,6 +533,19 @@ def VASTART_SAVE_XMM_REGS : I<0, Pseudo, imm:$regsavefi, imm:$offset)]>; +// Dynamic stack allocation yields _alloca call for Cygwin/Mingw targets. Calls +// to _alloca is needed to probe the stack when allocating more than 4k bytes in +// one go. Touching the stack at 4K increments is necessary to ensure that the +// guard pages used by the OS virtual memory manager are allocated in correct +// sequence. +// The main point of having separate instruction are extra unmodelled effects +// (compared to ordinary calls) like stack pointer change. + +def MINGW_ALLOCA : I<0, Pseudo, (outs), (ins), + "# dynamic stack allocation", + [(X86MingwAlloca)]>; +} + // Nop let neverHasSideEffects = 1 in { def NOOP : I<0x90, RawFrm, (outs), (ins), "nop", []>; @@ -596,7 +569,7 @@ let neverHasSideEffects = 1, isNotDuplicable = 1, Uses = [ESP] in "", []>; //===----------------------------------------------------------------------===// -// Control Flow Instructions... +// Control Flow Instructions. // // Return instructions. @@ -614,16 +587,46 @@ let isTerminator = 1, isReturn = 1, isBarrier = 1, "lret\t$amt", []>; } -// All branches are RawFrm, Void, Branch, and Terminators -let isBranch = 1, isTerminator = 1 in - class IBr opcode, dag ins, string asm, list pattern> : - I; +// Unconditional branches. +let isBarrier = 1, isBranch = 1, isTerminator = 1 in { + def JMP_4 : Ii32PCRel<0xE9, RawFrm, (outs), (ins brtarget:$dst), + "jmp\t$dst", [(br bb:$dst)]>; + def JMP_1 : Ii8PCRel<0xEB, RawFrm, (outs), (ins brtarget8:$dst), + "jmp\t$dst", []>; +} -let isBranch = 1, isBarrier = 1 in { - def JMP : IBr<0xE9, (ins brtarget:$dst), "jmp\t$dst", [(br bb:$dst)]>; - def JMP8 : IBr<0xEB, (ins brtarget8:$dst), "jmp\t$dst", []>; +// Conditional Branches. +let isBranch = 1, isTerminator = 1, Uses = [EFLAGS] in { + multiclass ICBr opc1, bits<8> opc4, string asm, PatFrag Cond> { + def _1 : Ii8PCRel ; + def _4 : Ii32PCRel, TB; + } } +defm JO : ICBr<0x70, 0x80, "jo\t$dst" , X86_COND_O>; +defm JNO : ICBr<0x71, 0x81, "jno\t$dst" , X86_COND_NO>; +defm JB : ICBr<0x72, 0x82, "jb\t$dst" , X86_COND_B>; +defm JAE : ICBr<0x73, 0x83, "jae\t$dst", X86_COND_AE>; +defm JE : ICBr<0x74, 0x84, "je\t$dst" , X86_COND_E>; +defm JNE : ICBr<0x75, 0x85, "jne\t$dst", X86_COND_NE>; +defm JBE : ICBr<0x76, 0x86, "jbe\t$dst", X86_COND_BE>; +defm JA : ICBr<0x77, 0x87, "ja\t$dst" , X86_COND_A>; +defm JS : ICBr<0x78, 0x88, "js\t$dst" , X86_COND_S>; +defm JNS : ICBr<0x79, 0x89, "jns\t$dst", X86_COND_NS>; +defm JP : ICBr<0x7A, 0x8A, "jp\t$dst" , X86_COND_P>; +defm JNP : ICBr<0x7B, 0x8B, "jnp\t$dst", X86_COND_NP>; +defm JL : ICBr<0x7C, 0x8C, "jl\t$dst" , X86_COND_L>; +defm JGE : ICBr<0x7D, 0x8D, "jge\t$dst", X86_COND_GE>; +defm JLE : ICBr<0x7E, 0x8E, "jle\t$dst", X86_COND_LE>; +defm JG : ICBr<0x7F, 0x8F, "jg\t$dst" , X86_COND_G>; + +// FIXME: What about the CX/RCX versions of this instruction? +let Uses = [ECX], isBranch = 1, isTerminator = 1 in + def JCXZ8 : Ii8PCRel<0xE3, RawFrm, (outs), (ins brtarget8:$dst), + "jcxz\t$dst", []>; + + // Indirect branches let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { def JMP32r : I<0xFF, MRM4r, (outs), (ins GR32:$dst), "jmp{l}\t{*}$dst", @@ -644,63 +647,6 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { "ljmp{l}\t{*}$dst", []>; } -// Conditional branches -let Uses = [EFLAGS] in { -// Short conditional jumps -def JO8 : IBr<0x70, (ins brtarget8:$dst), "jo\t$dst", []>; -def JNO8 : IBr<0x71, (ins brtarget8:$dst), "jno\t$dst", []>; -def JB8 : IBr<0x72, (ins brtarget8:$dst), "jb\t$dst", []>; -def JAE8 : IBr<0x73, (ins brtarget8:$dst), "jae\t$dst", []>; -def JE8 : IBr<0x74, (ins brtarget8:$dst), "je\t$dst", []>; -def JNE8 : IBr<0x75, (ins brtarget8:$dst), "jne\t$dst", []>; -def JBE8 : IBr<0x76, (ins brtarget8:$dst), "jbe\t$dst", []>; -def JA8 : IBr<0x77, (ins brtarget8:$dst), "ja\t$dst", []>; -def JS8 : IBr<0x78, (ins brtarget8:$dst), "js\t$dst", []>; -def JNS8 : IBr<0x79, (ins brtarget8:$dst), "jns\t$dst", []>; -def JP8 : IBr<0x7A, (ins brtarget8:$dst), "jp\t$dst", []>; -def JNP8 : IBr<0x7B, (ins brtarget8:$dst), "jnp\t$dst", []>; -def JL8 : IBr<0x7C, (ins brtarget8:$dst), "jl\t$dst", []>; -def JGE8 : IBr<0x7D, (ins brtarget8:$dst), "jge\t$dst", []>; -def JLE8 : IBr<0x7E, (ins brtarget8:$dst), "jle\t$dst", []>; -def JG8 : IBr<0x7F, (ins brtarget8:$dst), "jg\t$dst", []>; - -def JCXZ8 : IBr<0xE3, (ins brtarget8:$dst), "jcxz\t$dst", []>; - -def JE : IBr<0x84, (ins brtarget:$dst), "je\t$dst", - [(X86brcond bb:$dst, X86_COND_E, EFLAGS)]>, TB; -def JNE : IBr<0x85, (ins brtarget:$dst), "jne\t$dst", - [(X86brcond bb:$dst, X86_COND_NE, EFLAGS)]>, TB; -def JL : IBr<0x8C, (ins brtarget:$dst), "jl\t$dst", - [(X86brcond bb:$dst, X86_COND_L, EFLAGS)]>, TB; -def JLE : IBr<0x8E, (ins brtarget:$dst), "jle\t$dst", - [(X86brcond bb:$dst, X86_COND_LE, EFLAGS)]>, TB; -def JG : IBr<0x8F, (ins brtarget:$dst), "jg\t$dst", - [(X86brcond bb:$dst, X86_COND_G, EFLAGS)]>, TB; -def JGE : IBr<0x8D, (ins brtarget:$dst), "jge\t$dst", - [(X86brcond bb:$dst, X86_COND_GE, EFLAGS)]>, TB; - -def JB : IBr<0x82, (ins brtarget:$dst), "jb\t$dst", - [(X86brcond bb:$dst, X86_COND_B, EFLAGS)]>, TB; -def JBE : IBr<0x86, (ins brtarget:$dst), "jbe\t$dst", - [(X86brcond bb:$dst, X86_COND_BE, EFLAGS)]>, TB; -def JA : IBr<0x87, (ins brtarget:$dst), "ja\t$dst", - [(X86brcond bb:$dst, X86_COND_A, EFLAGS)]>, TB; -def JAE : IBr<0x83, (ins brtarget:$dst), "jae\t$dst", - [(X86brcond bb:$dst, X86_COND_AE, EFLAGS)]>, TB; - -def JS : IBr<0x88, (ins brtarget:$dst), "js\t$dst", - [(X86brcond bb:$dst, X86_COND_S, EFLAGS)]>, TB; -def JNS : IBr<0x89, (ins brtarget:$dst), "jns\t$dst", - [(X86brcond bb:$dst, X86_COND_NS, EFLAGS)]>, TB; -def JP : IBr<0x8A, (ins brtarget:$dst), "jp\t$dst", - [(X86brcond bb:$dst, X86_COND_P, EFLAGS)]>, TB; -def JNP : IBr<0x8B, (ins brtarget:$dst), "jnp\t$dst", - [(X86brcond bb:$dst, X86_COND_NP, EFLAGS)]>, TB; -def JO : IBr<0x80, (ins brtarget:$dst), "jo\t$dst", - [(X86brcond bb:$dst, X86_COND_O, EFLAGS)]>, TB; -def JNO : IBr<0x81, (ins brtarget:$dst), "jno\t$dst", - [(X86brcond bb:$dst, X86_COND_NO, EFLAGS)]>, TB; -} // Uses = [EFLAGS] // Loop instructions @@ -721,7 +667,7 @@ let isCall = 1 in XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], Uses = [ESP] in { - def CALLpcrel32 : Ii32<0xE8, RawFrm, + def CALLpcrel32 : Ii32PCRel<0xE8, RawFrm, (outs), (ins i32imm_pcrel:$dst,variable_ops), "call\t$dst", []>; def CALL32r : I<0xFF, MRM2r, (outs), (ins GR32:$dst, variable_ops), @@ -761,8 +707,10 @@ def TCRETURNri : I<0, Pseudo, (outs), "#TC_RETURN $dst $offset", []>; -let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in - def TAILJMPd : IBr<0xE9, (ins i32imm_pcrel:$dst, variable_ops), +// FIXME: The should be pseudo instructions that are lowered when going to +// mcinst. +let isCall = 1, isBranch = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in + def TAILJMPd : Ii32<0xE9, RawFrm, (outs),(ins i32imm_pcrel:$dst,variable_ops), "jmp\t$dst # TAILCALL", []>; let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1 in @@ -929,6 +877,9 @@ let Defs = [RAX, RDX] in def RDTSC : I<0x31, RawFrm, (outs), (ins), "rdtsc", [(X86rdtsc)]>, TB; +let Defs = [RAX, RCX, RDX] in +def RDTSCP : I<0x01, MRM_F9, (outs), (ins), "rdtscp", []>, TB; + let isBarrier = 1, hasCtrlDep = 1 in { def TRAP : I<0x0B, RawFrm, (outs), (ins), "ud2", [(trap)]>, TB; } @@ -1059,7 +1010,7 @@ def MOV16rr_REV : I<0x8B, MRMSrcReg, (outs GR16:$dst), (ins GR16:$src), def MOV32rr_REV : I<0x8B, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), "mov{l}\t{$src, $dst|$dst, $src}", []>; -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in { +let canFoldAsLoad = 1, isReMaterializable = 1 in { def MOV8rm : I<0x8A, MRMSrcMem, (outs GR8 :$dst), (ins i8mem :$src), "mov{b}\t{$src, $dst|$dst, $src}", [(set GR8:$dst, (loadi8 addr:$src))]>; @@ -1093,7 +1044,7 @@ def MOV8mr_NOREX : I<0x88, MRMDestMem, (outs), (ins i8mem_NOREX:$dst, GR8_NOREX:$src), "mov{b}\t{$src, $dst|$dst, $src} # NOREX", []>; let mayLoad = 1, - canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in + canFoldAsLoad = 1, isReMaterializable = 1 in def MOV8rm_NOREX : I<0x8A, MRMSrcMem, (outs GR8_NOREX:$dst), (ins i8mem_NOREX:$src), "mov{b}\t{$src, $dst|$dst, $src} # NOREX", []>; @@ -1115,7 +1066,10 @@ def MOV32cr : I<0x22, MRMSrcReg, (outs CONTROL_REG_32:$dst), (ins GR32:$src), // // Extra precision multiplication -let Defs = [AL,AH,EFLAGS], Uses = [AL] in + +// AL is really implied by AX, by the registers in Defs must match the +// SDNode results (i8, i32). +let Defs = [AL,EFLAGS,AX], Uses = [AL] in def MUL8r : I<0xF6, MRM4r, (outs), (ins GR8:$src), "mul{b}\t$src", // FIXME: Used for 8-bit mul, ignore result upper 8 bits. // This probably ought to be moved to a def : Pat<> if the @@ -1133,7 +1087,7 @@ def MUL32r : I<0xF7, MRM4r, (outs), (ins GR32:$src), "mul{l}\t$src", []>; // EAX,EDX = EAX*GR32 -let Defs = [AL,AH,EFLAGS], Uses = [AL] in +let Defs = [AL,EFLAGS,AX], Uses = [AL] in def MUL8m : I<0xF6, MRM4m, (outs), (ins i8mem :$src), "mul{b}\t$src", // FIXME: Used for 8-bit mul, ignore result upper 8 bits. @@ -1155,7 +1109,7 @@ def MUL32m : I<0xF7, MRM4m, (outs), (ins i32mem:$src), } let neverHasSideEffects = 1 in { -let Defs = [AL,AH,EFLAGS], Uses = [AL] in +let Defs = [AL,EFLAGS,AX], Uses = [AL] in def IMUL8r : I<0xF6, MRM5r, (outs), (ins GR8:$src), "imul{b}\t$src", []>; // AL,AH = AL*GR8 let Defs = [AX,DX,EFLAGS], Uses = [AX] in @@ -1165,7 +1119,7 @@ let Defs = [EAX,EDX,EFLAGS], Uses = [EAX] in def IMUL32r : I<0xF7, MRM5r, (outs), (ins GR32:$src), "imul{l}\t$src", []>; // EAX,EDX = EAX*GR32 let mayLoad = 1 in { -let Defs = [AL,AH,EFLAGS], Uses = [AL] in +let Defs = [AL,EFLAGS,AX], Uses = [AL] in def IMUL8m : I<0xF6, MRM5m, (outs), (ins i8mem :$src), "imul{b}\t$src", []>; // AL,AH = AL*[mem8] let Defs = [AX,DX,EFLAGS], Uses = [AX] in @@ -1178,7 +1132,7 @@ def IMUL32m : I<0xF7, MRM5m, (outs), (ins i32mem:$src), } // neverHasSideEffects // unsigned division/remainder -let Defs = [AL,AH,EFLAGS], Uses = [AX] in +let Defs = [AL,EFLAGS,AX], Uses = [AX] in def DIV8r : I<0xF6, MRM6r, (outs), (ins GR8:$src), // AX/r8 = AL,AH "div{b}\t$src", []>; let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in @@ -1188,7 +1142,7 @@ let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in def DIV32r : I<0xF7, MRM6r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX "div{l}\t$src", []>; let mayLoad = 1 in { -let Defs = [AL,AH,EFLAGS], Uses = [AX] in +let Defs = [AL,EFLAGS,AX], Uses = [AX] in def DIV8m : I<0xF6, MRM6m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH "div{b}\t$src", []>; let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in @@ -1201,7 +1155,7 @@ def DIV32m : I<0xF7, MRM6m, (outs), (ins i32mem:$src), } // Signed division/remainder. -let Defs = [AL,AH,EFLAGS], Uses = [AX] in +let Defs = [AL,EFLAGS,AX], Uses = [AX] in def IDIV8r : I<0xF6, MRM7r, (outs), (ins GR8:$src), // AX/r8 = AL,AH "idiv{b}\t$src", []>; let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in @@ -1211,7 +1165,7 @@ let Defs = [EAX,EDX,EFLAGS], Uses = [EAX,EDX] in def IDIV32r: I<0xF7, MRM7r, (outs), (ins GR32:$src), // EDX:EAX/r32 = EAX,EDX "idiv{l}\t$src", []>; let mayLoad = 1, mayLoad = 1 in { -let Defs = [AL,AH,EFLAGS], Uses = [AX] in +let Defs = [AL,EFLAGS,AX], Uses = [AX] in def IDIV8m : I<0xF6, MRM7m, (outs), (ins i8mem:$src), // AX/[mem8] = AL,AH "idiv{b}\t$src", []>; let Defs = [AX,DX,EFLAGS], Uses = [AX,DX] in @@ -2328,98 +2282,100 @@ let isTwoAddress = 0 in { def RCL8r1 : I<0xD0, MRM2r, (outs GR8:$dst), (ins GR8:$src), "rcl{b}\t{1, $dst|$dst, 1}", []>; -def RCL8m1 : I<0xD0, MRM2m, (outs i8mem:$dst), (ins i8mem:$src), - "rcl{b}\t{1, $dst|$dst, 1}", []>; let Uses = [CL] in { def RCL8rCL : I<0xD2, MRM2r, (outs GR8:$dst), (ins GR8:$src), "rcl{b}\t{%cl, $dst|$dst, CL}", []>; -def RCL8mCL : I<0xD2, MRM2m, (outs i8mem:$dst), (ins i8mem:$src), - "rcl{b}\t{%cl, $dst|$dst, CL}", []>; } def RCL8ri : Ii8<0xC0, MRM2r, (outs GR8:$dst), (ins GR8:$src, i8imm:$cnt), "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCL8mi : Ii8<0xC0, MRM2m, (outs i8mem:$dst), (ins i8mem:$src, i8imm:$cnt), - "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; def RCL16r1 : I<0xD1, MRM2r, (outs GR16:$dst), (ins GR16:$src), "rcl{w}\t{1, $dst|$dst, 1}", []>, OpSize; -def RCL16m1 : I<0xD1, MRM2m, (outs i16mem:$dst), (ins i16mem:$src), - "rcl{w}\t{1, $dst|$dst, 1}", []>, OpSize; let Uses = [CL] in { def RCL16rCL : I<0xD3, MRM2r, (outs GR16:$dst), (ins GR16:$src), "rcl{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; -def RCL16mCL : I<0xD3, MRM2m, (outs i16mem:$dst), (ins i16mem:$src), - "rcl{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; } def RCL16ri : Ii8<0xC1, MRM2r, (outs GR16:$dst), (ins GR16:$src, i8imm:$cnt), "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; -def RCL16mi : Ii8<0xC1, MRM2m, (outs i16mem:$dst), - (ins i16mem:$src, i8imm:$cnt), - "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; def RCL32r1 : I<0xD1, MRM2r, (outs GR32:$dst), (ins GR32:$src), "rcl{l}\t{1, $dst|$dst, 1}", []>; -def RCL32m1 : I<0xD1, MRM2m, (outs i32mem:$dst), (ins i32mem:$src), - "rcl{l}\t{1, $dst|$dst, 1}", []>; let Uses = [CL] in { def RCL32rCL : I<0xD3, MRM2r, (outs GR32:$dst), (ins GR32:$src), "rcl{l}\t{%cl, $dst|$dst, CL}", []>; -def RCL32mCL : I<0xD3, MRM2m, (outs i32mem:$dst), (ins i32mem:$src), - "rcl{l}\t{%cl, $dst|$dst, CL}", []>; } def RCL32ri : Ii8<0xC1, MRM2r, (outs GR32:$dst), (ins GR32:$src, i8imm:$cnt), "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCL32mi : Ii8<0xC1, MRM2m, (outs i32mem:$dst), - (ins i32mem:$src, i8imm:$cnt), - "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>; def RCR8r1 : I<0xD0, MRM3r, (outs GR8:$dst), (ins GR8:$src), "rcr{b}\t{1, $dst|$dst, 1}", []>; -def RCR8m1 : I<0xD0, MRM3m, (outs i8mem:$dst), (ins i8mem:$src), - "rcr{b}\t{1, $dst|$dst, 1}", []>; let Uses = [CL] in { def RCR8rCL : I<0xD2, MRM3r, (outs GR8:$dst), (ins GR8:$src), "rcr{b}\t{%cl, $dst|$dst, CL}", []>; -def RCR8mCL : I<0xD2, MRM3m, (outs i8mem:$dst), (ins i8mem:$src), - "rcr{b}\t{%cl, $dst|$dst, CL}", []>; } def RCR8ri : Ii8<0xC0, MRM3r, (outs GR8:$dst), (ins GR8:$src, i8imm:$cnt), "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCR8mi : Ii8<0xC0, MRM3m, (outs i8mem:$dst), (ins i8mem:$src, i8imm:$cnt), - "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; def RCR16r1 : I<0xD1, MRM3r, (outs GR16:$dst), (ins GR16:$src), "rcr{w}\t{1, $dst|$dst, 1}", []>, OpSize; -def RCR16m1 : I<0xD1, MRM3m, (outs i16mem:$dst), (ins i16mem:$src), - "rcr{w}\t{1, $dst|$dst, 1}", []>, OpSize; let Uses = [CL] in { def RCR16rCL : I<0xD3, MRM3r, (outs GR16:$dst), (ins GR16:$src), "rcr{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; -def RCR16mCL : I<0xD3, MRM3m, (outs i16mem:$dst), (ins i16mem:$src), - "rcr{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; } def RCR16ri : Ii8<0xC1, MRM3r, (outs GR16:$dst), (ins GR16:$src, i8imm:$cnt), "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; -def RCR16mi : Ii8<0xC1, MRM3m, (outs i16mem:$dst), - (ins i16mem:$src, i8imm:$cnt), - "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; def RCR32r1 : I<0xD1, MRM3r, (outs GR32:$dst), (ins GR32:$src), "rcr{l}\t{1, $dst|$dst, 1}", []>; -def RCR32m1 : I<0xD1, MRM3m, (outs i32mem:$dst), (ins i32mem:$src), - "rcr{l}\t{1, $dst|$dst, 1}", []>; let Uses = [CL] in { def RCR32rCL : I<0xD3, MRM3r, (outs GR32:$dst), (ins GR32:$src), "rcr{l}\t{%cl, $dst|$dst, CL}", []>; -def RCR32mCL : I<0xD3, MRM3m, (outs i32mem:$dst), (ins i32mem:$src), - "rcr{l}\t{%cl, $dst|$dst, CL}", []>; } def RCR32ri : Ii8<0xC1, MRM3r, (outs GR32:$dst), (ins GR32:$src, i8imm:$cnt), "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>; -def RCR32mi : Ii8<0xC1, MRM3m, (outs i32mem:$dst), - (ins i32mem:$src, i8imm:$cnt), + +let isTwoAddress = 0 in { +def RCL8m1 : I<0xD0, MRM2m, (outs), (ins i8mem:$dst), + "rcl{b}\t{1, $dst|$dst, 1}", []>; +def RCL8mi : Ii8<0xC0, MRM2m, (outs), (ins i8mem:$dst, i8imm:$cnt), + "rcl{b}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCL16m1 : I<0xD1, MRM2m, (outs), (ins i16mem:$dst), + "rcl{w}\t{1, $dst|$dst, 1}", []>, OpSize; +def RCL16mi : Ii8<0xC1, MRM2m, (outs), (ins i16mem:$dst, i8imm:$cnt), + "rcl{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; +def RCL32m1 : I<0xD1, MRM2m, (outs), (ins i32mem:$dst), + "rcl{l}\t{1, $dst|$dst, 1}", []>; +def RCL32mi : Ii8<0xC1, MRM2m, (outs), (ins i32mem:$dst, i8imm:$cnt), + "rcl{l}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCR8m1 : I<0xD0, MRM3m, (outs), (ins i8mem:$dst), + "rcr{b}\t{1, $dst|$dst, 1}", []>; +def RCR8mi : Ii8<0xC0, MRM3m, (outs), (ins i8mem:$dst, i8imm:$cnt), + "rcr{b}\t{$cnt, $dst|$dst, $cnt}", []>; +def RCR16m1 : I<0xD1, MRM3m, (outs), (ins i16mem:$dst), + "rcr{w}\t{1, $dst|$dst, 1}", []>, OpSize; +def RCR16mi : Ii8<0xC1, MRM3m, (outs), (ins i16mem:$dst, i8imm:$cnt), + "rcr{w}\t{$cnt, $dst|$dst, $cnt}", []>, OpSize; +def RCR32m1 : I<0xD1, MRM3m, (outs), (ins i32mem:$dst), + "rcr{l}\t{1, $dst|$dst, 1}", []>; +def RCR32mi : Ii8<0xC1, MRM3m, (outs), (ins i32mem:$dst, i8imm:$cnt), "rcr{l}\t{$cnt, $dst|$dst, $cnt}", []>; +let Uses = [CL] in { +def RCL8mCL : I<0xD2, MRM2m, (outs), (ins i8mem:$dst), + "rcl{b}\t{%cl, $dst|$dst, CL}", []>; +def RCL16mCL : I<0xD3, MRM2m, (outs), (ins i16mem:$dst), + "rcl{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; +def RCL32mCL : I<0xD3, MRM2m, (outs), (ins i32mem:$dst), + "rcl{l}\t{%cl, $dst|$dst, CL}", []>; +def RCR8mCL : I<0xD2, MRM3m, (outs), (ins i8mem:$dst), + "rcr{b}\t{%cl, $dst|$dst, CL}", []>; +def RCR16mCL : I<0xD3, MRM3m, (outs), (ins i16mem:$dst), + "rcr{w}\t{%cl, $dst|$dst, CL}", []>, OpSize; +def RCR32mCL : I<0xD3, MRM3m, (outs), (ins i32mem:$dst), + "rcr{l}\t{%cl, $dst|$dst, CL}", []>; +} +} + // FIXME: provide shorter instructions when imm8 == 1 let Uses = [CL] in { def ROL8rCL : I<0xD2, MRM0r, (outs GR8 :$dst), (ins GR8 :$src), @@ -4100,7 +4056,7 @@ def LSL32rm : I<0x03, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), def LSL32rr : I<0x03, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), "lsl{l}\t{$src, $dst|$dst, $src}", []>, TB; -def INVLPG : I<0x01, RawFrm, (outs), (ins), "invlpg", []>, TB; +def INVLPG : I<0x01, MRM7m, (outs), (ins i8mem:$addr), "invlpg\t$addr", []>, TB; def STRr : I<0x00, MRM1r, (outs GR16:$dst), (ins), "str{w}\t{$dst}", []>, TB; @@ -4262,17 +4218,17 @@ def WBINVD : I<0x09, RawFrm, (outs), (ins), "wbinvd", []>, TB; // VMX instructions // 66 0F 38 80 -def INVEPT : I<0x38, RawFrm, (outs), (ins), "invept", []>, OpSize, TB; +def INVEPT : I<0x80, RawFrm, (outs), (ins), "invept", []>, OpSize, T8; // 66 0F 38 81 -def INVVPID : I<0x38, RawFrm, (outs), (ins), "invvpid", []>, OpSize, TB; +def INVVPID : I<0x81, RawFrm, (outs), (ins), "invvpid", []>, OpSize, T8; // 0F 01 C1 -def VMCALL : I<0x01, RawFrm, (outs), (ins), "vmcall", []>, TB; +def VMCALL : I<0x01, MRM_C1, (outs), (ins), "vmcall", []>, TB; def VMCLEARm : I<0xC7, MRM6m, (outs), (ins i64mem:$vmcs), "vmclear\t$vmcs", []>, OpSize, TB; // 0F 01 C2 -def VMLAUNCH : I<0x01, RawFrm, (outs), (ins), "vmlaunch", []>, TB; +def VMLAUNCH : I<0x01, MRM_C2, (outs), (ins), "vmlaunch", []>, TB; // 0F 01 C3 -def VMRESUME : I<0x01, RawFrm, (outs), (ins), "vmresume", []>, TB; +def VMRESUME : I<0x01, MRM_C3, (outs), (ins), "vmresume", []>, TB; def VMPTRLDm : I<0xC7, MRM6m, (outs), (ins i64mem:$vmcs), "vmptrld\t$vmcs", []>, TB; def VMPTRSTm : I<0xC7, MRM7m, (outs i64mem:$vmcs), (ins), @@ -4294,7 +4250,7 @@ def VMWRITE32rm : I<0x79, MRMSrcMem, (outs GR32:$dst), (ins i32mem:$src), def VMWRITE32rr : I<0x79, MRMSrcReg, (outs GR32:$dst), (ins GR32:$src), "vmwrite{l}\t{$src, $dst|$dst, $src}", []>, TB; // 0F 01 C4 -def VMXOFF : I<0x01, RawFrm, (outs), (ins), "vmxoff", []>, OpSize; +def VMXOFF : I<0x01, MRM_C4, (outs), (ins), "vmxoff", []>, TB; def VMXON : I<0xC7, MRM6m, (outs), (ins i64mem:$vmxon), "vmxon\t{$vmxon}", []>, XD; @@ -4462,12 +4418,6 @@ def : Pat<(i16 (anyext GR8 :$src)), (MOVZX16rr8 GR8 :$src)>; def : Pat<(i32 (anyext GR8 :$src)), (MOVZX32rr8 GR8 :$src)>; def : Pat<(i32 (anyext GR16:$src)), (MOVZX32rr16 GR16:$src)>; -// (and (i32 load), 255) -> (zextload i8) -def : Pat<(i32 (and (nvloadi32 addr:$src), (i32 255))), - (MOVZX32rm8 addr:$src)>; -def : Pat<(i32 (and (nvloadi32 addr:$src), (i32 65535))), - (MOVZX32rm16 addr:$src)>; - //===----------------------------------------------------------------------===// // Some peepholes //===----------------------------------------------------------------------===// @@ -4563,43 +4513,43 @@ def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>; def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>; // (shl x (and y, 31)) ==> (shl x, y) -def : Pat<(shl GR8:$src1, (and CL:$amt, 31)), +def : Pat<(shl GR8:$src1, (and CL, 31)), (SHL8rCL GR8:$src1)>; -def : Pat<(shl GR16:$src1, (and CL:$amt, 31)), +def : Pat<(shl GR16:$src1, (and CL, 31)), (SHL16rCL GR16:$src1)>; -def : Pat<(shl GR32:$src1, (and CL:$amt, 31)), +def : Pat<(shl GR32:$src1, (and CL, 31)), (SHL32rCL GR32:$src1)>; -def : Pat<(store (shl (loadi8 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (shl (loadi8 addr:$dst), (and CL, 31)), addr:$dst), (SHL8mCL addr:$dst)>; -def : Pat<(store (shl (loadi16 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (shl (loadi16 addr:$dst), (and CL, 31)), addr:$dst), (SHL16mCL addr:$dst)>; -def : Pat<(store (shl (loadi32 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (shl (loadi32 addr:$dst), (and CL, 31)), addr:$dst), (SHL32mCL addr:$dst)>; -def : Pat<(srl GR8:$src1, (and CL:$amt, 31)), +def : Pat<(srl GR8:$src1, (and CL, 31)), (SHR8rCL GR8:$src1)>; -def : Pat<(srl GR16:$src1, (and CL:$amt, 31)), +def : Pat<(srl GR16:$src1, (and CL, 31)), (SHR16rCL GR16:$src1)>; -def : Pat<(srl GR32:$src1, (and CL:$amt, 31)), +def : Pat<(srl GR32:$src1, (and CL, 31)), (SHR32rCL GR32:$src1)>; -def : Pat<(store (srl (loadi8 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (srl (loadi8 addr:$dst), (and CL, 31)), addr:$dst), (SHR8mCL addr:$dst)>; -def : Pat<(store (srl (loadi16 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (srl (loadi16 addr:$dst), (and CL, 31)), addr:$dst), (SHR16mCL addr:$dst)>; -def : Pat<(store (srl (loadi32 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (srl (loadi32 addr:$dst), (and CL, 31)), addr:$dst), (SHR32mCL addr:$dst)>; -def : Pat<(sra GR8:$src1, (and CL:$amt, 31)), +def : Pat<(sra GR8:$src1, (and CL, 31)), (SAR8rCL GR8:$src1)>; -def : Pat<(sra GR16:$src1, (and CL:$amt, 31)), +def : Pat<(sra GR16:$src1, (and CL, 31)), (SAR16rCL GR16:$src1)>; -def : Pat<(sra GR32:$src1, (and CL:$amt, 31)), +def : Pat<(sra GR32:$src1, (and CL, 31)), (SAR32rCL GR32:$src1)>; -def : Pat<(store (sra (loadi8 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (sra (loadi8 addr:$dst), (and CL, 31)), addr:$dst), (SAR8mCL addr:$dst)>; -def : Pat<(store (sra (loadi16 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (sra (loadi16 addr:$dst), (and CL, 31)), addr:$dst), (SAR16mCL addr:$dst)>; -def : Pat<(store (sra (loadi32 addr:$dst), (and CL:$amt, 31)), addr:$dst), +def : Pat<(store (sra (loadi32 addr:$dst), (and CL, 31)), addr:$dst), (SAR32mCL addr:$dst)>; // (or (x >> c) | (y << (32 - c))) ==> (shrd32 x, y, c) @@ -4620,11 +4570,11 @@ def : Pat<(store (or (srl (loadi32 addr:$dst), (i8 (trunc ECX:$amt))), addr:$dst), (SHRD32mrCL addr:$dst, GR32:$src2)>; -def : Pat<(shrd GR32:$src1, (i8 imm:$amt1), GR32:$src2, (i8 imm:$amt2)), +def : Pat<(shrd GR32:$src1, (i8 imm:$amt1), GR32:$src2, (i8 imm/*:$amt2*/)), (SHRD32rri8 GR32:$src1, GR32:$src2, (i8 imm:$amt1))>; def : Pat<(store (shrd (loadi32 addr:$dst), (i8 imm:$amt1), - GR32:$src2, (i8 imm:$amt2)), addr:$dst), + GR32:$src2, (i8 imm/*:$amt2*/)), addr:$dst), (SHRD32mri8 addr:$dst, GR32:$src2, (i8 imm:$amt1))>; // (or (x << c) | (y >> (32 - c))) ==> (shld32 x, y, c) @@ -4645,11 +4595,11 @@ def : Pat<(store (or (shl (loadi32 addr:$dst), (i8 (trunc ECX:$amt))), addr:$dst), (SHLD32mrCL addr:$dst, GR32:$src2)>; -def : Pat<(shld GR32:$src1, (i8 imm:$amt1), GR32:$src2, (i8 imm:$amt2)), +def : Pat<(shld GR32:$src1, (i8 imm:$amt1), GR32:$src2, (i8 imm/*:$amt2*/)), (SHLD32rri8 GR32:$src1, GR32:$src2, (i8 imm:$amt1))>; def : Pat<(store (shld (loadi32 addr:$dst), (i8 imm:$amt1), - GR32:$src2, (i8 imm:$amt2)), addr:$dst), + GR32:$src2, (i8 imm/*:$amt2*/)), addr:$dst), (SHLD32mri8 addr:$dst, GR32:$src2, (i8 imm:$amt1))>; // (or (x >> c) | (y << (16 - c))) ==> (shrd16 x, y, c) @@ -4670,11 +4620,11 @@ def : Pat<(store (or (srl (loadi16 addr:$dst), (i8 (trunc CX:$amt))), addr:$dst), (SHRD16mrCL addr:$dst, GR16:$src2)>; -def : Pat<(shrd GR16:$src1, (i8 imm:$amt1), GR16:$src2, (i8 imm:$amt2)), +def : Pat<(shrd GR16:$src1, (i8 imm:$amt1), GR16:$src2, (i8 imm/*:$amt2*/)), (SHRD16rri8 GR16:$src1, GR16:$src2, (i8 imm:$amt1))>; def : Pat<(store (shrd (loadi16 addr:$dst), (i8 imm:$amt1), - GR16:$src2, (i8 imm:$amt2)), addr:$dst), + GR16:$src2, (i8 imm/*:$amt2*/)), addr:$dst), (SHRD16mri8 addr:$dst, GR16:$src2, (i8 imm:$amt1))>; // (or (x << c) | (y >> (16 - c))) ==> (shld16 x, y, c) @@ -4695,11 +4645,11 @@ def : Pat<(store (or (shl (loadi16 addr:$dst), (i8 (trunc CX:$amt))), addr:$dst), (SHLD16mrCL addr:$dst, GR16:$src2)>; -def : Pat<(shld GR16:$src1, (i8 imm:$amt1), GR16:$src2, (i8 imm:$amt2)), +def : Pat<(shld GR16:$src1, (i8 imm:$amt1), GR16:$src2, (i8 imm/*:$amt2*/)), (SHLD16rri8 GR16:$src1, GR16:$src2, (i8 imm:$amt1))>; def : Pat<(store (shld (loadi16 addr:$dst), (i8 imm:$amt1), - GR16:$src2, (i8 imm:$amt2)), addr:$dst), + GR16:$src2, (i8 imm/*:$amt2*/)), addr:$dst), (SHLD16mri8 addr:$dst, GR16:$src2, (i8 imm:$amt1))>; // (anyext (setcc_carry)) -> (setcc_carry) diff --git a/lib/Target/X86/X86InstrMMX.td b/lib/Target/X86/X86InstrMMX.td index 89f020cc72..c8e07239d0 100644 --- a/lib/Target/X86/X86InstrMMX.td +++ b/lib/Target/X86/X86InstrMMX.td @@ -141,7 +141,7 @@ def MMX_MOVD64rrv164 : MMXI<0x6E, MRMSrcReg, (outs VR64:$dst), (ins GR64:$src), let neverHasSideEffects = 1 in def MMX_MOVQ64rr : MMXI<0x6F, MRMSrcReg, (outs VR64:$dst), (ins VR64:$src), "movq\t{$src, $dst|$dst, $src}", []>; -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def MMX_MOVQ64rm : MMXI<0x6F, MRMSrcMem, (outs VR64:$dst), (ins i64mem:$src), "movq\t{$src, $dst|$dst, $src}", [(set VR64:$dst, (load_mmx addr:$src))]>; @@ -426,13 +426,15 @@ def MMX_CVTTPS2PIrm : MMXI<0x2C, MRMSrcMem, (outs VR64:$dst), (ins f64mem:$src), // Extract / Insert -def MMX_X86pextrw : SDNode<"X86ISD::PEXTRW", SDTypeProfile<1, 2, []>, []>; -def MMX_X86pinsrw : SDNode<"X86ISD::PINSRW", SDTypeProfile<1, 3, []>, []>; +def MMX_X86pinsrw : SDNode<"X86ISD::MMX_PINSRW", + SDTypeProfile<1, 3, [SDTCisVT<0, v4i16>, SDTCisSameAs<0,1>, + SDTCisVT<2, i32>, SDTCisPtrTy<3>]>>; + def MMX_PEXTRWri : MMXIi8<0xC5, MRMSrcReg, (outs GR32:$dst), (ins VR64:$src1, i16i8imm:$src2), "pextrw\t{$src2, $src1, $dst|$dst, $src1, $src2}", - [(set GR32:$dst, (MMX_X86pextrw (v4i16 VR64:$src1), + [(set GR32:$dst, (X86pextrw (v4i16 VR64:$src1), (iPTR imm:$src2)))]>; let Constraints = "$src1 = $dst" in { def MMX_PINSRWrri : MMXIi8<0xC4, MRMSrcReg, @@ -597,13 +599,6 @@ let AddedComplexity = 10 in { (MMX_PUNPCKHDQrr VR64:$src, VR64:$src)>; } -// Patterns to perform vector shuffling with a zeroed out vector. -let AddedComplexity = 20 in { - def : Pat<(bc_v2i32 (mmx_unpckl immAllZerosV, - (v2i32 (scalar_to_vector (load_mmx addr:$src))))), - (MMX_PUNPCKLDQrm VR64:$src, VR64:$src)>; -} - // Some special case PANDN patterns. // FIXME: Get rid of these. def : Pat<(v1i64 (and (xor VR64:$src1, (bc_v1i64 (v2i32 immAllOnesV))), diff --git a/lib/Target/X86/X86InstrSSE.td b/lib/Target/X86/X86InstrSSE.td index e26c9799b6..2743dba8a9 100644 --- a/lib/Target/X86/X86InstrSSE.td +++ b/lib/Target/X86/X86InstrSSE.td @@ -160,6 +160,32 @@ def memopv4i16 : PatFrag<(ops node:$ptr), (v4i16 (memop64 node:$ptr))>; def memopv8i16 : PatFrag<(ops node:$ptr), (v8i16 (memop64 node:$ptr))>; def memopv2i32 : PatFrag<(ops node:$ptr), (v2i32 (memop64 node:$ptr))>; +// MOVNT Support +// Like 'store', but requires the non-temporal bit to be set +def nontemporalstore : PatFrag<(ops node:$val, node:$ptr), + (st node:$val, node:$ptr), [{ + if (StoreSDNode *ST = dyn_cast(N)) + return ST->isNonTemporal(); + return false; +}]>; + +def alignednontemporalstore : PatFrag<(ops node:$val, node:$ptr), + (st node:$val, node:$ptr), [{ + if (StoreSDNode *ST = dyn_cast(N)) + return ST->isNonTemporal() && !ST->isTruncatingStore() && + ST->getAddressingMode() == ISD::UNINDEXED && + ST->getAlignment() >= 16; + return false; +}]>; + +def unalignednontemporalstore : PatFrag<(ops node:$val, node:$ptr), + (st node:$val, node:$ptr), [{ + if (StoreSDNode *ST = dyn_cast(N)) + return ST->isNonTemporal() && + ST->getAlignment() < 16; + return false; +}]>; + def bc_v4f32 : PatFrag<(ops node:$in), (v4f32 (bitconvert node:$in))>; def bc_v2f64 : PatFrag<(ops node:$in), (v2f64 (bitconvert node:$in))>; def bc_v16i8 : PatFrag<(ops node:$in), (v16i8 (bitconvert node:$in))>; @@ -344,18 +370,56 @@ let Uses = [EFLAGS], usesCustomInserter = 1 in { // SSE1 Instructions //===----------------------------------------------------------------------===// -// Move Instructions -let neverHasSideEffects = 1 in -def MOVSSrr : SSI<0x10, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src), - "movss\t{$src, $dst|$dst, $src}", []>; -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +// Move Instructions. Register-to-register movss is not used for FR32 +// register copies because it's a partial register update; FsMOVAPSrr is +// used instead. Register-to-register movss is not modeled as an INSERT_SUBREG +// because INSERT_SUBREG requires that the insert be implementable in terms of +// a copy, and just mentioned, we don't use movss for copies. +let Constraints = "$src1 = $dst" in +def MOVSSrr : SSI<0x10, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, FR32:$src2), + "movss\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (movl VR128:$src1, (scalar_to_vector FR32:$src2)))]>; + +// Extract the low 32-bit value from one vector and insert it into another. +let AddedComplexity = 15 in +def : Pat<(v4f32 (movl VR128:$src1, VR128:$src2)), + (MOVSSrr VR128:$src1, + (EXTRACT_SUBREG (v4f32 VR128:$src2), x86_subreg_ss))>; + +// Implicitly promote a 32-bit scalar to a vector. +def : Pat<(v4f32 (scalar_to_vector FR32:$src)), + (INSERT_SUBREG (v4f32 (IMPLICIT_DEF)), FR32:$src, x86_subreg_ss)>; + +// Loading from memory automatically zeroing upper bits. +let canFoldAsLoad = 1, isReMaterializable = 1 in def MOVSSrm : SSI<0x10, MRMSrcMem, (outs FR32:$dst), (ins f32mem:$src), "movss\t{$src, $dst|$dst, $src}", [(set FR32:$dst, (loadf32 addr:$src))]>; + +// MOVSSrm zeros the high parts of the register; represent this +// with SUBREG_TO_REG. +let AddedComplexity = 20 in { +def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), + (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), x86_subreg_ss)>; +def : Pat<(v4f32 (scalar_to_vector (loadf32 addr:$src))), + (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), x86_subreg_ss)>; +def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), + (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), x86_subreg_ss)>; +} + +// Store scalar value to memory. def MOVSSmr : SSI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, FR32:$src), "movss\t{$src, $dst|$dst, $src}", [(store FR32:$src, addr:$dst)]>; +// Extract and store. +def : Pat<(store (f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), + addr:$dst), + (MOVSSmr addr:$dst, + (EXTRACT_SUBREG (v4f32 VR128:$src), x86_subreg_ss))>; + // Conversion instructions def CVTTSS2SIrr : SSI<0x2C, MRMSrcReg, (outs GR32:$dst), (ins FR32:$src), "cvttss2si\t{$src, $dst|$dst, $src}", @@ -518,7 +582,7 @@ def FsMOVAPSrr : PSI<0x28, MRMSrcReg, (outs FR32:$dst), (ins FR32:$src), // Alias instruction to load FR32 from f128mem using movaps. Upper bits are // disregarded. -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def FsMOVAPSrm : PSI<0x28, MRMSrcMem, (outs FR32:$dst), (ins f128mem:$src), "movaps\t{$src, $dst|$dst, $src}", [(set FR32:$dst, (alignedloadfsf32 addr:$src))]>; @@ -715,7 +779,7 @@ defm MIN : sse1_fp_binop_rm<0x5D, "min", X86fmin, let neverHasSideEffects = 1 in def MOVAPSrr : PSI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movaps\t{$src, $dst|$dst, $src}", []>; -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def MOVAPSrm : PSI<0x28, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movaps\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (alignedloadv4f32 addr:$src))]>; @@ -727,7 +791,7 @@ def MOVAPSmr : PSI<0x29, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), let neverHasSideEffects = 1 in def MOVUPSrr : PSI<0x10, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movups\t{$src, $dst|$dst, $src}", []>; -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def MOVUPSrm : PSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movups\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (loadv4f32 addr:$src))]>; @@ -736,7 +800,7 @@ def MOVUPSmr : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), [(store (v4f32 VR128:$src), addr:$dst)]>; // Intrinsic forms of MOVUPS load and store -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def MOVUPSrm_Int : PSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movups\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>; @@ -762,6 +826,9 @@ let Constraints = "$src1 = $dst" in { } // Constraints = "$src1 = $dst" +def : Pat<(movlhps VR128:$src1, (bc_v4i32 (v2i64 (X86vzload addr:$src2)))), + (MOVHPSrm VR128:$src1, addr:$src2)>; + def MOVLPSmr : PSI<0x13, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), "movlps\t{$src, $dst|$dst, $src}", [(store (f64 (vector_extract (bc_v2f64 (v4f32 VR128:$src)), @@ -793,9 +860,9 @@ def MOVHLPSrr : PSI<0x12, MRMSrcReg, (outs VR128:$dst), let AddedComplexity = 20 in { def : Pat<(v4f32 (movddup VR128:$src, (undef))), - (MOVLHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; + (MOVLHPSrr VR128:$src, VR128:$src)>; def : Pat<(v2i64 (movddup VR128:$src, (undef))), - (MOVLHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; + (MOVLHPSrr VR128:$src, VR128:$src)>; } @@ -1010,10 +1077,33 @@ def PREFETCHNTA : PSI<0x18, MRM0m, (outs), (ins i8mem:$src), "prefetchnta\t$src", [(prefetch addr:$src, imm, (i32 0))]>; // Non-temporal stores -def MOVNTPSmr : PSI<0x2B, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), +def MOVNTPSmr_Int : PSI<0x2B, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "movntps\t{$src, $dst|$dst, $src}", [(int_x86_sse_movnt_ps addr:$dst, VR128:$src)]>; +let AddedComplexity = 400 in { // Prefer non-temporal versions +def MOVNTPSmr : PSI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movntps\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v4f32 VR128:$src), addr:$dst)]>; + +def MOVNTDQ_64mr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movntdq\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v2f64 VR128:$src), addr:$dst)]>; + +def : Pat<(alignednontemporalstore (v2i64 VR128:$src), addr:$dst), + (MOVNTDQ_64mr VR128:$src, addr:$dst)>; + +def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), + "movnti\t{$src, $dst|$dst, $src}", + [(nontemporalstore (i32 GR32:$src), addr:$dst)]>, + TB, Requires<[HasSSE2]>; + +def MOVNTI_64mr : RI<0xC3, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src), + "movnti\t{$src, $dst|$dst, $src}", + [(nontemporalstore (i64 GR64:$src), addr:$dst)]>, + TB, Requires<[HasSSE2]>; +} + // Load, store, and memory fence def SFENCE : PSI<0xAE, MRM7r, (outs), (ins), "sfence", [(int_x86_sse_sfence)]>; @@ -1032,84 +1122,73 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, def V_SET0 : PSI<0x57, MRMInitReg, (outs VR128:$dst), (ins), "", [(set VR128:$dst, (v4i32 immAllZerosV))]>; -let Predicates = [HasSSE1] in { - def : Pat<(v2i64 immAllZerosV), (V_SET0)>; - def : Pat<(v8i16 immAllZerosV), (V_SET0)>; - def : Pat<(v16i8 immAllZerosV), (V_SET0)>; - def : Pat<(v2f64 immAllZerosV), (V_SET0)>; - def : Pat<(v4f32 immAllZerosV), (V_SET0)>; -} - -// FR32 to 128-bit vector conversion. -let isAsCheapAsAMove = 1 in -def MOVSS2PSrr : SSI<0x10, MRMSrcReg, (outs VR128:$dst), (ins FR32:$src), - "movss\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4f32 (scalar_to_vector FR32:$src)))]>; -def MOVSS2PSrm : SSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f32mem:$src), - "movss\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v4f32 (scalar_to_vector (loadf32 addr:$src))))]>; - -// FIXME: may not be able to eliminate this movss with coalescing the src and -// dest register classes are different. We really want to write this pattern -// like this: -// def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), -// (f32 FR32:$src)>; -let isAsCheapAsAMove = 1 in -def MOVPS2SSrr : SSI<0x10, MRMSrcReg, (outs FR32:$dst), (ins VR128:$src), - "movss\t{$src, $dst|$dst, $src}", - [(set FR32:$dst, (vector_extract (v4f32 VR128:$src), - (iPTR 0)))]>; -def MOVPS2SSmr : SSI<0x11, MRMDestMem, (outs), (ins f32mem:$dst, VR128:$src), - "movss\t{$src, $dst|$dst, $src}", - [(store (f32 (vector_extract (v4f32 VR128:$src), - (iPTR 0))), addr:$dst)]>; - - -// Move to lower bits of a VR128, leaving upper bits alone. -// Three operand (but two address) aliases. -let Constraints = "$src1 = $dst" in { -let neverHasSideEffects = 1 in - def MOVLSS2PSrr : SSI<0x10, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, FR32:$src2), - "movss\t{$src2, $dst|$dst, $src2}", []>; - - let AddedComplexity = 15 in - def MOVLPSrr : SSI<0x10, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "movss\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (v4f32 (movl VR128:$src1, VR128:$src2)))]>; -} +def : Pat<(v2i64 immAllZerosV), (V_SET0)>; +def : Pat<(v8i16 immAllZerosV), (V_SET0)>; +def : Pat<(v16i8 immAllZerosV), (V_SET0)>; +def : Pat<(v2f64 immAllZerosV), (V_SET0)>; +def : Pat<(v4f32 immAllZerosV), (V_SET0)>; -// Move to lower bits of a VR128 and zeroing upper bits. -// Loading from memory automatically zeroing upper bits. -let AddedComplexity = 20 in -def MOVZSS2PSrm : SSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f32mem:$src), - "movss\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (v4f32 (X86vzmovl (v4f32 (scalar_to_vector - (loadf32 addr:$src))))))]>; - -def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), - (MOVZSS2PSrm addr:$src)>; +def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), + (f32 (EXTRACT_SUBREG (v4f32 VR128:$src), x86_subreg_ss))>; //===---------------------------------------------------------------------===// // SSE2 Instructions //===---------------------------------------------------------------------===// -// Move Instructions -let neverHasSideEffects = 1 in -def MOVSDrr : SDI<0x10, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src), - "movsd\t{$src, $dst|$dst, $src}", []>; -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +// Move Instructions. Register-to-register movsd is not used for FR64 +// register copies because it's a partial register update; FsMOVAPDrr is +// used instead. Register-to-register movsd is not modeled as an INSERT_SUBREG +// because INSERT_SUBREG requires that the insert be implementable in terms of +// a copy, and just mentioned, we don't use movsd for copies. +let Constraints = "$src1 = $dst" in +def MOVSDrr : SDI<0x10, MRMSrcReg, + (outs VR128:$dst), (ins VR128:$src1, FR64:$src2), + "movsd\t{$src2, $dst|$dst, $src2}", + [(set VR128:$dst, + (movl VR128:$src1, (scalar_to_vector FR64:$src2)))]>; + +// Extract the low 64-bit value from one vector and insert it into another. +let AddedComplexity = 15 in +def : Pat<(v2f64 (movl VR128:$src1, VR128:$src2)), + (MOVSDrr VR128:$src1, + (EXTRACT_SUBREG (v2f64 VR128:$src2), x86_subreg_sd))>; + +// Implicitly promote a 64-bit scalar to a vector. +def : Pat<(v2f64 (scalar_to_vector FR64:$src)), + (INSERT_SUBREG (v2f64 (IMPLICIT_DEF)), FR64:$src, x86_subreg_sd)>; + +// Loading from memory automatically zeroing upper bits. +let canFoldAsLoad = 1, isReMaterializable = 1, AddedComplexity = 20 in def MOVSDrm : SDI<0x10, MRMSrcMem, (outs FR64:$dst), (ins f64mem:$src), "movsd\t{$src, $dst|$dst, $src}", [(set FR64:$dst, (loadf64 addr:$src))]>; + +// MOVSDrm zeros the high parts of the register; represent this +// with SUBREG_TO_REG. +let AddedComplexity = 20 in { +def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), x86_subreg_sd)>; +def : Pat<(v2f64 (scalar_to_vector (loadf64 addr:$src))), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), x86_subreg_sd)>; +def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), x86_subreg_sd)>; +def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), x86_subreg_sd)>; +def : Pat<(v2f64 (X86vzload addr:$src)), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), x86_subreg_sd)>; +} + +// Store scalar value to memory. def MOVSDmr : SDI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, FR64:$src), "movsd\t{$src, $dst|$dst, $src}", [(store FR64:$src, addr:$dst)]>; +// Extract and store. +def : Pat<(store (f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))), + addr:$dst), + (MOVSDmr addr:$dst, + (EXTRACT_SUBREG (v2f64 VR128:$src), x86_subreg_sd))>; + // Conversion instructions def CVTTSD2SIrr : SDI<0x2C, MRMSrcReg, (outs GR32:$dst), (ins FR64:$src), "cvttsd2si\t{$src, $dst|$dst, $src}", @@ -1163,7 +1242,8 @@ def CVTSS2SDrm : I<0x5A, MRMSrcMem, (outs FR64:$dst), (ins f32mem:$src), Requires<[HasSSE2, OptForSize]>; def : Pat<(extloadf32 addr:$src), - (CVTSS2SDrr (MOVSSrm addr:$src))>, Requires<[HasSSE2, OptForSpeed]>; + (CVTSS2SDrr (MOVSSrm addr:$src))>, + Requires<[HasSSE2, OptForSpeed]>; // Match intrinsics which expect XMM operand(s). def Int_CVTSD2SIrr : SDI<0x2D, MRMSrcReg, (outs GR32:$dst), (ins VR128:$src), @@ -1282,7 +1362,7 @@ def FsMOVAPDrr : PDI<0x28, MRMSrcReg, (outs FR64:$dst), (ins FR64:$src), // Alias instruction to load FR64 from f128mem using movapd. Upper bits are // disregarded. -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def FsMOVAPDrm : PDI<0x28, MRMSrcMem, (outs FR64:$dst), (ins f128mem:$src), "movapd\t{$src, $dst|$dst, $src}", [(set FR64:$dst, (alignedloadfsf64 addr:$src))]>; @@ -1480,7 +1560,7 @@ defm MIN : sse2_fp_binop_rm<0x5D, "min", X86fmin, let neverHasSideEffects = 1 in def MOVAPDrr : PDI<0x28, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "movapd\t{$src, $dst|$dst, $src}", []>; -let canFoldAsLoad = 1, isReMaterializable = 1, mayHaveSideEffects = 1 in +let canFoldAsLoad = 1, isReMaterializable = 1 in def MOVAPDrm : PDI<0x28, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), "movapd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, (alignedloadv2f64 addr:$src))]>; @@ -2295,34 +2375,47 @@ def MASKMOVDQU64 : PDI<0xF7, MRMSrcReg, (outs), (ins VR128:$src, VR128:$mask), [(int_x86_sse2_maskmov_dqu VR128:$src, VR128:$mask, RDI)]>; // Non-temporal stores -def MOVNTPDmr : PDI<0x2B, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), - "movntpd\t{$src, $dst|$dst, $src}", - [(int_x86_sse2_movnt_pd addr:$dst, VR128:$src)]>; -def MOVNTDQmr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), - "movntdq\t{$src, $dst|$dst, $src}", - [(int_x86_sse2_movnt_dq addr:$dst, VR128:$src)]>; -def MOVNTImr : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), +def MOVNTPDmr_Int : PDI<0x2B, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), + "movntpd\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_movnt_pd addr:$dst, VR128:$src)]>; +def MOVNTDQmr_Int : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movntdq\t{$src, $dst|$dst, $src}", + [(int_x86_sse2_movnt_dq addr:$dst, VR128:$src)]>; +def MOVNTImr_Int : I<0xC3, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src), "movnti\t{$src, $dst|$dst, $src}", [(int_x86_sse2_movnt_i addr:$dst, GR32:$src)]>, TB, Requires<[HasSSE2]>; +let AddedComplexity = 400 in { // Prefer non-temporal versions +def MOVNTPDmr : PDI<0x2B, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movntpd\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore(v2f64 VR128:$src), addr:$dst)]>; + +def MOVNTDQmr : PDI<0xE7, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), + "movntdq\t{$src, $dst|$dst, $src}", + [(alignednontemporalstore (v4f32 VR128:$src), addr:$dst)]>; + +def : Pat<(alignednontemporalstore (v4i32 VR128:$src), addr:$dst), + (MOVNTDQmr VR128:$src, addr:$dst)>; +} + // Flush cache def CLFLUSH : I<0xAE, MRM7m, (outs), (ins i8mem:$src), "clflush\t$src", [(int_x86_sse2_clflush addr:$src)]>, TB, Requires<[HasSSE2]>; // Load, store, and memory fence -def LFENCE : I<0xAE, MRM5r, (outs), (ins), +def LFENCE : I<0xAE, MRM_E8, (outs), (ins), "lfence", [(int_x86_sse2_lfence)]>, TB, Requires<[HasSSE2]>; -def MFENCE : I<0xAE, MRM6r, (outs), (ins), +def MFENCE : I<0xAE, MRM_F0, (outs), (ins), "mfence", [(int_x86_sse2_mfence)]>, TB, Requires<[HasSSE2]>; //TODO: custom lower this so as to never even generate the noop -def : Pat<(membarrier (i8 imm:$ll), (i8 imm:$ls), (i8 imm:$sl), (i8 imm:$ss), +def : Pat<(membarrier (i8 imm), (i8 imm), (i8 imm), (i8 imm), (i8 0)), (NOOP)>; def : Pat<(membarrier (i8 0), (i8 0), (i8 0), (i8 1), (i8 1)), (SFENCE)>; def : Pat<(membarrier (i8 1), (i8 0), (i8 0), (i8 0), (i8 1)), (LFENCE)>; -def : Pat<(membarrier (i8 imm:$ll), (i8 imm:$ls), (i8 imm:$sl), (i8 imm:$ss), +def : Pat<(membarrier (i8 imm), (i8 imm), (i8 imm), (i8 imm), (i8 1)), (MFENCE)>; // Alias instructions that map zero vector to pxor / xorp* for sse. @@ -2334,17 +2427,6 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1, canFoldAsLoad = 1, def V_SETALLONES : PDI<0x76, MRMInitReg, (outs VR128:$dst), (ins), "", [(set VR128:$dst, (v4i32 immAllOnesV))]>; -// FR64 to 128-bit vector conversion. -let isAsCheapAsAMove = 1 in -def MOVSD2PDrr : SDI<0x10, MRMSrcReg, (outs VR128:$dst), (ins FR64:$src), - "movsd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (scalar_to_vector FR64:$src)))]>; -def MOVSD2PDrm : SDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), - "movsd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (scalar_to_vector (loadf64 addr:$src))))]>; - def MOVDI2PDIrr : PDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), "movd\t{$src, $dst|$dst, $src}", [(set VR128:$dst, @@ -2373,20 +2455,9 @@ def MOVPQI2QImr : PDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), [(store (i64 (vector_extract (v2i64 VR128:$src), (iPTR 0))), addr:$dst)]>; -// FIXME: may not be able to eliminate this movss with coalescing the src and -// dest register classes are different. We really want to write this pattern -// like this: -// def : Pat<(f32 (vector_extract (v4f32 VR128:$src), (iPTR 0))), -// (f32 FR32:$src)>; -let isAsCheapAsAMove = 1 in -def MOVPD2SDrr : SDI<0x10, MRMSrcReg, (outs FR64:$dst), (ins VR128:$src), - "movsd\t{$src, $dst|$dst, $src}", - [(set FR64:$dst, (vector_extract (v2f64 VR128:$src), - (iPTR 0)))]>; -def MOVPD2SDmr : SDI<0x11, MRMDestMem, (outs), (ins f64mem:$dst, VR128:$src), - "movsd\t{$src, $dst|$dst, $src}", - [(store (f64 (vector_extract (v2f64 VR128:$src), - (iPTR 0))), addr:$dst)]>; +def : Pat<(f64 (vector_extract (v2f64 VR128:$src), (iPTR 0))), + (f64 (EXTRACT_SUBREG (v2f64 VR128:$src), x86_subreg_sd))>; + def MOVPDI2DIrr : PDI<0x7E, MRMDestReg, (outs GR32:$dst), (ins VR128:$src), "movd\t{$src, $dst|$dst, $src}", [(set GR32:$dst, (vector_extract (v4i32 VR128:$src), @@ -2403,44 +2474,11 @@ def MOVSS2DImr : PDI<0x7E, MRMDestMem, (outs), (ins i32mem:$dst, FR32:$src), "movd\t{$src, $dst|$dst, $src}", [(store (i32 (bitconvert FR32:$src)), addr:$dst)]>; - -// Move to lower bits of a VR128, leaving upper bits alone. -// Three operand (but two address) aliases. -let Constraints = "$src1 = $dst" in { - let neverHasSideEffects = 1 in - def MOVLSD2PDrr : SDI<0x10, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, FR64:$src2), - "movsd\t{$src2, $dst|$dst, $src2}", []>; - - let AddedComplexity = 15 in - def MOVLPDrr : SDI<0x10, MRMSrcReg, - (outs VR128:$dst), (ins VR128:$src1, VR128:$src2), - "movsd\t{$src2, $dst|$dst, $src2}", - [(set VR128:$dst, - (v2f64 (movl VR128:$src1, VR128:$src2)))]>; -} - // Store / copy lower 64-bits of a XMM register. def MOVLQ128mr : PDI<0xD6, MRMDestMem, (outs), (ins i64mem:$dst, VR128:$src), "movq\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storel_dq addr:$dst, VR128:$src)]>; -// Move to lower bits of a VR128 and zeroing upper bits. -// Loading from memory automatically zeroing upper bits. -let AddedComplexity = 20 in { -def MOVZSD2PDrm : SDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f64mem:$src), - "movsd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, - (v2f64 (X86vzmovl (v2f64 (scalar_to_vector - (loadf64 addr:$src))))))]>; - -def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), - (MOVZSD2PDrm addr:$src)>; -def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), - (MOVZSD2PDrm addr:$src)>; -def : Pat<(v2f64 (X86vzload addr:$src)), (MOVZSD2PDrm addr:$src)>; -} - // movd / movq to XMM register zero-extends let AddedComplexity = 15 in { def MOVZDI2PDIrr : PDI<0x6E, MRMSrcReg, (outs VR128:$dst), (ins GR32:$src), @@ -2613,9 +2651,9 @@ let Constraints = "$src1 = $dst" in { } // Thread synchronization -def MONITOR : I<0x01, MRM1r, (outs), (ins), "monitor", +def MONITOR : I<0x01, MRM_C8, (outs), (ins), "monitor", [(int_x86_sse3_monitor EAX, ECX, EDX)]>,TB, Requires<[HasSSE3]>; -def MWAIT : I<0x01, MRM1r, (outs), (ins), "mwait", +def MWAIT : I<0x01, MRM_C9, (outs), (ins), "mwait", [(int_x86_sse3_mwait ECX, EAX)]>, TB, Requires<[HasSSE3]>; // vector_shuffle v1, <1, 1, 3, 3> @@ -2986,13 +3024,15 @@ let Predicates = [HasSSE2] in { let AddedComplexity = 15 in { // Zeroing a VR128 then do a MOVS{S|D} to the lower bits. def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector FR64:$src)))), - (MOVLSD2PDrr (V_SET0), FR64:$src)>, Requires<[HasSSE2]>; + (MOVSDrr (v2f64 (V_SET0)), FR64:$src)>; def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector FR32:$src)))), - (MOVLSS2PSrr (V_SET0), FR32:$src)>, Requires<[HasSSE1]>; + (MOVSSrr (v4f32 (V_SET0)), FR32:$src)>; def : Pat<(v4f32 (X86vzmovl (v4f32 VR128:$src))), - (MOVLPSrr (V_SET0), VR128:$src)>, Requires<[HasSSE1]>; + (MOVSSrr (v4f32 (V_SET0)), + (f32 (EXTRACT_SUBREG (v4f32 VR128:$src), x86_subreg_ss)))>; def : Pat<(v4i32 (X86vzmovl (v4i32 VR128:$src))), - (MOVLPSrr (V_SET0), VR128:$src)>, Requires<[HasSSE1]>; + (MOVSSrr (v4i32 (V_SET0)), + (EXTRACT_SUBREG (v4i32 VR128:$src), x86_subreg_ss))>; } // Splat v2f64 / v2i64 @@ -3010,8 +3050,7 @@ def : Pat<(unpckh (v2i64 VR128:$src), (undef)), // Special unary SHUFPSrri case. def : Pat<(v4f32 (pshufd:$src3 VR128:$src1, (undef))), (SHUFPSrri VR128:$src1, VR128:$src1, - (SHUFFLE_get_shuf_imm VR128:$src3))>, - Requires<[HasSSE1]>; + (SHUFFLE_get_shuf_imm VR128:$src3))>; let AddedComplexity = 5 in def : Pat<(v4f32 (pshufd:$src2 VR128:$src1, (undef))), (PSHUFDri VR128:$src1, (SHUFFLE_get_shuf_imm VR128:$src2))>, @@ -3057,13 +3096,13 @@ def : Pat<(v4f32 (unpckl_undef:$src2 VR128:$src, (undef))), } let AddedComplexity = 10 in { def : Pat<(v4f32 (unpckl_undef VR128:$src, (undef))), - (UNPCKLPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; + (UNPCKLPSrr VR128:$src, VR128:$src)>; def : Pat<(v16i8 (unpckl_undef VR128:$src, (undef))), - (PUNPCKLBWrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; + (PUNPCKLBWrr VR128:$src, VR128:$src)>; def : Pat<(v8i16 (unpckl_undef VR128:$src, (undef))), - (PUNPCKLWDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; + (PUNPCKLWDrr VR128:$src, VR128:$src)>; def : Pat<(v4i32 (unpckl_undef VR128:$src, (undef))), - (PUNPCKLDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; + (PUNPCKLDQrr VR128:$src, VR128:$src)>; } // vector_shuffle v1, , <2, 2, 3, 3, ...> @@ -3077,13 +3116,13 @@ def : Pat<(v4f32 (unpckh_undef:$src2 VR128:$src, (undef))), } let AddedComplexity = 10 in { def : Pat<(v4f32 (unpckh_undef VR128:$src, (undef))), - (UNPCKHPSrr VR128:$src, VR128:$src)>, Requires<[HasSSE1]>; + (UNPCKHPSrr VR128:$src, VR128:$src)>; def : Pat<(v16i8 (unpckh_undef VR128:$src, (undef))), - (PUNPCKHBWrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; + (PUNPCKHBWrr VR128:$src, VR128:$src)>; def : Pat<(v8i16 (unpckh_undef VR128:$src, (undef))), - (PUNPCKHWDrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; + (PUNPCKHWDrr VR128:$src, VR128:$src)>; def : Pat<(v4i32 (unpckh_undef VR128:$src, (undef))), - (PUNPCKHDQrr VR128:$src, VR128:$src)>, Requires<[HasSSE2]>; + (PUNPCKHDQrr VR128:$src, VR128:$src)>; } let AddedComplexity = 20 in { @@ -3105,45 +3144,49 @@ def : Pat<(v4i32 (movhlps_undef VR128:$src1, (undef))), let AddedComplexity = 20 in { // vector_shuffle v1, (load v2) <4, 5, 2, 3> using MOVLPS def : Pat<(v4f32 (movlp VR128:$src1, (load addr:$src2))), - (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE1]>; + (MOVLPSrm VR128:$src1, addr:$src2)>; def : Pat<(v2f64 (movlp VR128:$src1, (load addr:$src2))), - (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; + (MOVLPDrm VR128:$src1, addr:$src2)>; def : Pat<(v4i32 (movlp VR128:$src1, (load addr:$src2))), - (MOVLPSrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; + (MOVLPSrm VR128:$src1, addr:$src2)>; def : Pat<(v2i64 (movlp VR128:$src1, (load addr:$src2))), - (MOVLPDrm VR128:$src1, addr:$src2)>, Requires<[HasSSE2]>; + (MOVLPDrm VR128:$src1, addr:$src2)>; } // (store (vector_shuffle (load addr), v2, <4, 5, 2, 3>), addr) using MOVLPS def : Pat<(store (v4f32 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), - (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; + (MOVLPSmr addr:$src1, VR128:$src2)>; def : Pat<(store (v2f64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), - (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + (MOVLPDmr addr:$src1, VR128:$src2)>; def : Pat<(store (v4i32 (movlp (bc_v4i32 (loadv2i64 addr:$src1)), VR128:$src2)), addr:$src1), - (MOVLPSmr addr:$src1, VR128:$src2)>, Requires<[HasSSE1]>; + (MOVLPSmr addr:$src1, VR128:$src2)>; def : Pat<(store (v2i64 (movlp (load addr:$src1), VR128:$src2)), addr:$src1), - (MOVLPDmr addr:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + (MOVLPDmr addr:$src1, VR128:$src2)>; let AddedComplexity = 15 in { // Setting the lowest element in the vector. def : Pat<(v4i32 (movl VR128:$src1, VR128:$src2)), - (MOVLPSrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + (MOVSSrr (v4i32 VR128:$src1), + (EXTRACT_SUBREG (v4i32 VR128:$src2), x86_subreg_ss))>; def : Pat<(v2i64 (movl VR128:$src1, VR128:$src2)), - (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + (MOVSDrr (v2i64 VR128:$src1), + (EXTRACT_SUBREG (v2i64 VR128:$src2), x86_subreg_sd))>; -// vector_shuffle v1, v2 <4, 5, 2, 3> using MOVLPDrr (movsd) +// vector_shuffle v1, v2 <4, 5, 2, 3> using movsd def : Pat<(v4f32 (movlp VR128:$src1, VR128:$src2)), - (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + (MOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, x86_subreg_sd))>, + Requires<[HasSSE2]>; def : Pat<(v4i32 (movlp VR128:$src1, VR128:$src2)), - (MOVLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasSSE2]>; + (MOVSDrr VR128:$src1, (EXTRACT_SUBREG VR128:$src2, x86_subreg_sd))>, + Requires<[HasSSE2]>; } // vector_shuffle v1, v2 <4, 5, 2, 3> using SHUFPSrri (we prefer movsd, but // fall back to this for SSE1) def : Pat<(v4f32 (movlp:$src3 VR128:$src1, (v4f32 VR128:$src2))), (SHUFPSrri VR128:$src2, VR128:$src1, - (SHUFFLE_get_shuf_imm VR128:$src3))>, Requires<[HasSSE1]>; + (SHUFFLE_get_shuf_imm VR128:$src3))>; // Set lowest element and zero upper elements. let AddedComplexity = 15 in @@ -3185,30 +3228,30 @@ def : Pat<(v2i32 (fp_to_sint (v2f64 VR128:$src))), // Use movaps / movups for SSE integer load / store (one byte shorter). def : Pat<(alignedloadv4i32 addr:$src), - (MOVAPSrm addr:$src)>, Requires<[HasSSE1]>; + (MOVAPSrm addr:$src)>; def : Pat<(loadv4i32 addr:$src), - (MOVUPSrm addr:$src)>, Requires<[HasSSE1]>; + (MOVUPSrm addr:$src)>; def : Pat<(alignedloadv2i64 addr:$src), - (MOVAPSrm addr:$src)>, Requires<[HasSSE2]>; + (MOVAPSrm addr:$src)>; def : Pat<(loadv2i64 addr:$src), - (MOVUPSrm addr:$src)>, Requires<[HasSSE2]>; + (MOVUPSrm addr:$src)>; def : Pat<(alignedstore (v2i64 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + (MOVAPSmr addr:$dst, VR128:$src)>; def : Pat<(alignedstore (v4i32 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + (MOVAPSmr addr:$dst, VR128:$src)>; def : Pat<(alignedstore (v8i16 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + (MOVAPSmr addr:$dst, VR128:$src)>; def : Pat<(alignedstore (v16i8 VR128:$src), addr:$dst), - (MOVAPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + (MOVAPSmr addr:$dst, VR128:$src)>; def : Pat<(store (v2i64 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + (MOVUPSmr addr:$dst, VR128:$src)>; def : Pat<(store (v4i32 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + (MOVUPSmr addr:$dst, VR128:$src)>; def : Pat<(store (v8i16 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + (MOVUPSmr addr:$dst, VR128:$src)>; def : Pat<(store (v16i8 VR128:$src), addr:$dst), - (MOVUPSmr addr:$dst, VR128:$src)>, Requires<[HasSSE2]>; + (MOVUPSmr addr:$dst, VR128:$src)>; //===----------------------------------------------------------------------===// // SSE4.1 Instructions @@ -3397,7 +3440,7 @@ let Constraints = "$src1 = $dst" in { (ins VR128:$src1, i128mem:$src2), !strconcat(OpcodeStr, "\t{$src2, $dst|$dst, $src2}"), [(set VR128:$dst, - (OpNode VR128:$src1, (memop addr:$src2)))]>, OpSize; + (OpVT (OpNode VR128:$src1, (memop addr:$src2))))]>, OpSize; def rm_int : SS48I= FirstTargetFixupKind && Kind < MaxTargetFixupKind && + assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); return Infos[Kind - FirstTargetFixupKind]; } @@ -83,9 +74,11 @@ public: } } - void EmitDisplacementField(const MCOperand &Disp, int64_t Adj, bool IsPCRel, - unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl &Fixups) const; + void EmitImmediate(const MCOperand &Disp, + unsigned ImmSize, MCFixupKind FixupKind, + unsigned &CurByte, raw_ostream &OS, + SmallVectorImpl &Fixups, + int ImmOffset = 0) const; inline static unsigned char ModRMByte(unsigned Mod, unsigned RegOpcode, unsigned RM) { @@ -106,8 +99,8 @@ public: void EmitMemModRMByte(const MCInst &MI, unsigned Op, - unsigned RegOpcodeField, intptr_t PCAdj, - unsigned &CurByte, raw_ostream &OS, + unsigned RegOpcodeField, + unsigned TSFlags, unsigned &CurByte, raw_ostream &OS, SmallVectorImpl &Fixups) const; void EncodeInstruction(const MCInst &MI, raw_ostream &OS, @@ -119,13 +112,15 @@ public: MCCodeEmitter *llvm::createX86_32MCCodeEmitter(const Target &, - TargetMachine &TM) { - return new X86MCCodeEmitter(TM, false); + TargetMachine &TM, + MCContext &Ctx) { + return new X86MCCodeEmitter(TM, Ctx, false); } MCCodeEmitter *llvm::createX86_64MCCodeEmitter(const Target &, - TargetMachine &TM) { - return new X86MCCodeEmitter(TM, true); + TargetMachine &TM, + MCContext &Ctx) { + return new X86MCCodeEmitter(TM, Ctx, true); } @@ -135,36 +130,59 @@ static bool isDisp8(int Value) { return Value == (signed char)Value; } +/// getImmFixupKind - Return the appropriate fixup kind to use for an immediate +/// in an instruction with the specified TSFlags. +static MCFixupKind getImmFixupKind(unsigned TSFlags) { + unsigned Size = X86II::getSizeOfImm(TSFlags); + bool isPCRel = X86II::isImmPCRel(TSFlags); + + switch (Size) { + default: assert(0 && "Unknown immediate size"); + case 1: return isPCRel ? MCFixupKind(X86::reloc_pcrel_1byte) : FK_Data_1; + case 4: return isPCRel ? MCFixupKind(X86::reloc_pcrel_4byte) : FK_Data_4; + case 2: assert(!isPCRel); return FK_Data_2; + case 8: assert(!isPCRel); return FK_Data_8; + } +} + + void X86MCCodeEmitter:: -EmitDisplacementField(const MCOperand &DispOp, int64_t Adj, bool IsPCRel, - unsigned &CurByte, raw_ostream &OS, - SmallVectorImpl &Fixups) const { +EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind, + unsigned &CurByte, raw_ostream &OS, + SmallVectorImpl &Fixups, int ImmOffset) const { // If this is a simple integer displacement that doesn't require a relocation, // emit it now. if (DispOp.isImm()) { - EmitConstant(DispOp.getImm(), 4, CurByte, OS); + // FIXME: is this right for pc-rel encoding?? Probably need to emit this as + // a fixup if so. + EmitConstant(DispOp.getImm()+ImmOffset, Size, CurByte, OS); return; } -#if 0 - // Otherwise, this is something that requires a relocation. Emit it as such - // now. - unsigned RelocType = Is64BitMode ? - (IsPCRel ? X86::reloc_pcrel_word : X86::reloc_absolute_word_sext) - : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); -#endif + // If we have an immoffset, add it to the expression. + const MCExpr *Expr = DispOp.getExpr(); + + // If the fixup is pc-relative, we need to bias the value to be relative to + // the start of the field, not the end of the field. + if (FixupKind == MCFixupKind(X86::reloc_pcrel_4byte) || + FixupKind == MCFixupKind(X86::reloc_riprel_4byte)) + ImmOffset -= 4; + if (FixupKind == MCFixupKind(X86::reloc_pcrel_1byte)) + ImmOffset -= 1; + + if (ImmOffset) + Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(ImmOffset, Ctx), + Ctx); // Emit a symbolic constant as a fixup and 4 zeros. - Fixups.push_back(MCFixup::Create(CurByte, DispOp.getExpr(), - MCFixupKind(X86::reloc_absolute_word))); - EmitConstant(0, 4, CurByte, OS); + Fixups.push_back(MCFixup::Create(CurByte, Expr, FixupKind)); + EmitConstant(0, Size, CurByte, OS); } void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, unsigned RegOpcodeField, - intptr_t PCAdj, - unsigned &CurByte, + unsigned TSFlags, unsigned &CurByte, raw_ostream &OS, SmallVectorImpl &Fixups) const{ const MCOperand &Disp = MI.getOperand(Op+3); @@ -172,31 +190,48 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, const MCOperand &Scale = MI.getOperand(Op+1); const MCOperand &IndexReg = MI.getOperand(Op+2); unsigned BaseReg = Base.getReg(); - - // FIXME: Eliminate! - bool IsPCRel = false; + + // Handle %rip relative addressing. + if (BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode + assert(IndexReg.getReg() == 0 && Is64BitMode && + "Invalid rip-relative address"); + EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); + + // rip-relative addressing is actually relative to the *next* instruction. + // Since an immediate can follow the mod/rm byte for an instruction, this + // means that we need to bias the immediate field of the instruction with + // the size of the immediate field. If we have this case, add it into the + // expression to emit. + int ImmSize = X86II::hasImm(TSFlags) ? X86II::getSizeOfImm(TSFlags) : 0; + EmitImmediate(Disp, 4, MCFixupKind(X86::reloc_riprel_4byte), + CurByte, OS, Fixups, -ImmSize); + return; + } + + unsigned BaseRegNo = BaseReg ? GetX86RegNum(Base) : -1U; + // Determine whether a SIB byte is needed. // If no BaseReg, issue a RIP relative instruction only if the MCE can // resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table // 2-7) and absolute references. + if (// The SIB byte must be used if there is an index register. IndexReg.getReg() == 0 && - // The SIB byte must be used if the base is ESP/RSP. - BaseReg != X86::ESP && BaseReg != X86::RSP && + // The SIB byte must be used if the base is ESP/RSP/R12, all of which + // encode to an R/M value of 4, which indicates that a SIB byte is + // present. + BaseRegNo != N86::ESP && // If there is no base register and we're in 64-bit mode, we need a SIB // byte to emit an addr that is just 'disp32' (the non-RIP relative form). (!Is64BitMode || BaseReg != 0)) { - if (BaseReg == 0 || // [disp32] in X86-32 mode - BaseReg == X86::RIP) { // [disp32+RIP] in X86-64 mode + if (BaseReg == 0) { // [disp32] in X86-32 mode EmitByte(ModRMByte(0, RegOpcodeField, 5), CurByte, OS); - EmitDisplacementField(Disp, PCAdj, true, CurByte, OS, Fixups); + EmitImmediate(Disp, 4, FK_Data_4, CurByte, OS, Fixups); return; } - unsigned BaseRegNo = GetX86RegNum(Base); - // If the base is not EBP/ESP and there is no displacement, use simple // indirect register encoding, this handles addresses like [EAX]. The // encoding for [EBP] with no displacement means [disp32] so we handle it @@ -209,13 +244,13 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, // Otherwise, if the displacement fits in a byte, encode as [REG+disp8]. if (Disp.isImm() && isDisp8(Disp.getImm())) { EmitByte(ModRMByte(1, RegOpcodeField, BaseRegNo), CurByte, OS); - EmitConstant(Disp.getImm(), 1, CurByte, OS); + EmitImmediate(Disp, 1, FK_Data_1, CurByte, OS, Fixups); return; } // Otherwise, emit the most general non-SIB encoding: [REG+disp32] EmitByte(ModRMByte(2, RegOpcodeField, BaseRegNo), CurByte, OS); - EmitDisplacementField(Disp, PCAdj, IsPCRel, CurByte, OS, Fixups); + EmitImmediate(Disp, 4, FK_Data_4, CurByte, OS, Fixups); return; } @@ -270,9 +305,9 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, // Do we need to output a displacement? if (ForceDisp8) - EmitConstant(Disp.getImm(), 1, CurByte, OS); + EmitImmediate(Disp, 1, FK_Data_1, CurByte, OS, Fixups); else if (ForceDisp32 || Disp.getImm() != 0) - EmitDisplacementField(Disp, PCAdj, IsPCRel, CurByte, OS, Fixups); + EmitImmediate(Disp, 4, FK_Data_4, CurByte, OS, Fixups); } /// DetermineREXPrefix - Determine if the MCInst has to be encoded with a X86-64 @@ -280,11 +315,11 @@ void X86MCCodeEmitter::EmitMemModRMByte(const MCInst &MI, unsigned Op, /// size, and 3) use of X86-64 extended registers. static unsigned DetermineREXPrefix(const MCInst &MI, unsigned TSFlags, const TargetInstrDesc &Desc) { - unsigned REX = 0; - - // Pseudo instructions do not need REX prefix byte. + // Pseudo instructions never have a rex byte. if ((TSFlags & X86II::FormMask) == X86II::Pseudo) return 0; + + unsigned REX = 0; if (TSFlags & X86II::REX_W) REX |= 1 << 3; @@ -482,52 +517,29 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, case X86II::MRMInitReg: assert(0 && "FIXME: Remove this form when the JIT moves to MCCodeEmitter!"); default: errs() << "FORM: " << (TSFlags & X86II::FormMask) << "\n"; - assert(0 && "Unknown FormMask value in X86MCCodeEmitter!"); - case X86II::RawFrm: { + assert(0 && "Unknown FormMask value in X86MCCodeEmitter!"); + case X86II::Pseudo: return; // Pseudo instructions encode to nothing. + case X86II::RawFrm: EmitByte(BaseOpcode, CurByte, OS); - - if (CurOp == NumOps) - break; - - assert(0 && "Unimpl RawFrm expr"); break; - } - case X86II::AddRegFrm: { + case X86II::AddRegFrm: EmitByte(BaseOpcode + GetX86RegNum(MI.getOperand(CurOp++)), CurByte, OS); - if (CurOp == NumOps) - break; - - const MCOperand &MO1 = MI.getOperand(CurOp++); - if (MO1.isImm()) { - unsigned Size = X86II::getSizeOfImm(TSFlags); - EmitConstant(MO1.getImm(), Size, CurByte, OS); - break; - } - - assert(0 && "Unimpl AddRegFrm expr"); break; - } case X86II::MRMDestReg: EmitByte(BaseOpcode, CurByte, OS); EmitRegModRMByte(MI.getOperand(CurOp), GetX86RegNum(MI.getOperand(CurOp+1)), CurByte, OS); CurOp += 2; - if (CurOp != NumOps) - EmitConstant(MI.getOperand(CurOp++).getImm(), - X86II::getSizeOfImm(TSFlags), CurByte, OS); break; case X86II::MRMDestMem: EmitByte(BaseOpcode, CurByte, OS); EmitMemModRMByte(MI, CurOp, GetX86RegNum(MI.getOperand(CurOp + X86AddrNumOperands)), - 0, CurByte, OS, Fixups); + TSFlags, CurByte, OS, Fixups); CurOp += X86AddrNumOperands + 1; - if (CurOp != NumOps) - EmitConstant(MI.getOperand(CurOp++).getImm(), - X86II::getSizeOfImm(TSFlags), CurByte, OS); break; case X86II::MRMSrcReg: @@ -535,9 +547,6 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, EmitRegModRMByte(MI.getOperand(CurOp+1), GetX86RegNum(MI.getOperand(CurOp)), CurByte, OS); CurOp += 2; - if (CurOp != NumOps) - EmitConstant(MI.getOperand(CurOp++).getImm(), - X86II::getSizeOfImm(TSFlags), CurByte, OS); break; case X86II::MRMSrcMem: { @@ -551,117 +560,78 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, else AddrOperands = X86AddrNumOperands; - // FIXME: What is this actually doing? - intptr_t PCAdj = (CurOp + AddrOperands + 1 != NumOps) ? - X86II::getSizeOfImm(TSFlags) : 0; - EmitMemModRMByte(MI, CurOp+1, GetX86RegNum(MI.getOperand(CurOp)), - PCAdj, CurByte, OS, Fixups); + TSFlags, CurByte, OS, Fixups); CurOp += AddrOperands + 1; - if (CurOp != NumOps) - EmitConstant(MI.getOperand(CurOp++).getImm(), - X86II::getSizeOfImm(TSFlags), CurByte, OS); break; } case X86II::MRM0r: case X86II::MRM1r: case X86II::MRM2r: case X86II::MRM3r: case X86II::MRM4r: case X86II::MRM5r: - case X86II::MRM6r: case X86II::MRM7r: { + case X86II::MRM6r: case X86II::MRM7r: EmitByte(BaseOpcode, CurByte, OS); - - // Special handling of lfence, mfence, monitor, and mwait. - // FIXME: This is terrible, they should get proper encoding bits in TSFlags. - if (Opcode == X86::LFENCE || Opcode == X86::MFENCE || - Opcode == X86::MONITOR || Opcode == X86::MWAIT) { - EmitByte(ModRMByte(3, (TSFlags & X86II::FormMask)-X86II::MRM0r, 0), - CurByte, OS); - - switch (Opcode) { - default: break; - case X86::MONITOR: EmitByte(0xC8, CurByte, OS); break; - case X86::MWAIT: EmitByte(0xC9, CurByte, OS); break; - } - } else { - EmitRegModRMByte(MI.getOperand(CurOp++), - (TSFlags & X86II::FormMask)-X86II::MRM0r, - CurByte, OS); - } - - if (CurOp == NumOps) - break; - - const MCOperand &MO1 = MI.getOperand(CurOp++); - if (MO1.isImm()) { - EmitConstant(MO1.getImm(), X86II::getSizeOfImm(TSFlags), CurByte, OS); - break; - } - - assert(0 && "relo unimpl"); -#if 0 - unsigned rt = Is64BitMode ? X86::reloc_pcrel_word - : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); - if (Opcode == X86::MOV64ri32) - rt = X86::reloc_absolute_word_sext; // FIXME: add X86II flag? - if (MO1.isGlobal()) { - bool Indirect = gvNeedsNonLazyPtr(MO1, TM); - emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, - Indirect); - } else if (MO1.isSymbol()) - emitExternalSymbolAddress(MO1.getSymbolName(), rt); - else if (MO1.isCPI()) - emitConstPoolAddress(MO1.getIndex(), rt); - else if (MO1.isJTI()) - emitJumpTableAddress(MO1.getIndex(), rt); + EmitRegModRMByte(MI.getOperand(CurOp++), + (TSFlags & X86II::FormMask)-X86II::MRM0r, + CurByte, OS); break; -#endif - } case X86II::MRM0m: case X86II::MRM1m: case X86II::MRM2m: case X86II::MRM3m: case X86II::MRM4m: case X86II::MRM5m: - case X86II::MRM6m: case X86II::MRM7m: { - intptr_t PCAdj = 0; - if (CurOp + X86AddrNumOperands != NumOps) { - if (MI.getOperand(CurOp+X86AddrNumOperands).isImm()) - PCAdj = X86II::getSizeOfImm(TSFlags); - else - PCAdj = 4; - } - + case X86II::MRM6m: case X86II::MRM7m: EmitByte(BaseOpcode, CurByte, OS); EmitMemModRMByte(MI, CurOp, (TSFlags & X86II::FormMask)-X86II::MRM0m, - PCAdj, CurByte, OS, Fixups); + TSFlags, CurByte, OS, Fixups); CurOp += X86AddrNumOperands; - - if (CurOp == NumOps) - break; - - const MCOperand &MO = MI.getOperand(CurOp++); - if (MO.isImm()) { - EmitConstant(MO.getImm(), X86II::getSizeOfImm(TSFlags), CurByte, OS); - break; - } - - assert(0 && "relo not handled"); -#if 0 - unsigned rt = Is64BitMode ? X86::reloc_pcrel_word - : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word); - if (Opcode == X86::MOV64mi32) - rt = X86::reloc_absolute_word_sext; // FIXME: add X86II flag? - if (MO.isGlobal()) { - bool Indirect = gvNeedsNonLazyPtr(MO, TM); - emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0, - Indirect); - } else if (MO.isSymbol()) - emitExternalSymbolAddress(MO.getSymbolName(), rt); - else if (MO.isCPI()) - emitConstPoolAddress(MO.getIndex(), rt); - else if (MO.isJTI()) - emitJumpTableAddress(MO.getIndex(), rt); -#endif + break; + case X86II::MRM_C1: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xC1, CurByte, OS); + break; + case X86II::MRM_C2: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xC2, CurByte, OS); + break; + case X86II::MRM_C3: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xC3, CurByte, OS); + break; + case X86II::MRM_C4: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xC4, CurByte, OS); + break; + case X86II::MRM_C8: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xC8, CurByte, OS); + break; + case X86II::MRM_C9: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xC9, CurByte, OS); + break; + case X86II::MRM_E8: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xE8, CurByte, OS); + break; + case X86II::MRM_F0: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xF0, CurByte, OS); + break; + case X86II::MRM_F8: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xF8, CurByte, OS); + break; + case X86II::MRM_F9: + EmitByte(BaseOpcode, CurByte, OS); + EmitByte(0xF9, CurByte, OS); break; } - } + + // If there is a remaining operand, it must be a trailing immediate. Emit it + // according to the right size for the instruction. + if (CurOp != NumOps) + EmitImmediate(MI.getOperand(CurOp++), + X86II::getSizeOfImm(TSFlags), getImmFixupKind(TSFlags), + CurByte, OS, Fixups); #ifndef NDEBUG // FIXME: Verify. diff --git a/lib/Target/X86/X86MachineFunctionInfo.h b/lib/Target/X86/X86MachineFunctionInfo.h index bb53bf14ce..4b2529bccf 100644 --- a/lib/Target/X86/X86MachineFunctionInfo.h +++ b/lib/Target/X86/X86MachineFunctionInfo.h @@ -18,12 +18,6 @@ namespace llvm { -enum NameDecorationStyle { - None, - StdCall, - FastCall -}; - /// X86MachineFunctionInfo - This class is derived from MachineFunction and /// contains private X86 target-specific information for each MachineFunction. class X86MachineFunctionInfo : public MachineFunctionInfo { @@ -41,10 +35,6 @@ class X86MachineFunctionInfo : public MachineFunctionInfo { /// Used on windows platform for stdcall & fastcall name decoration unsigned BytesToPopOnReturn; - /// DecorationStyle - If the function requires additional name decoration, - /// DecorationStyle holds the right way to do so. - NameDecorationStyle DecorationStyle; - /// ReturnAddrIndex - FrameIndex for return slot. int ReturnAddrIndex; @@ -66,7 +56,6 @@ public: X86MachineFunctionInfo() : ForceFramePointer(false), CalleeSavedFrameSize(0), BytesToPopOnReturn(0), - DecorationStyle(None), ReturnAddrIndex(0), TailCallReturnAddrDelta(0), SRetReturnReg(0), @@ -76,7 +65,6 @@ public: : ForceFramePointer(false), CalleeSavedFrameSize(0), BytesToPopOnReturn(0), - DecorationStyle(None), ReturnAddrIndex(0), TailCallReturnAddrDelta(0), SRetReturnReg(0), @@ -91,9 +79,6 @@ public: unsigned getBytesToPopOnReturn() const { return BytesToPopOnReturn; } void setBytesToPopOnReturn (unsigned bytes) { BytesToPopOnReturn = bytes;} - NameDecorationStyle getDecorationStyle() const { return DecorationStyle; } - void setDecorationStyle(NameDecorationStyle style) { DecorationStyle = style;} - int getRAIndex() const { return ReturnAddrIndex; } void setRAIndex(int Index) { ReturnAddrIndex = Index; } diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 081c6d9061..0f4ce37649 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -191,6 +191,8 @@ X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A, return &X86::GR16_NOREXRegClass; else if (A == &X86::GR16_ABCDRegClass) return &X86::GR16_ABCDRegClass; + } else if (B == &X86::FR32RegClass) { + return A; } break; case 2: @@ -207,6 +209,8 @@ X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A, else if (A == &X86::GR16RegClass || A == &X86::GR16_ABCDRegClass || A == &X86::GR16_NOREXRegClass) return &X86::GR16_ABCDRegClass; + } else if (B == &X86::FR64RegClass) { + return A; } break; case 3: @@ -234,6 +238,8 @@ X86RegisterInfo::getMatchingSuperRegClass(const TargetRegisterClass *A, return &X86::GR32_NOREXRegClass; else if (A == &X86::GR32_ABCDRegClass) return &X86::GR64_ABCDRegClass; + } else if (B == &X86::VR128RegClass) { + return A; } break; case 4: @@ -446,8 +452,10 @@ bool X86RegisterInfo::canRealignStack(const MachineFunction &MF) const { bool X86RegisterInfo::needsStackRealignment(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); + const Function *F = MF.getFunction(); bool requiresRealignment = - RealignStack && (MFI->getMaxAlignment() > StackAlign); + RealignStack && ((MFI->getMaxAlignment() > StackAlign) || + F->hasFnAttr(Attribute::StackAlignment)); // FIXME: Currently we don't support stack realignment for functions with // variable-sized allocas. @@ -485,7 +493,7 @@ X86RegisterInfo::getFrameIndexOffset(const MachineFunction &MF, int FI) const { Offset += SlotSize; } else { unsigned Align = MFI->getObjectAlignment(FI); - assert( (-(Offset + StackSize)) % Align == 0); + assert((-(Offset + StackSize)) % Align == 0); Align = 0; return Offset + StackSize; } @@ -627,10 +635,6 @@ X86RegisterInfo::processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineFrameInfo *MFI = MF.getFrameInfo(); - // Calculate and set max stack object alignment early, so we can decide - // whether we will need stack realignment (and thus FP). - MFI->calculateMaxStackAlignment(); - X86MachineFunctionInfo *X86FI = MF.getInfo(); int32_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); @@ -1053,7 +1057,8 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) .addImm(NumBytes); BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32)) - .addExternalSymbol("_alloca"); + .addExternalSymbol("_alloca") + .addReg(StackPtr, RegState::Define | RegState::Implicit); } else { // Save EAX BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r)) @@ -1064,7 +1069,8 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const { BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) .addImm(NumBytes - 4); BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32)) - .addExternalSymbol("_alloca"); + .addExternalSymbol("_alloca") + .addReg(StackPtr, RegState::Define | RegState::Implicit); // Restore EAX MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm), diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index 8fb5e9258b..e4bdb4e4c2 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -35,7 +35,8 @@ namespace X86 { /// these indices must be kept in sync with the class indices in the /// X86RegisterInfo.td file. enum SubregIndex { - SUBREG_8BIT = 1, SUBREG_8BIT_HI = 2, SUBREG_16BIT = 3, SUBREG_32BIT = 4 + SUBREG_8BIT = 1, SUBREG_8BIT_HI = 2, SUBREG_16BIT = 3, SUBREG_32BIT = 4, + SUBREG_SS = 1, SUBREG_SD = 2, SUBREG_XMM = 3 }; } diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index 1559bf7ce1..ed2ce6c353 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -158,22 +158,22 @@ let Namespace = "X86" in { def XMM15: Register<"xmm15">, DwarfRegNum<[32, -2, -2]>; // YMM Registers, used by AVX instructions - def YMM0: Register<"ymm0">, DwarfRegNum<[17, 21, 21]>; - def YMM1: Register<"ymm1">, DwarfRegNum<[18, 22, 22]>; - def YMM2: Register<"ymm2">, DwarfRegNum<[19, 23, 23]>; - def YMM3: Register<"ymm3">, DwarfRegNum<[20, 24, 24]>; - def YMM4: Register<"ymm4">, DwarfRegNum<[21, 25, 25]>; - def YMM5: Register<"ymm5">, DwarfRegNum<[22, 26, 26]>; - def YMM6: Register<"ymm6">, DwarfRegNum<[23, 27, 27]>; - def YMM7: Register<"ymm7">, DwarfRegNum<[24, 28, 28]>; - def YMM8: Register<"ymm8">, DwarfRegNum<[25, -2, -2]>; - def YMM9: Register<"ymm9">, DwarfRegNum<[26, -2, -2]>; - def YMM10: Register<"ymm10">, DwarfRegNum<[27, -2, -2]>; - def YMM11: Register<"ymm11">, DwarfRegNum<[28, -2, -2]>; - def YMM12: Register<"ymm12">, DwarfRegNum<[29, -2, -2]>; - def YMM13: Register<"ymm13">, DwarfRegNum<[30, -2, -2]>; - def YMM14: Register<"ymm14">, DwarfRegNum<[31, -2, -2]>; - def YMM15: Register<"ymm15">, DwarfRegNum<[32, -2, -2]>; + def YMM0: RegisterWithSubRegs<"ymm0", [XMM0]>, DwarfRegNum<[17, 21, 21]>; + def YMM1: RegisterWithSubRegs<"ymm1", [XMM1]>, DwarfRegNum<[18, 22, 22]>; + def YMM2: RegisterWithSubRegs<"ymm2", [XMM2]>, DwarfRegNum<[19, 23, 23]>; + def YMM3: RegisterWithSubRegs<"ymm3", [XMM3]>, DwarfRegNum<[20, 24, 24]>; + def YMM4: RegisterWithSubRegs<"ymm4", [XMM4]>, DwarfRegNum<[21, 25, 25]>; + def YMM5: RegisterWithSubRegs<"ymm5", [XMM5]>, DwarfRegNum<[22, 26, 26]>; + def YMM6: RegisterWithSubRegs<"ymm6", [XMM6]>, DwarfRegNum<[23, 27, 27]>; + def YMM7: RegisterWithSubRegs<"ymm7", [XMM7]>, DwarfRegNum<[24, 28, 28]>; + def YMM8: RegisterWithSubRegs<"ymm8", [XMM8]>, DwarfRegNum<[25, -2, -2]>; + def YMM9: RegisterWithSubRegs<"ymm9", [XMM9]>, DwarfRegNum<[26, -2, -2]>; + def YMM10: RegisterWithSubRegs<"ymm10", [XMM10]>, DwarfRegNum<[27, -2, -2]>; + def YMM11: RegisterWithSubRegs<"ymm11", [XMM11]>, DwarfRegNum<[28, -2, -2]>; + def YMM12: RegisterWithSubRegs<"ymm12", [XMM12]>, DwarfRegNum<[29, -2, -2]>; + def YMM13: RegisterWithSubRegs<"ymm13", [XMM13]>, DwarfRegNum<[30, -2, -2]>; + def YMM14: RegisterWithSubRegs<"ymm14", [XMM14]>, DwarfRegNum<[31, -2, -2]>; + def YMM15: RegisterWithSubRegs<"ymm15", [XMM15]>, DwarfRegNum<[32, -2, -2]>; // Floating point stack registers def ST0 : Register<"st(0)">, DwarfRegNum<[33, 12, 11]>; @@ -238,6 +238,10 @@ def x86_subreg_8bit_hi : PatLeaf<(i32 2)>; def x86_subreg_16bit : PatLeaf<(i32 3)>; def x86_subreg_32bit : PatLeaf<(i32 4)>; +def x86_subreg_ss : PatLeaf<(i32 1)>; +def x86_subreg_sd : PatLeaf<(i32 2)>; +def x86_subreg_xmm : PatLeaf<(i32 3)>; + def : SubRegSet<1, [AX, CX, DX, BX, SP, BP, SI, DI, R8W, R9W, R10W, R11W, R12W, R13W, R14W, R15W], [AL, CL, DL, BL, SPL, BPL, SIL, DIL, @@ -277,11 +281,31 @@ def : SubRegSet<4, [RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, [EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, R8D, R9D, R10D, R11D, R12D, R13D, R14D, R15D]>; -def : SubRegSet<1, [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, +def : SubRegSet<1, [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, + YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]>; + +def : SubRegSet<2, [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, + YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]>; + +def : SubRegSet<3, [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15], [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]>; +def : SubRegSet<1, [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]>; + +def : SubRegSet<2, [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15], + [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, + XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]>; + //===----------------------------------------------------------------------===// // Register Class Definitions... now that we have all of the pieces, define the // top-level register classes. The order specified in the register list is @@ -793,6 +817,7 @@ def VR128 : RegisterClass<"X86", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],128, [XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15]> { + let SubRegClassList = [FR32, FR64]; let MethodProtos = [{ iterator allocation_order_end(const MachineFunction &MF) const; }]; @@ -811,7 +836,9 @@ def VR128 : RegisterClass<"X86", [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64],128, def VR256 : RegisterClass<"X86", [ v8i32, v4i64, v8f32, v4f64],256, [YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, YMM8, YMM9, YMM10, YMM11, - YMM12, YMM13, YMM14, YMM15]>; + YMM12, YMM13, YMM14, YMM15]> { + let SubRegClassList = [FR32, FR64, VR128]; +} // Status flags registers. def CCR : RegisterClass<"X86", [i32], 32, [EFLAGS]> { diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h index 618dd102f3..594a470009 100644 --- a/lib/Target/X86/X86Subtarget.h +++ b/lib/Target/X86/X86Subtarget.h @@ -20,9 +20,9 @@ namespace llvm { class GlobalValue; class TargetMachine; - + /// PICStyles - The X86 backend supports a number of different styles of PIC. -/// +/// namespace PICStyles { enum Style { StubPIC, // Used on i386-darwin in -fPIC mode. @@ -46,7 +46,7 @@ protected: /// PICStyle - Which PIC style to use /// PICStyles::Style PICStyle; - + /// X86SSELevel - MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42, or /// none supported. X86SSEEnum X86SSELevel; @@ -58,7 +58,7 @@ protected: /// HasCMov - True if this processor has conditional move instructions /// (generally pentium pro+). bool HasCMov; - + /// HasX86_64 - True if the processor supports X86-64 instructions. /// bool HasX86_64; @@ -78,8 +78,9 @@ protected: /// IsBTMemSlow - True if BT (bit test) of memory instructions are slow. bool IsBTMemSlow; - /// HasVectorUAMem - True if SIMD operations can have unaligned memory operands. - /// This may require setting a feature bit in the processor. + /// HasVectorUAMem - True if SIMD operations can have unaligned memory + /// operands. This may require setting a feature bit in the + /// processor. bool HasVectorUAMem; /// DarwinVers - Nonzero if this is a darwin platform: the numeric @@ -150,20 +151,20 @@ public: bool isTargetDarwin() const { return TargetType == isDarwin; } bool isTargetELF() const { return TargetType == isELF; } - + bool isTargetWindows() const { return TargetType == isWindows; } bool isTargetMingw() const { return TargetType == isMingw; } bool isTargetCygwin() const { return TargetType == isCygwin; } bool isTargetCygMing() const { return TargetType == isMingw || TargetType == isCygwin; } - + /// isTargetCOFF - Return true if this is any COFF/Windows target variant. bool isTargetCOFF() const { return TargetType == isMingw || TargetType == isCygwin || TargetType == isWindows; } - + bool isTargetWin64() const { return Is64Bit && (TargetType == isMingw || TargetType == isWindows); } @@ -175,7 +176,7 @@ public: else if (isTargetDarwin()) p = "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-n8:16:32"; else if (isTargetMingw() || isTargetWindows()) - p = "e-p:32:32-f64:64:64-i64:64:64-f80:128:128-n8:16:32"; + p = "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32"; else p = "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"; @@ -196,11 +197,11 @@ public: bool isPICStyleStubAny() const { return PICStyle == PICStyles::StubDynamicNoPIC || PICStyle == PICStyles::StubPIC; } - + /// getDarwinVers - Return the darwin version number, 8 = Tiger, 9 = Leopard, /// 10 = Snow Leopard, etc. unsigned getDarwinVers() const { return DarwinVers; } - + /// ClassifyGlobalReference - Classify a global variable reference for the /// current subtarget according to how we should reference it in a non-pcrel /// context. diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index f835e295e6..56ddaf858a 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -30,9 +30,8 @@ static const MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) { case Triple::MinGW32: case Triple::MinGW64: case Triple::Cygwin: - return new X86MCAsmInfoCOFF(TheTriple); case Triple::Win32: - return new X86WinMCAsmInfo(TheTriple); + return new X86MCAsmInfoCOFF(TheTriple); default: return new X86ELFMCAsmInfo(TheTriple); } @@ -48,11 +47,16 @@ extern "C" void LLVMInitializeX86Target() { RegisterAsmInfoFn B(TheX86_64Target, createMCAsmInfo); // Register the code emitter. - // FIXME: Remove the heinous one when the new one works. TargetRegistry::RegisterCodeEmitter(TheX86_32Target, - createHeinousX86MCCodeEmitter); + createX86_32MCCodeEmitter); TargetRegistry::RegisterCodeEmitter(TheX86_64Target, - createHeinousX86MCCodeEmitter); + createX86_64MCCodeEmitter); + + // Register the asm backend. + TargetRegistry::RegisterAsmBackend(TheX86_32Target, + createX86_32AsmBackend); + TargetRegistry::RegisterAsmBackend(TheX86_64Target, + createX86_64AsmBackend); } @@ -201,32 +205,3 @@ void X86TargetMachine::setCodeModelForJIT() { else setCodeModel(CodeModel::Small); } - -/// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are 4-byte, -/// 8-byte, and target default. The CIE is hard-coded to indicate that the LSDA -/// pointer in the FDE section is an "sdata4", and should be encoded as a 4-byte -/// pointer by default. However, some systems may require a different size due -/// to bugs or other conditions. We will default to a 4-byte encoding unless the -/// system tells us otherwise. -/// -/// The issue is when the CIE says their is an LSDA. That mandates that every -/// FDE have an LSDA slot. But if the function does not need an LSDA. There -/// needs to be some way to signify there is none. The LSDA is encoded as -/// pc-rel. But you don't look for some magic value after adding the pc. You -/// have to look for a zero before adding the pc. The problem is that the size -/// of the zero to look for depends on the encoding. The unwinder bug in SL is -/// that it always checks for a pointer-size zero. So on x86_64 it looks for 8 -/// bytes of zero. If you have an LSDA, it works fine since the 8-bytes are -/// non-zero so it goes ahead and then reads the value based on the encoding. -/// But if you use sdata4 and there is no LSDA, then the test for zero gives a -/// false negative and the unwinder thinks there is an LSDA. -/// -/// FIXME: This call-back isn't good! We should be using the correct encoding -/// regardless of the system. However, there are some systems which have bugs -/// that prevent this from occuring. -DwarfLSDAEncoding::Encoding X86TargetMachine::getLSDAEncoding() const { - if (Subtarget.isTargetDarwin() && Subtarget.getDarwinVers() != 10) - return DwarfLSDAEncoding::Default; - - return DwarfLSDAEncoding::EightByte; -} diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h index eee29be59e..2bb54544d4 100644 --- a/lib/Target/X86/X86TargetMachine.h +++ b/lib/Target/X86/X86TargetMachine.h @@ -62,18 +62,6 @@ public: return Subtarget.isTargetELF() ? &ELFWriterInfo : 0; } - /// getLSDAEncoding - Returns the LSDA pointer encoding. The choices are - /// 4-byte, 8-byte, and target default. The CIE is hard-coded to indicate that - /// the LSDA pointer in the FDE section is an "sdata4", and should be encoded - /// as a 4-byte pointer by default. However, some systems may require a - /// different size due to bugs or other conditions. We will default to a - /// 4-byte encoding unless the system tells us otherwise. - /// - /// FIXME: This call-back isn't good! We should be using the correct encoding - /// regardless of the system. However, there are some systems which have bugs - /// that prevent this from occuring. - virtual DwarfLSDAEncoding::Encoding getLSDAEncoding() const; - // Set up the pass pipeline. virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); virtual bool addPreRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); diff --git a/lib/Target/X86/X86TargetObjectFile.cpp b/lib/Target/X86/X86TargetObjectFile.cpp index b8cef7def2..29a0be53f2 100644 --- a/lib/Target/X86/X86TargetObjectFile.cpp +++ b/lib/Target/X86/X86TargetObjectFile.cpp @@ -7,61 +7,112 @@ // //===----------------------------------------------------------------------===// -#include "X86TargetObjectFile.h" #include "X86MCTargetExpr.h" +#include "X86TargetObjectFile.h" +#include "X86TargetMachine.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/MC/MCContext.h" #include "llvm/Target/Mangler.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Support/Dwarf.h" using namespace llvm; +using namespace dwarf; -const MCExpr *X8632_MachoTargetObjectFile:: +const MCExpr *X8664_MachoTargetObjectFile:: getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, - bool &IsIndirect, bool &IsPCRel) const { - // The mach-o version of this method defaults to returning a stub reference. - IsIndirect = true; - IsPCRel = false; - - - MachineModuleInfoMachO &MachOMMI = - MMI->getObjFileInfo(); - - // FIXME: Use GetSymbolWithGlobalValueBase. - SmallString<128> Name; - Mang->getNameWithPrefix(Name, GV, true); - Name += "$non_lazy_ptr"; - - // Add information about the stub reference to MachOMMI so that the stub gets - // emitted by the asmprinter. - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name.str()); - MCSymbol *&StubSym = MachOMMI.getGVStubEntry(Sym); - if (StubSym == 0) { - Name.clear(); + MachineModuleInfo *MMI, unsigned Encoding) const { + + // On Darwin/X86-64, we can reference dwarf symbols with foo@GOTPCREL+4, which + // is an indirect pc-relative reference. + if (Encoding & (DW_EH_PE_indirect | DW_EH_PE_pcrel)) { + SmallString<128> Name; Mang->getNameWithPrefix(Name, GV, false); - StubSym = getContext().GetOrCreateSymbol(Name.str()); + const MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + const MCExpr *Res = + X86MCTargetExpr::Create(Sym, X86MCTargetExpr::GOTPCREL, getContext()); + const MCExpr *Four = MCConstantExpr::Create(4, getContext()); + return MCBinaryExpr::CreateAdd(Res, Four, getContext()); } - - return MCSymbolRefExpr::Create(Sym, getContext()); + + return TargetLoweringObjectFileMachO:: + getSymbolForDwarfGlobalReference(GV, Mang, MMI, Encoding); } -const MCExpr *X8664_MachoTargetObjectFile:: -getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, - bool &IsIndirect, bool &IsPCRel) const { - - // On Darwin/X86-64, we can reference dwarf symbols with foo@GOTPCREL+4, which - // is an indirect pc-relative reference. - IsIndirect = true; - IsPCRel = true; - - // FIXME: Use GetSymbolWithGlobalValueBase. - SmallString<128> Name; - Mang->getNameWithPrefix(Name, GV, false); - const MCSymbol *Sym = getContext().CreateSymbol(Name); - const MCExpr *Res = - X86MCTargetExpr::Create(Sym, X86MCTargetExpr::GOTPCREL, getContext()); - const MCExpr *Four = MCConstantExpr::Create(4, getContext()); - return MCBinaryExpr::CreateAdd(Res, Four, getContext()); +unsigned X8632_ELFTargetObjectFile::getPersonalityEncoding() const { + if (TM.getRelocationModel() == Reloc::PIC_) + return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; + else + return DW_EH_PE_absptr; +} + +unsigned X8632_ELFTargetObjectFile::getLSDAEncoding() const { + if (TM.getRelocationModel() == Reloc::PIC_) + return DW_EH_PE_pcrel | DW_EH_PE_sdata4; + else + return DW_EH_PE_absptr; +} + +unsigned X8632_ELFTargetObjectFile::getFDEEncoding() const { + if (TM.getRelocationModel() == Reloc::PIC_) + return DW_EH_PE_pcrel | DW_EH_PE_sdata4; + else + return DW_EH_PE_absptr; +} + +unsigned X8632_ELFTargetObjectFile::getTTypeEncoding() const { + if (TM.getRelocationModel() == Reloc::PIC_) + return DW_EH_PE_indirect | DW_EH_PE_pcrel | DW_EH_PE_sdata4; + else + return DW_EH_PE_absptr; +} + +unsigned X8664_ELFTargetObjectFile::getPersonalityEncoding() const { + CodeModel::Model Model = TM.getCodeModel(); + if (TM.getRelocationModel() == Reloc::PIC_) + return DW_EH_PE_indirect | DW_EH_PE_pcrel | (Model == CodeModel::Small || + Model == CodeModel::Medium ? + DW_EH_PE_sdata4 : DW_EH_PE_sdata8); + + if (Model == CodeModel::Small || Model == CodeModel::Medium) + return DW_EH_PE_udata4; + + return DW_EH_PE_absptr; +} + +unsigned X8664_ELFTargetObjectFile::getLSDAEncoding() const { + CodeModel::Model Model = TM.getCodeModel(); + if (TM.getRelocationModel() == Reloc::PIC_) + return DW_EH_PE_pcrel | (Model == CodeModel::Small ? + DW_EH_PE_sdata4 : DW_EH_PE_sdata8); + + if (Model == CodeModel::Small) + return DW_EH_PE_udata4; + + return DW_EH_PE_absptr; +} + +unsigned X8664_ELFTargetObjectFile::getFDEEncoding() const { + CodeModel::Model Model = TM.getCodeModel(); + if (TM.getRelocationModel() == Reloc::PIC_) + return DW_EH_PE_pcrel | (Model == CodeModel::Small || + Model == CodeModel::Medium ? + DW_EH_PE_sdata4 : DW_EH_PE_sdata8); + + if (Model == CodeModel::Small || Model == CodeModel::Medium) + return DW_EH_PE_udata4; + + return DW_EH_PE_absptr; } +unsigned X8664_ELFTargetObjectFile::getTTypeEncoding() const { + CodeModel::Model Model = TM.getCodeModel(); + if (TM.getRelocationModel() == Reloc::PIC_) + return DW_EH_PE_indirect | DW_EH_PE_pcrel | (Model == CodeModel::Small || + Model == CodeModel::Medium ? + DW_EH_PE_sdata4 : DW_EH_PE_sdata8); + + if (Model == CodeModel::Small) + return DW_EH_PE_udata4; + + return DW_EH_PE_absptr; +} diff --git a/lib/Target/X86/X86TargetObjectFile.h b/lib/Target/X86/X86TargetObjectFile.h index 377a93bb71..0444417154 100644 --- a/lib/Target/X86/X86TargetObjectFile.h +++ b/lib/Target/X86/X86TargetObjectFile.h @@ -10,21 +10,13 @@ #ifndef LLVM_TARGET_X86_TARGETOBJECTFILE_H #define LLVM_TARGET_X86_TARGETOBJECTFILE_H +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetLoweringObjectFile.h" namespace llvm { - - /// X8632_MachoTargetObjectFile - This TLOF implementation is used for - /// Darwin/x86-32. - class X8632_MachoTargetObjectFile : public TargetLoweringObjectFileMachO { - public: - - virtual const MCExpr * - getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, - bool &IsIndirect, bool &IsPCRel) const; - }; - + class X86TargetMachine; + /// X8664_MachoTargetObjectFile - This TLOF implementation is used for /// Darwin/x86-64. class X8664_MachoTargetObjectFile : public TargetLoweringObjectFileMachO { @@ -32,9 +24,31 @@ namespace llvm { virtual const MCExpr * getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang, - MachineModuleInfo *MMI, - bool &IsIndirect, bool &IsPCRel) const; + MachineModuleInfo *MMI, unsigned Encoding) const; + }; + + class X8632_ELFTargetObjectFile : public TargetLoweringObjectFileELF { + const X86TargetMachine &TM; + public: + X8632_ELFTargetObjectFile(const X86TargetMachine &tm) + :TM(tm) { } + virtual unsigned getPersonalityEncoding() const; + virtual unsigned getLSDAEncoding() const; + virtual unsigned getFDEEncoding() const; + virtual unsigned getTTypeEncoding() const; + }; + + class X8664_ELFTargetObjectFile : public TargetLoweringObjectFileELF { + const X86TargetMachine &TM; + public: + X8664_ELFTargetObjectFile(const X86TargetMachine &tm) + :TM(tm) { } + virtual unsigned getPersonalityEncoding() const; + virtual unsigned getLSDAEncoding() const; + virtual unsigned getFDEEncoding() const; + virtual unsigned getTTypeEncoding() const; }; + } // end namespace llvm #endif diff --git a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp index d18f55de81..82e23a13e8 100644 --- a/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp +++ b/lib/Target/XCore/AsmPrinter/XCoreAsmPrinter.cpp @@ -27,6 +27,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetData.h" @@ -62,6 +63,11 @@ namespace { } void printMemOperand(const MachineInstr *MI, int opNum); + void printInlineJT(const MachineInstr *MI, int opNum, + const std::string &directive = ".jmptable"); + void printInlineJT32(const MachineInstr *MI, int opNum) { + printInlineJT(MI, opNum, ".jmptable32"); + } void printOperand(const MachineInstr *MI, int opNum); bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode); @@ -257,6 +263,23 @@ void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) printOperand(MI, opNum+1); } +void XCoreAsmPrinter:: +printInlineJT(const MachineInstr *MI, int opNum, const std::string &directive) +{ + unsigned JTI = MI->getOperand(opNum).getIndex(); + const MachineFunction *MF = MI->getParent()->getParent(); + const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); + const std::vector &JT = MJTI->getJumpTables(); + const std::vector &JTBBs = JT[JTI].MBBs; + O << "\t" << directive << " "; + for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) { + MachineBasicBlock *MBB = JTBBs[i]; + if (i > 0) + O << ","; + O << *MBB->getSymbol(OutContext); + } +} + void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { const MachineOperand &MO = MI->getOperand(opNum); switch (MO.getType()) { diff --git a/lib/Target/XCore/XCoreISelDAGToDAG.cpp b/lib/Target/XCore/XCoreISelDAGToDAG.cpp index 383fd91d2e..b1ab13272f 100644 --- a/lib/Target/XCore/XCoreISelDAGToDAG.cpp +++ b/lib/Target/XCore/XCoreISelDAGToDAG.cpp @@ -65,8 +65,6 @@ namespace { bool SelectADDRcpii(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset); - virtual void InstructionSelect(); - virtual const char *getPassName() const { return "XCore DAG->DAG Pattern Instruction Selection"; } @@ -147,15 +145,6 @@ bool XCoreDAGToDAGISel::SelectADDRcpii(SDNode *Op, SDValue Addr, return false; } -/// InstructionSelect - This callback is invoked by -/// SelectionDAGISel when it has created a SelectionDAG for us to codegen. -void XCoreDAGToDAGISel::InstructionSelect() { - // Select target instructions for the DAG. - SelectRoot(*CurDAG); - - CurDAG->RemoveDeadNodes(); -} - SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { DebugLoc dl = N->getDebugLoc(); EVT NVT = N->getValueType(0); @@ -164,7 +153,11 @@ SDNode *XCoreDAGToDAGISel::Select(SDNode *N) { default: break; case ISD::Constant: { if (Predicate_immMskBitp(N)) { - SDValue MskSize = Transform_msksize_xform(N); + // Transformation function: get the size of a mask + int64_t MaskVal = cast(N)->getZExtValue(); + assert(isMask_32(MaskVal)); + // Look for the first non-zero bit + SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(MaskVal)); return CurDAG->getMachineNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize); } diff --git a/lib/Target/XCore/XCoreISelLowering.cpp b/lib/Target/XCore/XCoreISelLowering.cpp index bf8c38fbdd..e6515d821b 100644 --- a/lib/Target/XCore/XCoreISelLowering.cpp +++ b/lib/Target/XCore/XCoreISelLowering.cpp @@ -29,6 +29,7 @@ #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/CodeGen/ValueTypes.h" @@ -53,6 +54,8 @@ getTargetNodeName(unsigned Opcode) const case XCoreISD::RETSP : return "XCoreISD::RETSP"; case XCoreISD::LADD : return "XCoreISD::LADD"; case XCoreISD::LSUB : return "XCoreISD::LSUB"; + case XCoreISD::BR_JT : return "XCoreISD::BR_JT"; + case XCoreISD::BR_JT32 : return "XCoreISD::BR_JT32"; default : return NULL; } } @@ -106,9 +109,8 @@ XCoreTargetLowering::XCoreTargetLowering(XCoreTargetMachine &XTM) setOperationAction(ISD::TRAP, MVT::Other, Legal); - // Expand jump tables for now - setOperationAction(ISD::BR_JT, MVT::Other, Expand); - setOperationAction(ISD::JumpTable, MVT::i32, Custom); + // Jump tables. + setOperationAction(ISD::BR_JT, MVT::Other, Custom); setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); setOperationAction(ISD::BlockAddress, MVT::i32 , Custom); @@ -157,7 +159,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG); case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); case ISD::ConstantPool: return LowerConstantPool(Op, DAG); - case ISD::JumpTable: return LowerJumpTable(Op, DAG); + case ISD::BR_JT: return LowerBR_JT(Op, DAG); case ISD::LOAD: return LowerLOAD(Op, DAG); case ISD::STORE: return LowerSTORE(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); @@ -315,14 +317,27 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) } SDValue XCoreTargetLowering:: -LowerJumpTable(SDValue Op, SelectionDAG &DAG) +LowerBR_JT(SDValue Op, SelectionDAG &DAG) { - // FIXME there isn't really debug info here + SDValue Chain = Op.getOperand(0); + SDValue Table = Op.getOperand(1); + SDValue Index = Op.getOperand(2); DebugLoc dl = Op.getDebugLoc(); - EVT PtrVT = Op.getValueType(); - JumpTableSDNode *JT = cast(Op); - SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); - return DAG.getNode(XCoreISD::DPRelativeWrapper, dl, MVT::i32, JTI); + JumpTableSDNode *JT = cast(Table); + unsigned JTI = JT->getIndex(); + MachineFunction &MF = DAG.getMachineFunction(); + const MachineJumpTableInfo *MJTI = MF.getJumpTableInfo(); + SDValue TargetJT = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32); + + unsigned NumEntries = MJTI->getJumpTables()[JTI].MBBs.size(); + if (NumEntries <= 32) { + return DAG.getNode(XCoreISD::BR_JT, dl, MVT::Other, Chain, TargetJT, Index); + } + assert((NumEntries >> 31) == 0); + SDValue ScaledIndex = DAG.getNode(ISD::SHL, dl, MVT::i32, Index, + DAG.getConstant(1, MVT::i32)); + return DAG.getNode(XCoreISD::BR_JT32, dl, MVT::Other, Chain, TargetJT, + ScaledIndex); } static bool @@ -390,7 +405,12 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) if (Offset % 4 == 0) { // We've managed to infer better alignment information than the load // already has. Use an aligned load. - return DAG.getLoad(getPointerTy(), dl, Chain, BasePtr, NULL, 4); + // + // FIXME: No new alignment information is actually passed here. + // Should the offset really be 4? + // + return DAG.getLoad(getPointerTy(), dl, Chain, BasePtr, NULL, 4, + false, false, 0); } // Lower to // ldw low, base[offset >> 2] @@ -407,9 +427,9 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, Base, HighOffset); SDValue Low = DAG.getLoad(getPointerTy(), dl, Chain, - LowAddr, NULL, 4); + LowAddr, NULL, 4, false, false, 0); SDValue High = DAG.getLoad(getPointerTy(), dl, Chain, - HighAddr, NULL, 4); + HighAddr, NULL, 4, false, false, 0); SDValue LowShifted = DAG.getNode(ISD::SRL, dl, MVT::i32, Low, LowShift); SDValue HighShifted = DAG.getNode(ISD::SHL, dl, MVT::i32, High, HighShift); SDValue Result = DAG.getNode(ISD::OR, dl, MVT::i32, LowShifted, HighShifted); @@ -423,12 +443,13 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) int SVOffset = LD->getSrcValueOffset(); SDValue Low = DAG.getExtLoad(ISD::ZEXTLOAD, dl, MVT::i32, Chain, BasePtr, LD->getSrcValue(), SVOffset, MVT::i16, - LD->isVolatile(), 2); + LD->isVolatile(), LD->isNonTemporal(), 2); SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, DAG.getConstant(2, MVT::i32)); SDValue High = DAG.getExtLoad(ISD::EXTLOAD, dl, MVT::i32, Chain, HighAddr, LD->getSrcValue(), SVOffset + 2, - MVT::i16, LD->isVolatile(), 2); + MVT::i16, LD->isVolatile(), + LD->isNonTemporal(), 2); SDValue HighShifted = DAG.getNode(ISD::SHL, dl, MVT::i32, High, DAG.getConstant(16, MVT::i32)); SDValue Result = DAG.getNode(ISD::OR, dl, MVT::i32, Low, HighShifted); @@ -452,7 +473,7 @@ LowerLOAD(SDValue Op, SelectionDAG &DAG) false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/true, DAG.getExternalSymbol("__misaligned_load", getPointerTy()), - Args, DAG, dl, DAG.GetOrdering(Chain.getNode())); + Args, DAG, dl); SDValue Ops[] = { CallResult.first, CallResult.second }; @@ -487,12 +508,14 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) DAG.getConstant(16, MVT::i32)); SDValue StoreLow = DAG.getTruncStore(Chain, dl, Low, BasePtr, ST->getSrcValue(), SVOffset, MVT::i16, - ST->isVolatile(), 2); + ST->isVolatile(), ST->isNonTemporal(), + 2); SDValue HighAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, BasePtr, DAG.getConstant(2, MVT::i32)); SDValue StoreHigh = DAG.getTruncStore(Chain, dl, High, HighAddr, ST->getSrcValue(), SVOffset + 2, - MVT::i16, ST->isVolatile(), 2); + MVT::i16, ST->isVolatile(), + ST->isNonTemporal(), 2); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, StoreLow, StoreHigh); } @@ -513,7 +536,7 @@ LowerSTORE(SDValue Op, SelectionDAG &DAG) false, false, 0, CallingConv::C, false, /*isReturnValueUsed=*/true, DAG.getExternalSymbol("__misaligned_store", getPointerTy()), - Args, DAG, dl, DAG.GetOrdering(Chain.getNode())); + Args, DAG, dl); return CallResult.second; } @@ -561,15 +584,16 @@ LowerVAARG(SDValue Op, SelectionDAG &DAG) const Value *V = cast(Node->getOperand(2))->getValue(); EVT VT = Node->getValueType(0); SDValue VAList = DAG.getLoad(getPointerTy(), dl, Node->getOperand(0), - Node->getOperand(1), V, 0); + Node->getOperand(1), V, 0, false, false, 0); // Increment the pointer, VAList, to the next vararg SDValue Tmp3 = DAG.getNode(ISD::ADD, dl, getPointerTy(), VAList, DAG.getConstant(VT.getSizeInBits(), getPointerTy())); // Store the incremented VAList to the legalized pointer - Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1), V, 0); + Tmp3 = DAG.getStore(VAList.getValue(1), dl, Tmp3, Node->getOperand(1), V, 0, + false, false, 0); // Load the actual argument out of the pointer VAList - return DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0); + return DAG.getLoad(VT, dl, Tmp3, VAList, NULL, 0, false, false, 0); } SDValue XCoreTargetLowering:: @@ -582,7 +606,8 @@ LowerVASTART(SDValue Op, SelectionDAG &DAG) XCoreFunctionInfo *XFI = MF.getInfo(); SDValue Addr = DAG.getFrameIndex(XFI->getVarArgsFrameIndex(), MVT::i32); const Value *SV = cast(Op.getOperand(2))->getValue(); - return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), SV, 0); + return DAG.getStore(Op.getOperand(0), dl, Addr, Op.getOperand(1), SV, 0, + false, false, 0); } SDValue XCoreTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { @@ -877,7 +902,8 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, // Create the SelectionDAG nodes corresponding to a load //from this parameter SDValue FIN = DAG.getFrameIndex(FI, MVT::i32); - InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, NULL, 0)); + InVals.push_back(DAG.getLoad(VA.getLocVT(), dl, Chain, FIN, NULL, 0, + false, false, 0)); } } @@ -908,7 +934,8 @@ XCoreTargetLowering::LowerCCCArguments(SDValue Chain, RegInfo.addLiveIn(ArgRegs[i], VReg); SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); // Move argument from virt reg -> stack - SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); + SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0, + false, false, 0); MemOps.push_back(Store); } if (!MemOps.empty()) @@ -1134,10 +1161,8 @@ static inline bool isImmUs4(int64_t val) bool XCoreTargetLowering::isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const { - // Be conservative with void - // FIXME: Can we be more aggressive? if (Ty->getTypeID() == Type::VoidTyID) - return false; + return AM.Scale == 0 && isImmUs(AM.BaseOffs) && isImmUs4(AM.BaseOffs); const TargetData *TD = TM.getTargetData(); unsigned Size = TD->getTypeAllocSize(Ty); diff --git a/lib/Target/XCore/XCoreISelLowering.h b/lib/Target/XCore/XCoreISelLowering.h index f7b620e5fb..0c638aff48 100644 --- a/lib/Target/XCore/XCoreISelLowering.h +++ b/lib/Target/XCore/XCoreISelLowering.h @@ -28,7 +28,7 @@ namespace llvm { namespace XCoreISD { enum NodeType { // Start the numbering where the builtin ops and target ops leave off. - FIRST_NUMBER = ISD::BUILTIN_OP_END+XCore::INSTRUCTION_LIST_END, + FIRST_NUMBER = ISD::BUILTIN_OP_END, // Branch and link (call) BL, @@ -52,7 +52,13 @@ namespace llvm { LADD, // Corresponds to LSUB instruction - LSUB + LSUB, + + // Jumptable branch. + BR_JT, + + // Jumptable branch using long branches for each entry. + BR_JT32 }; } @@ -122,7 +128,7 @@ namespace llvm { SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG); SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG); - SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG); + SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG); SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG); SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG); diff --git a/lib/Target/XCore/XCoreInstrInfo.cpp b/lib/Target/XCore/XCoreInstrInfo.cpp index 5a548449d8..722e7470f0 100644 --- a/lib/Target/XCore/XCoreInstrInfo.cpp +++ b/lib/Target/XCore/XCoreInstrInfo.cpp @@ -145,6 +145,11 @@ static inline bool IsCondBranch(unsigned BrOpc) { return IsBRF(BrOpc) || IsBRT(BrOpc); } +static inline bool IsBR_JT(unsigned BrOpc) { + return BrOpc == XCore::BR_JT + || BrOpc == XCore::BR_JT32; +} + /// GetCondFromBranchOpc - Return the XCore CC that matches /// the correspondent Branch instruction opcode. static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc) @@ -271,6 +276,14 @@ XCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, return false; } + // Likewise if it ends with a branch table followed by an unconditional branch. + if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) { + I = LastInst; + if (AllowModify) + I->eraseFromParent(); + return true; + } + // Otherwise, can't handle this. return true; } diff --git a/lib/Target/XCore/XCoreInstrInfo.td b/lib/Target/XCore/XCoreInstrInfo.td index 10dc18cfea..46805d59ae 100644 --- a/lib/Target/XCore/XCoreInstrInfo.td +++ b/lib/Target/XCore/XCoreInstrInfo.td @@ -34,6 +34,15 @@ def XCoreBranchLink : SDNode<"XCoreISD::BL",SDT_XCoreBranchLink, def XCoreRetsp : SDNode<"XCoreISD::RETSP", SDTNone, [SDNPHasChain, SDNPOptInFlag]>; +def SDT_XCoreBR_JT : SDTypeProfile<0, 2, + [SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; + +def XCoreBR_JT : SDNode<"XCoreISD::BR_JT", SDT_XCoreBR_JT, + [SDNPHasChain]>; + +def XCoreBR_JT32 : SDNode<"XCoreISD::BR_JT32", SDT_XCoreBR_JT, + [SDNPHasChain]>; + def SDT_XCoreAddress : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>; @@ -185,6 +194,15 @@ def MEMii : Operand { let MIOperandInfo = (ops i32imm, i32imm); } +// Jump tables. +def InlineJT : Operand { + let PrintMethod = "printInlineJT"; +} + +def InlineJT32 : Operand { + let PrintMethod = "printInlineJT32"; +} + //===----------------------------------------------------------------------===// // Instruction Class Templates //===----------------------------------------------------------------------===// @@ -624,7 +642,7 @@ defm RETSP : FU6_LU6<"retsp", XCoreRetsp>; // TODO extdp, kentsp, krestsp, blat, setsr // clrsr, getsr, kalli -let isBranch = 1, isTerminator = 1 in { +let isBranch = 1, isTerminator = 1, isBarrier = 1 in { def BRBU_u6 : _FU6< (outs), (ins brtarget:$target), @@ -756,24 +774,34 @@ def CLZ_l2r : _FL2R<(outs GRRegs:$dst), (ins GRRegs:$src), // One operand short // TODO edu, eeu, waitet, waitef, freer, tstart, msync, mjoin, syncr, clrtp -// bru, setdp, setcp, setv, setev, kcall +// setdp, setcp, setv, setev, kcall // dgetreg -let isBranch=1, isIndirectBranch=1, isTerminator=1 in +let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in def BAU_1r : _F1R<(outs), (ins GRRegs:$addr), "bau $addr", [(brind GRRegs:$addr)]>; +let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in +def BR_JT : PseudoInstXCore<(outs), (ins InlineJT:$t, GRRegs:$i), + "bru $i\n$t", + [(XCoreBR_JT tjumptable:$t, GRRegs:$i)]>; + +let isBranch=1, isIndirectBranch=1, isTerminator=1, isBarrier = 1 in +def BR_JT32 : PseudoInstXCore<(outs), (ins InlineJT32:$t, GRRegs:$i), + "bru $i\n$t", + [(XCoreBR_JT32 tjumptable:$t, GRRegs:$i)]>; + let Defs=[SP], neverHasSideEffects=1 in def SETSP_1r : _F1R<(outs), (ins GRRegs:$src), "set sp, $src", []>; -let isBarrier = 1, hasCtrlDep = 1 in +let hasCtrlDep = 1 in def ECALLT_1r : _F1R<(outs), (ins GRRegs:$src), "ecallt $src", []>; -let isBarrier = 1, hasCtrlDep = 1 in +let hasCtrlDep = 1 in def ECALLF_1r : _F1R<(outs), (ins GRRegs:$src), "ecallf $src", []>; diff --git a/lib/Target/XCore/XCoreTargetObjectFile.h b/lib/Target/XCore/XCoreTargetObjectFile.h index 7efb990b79..7424c78be3 100644 --- a/lib/Target/XCore/XCoreTargetObjectFile.h +++ b/lib/Target/XCore/XCoreTargetObjectFile.h @@ -10,13 +10,12 @@ #ifndef LLVM_TARGET_XCORE_TARGETOBJECTFILE_H #define LLVM_TARGET_XCORE_TARGETOBJECTFILE_H -#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" namespace llvm { class XCoreTargetObjectFile : public TargetLoweringObjectFileELF { public: - void Initialize(MCContext &Ctx, const TargetMachine &TM); // TODO: Classify globals as xcore wishes. diff --git a/lib/Transforms/Hello/Hello.cpp b/lib/Transforms/Hello/Hello.cpp index eac4e17b15..37d7a00396 100644 --- a/lib/Transforms/Hello/Hello.cpp +++ b/lib/Transforms/Hello/Hello.cpp @@ -15,7 +15,6 @@ #define DEBUG_TYPE "hello" #include "llvm/Pass.h" #include "llvm/Function.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/Statistic.h" using namespace llvm; diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp index 325d353f39..7cb13671bc 100644 --- a/lib/Transforms/IPO/ArgumentPromotion.cpp +++ b/lib/Transforms/IPO/ArgumentPromotion.cpp @@ -124,7 +124,7 @@ CallGraphNode *ArgPromotion::PromoteArguments(CallGraphNode *CGN) { unsigned ArgNo = 0; for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I, ++ArgNo) - if (isa(I->getType())) + if (I->getType()->isPointerTy()) PointerArgs.push_back(std::pair(I, ArgNo)); if (PointerArgs.empty()) return 0; @@ -317,7 +317,7 @@ bool ArgPromotion::isSafeToPromoteArgument(Argument *Arg, bool isByVal) const { GEPIndicesSet ToPromote; // If the pointer is always valid, any load with first index 0 is valid. - if(isByVal || AllCalleesPassInValidPointerForArgument(Arg)) + if (isByVal || AllCalleesPassInValidPointerForArgument(Arg)) SafeToUnconditionallyLoad.insert(IndicesVector(1, 0)); // First, iterate the entry block and mark loads of (geps of) arguments as @@ -673,7 +673,7 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F, IE = SI->end(); II != IE; ++II) { // Use i32 to index structs, and i64 for others (pointers/arrays). // This satisfies GEP constraints. - const Type *IdxTy = (isa(ElTy) ? + const Type *IdxTy = (ElTy->isStructTy() ? Type::getInt32Ty(F->getContext()) : Type::getInt64Ty(F->getContext())); Ops.push_back(ConstantInt::get(IdxTy, *II)); diff --git a/lib/Transforms/IPO/ConstantMerge.cpp b/lib/Transforms/IPO/ConstantMerge.cpp index 4972687406..3c05f88027 100644 --- a/lib/Transforms/IPO/ConstantMerge.cpp +++ b/lib/Transforms/IPO/ConstantMerge.cpp @@ -19,10 +19,11 @@ #define DEBUG_TYPE "constmerge" #include "llvm/Transforms/IPO.h" +#include "llvm/DerivedTypes.h" #include "llvm/Module.h" #include "llvm/Pass.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Statistic.h" -#include using namespace llvm; STATISTIC(NumMerged, "Number of global constants merged"); @@ -48,10 +49,10 @@ ModulePass *llvm::createConstantMergePass() { return new ConstantMerge(); } bool ConstantMerge::runOnModule(Module &M) { // Map unique constant/section pairs to globals. We don't want to merge // globals in different sections. - std::map, GlobalVariable*> CMap; + DenseMap CMap; // Replacements - This vector contains a list of replacements to perform. - std::vector > Replacements; + SmallVector, 32> Replacements; bool MadeChange = false; @@ -76,19 +77,21 @@ bool ConstantMerge::runOnModule(Module &M) { continue; } - // Only process constants with initializers. - if (GV->isConstant() && GV->hasDefinitiveInitializer()) { - Constant *Init = GV->getInitializer(); - - // Check to see if the initializer is already known. - GlobalVariable *&Slot = CMap[std::make_pair(Init, GV->getSection())]; - - if (Slot == 0) { // Nope, add it to the map. - Slot = GV; - } else if (GV->hasLocalLinkage()) { // Yup, this is a duplicate! - // Make all uses of the duplicate constant use the canonical version. - Replacements.push_back(std::make_pair(GV, Slot)); - } + // Only process constants with initializers in the default addres space. + if (!GV->isConstant() ||!GV->hasDefinitiveInitializer() || + GV->getType()->getAddressSpace() != 0 || !GV->getSection().empty()) + continue; + + Constant *Init = GV->getInitializer(); + + // Check to see if the initializer is already known. + GlobalVariable *&Slot = CMap[Init]; + + if (Slot == 0) { // Nope, add it to the map. + Slot = GV; + } else if (GV->hasLocalLinkage()) { // Yup, this is a duplicate! + // Make all uses of the duplicate constant use the canonical version. + Replacements.push_back(std::make_pair(GV, Slot)); } } @@ -100,11 +103,11 @@ bool ConstantMerge::runOnModule(Module &M) { // now. This avoid invalidating the pointers in CMap, which are unneeded // now. for (unsigned i = 0, e = Replacements.size(); i != e; ++i) { - // Eliminate any uses of the dead global... + // Eliminate any uses of the dead global. Replacements[i].first->replaceAllUsesWith(Replacements[i].second); - // Delete the global value from the module... - M.getGlobalList().erase(Replacements[i].first); + // Delete the global value from the module. + Replacements[i].first->eraseFromParent(); } NumMerged += Replacements.size(); diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 1749b1eff3..f386ed78b5 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -796,7 +796,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { // Replace by null for now. Call->replaceAllUsesWith(Constant::getNullValue(Call->getType())); } else { - assert(isa(RetTy) && + assert(RetTy->isStructTy() && "Return type changed, but not into a void. The old return type" " must have been a struct!"); Instruction *InsertPt = Call; @@ -870,7 +870,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { if (NFTy->getReturnType() == Type::getVoidTy(F->getContext())) { RetVal = 0; } else { - assert (isa(RetTy)); + assert (RetTy->isStructTy()); // The original return value was a struct, insert // extractvalue/insertvalue chains to extract only the values we need // to return and insert them into our new result. diff --git a/lib/Transforms/IPO/DeadTypeElimination.cpp b/lib/Transforms/IPO/DeadTypeElimination.cpp index 025d77e0c8..662fbb5cd4 100644 --- a/lib/Transforms/IPO/DeadTypeElimination.cpp +++ b/lib/Transforms/IPO/DeadTypeElimination.cpp @@ -57,13 +57,13 @@ ModulePass *llvm::createDeadTypeEliminationPass() { // static inline bool ShouldNukeSymtabEntry(const Type *Ty){ // Nuke all names for primitive types! - if (Ty->isPrimitiveType() || Ty->isInteger()) + if (Ty->isPrimitiveType() || Ty->isIntegerTy()) return true; // Nuke all pointers to primitive types as well... if (const PointerType *PT = dyn_cast(Ty)) if (PT->getElementType()->isPrimitiveType() || - PT->getElementType()->isInteger()) + PT->getElementType()->isIntegerTy()) return true; return false; diff --git a/lib/Transforms/IPO/FunctionAttrs.cpp b/lib/Transforms/IPO/FunctionAttrs.cpp index 64a6d78096..298d5cf391 100644 --- a/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/lib/Transforms/IPO/FunctionAttrs.cpp @@ -175,7 +175,7 @@ bool FunctionAttrs::AddReadAttrs(const std::vector &SCC) { for (CallSite::arg_iterator CI = CS.arg_begin(), CE = CS.arg_end(); CI != CE; ++CI) { Value *Arg = *CI; - if (isa(Arg->getType()) && !PointsToLocalMemory(Arg)) + if (Arg->getType()->isPointerTy() && !PointsToLocalMemory(Arg)) // Writes memory. Just give up. return false; } @@ -257,7 +257,7 @@ bool FunctionAttrs::AddNoCaptureAttrs(const std::vector &SCC) { continue; for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A) - if (isa(A->getType()) && !A->hasNoCaptureAttr() && + if (A->getType()->isPointerTy() && !A->hasNoCaptureAttr() && !PointerMayBeCaptured(A, true, /*StoreCaptures=*/false)) { A->addAttr(Attribute::NoCapture); ++NumNoCapture; @@ -362,7 +362,7 @@ bool FunctionAttrs::AddNoAliasAttrs(const std::vector &SCC) { // We annotate noalias return values, which are only applicable to // pointer types. - if (!isa(F->getReturnType())) + if (!F->getReturnType()->isPointerTy()) continue; if (!IsFunctionMallocLike(F, SCCNodes)) @@ -372,7 +372,7 @@ bool FunctionAttrs::AddNoAliasAttrs(const std::vector &SCC) { bool MadeChange = false; for (unsigned i = 0, e = SCC.size(); i != e; ++i) { Function *F = SCC[i]->getFunction(); - if (F->doesNotAlias(0) || !isa(F->getReturnType())) + if (F->doesNotAlias(0) || !F->getReturnType()->isPointerTy()) continue; F->setDoesNotAlias(0); diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index ac91631f56..7b1e9c0efd 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -303,7 +303,7 @@ static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) { SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE); Changed |= CleanupConstantGlobalUsers(CE, SubInit); } else if (CE->getOpcode() == Instruction::BitCast && - isa(CE->getType())) { + CE->getType()->isPointerTy()) { // Pointer cast, delete any stores and memsets to the global. Changed |= CleanupConstantGlobalUsers(CE, 0); } @@ -431,7 +431,7 @@ static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) { else if (const VectorType *SubVectorTy = dyn_cast(*GEPI)) NumElements = SubVectorTy->getNumElements(); else { - assert(isa(*GEPI) && + assert((*GEPI)->isStructTy() && "Indexed GEP type is not array, vector, or struct!"); continue; } @@ -543,7 +543,7 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) { if (NewGlobals.empty()) return 0; - + DEBUG(dbgs() << "PERFORMING GLOBAL SRA ON: " << *GV); Constant *NullInt =Constant::getNullValue(Type::getInt32Ty(GV->getContext())); @@ -642,7 +642,7 @@ static bool AllUsesOfValueWillTrapIfNull(Value *V, return false; } else if (isa(*UI) && isa(UI->getOperand(1))) { - // Ignore setcc X, null + // Ignore icmp X, null } else { //cerr << "NONTRAPPING USE: " << **UI; return false; @@ -813,57 +813,47 @@ static void ConstantPropUsersOf(Value *V) { static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV, CallInst *CI, const Type *AllocTy, - Value* NElems, + ConstantInt *NElements, TargetData* TD) { - DEBUG(dbgs() << "PROMOTING GLOBAL: " << *GV << " CALL = " << *CI << '\n'); - - const Type *IntPtrTy = TD->getIntPtrType(GV->getContext()); + DEBUG(errs() << "PROMOTING GLOBAL: " << *GV << " CALL = " << *CI << '\n'); - // CI has either 0 or 1 bitcast uses (getMallocType() would otherwise have - // returned NULL and we would not be here). - BitCastInst *BCI = NULL; - for (Value::use_iterator UI = CI->use_begin(), E = CI->use_end(); UI != E; ) - if ((BCI = dyn_cast(cast(*UI++)))) - break; - - ConstantInt *NElements = cast(NElems); - if (NElements->getZExtValue() != 1) { - // If we have an array allocation, transform it to a single element - // allocation to make the code below simpler. - Type *NewTy = ArrayType::get(AllocTy, NElements->getZExtValue()); - unsigned TypeSize = TD->getTypeAllocSize(NewTy); - if (const StructType *ST = dyn_cast(NewTy)) - TypeSize = TD->getStructLayout(ST)->getSizeInBytes(); - Instruction *NewCI = CallInst::CreateMalloc(CI, IntPtrTy, NewTy, - ConstantInt::get(IntPtrTy, TypeSize)); - Value* Indices[2]; - Indices[0] = Indices[1] = Constant::getNullValue(IntPtrTy); - Value *NewGEP = GetElementPtrInst::Create(NewCI, Indices, Indices + 2, - NewCI->getName()+".el0", CI); - Value *Cast = new BitCastInst(NewGEP, CI->getType(), "el0", CI); - if (BCI) BCI->replaceAllUsesWith(NewGEP); - CI->replaceAllUsesWith(Cast); - if (BCI) BCI->eraseFromParent(); - CI->eraseFromParent(); - BCI = dyn_cast(NewCI); - CI = BCI ? extractMallocCallFromBitCast(BCI) : cast(NewCI); - } + const Type *GlobalType; + if (NElements->getZExtValue() == 1) + GlobalType = AllocTy; + else + // If we have an array allocation, the global variable is of an array. + GlobalType = ArrayType::get(AllocTy, NElements->getZExtValue()); // Create the new global variable. The contents of the malloc'd memory is // undefined, so initialize with an undef value. - const Type *MAT = getMallocAllocatedType(CI); - Constant *Init = UndefValue::get(MAT); GlobalVariable *NewGV = new GlobalVariable(*GV->getParent(), - MAT, false, - GlobalValue::InternalLinkage, Init, + GlobalType, false, + GlobalValue::InternalLinkage, + UndefValue::get(GlobalType), GV->getName()+".body", GV, GV->isThreadLocal()); - // Anything that used the malloc or its bitcast now uses the global directly. - if (BCI) BCI->replaceAllUsesWith(NewGV); - CI->replaceAllUsesWith(new BitCastInst(NewGV, CI->getType(), "newgv", CI)); - + // If there are bitcast users of the malloc (which is typical, usually we have + // a malloc + bitcast) then replace them with uses of the new global. Update + // other users to use the global as well. + BitCastInst *TheBC = 0; + while (!CI->use_empty()) { + Instruction *User = cast(CI->use_back()); + if (BitCastInst *BCI = dyn_cast(User)) { + if (BCI->getType() == NewGV->getType()) { + BCI->replaceAllUsesWith(NewGV); + BCI->eraseFromParent(); + } else { + BCI->setOperand(0, NewGV); + } + } else { + if (TheBC == 0) + TheBC = new BitCastInst(NewGV, CI->getType(), "newgv", CI); + User->replaceUsesOfWith(CI, TheBC); + } + } + Constant *RepValue = NewGV; if (NewGV->getType() != GV->getType()->getElementType()) RepValue = ConstantExpr::getBitCast(RepValue, @@ -879,60 +869,60 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV, bool InitBoolUsed = false; // Loop over all uses of GV, processing them in turn. - std::vector Stores; - while (!GV->use_empty()) - if (LoadInst *LI = dyn_cast(GV->use_back())) { - while (!LI->use_empty()) { - Use &LoadUse = LI->use_begin().getUse(); - if (!isa(LoadUse.getUser())) - LoadUse = RepValue; - else { - ICmpInst *ICI = cast(LoadUse.getUser()); - // Replace the cmp X, 0 with a use of the bool value. - Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", ICI); - InitBoolUsed = true; - switch (ICI->getPredicate()) { - default: llvm_unreachable("Unknown ICmp Predicate!"); - case ICmpInst::ICMP_ULT: - case ICmpInst::ICMP_SLT: // X < null -> always false - LV = ConstantInt::getFalse(GV->getContext()); - break; - case ICmpInst::ICMP_ULE: - case ICmpInst::ICMP_SLE: - case ICmpInst::ICMP_EQ: - LV = BinaryOperator::CreateNot(LV, "notinit", ICI); - break; - case ICmpInst::ICMP_NE: - case ICmpInst::ICMP_UGE: - case ICmpInst::ICMP_SGE: - case ICmpInst::ICMP_UGT: - case ICmpInst::ICMP_SGT: - break; // no change. - } - ICI->replaceAllUsesWith(LV); - ICI->eraseFromParent(); - } - } - LI->eraseFromParent(); - } else { - StoreInst *SI = cast(GV->use_back()); + while (!GV->use_empty()) { + if (StoreInst *SI = dyn_cast(GV->use_back())) { // The global is initialized when the store to it occurs. new StoreInst(ConstantInt::getTrue(GV->getContext()), InitBool, SI); SI->eraseFromParent(); + continue; } + + LoadInst *LI = cast(GV->use_back()); + while (!LI->use_empty()) { + Use &LoadUse = LI->use_begin().getUse(); + if (!isa(LoadUse.getUser())) { + LoadUse = RepValue; + continue; + } + + ICmpInst *ICI = cast(LoadUse.getUser()); + // Replace the cmp X, 0 with a use of the bool value. + Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", ICI); + InitBoolUsed = true; + switch (ICI->getPredicate()) { + default: llvm_unreachable("Unknown ICmp Predicate!"); + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_SLT: // X < null -> always false + LV = ConstantInt::getFalse(GV->getContext()); + break; + case ICmpInst::ICMP_ULE: + case ICmpInst::ICMP_SLE: + case ICmpInst::ICMP_EQ: + LV = BinaryOperator::CreateNot(LV, "notinit", ICI); + break; + case ICmpInst::ICMP_NE: + case ICmpInst::ICMP_UGE: + case ICmpInst::ICMP_SGE: + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_SGT: + break; // no change. + } + ICI->replaceAllUsesWith(LV); + ICI->eraseFromParent(); + } + LI->eraseFromParent(); + } // If the initialization boolean was used, insert it, otherwise delete it. if (!InitBoolUsed) { while (!InitBool->use_empty()) // Delete initializations - cast(InitBool->use_back())->eraseFromParent(); + cast(InitBool->use_back())->eraseFromParent(); delete InitBool; } else GV->getParent()->getGlobalList().insert(GV, InitBool); - - // Now the GV is dead, nuke it and the malloc (both CI and BCI). + // Now the GV is dead, nuke it and the malloc.. GV->eraseFromParent(); - if (BCI) BCI->eraseFromParent(); CI->eraseFromParent(); // To further other optimizations, loop over all users of NewGV and try to @@ -1303,9 +1293,7 @@ static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, CallInst *CI, ConstantInt::get(IntPtrTy, TypeSize), NElems, CI->getName() + ".f" + Twine(FieldNo)); - CallInst *NCI = dyn_cast(NMI) ? - extractMallocCallFromBitCast(NMI) : cast(NMI); - FieldMallocs.push_back(NCI); + FieldMallocs.push_back(NMI); new StoreInst(NMI, NGV, CI); } @@ -1497,7 +1485,7 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV, // something. if (TD && NElements->getZExtValue() * TD->getTypeAllocSize(AllocTy) < 2048) { - GVI = OptimizeGlobalAddressOfMalloc(GV, CI, AllocTy, NElems, TD); + GVI = OptimizeGlobalAddressOfMalloc(GV, CI, AllocTy, NElements, TD); return true; } @@ -1556,7 +1544,7 @@ static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal, // only has one (non-null) value stored into it, then we can optimize any // users of the loaded value (often calls and loads) that would trap if the // value was null. - if (isa(GV->getInitializer()->getType()) && + if (GV->getInitializer()->getType()->isPointerTy() && GV->getInitializer()->isNullValue()) { if (Constant *SOVC = dyn_cast(StoredOnceVal)) { if (GV->getInitializer()->getType() != SOVC->getType()) @@ -1590,8 +1578,8 @@ static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) { // simplification. In these cases, we typically end up with "cond ? v1 : v2" // where v1 and v2 both require constant pool loads, a big loss. if (GVElType == Type::getInt1Ty(GV->getContext()) || - GVElType->isFloatingPoint() || - isa(GVElType) || isa(GVElType)) + GVElType->isFloatingPointTy() || + GVElType->isPointerTy() || GVElType->isVectorTy()) return false; // Walk the use list of the global seeing if all the uses are load or store. @@ -1925,7 +1913,7 @@ GlobalVariable *GlobalOpt::FindGlobalCtors(Module &M) { if (!ATy) return 0; const StructType *STy = dyn_cast(ATy->getElementType()); if (!STy || STy->getNumElements() != 2 || - !STy->getElementType(0)->isInteger(32)) return 0; + !STy->getElementType(0)->isIntegerTy(32)) return 0; const PointerType *PFTy = dyn_cast(STy->getElementType(1)); if (!PFTy) return 0; const FunctionType *FTy = dyn_cast(PFTy->getElementType()); @@ -2148,7 +2136,7 @@ static Constant *EvaluateStoreInto(Constant *Init, Constant *Val, Elts[CI->getZExtValue()] = EvaluateStoreInto(Elts[CI->getZExtValue()], Val, Addr, OpNo+1); - if (isa(Init->getType())) + if (Init->getType()->isArrayTy()) return ConstantArray::get(cast(InitTy), Elts); else return ConstantVector::get(&Elts[0], Elts.size()); diff --git a/lib/Transforms/IPO/Inliner.cpp b/lib/Transforms/IPO/Inliner.cpp index 97e2f06394..752a97c99c 100644 --- a/lib/Transforms/IPO/Inliner.cpp +++ b/lib/Transforms/IPO/Inliner.cpp @@ -41,12 +41,9 @@ static cl::opt InlineLimit("inline-threshold", cl::Hidden, cl::init(225), cl::ZeroOrMore, cl::desc("Control the amount of inlining to perform (default = 225)")); -static cl::opt -RespectHint("respect-inlinehint", cl::Hidden, - cl::desc("Respect the inlinehint attribute")); - -// Threshold to use when inlinehint is given. -const int HintThreshold = 300; +static cl::opt +HintThreshold("inlinehint-threshold", cl::Hidden, cl::init(325), + cl::desc("Threshold for inlining functions with inline hint")); // Threshold to use when optsize is specified (and there is no -inline-limit). const int OptSizeThreshold = 75; @@ -183,20 +180,22 @@ static bool InlineCallIfPossible(CallSite CS, CallGraph &CG, } unsigned Inliner::getInlineThreshold(CallSite CS) const { - // Listen to inlinehint when -respect-inlinehint is given. - Function *Callee = CS.getCalledFunction(); - if (RespectHint && Callee && !Callee->isDeclaration() && - Callee->hasFnAttr(Attribute::InlineHint)) - return HintThreshold; + int thres = InlineThreshold; // Listen to optsize when -inline-limit is not given. Function *Caller = CS.getCaller(); if (Caller && !Caller->isDeclaration() && Caller->hasFnAttr(Attribute::OptimizeForSize) && InlineLimit.getNumOccurrences() == 0) - return OptSizeThreshold; + thres = OptSizeThreshold; + + // Listen to inlinehint when it would increase the threshold. + Function *Callee = CS.getCalledFunction(); + if (HintThreshold > thres && Callee && !Callee->isDeclaration() && + Callee->hasFnAttr(Attribute::InlineHint)) + thres = HintThreshold; - return InlineThreshold; + return thres; } /// shouldInline - Return true if the inliner should attempt to inline diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp index 0e0d83af42..310e4a29e5 100644 --- a/lib/Transforms/IPO/StripSymbols.cpp +++ b/lib/Transforms/IPO/StripSymbols.cpp @@ -214,6 +214,15 @@ static bool StripDebugInfo(Module &M) { Changed = true; } + if (Function *DbgVal = M.getFunction("llvm.dbg.value")) { + while (!DbgVal->use_empty()) { + CallInst *CI = cast(DbgVal->use_back()); + CI->eraseFromParent(); + } + DbgVal->eraseFromParent(); + Changed = true; + } + NamedMDNode *NMD = M.getNamedMetadata("llvm.dbg.gv"); if (NMD) { Changed = true; diff --git a/lib/Transforms/InstCombine/InstCombine.h b/lib/Transforms/InstCombine/InstCombine.h index 536790004e..bd06499743 100644 --- a/lib/Transforms/InstCombine/InstCombine.h +++ b/lib/Transforms/InstCombine/InstCombine.h @@ -117,11 +117,11 @@ public: Instruction *visitUDiv(BinaryOperator &I); Instruction *visitSDiv(BinaryOperator &I); Instruction *visitFDiv(BinaryOperator &I); - Instruction *FoldAndOfICmps(Instruction &I, ICmpInst *LHS, ICmpInst *RHS); - Instruction *FoldAndOfFCmps(Instruction &I, FCmpInst *LHS, FCmpInst *RHS); + Value *FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS); + Value *FoldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS); Instruction *visitAnd(BinaryOperator &I); - Instruction *FoldOrOfICmps(Instruction &I, ICmpInst *LHS, ICmpInst *RHS); - Instruction *FoldOrOfFCmps(Instruction &I, FCmpInst *LHS, FCmpInst *RHS); + Value *FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS); + Value *FoldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS); Instruction *FoldOrWithConstants(BinaryOperator &I, Value *Op, Value *A, Value *B, Value *C); Instruction *visitOr (BinaryOperator &I); @@ -199,13 +199,15 @@ private: SmallVectorImpl &NewIndices); Instruction *FoldOpIntoSelect(Instruction &Op, SelectInst *SI); - /// ValueRequiresCast - Return true if the cast from "V to Ty" actually - /// results in any code being generated. It does not require codegen if V is - /// simple enough or if the cast can be folded into other casts. - bool ValueRequiresCast(Instruction::CastOps opcode,const Value *V, - const Type *Ty); + /// ShouldOptimizeCast - Return true if the cast from "V to Ty" actually + /// results in any code being generated and is interesting to optimize out. If + /// the cast can be eliminated by some other simple transformation, we prefer + /// to do the simplification first. + bool ShouldOptimizeCast(Instruction::CastOps opcode,const Value *V, + const Type *Ty); Instruction *visitCallSite(CallSite CS); + Instruction *tryOptimizeCall(CallInst *CI, const TargetData *TD); bool transformConstExprCastCall(CallSite CS); Instruction *transformCallThroughTrampoline(CallSite CS); Instruction *transformZExtICmp(ICmpInst *ICI, Instruction &CI, @@ -326,8 +328,8 @@ private: Value *FoldLogicalPlusAnd(Value *LHS, Value *RHS, ConstantInt *Mask, bool isSub, Instruction &I); - Instruction *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi, - bool isSigned, bool Inside, Instruction &IB); + Value *InsertRangeTest(Value *V, Constant *Lo, Constant *Hi, + bool isSigned, bool Inside); Instruction *PromoteCastOfAllocation(BitCastInst &CI, AllocaInst &AI); Instruction *MatchBSwap(BinaryOperator &I); bool SimplifyStoreAtEndOfBlock(StoreInst &SI); diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index c2924abba1..4d2c89e60f 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -35,7 +35,7 @@ static Constant *SubOne(ConstantInt *C) { // Otherwise, return null. // static inline Value *dyn_castFoldableMul(Value *V, ConstantInt *&CST) { - if (!V->hasOneUse() || !V->getType()->isInteger()) + if (!V->hasOneUse() || !V->getType()->isIntegerTy()) return 0; Instruction *I = dyn_cast(V); @@ -145,10 +145,10 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } } - if (I.getType()->isInteger(1)) + if (I.getType()->isIntegerTy(1)) return BinaryOperator::CreateXor(LHS, RHS); - if (I.getType()->isInteger()) { + if (I.getType()->isIntegerTy()) { // X + X --> X << 1 if (LHS == RHS) return BinaryOperator::CreateShl(LHS, ConstantInt::get(I.getType(), 1)); @@ -168,7 +168,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { // -A + B --> B - A // -A + -B --> -(A + B) if (Value *LHSV = dyn_castNegVal(LHS)) { - if (LHS->getType()->isIntOrIntVector()) { + if (LHS->getType()->isIntOrIntVectorTy()) { if (Value *RHSV = dyn_castNegVal(RHS)) { Value *NewAdd = Builder->CreateAdd(LHSV, RHSV, "sum"); return BinaryOperator::CreateNeg(NewAdd); @@ -222,7 +222,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) { } // W*X + Y*Z --> W * (X+Z) iff W == Y - if (I.getType()->isIntOrIntVector()) { + if (I.getType()->isIntOrIntVectorTy()) { Value *W, *X, *Y, *Z; if (match(LHS, m_Mul(m_Value(W), m_Value(X))) && match(RHS, m_Mul(m_Value(Y), m_Value(Z)))) { @@ -373,10 +373,10 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { if (CFP->getValueAPF().isPosZero() && CannotBeNegativeZero(LHS)) return ReplaceInstUsesWith(I, LHS); - // Check for (add double (sitofp x), y), see if we can merge this into an + // Check for (fadd double (sitofp x), y), see if we can merge this into an // integer add followed by a promotion. if (SIToFPInst *LHSConv = dyn_cast(LHS)) { - // (add double (sitofp x), fpcst) --> (sitofp (add int x, intcst)) + // (fadd double (sitofp x), fpcst) --> (sitofp (add int x, intcst)) // ... if the constant fits in the integer value. This is useful for things // like (double)(x & 1234) + 4.0 -> (double)((X & 1234)+4) which no longer // requires a constant pool load, and generally allows the add to be better @@ -394,7 +394,7 @@ Instruction *InstCombiner::visitFAdd(BinaryOperator &I) { } } - // (add double (sitofp x), (sitofp y)) --> (sitofp (add int x, y)) + // (fadd double (sitofp x), (sitofp y)) --> (sitofp (add int x, y)) if (SIToFPInst *RHSConv = dyn_cast(RHS)) { // Only do this if x/y have the same type, if at last one of them has a // single use (so we don't increase the number of int->fp conversions), @@ -560,7 +560,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) { return ReplaceInstUsesWith(I, Op0); // undef - X -> undef if (isa(Op1)) return ReplaceInstUsesWith(I, Op1); // X - undef -> undef - if (I.getType()->isInteger(1)) + if (I.getType()->isIntegerTy(1)) return BinaryOperator::CreateXor(Op0, Op1); if (ConstantInt *C = dyn_cast(Op0)) { diff --git a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 28fd70ef69..3fb3de7507 100644 --- a/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -137,80 +137,44 @@ static unsigned getFCmpCode(FCmpInst::Predicate CC, bool &isOrdered) { /// opcode and two operands into either a constant true or false, or a brand /// new ICmp instruction. The sign is passed in to determine which kind /// of predicate to use in the new icmp instruction. -static Value *getICmpValue(bool Sign, unsigned Code, Value *LHS, Value *RHS) { +static Value *getICmpValue(bool Sign, unsigned Code, Value *LHS, Value *RHS, + InstCombiner::BuilderTy *Builder) { + CmpInst::Predicate Pred; switch (Code) { default: assert(0 && "Illegal ICmp code!"); - case 0: - return ConstantInt::getFalse(LHS->getContext()); - case 1: - if (Sign) - return new ICmpInst(ICmpInst::ICMP_SGT, LHS, RHS); - return new ICmpInst(ICmpInst::ICMP_UGT, LHS, RHS); - case 2: - return new ICmpInst(ICmpInst::ICMP_EQ, LHS, RHS); - case 3: - if (Sign) - return new ICmpInst(ICmpInst::ICMP_SGE, LHS, RHS); - return new ICmpInst(ICmpInst::ICMP_UGE, LHS, RHS); - case 4: - if (Sign) - return new ICmpInst(ICmpInst::ICMP_SLT, LHS, RHS); - return new ICmpInst(ICmpInst::ICMP_ULT, LHS, RHS); - case 5: - return new ICmpInst(ICmpInst::ICMP_NE, LHS, RHS); - case 6: - if (Sign) - return new ICmpInst(ICmpInst::ICMP_SLE, LHS, RHS); - return new ICmpInst(ICmpInst::ICMP_ULE, LHS, RHS); - case 7: - return ConstantInt::getTrue(LHS->getContext()); + case 0: // False. + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); + case 1: Pred = Sign ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT; break; + case 2: Pred = ICmpInst::ICMP_EQ; break; + case 3: Pred = Sign ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE; break; + case 4: Pred = Sign ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; break; + case 5: Pred = ICmpInst::ICMP_NE; break; + case 6: Pred = Sign ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; break; + case 7: // True. + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 1); } + return Builder->CreateICmp(Pred, LHS, RHS); } /// getFCmpValue - This is the complement of getFCmpCode, which turns an /// opcode and two operands into either a FCmp instruction. isordered is passed /// in to determine which kind of predicate to use in the new fcmp instruction. static Value *getFCmpValue(bool isordered, unsigned code, - Value *LHS, Value *RHS) { + Value *LHS, Value *RHS, + InstCombiner::BuilderTy *Builder) { + CmpInst::Predicate Pred; switch (code) { - default: llvm_unreachable("Illegal FCmp code!"); - case 0: - if (isordered) - return new FCmpInst(FCmpInst::FCMP_ORD, LHS, RHS); - else - return new FCmpInst(FCmpInst::FCMP_UNO, LHS, RHS); - case 1: - if (isordered) - return new FCmpInst(FCmpInst::FCMP_OGT, LHS, RHS); - else - return new FCmpInst(FCmpInst::FCMP_UGT, LHS, RHS); - case 2: - if (isordered) - return new FCmpInst(FCmpInst::FCMP_OEQ, LHS, RHS); - else - return new FCmpInst(FCmpInst::FCMP_UEQ, LHS, RHS); - case 3: - if (isordered) - return new FCmpInst(FCmpInst::FCMP_OGE, LHS, RHS); - else - return new FCmpInst(FCmpInst::FCMP_UGE, LHS, RHS); - case 4: - if (isordered) - return new FCmpInst(FCmpInst::FCMP_OLT, LHS, RHS); - else - return new FCmpInst(FCmpInst::FCMP_ULT, LHS, RHS); - case 5: - if (isordered) - return new FCmpInst(FCmpInst::FCMP_ONE, LHS, RHS); - else - return new FCmpInst(FCmpInst::FCMP_UNE, LHS, RHS); - case 6: - if (isordered) - return new FCmpInst(FCmpInst::FCMP_OLE, LHS, RHS); - else - return new FCmpInst(FCmpInst::FCMP_ULE, LHS, RHS); - case 7: return ConstantInt::getTrue(LHS->getContext()); + default: assert(0 && "Illegal FCmp code!"); + case 0: Pred = isordered ? FCmpInst::FCMP_ORD : FCmpInst::FCMP_UNO; break; + case 1: Pred = isordered ? FCmpInst::FCMP_OGT : FCmpInst::FCMP_UGT; break; + case 2: Pred = isordered ? FCmpInst::FCMP_OEQ : FCmpInst::FCMP_UEQ; break; + case 3: Pred = isordered ? FCmpInst::FCMP_OGE : FCmpInst::FCMP_UGE; break; + case 4: Pred = isordered ? FCmpInst::FCMP_OLT : FCmpInst::FCMP_ULT; break; + case 5: Pred = isordered ? FCmpInst::FCMP_ONE : FCmpInst::FCMP_UNE; break; + case 6: Pred = isordered ? FCmpInst::FCMP_OLE : FCmpInst::FCMP_ULE; break; + case 7: return ConstantInt::getTrue(LHS->getContext()); } + return Builder->CreateFCmp(Pred, LHS, RHS); } /// PredicatesFoldable - Return true if both predicates match sign or if at @@ -355,40 +319,39 @@ Instruction *InstCombiner::OptAndOp(Instruction *Op, /// (V-Lo) (ConstantExpr::getICmp((isSigned ? ICmpInst::ICMP_SLE:ICmpInst::ICMP_ULE), Lo, Hi))->getZExtValue() && "Lo is not <= Hi in range emission code!"); if (Inside) { if (Lo == Hi) // Trivially false. - return new ICmpInst(ICmpInst::ICMP_NE, V, V); + return ConstantInt::getFalse(V->getContext()); // V >= Min && V < Hi --> V < Hi if (cast(Lo)->isMinValue(isSigned)) { ICmpInst::Predicate pred = (isSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT); - return new ICmpInst(pred, V, Hi); + return Builder->CreateICmp(pred, V, Hi); } // Emit V-Lo CreateAdd(V, NegLo, V->getName()+".off"); Constant *UpperBound = ConstantExpr::getAdd(NegLo, Hi); - return new ICmpInst(ICmpInst::ICMP_ULT, Add, UpperBound); + return Builder->CreateICmpULT(Add, UpperBound); } if (Lo == Hi) // Trivially true. - return new ICmpInst(ICmpInst::ICMP_EQ, V, V); + return ConstantInt::getTrue(V->getContext()); // V < Min || V >= Hi -> V > Hi-1 Hi = SubOne(cast(Hi)); if (cast(Lo)->isMinValue(isSigned)) { ICmpInst::Predicate pred = (isSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT); - return new ICmpInst(pred, V, Hi); + return Builder->CreateICmp(pred, V, Hi); } // Emit V-Lo >u Hi-1-Lo @@ -396,7 +359,7 @@ Instruction *InstCombiner::InsertRangeTest(Value *V, Constant *Lo, Constant *Hi, ConstantInt *NegLo = cast(ConstantExpr::getNeg(Lo)); Value *Add = Builder->CreateAdd(V, NegLo, V->getName()+".off"); Constant *LowerBound = ConstantExpr::getAdd(NegLo, Hi); - return new ICmpInst(ICmpInst::ICMP_UGT, Add, LowerBound); + return Builder->CreateICmpUGT(Add, LowerBound); } // isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s with @@ -472,8 +435,7 @@ Value *InstCombiner::FoldLogicalPlusAnd(Value *LHS, Value *RHS, } /// FoldAndOfICmps - Fold (icmp)&(icmp) if possible. -Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, - ICmpInst *LHS, ICmpInst *RHS) { +Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) { ICmpInst::Predicate LHSCC = LHS->getPredicate(), RHSCC = RHS->getPredicate(); // (icmp1 A, B) & (icmp2 A, B) --> (icmp3 A, B) @@ -486,11 +448,7 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1); unsigned Code = getICmpCode(LHS) & getICmpCode(RHS); bool isSigned = LHS->isSigned() || RHS->isSigned(); - Value *RV = getICmpValue(isSigned, Code, Op0, Op1); - if (Instruction *I = dyn_cast(RV)) - return I; - // Otherwise, it's a constant boolean value. - return ReplaceInstUsesWith(I, RV); + return getICmpValue(isSigned, Code, Op0, Op1, Builder); } } @@ -506,13 +464,13 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, if (LHSCC == ICmpInst::ICMP_ULT && LHSCst->getValue().isPowerOf2()) { Value *NewOr = Builder->CreateOr(Val, Val2); - return new ICmpInst(LHSCC, NewOr, LHSCst); + return Builder->CreateICmp(LHSCC, NewOr, LHSCst); } // (icmp eq A, 0) & (icmp eq B, 0) --> (icmp eq (A|B), 0) if (LHSCC == ICmpInst::ICMP_EQ && LHSCst->isZero()) { Value *NewOr = Builder->CreateOr(Val, Val2); - return new ICmpInst(LHSCC, NewOr, LHSCst); + return Builder->CreateICmp(LHSCC, NewOr, LHSCst); } } @@ -562,33 +520,32 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, case ICmpInst::ICMP_EQ: // (X == 13 & X == 15) -> false case ICmpInst::ICMP_UGT: // (X == 13 & X > 15) -> false case ICmpInst::ICMP_SGT: // (X == 13 & X > 15) -> false - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); case ICmpInst::ICMP_NE: // (X == 13 & X != 15) -> X == 13 case ICmpInst::ICMP_ULT: // (X == 13 & X < 15) -> X == 13 case ICmpInst::ICMP_SLT: // (X == 13 & X < 15) -> X == 13 - return ReplaceInstUsesWith(I, LHS); + return LHS; } case ICmpInst::ICMP_NE: switch (RHSCC) { default: llvm_unreachable("Unknown integer condition code!"); case ICmpInst::ICMP_ULT: if (LHSCst == SubOne(RHSCst)) // (X != 13 & X u< 14) -> X < 13 - return new ICmpInst(ICmpInst::ICMP_ULT, Val, LHSCst); + return Builder->CreateICmpULT(Val, LHSCst); break; // (X != 13 & X u< 15) -> no change case ICmpInst::ICMP_SLT: if (LHSCst == SubOne(RHSCst)) // (X != 13 & X s< 14) -> X < 13 - return new ICmpInst(ICmpInst::ICMP_SLT, Val, LHSCst); + return Builder->CreateICmpSLT(Val, LHSCst); break; // (X != 13 & X s< 15) -> no change case ICmpInst::ICMP_EQ: // (X != 13 & X == 15) -> X == 15 case ICmpInst::ICMP_UGT: // (X != 13 & X u> 15) -> X u> 15 case ICmpInst::ICMP_SGT: // (X != 13 & X s> 15) -> X s> 15 - return ReplaceInstUsesWith(I, RHS); + return RHS; case ICmpInst::ICMP_NE: if (LHSCst == SubOne(RHSCst)){// (X != 13 & X != 14) -> X-13 >u 1 Constant *AddCST = ConstantExpr::getNeg(LHSCst); Value *Add = Builder->CreateAdd(Val, AddCST, Val->getName()+".off"); - return new ICmpInst(ICmpInst::ICMP_UGT, Add, - ConstantInt::get(Add->getType(), 1)); + return Builder->CreateICmpUGT(Add, ConstantInt::get(Add->getType(), 1)); } break; // (X != 13 & X != 15) -> no change } @@ -598,12 +555,12 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, default: llvm_unreachable("Unknown integer condition code!"); case ICmpInst::ICMP_EQ: // (X u< 13 & X == 15) -> false case ICmpInst::ICMP_UGT: // (X u< 13 & X u> 15) -> false - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); case ICmpInst::ICMP_SGT: // (X u< 13 & X s> 15) -> no change break; case ICmpInst::ICMP_NE: // (X u< 13 & X != 15) -> X u< 13 case ICmpInst::ICMP_ULT: // (X u< 13 & X u< 15) -> X u< 13 - return ReplaceInstUsesWith(I, LHS); + return LHS; case ICmpInst::ICMP_SLT: // (X u< 13 & X s< 15) -> no change break; } @@ -613,12 +570,12 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, default: llvm_unreachable("Unknown integer condition code!"); case ICmpInst::ICMP_EQ: // (X s< 13 & X == 15) -> false case ICmpInst::ICMP_SGT: // (X s< 13 & X s> 15) -> false - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); case ICmpInst::ICMP_UGT: // (X s< 13 & X u> 15) -> no change break; case ICmpInst::ICMP_NE: // (X s< 13 & X != 15) -> X < 13 case ICmpInst::ICMP_SLT: // (X s< 13 & X s< 15) -> X < 13 - return ReplaceInstUsesWith(I, LHS); + return LHS; case ICmpInst::ICMP_ULT: // (X s< 13 & X u< 15) -> no change break; } @@ -628,16 +585,15 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, default: llvm_unreachable("Unknown integer condition code!"); case ICmpInst::ICMP_EQ: // (X u> 13 & X == 15) -> X == 15 case ICmpInst::ICMP_UGT: // (X u> 13 & X u> 15) -> X u> 15 - return ReplaceInstUsesWith(I, RHS); + return RHS; case ICmpInst::ICMP_SGT: // (X u> 13 & X s> 15) -> no change break; case ICmpInst::ICMP_NE: if (RHSCst == AddOne(LHSCst)) // (X u> 13 & X != 14) -> X u> 14 - return new ICmpInst(LHSCC, Val, RHSCst); + return Builder->CreateICmp(LHSCC, Val, RHSCst); break; // (X u> 13 & X != 15) -> no change case ICmpInst::ICMP_ULT: // (X u> 13 & X u< 15) -> (X-14) 13 & X s< 15) -> no change break; } @@ -647,16 +603,15 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, default: llvm_unreachable("Unknown integer condition code!"); case ICmpInst::ICMP_EQ: // (X s> 13 & X == 15) -> X == 15 case ICmpInst::ICMP_SGT: // (X s> 13 & X s> 15) -> X s> 15 - return ReplaceInstUsesWith(I, RHS); + return RHS; case ICmpInst::ICMP_UGT: // (X s> 13 & X u> 15) -> no change break; case ICmpInst::ICMP_NE: if (RHSCst == AddOne(LHSCst)) // (X s> 13 & X != 14) -> X s> 14 - return new ICmpInst(LHSCC, Val, RHSCst); + return Builder->CreateICmp(LHSCC, Val, RHSCst); break; // (X s> 13 & X != 15) -> no change case ICmpInst::ICMP_SLT: // (X s> 13 & X s< 15) -> (X-14) s< 1 - return InsertRangeTest(Val, AddOne(LHSCst), - RHSCst, true, true, I); + return InsertRangeTest(Val, AddOne(LHSCst), RHSCst, true, true); case ICmpInst::ICMP_ULT: // (X s> 13 & X u< 15) -> no change break; } @@ -666,9 +621,10 @@ Instruction *InstCombiner::FoldAndOfICmps(Instruction &I, return 0; } -Instruction *InstCombiner::FoldAndOfFCmps(Instruction &I, FCmpInst *LHS, - FCmpInst *RHS) { - +/// FoldAndOfFCmps - Optimize (fcmp)&(fcmp). NOTE: Unlike the rest of +/// instcombine, this returns a Value which should already be inserted into the +/// function. +Value *InstCombiner::FoldAndOfFCmps(FCmpInst *LHS, FCmpInst *RHS) { if (LHS->getPredicate() == FCmpInst::FCMP_ORD && RHS->getPredicate() == FCmpInst::FCMP_ORD) { // (fcmp ord x, c) & (fcmp ord y, c) -> (fcmp ord x, y) @@ -677,17 +633,15 @@ Instruction *InstCombiner::FoldAndOfFCmps(Instruction &I, FCmpInst *LHS, // If either of the constants are nans, then the whole thing returns // false. if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN()) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); - return new FCmpInst(FCmpInst::FCMP_ORD, - LHS->getOperand(0), RHS->getOperand(0)); + return ConstantInt::getFalse(LHS->getContext()); + return Builder->CreateFCmpORD(LHS->getOperand(0), RHS->getOperand(0)); } // Handle vector zeros. This occurs because the canonical form of // "fcmp ord x,x" is "fcmp ord x, 0". if (isa(LHS->getOperand(1)) && isa(RHS->getOperand(1))) - return new FCmpInst(FCmpInst::FCMP_ORD, - LHS->getOperand(0), RHS->getOperand(0)); + return Builder->CreateFCmpORD(LHS->getOperand(0), RHS->getOperand(0)); return 0; } @@ -705,14 +659,13 @@ Instruction *InstCombiner::FoldAndOfFCmps(Instruction &I, FCmpInst *LHS, if (Op0LHS == Op1LHS && Op0RHS == Op1RHS) { // Simplify (fcmp cc0 x, y) & (fcmp cc1 x, y). if (Op0CC == Op1CC) - return new FCmpInst((FCmpInst::Predicate)Op0CC, Op0LHS, Op0RHS); - + return Builder->CreateFCmp((FCmpInst::Predicate)Op0CC, Op0LHS, Op0RHS); if (Op0CC == FCmpInst::FCMP_FALSE || Op1CC == FCmpInst::FCMP_FALSE) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); if (Op0CC == FCmpInst::FCMP_TRUE) - return ReplaceInstUsesWith(I, RHS); + return RHS; if (Op1CC == FCmpInst::FCMP_TRUE) - return ReplaceInstUsesWith(I, LHS); + return LHS; bool Op0Ordered; bool Op1Ordered; @@ -727,14 +680,14 @@ Instruction *InstCombiner::FoldAndOfFCmps(Instruction &I, FCmpInst *LHS, // uno && ueq -> uno && (uno || eq) -> ueq // ord && olt -> ord && (ord && lt) -> olt if (Op0Ordered == Op1Ordered) - return ReplaceInstUsesWith(I, RHS); + return RHS; // uno && oeq -> uno && (ord && eq) -> false // uno && ord -> false if (!Op0Ordered) - return ReplaceInstUsesWith(I, ConstantInt::getFalse(I.getContext())); + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 0); // ord && ueq -> ord && (uno || eq) -> oeq - return cast(getFCmpValue(true, Op1Pred, Op0LHS, Op0RHS)); + return getFCmpValue(true, Op1Pred, Op0LHS, Op0RHS, Builder); } } @@ -930,26 +883,47 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { if (ICmpInst *RHS = dyn_cast(Op1)) if (ICmpInst *LHS = dyn_cast(Op0)) - if (Instruction *Res = FoldAndOfICmps(I, LHS, RHS)) - return Res; - + if (Value *Res = FoldAndOfICmps(LHS, RHS)) + return ReplaceInstUsesWith(I, Res); + + // If and'ing two fcmp, try combine them into one. + if (FCmpInst *LHS = dyn_cast(I.getOperand(0))) + if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) + if (Value *Res = FoldAndOfFCmps(LHS, RHS)) + return ReplaceInstUsesWith(I, Res); + + // fold (and (cast A), (cast B)) -> (cast (and A, B)) if (CastInst *Op0C = dyn_cast(Op0)) - if (CastInst *Op1C = dyn_cast(Op1)) - if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind ? - const Type *SrcTy = Op0C->getOperand(0)->getType(); - if (SrcTy == Op1C->getOperand(0)->getType() && - SrcTy->isIntOrIntVector() && - // Only do this if the casts both really cause code to be generated. - ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0), - I.getType()) && - ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0), - I.getType())) { - Value *NewOp = Builder->CreateAnd(Op0C->getOperand(0), - Op1C->getOperand(0), I.getName()); + if (CastInst *Op1C = dyn_cast(Op1)) { + const Type *SrcTy = Op0C->getOperand(0)->getType(); + if (Op0C->getOpcode() == Op1C->getOpcode() && // same cast kind ? + SrcTy == Op1C->getOperand(0)->getType() && + SrcTy->isIntOrIntVectorTy()) { + Value *Op0COp = Op0C->getOperand(0), *Op1COp = Op1C->getOperand(0); + + // Only do this if the casts both really cause code to be generated. + if (ShouldOptimizeCast(Op0C->getOpcode(), Op0COp, I.getType()) && + ShouldOptimizeCast(Op1C->getOpcode(), Op1COp, I.getType())) { + Value *NewOp = Builder->CreateAnd(Op0COp, Op1COp, I.getName()); return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType()); } + + // If this is and(cast(icmp), cast(icmp)), try to fold this even if the + // cast is otherwise not optimizable. This happens for vector sexts. + if (ICmpInst *RHS = dyn_cast(Op1COp)) + if (ICmpInst *LHS = dyn_cast(Op0COp)) + if (Value *Res = FoldAndOfICmps(LHS, RHS)) + return CastInst::Create(Op0C->getOpcode(), Res, I.getType()); + + // If this is and(cast(fcmp), cast(fcmp)), try to fold this even if the + // cast is otherwise not optimizable. This happens for vector sexts. + if (FCmpInst *RHS = dyn_cast(Op1COp)) + if (FCmpInst *LHS = dyn_cast(Op0COp)) + if (Value *Res = FoldAndOfFCmps(LHS, RHS)) + return CastInst::Create(Op0C->getOpcode(), Res, I.getType()); } + } // (X >> Z) & (Y >> Z) -> (X&Y) >> Z for all shifts. if (BinaryOperator *SI1 = dyn_cast(Op1)) { @@ -965,13 +939,6 @@ Instruction *InstCombiner::visitAnd(BinaryOperator &I) { } } - // If and'ing two fcmp, try combine them into one. - if (FCmpInst *LHS = dyn_cast(I.getOperand(0))) { - if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) - if (Instruction *Res = FoldAndOfFCmps(I, LHS, RHS)) - return Res; - } - return Changed ? &I : 0; } @@ -1143,7 +1110,7 @@ static Instruction *MatchSelectFromAndOr(Value *A, Value *B, // If A is not a select of -1/0, this cannot match. Value *Cond = 0; if (!match(A, m_SExt(m_Value(Cond))) || - !Cond->getType()->isInteger(1)) + !Cond->getType()->isIntegerTy(1)) return 0; // ((cond?-1:0)&C) | (B&(cond?0:-1)) -> cond ? C : B. @@ -1161,8 +1128,7 @@ static Instruction *MatchSelectFromAndOr(Value *A, Value *B, } /// FoldOrOfICmps - Fold (icmp)|(icmp) if possible. -Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, - ICmpInst *LHS, ICmpInst *RHS) { +Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS) { ICmpInst::Predicate LHSCC = LHS->getPredicate(), RHSCC = RHS->getPredicate(); // (icmp1 A, B) | (icmp2 A, B) --> (icmp3 A, B) @@ -1175,11 +1141,7 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1); unsigned Code = getICmpCode(LHS) | getICmpCode(RHS); bool isSigned = LHS->isSigned() || RHS->isSigned(); - Value *RV = getICmpValue(isSigned, Code, Op0, Op1); - if (Instruction *I = dyn_cast(RV)) - return I; - // Otherwise, it's a constant boolean value. - return ReplaceInstUsesWith(I, RV); + return getICmpValue(isSigned, Code, Op0, Op1, Builder); } } @@ -1193,7 +1155,7 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, if (LHSCst == RHSCst && LHSCC == RHSCC && LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero()) { Value *NewOr = Builder->CreateOr(Val, Val2); - return new ICmpInst(LHSCC, NewOr, LHSCst); + return Builder->CreateICmp(LHSCC, NewOr, LHSCst); } // From here on, we only handle: @@ -1245,7 +1207,7 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, Constant *AddCST = ConstantExpr::getNeg(LHSCst); Value *Add = Builder->CreateAdd(Val, AddCST, Val->getName()+".off"); AddCST = ConstantExpr::getSub(AddOne(RHSCst), LHSCst); - return new ICmpInst(ICmpInst::ICMP_ULT, Add, AddCST); + return Builder->CreateICmpULT(Add, AddCST); } break; // (X == 13 | X == 15) -> no change case ICmpInst::ICMP_UGT: // (X == 13 | X u> 14) -> no change @@ -1254,7 +1216,7 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, case ICmpInst::ICMP_NE: // (X == 13 | X != 15) -> X != 15 case ICmpInst::ICMP_ULT: // (X == 13 | X u< 15) -> X u< 15 case ICmpInst::ICMP_SLT: // (X == 13 | X s< 15) -> X s< 15 - return ReplaceInstUsesWith(I, RHS); + return RHS; } break; case ICmpInst::ICMP_NE: @@ -1263,11 +1225,11 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, case ICmpInst::ICMP_EQ: // (X != 13 | X == 15) -> X != 13 case ICmpInst::ICMP_UGT: // (X != 13 | X u> 15) -> X != 13 case ICmpInst::ICMP_SGT: // (X != 13 | X s> 15) -> X != 13 - return ReplaceInstUsesWith(I, LHS); + return LHS; case ICmpInst::ICMP_NE: // (X != 13 | X != 15) -> true case ICmpInst::ICMP_ULT: // (X != 13 | X u< 15) -> true case ICmpInst::ICMP_SLT: // (X != 13 | X s< 15) -> true - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ConstantInt::getTrue(LHS->getContext()); } break; case ICmpInst::ICMP_ULT: @@ -1279,14 +1241,13 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, // If RHSCst is [us]MAXINT, it is always false. Not handling // this can cause overflow. if (RHSCst->isMaxValue(false)) - return ReplaceInstUsesWith(I, LHS); - return InsertRangeTest(Val, LHSCst, AddOne(RHSCst), - false, false, I); + return LHS; + return InsertRangeTest(Val, LHSCst, AddOne(RHSCst), false, false); case ICmpInst::ICMP_SGT: // (X u< 13 | X s> 15) -> no change break; case ICmpInst::ICMP_NE: // (X u< 13 | X != 15) -> X != 15 case ICmpInst::ICMP_ULT: // (X u< 13 | X u< 15) -> X u< 15 - return ReplaceInstUsesWith(I, RHS); + return RHS; case ICmpInst::ICMP_SLT: // (X u< 13 | X s< 15) -> no change break; } @@ -1300,14 +1261,13 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, // If RHSCst is [us]MAXINT, it is always false. Not handling // this can cause overflow. if (RHSCst->isMaxValue(true)) - return ReplaceInstUsesWith(I, LHS); - return InsertRangeTest(Val, LHSCst, AddOne(RHSCst), - true, false, I); + return LHS; + return InsertRangeTest(Val, LHSCst, AddOne(RHSCst), true, false); case ICmpInst::ICMP_UGT: // (X s< 13 | X u> 15) -> no change break; case ICmpInst::ICMP_NE: // (X s< 13 | X != 15) -> X != 15 case ICmpInst::ICMP_SLT: // (X s< 13 | X s< 15) -> X s< 15 - return ReplaceInstUsesWith(I, RHS); + return RHS; case ICmpInst::ICMP_ULT: // (X s< 13 | X u< 15) -> no change break; } @@ -1317,12 +1277,12 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, default: llvm_unreachable("Unknown integer condition code!"); case ICmpInst::ICMP_EQ: // (X u> 13 | X == 15) -> X u> 13 case ICmpInst::ICMP_UGT: // (X u> 13 | X u> 15) -> X u> 13 - return ReplaceInstUsesWith(I, LHS); + return LHS; case ICmpInst::ICMP_SGT: // (X u> 13 | X s> 15) -> no change break; case ICmpInst::ICMP_NE: // (X u> 13 | X != 15) -> true case ICmpInst::ICMP_ULT: // (X u> 13 | X u< 15) -> true - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ConstantInt::getTrue(LHS->getContext()); case ICmpInst::ICMP_SLT: // (X u> 13 | X s< 15) -> no change break; } @@ -1332,12 +1292,12 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, default: llvm_unreachable("Unknown integer condition code!"); case ICmpInst::ICMP_EQ: // (X s> 13 | X == 15) -> X > 13 case ICmpInst::ICMP_SGT: // (X s> 13 | X s> 15) -> X > 13 - return ReplaceInstUsesWith(I, LHS); + return LHS; case ICmpInst::ICMP_UGT: // (X s> 13 | X u> 15) -> no change break; case ICmpInst::ICMP_NE: // (X s> 13 | X != 15) -> true case ICmpInst::ICMP_SLT: // (X s> 13 | X s< 15) -> true - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ConstantInt::getTrue(LHS->getContext()); case ICmpInst::ICMP_ULT: // (X s> 13 | X u< 15) -> no change break; } @@ -1346,8 +1306,10 @@ Instruction *InstCombiner::FoldOrOfICmps(Instruction &I, return 0; } -Instruction *InstCombiner::FoldOrOfFCmps(Instruction &I, FCmpInst *LHS, - FCmpInst *RHS) { +/// FoldOrOfFCmps - Optimize (fcmp)|(fcmp). NOTE: Unlike the rest of +/// instcombine, this returns a Value which should already be inserted into the +/// function. +Value *InstCombiner::FoldOrOfFCmps(FCmpInst *LHS, FCmpInst *RHS) { if (LHS->getPredicate() == FCmpInst::FCMP_UNO && RHS->getPredicate() == FCmpInst::FCMP_UNO && LHS->getOperand(0)->getType() == RHS->getOperand(0)->getType()) { @@ -1356,20 +1318,18 @@ Instruction *InstCombiner::FoldOrOfFCmps(Instruction &I, FCmpInst *LHS, // If either of the constants are nans, then the whole thing returns // true. if (LHSC->getValueAPF().isNaN() || RHSC->getValueAPF().isNaN()) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ConstantInt::getTrue(LHS->getContext()); // Otherwise, no need to compare the two constants, compare the // rest. - return new FCmpInst(FCmpInst::FCMP_UNO, - LHS->getOperand(0), RHS->getOperand(0)); + return Builder->CreateFCmpUNO(LHS->getOperand(0), RHS->getOperand(0)); } // Handle vector zeros. This occurs because the canonical form of // "fcmp uno x,x" is "fcmp uno x, 0". if (isa(LHS->getOperand(1)) && isa(RHS->getOperand(1))) - return new FCmpInst(FCmpInst::FCMP_UNO, - LHS->getOperand(0), RHS->getOperand(0)); + return Builder->CreateFCmpUNO(LHS->getOperand(0), RHS->getOperand(0)); return 0; } @@ -1386,14 +1346,13 @@ Instruction *InstCombiner::FoldOrOfFCmps(Instruction &I, FCmpInst *LHS, if (Op0LHS == Op1LHS && Op0RHS == Op1RHS) { // Simplify (fcmp cc0 x, y) | (fcmp cc1 x, y). if (Op0CC == Op1CC) - return new FCmpInst((FCmpInst::Predicate)Op0CC, - Op0LHS, Op0RHS); + return Builder->CreateFCmp((FCmpInst::Predicate)Op0CC, Op0LHS, Op0RHS); if (Op0CC == FCmpInst::FCMP_TRUE || Op1CC == FCmpInst::FCMP_TRUE) - return ReplaceInstUsesWith(I, ConstantInt::getTrue(I.getContext())); + return ConstantInt::get(CmpInst::makeCmpResultType(LHS->getType()), 1); if (Op0CC == FCmpInst::FCMP_FALSE) - return ReplaceInstUsesWith(I, RHS); + return RHS; if (Op1CC == FCmpInst::FCMP_FALSE) - return ReplaceInstUsesWith(I, LHS); + return LHS; bool Op0Ordered; bool Op1Ordered; unsigned Op0Pred = getFCmpCode(Op0CC, Op0Ordered); @@ -1401,11 +1360,7 @@ Instruction *InstCombiner::FoldOrOfFCmps(Instruction &I, FCmpInst *LHS, if (Op0Ordered == Op1Ordered) { // If both are ordered or unordered, return a new fcmp with // or'ed predicates. - Value *RV = getFCmpValue(Op0Ordered, Op0Pred|Op1Pred, Op0LHS, Op0RHS); - if (Instruction *I = dyn_cast(RV)) - return I; - // Otherwise, it's a constant boolean value... - return ReplaceInstUsesWith(I, RV); + return getFCmpValue(Op0Ordered, Op0Pred|Op1Pred, Op0LHS, Op0RHS, Builder); } } return 0; @@ -1446,8 +1401,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (Value *V = SimplifyOrInst(Op0, Op1, TD)) return ReplaceInstUsesWith(I, V); - - + // See if we can simplify any instructions used by the instruction whose sole // purpose is to compute bits we don't care about. if (SimplifyDemandedInstructionBits(I)) @@ -1456,7 +1410,9 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (ConstantInt *RHS = dyn_cast(Op1)) { ConstantInt *C1 = 0; Value *X = 0; // (X & C1) | C2 --> (X | C2) & (C1|C2) + // iff (C1 & C2) == 0. if (match(Op0, m_And(m_Value(X), m_ConstantInt(C1))) && + (RHS->getValue() & C1->getValue()) != 0 && Op0->hasOneUse()) { Value *Or = Builder->CreateOr(X, RHS); Or->takeName(Op0); @@ -1479,6 +1435,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (SelectInst *SI = dyn_cast(Op0)) if (Instruction *R = FoldOpIntoSelect(I, SI)) return R; + if (isa(Op0)) if (Instruction *NV = FoldOpIntoPhi(I)) return NV; @@ -1600,7 +1557,7 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { // (A & (C0?-1:0)) | (B & ~(C0?-1:0)) -> C0 ? A : B, and commuted variants. // Don't do this for vector select idioms, the code generator doesn't handle // them well yet. - if (!isa(I.getType())) { + if (!I.getType()->isVectorTy()) { if (Instruction *Match = MatchSelectFromAndOr(A, B, C, D)) return Match; if (Instruction *Match = MatchSelectFromAndOr(B, A, D, C)) @@ -1666,40 +1623,50 @@ Instruction *InstCombiner::visitOr(BinaryOperator &I) { if (ICmpInst *RHS = dyn_cast(I.getOperand(1))) if (ICmpInst *LHS = dyn_cast(I.getOperand(0))) - if (Instruction *Res = FoldOrOfICmps(I, LHS, RHS)) - return Res; + if (Value *Res = FoldOrOfICmps(LHS, RHS)) + return ReplaceInstUsesWith(I, Res); + // (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y) + if (FCmpInst *LHS = dyn_cast(I.getOperand(0))) + if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) + if (Value *Res = FoldOrOfFCmps(LHS, RHS)) + return ReplaceInstUsesWith(I, Res); + // fold (or (cast A), (cast B)) -> (cast (or A, B)) if (CastInst *Op0C = dyn_cast(Op0)) { if (CastInst *Op1C = dyn_cast(Op1)) if (Op0C->getOpcode() == Op1C->getOpcode()) {// same cast kind ? - if (!isa(Op0C->getOperand(0)) || - !isa(Op1C->getOperand(0))) { - const Type *SrcTy = Op0C->getOperand(0)->getType(); - if (SrcTy == Op1C->getOperand(0)->getType() && - SrcTy->isIntOrIntVector() && + const Type *SrcTy = Op0C->getOperand(0)->getType(); + if (SrcTy == Op1C->getOperand(0)->getType() && + SrcTy->isIntOrIntVectorTy()) { + Value *Op0COp = Op0C->getOperand(0), *Op1COp = Op1C->getOperand(0); + + if ((!isa(Op0COp) || !isa(Op1COp)) && // Only do this if the casts both really cause code to be // generated. - ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0), - I.getType()) && - ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0), - I.getType())) { - Value *NewOp = Builder->CreateOr(Op0C->getOperand(0), - Op1C->getOperand(0), I.getName()); + ShouldOptimizeCast(Op0C->getOpcode(), Op0COp, I.getType()) && + ShouldOptimizeCast(Op1C->getOpcode(), Op1COp, I.getType())) { + Value *NewOp = Builder->CreateOr(Op0COp, Op1COp, I.getName()); return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType()); } + + // If this is or(cast(icmp), cast(icmp)), try to fold this even if the + // cast is otherwise not optimizable. This happens for vector sexts. + if (ICmpInst *RHS = dyn_cast(Op1COp)) + if (ICmpInst *LHS = dyn_cast(Op0COp)) + if (Value *Res = FoldOrOfICmps(LHS, RHS)) + return CastInst::Create(Op0C->getOpcode(), Res, I.getType()); + + // If this is or(cast(fcmp), cast(fcmp)), try to fold this even if the + // cast is otherwise not optimizable. This happens for vector sexts. + if (FCmpInst *RHS = dyn_cast(Op1COp)) + if (FCmpInst *LHS = dyn_cast(Op0COp)) + if (Value *Res = FoldOrOfFCmps(LHS, RHS)) + return CastInst::Create(Op0C->getOpcode(), Res, I.getType()); } } } - - // (fcmp uno x, c) | (fcmp uno y, c) -> (fcmp uno x, y) - if (FCmpInst *LHS = dyn_cast(I.getOperand(0))) { - if (FCmpInst *RHS = dyn_cast(I.getOperand(1))) - if (Instruction *Res = FoldOrOfFCmps(I, LHS, RHS)) - return Res; - } - return Changed ? &I : 0; } @@ -1723,7 +1690,7 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { // purpose is to compute bits we don't care about. if (SimplifyDemandedInstructionBits(I)) return &I; - if (isa(I.getType())) + if (I.getType()->isVectorTy()) if (isa(Op1)) return ReplaceInstUsesWith(I, Op0); // X ^ <0,0> -> X @@ -1971,11 +1938,8 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1); unsigned Code = getICmpCode(LHS) ^ getICmpCode(RHS); bool isSigned = LHS->isSigned() || RHS->isSigned(); - Value *RV = getICmpValue(isSigned, Code, Op0, Op1); - if (Instruction *I = dyn_cast(RV)) - return I; - // Otherwise, it's a constant boolean value. - return ReplaceInstUsesWith(I, RV); + return ReplaceInstUsesWith(I, + getICmpValue(isSigned, Code, Op0, Op1, Builder)); } } @@ -1984,12 +1948,12 @@ Instruction *InstCombiner::visitXor(BinaryOperator &I) { if (CastInst *Op1C = dyn_cast(Op1)) if (Op0C->getOpcode() == Op1C->getOpcode()) { // same cast kind? const Type *SrcTy = Op0C->getOperand(0)->getType(); - if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isInteger() && + if (SrcTy == Op1C->getOperand(0)->getType() && SrcTy->isIntegerTy() && // Only do this if the casts both really cause code to be generated. - ValueRequiresCast(Op0C->getOpcode(), Op0C->getOperand(0), - I.getType()) && - ValueRequiresCast(Op1C->getOpcode(), Op1C->getOperand(0), - I.getType())) { + ShouldOptimizeCast(Op0C->getOpcode(), Op0C->getOperand(0), + I.getType()) && + ShouldOptimizeCast(Op1C->getOpcode(), Op1C->getOperand(0), + I.getType())) { Value *NewOp = Builder->CreateXor(Op0C->getOperand(0), Op1C->getOperand(0), I.getName()); return CastInst::Create(Op0C->getOpcode(), NewOp, I.getType()); diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 4929f4070f..e2b7d3d60d 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -16,6 +16,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/Target/TargetData.h" #include "llvm/Analysis/MemoryBuiltins.h" +#include "llvm/Transforms/Utils/BuildLibCalls.h" using namespace llvm; /// getPromotedType - Return the specified type promoted as it would be to pass @@ -199,7 +200,7 @@ Instruction *InstCombiner::SimplifyMemSet(MemSetInst *MI) { // Extract the length and alignment and fill if they are constant. ConstantInt *LenC = dyn_cast(MI->getLength()); ConstantInt *FillC = dyn_cast(MI->getValue()); - if (!LenC || !FillC || !FillC->getType()->isInteger(8)) + if (!LenC || !FillC || !FillC->getType()->isIntegerTy(8)) return 0; uint64_t Len = LenC->getZExtValue(); Alignment = MI->getAlignment(); @@ -304,23 +305,77 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { switch (II->getIntrinsicID()) { default: break; case Intrinsic::objectsize: { + // We need target data for just about everything so depend on it. + if (!TD) break; + const Type *ReturnTy = CI.getType(); - Value *Op1 = II->getOperand(1); bool Min = (cast(II->getOperand(2))->getZExtValue() == 1); + + // Get to the real allocated thing and offset as fast as possible. + Value *Op1 = II->getOperand(1)->stripPointerCasts(); - if (!TD) break; - Op1 = Op1->stripPointerCasts(); - + // If we've stripped down to a single global variable that we + // can know the size of then just return that. if (GlobalVariable *GV = dyn_cast(Op1)) { if (GV->hasDefinitiveInitializer()) { Constant *C = GV->getInitializer(); - size_t globalSize = TD->getTypeAllocSize(C->getType()); - return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, globalSize)); + uint64_t GlobalSize = TD->getTypeAllocSize(C->getType()); + return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, GlobalSize)); } else { + // Can't determine size of the GV. Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL); return ReplaceInstUsesWith(CI, RetVal); } - } + } else if (AllocaInst *AI = dyn_cast(Op1)) { + // Get alloca size. + if (AI->getAllocatedType()->isSized()) { + uint64_t AllocaSize = TD->getTypeAllocSize(AI->getAllocatedType()); + if (AI->isArrayAllocation()) { + const ConstantInt *C = dyn_cast(AI->getArraySize()); + if (!C) break; + AllocaSize *= C->getZExtValue(); + } + return ReplaceInstUsesWith(CI, ConstantInt::get(ReturnTy, AllocaSize)); + } + } else if (ConstantExpr *CE = dyn_cast(Op1)) { + // Only handle constant GEPs here. + if (CE->getOpcode() != Instruction::GetElementPtr) break; + GEPOperator *GEP = cast(CE); + + // Make sure we're not a constant offset from an external + // global. + Value *Operand = GEP->getPointerOperand(); + Operand = Operand->stripPointerCasts(); + if (GlobalVariable *GV = dyn_cast(Operand)) + if (!GV->hasDefinitiveInitializer()) break; + + // Get what we're pointing to and its size. + const PointerType *BaseType = + cast(Operand->getType()); + uint64_t Size = TD->getTypeAllocSize(BaseType->getElementType()); + + // Get the current byte offset into the thing. Use the original + // operand in case we're looking through a bitcast. + SmallVector Ops(CE->op_begin()+1, CE->op_end()); + const PointerType *OffsetType = + cast(GEP->getPointerOperand()->getType()); + uint64_t Offset = TD->getIndexedOffset(OffsetType, &Ops[0], Ops.size()); + + if (Size < Offset) { + // Out of bound reference? Negative index normalized to large + // index? Just return "I don't know". + Constant *RetVal = ConstantInt::get(ReturnTy, Min ? 0 : -1ULL); + return ReplaceInstUsesWith(CI, RetVal); + } + + Constant *RetVal = ConstantInt::get(ReturnTy, Size-Offset); + return ReplaceInstUsesWith(CI, RetVal); + + } + + // Do not return "I don't know" here. Later optimization passes could + // make it possible to evaluate objectsize to a constant. + break; } case Intrinsic::bswap: // bswap(bswap(x)) -> x @@ -686,6 +741,122 @@ static bool isSafeToEliminateVarargsCast(const CallSite CS, return true; } +// Try to fold some different type of calls here. +// Currently we're only working with the checking functions, memcpy_chk, +// mempcpy_chk, memmove_chk, memset_chk, strcpy_chk, stpcpy_chk, strncpy_chk, +// strcat_chk and strncat_chk. +Instruction *InstCombiner::tryOptimizeCall(CallInst *CI, const TargetData *TD) { + if (CI->getCalledFunction() == 0) return 0; + + StringRef Name = CI->getCalledFunction()->getName(); + BasicBlock *BB = CI->getParent(); + IRBuilder<> B(CI->getParent()->getContext()); + + // Set the builder to the instruction after the call. + B.SetInsertPoint(BB, CI); + + if (Name == "__memcpy_chk") { + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + // Should be similar to memcpy. + if (Name == "__mempcpy_chk") { + return 0; + } + + if (Name == "__memmove_chk") { + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + if (Name == "__memset_chk") { + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + Value *Val = B.CreateIntCast(CI->getOperand(2), B.getInt8Ty(), + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); + return ReplaceInstUsesWith(*CI, CI->getOperand(1)); + } + return 0; + } + + if (Name == "__strcpy_chk") { + ConstantInt *SizeCI = dyn_cast(CI->getOperand(3)); + if (!SizeCI) + return 0; + // If a) we don't have any length information, or b) we know this will + // fit then just lower to a plain strcpy. Otherwise we'll keep our + // strcpy_chk call which may fail at runtime if the size is too long. + // TODO: It might be nice to get a maximum length out of the possible + // string lengths for varying. + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2))) { + Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); + return ReplaceInstUsesWith(*CI, Ret); + } + return 0; + } + + // Should be similar to strcpy. + if (Name == "__stpcpy_chk") { + return 0; + } + + if (Name == "__strncpy_chk") { + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + ConstantInt *SizeArg = dyn_cast(CI->getOperand(3)); + if (!SizeArg) + return 0; + if (SizeCI->isAllOnesValue() || + SizeCI->getZExtValue() <= SizeArg->getZExtValue()) { + Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD); + return ReplaceInstUsesWith(*CI, Ret); + } + return 0; + } + + if (Name == "__strcat_chk") { + return 0; + } + + if (Name == "__strncat_chk") { + return 0; + } + + return 0; +} + // visitCallSite - Improvements for call and invoke instructions. // Instruction *InstCombiner::visitCallSite(CallSite CS) { @@ -772,6 +943,16 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) { Changed = true; } + // Try to optimize the call if possible, we require TargetData for most of + // this. None of these calls are seen as possibly dead so go ahead and + // delete the instruction now. + if (CallInst *CI = dyn_cast(CS.getInstruction())) { + Instruction *I = tryOptimizeCall(CI, TD); + // If we changed something return the result, etc. Otherwise let + // the fallthrough check. + if (I) return EraseInstFromFunction(*I); + } + return Changed ? CS.getInstruction() : 0; } @@ -796,7 +977,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { const Type *OldRetTy = Caller->getType(); const Type *NewRetTy = FT->getReturnType(); - if (isa(NewRetTy)) + if (NewRetTy->isStructTy()) return false; // TODO: Handle multiple return values. // Check to see if we are changing the return type... @@ -804,9 +985,9 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { if (Callee->isDeclaration() && // Conversion is ok if changing from one pointer type to another or from // a pointer to an integer of the same size. - !((isa(OldRetTy) || !TD || + !((OldRetTy->isPointerTy() || !TD || OldRetTy == TD->getIntPtrType(Caller->getContext())) && - (isa(NewRetTy) || !TD || + (NewRetTy->isPointerTy() || !TD || NewRetTy == TD->getIntPtrType(Caller->getContext())))) return false; // Cannot transform this return value. @@ -853,9 +1034,9 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { // Converting from one pointer type to another or between a pointer and an // integer of the same size is safe even if we do not have a body. bool isConvertible = ActTy == ParamTy || - (TD && ((isa(ParamTy) || + (TD && ((ParamTy->isPointerTy() || ParamTy == TD->getIntPtrType(Caller->getContext())) && - (isa(ActTy) || + (ActTy->isPointerTy() || ActTy == TD->getIntPtrType(Caller->getContext())))); if (Callee->isDeclaration() && !isConvertible) return false; } diff --git a/lib/Transforms/InstCombine/InstCombineCasts.cpp b/lib/Transforms/InstCombine/InstCombineCasts.cpp index 09cd21f144..a68fc6df47 100644 --- a/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -23,7 +23,7 @@ using namespace PatternMatch; /// static Value *DecomposeSimpleLinearExpr(Value *Val, unsigned &Scale, int &Offset) { - assert(Val->getType()->isInteger(32) && "Unexpected allocation size type!"); + assert(Val->getType()->isIntegerTy(32) && "Unexpected allocation size type!"); if (ConstantInt *CI = dyn_cast(Val)) { Offset = CI->getZExtValue(); Scale = 0; @@ -255,17 +255,26 @@ isEliminableCastPair( return Instruction::CastOps(Res); } -/// ValueRequiresCast - Return true if the cast from "V to Ty" actually results -/// in any code being generated. It does not require codegen if V is simple -/// enough or if the cast can be folded into other casts. -bool InstCombiner::ValueRequiresCast(Instruction::CastOps opcode,const Value *V, - const Type *Ty) { +/// ShouldOptimizeCast - Return true if the cast from "V to Ty" actually +/// results in any code being generated and is interesting to optimize out. If +/// the cast can be eliminated by some other simple transformation, we prefer +/// to do the simplification first. +bool InstCombiner::ShouldOptimizeCast(Instruction::CastOps opc, const Value *V, + const Type *Ty) { + // Noop casts and casts of constants should be eliminated trivially. if (V->getType() == Ty || isa(V)) return false; - // If this is another cast that can be eliminated, it isn't codegen either. + // If this is another cast that can be eliminated, we prefer to have it + // eliminated. if (const CastInst *CI = dyn_cast(V)) - if (isEliminableCastPair(CI, opcode, Ty, TD)) + if (isEliminableCastPair(CI, opc, Ty, TD)) return false; + + // If this is a vector sext from a compare, then we don't want to break the + // idiom where each element of the extended vector is either zero or all ones. + if (opc == Instruction::SExt && isa(V) && Ty->isVectorTy()) + return false; + return true; } @@ -294,8 +303,8 @@ Instruction *InstCombiner::commonCastTransforms(CastInst &CI) { if (isa(Src)) { // We don't do this if this would create a PHI node with an illegal type if // it is currently legal. - if (!isa(Src->getType()) || - !isa(CI.getType()) || + if (!Src->getType()->isIntegerTy() || + !CI.getType()->isIntegerTy() || ShouldChangeType(CI.getType(), Src->getType())) if (Instruction *NV = FoldOpIntoPhi(CI)) return NV; @@ -427,7 +436,7 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) { // type. Only do this if the dest type is a simple type, don't convert the // expression tree to something weird like i93 unless the source is also // strange. - if ((isa(DestTy) || ShouldChangeType(SrcTy, DestTy)) && + if ((DestTy->isVectorTy() || ShouldChangeType(SrcTy, DestTy)) && CanEvaluateTruncated(Src, DestTy)) { // If this cast is a truncate, evaluting in a different type always @@ -719,7 +728,7 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) { // expression tree to something weird like i93 unless the source is also // strange. unsigned BitsToClear; - if ((isa(DestTy) || ShouldChangeType(SrcTy, DestTy)) && + if ((DestTy->isVectorTy() || ShouldChangeType(SrcTy, DestTy)) && CanEvaluateZExtd(Src, DestTy, BitsToClear)) { assert(BitsToClear < SrcTy->getScalarSizeInBits() && "Unreasonable BitsToClear"); @@ -828,7 +837,7 @@ Instruction *InstCombiner::visitZExt(ZExtInst &CI) { // zext (xor i1 X, true) to i32 --> xor (zext i1 X to i32), 1 Value *X; - if (SrcI && SrcI->hasOneUse() && SrcI->getType()->isInteger(1) && + if (SrcI && SrcI->hasOneUse() && SrcI->getType()->isIntegerTy(1) && match(SrcI, m_Not(m_Value(X))) && (!X->hasOneUse() || !isa(X))) { Value *New = Builder->CreateZExt(X, CI.getType()); @@ -927,7 +936,7 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) { // type. Only do this if the dest type is a simple type, don't convert the // expression tree to something weird like i93 unless the source is also // strange. - if ((isa(DestTy) || ShouldChangeType(SrcTy, DestTy)) && + if ((DestTy->isVectorTy() || ShouldChangeType(SrcTy, DestTy)) && CanEvaluateSExtd(Src, DestTy)) { // Okay, we can transform this! Insert the new expression now. DEBUG(dbgs() << "ICE: EvaluateInDifferentType converting expression type" @@ -1280,7 +1289,7 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { Constant::getNullValue(Type::getInt32Ty(CI.getContext())); unsigned NumZeros = 0; while (SrcElTy != DstElTy && - isa(SrcElTy) && !isa(SrcElTy) && + isa(SrcElTy) && !SrcElTy->isPointerTy() && SrcElTy->getNumContainedTypes() /* not "{}" */) { SrcElTy = cast(SrcElTy)->getTypeAtIndex(ZeroUInt); ++NumZeros; @@ -1295,7 +1304,7 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { } if (const VectorType *DestVTy = dyn_cast(DestTy)) { - if (DestVTy->getNumElements() == 1 && !isa(SrcTy)) { + if (DestVTy->getNumElements() == 1 && !SrcTy->isVectorTy()) { Value *Elem = Builder->CreateBitCast(Src, DestVTy->getElementType()); return InsertElementInst::Create(UndefValue::get(DestTy), Elem, Constant::getNullValue(Type::getInt32Ty(CI.getContext()))); @@ -1304,7 +1313,7 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { } if (const VectorType *SrcVTy = dyn_cast(SrcTy)) { - if (SrcVTy->getNumElements() == 1 && !isa(DestTy)) { + if (SrcVTy->getNumElements() == 1 && !DestTy->isVectorTy()) { Value *Elem = Builder->CreateExtractElement(Src, Constant::getNullValue(Type::getInt32Ty(CI.getContext()))); @@ -1315,7 +1324,7 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { if (ShuffleVectorInst *SVI = dyn_cast(Src)) { // Okay, we have (bitcast (shuffle ..)). Check to see if this is // a bitconvert to a vector with the same # elts. - if (SVI->hasOneUse() && isa(DestTy) && + if (SVI->hasOneUse() && DestTy->isVectorTy() && cast(DestTy)->getNumElements() == SVI->getType()->getNumElements() && SVI->getType()->getNumElements() == @@ -1337,7 +1346,7 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { } } - if (isa(SrcTy)) + if (SrcTy->isPointerTy()) return commonPointerCastTransforms(CI); return commonCastTransforms(CI); } diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 7c00c2c61c..72fd5588d1 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -877,25 +877,26 @@ Instruction *InstCombiner::FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI, case ICmpInst::ICMP_EQ: if (LoOverflow && HiOverflow) return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(ICI.getContext())); - else if (HiOverflow) + if (HiOverflow) return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE, X, LoBound); - else if (LoOverflow) + if (LoOverflow) return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT, X, HiBound); - else - return InsertRangeTest(X, LoBound, HiBound, DivIsSigned, true, ICI); + return ReplaceInstUsesWith(ICI, + InsertRangeTest(X, LoBound, HiBound, DivIsSigned, + true)); case ICmpInst::ICMP_NE: if (LoOverflow && HiOverflow) return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(ICI.getContext())); - else if (HiOverflow) + if (HiOverflow) return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT, X, LoBound); - else if (LoOverflow) + if (LoOverflow) return new ICmpInst(DivIsSigned ? ICmpInst::ICMP_SGE : ICmpInst::ICMP_UGE, X, HiBound); - else - return InsertRangeTest(X, LoBound, HiBound, DivIsSigned, false, ICI); + return ReplaceInstUsesWith(ICI, InsertRangeTest(X, LoBound, HiBound, + DivIsSigned, false)); case ICmpInst::ICMP_ULT: case ICmpInst::ICMP_SLT: if (LoOverflow == +1) // Low bound is greater than input range. @@ -1606,7 +1607,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { const Type *Ty = Op0->getType(); // icmp's with boolean values can always be turned into bitwise operations - if (Ty->isInteger(1)) { + if (Ty->isIntegerTy(1)) { switch (I.getPredicate()) { default: llvm_unreachable("Invalid icmp instruction!"); case ICmpInst::ICMP_EQ: { // icmp eq i1 A, B -> ~(A^B) @@ -1650,7 +1651,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { unsigned BitWidth = 0; if (TD) BitWidth = TD->getTypeSizeInBits(Ty->getScalarType()); - else if (Ty->isIntOrIntVector()) + else if (Ty->isIntOrIntVectorTy()) BitWidth = Ty->getScalarSizeInBits(); bool isSignBit = false; @@ -1988,7 +1989,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { // values. If the ptr->ptr cast can be stripped off both arguments, we do so // now. if (BitCastInst *CI = dyn_cast(Op0)) { - if (isa(Op0->getType()) && + if (Op0->getType()->isPointerTy() && (isa(Op1) || isa(Op1))) { // We keep moving the cast from the left operand over to the right // operand, where it can often be eliminated completely. @@ -2458,17 +2459,17 @@ Instruction *InstCombiner::visitFCmpInst(FCmpInst &I) { return SelectInst::Create(LHSI->getOperand(0), Op1, Op2); break; } - case Instruction::Load: - if (GetElementPtrInst *GEP = - dyn_cast(LHSI->getOperand(0))) { - if (GlobalVariable *GV = dyn_cast(GEP->getOperand(0))) - if (GV->isConstant() && GV->hasDefinitiveInitializer() && - !cast(LHSI)->isVolatile()) - if (Instruction *Res = FoldCmpLoadFromIndexedGlobal(GEP, GV, I)) - return Res; + case Instruction::Load: + if (GetElementPtrInst *GEP = + dyn_cast(LHSI->getOperand(0))) { + if (GlobalVariable *GV = dyn_cast(GEP->getOperand(0))) + if (GV->isConstant() && GV->hasDefinitiveInitializer() && + !cast(LHSI)->isVolatile()) + if (Instruction *Res = FoldCmpLoadFromIndexedGlobal(GEP, GV, I)) + return Res; + } + break; } - break; - } } return Changed ? &I : 0; diff --git a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp index 2d13298300..0f2a24f59b 100644 --- a/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp +++ b/lib/Transforms/InstCombine/InstCombineLoadStoreAlloca.cpp @@ -87,8 +87,8 @@ static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI, const Type *SrcPTy = SrcTy->getElementType(); - if (DestPTy->isInteger() || isa(DestPTy) || - isa(DestPTy)) { + if (DestPTy->isIntegerTy() || DestPTy->isPointerTy() || + DestPTy->isVectorTy()) { // If the source is an array, the code below will not succeed. Check to // see if a trivial 'gep P, 0, 0' will help matters. Only do this for // constants. @@ -104,11 +104,11 @@ static Instruction *InstCombineLoadCast(InstCombiner &IC, LoadInst &LI, } if (IC.getTargetData() && - (SrcPTy->isInteger() || isa(SrcPTy) || - isa(SrcPTy)) && + (SrcPTy->isIntegerTy() || SrcPTy->isPointerTy() || + SrcPTy->isVectorTy()) && // Do not allow turning this into a load of an integer, which is then // casted to a pointer, this pessimizes pointer analysis a lot. - (isa(SrcPTy) == isa(LI.getType())) && + (SrcPTy->isPointerTy() == LI.getType()->isPointerTy()) && IC.getTargetData()->getTypeSizeInBits(SrcPTy) == IC.getTargetData()->getTypeSizeInBits(DestPTy)) { @@ -243,7 +243,7 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) { const Type *SrcPTy = SrcTy->getElementType(); - if (!DestPTy->isInteger() && !isa(DestPTy)) + if (!DestPTy->isIntegerTy() && !DestPTy->isPointerTy()) return 0; /// NewGEPIndices - If SrcPTy is an aggregate type, we can emit a "noop gep" @@ -255,7 +255,7 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) { // If the source is an array, the code below will not succeed. Check to // see if a trivial 'gep P, 0, 0' will help matters. Only do this for // constants. - if (isa(SrcPTy) || isa(SrcPTy)) { + if (SrcPTy->isArrayTy() || SrcPTy->isStructTy()) { // Index through pointer. Constant *Zero = Constant::getNullValue(Type::getInt32Ty(SI.getContext())); NewGEPIndices.push_back(Zero); @@ -277,7 +277,7 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) { SrcTy = PointerType::get(SrcPTy, SrcTy->getAddressSpace()); } - if (!SrcPTy->isInteger() && !isa(SrcPTy)) + if (!SrcPTy->isIntegerTy() && !SrcPTy->isPointerTy()) return 0; // If the pointers point into different address spaces or if they point to @@ -297,11 +297,11 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) { Instruction::CastOps opcode = Instruction::BitCast; const Type* CastSrcTy = SIOp0->getType(); const Type* CastDstTy = SrcPTy; - if (isa(CastDstTy)) { - if (CastSrcTy->isInteger()) + if (CastDstTy->isPointerTy()) { + if (CastSrcTy->isIntegerTy()) opcode = Instruction::IntToPtr; - } else if (isa(CastDstTy)) { - if (isa(SIOp0->getType())) + } else if (CastDstTy->isIntegerTy()) { + if (SIOp0->getType()->isPointerTy()) opcode = Instruction::PtrToInt; } @@ -413,7 +413,7 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) { // Don't count debug info directives, lest they affect codegen, // and we skip pointer-to-pointer bitcasts, which are NOPs. if (isa(BBI) || - (isa(BBI) && isa(BBI->getType()))) { + (isa(BBI) && BBI->getType()->isPointerTy())) { ScanInsts++; continue; } @@ -483,7 +483,7 @@ Instruction *InstCombiner::visitStoreInst(StoreInst &SI) { do { ++BBI; } while (isa(BBI) || - (isa(BBI) && isa(BBI->getType()))); + (isa(BBI) && BBI->getType()->isPointerTy())); if (BranchInst *BI = dyn_cast(BBI)) if (BI->isUnconditional()) if (SimplifyStoreAtEndOfBlock(SI)) @@ -544,7 +544,7 @@ bool InstCombiner::SimplifyStoreAtEndOfBlock(StoreInst &SI) { --BBI; // Skip over debugging info. while (isa(BBI) || - (isa(BBI) && isa(BBI->getType()))) { + (isa(BBI) && BBI->getType()->isPointerTy())) { if (BBI==OtherBB->begin()) return false; --BBI; diff --git a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 2e26a75b2a..b3974e8eef 100644 --- a/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -76,7 +76,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { return BinaryOperator::CreateShl(Op0, ConstantInt::get(Op0->getType(), Val.logBase2())); } - } else if (isa(Op1C->getType())) { + } else if (Op1C->getType()->isVectorTy()) { if (Op1C->isNullValue()) return ReplaceInstUsesWith(I, Op1C); @@ -157,7 +157,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { } /// i1 mul -> i1 and. - if (I.getType()->isInteger(1)) + if (I.getType()->isIntegerTy(1)) return BinaryOperator::CreateAnd(Op0, Op1); // X*(1 << Y) --> X << Y @@ -173,7 +173,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) { // If one of the operands of the multiply is a cast from a boolean value, then // we know the bool is either zero or one, so this is a 'masking' multiply. // X * Y (where Y is 0 or 1) -> X & (0-Y) - if (!isa(I.getType())) { + if (!I.getType()->isVectorTy()) { // -2 is "-1 << 1" so it is all bits set except the low one. APInt Negative2(I.getType()->getPrimitiveSizeInBits(), (uint64_t)-2, true); @@ -203,8 +203,8 @@ Instruction *InstCombiner::visitFMul(BinaryOperator &I) { // "In IEEE floating point, x*1 is not equivalent to x for nans. However, // ANSI says we can drop signals, so we can do this anyway." (from GCC) if (Op1F->isExactlyValue(1.0)) - return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0' - } else if (isa(Op1C->getType())) { + return ReplaceInstUsesWith(I, Op0); // Eliminate 'fmul double %X, 1.0' + } else if (Op1C->getType()->isVectorTy()) { if (ConstantVector *Op1V = dyn_cast(Op1C)) { // As above, vector X*splat(1.0) -> X in all defined cases. if (Constant *Splat = Op1V->getSplatValue()) { @@ -314,7 +314,7 @@ Instruction *InstCombiner::commonDivTransforms(BinaryOperator &I) { // undef / X -> 0 for integer. // undef / X -> undef for FP (the undef could be a snan). if (isa(Op0)) { - if (Op0->getType()->isFPOrFPVector()) + if (Op0->getType()->isFPOrFPVectorTy()) return ReplaceInstUsesWith(I, Op0); return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); } @@ -386,7 +386,7 @@ Instruction *InstCombiner::commonIDivTransforms(BinaryOperator &I) { return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); // It can't be division by zero, hence it must be division by one. - if (I.getType()->isInteger(1)) + if (I.getType()->isIntegerTy(1)) return ReplaceInstUsesWith(I, Op0); if (ConstantVector *Op1V = dyn_cast(Op1)) { @@ -493,7 +493,7 @@ Instruction *InstCombiner::visitSDiv(BinaryOperator &I) { // If the sign bits of both operands are zero (i.e. we can prove they are // unsigned inputs), turn this into a udiv. - if (I.getType()->isInteger()) { + if (I.getType()->isIntegerTy()) { APInt Mask(APInt::getSignBit(I.getType()->getPrimitiveSizeInBits())); if (MaskedValueIsZero(Op0, Mask)) { if (MaskedValueIsZero(Op1, Mask)) { @@ -527,7 +527,7 @@ Instruction *InstCombiner::commonRemTransforms(BinaryOperator &I) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); if (isa(Op0)) { // undef % X -> 0 - if (I.getType()->isFPOrFPVector()) + if (I.getType()->isFPOrFPVectorTy()) return ReplaceInstUsesWith(I, Op0); // X % undef -> undef (could be SNaN) return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType())); } @@ -648,7 +648,7 @@ Instruction *InstCombiner::visitSRem(BinaryOperator &I) { // If the sign bits of both operands are zero (i.e. we can prove they are // unsigned inputs), turn this into a urem. - if (I.getType()->isInteger()) { + if (I.getType()->isIntegerTy()) { APInt Mask(APInt::getSignBit(I.getType()->getPrimitiveSizeInBits())); if (MaskedValueIsZero(Op1, Mask) && MaskedValueIsZero(Op0, Mask)) { // X srem Y -> X urem Y, iff X and Y don't have sign bit set diff --git a/lib/Transforms/InstCombine/InstCombinePHI.cpp b/lib/Transforms/InstCombine/InstCombinePHI.cpp index bb7632fd2d..65f0393687 100644 --- a/lib/Transforms/InstCombine/InstCombinePHI.cpp +++ b/lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -266,6 +266,7 @@ Instruction *InstCombiner::FoldPHIArgLoadIntoPHI(PHINode &PN) { // and if TD isn't around, we can't handle the mixed case. bool isVolatile = FirstLI->isVolatile(); unsigned LoadAlignment = FirstLI->getAlignment(); + unsigned LoadAddrSpace = FirstLI->getPointerAddressSpace(); // We can't sink the load if the loaded value could be modified between the // load and the PHI. @@ -290,6 +291,7 @@ Instruction *InstCombiner::FoldPHIArgLoadIntoPHI(PHINode &PN) { // the load and the PHI. if (LI->isVolatile() != isVolatile || LI->getParent() != PN.getIncomingBlock(i) || + LI->getPointerAddressSpace() != LoadAddrSpace || !isSafeAndProfitableToSinkLoad(LI)) return 0; @@ -371,7 +373,7 @@ Instruction *InstCombiner::FoldPHIArgOpIntoPHI(PHINode &PN) { // Be careful about transforming integer PHIs. We don't want to pessimize // the code by turning an i32 into an i1293. - if (isa(PN.getType()) && isa(CastSrcTy)) { + if (PN.getType()->isIntegerTy() && CastSrcTy->isIntegerTy()) { if (!ShouldChangeType(PN.getType(), CastSrcTy)) return 0; } @@ -832,7 +834,7 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) { // it is only used by trunc or trunc(lshr) operations. If so, we split the // PHI into the various pieces being extracted. This sort of thing is // introduced when SROA promotes an aggregate to a single large integer type. - if (isa(PN.getType()) && TD && + if (PN.getType()->isIntegerTy() && TD && !TD->isLegalInteger(PN.getType()->getPrimitiveSizeInBits())) if (Instruction *Res = SliceUpIllegalIntegerPHI(PN)) return Res; diff --git a/lib/Transforms/InstCombine/InstCombineSelect.cpp b/lib/Transforms/InstCombine/InstCombineSelect.cpp index 9a02b33b7b..2fc932594f 100644 --- a/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -441,7 +441,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { return ReplaceInstUsesWith(SI, FalseVal); } - if (SI.getType()->isInteger(1)) { + if (SI.getType()->isIntegerTy(1)) { if (ConstantInt *C = dyn_cast(TrueVal)) { if (C->getZExtValue()) { // Change: A = select B, true, C --> A = or B, C @@ -539,9 +539,18 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { !CFPf->getValueAPF().isZero())) return ReplaceInstUsesWith(SI, FalseVal); } - // Transform (X != Y) ? X : Y -> X - if (FCI->getPredicate() == FCmpInst::FCMP_ONE) + // Transform (X une Y) ? X : Y -> X + if (FCI->getPredicate() == FCmpInst::FCMP_UNE) { + // This is not safe in general for floating point: + // consider X== -0, Y== +0. + // It becomes safe if either operand is a nonzero constant. + ConstantFP *CFPt, *CFPf; + if (((CFPt = dyn_cast(TrueVal)) && + !CFPt->getValueAPF().isZero()) || + ((CFPf = dyn_cast(FalseVal)) && + !CFPf->getValueAPF().isZero())) return ReplaceInstUsesWith(SI, TrueVal); + } // NOTE: if we wanted to, this is where to detect MIN/MAX } else if (FCI->getOperand(0) == FalseVal && FCI->getOperand(1) == TrueVal){ @@ -557,9 +566,18 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { !CFPf->getValueAPF().isZero())) return ReplaceInstUsesWith(SI, FalseVal); } - // Transform (X != Y) ? Y : X -> Y - if (FCI->getPredicate() == FCmpInst::FCMP_ONE) - return ReplaceInstUsesWith(SI, TrueVal); + // Transform (X une Y) ? Y : X -> Y + if (FCI->getPredicate() == FCmpInst::FCMP_UNE) { + // This is not safe in general for floating point: + // consider X== -0, Y== +0. + // It becomes safe if either operand is a nonzero constant. + ConstantFP *CFPt, *CFPf; + if (((CFPt = dyn_cast(TrueVal)) && + !CFPt->getValueAPF().isZero()) || + ((CFPf = dyn_cast(FalseVal)) && + !CFPf->getValueAPF().isZero())) + return ReplaceInstUsesWith(SI, TrueVal); + } // NOTE: if we wanted to, this is where to detect MIN/MAX } // NOTE: if we wanted to, this is where to detect ABS @@ -629,7 +647,7 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) { } // See if we can fold the select into one of our operands. - if (SI.getType()->isInteger()) { + if (SI.getType()->isIntegerTy()) { if (Instruction *FoldI = FoldSelectIntoOp(SI, TrueVal, FalseVal)) return FoldI; diff --git a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 53a568466e..cd41844c33 100644 --- a/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -104,10 +104,10 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, assert(Depth <= 6 && "Limit Search Depth"); uint32_t BitWidth = DemandedMask.getBitWidth(); const Type *VTy = V->getType(); - assert((TD || !isa(VTy)) && + assert((TD || !VTy->isPointerTy()) && "SimplifyDemandedBits needs to know bit widths!"); assert((!TD || TD->getTypeSizeInBits(VTy->getScalarType()) == BitWidth) && - (!VTy->isIntOrIntVector() || + (!VTy->isIntOrIntVectorTy() || VTy->getScalarSizeInBits() == BitWidth) && KnownZero.getBitWidth() == BitWidth && KnownOne.getBitWidth() == BitWidth && @@ -401,7 +401,7 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, break; } case Instruction::BitCast: - if (!I->getOperand(0)->getType()->isIntOrIntVector()) + if (!I->getOperand(0)->getType()->isIntOrIntVectorTy()) return 0; // vector->int or fp->int? if (const VectorType *DstVTy = dyn_cast(I->getType())) { @@ -413,7 +413,7 @@ Value *InstCombiner::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, } else // Don't touch a scalar-to-vector bitcast. return 0; - } else if (isa(I->getOperand(0)->getType())) + } else if (I->getOperand(0)->getType()->isVectorTy()) // Don't touch a vector-to-scalar bitcast. return 0; diff --git a/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/lib/Transforms/InstCombine/InstCombineVectorOps.cpp index 20fda1a271..a58124d703 100644 --- a/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -78,7 +78,7 @@ static std::vector getShuffleMask(const ShuffleVectorInst *SVI) { /// value is already around as a register, for example if it were inserted then /// extracted from the vector. static Value *FindScalarElement(Value *V, unsigned EltNo) { - assert(isa(V->getType()) && "Not looking at a vector?"); + assert(V->getType()->isVectorTy() && "Not looking at a vector?"); const VectorType *PTy = cast(V->getType()); unsigned Width = PTy->getNumElements(); if (EltNo >= Width) // Out of range access. @@ -322,7 +322,7 @@ static bool CollectSingleShuffleElements(Value *V, Value *LHS, Value *RHS, /// that computes V and the LHS value of the shuffle. static Value *CollectShuffleElements(Value *V, std::vector &Mask, Value *&RHS) { - assert(isa(V->getType()) && + assert(V->getType()->isVectorTy() && (RHS == 0 || V->getType() == RHS->getType()) && "Invalid shuffle!"); unsigned NumElts = cast(V->getType())->getNumElements(); diff --git a/lib/Transforms/InstCombine/InstructionCombining.cpp b/lib/Transforms/InstCombine/InstructionCombining.cpp index 93b196126b..af9ec5cacf 100644 --- a/lib/Transforms/InstCombine/InstructionCombining.cpp +++ b/lib/Transforms/InstCombine/InstructionCombining.cpp @@ -73,7 +73,7 @@ void InstCombiner::getAnalysisUsage(AnalysisUsage &AU) const { /// from 'From' to 'To'. We don't want to convert from a legal to an illegal /// type for example, or from a smaller to a larger illegal type. bool InstCombiner::ShouldChangeType(const Type *From, const Type *To) const { - assert(isa(From) && isa(To)); + assert(From->isIntegerTy() && To->isIntegerTy()); // If we don't have TD, we don't know if the source/dest are legal. if (!TD) return false; @@ -158,7 +158,7 @@ Value *InstCombiner::dyn_castNegVal(Value *V) const { return ConstantExpr::getNeg(C); if (ConstantVector *C = dyn_cast(V)) - if (C->getType()->getElementType()->isInteger()) + if (C->getType()->getElementType()->isIntegerTy()) return ConstantExpr::getNeg(C); return 0; @@ -177,7 +177,7 @@ Value *InstCombiner::dyn_castFNegVal(Value *V) const { return ConstantExpr::getFNeg(C); if (ConstantVector *C = dyn_cast(V)) - if (C->getType()->getElementType()->isFloatingPoint()) + if (C->getType()->getElementType()->isFloatingPointTy()) return ConstantExpr::getFNeg(C); return 0; @@ -226,7 +226,7 @@ Instruction *InstCombiner::FoldOpIntoSelect(Instruction &Op, SelectInst *SI) { if (isa(TV) || isa(FV)) { // Bool selects with constant operands can be folded to logical ops. - if (SI->getType()->isInteger(1)) return 0; + if (SI->getType()->isIntegerTy(1)) return 0; Value *SelectTrueVal = FoldOperationIntoSelectOperand(Op, TV, this); Value *SelectFalseVal = FoldOperationIntoSelectOperand(Op, FV, this); @@ -478,7 +478,7 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { bool EndsWithSequential = false; for (gep_type_iterator I = gep_type_begin(*Src), E = gep_type_end(*Src); I != E; ++I) - EndsWithSequential = !isa(*I); + EndsWithSequential = !(*I)->isStructTy(); // Can we combine the two pointer arithmetics offsets? if (EndsWithSequential) { @@ -578,7 +578,7 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { // into: %t1 = getelementptr [2 x i32]* %str, i32 0, i32 %V; bitcast const Type *SrcElTy = StrippedPtrTy->getElementType(); const Type *ResElTy=cast(PtrOp->getType())->getElementType(); - if (TD && isa(SrcElTy) && + if (TD && SrcElTy->isArrayTy() && TD->getTypeAllocSize(cast(SrcElTy)->getElementType()) == TD->getTypeAllocSize(ResElTy)) { Value *Idx[2]; @@ -596,7 +596,7 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { // (where tmp = 8*tmp2) into: // getelementptr [100 x double]* %arr, i32 0, i32 %tmp2; bitcast - if (TD && isa(SrcElTy) && ResElTy->isInteger(8)) { + if (TD && SrcElTy->isArrayTy() && ResElTy->isIntegerTy(8)) { uint64_t ArrayEltSize = TD->getTypeAllocSize(cast(SrcElTy)->getElementType()); diff --git a/lib/Transforms/Instrumentation/ProfilingUtils.cpp b/lib/Transforms/Instrumentation/ProfilingUtils.cpp index 3214c8c459..8662a82e8e 100644 --- a/lib/Transforms/Instrumentation/ProfilingUtils.cpp +++ b/lib/Transforms/Instrumentation/ProfilingUtils.cpp @@ -84,7 +84,7 @@ void llvm::InsertProfilingInitCall(Function *MainFn, const char *FnName, AI = MainFn->arg_begin(); // If the program looked at argc, have it look at the return value of the // init call instead. - if (!AI->getType()->isInteger(32)) { + if (!AI->getType()->isIntegerTy(32)) { Instruction::CastOps opcode; if (!AI->use_empty()) { opcode = CastInst::getCastOpcode(InitCall, true, AI->getType(), true); diff --git a/lib/Transforms/Scalar/ABCD.cpp b/lib/Transforms/Scalar/ABCD.cpp index cf5e8c07a5..ea8e5c3e53 100644 --- a/lib/Transforms/Scalar/ABCD.cpp +++ b/lib/Transforms/Scalar/ABCD.cpp @@ -505,7 +505,7 @@ void ABCD::executeABCD(Function &F) { continue; ICmpInst *ICI = dyn_cast(TI->getOperand(0)); - if (!ICI || !isa(ICI->getOperand(0)->getType())) + if (!ICI || !ICI->getOperand(0)->getType()->isIntegerTy()) continue; createConstraintCmpInst(ICI, TI); @@ -713,7 +713,7 @@ void ABCD::createConstraintCmpInst(ICmpInst *ICI, TerminatorInst *TI) { Value *V_op1 = ICI->getOperand(0); Value *V_op2 = ICI->getOperand(1); - if (!isa(V_op1->getType())) + if (!V_op1->getType()->isIntegerTy()) return; Instruction *I_op1 = dyn_cast(V_op1); diff --git a/lib/Transforms/Scalar/Android.mk b/lib/Transforms/Scalar/Android.mk new file mode 100644 index 0000000000..dea9b8ffe0 --- /dev/null +++ b/lib/Transforms/Scalar/Android.mk @@ -0,0 +1,55 @@ +LOCAL_PATH:= $(call my-dir) + +transforms_scalar_SRC_FILES := \ + ABCD.cpp \ + ADCE.cpp \ + BasicBlockPlacement.cpp \ + CodeGenPrepare.cpp \ + ConstantProp.cpp \ + DCE.cpp \ + DeadStoreElimination.cpp \ + GEPSplitter.cpp \ + GVN.cpp \ + IndVarSimplify.cpp \ + JumpThreading.cpp \ + LICM.cpp \ + LoopDeletion.cpp \ + LoopIndexSplit.cpp \ + LoopRotation.cpp \ + LoopStrengthReduce.cpp \ + LoopUnrollPass.cpp \ + LoopUnswitch.cpp \ + MemCpyOptimizer.cpp \ + Reassociate.cpp \ + Reg2Mem.cpp \ + SCCP.cpp \ + SCCVN.cpp \ + Scalar.cpp \ + ScalarReplAggregates.cpp \ + SimplifyCFGPass.cpp \ + SimplifyHalfPowrLibCalls.cpp \ + SimplifyLibCalls.cpp \ + TailDuplication.cpp \ + TailRecursionElimination.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(transforms_scalar_SRC_FILES) +LOCAL_MODULE:= libLLVMScalarOpts + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(transforms_scalar_SRC_FILES) +LOCAL_MODULE:= libLLVMScalarOpts + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index fa60d3f290..7ceda1fa1f 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -32,7 +32,6 @@ #include "llvm/ADT/SmallSet.h" #include "llvm/Assembly/Writer.h" #include "llvm/Support/CallSite.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/PatternMatch.h" @@ -40,9 +39,6 @@ using namespace llvm; using namespace llvm::PatternMatch; -static cl::opt FactorCommonPreds("split-critical-paths-tweak", - cl::init(false), cl::Hidden); - namespace { class CodeGenPrepare : public FunctionPass { /// TLI - Keep a pointer of a TargetLowering to consult for determining @@ -301,6 +297,70 @@ void CodeGenPrepare::EliminateMostlyEmptyBlock(BasicBlock *BB) { DEBUG(dbgs() << "AFTER:\n" << *DestBB << "\n\n\n"); } +/// FindReusablePredBB - Check all of the predecessors of the block DestPHI +/// lives in to see if there is a block that we can reuse as a critical edge +/// from TIBB. +static BasicBlock *FindReusablePredBB(PHINode *DestPHI, BasicBlock *TIBB) { + BasicBlock *Dest = DestPHI->getParent(); + + /// TIPHIValues - This array is lazily computed to determine the values of + /// PHIs in Dest that TI would provide. + SmallVector TIPHIValues; + + /// TIBBEntryNo - This is a cache to speed up pred queries for TIBB. + unsigned TIBBEntryNo = 0; + + // Check to see if Dest has any blocks that can be used as a split edge for + // this terminator. + for (unsigned pi = 0, e = DestPHI->getNumIncomingValues(); pi != e; ++pi) { + BasicBlock *Pred = DestPHI->getIncomingBlock(pi); + // To be usable, the pred has to end with an uncond branch to the dest. + BranchInst *PredBr = dyn_cast(Pred->getTerminator()); + if (!PredBr || !PredBr->isUnconditional()) + continue; + // Must be empty other than the branch and debug info. + BasicBlock::iterator I = Pred->begin(); + while (isa(I)) + I++; + if (&*I != PredBr) + continue; + // Cannot be the entry block; its label does not get emitted. + if (Pred == &Dest->getParent()->getEntryBlock()) + continue; + + // Finally, since we know that Dest has phi nodes in it, we have to make + // sure that jumping to Pred will have the same effect as going to Dest in + // terms of PHI values. + PHINode *PN; + unsigned PHINo = 0; + unsigned PredEntryNo = pi; + + bool FoundMatch = true; + for (BasicBlock::iterator I = Dest->begin(); + (PN = dyn_cast(I)); ++I, ++PHINo) { + if (PHINo == TIPHIValues.size()) { + if (PN->getIncomingBlock(TIBBEntryNo) != TIBB) + TIBBEntryNo = PN->getBasicBlockIndex(TIBB); + TIPHIValues.push_back(PN->getIncomingValue(TIBBEntryNo)); + } + + // If the PHI entry doesn't work, we can't use this pred. + if (PN->getIncomingBlock(PredEntryNo) != Pred) + PredEntryNo = PN->getBasicBlockIndex(Pred); + + if (TIPHIValues[PHINo] != PN->getIncomingValue(PredEntryNo)) { + FoundMatch = false; + break; + } + } + + // If we found a workable predecessor, change TI to branch to Succ. + if (FoundMatch) + return Pred; + } + return 0; +} + /// SplitEdgeNicely - Split the critical edge from TI to its specified /// successor if it will improve codegen. We only do this if the successor has @@ -315,13 +375,12 @@ static void SplitEdgeNicely(TerminatorInst *TI, unsigned SuccNum, BasicBlock *Dest = TI->getSuccessor(SuccNum); assert(isa(Dest->begin()) && "This should only be called if Dest has a PHI!"); + PHINode *DestPHI = cast(Dest->begin()); // Do not split edges to EH landing pads. - if (InvokeInst *Invoke = dyn_cast(TI)) { + if (InvokeInst *Invoke = dyn_cast(TI)) if (Invoke->getSuccessor(1) == Dest) return; - } - // As a hack, never split backedges of loops. Even though the copy for any // PHIs inserted on the backedge would be dead for exits from the loop, we @@ -329,92 +388,16 @@ static void SplitEdgeNicely(TerminatorInst *TI, unsigned SuccNum, if (BackEdges.count(std::make_pair(TIBB, Dest))) return; - if (!FactorCommonPreds) { - /// TIPHIValues - This array is lazily computed to determine the values of - /// PHIs in Dest that TI would provide. - SmallVector TIPHIValues; - - // Check to see if Dest has any blocks that can be used as a split edge for - // this terminator. - for (pred_iterator PI = pred_begin(Dest), E = pred_end(Dest); PI != E; ++PI) { - BasicBlock *Pred = *PI; - // To be usable, the pred has to end with an uncond branch to the dest. - BranchInst *PredBr = dyn_cast(Pred->getTerminator()); - if (!PredBr || !PredBr->isUnconditional()) - continue; - // Must be empty other than the branch and debug info. - BasicBlock::iterator I = Pred->begin(); - while (isa(I)) - I++; - if (dyn_cast(I) != PredBr) - continue; - // Cannot be the entry block; its label does not get emitted. - if (Pred == &(Dest->getParent()->getEntryBlock())) - continue; - - // Finally, since we know that Dest has phi nodes in it, we have to make - // sure that jumping to Pred will have the same effect as going to Dest in - // terms of PHI values. - PHINode *PN; - unsigned PHINo = 0; - bool FoundMatch = true; - for (BasicBlock::iterator I = Dest->begin(); - (PN = dyn_cast(I)); ++I, ++PHINo) { - if (PHINo == TIPHIValues.size()) - TIPHIValues.push_back(PN->getIncomingValueForBlock(TIBB)); - - // If the PHI entry doesn't work, we can't use this pred. - if (TIPHIValues[PHINo] != PN->getIncomingValueForBlock(Pred)) { - FoundMatch = false; - break; - } - } - - // If we found a workable predecessor, change TI to branch to Succ. - if (FoundMatch) { - ProfileInfo *PFI = P->getAnalysisIfAvailable(); - if (PFI) - PFI->splitEdge(TIBB, Dest, Pred); - Dest->removePredecessor(TIBB); - TI->setSuccessor(SuccNum, Pred); - return; - } - } - - SplitCriticalEdge(TI, SuccNum, P, true); + if (BasicBlock *ReuseBB = FindReusablePredBB(DestPHI, TIBB)) { + ProfileInfo *PFI = P->getAnalysisIfAvailable(); + if (PFI) + PFI->splitEdge(TIBB, Dest, ReuseBB); + Dest->removePredecessor(TIBB); + TI->setSuccessor(SuccNum, ReuseBB); return; } - PHINode *PN; - SmallVector TIPHIValues; - for (BasicBlock::iterator I = Dest->begin(); - (PN = dyn_cast(I)); ++I) - TIPHIValues.push_back(PN->getIncomingValueForBlock(TIBB)); - - SmallVector IdenticalPreds; - for (pred_iterator PI = pred_begin(Dest), E = pred_end(Dest); PI != E; ++PI) { - BasicBlock *Pred = *PI; - if (BackEdges.count(std::make_pair(Pred, Dest))) - continue; - if (PI == TIBB) - IdenticalPreds.push_back(Pred); - else { - bool Identical = true; - unsigned PHINo = 0; - for (BasicBlock::iterator I = Dest->begin(); - (PN = dyn_cast(I)); ++I, ++PHINo) - if (TIPHIValues[PHINo] != PN->getIncomingValueForBlock(Pred)) { - Identical = false; - break; - } - if (Identical) - IdenticalPreds.push_back(Pred); - } - } - - assert(!IdenticalPreds.empty()); - SplitBlockPredecessors(Dest, &IdenticalPreds[0], IdenticalPreds.size(), - ".critedge", P); + SplitCriticalEdge(TI, SuccNum, P, true); } @@ -629,7 +612,7 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, // we'd end up sinking both muls. if (AddrMode.BaseReg) { Value *V = AddrMode.BaseReg; - if (isa(V->getType())) + if (V->getType()->isPointerTy()) V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); if (V->getType() != IntPtrTy) V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true, @@ -642,7 +625,7 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, Value *V = AddrMode.ScaledReg; if (V->getType() == IntPtrTy) { // done. - } else if (isa(V->getType())) { + } else if (V->getType()->isPointerTy()) { V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); } else if (cast(IntPtrTy)->getBitWidth() < cast(V->getType())->getBitWidth()) { diff --git a/lib/Transforms/Scalar/DeadStoreElimination.cpp b/lib/Transforms/Scalar/DeadStoreElimination.cpp index 320afa19d5..09c01d3141 100644 --- a/lib/Transforms/Scalar/DeadStoreElimination.cpp +++ b/lib/Transforms/Scalar/DeadStoreElimination.cpp @@ -44,8 +44,14 @@ namespace { virtual bool runOnFunction(Function &F) { bool Changed = false; + + DominatorTree &DT = getAnalysis(); + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) - Changed |= runOnBasicBlock(*I); + // Only check non-dead blocks. Dead blocks may have strange pointer + // cycles that will confuse alias analysis. + if (DT.isReachableFromEntry(I)) + Changed |= runOnBasicBlock(*I); return Changed; } diff --git a/lib/Transforms/Scalar/GVN.cpp b/lib/Transforms/Scalar/GVN.cpp index 80e0027a17..fcb802a72a 100644 --- a/lib/Transforms/Scalar/GVN.cpp +++ b/lib/Transforms/Scalar/GVN.cpp @@ -662,11 +662,10 @@ namespace { bool runOnFunction(Function &F); public: static char ID; // Pass identification, replacement for typeid - explicit GVN(bool nopre = false, bool noloads = false) - : FunctionPass(&ID), NoPRE(nopre), NoLoads(noloads), MD(0) { } + explicit GVN(bool noloads = false) + : FunctionPass(&ID), NoLoads(noloads), MD(0) { } private: - bool NoPRE; bool NoLoads; MemoryDependenceAnalysis *MD; DominatorTree *DT; @@ -674,6 +673,9 @@ namespace { ValueTable VN; DenseMap localAvail; + // List of critical edges to be split between iterations. + SmallVector, 4> toSplit; + // This transformation requires dominator postdominator info virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); @@ -701,14 +703,15 @@ namespace { Value *lookupNumber(BasicBlock *BB, uint32_t num); void cleanupGlobalSets(); void verifyRemoved(const Instruction *I) const; + bool splitCriticalEdges(); }; char GVN::ID = 0; } // createGVNPass - The public interface to this file... -FunctionPass *llvm::createGVNPass(bool NoPRE, bool NoLoads) { - return new GVN(NoPRE, NoLoads); +FunctionPass *llvm::createGVNPass(bool NoLoads) { + return new GVN(NoLoads); } static RegisterPass X("gvn", @@ -836,9 +839,9 @@ static bool CanCoerceMustAliasedValueToLoad(Value *StoredVal, const TargetData &TD) { // If the loaded or stored value is an first class array or struct, don't try // to transform them. We need to be able to bitcast to integer. - if (isa(LoadTy) || isa(LoadTy) || - isa(StoredVal->getType()) || - isa(StoredVal->getType())) + if (LoadTy->isStructTy() || LoadTy->isArrayTy() || + StoredVal->getType()->isStructTy() || + StoredVal->getType()->isArrayTy()) return false; // The store has to be at least as big as the load. @@ -870,26 +873,26 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, // If the store and reload are the same size, we can always reuse it. if (StoreSize == LoadSize) { - if (isa(StoredValTy) && isa(LoadedTy)) { + if (StoredValTy->isPointerTy() && LoadedTy->isPointerTy()) { // Pointer to Pointer -> use bitcast. return new BitCastInst(StoredVal, LoadedTy, "", InsertPt); } // Convert source pointers to integers, which can be bitcast. - if (isa(StoredValTy)) { + if (StoredValTy->isPointerTy()) { StoredValTy = TD.getIntPtrType(StoredValTy->getContext()); StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt); } const Type *TypeToCastTo = LoadedTy; - if (isa(TypeToCastTo)) + if (TypeToCastTo->isPointerTy()) TypeToCastTo = TD.getIntPtrType(StoredValTy->getContext()); if (StoredValTy != TypeToCastTo) StoredVal = new BitCastInst(StoredVal, TypeToCastTo, "", InsertPt); // Cast to pointer if the load needs a pointer type. - if (isa(LoadedTy)) + if (LoadedTy->isPointerTy()) StoredVal = new IntToPtrInst(StoredVal, LoadedTy, "", InsertPt); return StoredVal; @@ -901,13 +904,13 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, assert(StoreSize >= LoadSize && "CanCoerceMustAliasedValueToLoad fail"); // Convert source pointers to integers, which can be manipulated. - if (isa(StoredValTy)) { + if (StoredValTy->isPointerTy()) { StoredValTy = TD.getIntPtrType(StoredValTy->getContext()); StoredVal = new PtrToIntInst(StoredVal, StoredValTy, "", InsertPt); } // Convert vectors and fp to integer, which can be manipulated. - if (!isa(StoredValTy)) { + if (!StoredValTy->isIntegerTy()) { StoredValTy = IntegerType::get(StoredValTy->getContext(), StoreSize); StoredVal = new BitCastInst(StoredVal, StoredValTy, "", InsertPt); } @@ -927,7 +930,7 @@ static Value *CoerceAvailableValueToLoadType(Value *StoredVal, return StoredVal; // If the result is a pointer, inttoptr. - if (isa(LoadedTy)) + if (LoadedTy->isPointerTy()) return new IntToPtrInst(StoredVal, LoadedTy, "inttoptr", InsertPt); // Otherwise, bitcast. @@ -989,7 +992,7 @@ static int AnalyzeLoadFromClobberingWrite(const Type *LoadTy, Value *LoadPtr, const TargetData &TD) { // If the loaded or stored value is an first class array or struct, don't try // to transform them. We need to be able to bitcast to integer. - if (isa(LoadTy) || isa(LoadTy)) + if (LoadTy->isStructTy() || LoadTy->isArrayTy()) return -1; int64_t StoreOffset = 0, LoadOffset = 0; @@ -1064,8 +1067,8 @@ static int AnalyzeLoadFromClobberingStore(const Type *LoadTy, Value *LoadPtr, StoreInst *DepSI, const TargetData &TD) { // Cannot handle reading from store of first-class aggregate yet. - if (isa(DepSI->getOperand(0)->getType()) || - isa(DepSI->getOperand(0)->getType())) + if (DepSI->getOperand(0)->getType()->isStructTy() || + DepSI->getOperand(0)->getType()->isArrayTy()) return -1; Value *StorePtr = DepSI->getPointerOperand(); @@ -1136,9 +1139,9 @@ static Value *GetStoreValueForLoad(Value *SrcVal, unsigned Offset, // Compute which bits of the stored value are being used by the load. Convert // to an integer type to start with. - if (isa(SrcVal->getType())) + if (SrcVal->getType()->isPointerTy()) SrcVal = Builder.CreatePtrToInt(SrcVal, TD.getIntPtrType(Ctx), "tmp"); - if (!isa(SrcVal->getType())) + if (!SrcVal->getType()->isIntegerTy()) SrcVal = Builder.CreateBitCast(SrcVal, IntegerType::get(Ctx, StoreSize*8), "tmp"); @@ -1323,7 +1326,7 @@ static Value *ConstructSSAForLoadSet(LoadInst *LI, Value *V = SSAUpdate.GetValueInMiddleOfBlock(LI->getParent()); // If new PHI nodes were created, notify alias analysis. - if (isa(V->getType())) + if (V->getType()->isPointerTy()) for (unsigned i = 0, e = NewPHIs.size(); i != e; ++i) AA->copyValue(LI, NewPHIs[i]); @@ -1491,8 +1494,9 @@ bool GVN::processNonLocalLoad(LoadInst *LI, if (isa(V)) V->takeName(LI); - if (isa(V->getType())) + if (V->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(V); + VN.erase(LI); toErase.push_back(LI); NumGVNLoad++; return true; @@ -1538,11 +1542,13 @@ bool GVN::processNonLocalLoad(LoadInst *LI, // at least one of the values is LI. Since this means that we won't be able // to eliminate LI even if we insert uses in the other predecessors, we will // end up increasing code size. Reject this by scanning for LI. - if (!EnableFullLoadPRE) { - for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i) - if (ValuesPerBlock[i].isSimpleValue() && - ValuesPerBlock[i].getSimpleValue() == LI) + for (unsigned i = 0, e = ValuesPerBlock.size(); i != e; ++i) { + if (ValuesPerBlock[i].isSimpleValue() && + ValuesPerBlock[i].getSimpleValue() == LI) { + // Skip cases where LI is the only definition, even for EnableFullLoadPRE. + if (!EnableFullLoadPRE || e == 1) return false; + } } // FIXME: It is extremely unclear what this loop is doing, other than @@ -1576,6 +1582,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI, for (unsigned i = 0, e = UnavailableBlocks.size(); i != e; ++i) FullyAvailableBlocks[UnavailableBlocks[i]] = false; + bool NeedToSplitEdges = false; for (pred_iterator PI = pred_begin(LoadBB), E = pred_end(LoadBB); PI != E; ++PI) { BasicBlock *Pred = *PI; @@ -1583,13 +1590,20 @@ bool GVN::processNonLocalLoad(LoadInst *LI, continue; } PredLoads[Pred] = 0; - // We don't currently handle critical edges :( + if (Pred->getTerminator()->getNumSuccessors() != 1) { - DEBUG(dbgs() << "COULD NOT PRE LOAD BECAUSE OF CRITICAL EDGE '" - << Pred->getName() << "': " << *LI << '\n'); - return false; + if (isa(Pred->getTerminator())) { + DEBUG(dbgs() << "COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '" + << Pred->getName() << "': " << *LI << '\n'); + return false; + } + unsigned SuccNum = GetSuccessorNumber(Pred, LoadBB); + toSplit.push_back(std::make_pair(Pred->getTerminator(), SuccNum)); + NeedToSplitEdges = true; } } + if (NeedToSplitEdges) + return false; // Decide whether PRE is profitable for this load. unsigned NumUnavailablePreds = PredLoads.size(); @@ -1623,13 +1637,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI, LoadPtr = Address.PHITranslateWithInsertion(LoadBB, UnavailablePred, *DT, NewInsts); } else { - Address.PHITranslateValue(LoadBB, UnavailablePred); + Address.PHITranslateValue(LoadBB, UnavailablePred, DT); LoadPtr = Address.getAddr(); - - // Make sure the value is live in the predecessor. - if (Instruction *Inst = dyn_cast_or_null(LoadPtr)) - if (!DT->dominates(Inst->getParent(), UnavailablePred)) - LoadPtr = 0; } // If we couldn't find or insert a computation of this phi translated value, @@ -1697,6 +1706,8 @@ bool GVN::processNonLocalLoad(LoadInst *LI, // Add the newly created load. ValuesPerBlock.push_back(AvailableValueInBlock::get(UnavailablePred, NewLoad)); + MD->invalidateCachedPointerInfo(LoadPtr); + DEBUG(dbgs() << "GVN INSERTED " << *NewLoad << '\n'); } // Perform PHI construction. @@ -1705,8 +1716,9 @@ bool GVN::processNonLocalLoad(LoadInst *LI, LI->replaceAllUsesWith(V); if (isa(V)) V->takeName(LI); - if (isa(V->getType())) + if (V->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(V); + VN.erase(LI); toErase.push_back(LI); NumPRELoad++; return true; @@ -1765,8 +1777,9 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // Replace the load! L->replaceAllUsesWith(AvailVal); - if (isa(AvailVal->getType())) + if (AvailVal->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(AvailVal); + VN.erase(L); toErase.push_back(L); NumGVNLoad++; return true; @@ -1810,8 +1823,9 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // Remove it! L->replaceAllUsesWith(StoredVal); - if (isa(StoredVal->getType())) + if (StoredVal->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(StoredVal); + VN.erase(L); toErase.push_back(L); NumGVNLoad++; return true; @@ -1839,8 +1853,9 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // Remove it! L->replaceAllUsesWith(AvailableVal); - if (isa(DepLI->getType())) + if (DepLI->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(DepLI); + VN.erase(L); toErase.push_back(L); NumGVNLoad++; return true; @@ -1851,6 +1866,7 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { // intervening stores, for example. if (isa(DepInst) || isMalloc(DepInst)) { L->replaceAllUsesWith(UndefValue::get(L->getType())); + VN.erase(L); toErase.push_back(L); NumGVNLoad++; return true; @@ -1861,6 +1877,7 @@ bool GVN::processLoad(LoadInst *L, SmallVectorImpl &toErase) { if (IntrinsicInst* II = dyn_cast(DepInst)) { if (II->getIntrinsicID() == Intrinsic::lifetime_start) { L->replaceAllUsesWith(UndefValue::get(L->getType())); + VN.erase(L); toErase.push_back(L); NumGVNLoad++; return true; @@ -1891,6 +1908,10 @@ Value *GVN::lookupNumber(BasicBlock *BB, uint32_t num) { /// by inserting it into the appropriate sets bool GVN::processInstruction(Instruction *I, SmallVectorImpl &toErase) { + // Ignore dbg info intrinsics. + if (isa(I)) + return false; + if (LoadInst *LI = dyn_cast(I)) { bool Changed = processLoad(LI, toErase); @@ -1939,7 +1960,7 @@ bool GVN::processInstruction(Instruction *I, if (constVal) { p->replaceAllUsesWith(constVal); - if (MD && isa(constVal->getType())) + if (MD && constVal->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(constVal); VN.erase(p); @@ -1960,7 +1981,7 @@ bool GVN::processInstruction(Instruction *I, // Remove it! VN.erase(I); I->replaceAllUsesWith(repl); - if (MD && isa(repl->getType())) + if (MD && repl->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(repl); toErase.push_back(I); return true; @@ -2000,6 +2021,8 @@ bool GVN::runOnFunction(Function& F) { while (ShouldContinue) { DEBUG(dbgs() << "GVN iteration: " << Iteration << "\n"); ShouldContinue = iterateOnFunction(F); + if (splitCriticalEdges()) + ShouldContinue = true; Changed |= ShouldContinue; ++Iteration; } @@ -2066,7 +2089,6 @@ bool GVN::processBlock(BasicBlock *BB) { /// control flow patterns and attempts to perform simple PRE at the join point. bool GVN::performPRE(Function &F) { bool Changed = false; - SmallVector, 4> toSplit; DenseMap predMap; for (df_iterator DI = df_begin(&F.getEntryBlock()), DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) { @@ -2137,14 +2159,7 @@ bool GVN::performPRE(Function &F) { // We can't do PRE safely on a critical edge, so instead we schedule // the edge to be split and perform the PRE the next time we iterate // on the function. - unsigned SuccNum = 0; - for (unsigned i = 0, e = PREPred->getTerminator()->getNumSuccessors(); - i != e; ++i) - if (PREPred->getTerminator()->getSuccessor(i) == CurrentBlock) { - SuccNum = i; - break; - } - + unsigned SuccNum = GetSuccessorNumber(PREPred, CurrentBlock); if (isCriticalEdge(PREPred->getTerminator(), SuccNum)) { toSplit.push_back(std::make_pair(PREPred->getTerminator(), SuccNum)); continue; @@ -2200,7 +2215,7 @@ bool GVN::performPRE(Function &F) { localAvail[CurrentBlock]->table[ValNo] = Phi; CurInst->replaceAllUsesWith(Phi); - if (MD && isa(Phi->getType())) + if (MD && Phi->getType()->isPointerTy()) MD->invalidateCachedPointerInfo(Phi); VN.erase(CurInst); @@ -2212,11 +2227,23 @@ bool GVN::performPRE(Function &F) { } } - for (SmallVector, 4>::iterator - I = toSplit.begin(), E = toSplit.end(); I != E; ++I) - SplitCriticalEdge(I->first, I->second, this); + if (splitCriticalEdges()) + Changed = true; + + return Changed; +} - return Changed || toSplit.size(); +/// splitCriticalEdges - Split critical edges found during the previous +/// iteration that may enable further optimization. +bool GVN::splitCriticalEdges() { + if (toSplit.empty()) + return false; + do { + std::pair Edge = toSplit.pop_back_val(); + SplitCriticalEdge(Edge.first, Edge.second, this); + } while (!toSplit.empty()); + if (MD) MD->invalidateCachedPredecessors(); + return true; } /// iterateOnFunction - Executes one iteration of GVN diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index c54f596f2c..cb563c3a7d 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -103,11 +103,9 @@ namespace { BasicBlock *ExitingBlock, BranchInst *BI, SCEVExpander &Rewriter); - void RewriteLoopExitValues(Loop *L, const SCEV *BackedgeTakenCount, - SCEVExpander &Rewriter); + void RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter); - void RewriteIVExpressions(Loop *L, const Type *LargestType, - SCEVExpander &Rewriter); + void RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter); void SinkUnusedInvariants(Loop *L); @@ -190,7 +188,7 @@ ICmpInst *IndVarSimplify::LinearFunctionTestReplace(Loop *L, ICmpInst *Cond = new ICmpInst(BI, Opcode, CmpIndVar, ExitCnt, "exitcond"); - Instruction *OrigCond = cast(BI->getCondition()); + Value *OrigCond = BI->getCondition(); // It's tempting to use replaceAllUsesWith here to fully replace the old // comparison, but that's not immediately safe, since users of the old // comparison may not be dominated by the new comparison. Instead, just @@ -215,7 +213,6 @@ ICmpInst *IndVarSimplify::LinearFunctionTestReplace(Loop *L, /// able to brute-force evaluate arbitrary instructions as long as they have /// constant operands at the beginning of the loop. void IndVarSimplify::RewriteLoopExitValues(Loop *L, - const SCEV *BackedgeTakenCount, SCEVExpander &Rewriter) { // Verify the input to the pass in already in LCSSA form. assert(L->isLCSSAForm()); @@ -241,15 +238,24 @@ void IndVarSimplify::RewriteLoopExitValues(Loop *L, while ((PN = dyn_cast(BBI++))) { if (PN->use_empty()) continue; // dead use, don't replace it + + // SCEV only supports integer expressions for now. + if (!PN->getType()->isIntegerTy() && !PN->getType()->isPointerTy()) + continue; + + // It's necessary to tell ScalarEvolution about this explicitly so that + // it can walk the def-use list and forget all SCEVs, as it may not be + // watching the PHI itself. Once the new exit value is in place, there + // may not be a def-use connection between the loop and every instruction + // which got a SCEVAddRecExpr for that loop. + SE->forgetValue(PN); + // Iterate over all of the values in all the PHI nodes. for (unsigned i = 0; i != NumPreds; ++i) { // If the value being merged in is not integer or is not defined // in the loop, skip it. Value *InVal = PN->getIncomingValue(i); - if (!isa(InVal) || - // SCEV only supports integer expressions for now. - (!isa(InVal->getType()) && - !isa(InVal->getType()))) + if (!isa(InVal)) continue; // If this pred is for a subloop, not L itself, skip it. @@ -349,7 +355,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { // the current expressions. // if (!isa(BackedgeTakenCount)) - RewriteLoopExitValues(L, BackedgeTakenCount, Rewriter); + RewriteLoopExitValues(L, Rewriter); // Compute the type of the largest recurrence expression, and decide whether // a canonical induction variable should be inserted. @@ -364,37 +370,32 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { if (ExitingBlock) NeedCannIV = true; } - for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { - const SCEV *Stride = IU->StrideOrder[i]; - const Type *Ty = SE->getEffectiveSCEVType(Stride->getType()); + for (IVUsers::const_iterator I = IU->begin(), E = IU->end(); I != E; ++I) { + const Type *Ty = + SE->getEffectiveSCEVType(I->getOperandValToReplace()->getType()); if (!LargestType || SE->getTypeSizeInBits(Ty) > SE->getTypeSizeInBits(LargestType)) LargestType = Ty; - - std::map::iterator SI = - IU->IVUsesByStride.find(IU->StrideOrder[i]); - assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); - - if (!SI->second->Users.empty()) - NeedCannIV = true; + NeedCannIV = true; } // Now that we know the largest of the induction variable expressions // in this loop, insert a canonical induction variable of the largest size. Value *IndVar = 0; if (NeedCannIV) { - // Check to see if the loop already has a canonical-looking induction - // variable. If one is present and it's wider than the planned canonical - // induction variable, temporarily remove it, so that the Rewriter - // doesn't attempt to reuse it. - PHINode *OldCannIV = L->getCanonicalInductionVariable(); - if (OldCannIV) { + // Check to see if the loop already has any canonical-looking induction + // variables. If any are present and wider than the planned canonical + // induction variable, temporarily remove them, so that the Rewriter + // doesn't attempt to reuse them. + SmallVector OldCannIVs; + while (PHINode *OldCannIV = L->getCanonicalInductionVariable()) { if (SE->getTypeSizeInBits(OldCannIV->getType()) > SE->getTypeSizeInBits(LargestType)) OldCannIV->removeFromParent(); else - OldCannIV = 0; + break; + OldCannIVs.push_back(OldCannIV); } IndVar = Rewriter.getOrInsertCanonicalInductionVariable(L, LargestType); @@ -404,17 +405,21 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { DEBUG(dbgs() << "INDVARS: New CanIV: " << *IndVar << '\n'); // Now that the official induction variable is established, reinsert - // the old canonical-looking variable after it so that the IR remains - // consistent. It will be deleted as part of the dead-PHI deletion at + // any old canonical-looking variables after it so that the IR remains + // consistent. They will be deleted as part of the dead-PHI deletion at // the end of the pass. - if (OldCannIV) - OldCannIV->insertAfter(cast(IndVar)); + while (!OldCannIVs.empty()) { + PHINode *OldCannIV = OldCannIVs.pop_back_val(); + OldCannIV->insertBefore(L->getHeader()->getFirstNonPHI()); + } } // If we have a trip count expression, rewrite the loop's exit condition // using it. We can currently only handle loops with a single exit. ICmpInst *NewICmp = 0; - if (!isa(BackedgeTakenCount) && ExitingBlock) { + if (!isa(BackedgeTakenCount) && + !BackedgeTakenCount->isZero() && + ExitingBlock) { assert(NeedCannIV && "LinearFunctionTestReplace requires a canonical induction variable"); // Can't rewrite non-branch yet. @@ -424,7 +429,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { } // Rewrite IV-derived expressions. Clears the rewriter cache. - RewriteIVExpressions(L, LargestType, Rewriter); + RewriteIVExpressions(L, Rewriter); // The Rewriter may not be used from this point on. @@ -444,8 +449,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { return Changed; } -void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, - SCEVExpander &Rewriter) { +void IndVarSimplify::RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter) { SmallVector DeadInsts; // Rewrite all induction variable expressions in terms of the canonical @@ -455,72 +459,64 @@ void IndVarSimplify::RewriteIVExpressions(Loop *L, const Type *LargestType, // add the offsets to the primary induction variable and cast, avoiding // the need for the code evaluation methods to insert induction variables // of different sizes. - for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { - const SCEV *Stride = IU->StrideOrder[i]; - - std::map::iterator SI = - IU->IVUsesByStride.find(IU->StrideOrder[i]); - assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); - ilist &List = SI->second->Users; - for (ilist::iterator UI = List.begin(), - E = List.end(); UI != E; ++UI) { - Value *Op = UI->getOperandValToReplace(); - const Type *UseTy = Op->getType(); - Instruction *User = UI->getUser(); - - // Compute the final addrec to expand into code. - const SCEV *AR = IU->getReplacementExpr(*UI); - - // Evaluate the expression out of the loop, if possible. - if (!L->contains(UI->getUser())) { - const SCEV *ExitVal = SE->getSCEVAtScope(AR, L->getParentLoop()); - if (ExitVal->isLoopInvariant(L)) - AR = ExitVal; - } + for (IVUsers::iterator UI = IU->begin(), E = IU->end(); UI != E; ++UI) { + const SCEV *Stride = UI->getStride(); + Value *Op = UI->getOperandValToReplace(); + const Type *UseTy = Op->getType(); + Instruction *User = UI->getUser(); + + // Compute the final addrec to expand into code. + const SCEV *AR = IU->getReplacementExpr(*UI); + + // Evaluate the expression out of the loop, if possible. + if (!L->contains(UI->getUser())) { + const SCEV *ExitVal = SE->getSCEVAtScope(AR, L->getParentLoop()); + if (ExitVal->isLoopInvariant(L)) + AR = ExitVal; + } - // FIXME: It is an extremely bad idea to indvar substitute anything more - // complex than affine induction variables. Doing so will put expensive - // polynomial evaluations inside of the loop, and the str reduction pass - // currently can only reduce affine polynomials. For now just disable - // indvar subst on anything more complex than an affine addrec, unless - // it can be expanded to a trivial value. - if (!AR->isLoopInvariant(L) && !Stride->isLoopInvariant(L)) - continue; + // FIXME: It is an extremely bad idea to indvar substitute anything more + // complex than affine induction variables. Doing so will put expensive + // polynomial evaluations inside of the loop, and the str reduction pass + // currently can only reduce affine polynomials. For now just disable + // indvar subst on anything more complex than an affine addrec, unless + // it can be expanded to a trivial value. + if (!AR->isLoopInvariant(L) && !Stride->isLoopInvariant(L)) + continue; - // Determine the insertion point for this user. By default, insert - // immediately before the user. The SCEVExpander class will automatically - // hoist loop invariants out of the loop. For PHI nodes, there may be - // multiple uses, so compute the nearest common dominator for the - // incoming blocks. - Instruction *InsertPt = User; - if (PHINode *PHI = dyn_cast(InsertPt)) - for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i) - if (PHI->getIncomingValue(i) == Op) { - if (InsertPt == User) - InsertPt = PHI->getIncomingBlock(i)->getTerminator(); - else - InsertPt = - DT->findNearestCommonDominator(InsertPt->getParent(), - PHI->getIncomingBlock(i)) - ->getTerminator(); - } - - // Now expand it into actual Instructions and patch it into place. - Value *NewVal = Rewriter.expandCodeFor(AR, UseTy, InsertPt); - - // Patch the new value into place. - if (Op->hasName()) - NewVal->takeName(Op); - User->replaceUsesOfWith(Op, NewVal); - UI->setOperandValToReplace(NewVal); - DEBUG(dbgs() << "INDVARS: Rewrote IV '" << *AR << "' " << *Op << '\n' - << " into = " << *NewVal << "\n"); - ++NumRemoved; - Changed = true; - - // The old value may be dead now. - DeadInsts.push_back(Op); - } + // Determine the insertion point for this user. By default, insert + // immediately before the user. The SCEVExpander class will automatically + // hoist loop invariants out of the loop. For PHI nodes, there may be + // multiple uses, so compute the nearest common dominator for the + // incoming blocks. + Instruction *InsertPt = User; + if (PHINode *PHI = dyn_cast(InsertPt)) + for (unsigned i = 0, e = PHI->getNumIncomingValues(); i != e; ++i) + if (PHI->getIncomingValue(i) == Op) { + if (InsertPt == User) + InsertPt = PHI->getIncomingBlock(i)->getTerminator(); + else + InsertPt = + DT->findNearestCommonDominator(InsertPt->getParent(), + PHI->getIncomingBlock(i)) + ->getTerminator(); + } + + // Now expand it into actual Instructions and patch it into place. + Value *NewVal = Rewriter.expandCodeFor(AR, UseTy, InsertPt); + + // Patch the new value into place. + if (Op->hasName()) + NewVal->takeName(Op); + User->replaceUsesOfWith(Op, NewVal); + UI->setOperandValToReplace(NewVal); + DEBUG(dbgs() << "INDVARS: Rewrote IV '" << *AR << "' " << *Op << '\n' + << " into = " << *NewVal << "\n"); + ++NumRemoved; + Changed = true; + + // The old value may be dead now. + DeadInsts.push_back(Op); } // Clear the rewriter cache, because values that are in the rewriter's cache @@ -598,8 +594,8 @@ void IndVarSimplify::SinkUnusedInvariants(Loop *L) { } } -/// Return true if it is OK to use SIToFPInst for an inducation variable -/// with given inital and exit values. +/// Return true if it is OK to use SIToFPInst for an induction variable +/// with given initial and exit values. static bool useSIToFPInst(ConstantFP &InitV, ConstantFP &ExitV, uint64_t intIV, uint64_t intEV) { @@ -652,7 +648,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH) { if (!convertToInt(InitValue->getValueAPF(), &newInitValue)) return; - // Check IV increment. Reject this PH if increement operation is not + // Check IV increment. Reject this PH if increment operation is not // an add or increment value can not be represented by an integer. BinaryOperator *Incr = dyn_cast(PH->getIncomingValue(BackEdge)); @@ -688,7 +684,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH) { if (BI->getCondition() != EC) return; } - // Find exit value. If exit value can not be represented as an interger then + // Find exit value. If exit value can not be represented as an integer then // do not handle this floating point PH. ConstantFP *EV = NULL; unsigned EVIndex = 1; @@ -750,11 +746,11 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH) { ICmpInst *NewEC = new ICmpInst(EC->getParent()->getTerminator(), NewPred, LHS, RHS, EC->getName()); - // In the following deltions, PH may become dead and may be deleted. + // In the following deletions, PH may become dead and may be deleted. // Use a WeakVH to observe whether this happens. WeakVH WeakPH = PH; - // Delete old, floating point, exit comparision instruction. + // Delete old, floating point, exit comparison instruction. NewEC->takeName(EC); EC->replaceAllUsesWith(NewEC); RecursivelyDeleteTriviallyDeadInstructions(EC); diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index 3eff3d8d23..a6489ecc2d 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -201,7 +201,7 @@ static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB) { if (isa(I)) continue; // If this is a pointer->pointer bitcast, it is free. - if (isa(I) && isa(I->getType())) + if (isa(I) && I->getType()->isPointerTy()) continue; // All other instructions count for at least one unit. @@ -214,7 +214,7 @@ static unsigned getJumpThreadDuplicationCost(const BasicBlock *BB) { if (const CallInst *CI = dyn_cast(I)) { if (!isa(CI)) Size += 3; - else if (!isa(CI->getType())) + else if (!CI->getType()->isVectorTy()) Size += 1; } } @@ -336,13 +336,18 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ else InterestingVal = ConstantInt::getFalse(I->getContext()); - // Scan for the sentinel. + // Scan for the sentinel. If we find an undef, force it to the + // interesting value: x|undef -> true and x&undef -> false. for (unsigned i = 0, e = LHSVals.size(); i != e; ++i) - if (LHSVals[i].first == InterestingVal || LHSVals[i].first == 0) + if (LHSVals[i].first == InterestingVal || LHSVals[i].first == 0) { Result.push_back(LHSVals[i]); + Result.back().first = InterestingVal; + } for (unsigned i = 0, e = RHSVals.size(); i != e; ++i) - if (RHSVals[i].first == InterestingVal || RHSVals[i].first == 0) + if (RHSVals[i].first == InterestingVal || RHSVals[i].first == 0) { Result.push_back(RHSVals[i]); + Result.back().first = InterestingVal; + } return !Result.empty(); } @@ -400,7 +405,7 @@ ComputeValueKnownInPredecessors(Value *V, BasicBlock *BB,PredValueInfo &Result){ // If comparing a live-in value against a constant, see if we know the // live-in value on any predecessors. if (LVI && isa(Cmp->getOperand(1)) && - Cmp->getType()->isInteger() && // Not vector compare. + Cmp->getType()->isIntegerTy() && // Not vector compare. (!isa(Cmp->getOperand(0)) || cast(Cmp->getOperand(0))->getParent() != BB)) { Constant *RHSCst = cast(Cmp->getOperand(1)); diff --git a/lib/Transforms/Scalar/LICM.cpp b/lib/Transforms/Scalar/LICM.cpp index 81f9ae61aa..d7ace342fc 100644 --- a/lib/Transforms/Scalar/LICM.cpp +++ b/lib/Transforms/Scalar/LICM.cpp @@ -678,7 +678,7 @@ void LICM::PromoteValuesInLoop() { // If we are promoting a pointer value, update alias information for the // inserted load. Value *LoadValue = 0; - if (isa(cast(Ptr->getType())->getElementType())) { + if (cast(Ptr->getType())->getElementType()->isPointerTy()) { // Locate a load or store through the pointer, and assign the same value // to LI as we are loading or storing. Since we know that the value is // stored in this loop, this will always succeed. @@ -751,7 +751,7 @@ void LICM::PromoteValuesInLoop() { LoadInst *LI = new LoadInst(PromotedValues[i].first, "", InsertPos); // If this is a pointer type, update alias info appropriately. - if (isa(LI->getType())) + if (LI->getType()->isPointerTy()) CurAST->copyValue(PointerValueNumbers[PVN++], LI); // Store into the memory we promoted. diff --git a/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/lib/Transforms/Scalar/LoopStrengthReduce.cpp index a5611ff113..f920dcab25 100644 --- a/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -17,6 +17,40 @@ // available on the target, and it performs a variety of other optimizations // related to loop induction variables. // +// Terminology note: this code has a lot of handling for "post-increment" or +// "post-inc" users. This is not talking about post-increment addressing modes; +// it is instead talking about code like this: +// +// %i = phi [ 0, %entry ], [ %i.next, %latch ] +// ... +// %i.next = add %i, 1 +// %c = icmp eq %i.next, %n +// +// The SCEV for %i is {0,+,1}<%L>. The SCEV for %i.next is {1,+,1}<%L>, however +// it's useful to think about these as the same register, with some uses using +// the value of the register before the add and some using // it after. In this +// example, the icmp is a post-increment user, since it uses %i.next, which is +// the value of the induction variable after the increment. The other common +// case of post-increment users is users outside the loop. +// +// TODO: More sophistication in the way Formulae are generated and filtered. +// +// TODO: Handle multiple loops at a time. +// +// TODO: Should TargetLowering::AddrMode::BaseGV be changed to a ConstantExpr +// instead of a GlobalValue? +// +// TODO: When truncation is free, truncate ICmp users' operands to make it a +// smaller encoding (on x86 at least). +// +// TODO: When a negated register is used by an add (such as in a list of +// multiple base registers, or as the increment expression in an addrec), +// we may not actually need both reg and (-1 * reg) in registers; the +// negation can be implemented by using a sub instead of an add. The +// lack of support for taking this into consideration when making +// register pressure decisions is partly worked around by the "Special" +// use kind. +// //===----------------------------------------------------------------------===// #define DEBUG_TYPE "loop-reduce" @@ -26,208 +60,434 @@ #include "llvm/IntrinsicInst.h" #include "llvm/DerivedTypes.h" #include "llvm/Analysis/IVUsers.h" +#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionExpander.h" -#include "llvm/Transforms/Utils/AddrModeMatcher.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" -#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetLowering.h" #include using namespace llvm; -STATISTIC(NumReduced , "Number of IV uses strength reduced"); -STATISTIC(NumInserted, "Number of PHIs inserted"); -STATISTIC(NumVariable, "Number of PHIs with variable strides"); -STATISTIC(NumEliminated, "Number of strides eliminated"); -STATISTIC(NumShadow, "Number of Shadow IVs optimized"); -STATISTIC(NumImmSunk, "Number of common expr immediates sunk into uses"); -STATISTIC(NumLoopCond, "Number of loop terminating conds optimized"); -STATISTIC(NumCountZero, "Number of count iv optimized to count toward zero"); +namespace { + +/// RegSortData - This class holds data which is used to order reuse candidates. +class RegSortData { +public: + /// UsedByIndices - This represents the set of LSRUse indices which reference + /// a particular register. + SmallBitVector UsedByIndices; + + RegSortData() {} + + void print(raw_ostream &OS) const; + void dump() const; +}; + +} + +void RegSortData::print(raw_ostream &OS) const { + OS << "[NumUses=" << UsedByIndices.count() << ']'; +} -static cl::opt EnableFullLSRMode("enable-full-lsr", - cl::init(false), - cl::Hidden); +void RegSortData::dump() const { + print(errs()); errs() << '\n'; +} namespace { - struct BasedUser; +/// RegUseTracker - Map register candidates to information about how they are +/// used. +class RegUseTracker { + typedef DenseMap RegUsesTy; - /// IVInfo - This structure keeps track of one IV expression inserted during - /// StrengthReduceStridedIVUsers. It contains the stride, the common base, as - /// well as the PHI node and increment value created for rewrite. - struct IVExpr { - const SCEV *Stride; - const SCEV *Base; - PHINode *PHI; + RegUsesTy RegUses; + SmallVector RegSequence; - IVExpr(const SCEV *const stride, const SCEV *const base, PHINode *phi) - : Stride(stride), Base(base), PHI(phi) {} - }; +public: + void CountRegister(const SCEV *Reg, size_t LUIdx); + + bool isRegUsedByUsesOtherThan(const SCEV *Reg, size_t LUIdx) const; + + const SmallBitVector &getUsedByIndices(const SCEV *Reg) const; + + void clear(); + + typedef SmallVectorImpl::iterator iterator; + typedef SmallVectorImpl::const_iterator const_iterator; + iterator begin() { return RegSequence.begin(); } + iterator end() { return RegSequence.end(); } + const_iterator begin() const { return RegSequence.begin(); } + const_iterator end() const { return RegSequence.end(); } +}; + +} + +void +RegUseTracker::CountRegister(const SCEV *Reg, size_t LUIdx) { + std::pair Pair = + RegUses.insert(std::make_pair(Reg, RegSortData())); + RegSortData &RSD = Pair.first->second; + if (Pair.second) + RegSequence.push_back(Reg); + RSD.UsedByIndices.resize(std::max(RSD.UsedByIndices.size(), LUIdx + 1)); + RSD.UsedByIndices.set(LUIdx); +} + +bool +RegUseTracker::isRegUsedByUsesOtherThan(const SCEV *Reg, size_t LUIdx) const { + if (!RegUses.count(Reg)) return false; + const SmallBitVector &UsedByIndices = + RegUses.find(Reg)->second.UsedByIndices; + int i = UsedByIndices.find_first(); + if (i == -1) return false; + if ((size_t)i != LUIdx) return true; + return UsedByIndices.find_next(i) != -1; +} + +const SmallBitVector &RegUseTracker::getUsedByIndices(const SCEV *Reg) const { + RegUsesTy::const_iterator I = RegUses.find(Reg); + assert(I != RegUses.end() && "Unknown register!"); + return I->second.UsedByIndices; +} + +void RegUseTracker::clear() { + RegUses.clear(); + RegSequence.clear(); +} + +namespace { + +/// Formula - This class holds information that describes a formula for +/// computing satisfying a use. It may include broken-out immediates and scaled +/// registers. +struct Formula { + /// AM - This is used to represent complex addressing, as well as other kinds + /// of interesting uses. + TargetLowering::AddrMode AM; + + /// BaseRegs - The list of "base" registers for this use. When this is + /// non-empty, AM.HasBaseReg should be set to true. + SmallVector BaseRegs; + + /// ScaledReg - The 'scaled' register for this use. This should be non-null + /// when AM.Scale is not zero. + const SCEV *ScaledReg; + + Formula() : ScaledReg(0) {} + + void InitialMatch(const SCEV *S, Loop *L, + ScalarEvolution &SE, DominatorTree &DT); + + unsigned getNumRegs() const; + const Type *getType() const; + + bool referencesReg(const SCEV *S) const; + bool hasRegsUsedByUsesOtherThan(size_t LUIdx, + const RegUseTracker &RegUses) const; + + void print(raw_ostream &OS) const; + void dump() const; +}; + +} + +/// DoInitialMatch - Recursion helper for InitialMatch. +static void DoInitialMatch(const SCEV *S, Loop *L, + SmallVectorImpl &Good, + SmallVectorImpl &Bad, + ScalarEvolution &SE, DominatorTree &DT) { + // Collect expressions which properly dominate the loop header. + if (S->properlyDominates(L->getHeader(), &DT)) { + Good.push_back(S); + return; + } - /// IVsOfOneStride - This structure keeps track of all IV expression inserted - /// during StrengthReduceStridedIVUsers for a particular stride of the IV. - struct IVsOfOneStride { - std::vector IVs; + // Look at add operands. + if (const SCEVAddExpr *Add = dyn_cast(S)) { + for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end(); + I != E; ++I) + DoInitialMatch(*I, L, Good, Bad, SE, DT); + return; + } - void addIV(const SCEV *const Stride, const SCEV *const Base, PHINode *PHI) { - IVs.push_back(IVExpr(Stride, Base, PHI)); + // Look at addrec operands. + if (const SCEVAddRecExpr *AR = dyn_cast(S)) + if (!AR->getStart()->isZero()) { + DoInitialMatch(AR->getStart(), L, Good, Bad, SE, DT); + DoInitialMatch(SE.getAddRecExpr(SE.getIntegerSCEV(0, AR->getType()), + AR->getStepRecurrence(SE), + AR->getLoop()), + L, Good, Bad, SE, DT); + return; } - }; - class LoopStrengthReduce : public LoopPass { - IVUsers *IU; - ScalarEvolution *SE; - bool Changed; - - /// IVsByStride - Keep track of all IVs that have been inserted for a - /// particular stride. - std::map IVsByStride; - - /// DeadInsts - Keep track of instructions we may have made dead, so that - /// we can remove them after we are done working. - SmallVector DeadInsts; - - /// TLI - Keep a pointer of a TargetLowering to consult for determining - /// transformation profitability. - const TargetLowering *TLI; - - public: - static char ID; // Pass ID, replacement for typeid - explicit LoopStrengthReduce(const TargetLowering *tli = NULL) : - LoopPass(&ID), TLI(tli) {} - - bool runOnLoop(Loop *L, LPPassManager &LPM); - - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - // We split critical edges, so we change the CFG. However, we do update - // many analyses if they are around. - AU.addPreservedID(LoopSimplifyID); - AU.addPreserved("loops"); - AU.addPreserved("domfrontier"); - AU.addPreserved("domtree"); - - AU.addRequiredID(LoopSimplifyID); - AU.addRequired(); - AU.addPreserved(); - AU.addRequired(); - AU.addPreserved(); + // Handle a multiplication by -1 (negation) if it didn't fold. + if (const SCEVMulExpr *Mul = dyn_cast(S)) + if (Mul->getOperand(0)->isAllOnesValue()) { + SmallVector Ops(Mul->op_begin()+1, Mul->op_end()); + const SCEV *NewMul = SE.getMulExpr(Ops); + + SmallVector MyGood; + SmallVector MyBad; + DoInitialMatch(NewMul, L, MyGood, MyBad, SE, DT); + const SCEV *NegOne = SE.getSCEV(ConstantInt::getAllOnesValue( + SE.getEffectiveSCEVType(NewMul->getType()))); + for (SmallVectorImpl::const_iterator I = MyGood.begin(), + E = MyGood.end(); I != E; ++I) + Good.push_back(SE.getMulExpr(NegOne, *I)); + for (SmallVectorImpl::const_iterator I = MyBad.begin(), + E = MyBad.end(); I != E; ++I) + Bad.push_back(SE.getMulExpr(NegOne, *I)); + return; } - private: - void OptimizeIndvars(Loop *L); - - /// OptimizeLoopTermCond - Change loop terminating condition to use the - /// postinc iv when possible. - void OptimizeLoopTermCond(Loop *L); - - /// OptimizeShadowIV - If IV is used in a int-to-float cast - /// inside the loop then try to eliminate the cast opeation. - void OptimizeShadowIV(Loop *L); - - /// OptimizeMax - Rewrite the loop's terminating condition - /// if it uses a max computation. - ICmpInst *OptimizeMax(Loop *L, ICmpInst *Cond, - IVStrideUse* &CondUse); - - /// OptimizeLoopCountIV - If, after all sharing of IVs, the IV used for - /// deciding when to exit the loop is used only for that purpose, try to - /// rearrange things so it counts down to a test against zero. - bool OptimizeLoopCountIV(Loop *L); - bool OptimizeLoopCountIVOfStride(const SCEV* &Stride, - IVStrideUse* &CondUse, Loop *L); - - /// StrengthReduceIVUsersOfStride - Strength reduce all of the users of a - /// single stride of IV. All of the users may have different starting - /// values, and this may not be the only stride. - void StrengthReduceIVUsersOfStride(const SCEV *Stride, - IVUsersOfOneStride &Uses, - Loop *L); - void StrengthReduceIVUsers(Loop *L); - - ICmpInst *ChangeCompareStride(Loop *L, ICmpInst *Cond, - IVStrideUse* &CondUse, - const SCEV* &CondStride, - bool PostPass = false); - - bool FindIVUserForCond(ICmpInst *Cond, IVStrideUse *&CondUse, - const SCEV* &CondStride); - bool RequiresTypeConversion(const Type *Ty, const Type *NewTy); - const SCEV *CheckForIVReuse(bool, bool, bool, const SCEV *, - IVExpr&, const Type*, - const std::vector& UsersToProcess); - bool ValidScale(bool, int64_t, - const std::vector& UsersToProcess); - bool ValidOffset(bool, int64_t, int64_t, - const std::vector& UsersToProcess); - const SCEV *CollectIVUsers(const SCEV *Stride, - IVUsersOfOneStride &Uses, - Loop *L, - bool &AllUsesAreAddresses, - bool &AllUsesAreOutsideLoop, - std::vector &UsersToProcess); - bool StrideMightBeShared(const SCEV *Stride, Loop *L, bool CheckPreInc); - bool ShouldUseFullStrengthReductionMode( - const std::vector &UsersToProcess, - const Loop *L, - bool AllUsesAreAddresses, - const SCEV *Stride); - void PrepareToStrengthReduceFully( - std::vector &UsersToProcess, - const SCEV *Stride, - const SCEV *CommonExprs, - const Loop *L, - SCEVExpander &PreheaderRewriter); - void PrepareToStrengthReduceFromSmallerStride( - std::vector &UsersToProcess, - Value *CommonBaseV, - const IVExpr &ReuseIV, - Instruction *PreInsertPt); - void PrepareToStrengthReduceWithNewPhi( - std::vector &UsersToProcess, - const SCEV *Stride, - const SCEV *CommonExprs, - Value *CommonBaseV, - Instruction *IVIncInsertPt, - const Loop *L, - SCEVExpander &PreheaderRewriter); - - void DeleteTriviallyDeadInstructions(); - }; + // Ok, we can't do anything interesting. Just stuff the whole thing into a + // register and hope for the best. + Bad.push_back(S); } -char LoopStrengthReduce::ID = 0; -static RegisterPass -X("loop-reduce", "Loop Strength Reduction"); +/// InitialMatch - Incorporate loop-variant parts of S into this Formula, +/// attempting to keep all loop-invariant and loop-computable values in a +/// single base register. +void Formula::InitialMatch(const SCEV *S, Loop *L, + ScalarEvolution &SE, DominatorTree &DT) { + SmallVector Good; + SmallVector Bad; + DoInitialMatch(S, L, Good, Bad, SE, DT); + if (!Good.empty()) { + BaseRegs.push_back(SE.getAddExpr(Good)); + AM.HasBaseReg = true; + } + if (!Bad.empty()) { + BaseRegs.push_back(SE.getAddExpr(Bad)); + AM.HasBaseReg = true; + } +} -Pass *llvm::createLoopStrengthReducePass(const TargetLowering *TLI) { - return new LoopStrengthReduce(TLI); +/// getNumRegs - Return the total number of register operands used by this +/// formula. This does not include register uses implied by non-constant +/// addrec strides. +unsigned Formula::getNumRegs() const { + return !!ScaledReg + BaseRegs.size(); } -/// DeleteTriviallyDeadInstructions - If any of the instructions is the -/// specified set are trivially dead, delete them and see if this makes any of -/// their operands subsequently dead. -void LoopStrengthReduce::DeleteTriviallyDeadInstructions() { - while (!DeadInsts.empty()) { - Instruction *I = dyn_cast_or_null(DeadInsts.pop_back_val()); +/// getType - Return the type of this formula, if it has one, or null +/// otherwise. This type is meaningless except for the bit size. +const Type *Formula::getType() const { + return !BaseRegs.empty() ? BaseRegs.front()->getType() : + ScaledReg ? ScaledReg->getType() : + AM.BaseGV ? AM.BaseGV->getType() : + 0; +} - if (I == 0 || !isInstructionTriviallyDead(I)) - continue; +/// referencesReg - Test if this formula references the given register. +bool Formula::referencesReg(const SCEV *S) const { + return S == ScaledReg || + std::find(BaseRegs.begin(), BaseRegs.end(), S) != BaseRegs.end(); +} - for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) - if (Instruction *U = dyn_cast(*OI)) { - *OI = 0; - if (U->use_empty()) - DeadInsts.push_back(U); +/// hasRegsUsedByUsesOtherThan - Test whether this formula uses registers +/// which are used by uses other than the use with the given index. +bool Formula::hasRegsUsedByUsesOtherThan(size_t LUIdx, + const RegUseTracker &RegUses) const { + if (ScaledReg) + if (RegUses.isRegUsedByUsesOtherThan(ScaledReg, LUIdx)) + return true; + for (SmallVectorImpl::const_iterator I = BaseRegs.begin(), + E = BaseRegs.end(); I != E; ++I) + if (RegUses.isRegUsedByUsesOtherThan(*I, LUIdx)) + return true; + return false; +} + +void Formula::print(raw_ostream &OS) const { + bool First = true; + if (AM.BaseGV) { + if (!First) OS << " + "; else First = false; + WriteAsOperand(OS, AM.BaseGV, /*PrintType=*/false); + } + if (AM.BaseOffs != 0) { + if (!First) OS << " + "; else First = false; + OS << AM.BaseOffs; + } + for (SmallVectorImpl::const_iterator I = BaseRegs.begin(), + E = BaseRegs.end(); I != E; ++I) { + if (!First) OS << " + "; else First = false; + OS << "reg(" << **I << ')'; + } + if (AM.Scale != 0) { + if (!First) OS << " + "; else First = false; + OS << AM.Scale << "*reg("; + if (ScaledReg) + OS << *ScaledReg; + else + OS << ""; + OS << ')'; + } +} + +void Formula::dump() const { + print(errs()); errs() << '\n'; +} + +/// isAddRecSExtable - Return true if the given addrec can be sign-extended +/// without changing its value. +static bool isAddRecSExtable(const SCEVAddRecExpr *AR, ScalarEvolution &SE) { + const Type *WideTy = + IntegerType::get(SE.getContext(), + SE.getTypeSizeInBits(AR->getType()) + 1); + return isa(SE.getSignExtendExpr(AR, WideTy)); +} + +/// isAddSExtable - Return true if the given add can be sign-extended +/// without changing its value. +static bool isAddSExtable(const SCEVAddExpr *A, ScalarEvolution &SE) { + const Type *WideTy = + IntegerType::get(SE.getContext(), + SE.getTypeSizeInBits(A->getType()) + 1); + return isa(SE.getSignExtendExpr(A, WideTy)); +} + +/// isMulSExtable - Return true if the given add can be sign-extended +/// without changing its value. +static bool isMulSExtable(const SCEVMulExpr *A, ScalarEvolution &SE) { + const Type *WideTy = + IntegerType::get(SE.getContext(), + SE.getTypeSizeInBits(A->getType()) + 1); + return isa(SE.getSignExtendExpr(A, WideTy)); +} + +/// getExactSDiv - Return an expression for LHS /s RHS, if it can be determined +/// and if the remainder is known to be zero, or null otherwise. If +/// IgnoreSignificantBits is true, expressions like (X * Y) /s Y are simplified +/// to Y, ignoring that the multiplication may overflow, which is useful when +/// the result will be used in a context where the most significant bits are +/// ignored. +static const SCEV *getExactSDiv(const SCEV *LHS, const SCEV *RHS, + ScalarEvolution &SE, + bool IgnoreSignificantBits = false) { + // Handle the trivial case, which works for any SCEV type. + if (LHS == RHS) + return SE.getIntegerSCEV(1, LHS->getType()); + + // Handle x /s -1 as x * -1, to give ScalarEvolution a chance to do some + // folding. + if (RHS->isAllOnesValue()) + return SE.getMulExpr(LHS, RHS); + + // Check for a division of a constant by a constant. + if (const SCEVConstant *C = dyn_cast(LHS)) { + const SCEVConstant *RC = dyn_cast(RHS); + if (!RC) + return 0; + if (C->getValue()->getValue().srem(RC->getValue()->getValue()) != 0) + return 0; + return SE.getConstant(C->getValue()->getValue() + .sdiv(RC->getValue()->getValue())); + } + + // Distribute the sdiv over addrec operands, if the addrec doesn't overflow. + if (const SCEVAddRecExpr *AR = dyn_cast(LHS)) { + if (IgnoreSignificantBits || isAddRecSExtable(AR, SE)) { + const SCEV *Start = getExactSDiv(AR->getStart(), RHS, SE, + IgnoreSignificantBits); + if (!Start) return 0; + const SCEV *Step = getExactSDiv(AR->getStepRecurrence(SE), RHS, SE, + IgnoreSignificantBits); + if (!Step) return 0; + return SE.getAddRecExpr(Start, Step, AR->getLoop()); + } + } + + // Distribute the sdiv over add operands, if the add doesn't overflow. + if (const SCEVAddExpr *Add = dyn_cast(LHS)) { + if (IgnoreSignificantBits || isAddSExtable(Add, SE)) { + SmallVector Ops; + for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end(); + I != E; ++I) { + const SCEV *Op = getExactSDiv(*I, RHS, SE, + IgnoreSignificantBits); + if (!Op) return 0; + Ops.push_back(Op); } + return SE.getAddExpr(Ops); + } + } - I->eraseFromParent(); - Changed = true; + // Check for a multiply operand that we can pull RHS out of. + if (const SCEVMulExpr *Mul = dyn_cast(LHS)) + if (IgnoreSignificantBits || isMulSExtable(Mul, SE)) { + SmallVector Ops; + bool Found = false; + for (SCEVMulExpr::op_iterator I = Mul->op_begin(), E = Mul->op_end(); + I != E; ++I) { + if (!Found) + if (const SCEV *Q = getExactSDiv(*I, RHS, SE, + IgnoreSignificantBits)) { + Ops.push_back(Q); + Found = true; + continue; + } + Ops.push_back(*I); + } + return Found ? SE.getMulExpr(Ops) : 0; + } + + // Otherwise we don't know. + return 0; +} + +/// ExtractImmediate - If S involves the addition of a constant integer value, +/// return that integer value, and mutate S to point to a new SCEV with that +/// value excluded. +static int64_t ExtractImmediate(const SCEV *&S, ScalarEvolution &SE) { + if (const SCEVConstant *C = dyn_cast(S)) { + if (C->getValue()->getValue().getMinSignedBits() <= 64) { + S = SE.getIntegerSCEV(0, C->getType()); + return C->getValue()->getSExtValue(); + } + } else if (const SCEVAddExpr *Add = dyn_cast(S)) { + SmallVector NewOps(Add->op_begin(), Add->op_end()); + int64_t Result = ExtractImmediate(NewOps.front(), SE); + S = SE.getAddExpr(NewOps); + return Result; + } else if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + SmallVector NewOps(AR->op_begin(), AR->op_end()); + int64_t Result = ExtractImmediate(NewOps.front(), SE); + S = SE.getAddRecExpr(NewOps, AR->getLoop()); + return Result; } + return 0; +} + +/// ExtractSymbol - If S involves the addition of a GlobalValue address, +/// return that symbol, and mutate S to point to a new SCEV with that +/// value excluded. +static GlobalValue *ExtractSymbol(const SCEV *&S, ScalarEvolution &SE) { + if (const SCEVUnknown *U = dyn_cast(S)) { + if (GlobalValue *GV = dyn_cast(U->getValue())) { + S = SE.getIntegerSCEV(0, GV->getType()); + return GV; + } + } else if (const SCEVAddExpr *Add = dyn_cast(S)) { + SmallVector NewOps(Add->op_begin(), Add->op_end()); + GlobalValue *Result = ExtractSymbol(NewOps.back(), SE); + S = SE.getAddExpr(NewOps); + return Result; + } else if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + SmallVector NewOps(AR->op_begin(), AR->op_end()); + GlobalValue *Result = ExtractSymbol(NewOps.front(), SE); + S = SE.getAddRecExpr(NewOps, AR->getLoop()); + return Result; + } + return 0; } /// isAddressUse - Returns true if the specified instruction is using the @@ -276,1776 +536,833 @@ static const Type *getAccessType(const Instruction *Inst) { break; } } + + // All pointers have the same requirements, so canonicalize them to an + // arbitrary pointer type to minimize variation. + if (const PointerType *PTy = dyn_cast(AccessTy)) + AccessTy = PointerType::get(IntegerType::get(PTy->getContext(), 1), + PTy->getAddressSpace()); + return AccessTy; } -namespace { - /// BasedUser - For a particular base value, keep information about how we've - /// partitioned the expression so far. - struct BasedUser { - /// Base - The Base value for the PHI node that needs to be inserted for - /// this use. As the use is processed, information gets moved from this - /// field to the Imm field (below). BasedUser values are sorted by this - /// field. - const SCEV *Base; - - /// Inst - The instruction using the induction variable. - Instruction *Inst; - - /// OperandValToReplace - The operand value of Inst to replace with the - /// EmittedBase. - Value *OperandValToReplace; - - /// Imm - The immediate value that should be added to the base immediately - /// before Inst, because it will be folded into the imm field of the - /// instruction. This is also sometimes used for loop-variant values that - /// must be added inside the loop. - const SCEV *Imm; - - /// Phi - The induction variable that performs the striding that - /// should be used for this user. - PHINode *Phi; - - // isUseOfPostIncrementedValue - True if this should use the - // post-incremented version of this IV, not the preincremented version. - // This can only be set in special cases, such as the terminating setcc - // instruction for a loop and uses outside the loop that are dominated by - // the loop. - bool isUseOfPostIncrementedValue; - - BasedUser(IVStrideUse &IVSU, ScalarEvolution *se) - : Base(IVSU.getOffset()), Inst(IVSU.getUser()), - OperandValToReplace(IVSU.getOperandValToReplace()), - Imm(se->getIntegerSCEV(0, Base->getType())), - isUseOfPostIncrementedValue(IVSU.isUseOfPostIncrementedValue()) {} - - // Once we rewrite the code to insert the new IVs we want, update the - // operands of Inst to use the new expression 'NewBase', with 'Imm' added - // to it. - void RewriteInstructionToUseNewBase(const SCEV *NewBase, - Instruction *InsertPt, - SCEVExpander &Rewriter, Loop *L, Pass *P, - SmallVectorImpl &DeadInsts, - ScalarEvolution *SE); - - Value *InsertCodeForBaseAtPosition(const SCEV *NewBase, - const Type *Ty, - SCEVExpander &Rewriter, - Instruction *IP, - ScalarEvolution *SE); - void dump() const; - }; -} +/// DeleteTriviallyDeadInstructions - If any of the instructions is the +/// specified set are trivially dead, delete them and see if this makes any of +/// their operands subsequently dead. +static bool +DeleteTriviallyDeadInstructions(SmallVectorImpl &DeadInsts) { + bool Changed = false; -void BasedUser::dump() const { - dbgs() << " Base=" << *Base; - dbgs() << " Imm=" << *Imm; - dbgs() << " Inst: " << *Inst; -} + while (!DeadInsts.empty()) { + Instruction *I = dyn_cast_or_null(DeadInsts.pop_back_val()); -Value *BasedUser::InsertCodeForBaseAtPosition(const SCEV *NewBase, - const Type *Ty, - SCEVExpander &Rewriter, - Instruction *IP, - ScalarEvolution *SE) { - Value *Base = Rewriter.expandCodeFor(NewBase, 0, IP); + if (I == 0 || !isInstructionTriviallyDead(I)) + continue; - // Wrap the base in a SCEVUnknown so that ScalarEvolution doesn't try to - // re-analyze it. - const SCEV *NewValSCEV = SE->getUnknown(Base); + for (User::op_iterator OI = I->op_begin(), E = I->op_end(); OI != E; ++OI) + if (Instruction *U = dyn_cast(*OI)) { + *OI = 0; + if (U->use_empty()) + DeadInsts.push_back(U); + } - // Always emit the immediate into the same block as the user. - NewValSCEV = SE->getAddExpr(NewValSCEV, Imm); + I->eraseFromParent(); + Changed = true; + } - return Rewriter.expandCodeFor(NewValSCEV, Ty, IP); + return Changed; } +namespace { -// Once we rewrite the code to insert the new IVs we want, update the -// operands of Inst to use the new expression 'NewBase', with 'Imm' added -// to it. NewBasePt is the last instruction which contributes to the -// value of NewBase in the case that it's a diffferent instruction from -// the PHI that NewBase is computed from, or null otherwise. -// -void BasedUser::RewriteInstructionToUseNewBase(const SCEV *NewBase, - Instruction *NewBasePt, - SCEVExpander &Rewriter, Loop *L, Pass *P, - SmallVectorImpl &DeadInsts, - ScalarEvolution *SE) { - if (!isa(Inst)) { - // By default, insert code at the user instruction. - BasicBlock::iterator InsertPt = Inst; - - // However, if the Operand is itself an instruction, the (potentially - // complex) inserted code may be shared by many users. Because of this, we - // want to emit code for the computation of the operand right before its old - // computation. This is usually safe, because we obviously used to use the - // computation when it was computed in its current block. However, in some - // cases (e.g. use of a post-incremented induction variable) the NewBase - // value will be pinned to live somewhere after the original computation. - // In this case, we have to back off. - // - // If this is a use outside the loop (which means after, since it is based - // on a loop indvar) we use the post-incremented value, so that we don't - // artificially make the preinc value live out the bottom of the loop. - if (!isUseOfPostIncrementedValue && L->contains(Inst)) { - if (NewBasePt && isa(OperandValToReplace)) { - InsertPt = NewBasePt; - ++InsertPt; - } else if (Instruction *OpInst - = dyn_cast(OperandValToReplace)) { - InsertPt = OpInst; - while (isa(InsertPt)) ++InsertPt; - } - } - Value *NewVal = InsertCodeForBaseAtPosition(NewBase, - OperandValToReplace->getType(), - Rewriter, InsertPt, SE); - // Replace the use of the operand Value with the new Phi we just created. - Inst->replaceUsesOfWith(OperandValToReplace, NewVal); - - DEBUG(dbgs() << " Replacing with "); - DEBUG(WriteAsOperand(dbgs(), NewVal, /*PrintType=*/false)); - DEBUG(dbgs() << ", which has value " << *NewBase << " plus IMM " - << *Imm << "\n"); - return; - } +/// Cost - This class is used to measure and compare candidate formulae. +class Cost { + /// TODO: Some of these could be merged. Also, a lexical ordering + /// isn't always optimal. + unsigned NumRegs; + unsigned AddRecCost; + unsigned NumIVMuls; + unsigned NumBaseAdds; + unsigned ImmCost; + unsigned SetupCost; + +public: + Cost() + : NumRegs(0), AddRecCost(0), NumIVMuls(0), NumBaseAdds(0), ImmCost(0), + SetupCost(0) {} + + unsigned getNumRegs() const { return NumRegs; } + + bool operator<(const Cost &Other) const; + + void Loose(); + + void RateFormula(const Formula &F, + SmallPtrSet &Regs, + const DenseSet &VisitedRegs, + const Loop *L, + const SmallVectorImpl &Offsets, + ScalarEvolution &SE, DominatorTree &DT); + + void print(raw_ostream &OS) const; + void dump() const; + +private: + void RateRegister(const SCEV *Reg, + SmallPtrSet &Regs, + const Loop *L, + ScalarEvolution &SE, DominatorTree &DT); + void RatePrimaryRegister(const SCEV *Reg, + SmallPtrSet &Regs, + const Loop *L, + ScalarEvolution &SE, DominatorTree &DT); +}; - // PHI nodes are more complex. We have to insert one copy of the NewBase+Imm - // expression into each operand block that uses it. Note that PHI nodes can - // have multiple entries for the same predecessor. We use a map to make sure - // that a PHI node only has a single Value* for each predecessor (which also - // prevents us from inserting duplicate code in some blocks). - DenseMap InsertedCode; - PHINode *PN = cast(Inst); - for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { - if (PN->getIncomingValue(i) == OperandValToReplace) { - // If the original expression is outside the loop, put the replacement - // code in the same place as the original expression, - // which need not be an immediate predecessor of this PHI. This way we - // need only one copy of it even if it is referenced multiple times in - // the PHI. We don't do this when the original expression is inside the - // loop because multiple copies sometimes do useful sinking of code in - // that case(?). - Instruction *OldLoc = dyn_cast(OperandValToReplace); - BasicBlock *PHIPred = PN->getIncomingBlock(i); - if (L->contains(OldLoc)) { - // If this is a critical edge, split the edge so that we do not insert - // the code on all predecessor/successor paths. We do this unless this - // is the canonical backedge for this loop, as this can make some - // inserted code be in an illegal position. - if (e != 1 && PHIPred->getTerminator()->getNumSuccessors() > 1 && - !isa(PHIPred->getTerminator()) && - (PN->getParent() != L->getHeader() || !L->contains(PHIPred))) { - - // First step, split the critical edge. - BasicBlock *NewBB = SplitCriticalEdge(PHIPred, PN->getParent(), - P, false); - - // Next step: move the basic block. In particular, if the PHI node - // is outside of the loop, and PredTI is in the loop, we want to - // move the block to be immediately before the PHI block, not - // immediately after PredTI. - if (L->contains(PHIPred) && !L->contains(PN)) - NewBB->moveBefore(PN->getParent()); - - // Splitting the edge can reduce the number of PHI entries we have. - e = PN->getNumIncomingValues(); - PHIPred = NewBB; - i = PN->getBasicBlockIndex(PHIPred); - } - } - Value *&Code = InsertedCode[PHIPred]; - if (!Code) { - // Insert the code into the end of the predecessor block. - Instruction *InsertPt = (L->contains(OldLoc)) ? - PHIPred->getTerminator() : - OldLoc->getParent()->getTerminator(); - Code = InsertCodeForBaseAtPosition(NewBase, PN->getType(), - Rewriter, InsertPt, SE); - - DEBUG(dbgs() << " Changing PHI use to "); - DEBUG(WriteAsOperand(dbgs(), Code, /*PrintType=*/false)); - DEBUG(dbgs() << ", which has value " << *NewBase << " plus IMM " - << *Imm << "\n"); - } +} + +/// RateRegister - Tally up interesting quantities from the given register. +void Cost::RateRegister(const SCEV *Reg, + SmallPtrSet &Regs, + const Loop *L, + ScalarEvolution &SE, DominatorTree &DT) { + if (const SCEVAddRecExpr *AR = dyn_cast(Reg)) { + if (AR->getLoop() == L) + AddRecCost += 1; /// TODO: This should be a function of the stride. + + // If this is an addrec for a loop that's already been visited by LSR, + // don't second-guess its addrec phi nodes. LSR isn't currently smart + // enough to reason about more than one loop at a time. Consider these + // registers free and leave them alone. + else if (L->contains(AR->getLoop()) || + (!AR->getLoop()->contains(L) && + DT.dominates(L->getHeader(), AR->getLoop()->getHeader()))) { + for (BasicBlock::iterator I = AR->getLoop()->getHeader()->begin(); + PHINode *PN = dyn_cast(I); ++I) + if (SE.isSCEVable(PN->getType()) && + (SE.getEffectiveSCEVType(PN->getType()) == + SE.getEffectiveSCEVType(AR->getType())) && + SE.getSCEV(PN) == AR) + return; - // Replace the use of the operand Value with the new Phi we just created. - PN->setIncomingValue(i, Code); - Rewriter.clear(); + // If this isn't one of the addrecs that the loop already has, it + // would require a costly new phi and add. TODO: This isn't + // precisely modeled right now. + ++NumBaseAdds; + if (!Regs.count(AR->getStart())) + RateRegister(AR->getStart(), Regs, L, SE, DT); } - } - // PHI node might have become a constant value after SplitCriticalEdge. - DeadInsts.push_back(Inst); + // Add the step value register, if it needs one. + // TODO: The non-affine case isn't precisely modeled here. + if (!AR->isAffine() || !isa(AR->getOperand(1))) + if (!Regs.count(AR->getStart())) + RateRegister(AR->getOperand(1), Regs, L, SE, DT); + } + ++NumRegs; + + // Rough heuristic; favor registers which don't require extra setup + // instructions in the preheader. + if (!isa(Reg) && + !isa(Reg) && + !(isa(Reg) && + (isa(cast(Reg)->getStart()) || + isa(cast(Reg)->getStart())))) + ++SetupCost; } +/// RatePrimaryRegister - Record this register in the set. If we haven't seen it +/// before, rate it. +void Cost::RatePrimaryRegister(const SCEV *Reg, + SmallPtrSet &Regs, + const Loop *L, + ScalarEvolution &SE, DominatorTree &DT) { + if (Regs.insert(Reg)) + RateRegister(Reg, Regs, L, SE, DT); +} -/// fitsInAddressMode - Return true if V can be subsumed within an addressing -/// mode, and does not need to be put in a register first. -static bool fitsInAddressMode(const SCEV *V, const Type *AccessTy, - const TargetLowering *TLI, bool HasBaseReg) { - if (const SCEVConstant *SC = dyn_cast(V)) { - int64_t VC = SC->getValue()->getSExtValue(); - if (TLI) { - TargetLowering::AddrMode AM; - AM.BaseOffs = VC; - AM.HasBaseReg = HasBaseReg; - return TLI->isLegalAddressingMode(AM, AccessTy); - } else { - // Defaults to PPC. PPC allows a sign-extended 16-bit immediate field. - return (VC > -(1 << 16) && VC < (1 << 16)-1); +void Cost::RateFormula(const Formula &F, + SmallPtrSet &Regs, + const DenseSet &VisitedRegs, + const Loop *L, + const SmallVectorImpl &Offsets, + ScalarEvolution &SE, DominatorTree &DT) { + // Tally up the registers. + if (const SCEV *ScaledReg = F.ScaledReg) { + if (VisitedRegs.count(ScaledReg)) { + Loose(); + return; } + RatePrimaryRegister(ScaledReg, Regs, L, SE, DT); } - - if (const SCEVUnknown *SU = dyn_cast(V)) - if (GlobalValue *GV = dyn_cast(SU->getValue())) { - if (TLI) { - TargetLowering::AddrMode AM; - AM.BaseGV = GV; - AM.HasBaseReg = HasBaseReg; - return TLI->isLegalAddressingMode(AM, AccessTy); - } else { - // Default: assume global addresses are not legal. - } + for (SmallVectorImpl::const_iterator I = F.BaseRegs.begin(), + E = F.BaseRegs.end(); I != E; ++I) { + const SCEV *BaseReg = *I; + if (VisitedRegs.count(BaseReg)) { + Loose(); + return; } + RatePrimaryRegister(BaseReg, Regs, L, SE, DT); - return false; + NumIVMuls += isa(BaseReg) && + BaseReg->hasComputableLoopEvolution(L); + } + + if (F.BaseRegs.size() > 1) + NumBaseAdds += F.BaseRegs.size() - 1; + + // Tally up the non-zero immediates. + for (SmallVectorImpl::const_iterator I = Offsets.begin(), + E = Offsets.end(); I != E; ++I) { + int64_t Offset = (uint64_t)*I + F.AM.BaseOffs; + if (F.AM.BaseGV) + ImmCost += 64; // Handle symbolic values conservatively. + // TODO: This should probably be the pointer size. + else if (Offset != 0) + ImmCost += APInt(64, Offset, true).getMinSignedBits(); + } } -/// MoveLoopVariantsToImmediateField - Move any subexpressions from Val that are -/// loop varying to the Imm operand. -static void MoveLoopVariantsToImmediateField(const SCEV *&Val, const SCEV *&Imm, - Loop *L, ScalarEvolution *SE) { - if (Val->isLoopInvariant(L)) return; // Nothing to do. +/// Loose - Set this cost to a loosing value. +void Cost::Loose() { + NumRegs = ~0u; + AddRecCost = ~0u; + NumIVMuls = ~0u; + NumBaseAdds = ~0u; + ImmCost = ~0u; + SetupCost = ~0u; +} - if (const SCEVAddExpr *SAE = dyn_cast(Val)) { - SmallVector NewOps; - NewOps.reserve(SAE->getNumOperands()); +/// operator< - Choose the lower cost. +bool Cost::operator<(const Cost &Other) const { + if (NumRegs != Other.NumRegs) + return NumRegs < Other.NumRegs; + if (AddRecCost != Other.AddRecCost) + return AddRecCost < Other.AddRecCost; + if (NumIVMuls != Other.NumIVMuls) + return NumIVMuls < Other.NumIVMuls; + if (NumBaseAdds != Other.NumBaseAdds) + return NumBaseAdds < Other.NumBaseAdds; + if (ImmCost != Other.ImmCost) + return ImmCost < Other.ImmCost; + if (SetupCost != Other.SetupCost) + return SetupCost < Other.SetupCost; + return false; +} - for (unsigned i = 0; i != SAE->getNumOperands(); ++i) - if (!SAE->getOperand(i)->isLoopInvariant(L)) { - // If this is a loop-variant expression, it must stay in the immediate - // field of the expression. - Imm = SE->getAddExpr(Imm, SAE->getOperand(i)); - } else { - NewOps.push_back(SAE->getOperand(i)); - } +void Cost::print(raw_ostream &OS) const { + OS << NumRegs << " reg" << (NumRegs == 1 ? "" : "s"); + if (AddRecCost != 0) + OS << ", with addrec cost " << AddRecCost; + if (NumIVMuls != 0) + OS << ", plus " << NumIVMuls << " IV mul" << (NumIVMuls == 1 ? "" : "s"); + if (NumBaseAdds != 0) + OS << ", plus " << NumBaseAdds << " base add" + << (NumBaseAdds == 1 ? "" : "s"); + if (ImmCost != 0) + OS << ", plus " << ImmCost << " imm cost"; + if (SetupCost != 0) + OS << ", plus " << SetupCost << " setup cost"; +} - if (NewOps.empty()) - Val = SE->getIntegerSCEV(0, Val->getType()); - else - Val = SE->getAddExpr(NewOps); - } else if (const SCEVAddRecExpr *SARE = dyn_cast(Val)) { - // Try to pull immediates out of the start value of nested addrec's. - const SCEV *Start = SARE->getStart(); - MoveLoopVariantsToImmediateField(Start, Imm, L, SE); - - SmallVector Ops(SARE->op_begin(), SARE->op_end()); - Ops[0] = Start; - Val = SE->getAddRecExpr(Ops, SARE->getLoop()); - } else { - // Otherwise, all of Val is variant, move the whole thing over. - Imm = SE->getAddExpr(Imm, Val); - Val = SE->getIntegerSCEV(0, Val->getType()); - } +void Cost::dump() const { + print(errs()); errs() << '\n'; } +namespace { -/// MoveImmediateValues - Look at Val, and pull out any additions of constants -/// that can fit into the immediate field of instructions in the target. -/// Accumulate these immediate values into the Imm value. -static void MoveImmediateValues(const TargetLowering *TLI, - const Type *AccessTy, - const SCEV *&Val, const SCEV *&Imm, - bool isAddress, Loop *L, - ScalarEvolution *SE) { - if (const SCEVAddExpr *SAE = dyn_cast(Val)) { - SmallVector NewOps; - NewOps.reserve(SAE->getNumOperands()); +/// LSRFixup - An operand value in an instruction which is to be replaced +/// with some equivalent, possibly strength-reduced, replacement. +struct LSRFixup { + /// UserInst - The instruction which will be updated. + Instruction *UserInst; - for (unsigned i = 0; i != SAE->getNumOperands(); ++i) { - const SCEV *NewOp = SAE->getOperand(i); - MoveImmediateValues(TLI, AccessTy, NewOp, Imm, isAddress, L, SE); + /// OperandValToReplace - The operand of the instruction which will + /// be replaced. The operand may be used more than once; every instance + /// will be replaced. + Value *OperandValToReplace; - if (!NewOp->isLoopInvariant(L)) { - // If this is a loop-variant expression, it must stay in the immediate - // field of the expression. - Imm = SE->getAddExpr(Imm, NewOp); - } else { - NewOps.push_back(NewOp); - } - } + /// PostIncLoop - If this user is to use the post-incremented value of an + /// induction variable, this variable is non-null and holds the loop + /// associated with the induction variable. + const Loop *PostIncLoop; - if (NewOps.empty()) - Val = SE->getIntegerSCEV(0, Val->getType()); - else - Val = SE->getAddExpr(NewOps); - return; - } else if (const SCEVAddRecExpr *SARE = dyn_cast(Val)) { - // Try to pull immediates out of the start value of nested addrec's. - const SCEV *Start = SARE->getStart(); - MoveImmediateValues(TLI, AccessTy, Start, Imm, isAddress, L, SE); - - if (Start != SARE->getStart()) { - SmallVector Ops(SARE->op_begin(), SARE->op_end()); - Ops[0] = Start; - Val = SE->getAddRecExpr(Ops, SARE->getLoop()); - } - return; - } else if (const SCEVMulExpr *SME = dyn_cast(Val)) { - // Transform "8 * (4 + v)" -> "32 + 8*V" if "32" fits in the immed field. - if (isAddress && - fitsInAddressMode(SME->getOperand(0), AccessTy, TLI, false) && - SME->getNumOperands() == 2 && SME->isLoopInvariant(L)) { - - const SCEV *SubImm = SE->getIntegerSCEV(0, Val->getType()); - const SCEV *NewOp = SME->getOperand(1); - MoveImmediateValues(TLI, AccessTy, NewOp, SubImm, isAddress, L, SE); - - // If we extracted something out of the subexpressions, see if we can - // simplify this! - if (NewOp != SME->getOperand(1)) { - // Scale SubImm up by "8". If the result is a target constant, we are - // good. - SubImm = SE->getMulExpr(SubImm, SME->getOperand(0)); - if (fitsInAddressMode(SubImm, AccessTy, TLI, false)) { - // Accumulate the immediate. - Imm = SE->getAddExpr(Imm, SubImm); - - // Update what is left of 'Val'. - Val = SE->getMulExpr(SME->getOperand(0), NewOp); - return; - } - } - } - } + /// LUIdx - The index of the LSRUse describing the expression which + /// this fixup needs, minus an offset (below). + size_t LUIdx; - // Loop-variant expressions must stay in the immediate field of the - // expression. - if ((isAddress && fitsInAddressMode(Val, AccessTy, TLI, false)) || - !Val->isLoopInvariant(L)) { - Imm = SE->getAddExpr(Imm, Val); - Val = SE->getIntegerSCEV(0, Val->getType()); - return; + /// Offset - A constant offset to be added to the LSRUse expression. + /// This allows multiple fixups to share the same LSRUse with different + /// offsets, for example in an unrolled loop. + int64_t Offset; + + LSRFixup(); + + void print(raw_ostream &OS) const; + void dump() const; +}; + +} + +LSRFixup::LSRFixup() + : UserInst(0), OperandValToReplace(0), PostIncLoop(0), + LUIdx(~size_t(0)), Offset(0) {} + +void LSRFixup::print(raw_ostream &OS) const { + OS << "UserInst="; + // Store is common and interesting enough to be worth special-casing. + if (StoreInst *Store = dyn_cast(UserInst)) { + OS << "store "; + WriteAsOperand(OS, Store->getOperand(0), /*PrintType=*/false); + } else if (UserInst->getType()->isVoidTy()) + OS << UserInst->getOpcodeName(); + else + WriteAsOperand(OS, UserInst, /*PrintType=*/false); + + OS << ", OperandValToReplace="; + WriteAsOperand(OS, OperandValToReplace, /*PrintType=*/false); + + if (PostIncLoop) { + OS << ", PostIncLoop="; + WriteAsOperand(OS, PostIncLoop->getHeader(), /*PrintType=*/false); } - // Otherwise, no immediates to move. + if (LUIdx != ~size_t(0)) + OS << ", LUIdx=" << LUIdx; + + if (Offset != 0) + OS << ", Offset=" << Offset; } -static void MoveImmediateValues(const TargetLowering *TLI, - Instruction *User, - const SCEV *&Val, const SCEV *&Imm, - bool isAddress, Loop *L, - ScalarEvolution *SE) { - const Type *AccessTy = getAccessType(User); - MoveImmediateValues(TLI, AccessTy, Val, Imm, isAddress, L, SE); +void LSRFixup::dump() const { + print(errs()); errs() << '\n'; } -/// SeparateSubExprs - Decompose Expr into all of the subexpressions that are -/// added together. This is used to reassociate common addition subexprs -/// together for maximal sharing when rewriting bases. -static void SeparateSubExprs(SmallVector &SubExprs, - const SCEV *Expr, - ScalarEvolution *SE) { - if (const SCEVAddExpr *AE = dyn_cast(Expr)) { - for (unsigned j = 0, e = AE->getNumOperands(); j != e; ++j) - SeparateSubExprs(SubExprs, AE->getOperand(j), SE); - } else if (const SCEVAddRecExpr *SARE = dyn_cast(Expr)) { - const SCEV *Zero = SE->getIntegerSCEV(0, Expr->getType()); - if (SARE->getOperand(0) == Zero) { - SubExprs.push_back(Expr); - } else { - // Compute the addrec with zero as its base. - SmallVector Ops(SARE->op_begin(), SARE->op_end()); - Ops[0] = Zero; // Start with zero base. - SubExprs.push_back(SE->getAddRecExpr(Ops, SARE->getLoop())); +namespace { +/// UniquifierDenseMapInfo - A DenseMapInfo implementation for holding +/// DenseMaps and DenseSets of sorted SmallVectors of const SCEV*. +struct UniquifierDenseMapInfo { + static SmallVector getEmptyKey() { + SmallVector V; + V.push_back(reinterpret_cast(-1)); + return V; + } - SeparateSubExprs(SubExprs, SARE->getOperand(0), SE); - } - } else if (!Expr->isZero()) { - // Do not add zero. - SubExprs.push_back(Expr); - } -} - -// This is logically local to the following function, but C++ says we have -// to make it file scope. -struct SubExprUseData { unsigned Count; bool notAllUsesAreFree; }; - -/// RemoveCommonExpressionsFromUseBases - Look through all of the Bases of all -/// the Uses, removing any common subexpressions, except that if all such -/// subexpressions can be folded into an addressing mode for all uses inside -/// the loop (this case is referred to as "free" in comments herein) we do -/// not remove anything. This looks for things like (a+b+c) and -/// (a+c+d) and computes the common (a+c) subexpression. The common expression -/// is *removed* from the Bases and returned. -static const SCEV * -RemoveCommonExpressionsFromUseBases(std::vector &Uses, - ScalarEvolution *SE, Loop *L, - const TargetLowering *TLI) { - unsigned NumUses = Uses.size(); - - // Only one use? This is a very common case, so we handle it specially and - // cheaply. - const SCEV *Zero = SE->getIntegerSCEV(0, Uses[0].Base->getType()); - const SCEV *Result = Zero; - const SCEV *FreeResult = Zero; - if (NumUses == 1) { - // If the use is inside the loop, use its base, regardless of what it is: - // it is clearly shared across all the IV's. If the use is outside the loop - // (which means after it) we don't want to factor anything *into* the loop, - // so just use 0 as the base. - if (L->contains(Uses[0].Inst)) - std::swap(Result, Uses[0].Base); + static SmallVector getTombstoneKey() { + SmallVector V; + V.push_back(reinterpret_cast(-2)); + return V; + } + + static unsigned getHashValue(const SmallVector &V) { + unsigned Result = 0; + for (SmallVectorImpl::const_iterator I = V.begin(), + E = V.end(); I != E; ++I) + Result ^= DenseMapInfo::getHashValue(*I); return Result; } - // To find common subexpressions, count how many of Uses use each expression. - // If any subexpressions are used Uses.size() times, they are common. - // Also track whether all uses of each expression can be moved into an - // an addressing mode "for free"; such expressions are left within the loop. - // struct SubExprUseData { unsigned Count; bool notAllUsesAreFree; }; - std::map SubExpressionUseData; - - // UniqueSubExprs - Keep track of all of the subexpressions we see in the - // order we see them. - SmallVector UniqueSubExprs; - - SmallVector SubExprs; - unsigned NumUsesInsideLoop = 0; - for (unsigned i = 0; i != NumUses; ++i) { - // If the user is outside the loop, just ignore it for base computation. - // Since the user is outside the loop, it must be *after* the loop (if it - // were before, it could not be based on the loop IV). We don't want users - // after the loop to affect base computation of values *inside* the loop, - // because we can always add their offsets to the result IV after the loop - // is done, ensuring we get good code inside the loop. - if (!L->contains(Uses[i].Inst)) - continue; - NumUsesInsideLoop++; + static bool isEqual(const SmallVector &LHS, + const SmallVector &RHS) { + return LHS == RHS; + } +}; + +/// LSRUse - This class holds the state that LSR keeps for each use in +/// IVUsers, as well as uses invented by LSR itself. It includes information +/// about what kinds of things can be folded into the user, information about +/// the user itself, and information about how the use may be satisfied. +/// TODO: Represent multiple users of the same expression in common? +class LSRUse { + DenseSet, UniquifierDenseMapInfo> Uniquifier; + +public: + /// KindType - An enum for a kind of use, indicating what types of + /// scaled and immediate operands it might support. + enum KindType { + Basic, ///< A normal use, with no folding. + Special, ///< A special case of basic, allowing -1 scales. + Address, ///< An address use; folding according to TargetLowering + ICmpZero ///< An equality icmp with both operands folded into one. + // TODO: Add a generic icmp too? + }; - // If the base is zero (which is common), return zero now, there are no - // CSEs we can find. - if (Uses[i].Base == Zero) return Zero; + KindType Kind; + const Type *AccessTy; - // If this use is as an address we may be able to put CSEs in the addressing - // mode rather than hoisting them. - bool isAddrUse = isAddressUse(Uses[i].Inst, Uses[i].OperandValToReplace); - // We may need the AccessTy below, but only when isAddrUse, so compute it - // only in that case. - const Type *AccessTy = 0; - if (isAddrUse) - AccessTy = getAccessType(Uses[i].Inst); - - // Split the expression into subexprs. - SeparateSubExprs(SubExprs, Uses[i].Base, SE); - // Add one to SubExpressionUseData.Count for each subexpr present, and - // if the subexpr is not a valid immediate within an addressing mode use, - // set SubExpressionUseData.notAllUsesAreFree. We definitely want to - // hoist these out of the loop (if they are common to all uses). - for (unsigned j = 0, e = SubExprs.size(); j != e; ++j) { - if (++SubExpressionUseData[SubExprs[j]].Count == 1) - UniqueSubExprs.push_back(SubExprs[j]); - if (!isAddrUse || !fitsInAddressMode(SubExprs[j], AccessTy, TLI, false)) - SubExpressionUseData[SubExprs[j]].notAllUsesAreFree = true; - } - SubExprs.clear(); - } - - // Now that we know how many times each is used, build Result. Iterate over - // UniqueSubexprs so that we have a stable ordering. - for (unsigned i = 0, e = UniqueSubExprs.size(); i != e; ++i) { - std::map::iterator I = - SubExpressionUseData.find(UniqueSubExprs[i]); - assert(I != SubExpressionUseData.end() && "Entry not found?"); - if (I->second.Count == NumUsesInsideLoop) { // Found CSE! - if (I->second.notAllUsesAreFree) - Result = SE->getAddExpr(Result, I->first); - else - FreeResult = SE->getAddExpr(FreeResult, I->first); - } else - // Remove non-cse's from SubExpressionUseData. - SubExpressionUseData.erase(I); - } - - if (FreeResult != Zero) { - // We have some subexpressions that can be subsumed into addressing - // modes in every use inside the loop. However, it's possible that - // there are so many of them that the combined FreeResult cannot - // be subsumed, or that the target cannot handle both a FreeResult - // and a Result in the same instruction (for example because it would - // require too many registers). Check this. - for (unsigned i=0; icontains(Uses[i].Inst)) - continue; - // We know this is an addressing mode use; if there are any uses that - // are not, FreeResult would be Zero. - const Type *AccessTy = getAccessType(Uses[i].Inst); - if (!fitsInAddressMode(FreeResult, AccessTy, TLI, Result!=Zero)) { - // FIXME: could split up FreeResult into pieces here, some hoisted - // and some not. There is no obvious advantage to this. - Result = SE->getAddExpr(Result, FreeResult); - FreeResult = Zero; - break; - } - } - } + SmallVector Offsets; + int64_t MinOffset; + int64_t MaxOffset; - // If we found no CSE's, return now. - if (Result == Zero) return Result; + /// AllFixupsOutsideLoop - This records whether all of the fixups using this + /// LSRUse are outside of the loop, in which case some special-case heuristics + /// may be used. + bool AllFixupsOutsideLoop; - // If we still have a FreeResult, remove its subexpressions from - // SubExpressionUseData. This means they will remain in the use Bases. - if (FreeResult != Zero) { - SeparateSubExprs(SubExprs, FreeResult, SE); - for (unsigned j = 0, e = SubExprs.size(); j != e; ++j) { - std::map::iterator I = - SubExpressionUseData.find(SubExprs[j]); - SubExpressionUseData.erase(I); - } - SubExprs.clear(); - } + /// Formulae - A list of ways to build a value that can satisfy this user. + /// After the list is populated, one of these is selected heuristically and + /// used to formulate a replacement for OperandValToReplace in UserInst. + SmallVector Formulae; - // Otherwise, remove all of the CSE's we found from each of the base values. - for (unsigned i = 0; i != NumUses; ++i) { - // Uses outside the loop don't necessarily include the common base, but - // the final IV value coming into those uses does. Instead of trying to - // remove the pieces of the common base, which might not be there, - // subtract off the base to compensate for this. - if (!L->contains(Uses[i].Inst)) { - Uses[i].Base = SE->getMinusSCEV(Uses[i].Base, Result); - continue; - } + /// Regs - The set of register candidates used by all formulae in this LSRUse. + SmallPtrSet Regs; - // Split the expression into subexprs. - SeparateSubExprs(SubExprs, Uses[i].Base, SE); + LSRUse(KindType K, const Type *T) : Kind(K), AccessTy(T), + MinOffset(INT64_MAX), + MaxOffset(INT64_MIN), + AllFixupsOutsideLoop(true) {} - // Remove any common subexpressions. - for (unsigned j = 0, e = SubExprs.size(); j != e; ++j) - if (SubExpressionUseData.count(SubExprs[j])) { - SubExprs.erase(SubExprs.begin()+j); - --j; --e; - } + bool InsertFormula(const Formula &F); + + void check() const; + + void print(raw_ostream &OS) const; + void dump() const; +}; + +/// InsertFormula - If the given formula has not yet been inserted, add it to +/// the list, and return true. Return false otherwise. +bool LSRUse::InsertFormula(const Formula &F) { + SmallVector Key = F.BaseRegs; + if (F.ScaledReg) Key.push_back(F.ScaledReg); + // Unstable sort by host order ok, because this is only used for uniquifying. + std::sort(Key.begin(), Key.end()); + + if (!Uniquifier.insert(Key).second) + return false; + + // Using a register to hold the value of 0 is not profitable. + assert((!F.ScaledReg || !F.ScaledReg->isZero()) && + "Zero allocated in a scaled register!"); +#ifndef NDEBUG + for (SmallVectorImpl::const_iterator I = + F.BaseRegs.begin(), E = F.BaseRegs.end(); I != E; ++I) + assert(!(*I)->isZero() && "Zero allocated in a base register!"); +#endif + + // Add the formula to the list. + Formulae.push_back(F); + + // Record registers now being used by this use. + if (F.ScaledReg) Regs.insert(F.ScaledReg); + Regs.insert(F.BaseRegs.begin(), F.BaseRegs.end()); - // Finally, add the non-shared expressions together. - if (SubExprs.empty()) - Uses[i].Base = Zero; + return true; +} + +void LSRUse::print(raw_ostream &OS) const { + OS << "LSR Use: Kind="; + switch (Kind) { + case Basic: OS << "Basic"; break; + case Special: OS << "Special"; break; + case ICmpZero: OS << "ICmpZero"; break; + case Address: + OS << "Address of "; + if (AccessTy->isPointerTy()) + OS << "pointer"; // the full pointer type could be really verbose else - Uses[i].Base = SE->getAddExpr(SubExprs); - SubExprs.clear(); + OS << *AccessTy; + } + + OS << ", Offsets={"; + for (SmallVectorImpl::const_iterator I = Offsets.begin(), + E = Offsets.end(); I != E; ++I) { + OS << *I; + if (next(I) != E) + OS << ','; } + OS << '}'; - return Result; + if (AllFixupsOutsideLoop) + OS << ", all-fixups-outside-loop"; } -/// ValidScale - Check whether the given Scale is valid for all loads and -/// stores in UsersToProcess. -/// -bool LoopStrengthReduce::ValidScale(bool HasBaseReg, int64_t Scale, - const std::vector& UsersToProcess) { - if (!TLI) - return true; +void LSRUse::dump() const { + print(errs()); errs() << '\n'; +} - for (unsigned i = 0, e = UsersToProcess.size(); i!=e; ++i) { - // If this is a load or other access, pass the type of the access in. - const Type *AccessTy = - Type::getVoidTy(UsersToProcess[i].Inst->getContext()); - if (isAddressUse(UsersToProcess[i].Inst, - UsersToProcess[i].OperandValToReplace)) - AccessTy = getAccessType(UsersToProcess[i].Inst); - else if (isa(UsersToProcess[i].Inst)) - continue; +/// isLegalUse - Test whether the use described by AM is "legal", meaning it can +/// be completely folded into the user instruction at isel time. This includes +/// address-mode folding and special icmp tricks. +static bool isLegalUse(const TargetLowering::AddrMode &AM, + LSRUse::KindType Kind, const Type *AccessTy, + const TargetLowering *TLI) { + switch (Kind) { + case LSRUse::Address: + // If we have low-level target information, ask the target if it can + // completely fold this address. + if (TLI) return TLI->isLegalAddressingMode(AM, AccessTy); + + // Otherwise, just guess that reg+reg addressing is legal. + return !AM.BaseGV && AM.BaseOffs == 0 && AM.Scale <= 1; + + case LSRUse::ICmpZero: + // There's not even a target hook for querying whether it would be legal to + // fold a GV into an ICmp. + if (AM.BaseGV) + return false; - TargetLowering::AddrMode AM; - if (const SCEVConstant *SC = dyn_cast(UsersToProcess[i].Imm)) - AM.BaseOffs = SC->getValue()->getSExtValue(); - AM.HasBaseReg = HasBaseReg || !UsersToProcess[i].Base->isZero(); - AM.Scale = Scale; + // ICmp only has two operands; don't allow more than two non-trivial parts. + if (AM.Scale != 0 && AM.HasBaseReg && AM.BaseOffs != 0) + return false; - // If load[imm+r*scale] is illegal, bail out. - if (!TLI->isLegalAddressingMode(AM, AccessTy)) + // ICmp only supports no scale or a -1 scale, as we can "fold" a -1 scale by + // putting the scaled register in the other operand of the icmp. + if (AM.Scale != 0 && AM.Scale != -1) return false; - } - return true; -} -/// ValidOffset - Check whether the given Offset is valid for all loads and -/// stores in UsersToProcess. -/// -bool LoopStrengthReduce::ValidOffset(bool HasBaseReg, - int64_t Offset, - int64_t Scale, - const std::vector& UsersToProcess) { - if (!TLI) + // If we have low-level target information, ask the target if it can fold an + // integer immediate on an icmp. + if (AM.BaseOffs != 0) { + if (TLI) return TLI->isLegalICmpImmediate(-AM.BaseOffs); + return false; + } + return true; - for (unsigned i=0, e = UsersToProcess.size(); i!=e; ++i) { - // If this is a load or other access, pass the type of the access in. - const Type *AccessTy = - Type::getVoidTy(UsersToProcess[i].Inst->getContext()); - if (isAddressUse(UsersToProcess[i].Inst, - UsersToProcess[i].OperandValToReplace)) - AccessTy = getAccessType(UsersToProcess[i].Inst); - else if (isa(UsersToProcess[i].Inst)) - continue; + case LSRUse::Basic: + // Only handle single-register values. + return !AM.BaseGV && AM.Scale == 0 && AM.BaseOffs == 0; + + case LSRUse::Special: + // Only handle -1 scales, or no scale. + return AM.Scale == 0 || AM.Scale == -1; + } - TargetLowering::AddrMode AM; - if (const SCEVConstant *SC = dyn_cast(UsersToProcess[i].Imm)) - AM.BaseOffs = SC->getValue()->getSExtValue(); - AM.BaseOffs = (uint64_t)AM.BaseOffs + (uint64_t)Offset; - AM.HasBaseReg = HasBaseReg || !UsersToProcess[i].Base->isZero(); - AM.Scale = Scale; + return false; +} - // If load[imm+r*scale] is illegal, bail out. - if (!TLI->isLegalAddressingMode(AM, AccessTy)) +static bool isLegalUse(TargetLowering::AddrMode AM, + int64_t MinOffset, int64_t MaxOffset, + LSRUse::KindType Kind, const Type *AccessTy, + const TargetLowering *TLI) { + // Check for overflow. + if (((int64_t)((uint64_t)AM.BaseOffs + MinOffset) > AM.BaseOffs) != + (MinOffset > 0)) + return false; + AM.BaseOffs = (uint64_t)AM.BaseOffs + MinOffset; + if (isLegalUse(AM, Kind, AccessTy, TLI)) { + AM.BaseOffs = (uint64_t)AM.BaseOffs - MinOffset; + // Check for overflow. + if (((int64_t)((uint64_t)AM.BaseOffs + MaxOffset) > AM.BaseOffs) != + (MaxOffset > 0)) return false; + AM.BaseOffs = (uint64_t)AM.BaseOffs + MaxOffset; + return isLegalUse(AM, Kind, AccessTy, TLI); } - return true; + return false; } -/// RequiresTypeConversion - Returns true if converting Ty1 to Ty2 is not -/// a nop. -bool LoopStrengthReduce::RequiresTypeConversion(const Type *Ty1, - const Type *Ty2) { - if (Ty1 == Ty2) - return false; - Ty1 = SE->getEffectiveSCEVType(Ty1); - Ty2 = SE->getEffectiveSCEVType(Ty2); - if (Ty1 == Ty2) - return false; - if (Ty1->canLosslesslyBitCastTo(Ty2)) - return false; - if (TLI && TLI->isTruncateFree(Ty1, Ty2)) - return false; - return true; +static bool isAlwaysFoldable(int64_t BaseOffs, + GlobalValue *BaseGV, + bool HasBaseReg, + LSRUse::KindType Kind, const Type *AccessTy, + const TargetLowering *TLI) { + // Fast-path: zero is always foldable. + if (BaseOffs == 0 && !BaseGV) return true; + + // Conservatively, create an address with an immediate and a + // base and a scale. + TargetLowering::AddrMode AM; + AM.BaseOffs = BaseOffs; + AM.BaseGV = BaseGV; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Kind == LSRUse::ICmpZero ? -1 : 1; + + return isLegalUse(AM, Kind, AccessTy, TLI); } -/// CheckForIVReuse - Returns the multiple if the stride is the multiple -/// of a previous stride and it is a legal value for the target addressing -/// mode scale component and optional base reg. This allows the users of -/// this stride to be rewritten as prev iv * factor. It returns 0 if no -/// reuse is possible. Factors can be negative on same targets, e.g. ARM. -/// -/// If all uses are outside the loop, we don't require that all multiplies -/// be folded into the addressing mode, nor even that the factor be constant; -/// a multiply (executed once) outside the loop is better than another IV -/// within. Well, usually. -const SCEV *LoopStrengthReduce::CheckForIVReuse(bool HasBaseReg, - bool AllUsesAreAddresses, - bool AllUsesAreOutsideLoop, - const SCEV *Stride, - IVExpr &IV, const Type *Ty, - const std::vector& UsersToProcess) { - if (const SCEVConstant *SC = dyn_cast(Stride)) { - int64_t SInt = SC->getValue()->getSExtValue(); - for (unsigned NewStride = 0, e = IU->StrideOrder.size(); - NewStride != e; ++NewStride) { - std::map::iterator SI = - IVsByStride.find(IU->StrideOrder[NewStride]); - if (SI == IVsByStride.end() || !isa(SI->first)) - continue; - // The other stride has no uses, don't reuse it. - std::map::iterator UI = - IU->IVUsesByStride.find(IU->StrideOrder[NewStride]); - if (UI->second->Users.empty()) - continue; - int64_t SSInt = cast(SI->first)->getValue()->getSExtValue(); - if (SI->first != Stride && - (unsigned(abs64(SInt)) < SSInt || (SInt % SSInt) != 0)) - continue; - int64_t Scale = SInt / SSInt; - // Check that this stride is valid for all the types used for loads and - // stores; if it can be used for some and not others, we might as well use - // the original stride everywhere, since we have to create the IV for it - // anyway. If the scale is 1, then we don't need to worry about folding - // multiplications. - if (Scale == 1 || - (AllUsesAreAddresses && - ValidScale(HasBaseReg, Scale, UsersToProcess))) { - // Prefer to reuse an IV with a base of zero. - for (std::vector::iterator II = SI->second.IVs.begin(), - IE = SI->second.IVs.end(); II != IE; ++II) - // Only reuse previous IV if it would not require a type conversion - // and if the base difference can be folded. - if (II->Base->isZero() && - !RequiresTypeConversion(II->Base->getType(), Ty)) { - IV = *II; - return SE->getIntegerSCEV(Scale, Stride->getType()); - } - // Otherwise, settle for an IV with a foldable base. - if (AllUsesAreAddresses) - for (std::vector::iterator II = SI->second.IVs.begin(), - IE = SI->second.IVs.end(); II != IE; ++II) - // Only reuse previous IV if it would not require a type conversion - // and if the base difference can be folded. - if (SE->getEffectiveSCEVType(II->Base->getType()) == - SE->getEffectiveSCEVType(Ty) && - isa(II->Base)) { - int64_t Base = - cast(II->Base)->getValue()->getSExtValue(); - if (Base > INT32_MIN && Base <= INT32_MAX && - ValidOffset(HasBaseReg, -Base * Scale, - Scale, UsersToProcess)) { - IV = *II; - return SE->getIntegerSCEV(Scale, Stride->getType()); - } - } - } - } - } else if (AllUsesAreOutsideLoop) { - // Accept nonconstant strides here; it is really really right to substitute - // an existing IV if we can. - for (unsigned NewStride = 0, e = IU->StrideOrder.size(); - NewStride != e; ++NewStride) { - std::map::iterator SI = - IVsByStride.find(IU->StrideOrder[NewStride]); - if (SI == IVsByStride.end() || !isa(SI->first)) - continue; - int64_t SSInt = cast(SI->first)->getValue()->getSExtValue(); - if (SI->first != Stride && SSInt != 1) - continue; - for (std::vector::iterator II = SI->second.IVs.begin(), - IE = SI->second.IVs.end(); II != IE; ++II) - // Accept nonzero base here. - // Only reuse previous IV if it would not require a type conversion. - if (!RequiresTypeConversion(II->Base->getType(), Ty)) { - IV = *II; - return Stride; - } - } - // Special case, old IV is -1*x and this one is x. Can treat this one as - // -1*old. - for (unsigned NewStride = 0, e = IU->StrideOrder.size(); - NewStride != e; ++NewStride) { - std::map::iterator SI = - IVsByStride.find(IU->StrideOrder[NewStride]); - if (SI == IVsByStride.end()) - continue; - if (const SCEVMulExpr *ME = dyn_cast(SI->first)) - if (const SCEVConstant *SC = dyn_cast(ME->getOperand(0))) - if (Stride == ME->getOperand(1) && - SC->getValue()->getSExtValue() == -1LL) - for (std::vector::iterator II = SI->second.IVs.begin(), - IE = SI->second.IVs.end(); II != IE; ++II) - // Accept nonzero base here. - // Only reuse previous IV if it would not require type conversion. - if (!RequiresTypeConversion(II->Base->getType(), Ty)) { - IV = *II; - return SE->getIntegerSCEV(-1LL, Stride->getType()); - } - } - } - return SE->getIntegerSCEV(0, Stride->getType()); -} - -/// PartitionByIsUseOfPostIncrementedValue - Simple boolean predicate that -/// returns true if Val's isUseOfPostIncrementedValue is true. -static bool PartitionByIsUseOfPostIncrementedValue(const BasedUser &Val) { - return Val.isUseOfPostIncrementedValue; -} - -/// isNonConstantNegative - Return true if the specified scev is negated, but -/// not a constant. -static bool isNonConstantNegative(const SCEV *Expr) { - const SCEVMulExpr *Mul = dyn_cast(Expr); - if (!Mul) return false; - - // If there is a constant factor, it will be first. - const SCEVConstant *SC = dyn_cast(Mul->getOperand(0)); - if (!SC) return false; - - // Return true if the value is negative, this matches things like (-42 * V). - return SC->getValue()->getValue().isNegative(); -} - -/// CollectIVUsers - Transform our list of users and offsets to a bit more -/// complex table. In this new vector, each 'BasedUser' contains 'Base', the -/// base of the strided accesses, as well as the old information from Uses. We -/// progressively move information from the Base field to the Imm field, until -/// we eventually have the full access expression to rewrite the use. -const SCEV *LoopStrengthReduce::CollectIVUsers(const SCEV *Stride, - IVUsersOfOneStride &Uses, - Loop *L, - bool &AllUsesAreAddresses, - bool &AllUsesAreOutsideLoop, - std::vector &UsersToProcess) { - // FIXME: Generalize to non-affine IV's. - if (!Stride->isLoopInvariant(L)) - return SE->getIntegerSCEV(0, Stride->getType()); - - UsersToProcess.reserve(Uses.Users.size()); - for (ilist::iterator I = Uses.Users.begin(), - E = Uses.Users.end(); I != E; ++I) { - UsersToProcess.push_back(BasedUser(*I, SE)); - - // Move any loop variant operands from the offset field to the immediate - // field of the use, so that we don't try to use something before it is - // computed. - MoveLoopVariantsToImmediateField(UsersToProcess.back().Base, - UsersToProcess.back().Imm, L, SE); - assert(UsersToProcess.back().Base->isLoopInvariant(L) && - "Base value is not loop invariant!"); - } - - // We now have a whole bunch of uses of like-strided induction variables, but - // they might all have different bases. We want to emit one PHI node for this - // stride which we fold as many common expressions (between the IVs) into as - // possible. Start by identifying the common expressions in the base values - // for the strides (e.g. if we have "A+C+B" and "A+B+D" as our bases, find - // "A+B"), emit it to the preheader, then remove the expression from the - // UsersToProcess base values. - const SCEV *CommonExprs = - RemoveCommonExpressionsFromUseBases(UsersToProcess, SE, L, TLI); - - // Next, figure out what we can represent in the immediate fields of - // instructions. If we can represent anything there, move it to the imm - // fields of the BasedUsers. We do this so that it increases the commonality - // of the remaining uses. - unsigned NumPHI = 0; - bool HasAddress = false; - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) { - // If the user is not in the current loop, this means it is using the exit - // value of the IV. Do not put anything in the base, make sure it's all in - // the immediate field to allow as much factoring as possible. - if (!L->contains(UsersToProcess[i].Inst)) { - UsersToProcess[i].Imm = SE->getAddExpr(UsersToProcess[i].Imm, - UsersToProcess[i].Base); - UsersToProcess[i].Base = - SE->getIntegerSCEV(0, UsersToProcess[i].Base->getType()); - } else { - // Not all uses are outside the loop. - AllUsesAreOutsideLoop = false; - - // Addressing modes can be folded into loads and stores. Be careful that - // the store is through the expression, not of the expression though. - bool isPHI = false; - bool isAddress = isAddressUse(UsersToProcess[i].Inst, - UsersToProcess[i].OperandValToReplace); - if (isa(UsersToProcess[i].Inst)) { - isPHI = true; - ++NumPHI; - } - - if (isAddress) - HasAddress = true; - - // If this use isn't an address, then not all uses are addresses. - if (!isAddress && !isPHI) - AllUsesAreAddresses = false; +static bool isAlwaysFoldable(const SCEV *S, + int64_t MinOffset, int64_t MaxOffset, + bool HasBaseReg, + LSRUse::KindType Kind, const Type *AccessTy, + const TargetLowering *TLI, + ScalarEvolution &SE) { + // Fast-path: zero is always foldable. + if (S->isZero()) return true; + + // Conservatively, create an address with an immediate and a + // base and a scale. + int64_t BaseOffs = ExtractImmediate(S, SE); + GlobalValue *BaseGV = ExtractSymbol(S, SE); + + // If there's anything else involved, it's not foldable. + if (!S->isZero()) return false; + + // Fast-path: zero is always foldable. + if (BaseOffs == 0 && !BaseGV) return true; + + // Conservatively, create an address with an immediate and a + // base and a scale. + TargetLowering::AddrMode AM; + AM.BaseOffs = BaseOffs; + AM.BaseGV = BaseGV; + AM.HasBaseReg = HasBaseReg; + AM.Scale = Kind == LSRUse::ICmpZero ? -1 : 1; + + return isLegalUse(AM, MinOffset, MaxOffset, Kind, AccessTy, TLI); +} - MoveImmediateValues(TLI, UsersToProcess[i].Inst, UsersToProcess[i].Base, - UsersToProcess[i].Imm, isAddress, L, SE); - } +/// FormulaSorter - This class implements an ordering for formulae which sorts +/// the by their standalone cost. +class FormulaSorter { + /// These two sets are kept empty, so that we compute standalone costs. + DenseSet VisitedRegs; + SmallPtrSet Regs; + Loop *L; + LSRUse *LU; + ScalarEvolution &SE; + DominatorTree &DT; + +public: + FormulaSorter(Loop *l, LSRUse &lu, ScalarEvolution &se, DominatorTree &dt) + : L(l), LU(&lu), SE(se), DT(dt) {} + + bool operator()(const Formula &A, const Formula &B) { + Cost CostA; + CostA.RateFormula(A, Regs, VisitedRegs, L, LU->Offsets, SE, DT); + Regs.clear(); + Cost CostB; + CostB.RateFormula(B, Regs, VisitedRegs, L, LU->Offsets, SE, DT); + Regs.clear(); + return CostA < CostB; + } +}; + +/// LSRInstance - This class holds state for the main loop strength reduction +/// logic. +class LSRInstance { + IVUsers &IU; + ScalarEvolution &SE; + DominatorTree &DT; + const TargetLowering *const TLI; + Loop *const L; + bool Changed; + + /// IVIncInsertPos - This is the insert position that the current loop's + /// induction variable increment should be placed. In simple loops, this is + /// the latch block's terminator. But in more complicated cases, this is a + /// position which will dominate all the in-loop post-increment users. + Instruction *IVIncInsertPos; + + /// Factors - Interesting factors between use strides. + SmallSetVector Factors; + + /// Types - Interesting use types, to facilitate truncation reuse. + SmallSetVector Types; + + /// Fixups - The list of operands which are to be replaced. + SmallVector Fixups; + + /// Uses - The list of interesting uses. + SmallVector Uses; + + /// RegUses - Track which uses use which register candidates. + RegUseTracker RegUses; + + void OptimizeShadowIV(); + bool FindIVUserForCond(ICmpInst *Cond, IVStrideUse *&CondUse); + ICmpInst *OptimizeMax(ICmpInst *Cond, IVStrideUse* &CondUse); + bool OptimizeLoopTermCond(); + + void CollectInterestingTypesAndFactors(); + void CollectFixupsAndInitialFormulae(); + + LSRFixup &getNewFixup() { + Fixups.push_back(LSRFixup()); + return Fixups.back(); } - // If one of the use is a PHI node and all other uses are addresses, still - // allow iv reuse. Essentially we are trading one constant multiplication - // for one fewer iv. - if (NumPHI > 1) - AllUsesAreAddresses = false; - - // There are no in-loop address uses. - if (AllUsesAreAddresses && (!HasAddress && !AllUsesAreOutsideLoop)) - AllUsesAreAddresses = false; + // Support for sharing of LSRUses between LSRFixups. + typedef DenseMap UseMapTy; + UseMapTy UseMap; + + bool reconcileNewOffset(LSRUse &LU, int64_t NewOffset, + LSRUse::KindType Kind, const Type *AccessTy); + + std::pair getUse(const SCEV *&Expr, + LSRUse::KindType Kind, + const Type *AccessTy); + +public: + void InsertInitialFormula(const SCEV *S, LSRUse &LU, size_t LUIdx); + void InsertSupplementalFormula(const SCEV *S, LSRUse &LU, size_t LUIdx); + void CountRegisters(const Formula &F, size_t LUIdx); + bool InsertFormula(LSRUse &LU, unsigned LUIdx, const Formula &F); + + void CollectLoopInvariantFixupsAndFormulae(); + + void GenerateReassociations(LSRUse &LU, unsigned LUIdx, Formula Base, + unsigned Depth = 0); + void GenerateCombinations(LSRUse &LU, unsigned LUIdx, Formula Base); + void GenerateSymbolicOffsets(LSRUse &LU, unsigned LUIdx, Formula Base); + void GenerateConstantOffsets(LSRUse &LU, unsigned LUIdx, Formula Base); + void GenerateICmpZeroScales(LSRUse &LU, unsigned LUIdx, Formula Base); + void GenerateScales(LSRUse &LU, unsigned LUIdx, Formula Base); + void GenerateTruncates(LSRUse &LU, unsigned LUIdx, Formula Base); + void GenerateCrossUseConstantOffsets(); + void GenerateAllReuseFormulae(); + + void FilterOutUndesirableDedicatedRegisters(); + void NarrowSearchSpaceUsingHeuristics(); + + void SolveRecurse(SmallVectorImpl &Solution, + Cost &SolutionCost, + SmallVectorImpl &Workspace, + const Cost &CurCost, + const SmallPtrSet &CurRegs, + DenseSet &VisitedRegs) const; + void Solve(SmallVectorImpl &Solution) const; + + Value *Expand(const LSRFixup &LF, + const Formula &F, + BasicBlock::iterator IP, + SCEVExpander &Rewriter, + SmallVectorImpl &DeadInsts) const; + void RewriteForPHI(PHINode *PN, const LSRFixup &LF, + const Formula &F, + SCEVExpander &Rewriter, + SmallVectorImpl &DeadInsts, + Pass *P) const; + void Rewrite(const LSRFixup &LF, + const Formula &F, + SCEVExpander &Rewriter, + SmallVectorImpl &DeadInsts, + Pass *P) const; + void ImplementSolution(const SmallVectorImpl &Solution, + Pass *P); + + LSRInstance(const TargetLowering *tli, Loop *l, Pass *P); + + bool getChanged() const { return Changed; } + + void print_factors_and_types(raw_ostream &OS) const; + void print_fixups(raw_ostream &OS) const; + void print_uses(raw_ostream &OS) const; + void print(raw_ostream &OS) const; + void dump() const; +}; - return CommonExprs; } -/// ShouldUseFullStrengthReductionMode - Test whether full strength-reduction -/// is valid and profitable for the given set of users of a stride. In -/// full strength-reduction mode, all addresses at the current stride are -/// strength-reduced all the way down to pointer arithmetic. -/// -bool LoopStrengthReduce::ShouldUseFullStrengthReductionMode( - const std::vector &UsersToProcess, - const Loop *L, - bool AllUsesAreAddresses, - const SCEV *Stride) { - if (!EnableFullLSRMode) - return false; - - // The heuristics below aim to avoid increasing register pressure, but - // fully strength-reducing all the addresses increases the number of - // add instructions, so don't do this when optimizing for size. - // TODO: If the loop is large, the savings due to simpler addresses - // may oughtweight the costs of the extra increment instructions. - if (L->getHeader()->getParent()->hasFnAttr(Attribute::OptimizeForSize)) - return false; +/// OptimizeShadowIV - If IV is used in a int-to-float cast +/// inside the loop then try to eliminate the cast operation. +void LSRInstance::OptimizeShadowIV() { + const SCEV *BackedgeTakenCount = SE.getBackedgeTakenCount(L); + if (isa(BackedgeTakenCount)) + return; - // TODO: For now, don't do full strength reduction if there could - // potentially be greater-stride multiples of the current stride - // which could reuse the current stride IV. - if (IU->StrideOrder.back() != Stride) - return false; + for (IVUsers::const_iterator UI = IU.begin(), E = IU.end(); + UI != E; /* empty */) { + IVUsers::const_iterator CandidateUI = UI; + ++UI; + Instruction *ShadowUse = CandidateUI->getUser(); + const Type *DestTy = NULL; - // Iterate through the uses to find conditions that automatically rule out - // full-lsr mode. - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ) { - const SCEV *Base = UsersToProcess[i].Base; - const SCEV *Imm = UsersToProcess[i].Imm; - // If any users have a loop-variant component, they can't be fully - // strength-reduced. - if (Imm && !Imm->isLoopInvariant(L)) - return false; - // If there are to users with the same base and the difference between - // the two Imm values can't be folded into the address, full - // strength reduction would increase register pressure. - do { - const SCEV *CurImm = UsersToProcess[i].Imm; - if ((CurImm || Imm) && CurImm != Imm) { - if (!CurImm) CurImm = SE->getIntegerSCEV(0, Stride->getType()); - if (!Imm) Imm = SE->getIntegerSCEV(0, Stride->getType()); - const Instruction *Inst = UsersToProcess[i].Inst; - const Type *AccessTy = getAccessType(Inst); - const SCEV *Diff = SE->getMinusSCEV(UsersToProcess[i].Imm, Imm); - if (!Diff->isZero() && - (!AllUsesAreAddresses || - !fitsInAddressMode(Diff, AccessTy, TLI, /*HasBaseReg=*/true))) - return false; - } - } while (++i != e && Base == UsersToProcess[i].Base); - } + /* If shadow use is a int->float cast then insert a second IV + to eliminate this cast. - // If there's exactly one user in this stride, fully strength-reducing it - // won't increase register pressure. If it's starting from a non-zero base, - // it'll be simpler this way. - if (UsersToProcess.size() == 1 && !UsersToProcess[0].Base->isZero()) - return true; + for (unsigned i = 0; i < n; ++i) + foo((double)i); - // Otherwise, if there are any users in this stride that don't require - // a register for their base, full strength-reduction will increase - // register pressure. - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) - if (UsersToProcess[i].Base->isZero()) - return false; + is transformed into - // Otherwise, go for it. - return true; -} + double d = 0.0; + for (unsigned i = 0; i < n; ++i, ++d) + foo(d); + */ + if (UIToFPInst *UCast = dyn_cast(CandidateUI->getUser())) + DestTy = UCast->getDestTy(); + else if (SIToFPInst *SCast = dyn_cast(CandidateUI->getUser())) + DestTy = SCast->getDestTy(); + if (!DestTy) continue; -/// InsertAffinePhi Create and insert a PHI node for an induction variable -/// with the specified start and step values in the specified loop. -/// -/// If NegateStride is true, the stride should be negated by using a -/// subtract instead of an add. -/// -/// Return the created phi node. -/// -static PHINode *InsertAffinePhi(const SCEV *Start, const SCEV *Step, - Instruction *IVIncInsertPt, - const Loop *L, - SCEVExpander &Rewriter) { - assert(Start->isLoopInvariant(L) && "New PHI start is not loop invariant!"); - assert(Step->isLoopInvariant(L) && "New PHI stride is not loop invariant!"); - - BasicBlock *Header = L->getHeader(); - BasicBlock *Preheader = L->getLoopPreheader(); - BasicBlock *LatchBlock = L->getLoopLatch(); - const Type *Ty = Start->getType(); - Ty = Rewriter.SE.getEffectiveSCEVType(Ty); - - PHINode *PN = PHINode::Create(Ty, "lsr.iv", Header->begin()); - PN->addIncoming(Rewriter.expandCodeFor(Start, Ty, Preheader->getTerminator()), - Preheader); - - // If the stride is negative, insert a sub instead of an add for the - // increment. - bool isNegative = isNonConstantNegative(Step); - const SCEV *IncAmount = Step; - if (isNegative) - IncAmount = Rewriter.SE.getNegativeSCEV(Step); - - // Insert an add instruction right before the terminator corresponding - // to the back-edge or just before the only use. The location is determined - // by the caller and passed in as IVIncInsertPt. - Value *StepV = Rewriter.expandCodeFor(IncAmount, Ty, - Preheader->getTerminator()); - Instruction *IncV; - if (isNegative) { - IncV = BinaryOperator::CreateSub(PN, StepV, "lsr.iv.next", - IVIncInsertPt); - } else { - IncV = BinaryOperator::CreateAdd(PN, StepV, "lsr.iv.next", - IVIncInsertPt); - } - if (!isa(StepV)) ++NumVariable; - - PN->addIncoming(IncV, LatchBlock); - - ++NumInserted; - return PN; -} - -static void SortUsersToProcess(std::vector &UsersToProcess) { - // We want to emit code for users inside the loop first. To do this, we - // rearrange BasedUser so that the entries at the end have - // isUseOfPostIncrementedValue = false, because we pop off the end of the - // vector (so we handle them first). - std::partition(UsersToProcess.begin(), UsersToProcess.end(), - PartitionByIsUseOfPostIncrementedValue); - - // Sort this by base, so that things with the same base are handled - // together. By partitioning first and stable-sorting later, we are - // guaranteed that within each base we will pop off users from within the - // loop before users outside of the loop with a particular base. - // - // We would like to use stable_sort here, but we can't. The problem is that - // const SCEV *'s don't have a deterministic ordering w.r.t to each other, so - // we don't have anything to do a '<' comparison on. Because we think the - // number of uses is small, do a horrible bubble sort which just relies on - // ==. - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) { - // Get a base value. - const SCEV *Base = UsersToProcess[i].Base; - - // Compact everything with this base to be consecutive with this one. - for (unsigned j = i+1; j != e; ++j) { - if (UsersToProcess[j].Base == Base) { - std::swap(UsersToProcess[i+1], UsersToProcess[j]); - ++i; - } + if (TLI) { + // If target does not support DestTy natively then do not apply + // this transformation. + EVT DVT = TLI->getValueType(DestTy); + if (!TLI->isTypeLegal(DVT)) continue; } - } -} -/// PrepareToStrengthReduceFully - Prepare to fully strength-reduce -/// UsersToProcess, meaning lowering addresses all the way down to direct -/// pointer arithmetic. -/// -void -LoopStrengthReduce::PrepareToStrengthReduceFully( - std::vector &UsersToProcess, - const SCEV *Stride, - const SCEV *CommonExprs, - const Loop *L, - SCEVExpander &PreheaderRewriter) { - DEBUG(dbgs() << " Fully reducing all users\n"); - - // Rewrite the UsersToProcess records, creating a separate PHI for each - // unique Base value. - Instruction *IVIncInsertPt = L->getLoopLatch()->getTerminator(); - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ) { - // TODO: The uses are grouped by base, but not sorted. We arbitrarily - // pick the first Imm value here to start with, and adjust it for the - // other uses. - const SCEV *Imm = UsersToProcess[i].Imm; - const SCEV *Base = UsersToProcess[i].Base; - const SCEV *Start = SE->getAddExpr(CommonExprs, Base, Imm); - PHINode *Phi = InsertAffinePhi(Start, Stride, IVIncInsertPt, L, - PreheaderRewriter); - // Loop over all the users with the same base. - do { - UsersToProcess[i].Base = SE->getIntegerSCEV(0, Stride->getType()); - UsersToProcess[i].Imm = SE->getMinusSCEV(UsersToProcess[i].Imm, Imm); - UsersToProcess[i].Phi = Phi; - assert(UsersToProcess[i].Imm->isLoopInvariant(L) && - "ShouldUseFullStrengthReductionMode should reject this!"); - } while (++i != e && Base == UsersToProcess[i].Base); - } -} - -/// FindIVIncInsertPt - Return the location to insert the increment instruction. -/// If the only use if a use of postinc value, (must be the loop termination -/// condition), then insert it just before the use. -static Instruction *FindIVIncInsertPt(std::vector &UsersToProcess, - const Loop *L) { - if (UsersToProcess.size() == 1 && - UsersToProcess[0].isUseOfPostIncrementedValue && - L->contains(UsersToProcess[0].Inst)) - return UsersToProcess[0].Inst; - return L->getLoopLatch()->getTerminator(); -} - -/// PrepareToStrengthReduceWithNewPhi - Insert a new induction variable for the -/// given users to share. -/// -void -LoopStrengthReduce::PrepareToStrengthReduceWithNewPhi( - std::vector &UsersToProcess, - const SCEV *Stride, - const SCEV *CommonExprs, - Value *CommonBaseV, - Instruction *IVIncInsertPt, - const Loop *L, - SCEVExpander &PreheaderRewriter) { - DEBUG(dbgs() << " Inserting new PHI:\n"); - - PHINode *Phi = InsertAffinePhi(SE->getUnknown(CommonBaseV), - Stride, IVIncInsertPt, L, - PreheaderRewriter); - - // Remember this in case a later stride is multiple of this. - IVsByStride[Stride].addIV(Stride, CommonExprs, Phi); - - // All the users will share this new IV. - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) - UsersToProcess[i].Phi = Phi; - - DEBUG(dbgs() << " IV="); - DEBUG(WriteAsOperand(dbgs(), Phi, /*PrintType=*/false)); - DEBUG(dbgs() << "\n"); -} - -/// PrepareToStrengthReduceFromSmallerStride - Prepare for the given users to -/// reuse an induction variable with a stride that is a factor of the current -/// induction variable. -/// -void -LoopStrengthReduce::PrepareToStrengthReduceFromSmallerStride( - std::vector &UsersToProcess, - Value *CommonBaseV, - const IVExpr &ReuseIV, - Instruction *PreInsertPt) { - DEBUG(dbgs() << " Rewriting in terms of existing IV of STRIDE " - << *ReuseIV.Stride << " and BASE " << *ReuseIV.Base << "\n"); - - // All the users will share the reused IV. - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) - UsersToProcess[i].Phi = ReuseIV.PHI; - - Constant *C = dyn_cast(CommonBaseV); - if (C && - (!C->isNullValue() && - !fitsInAddressMode(SE->getUnknown(CommonBaseV), CommonBaseV->getType(), - TLI, false))) - // We want the common base emitted into the preheader! This is just - // using cast as a copy so BitCast (no-op cast) is appropriate - CommonBaseV = new BitCastInst(CommonBaseV, CommonBaseV->getType(), - "commonbase", PreInsertPt); -} - -static bool IsImmFoldedIntoAddrMode(GlobalValue *GV, int64_t Offset, - const Type *AccessTy, - std::vector &UsersToProcess, - const TargetLowering *TLI) { - SmallVector AddrModeInsts; - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) { - if (UsersToProcess[i].isUseOfPostIncrementedValue) - continue; - ExtAddrMode AddrMode = - AddressingModeMatcher::Match(UsersToProcess[i].OperandValToReplace, - AccessTy, UsersToProcess[i].Inst, - AddrModeInsts, *TLI); - if (GV && GV != AddrMode.BaseGV) - return false; - if (Offset && !AddrMode.BaseOffs) - // FIXME: How to accurate check it's immediate offset is folded. - return false; - AddrModeInsts.clear(); - } - return true; -} + PHINode *PH = dyn_cast(ShadowUse->getOperand(0)); + if (!PH) continue; + if (PH->getNumIncomingValues() != 2) continue; -/// StrengthReduceIVUsersOfStride - Strength reduce all of the users of a single -/// stride of IV. All of the users may have different starting values, and this -/// may not be the only stride. -void -LoopStrengthReduce::StrengthReduceIVUsersOfStride(const SCEV *Stride, - IVUsersOfOneStride &Uses, - Loop *L) { - // If all the users are moved to another stride, then there is nothing to do. - if (Uses.Users.empty()) - return; + const Type *SrcTy = PH->getType(); + int Mantissa = DestTy->getFPMantissaWidth(); + if (Mantissa == -1) continue; + if ((int)SE.getTypeSizeInBits(SrcTy) > Mantissa) + continue; - // Keep track if every use in UsersToProcess is an address. If they all are, - // we may be able to rewrite the entire collection of them in terms of a - // smaller-stride IV. - bool AllUsesAreAddresses = true; - - // Keep track if every use of a single stride is outside the loop. If so, - // we want to be more aggressive about reusing a smaller-stride IV; a - // multiply outside the loop is better than another IV inside. Well, usually. - bool AllUsesAreOutsideLoop = true; - - // Transform our list of users and offsets to a bit more complex table. In - // this new vector, each 'BasedUser' contains 'Base' the base of the strided - // access as well as the old information from Uses. We progressively move - // information from the Base field to the Imm field until we eventually have - // the full access expression to rewrite the use. - std::vector UsersToProcess; - const SCEV *CommonExprs = CollectIVUsers(Stride, Uses, L, AllUsesAreAddresses, - AllUsesAreOutsideLoop, - UsersToProcess); - - // Sort the UsersToProcess array so that users with common bases are - // next to each other. - SortUsersToProcess(UsersToProcess); - - // If we managed to find some expressions in common, we'll need to carry - // their value in a register and add it in for each use. This will take up - // a register operand, which potentially restricts what stride values are - // valid. - bool HaveCommonExprs = !CommonExprs->isZero(); - const Type *ReplacedTy = CommonExprs->getType(); - - // If all uses are addresses, consider sinking the immediate part of the - // common expression back into uses if they can fit in the immediate fields. - if (TLI && HaveCommonExprs && AllUsesAreAddresses) { - const SCEV *NewCommon = CommonExprs; - const SCEV *Imm = SE->getIntegerSCEV(0, ReplacedTy); - MoveImmediateValues(TLI, Type::getVoidTy( - L->getLoopPreheader()->getContext()), - NewCommon, Imm, true, L, SE); - if (!Imm->isZero()) { - bool DoSink = true; - - // If the immediate part of the common expression is a GV, check if it's - // possible to fold it into the target addressing mode. - GlobalValue *GV = 0; - if (const SCEVUnknown *SU = dyn_cast(Imm)) - GV = dyn_cast(SU->getValue()); - int64_t Offset = 0; - if (const SCEVConstant *SC = dyn_cast(Imm)) - Offset = SC->getValue()->getSExtValue(); - if (GV || Offset) - // Pass VoidTy as the AccessTy to be conservative, because - // there could be multiple access types among all the uses. - DoSink = IsImmFoldedIntoAddrMode(GV, Offset, - Type::getVoidTy(L->getLoopPreheader()->getContext()), - UsersToProcess, TLI); - - if (DoSink) { - DEBUG(dbgs() << " Sinking " << *Imm << " back down into uses\n"); - for (unsigned i = 0, e = UsersToProcess.size(); i != e; ++i) - UsersToProcess[i].Imm = SE->getAddExpr(UsersToProcess[i].Imm, Imm); - CommonExprs = NewCommon; - HaveCommonExprs = !CommonExprs->isZero(); - ++NumImmSunk; - } + unsigned Entry, Latch; + if (PH->getIncomingBlock(0) == L->getLoopPreheader()) { + Entry = 0; + Latch = 1; + } else { + Entry = 1; + Latch = 0; } - } - - // Now that we know what we need to do, insert the PHI node itself. - // - DEBUG(dbgs() << "LSR: Examining IVs of TYPE " << *ReplacedTy << " of STRIDE " - << *Stride << ":\n" - << " Common base: " << *CommonExprs << '\n'); - SCEVExpander Rewriter(*SE); - SCEVExpander PreheaderRewriter(*SE); + ConstantInt *Init = dyn_cast(PH->getIncomingValue(Entry)); + if (!Init) continue; + Constant *NewInit = ConstantFP::get(DestTy, Init->getZExtValue()); - BasicBlock *Preheader = L->getLoopPreheader(); - Instruction *PreInsertPt = Preheader->getTerminator(); - BasicBlock *LatchBlock = L->getLoopLatch(); - Instruction *IVIncInsertPt = LatchBlock->getTerminator(); - - Value *CommonBaseV = Constant::getNullValue(ReplacedTy); - - const SCEV *RewriteFactor = SE->getIntegerSCEV(0, ReplacedTy); - IVExpr ReuseIV(SE->getIntegerSCEV(0, - Type::getInt32Ty(Preheader->getContext())), - SE->getIntegerSCEV(0, - Type::getInt32Ty(Preheader->getContext())), - 0); - - // Choose a strength-reduction strategy and prepare for it by creating - // the necessary PHIs and adjusting the bookkeeping. - if (ShouldUseFullStrengthReductionMode(UsersToProcess, L, - AllUsesAreAddresses, Stride)) { - PrepareToStrengthReduceFully(UsersToProcess, Stride, CommonExprs, L, - PreheaderRewriter); - } else { - // Emit the initial base value into the loop preheader. - CommonBaseV = PreheaderRewriter.expandCodeFor(CommonExprs, ReplacedTy, - PreInsertPt); - - // If all uses are addresses, check if it is possible to reuse an IV. The - // new IV must have a stride that is a multiple of the old stride; the - // multiple must be a number that can be encoded in the scale field of the - // target addressing mode; and we must have a valid instruction after this - // substitution, including the immediate field, if any. - RewriteFactor = CheckForIVReuse(HaveCommonExprs, AllUsesAreAddresses, - AllUsesAreOutsideLoop, - Stride, ReuseIV, ReplacedTy, - UsersToProcess); - if (!RewriteFactor->isZero()) - PrepareToStrengthReduceFromSmallerStride(UsersToProcess, CommonBaseV, - ReuseIV, PreInsertPt); - else { - IVIncInsertPt = FindIVIncInsertPt(UsersToProcess, L); - PrepareToStrengthReduceWithNewPhi(UsersToProcess, Stride, CommonExprs, - CommonBaseV, IVIncInsertPt, - L, PreheaderRewriter); - } - } - - // Process all the users now, replacing their strided uses with - // strength-reduced forms. This outer loop handles all bases, the inner - // loop handles all users of a particular base. - while (!UsersToProcess.empty()) { - const SCEV *Base = UsersToProcess.back().Base; - Instruction *Inst = UsersToProcess.back().Inst; - - // Emit the code for Base into the preheader. - Value *BaseV = 0; - if (!Base->isZero()) { - BaseV = PreheaderRewriter.expandCodeFor(Base, 0, PreInsertPt); - - DEBUG(dbgs() << " INSERTING code for BASE = " << *Base << ":"); - if (BaseV->hasName()) - DEBUG(dbgs() << " Result value name = %" << BaseV->getName()); - DEBUG(dbgs() << "\n"); - - // If BaseV is a non-zero constant, make sure that it gets inserted into - // the preheader, instead of being forward substituted into the uses. We - // do this by forcing a BitCast (noop cast) to be inserted into the - // preheader in this case. - if (!fitsInAddressMode(Base, getAccessType(Inst), TLI, false) && - isa(BaseV)) { - // We want this constant emitted into the preheader! This is just - // using cast as a copy so BitCast (no-op cast) is appropriate - BaseV = new BitCastInst(BaseV, BaseV->getType(), "preheaderinsert", - PreInsertPt); - } - } + BinaryOperator *Incr = + dyn_cast(PH->getIncomingValue(Latch)); + if (!Incr) continue; + if (Incr->getOpcode() != Instruction::Add + && Incr->getOpcode() != Instruction::Sub) + continue; - // Emit the code to add the immediate offset to the Phi value, just before - // the instructions that we identified as using this stride and base. - do { - // FIXME: Use emitted users to emit other users. - BasedUser &User = UsersToProcess.back(); + /* Initialize new IV, double d = 0.0 in above example. */ + ConstantInt *C = NULL; + if (Incr->getOperand(0) == PH) + C = dyn_cast(Incr->getOperand(1)); + else if (Incr->getOperand(1) == PH) + C = dyn_cast(Incr->getOperand(0)); + else + continue; - DEBUG(dbgs() << " Examining "); - if (User.isUseOfPostIncrementedValue) - DEBUG(dbgs() << "postinc"); - else - DEBUG(dbgs() << "preinc"); - DEBUG(dbgs() << " use "); - DEBUG(WriteAsOperand(dbgs(), UsersToProcess.back().OperandValToReplace, - /*PrintType=*/false)); - DEBUG(dbgs() << " in Inst: " << *User.Inst << '\n'); - - // If this instruction wants to use the post-incremented value, move it - // after the post-inc and use its value instead of the PHI. - Value *RewriteOp = User.Phi; - if (User.isUseOfPostIncrementedValue) { - RewriteOp = User.Phi->getIncomingValueForBlock(LatchBlock); - // If this user is in the loop, make sure it is the last thing in the - // loop to ensure it is dominated by the increment. In case it's the - // only use of the iv, the increment instruction is already before the - // use. - if (L->contains(User.Inst) && User.Inst != IVIncInsertPt) - User.Inst->moveBefore(IVIncInsertPt); - } + if (!C) continue; - const SCEV *RewriteExpr = SE->getUnknown(RewriteOp); + // Ignore negative constants, as the code below doesn't handle them + // correctly. TODO: Remove this restriction. + if (!C->getValue().isStrictlyPositive()) continue; - if (SE->getEffectiveSCEVType(RewriteOp->getType()) != - SE->getEffectiveSCEVType(ReplacedTy)) { - assert(SE->getTypeSizeInBits(RewriteOp->getType()) > - SE->getTypeSizeInBits(ReplacedTy) && - "Unexpected widening cast!"); - RewriteExpr = SE->getTruncateExpr(RewriteExpr, ReplacedTy); - } + /* Add new PHINode. */ + PHINode *NewPH = PHINode::Create(DestTy, "IV.S.", PH); - // If we had to insert new instructions for RewriteOp, we have to - // consider that they may not have been able to end up immediately - // next to RewriteOp, because non-PHI instructions may never precede - // PHI instructions in a block. In this case, remember where the last - // instruction was inserted so that if we're replacing a different - // PHI node, we can use the later point to expand the final - // RewriteExpr. - Instruction *NewBasePt = dyn_cast(RewriteOp); - if (RewriteOp == User.Phi) NewBasePt = 0; - - // Clear the SCEVExpander's expression map so that we are guaranteed - // to have the code emitted where we expect it. - Rewriter.clear(); - - // If we are reusing the iv, then it must be multiplied by a constant - // factor to take advantage of the addressing mode scale component. - if (!RewriteFactor->isZero()) { - // If we're reusing an IV with a nonzero base (currently this happens - // only when all reuses are outside the loop) subtract that base here. - // The base has been used to initialize the PHI node but we don't want - // it here. - if (!ReuseIV.Base->isZero()) { - const SCEV *typedBase = ReuseIV.Base; - if (SE->getEffectiveSCEVType(RewriteExpr->getType()) != - SE->getEffectiveSCEVType(ReuseIV.Base->getType())) { - // It's possible the original IV is a larger type than the new IV, - // in which case we have to truncate the Base. We checked in - // RequiresTypeConversion that this is valid. - assert(SE->getTypeSizeInBits(RewriteExpr->getType()) < - SE->getTypeSizeInBits(ReuseIV.Base->getType()) && - "Unexpected lengthening conversion!"); - typedBase = SE->getTruncateExpr(ReuseIV.Base, - RewriteExpr->getType()); - } - RewriteExpr = SE->getMinusSCEV(RewriteExpr, typedBase); - } + /* create new increment. '++d' in above example. */ + Constant *CFP = ConstantFP::get(DestTy, C->getZExtValue()); + BinaryOperator *NewIncr = + BinaryOperator::Create(Incr->getOpcode() == Instruction::Add ? + Instruction::FAdd : Instruction::FSub, + NewPH, CFP, "IV.S.next.", Incr); - // Multiply old variable, with base removed, by new scale factor. - RewriteExpr = SE->getMulExpr(RewriteFactor, - RewriteExpr); - - // The common base is emitted in the loop preheader. But since we - // are reusing an IV, it has not been used to initialize the PHI node. - // Add it to the expression used to rewrite the uses. - // When this use is outside the loop, we earlier subtracted the - // common base, and are adding it back here. Use the same expression - // as before, rather than CommonBaseV, so DAGCombiner will zap it. - if (!CommonExprs->isZero()) { - if (L->contains(User.Inst)) - RewriteExpr = SE->getAddExpr(RewriteExpr, - SE->getUnknown(CommonBaseV)); - else - RewriteExpr = SE->getAddExpr(RewriteExpr, CommonExprs); - } - } + NewPH->addIncoming(NewInit, PH->getIncomingBlock(Entry)); + NewPH->addIncoming(NewIncr, PH->getIncomingBlock(Latch)); - // Now that we know what we need to do, insert code before User for the - // immediate and any loop-variant expressions. - if (BaseV) - // Add BaseV to the PHI value if needed. - RewriteExpr = SE->getAddExpr(RewriteExpr, SE->getUnknown(BaseV)); - - User.RewriteInstructionToUseNewBase(RewriteExpr, NewBasePt, - Rewriter, L, this, - DeadInsts, SE); - - // Mark old value we replaced as possibly dead, so that it is eliminated - // if we just replaced the last use of that value. - DeadInsts.push_back(User.OperandValToReplace); - - UsersToProcess.pop_back(); - ++NumReduced; - - // If there are any more users to process with the same base, process them - // now. We sorted by base above, so we just have to check the last elt. - } while (!UsersToProcess.empty() && UsersToProcess.back().Base == Base); - // TODO: Next, find out which base index is the most common, pull it out. - } - - // IMPORTANT TODO: Figure out how to partition the IV's with this stride, but - // different starting values, into different PHIs. -} - -void LoopStrengthReduce::StrengthReduceIVUsers(Loop *L) { - // Note: this processes each stride/type pair individually. All users - // passed into StrengthReduceIVUsersOfStride have the same type AND stride. - // Also, note that we iterate over IVUsesByStride indirectly by using - // StrideOrder. This extra layer of indirection makes the ordering of - // strides deterministic - not dependent on map order. - for (unsigned Stride = 0, e = IU->StrideOrder.size(); Stride != e; ++Stride) { - std::map::iterator SI = - IU->IVUsesByStride.find(IU->StrideOrder[Stride]); - assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); - // FIXME: Generalize to non-affine IV's. - if (!SI->first->isLoopInvariant(L)) - continue; - StrengthReduceIVUsersOfStride(SI->first, *SI->second, L); + /* Remove cast operation */ + ShadowUse->replaceAllUsesWith(NewPH); + ShadowUse->eraseFromParent(); + break; } } /// FindIVUserForCond - If Cond has an operand that is an expression of an IV, /// set the IV user and stride information and return true, otherwise return /// false. -bool LoopStrengthReduce::FindIVUserForCond(ICmpInst *Cond, - IVStrideUse *&CondUse, - const SCEV* &CondStride) { - for (unsigned Stride = 0, e = IU->StrideOrder.size(); - Stride != e && !CondUse; ++Stride) { - std::map::iterator SI = - IU->IVUsesByStride.find(IU->StrideOrder[Stride]); - assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); - - for (ilist::iterator UI = SI->second->Users.begin(), - E = SI->second->Users.end(); UI != E; ++UI) - if (UI->getUser() == Cond) { - // NOTE: we could handle setcc instructions with multiple uses here, but - // InstCombine does it as well for simple uses, it's not clear that it - // occurs enough in real life to handle. - CondUse = UI; - CondStride = SI->first; - return true; - } - } - return false; -} - -namespace { - // Constant strides come first which in turns are sorted by their absolute - // values. If absolute values are the same, then positive strides comes first. - // e.g. - // 4, -1, X, 1, 2 ==> 1, -1, 2, 4, X - struct StrideCompare { - const ScalarEvolution *SE; - explicit StrideCompare(const ScalarEvolution *se) : SE(se) {} - - bool operator()(const SCEV *LHS, const SCEV *RHS) { - const SCEVConstant *LHSC = dyn_cast(LHS); - const SCEVConstant *RHSC = dyn_cast(RHS); - if (LHSC && RHSC) { - int64_t LV = LHSC->getValue()->getSExtValue(); - int64_t RV = RHSC->getValue()->getSExtValue(); - uint64_t ALV = (LV < 0) ? -LV : LV; - uint64_t ARV = (RV < 0) ? -RV : RV; - if (ALV == ARV) { - if (LV != RV) - return LV > RV; - } else { - return ALV < ARV; - } - - // If it's the same value but different type, sort by bit width so - // that we emit larger induction variables before smaller - // ones, letting the smaller be re-written in terms of larger ones. - return SE->getTypeSizeInBits(RHS->getType()) < - SE->getTypeSizeInBits(LHS->getType()); - } - return LHSC && !RHSC; - } - }; -} - -/// ChangeCompareStride - If a loop termination compare instruction is the only -/// use of its stride, and the comparison is against a constant value, try to -/// eliminate the stride by moving the compare instruction to another stride and -/// changing its constant operand accordingly. E.g. -/// -/// loop: -/// ... -/// v1 = v1 + 3 -/// v2 = v2 + 1 -/// if (v2 < 10) goto loop -/// => -/// loop: -/// ... -/// v1 = v1 + 3 -/// if (v1 < 30) goto loop -ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond, - IVStrideUse* &CondUse, - const SCEV* &CondStride, - bool PostPass) { - // If there's only one stride in the loop, there's nothing to do here. - if (IU->StrideOrder.size() < 2) - return Cond; - - // If there are other users of the condition's stride, don't bother trying to - // change the condition because the stride will still remain. - std::map::iterator I = - IU->IVUsesByStride.find(CondStride); - if (I == IU->IVUsesByStride.end()) - return Cond; - - if (I->second->Users.size() > 1) { - for (ilist::iterator II = I->second->Users.begin(), - EE = I->second->Users.end(); II != EE; ++II) { - if (II->getUser() == Cond) - continue; - if (!isInstructionTriviallyDead(II->getUser())) - return Cond; - } - } - - // Only handle constant strides for now. - const SCEVConstant *SC = dyn_cast(CondStride); - if (!SC) return Cond; - - ICmpInst::Predicate Predicate = Cond->getPredicate(); - int64_t CmpSSInt = SC->getValue()->getSExtValue(); - unsigned BitWidth = SE->getTypeSizeInBits(CondStride->getType()); - uint64_t SignBit = 1ULL << (BitWidth-1); - const Type *CmpTy = Cond->getOperand(0)->getType(); - const Type *NewCmpTy = NULL; - unsigned TyBits = SE->getTypeSizeInBits(CmpTy); - unsigned NewTyBits = 0; - const SCEV *NewStride = NULL; - Value *NewCmpLHS = NULL; - Value *NewCmpRHS = NULL; - int64_t Scale = 1; - const SCEV *NewOffset = SE->getIntegerSCEV(0, CmpTy); - - if (ConstantInt *C = dyn_cast(Cond->getOperand(1))) { - int64_t CmpVal = C->getValue().getSExtValue(); - - // Check the relevant induction variable for conformance to the pattern. - const SCEV *IV = SE->getSCEV(Cond->getOperand(0)); - const SCEVAddRecExpr *AR = dyn_cast(IV); - if (!AR || !AR->isAffine()) - return Cond; - - const SCEVConstant *StartC = dyn_cast(AR->getStart()); - // Check stride constant and the comparision constant signs to detect - // overflow. - if (StartC) { - if ((StartC->getValue()->getSExtValue() < CmpVal && CmpSSInt < 0) || - (StartC->getValue()->getSExtValue() > CmpVal && CmpSSInt > 0)) - return Cond; - } else { - // More restrictive check for the other cases. - if ((CmpVal & SignBit) != (CmpSSInt & SignBit)) - return Cond; - } - - // Look for a suitable stride / iv as replacement. - for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { - std::map::iterator SI = - IU->IVUsesByStride.find(IU->StrideOrder[i]); - if (!isa(SI->first) || SI->second->Users.empty()) - continue; - int64_t SSInt = cast(SI->first)->getValue()->getSExtValue(); - if (SSInt == CmpSSInt || - abs64(SSInt) < abs64(CmpSSInt) || - (SSInt % CmpSSInt) != 0) - continue; - - Scale = SSInt / CmpSSInt; - int64_t NewCmpVal = CmpVal * Scale; - - // If old icmp value fits in icmp immediate field, but the new one doesn't - // try something else. - if (TLI && - TLI->isLegalICmpImmediate(CmpVal) && - !TLI->isLegalICmpImmediate(NewCmpVal)) - continue; - - APInt Mul = APInt(BitWidth*2, CmpVal, true); - Mul = Mul * APInt(BitWidth*2, Scale, true); - // Check for overflow. - if (!Mul.isSignedIntN(BitWidth)) - continue; - // Check for overflow in the stride's type too. - if (!Mul.isSignedIntN(SE->getTypeSizeInBits(SI->first->getType()))) - continue; - - // Watch out for overflow. - if (ICmpInst::isSigned(Predicate) && - (CmpVal & SignBit) != (NewCmpVal & SignBit)) - continue; - - // Pick the best iv to use trying to avoid a cast. - NewCmpLHS = NULL; - for (ilist::iterator UI = SI->second->Users.begin(), - E = SI->second->Users.end(); UI != E; ++UI) { - Value *Op = UI->getOperandValToReplace(); - - // If the IVStrideUse implies a cast, check for an actual cast which - // can be used to find the original IV expression. - if (SE->getEffectiveSCEVType(Op->getType()) != - SE->getEffectiveSCEVType(SI->first->getType())) { - CastInst *CI = dyn_cast(Op); - // If it's not a simple cast, it's complicated. - if (!CI) - continue; - // If it's a cast from a type other than the stride type, - // it's complicated. - if (CI->getOperand(0)->getType() != SI->first->getType()) - continue; - // Ok, we found the IV expression in the stride's type. - Op = CI->getOperand(0); - } - - NewCmpLHS = Op; - if (NewCmpLHS->getType() == CmpTy) - break; - } - if (!NewCmpLHS) - continue; - - NewCmpTy = NewCmpLHS->getType(); - NewTyBits = SE->getTypeSizeInBits(NewCmpTy); - const Type *NewCmpIntTy = IntegerType::get(Cond->getContext(), NewTyBits); - if (RequiresTypeConversion(NewCmpTy, CmpTy)) { - // Check if it is possible to rewrite it using - // an iv / stride of a smaller integer type. - unsigned Bits = NewTyBits; - if (ICmpInst::isSigned(Predicate)) - --Bits; - uint64_t Mask = (1ULL << Bits) - 1; - if (((uint64_t)NewCmpVal & Mask) != (uint64_t)NewCmpVal) - continue; - } - - // Don't rewrite if use offset is non-constant and the new type is - // of a different type. - // FIXME: too conservative? - if (NewTyBits != TyBits && !isa(CondUse->getOffset())) - continue; - - if (!PostPass) { - bool AllUsesAreAddresses = true; - bool AllUsesAreOutsideLoop = true; - std::vector UsersToProcess; - const SCEV *CommonExprs = CollectIVUsers(SI->first, *SI->second, L, - AllUsesAreAddresses, - AllUsesAreOutsideLoop, - UsersToProcess); - // Avoid rewriting the compare instruction with an iv of new stride - // if it's likely the new stride uses will be rewritten using the - // stride of the compare instruction. - if (AllUsesAreAddresses && - ValidScale(!CommonExprs->isZero(), Scale, UsersToProcess)) - continue; - } - - // Avoid rewriting the compare instruction with an iv which has - // implicit extension or truncation built into it. - // TODO: This is over-conservative. - if (SE->getTypeSizeInBits(CondUse->getOffset()->getType()) != TyBits) - continue; - - // If scale is negative, use swapped predicate unless it's testing - // for equality. - if (Scale < 0 && !Cond->isEquality()) - Predicate = ICmpInst::getSwappedPredicate(Predicate); - - NewStride = IU->StrideOrder[i]; - if (!isa(NewCmpTy)) - NewCmpRHS = ConstantInt::get(NewCmpTy, NewCmpVal); - else { - Constant *CI = ConstantInt::get(NewCmpIntTy, NewCmpVal); - NewCmpRHS = ConstantExpr::getIntToPtr(CI, NewCmpTy); - } - NewOffset = TyBits == NewTyBits - ? SE->getMulExpr(CondUse->getOffset(), - SE->getConstant(CmpTy, Scale)) - : SE->getConstant(NewCmpIntTy, - cast(CondUse->getOffset())->getValue() - ->getSExtValue()*Scale); - break; +bool LSRInstance::FindIVUserForCond(ICmpInst *Cond, + IVStrideUse *&CondUse) { + for (IVUsers::iterator UI = IU.begin(), E = IU.end(); UI != E; ++UI) + if (UI->getUser() == Cond) { + // NOTE: we could handle setcc instructions with multiple uses here, but + // InstCombine does it as well for simple uses, it's not clear that it + // occurs enough in real life to handle. + CondUse = UI; + return true; } - } - - // Forgo this transformation if it the increment happens to be - // unfortunately positioned after the condition, and the condition - // has multiple uses which prevent it from being moved immediately - // before the branch. See - // test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-*.ll - // for an example of this situation. - if (!Cond->hasOneUse()) { - for (BasicBlock::iterator I = Cond, E = Cond->getParent()->end(); - I != E; ++I) - if (I == NewCmpLHS) - return Cond; - } - - if (NewCmpRHS) { - // Create a new compare instruction using new stride / iv. - ICmpInst *OldCond = Cond; - // Insert new compare instruction. - Cond = new ICmpInst(OldCond, Predicate, NewCmpLHS, NewCmpRHS, - L->getHeader()->getName() + ".termcond"); - - DEBUG(dbgs() << " Change compare stride in Inst " << *OldCond); - DEBUG(dbgs() << " to " << *Cond << '\n'); - - // Remove the old compare instruction. The old indvar is probably dead too. - DeadInsts.push_back(CondUse->getOperandValToReplace()); - OldCond->replaceAllUsesWith(Cond); - OldCond->eraseFromParent(); - - IU->IVUsesByStride[NewStride]->addUser(NewOffset, Cond, NewCmpLHS); - CondUse = &IU->IVUsesByStride[NewStride]->Users.back(); - CondStride = NewStride; - ++NumEliminated; - Changed = true; - } - - return Cond; + return false; } /// OptimizeMax - Rewrite the loop's terminating condition if it uses @@ -2088,7 +1405,7 @@ ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond, /// are designed around them. The most obvious example of this is the /// LoopInfo analysis, which doesn't remember trip count values. It /// expects to be able to rediscover the trip count each time it is -/// needed, and it does this using a simple analyis that only succeeds if +/// needed, and it does this using a simple analysis that only succeeds if /// the loop has a canonical induction variable. /// /// However, when it comes time to generate code, the maximum operation @@ -2098,8 +1415,7 @@ ICmpInst *LoopStrengthReduce::ChangeCompareStride(Loop *L, ICmpInst *Cond, /// rewriting their conditions from ICMP_NE back to ICMP_SLT, and deleting /// the instructions for the maximum computation. /// -ICmpInst *LoopStrengthReduce::OptimizeMax(Loop *L, ICmpInst *Cond, - IVStrideUse* &CondUse) { +ICmpInst *LSRInstance::OptimizeMax(ICmpInst *Cond, IVStrideUse* &CondUse) { // Check that the loop matches the pattern we're looking for. if (Cond->getPredicate() != CmpInst::ICMP_EQ && Cond->getPredicate() != CmpInst::ICMP_NE) @@ -2108,19 +1424,19 @@ ICmpInst *LoopStrengthReduce::OptimizeMax(Loop *L, ICmpInst *Cond, SelectInst *Sel = dyn_cast(Cond->getOperand(1)); if (!Sel || !Sel->hasOneUse()) return Cond; - const SCEV *BackedgeTakenCount = SE->getBackedgeTakenCount(L); + const SCEV *BackedgeTakenCount = SE.getBackedgeTakenCount(L); if (isa(BackedgeTakenCount)) return Cond; - const SCEV *One = SE->getIntegerSCEV(1, BackedgeTakenCount->getType()); + const SCEV *One = SE.getIntegerSCEV(1, BackedgeTakenCount->getType()); // Add one to the backedge-taken count to get the trip count. - const SCEV *IterationCount = SE->getAddExpr(BackedgeTakenCount, One); + const SCEV *IterationCount = SE.getAddExpr(BackedgeTakenCount, One); // Check for a max calculation that matches the pattern. if (!isa(IterationCount) && !isa(IterationCount)) return Cond; const SCEVNAryExpr *Max = cast(IterationCount); - if (Max != SE->getSCEV(Sel)) return Cond; + if (Max != SE.getSCEV(Sel)) return Cond; // To handle a max with more than two operands, this optimization would // require additional checking and setup. @@ -2130,14 +1446,13 @@ ICmpInst *LoopStrengthReduce::OptimizeMax(Loop *L, ICmpInst *Cond, const SCEV *MaxLHS = Max->getOperand(0); const SCEV *MaxRHS = Max->getOperand(1); if (!MaxLHS || MaxLHS != One) return Cond; - // Check the relevant induction variable for conformance to // the pattern. - const SCEV *IV = SE->getSCEV(Cond->getOperand(0)); + const SCEV *IV = SE.getSCEV(Cond->getOperand(0)); const SCEVAddRecExpr *AR = dyn_cast(IV); if (!AR || !AR->isAffine() || AR->getStart() != One || - AR->getStepRecurrence(*SE) != One) + AR->getStepRecurrence(SE) != One) return Cond; assert(AR->getLoop() == L && @@ -2146,9 +1461,9 @@ ICmpInst *LoopStrengthReduce::OptimizeMax(Loop *L, ICmpInst *Cond, // Check the right operand of the select, and remember it, as it will // be used in the new comparison instruction. Value *NewRHS = 0; - if (SE->getSCEV(Sel->getOperand(1)) == MaxRHS) + if (SE.getSCEV(Sel->getOperand(1)) == MaxRHS) NewRHS = Sel->getOperand(1); - else if (SE->getSCEV(Sel->getOperand(2)) == MaxRHS) + else if (SE.getSCEV(Sel->getOperand(2)) == MaxRHS) NewRHS = Sel->getOperand(2); if (!NewRHS) return Cond; @@ -2175,249 +1490,20 @@ ICmpInst *LoopStrengthReduce::OptimizeMax(Loop *L, ICmpInst *Cond, return NewCond; } -/// OptimizeShadowIV - If IV is used in a int-to-float cast -/// inside the loop then try to eliminate the cast opeation. -void LoopStrengthReduce::OptimizeShadowIV(Loop *L) { - - const SCEV *BackedgeTakenCount = SE->getBackedgeTakenCount(L); - if (isa(BackedgeTakenCount)) - return; - - for (unsigned Stride = 0, e = IU->StrideOrder.size(); Stride != e; - ++Stride) { - std::map::iterator SI = - IU->IVUsesByStride.find(IU->StrideOrder[Stride]); - assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); - if (!isa(SI->first)) - continue; - - for (ilist::iterator UI = SI->second->Users.begin(), - E = SI->second->Users.end(); UI != E; /* empty */) { - ilist::iterator CandidateUI = UI; - ++UI; - Instruction *ShadowUse = CandidateUI->getUser(); - const Type *DestTy = NULL; - - /* If shadow use is a int->float cast then insert a second IV - to eliminate this cast. - - for (unsigned i = 0; i < n; ++i) - foo((double)i); - - is transformed into - - double d = 0.0; - for (unsigned i = 0; i < n; ++i, ++d) - foo(d); - */ - if (UIToFPInst *UCast = dyn_cast(CandidateUI->getUser())) - DestTy = UCast->getDestTy(); - else if (SIToFPInst *SCast = dyn_cast(CandidateUI->getUser())) - DestTy = SCast->getDestTy(); - if (!DestTy) continue; - - if (TLI) { - // If target does not support DestTy natively then do not apply - // this transformation. - EVT DVT = TLI->getValueType(DestTy); - if (!TLI->isTypeLegal(DVT)) continue; - } - - PHINode *PH = dyn_cast(ShadowUse->getOperand(0)); - if (!PH) continue; - if (PH->getNumIncomingValues() != 2) continue; - - const Type *SrcTy = PH->getType(); - int Mantissa = DestTy->getFPMantissaWidth(); - if (Mantissa == -1) continue; - if ((int)SE->getTypeSizeInBits(SrcTy) > Mantissa) - continue; - - unsigned Entry, Latch; - if (PH->getIncomingBlock(0) == L->getLoopPreheader()) { - Entry = 0; - Latch = 1; - } else { - Entry = 1; - Latch = 0; - } - - ConstantInt *Init = dyn_cast(PH->getIncomingValue(Entry)); - if (!Init) continue; - Constant *NewInit = ConstantFP::get(DestTy, Init->getZExtValue()); - - BinaryOperator *Incr = - dyn_cast(PH->getIncomingValue(Latch)); - if (!Incr) continue; - if (Incr->getOpcode() != Instruction::Add - && Incr->getOpcode() != Instruction::Sub) - continue; - - /* Initialize new IV, double d = 0.0 in above example. */ - ConstantInt *C = NULL; - if (Incr->getOperand(0) == PH) - C = dyn_cast(Incr->getOperand(1)); - else if (Incr->getOperand(1) == PH) - C = dyn_cast(Incr->getOperand(0)); - else - continue; - - if (!C) continue; - - // Ignore negative constants, as the code below doesn't handle them - // correctly. TODO: Remove this restriction. - if (!C->getValue().isStrictlyPositive()) continue; - - /* Add new PHINode. */ - PHINode *NewPH = PHINode::Create(DestTy, "IV.S.", PH); - - /* create new increment. '++d' in above example. */ - Constant *CFP = ConstantFP::get(DestTy, C->getZExtValue()); - BinaryOperator *NewIncr = - BinaryOperator::Create(Incr->getOpcode() == Instruction::Add ? - Instruction::FAdd : Instruction::FSub, - NewPH, CFP, "IV.S.next.", Incr); - - NewPH->addIncoming(NewInit, PH->getIncomingBlock(Entry)); - NewPH->addIncoming(NewIncr, PH->getIncomingBlock(Latch)); - - /* Remove cast operation */ - ShadowUse->replaceAllUsesWith(NewPH); - ShadowUse->eraseFromParent(); - NumShadow++; - break; - } - } -} - -/// OptimizeIndvars - Now that IVUsesByStride is set up with all of the indvar -/// uses in the loop, look to see if we can eliminate some, in favor of using -/// common indvars for the different uses. -void LoopStrengthReduce::OptimizeIndvars(Loop *L) { - // TODO: implement optzns here. - - OptimizeShadowIV(L); -} - -bool LoopStrengthReduce::StrideMightBeShared(const SCEV* Stride, Loop *L, - bool CheckPreInc) { - int64_t SInt = cast(Stride)->getValue()->getSExtValue(); - for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { - std::map::iterator SI = - IU->IVUsesByStride.find(IU->StrideOrder[i]); - const SCEV *Share = SI->first; - if (!isa(SI->first) || Share == Stride) - continue; - int64_t SSInt = cast(Share)->getValue()->getSExtValue(); - if (SSInt == SInt) - return true; // This can definitely be reused. - if (unsigned(abs64(SSInt)) < SInt || (SSInt % SInt) != 0) - continue; - int64_t Scale = SSInt / SInt; - bool AllUsesAreAddresses = true; - bool AllUsesAreOutsideLoop = true; - std::vector UsersToProcess; - const SCEV *CommonExprs = CollectIVUsers(SI->first, *SI->second, L, - AllUsesAreAddresses, - AllUsesAreOutsideLoop, - UsersToProcess); - if (AllUsesAreAddresses && - ValidScale(!CommonExprs->isZero(), Scale, UsersToProcess)) { - if (!CheckPreInc) - return true; - // Any pre-inc iv use? - IVUsersOfOneStride &StrideUses = *IU->IVUsesByStride[Share]; - for (ilist::iterator I = StrideUses.Users.begin(), - E = StrideUses.Users.end(); I != E; ++I) { - if (!I->isUseOfPostIncrementedValue()) - return true; - } - } - } - return false; -} - -/// isUsedByExitBranch - Return true if icmp is used by a loop terminating -/// conditional branch or it's and / or with other conditions before being used -/// as the condition. -static bool isUsedByExitBranch(ICmpInst *Cond, Loop *L) { - BasicBlock *CondBB = Cond->getParent(); - if (!L->isLoopExiting(CondBB)) - return false; - BranchInst *TermBr = dyn_cast(CondBB->getTerminator()); - if (!TermBr || !TermBr->isConditional()) - return false; - - Value *User = *Cond->use_begin(); - Instruction *UserInst = dyn_cast(User); - while (UserInst && - (UserInst->getOpcode() == Instruction::And || - UserInst->getOpcode() == Instruction::Or)) { - if (!UserInst->hasOneUse() || UserInst->getParent() != CondBB) - return false; - User = *User->use_begin(); - UserInst = dyn_cast(User); - } - return User == TermBr; -} - -static bool ShouldCountToZero(ICmpInst *Cond, IVStrideUse* &CondUse, - ScalarEvolution *SE, Loop *L, - const TargetLowering *TLI = 0) { - if (!L->contains(Cond)) - return false; - - if (!isa(CondUse->getOffset())) - return false; - - // Handle only tests for equality for the moment. - if (!Cond->isEquality() || !Cond->hasOneUse()) - return false; - if (!isUsedByExitBranch(Cond, L)) - return false; - - Value *CondOp0 = Cond->getOperand(0); - const SCEV *IV = SE->getSCEV(CondOp0); - const SCEVAddRecExpr *AR = dyn_cast(IV); - if (!AR || !AR->isAffine()) - return false; - - const SCEVConstant *SC = dyn_cast(AR->getStepRecurrence(*SE)); - if (!SC || SC->getValue()->getSExtValue() < 0) - // If it's already counting down, don't do anything. - return false; - - // If the RHS of the comparison is not an loop invariant, the rewrite - // cannot be done. Also bail out if it's already comparing against a zero. - // If we are checking this before cmp stride optimization, check if it's - // comparing against a already legal immediate. - Value *RHS = Cond->getOperand(1); - ConstantInt *RHSC = dyn_cast(RHS); - if (!L->isLoopInvariant(RHS) || - (RHSC && RHSC->isZero()) || - (RHSC && TLI && TLI->isLegalICmpImmediate(RHSC->getSExtValue()))) - return false; - - // Make sure the IV is only used for counting. Value may be preinc or - // postinc; 2 uses in either case. - if (!CondOp0->hasNUses(2)) - return false; - - return true; -} - /// OptimizeLoopTermCond - Change loop terminating condition to use the /// postinc iv when possible. -void LoopStrengthReduce::OptimizeLoopTermCond(Loop *L) { +bool +LSRInstance::OptimizeLoopTermCond() { + SmallPtrSet PostIncs; + BasicBlock *LatchBlock = L->getLoopLatch(); - bool LatchExit = L->isLoopExiting(LatchBlock); SmallVector ExitingBlocks; L->getExitingBlocks(ExitingBlocks); for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { BasicBlock *ExitingBlock = ExitingBlocks[i]; - // Finally, get the terminating condition for the loop if possible. If we + // Get the terminating condition for the loop if possible. If we // can, we want to change it to use a post-incremented version of its // induction variable, to allow coalescing the live ranges for the IV into // one register value. @@ -2431,296 +1517,1777 @@ void LoopStrengthReduce::OptimizeLoopTermCond(Loop *L) { // Search IVUsesByStride to find Cond's IVUse if there is one. IVStrideUse *CondUse = 0; - const SCEV *CondStride = 0; ICmpInst *Cond = cast(TermBr->getCondition()); - if (!FindIVUserForCond(Cond, CondUse, CondStride)) + if (!FindIVUserForCond(Cond, CondUse)) continue; - // If the latch block is exiting and it's not a single block loop, it's - // not safe to use postinc iv in other exiting blocks. FIXME: overly - // conservative? How about icmp stride optimization? - bool UsePostInc = !(e > 1 && LatchExit && ExitingBlock != LatchBlock); - if (UsePostInc && ExitingBlock != LatchBlock) { - if (!Cond->hasOneUse()) - // See below, we don't want the condition to be cloned. - UsePostInc = false; - else { - // If exiting block is the latch block, we know it's safe and profitable - // to transform the icmp to use post-inc iv. Otherwise do so only if it - // would not reuse another iv and its iv would be reused by other uses. - // We are optimizing for the case where the icmp is the only use of the - // iv. - IVUsersOfOneStride &StrideUses = *IU->IVUsesByStride[CondStride]; - for (ilist::iterator I = StrideUses.Users.begin(), - E = StrideUses.Users.end(); I != E; ++I) { - if (I->getUser() == Cond) - continue; - if (!I->isUseOfPostIncrementedValue()) { - UsePostInc = false; - break; - } - } - } - - // If iv for the stride might be shared and any of the users use pre-inc - // iv might be used, then it's not safe to use post-inc iv. - if (UsePostInc && - isa(CondStride) && - StrideMightBeShared(CondStride, L, true)) - UsePostInc = false; - } - // If the trip count is computed in terms of a max (due to ScalarEvolution // being unable to find a sufficient guard, for example), change the loop // comparison to use SLT or ULT instead of NE. - Cond = OptimizeMax(L, Cond, CondUse); - - // If possible, change stride and operands of the compare instruction to - // eliminate one stride. However, avoid rewriting the compare instruction - // with an iv of new stride if it's likely the new stride uses will be - // rewritten using the stride of the compare instruction. - if (ExitingBlock == LatchBlock && isa(CondStride)) { - // If the condition stride is a constant and it's the only use, we might - // want to optimize it first by turning it to count toward zero. - if (!StrideMightBeShared(CondStride, L, false) && - !ShouldCountToZero(Cond, CondUse, SE, L, TLI)) - Cond = ChangeCompareStride(L, Cond, CondUse, CondStride); - } - - if (!UsePostInc) + // One consequence of doing this now is that it disrupts the count-down + // optimization. That's not always a bad thing though, because in such + // cases it may still be worthwhile to avoid a max. + Cond = OptimizeMax(Cond, CondUse); + + // If this exiting block dominates the latch block, it may also use + // the post-inc value if it won't be shared with other uses. + // Check for dominance. + if (!DT.dominates(ExitingBlock, LatchBlock)) continue; + // Conservatively avoid trying to use the post-inc value in non-latch + // exits if there may be pre-inc users in intervening blocks. + if (LatchBlock != ExitingBlock) + for (IVUsers::const_iterator UI = IU.begin(), E = IU.end(); UI != E; ++UI) + // Test if the use is reachable from the exiting block. This dominator + // query is a conservative approximation of reachability. + if (&*UI != CondUse && + !DT.properlyDominates(UI->getUser()->getParent(), ExitingBlock)) { + // Conservatively assume there may be reuse if the quotient of their + // strides could be a legal scale. + const SCEV *A = CondUse->getStride(); + const SCEV *B = UI->getStride(); + if (SE.getTypeSizeInBits(A->getType()) != + SE.getTypeSizeInBits(B->getType())) { + if (SE.getTypeSizeInBits(A->getType()) > + SE.getTypeSizeInBits(B->getType())) + B = SE.getSignExtendExpr(B, A->getType()); + else + A = SE.getSignExtendExpr(A, B->getType()); + } + if (const SCEVConstant *D = + dyn_cast_or_null(getExactSDiv(B, A, SE))) { + // Stride of one or negative one can have reuse with non-addresses. + if (D->getValue()->isOne() || + D->getValue()->isAllOnesValue()) + goto decline_post_inc; + // Avoid weird situations. + if (D->getValue()->getValue().getMinSignedBits() >= 64 || + D->getValue()->getValue().isMinSignedValue()) + goto decline_post_inc; + // Without TLI, assume that any stride might be valid, and so any + // use might be shared. + if (!TLI) + goto decline_post_inc; + // Check for possible scaled-address reuse. + const Type *AccessTy = getAccessType(UI->getUser()); + TargetLowering::AddrMode AM; + AM.Scale = D->getValue()->getSExtValue(); + if (TLI->isLegalAddressingMode(AM, AccessTy)) + goto decline_post_inc; + AM.Scale = -AM.Scale; + if (TLI->isLegalAddressingMode(AM, AccessTy)) + goto decline_post_inc; + } + } + DEBUG(dbgs() << " Change loop exiting icmp to use postinc iv: " - << *Cond << '\n'); + << *Cond << '\n'); // It's possible for the setcc instruction to be anywhere in the loop, and // possible for it to have multiple users. If it is not immediately before // the exiting block branch, move it. - if (&*++BasicBlock::iterator(Cond) != (Instruction*)TermBr) { - if (Cond->hasOneUse()) { // Condition has a single use, just move it. + if (&*++BasicBlock::iterator(Cond) != TermBr) { + if (Cond->hasOneUse()) { Cond->moveBefore(TermBr); } else { - // Otherwise, clone the terminating condition and insert into the - // loopend. + // Clone the terminating condition and insert into the loopend. + ICmpInst *OldCond = Cond; Cond = cast(Cond->clone()); Cond->setName(L->getHeader()->getName() + ".termcond"); ExitingBlock->getInstList().insert(TermBr, Cond); // Clone the IVUse, as the old use still exists! - IU->IVUsesByStride[CondStride]->addUser(CondUse->getOffset(), Cond, - CondUse->getOperandValToReplace()); - CondUse = &IU->IVUsesByStride[CondStride]->Users.back(); + CondUse = &IU.AddUser(CondUse->getStride(), CondUse->getOffset(), + Cond, CondUse->getOperandValToReplace()); + TermBr->replaceUsesOfWith(OldCond, Cond); } } // If we get to here, we know that we can transform the setcc instruction to // use the post-incremented version of the IV, allowing us to coalesce the // live ranges for the IV correctly. - CondUse->setOffset(SE->getMinusSCEV(CondUse->getOffset(), CondStride)); + CondUse->setOffset(SE.getMinusSCEV(CondUse->getOffset(), + CondUse->getStride())); CondUse->setIsUseOfPostIncrementedValue(true); Changed = true; - ++NumLoopCond; + PostIncs.insert(Cond); + decline_post_inc:; } -} - -bool LoopStrengthReduce::OptimizeLoopCountIVOfStride(const SCEV* &Stride, - IVStrideUse* &CondUse, - Loop *L) { - // If the only use is an icmp of a loop exiting conditional branch, then - // attempt the optimization. - BasedUser User = BasedUser(*CondUse, SE); - assert(isa(User.Inst) && "Expecting an ICMPInst!"); - ICmpInst *Cond = cast(User.Inst); - // Less strict check now that compare stride optimization is done. - if (!ShouldCountToZero(Cond, CondUse, SE, L)) - return false; + // Determine an insertion point for the loop induction variable increment. It + // must dominate all the post-inc comparisons we just set up, and it must + // dominate the loop latch edge. + IVIncInsertPos = L->getLoopLatch()->getTerminator(); + for (SmallPtrSet::const_iterator I = PostIncs.begin(), + E = PostIncs.end(); I != E; ++I) { + BasicBlock *BB = + DT.findNearestCommonDominator(IVIncInsertPos->getParent(), + (*I)->getParent()); + if (BB == (*I)->getParent()) + IVIncInsertPos = *I; + else if (BB != IVIncInsertPos->getParent()) + IVIncInsertPos = BB->getTerminator(); + } - Value *CondOp0 = Cond->getOperand(0); - PHINode *PHIExpr = dyn_cast(CondOp0); - Instruction *Incr; - if (!PHIExpr) { - // Value tested is postinc. Find the phi node. - Incr = dyn_cast(CondOp0); - // FIXME: Just use User.OperandValToReplace here? - if (!Incr || Incr->getOpcode() != Instruction::Add) - return false; + return Changed; +} - PHIExpr = dyn_cast(Incr->getOperand(0)); - if (!PHIExpr) - return false; - // 1 use for preinc value, the increment. - if (!PHIExpr->hasOneUse()) +bool +LSRInstance::reconcileNewOffset(LSRUse &LU, int64_t NewOffset, + LSRUse::KindType Kind, const Type *AccessTy) { + int64_t NewMinOffset = LU.MinOffset; + int64_t NewMaxOffset = LU.MaxOffset; + const Type *NewAccessTy = AccessTy; + + // Check for a mismatched kind. It's tempting to collapse mismatched kinds to + // something conservative, however this can pessimize in the case that one of + // the uses will have all its uses outside the loop, for example. + if (LU.Kind != Kind) + return false; + // Conservatively assume HasBaseReg is true for now. + if (NewOffset < LU.MinOffset) { + if (!isAlwaysFoldable(LU.MaxOffset - NewOffset, 0, /*HasBaseReg=*/true, + Kind, AccessTy, TLI)) return false; - } else { - assert(isa(CondOp0) && - "Unexpected loop exiting counting instruction sequence!"); - PHIExpr = cast(CondOp0); - // Value tested is preinc. Find the increment. - // A CmpInst is not a BinaryOperator; we depend on this. - Instruction::use_iterator UI = PHIExpr->use_begin(); - Incr = dyn_cast(UI); - if (!Incr) - Incr = dyn_cast(++UI); - // One use for postinc value, the phi. Unnecessarily conservative? - if (!Incr || !Incr->hasOneUse() || Incr->getOpcode() != Instruction::Add) + NewMinOffset = NewOffset; + } else if (NewOffset > LU.MaxOffset) { + if (!isAlwaysFoldable(NewOffset - LU.MinOffset, 0, /*HasBaseReg=*/true, + Kind, AccessTy, TLI)) return false; + NewMaxOffset = NewOffset; } + // Check for a mismatched access type, and fall back conservatively as needed. + if (Kind == LSRUse::Address && AccessTy != LU.AccessTy) + NewAccessTy = Type::getVoidTy(AccessTy->getContext()); + + // Update the use. + LU.MinOffset = NewMinOffset; + LU.MaxOffset = NewMaxOffset; + LU.AccessTy = NewAccessTy; + if (NewOffset != LU.Offsets.back()) + LU.Offsets.push_back(NewOffset); + return true; +} - // Replace the increment with a decrement. - DEBUG(dbgs() << "LSR: Examining use "); - DEBUG(WriteAsOperand(dbgs(), CondOp0, /*PrintType=*/false)); - DEBUG(dbgs() << " in Inst: " << *Cond << '\n'); - BinaryOperator *Decr = BinaryOperator::Create(Instruction::Sub, - Incr->getOperand(0), Incr->getOperand(1), "tmp", Incr); - Incr->replaceAllUsesWith(Decr); - Incr->eraseFromParent(); - - // Substitute endval-startval for the original startval, and 0 for the - // original endval. Since we're only testing for equality this is OK even - // if the computation wraps around. - BasicBlock *Preheader = L->getLoopPreheader(); - Instruction *PreInsertPt = Preheader->getTerminator(); - unsigned InBlock = L->contains(PHIExpr->getIncomingBlock(0)) ? 1 : 0; - Value *StartVal = PHIExpr->getIncomingValue(InBlock); - Value *EndVal = Cond->getOperand(1); - DEBUG(dbgs() << " Optimize loop counting iv to count down [" - << *EndVal << " .. " << *StartVal << "]\n"); - - // FIXME: check for case where both are constant. - Constant* Zero = ConstantInt::get(Cond->getOperand(1)->getType(), 0); - BinaryOperator *NewStartVal = BinaryOperator::Create(Instruction::Sub, - EndVal, StartVal, "tmp", PreInsertPt); - PHIExpr->setIncomingValue(InBlock, NewStartVal); - Cond->setOperand(1, Zero); - DEBUG(dbgs() << " New icmp: " << *Cond << "\n"); - - int64_t SInt = cast(Stride)->getValue()->getSExtValue(); - const SCEV *NewStride = 0; - bool Found = false; - for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { - const SCEV *OldStride = IU->StrideOrder[i]; - if (const SCEVConstant *SC = dyn_cast(OldStride)) - if (SC->getValue()->getSExtValue() == -SInt) { - Found = true; - NewStride = OldStride; - break; - } +/// getUse - Return an LSRUse index and an offset value for a fixup which +/// needs the given expression, with the given kind and optional access type. +/// Either reuse an existing use or create a new one, as needed. +std::pair +LSRInstance::getUse(const SCEV *&Expr, + LSRUse::KindType Kind, const Type *AccessTy) { + const SCEV *Copy = Expr; + int64_t Offset = ExtractImmediate(Expr, SE); + + // Basic uses can't accept any offset, for example. + if (!isAlwaysFoldable(Offset, 0, /*HasBaseReg=*/true, Kind, AccessTy, TLI)) { + Expr = Copy; + Offset = 0; } - if (!Found) - NewStride = SE->getIntegerSCEV(-SInt, Stride->getType()); - IU->AddUser(NewStride, CondUse->getOffset(), Cond, Cond->getOperand(0)); - IU->IVUsesByStride[Stride]->removeUser(CondUse); + std::pair P = + UseMap.insert(std::make_pair(Expr, 0)); + if (!P.second) { + // A use already existed with this base. + size_t LUIdx = P.first->second; + LSRUse &LU = Uses[LUIdx]; + if (reconcileNewOffset(LU, Offset, Kind, AccessTy)) + // Reuse this use. + return std::make_pair(LUIdx, Offset); + } - CondUse = &IU->IVUsesByStride[NewStride]->Users.back(); - Stride = NewStride; + // Create a new use. + size_t LUIdx = Uses.size(); + P.first->second = LUIdx; + Uses.push_back(LSRUse(Kind, AccessTy)); + LSRUse &LU = Uses[LUIdx]; - ++NumCountZero; + // We don't need to track redundant offsets, but we don't need to go out + // of our way here to avoid them. + if (LU.Offsets.empty() || Offset != LU.Offsets.back()) + LU.Offsets.push_back(Offset); - return true; + LU.MinOffset = Offset; + LU.MaxOffset = Offset; + return std::make_pair(LUIdx, Offset); } -/// OptimizeLoopCountIV - If, after all sharing of IVs, the IV used for deciding -/// when to exit the loop is used only for that purpose, try to rearrange things -/// so it counts down to a test against zero. -bool LoopStrengthReduce::OptimizeLoopCountIV(Loop *L) { - bool ThisChanged = false; - for (unsigned i = 0, e = IU->StrideOrder.size(); i != e; ++i) { - const SCEV *Stride = IU->StrideOrder[i]; - std::map::iterator SI = - IU->IVUsesByStride.find(Stride); - assert(SI != IU->IVUsesByStride.end() && "Stride doesn't exist!"); - // FIXME: Generalize to non-affine IV's. - if (!SI->first->isLoopInvariant(L)) - continue; - // If stride is a constant and it has an icmpinst use, check if we can - // optimize the loop to count down. - if (isa(Stride) && SI->second->Users.size() == 1) { - Instruction *User = SI->second->Users.begin()->getUser(); - if (!isa(User)) - continue; - const SCEV *CondStride = Stride; - IVStrideUse *Use = &*SI->second->Users.begin(); - if (!OptimizeLoopCountIVOfStride(CondStride, Use, L)) - continue; - ThisChanged = true; +void LSRInstance::CollectInterestingTypesAndFactors() { + SmallSetVector Strides; - // Now check if it's possible to reuse this iv for other stride uses. - for (unsigned j = 0, ee = IU->StrideOrder.size(); j != ee; ++j) { - const SCEV *SStride = IU->StrideOrder[j]; - if (SStride == CondStride) - continue; - std::map::iterator SII = - IU->IVUsesByStride.find(SStride); - assert(SII != IU->IVUsesByStride.end() && "Stride doesn't exist!"); - // FIXME: Generalize to non-affine IV's. - if (!SII->first->isLoopInvariant(L)) - continue; - // FIXME: Rewrite other stride using CondStride. + // Collect interesting types and strides. + for (IVUsers::const_iterator UI = IU.begin(), E = IU.end(); UI != E; ++UI) { + const SCEV *Stride = UI->getStride(); + + // Collect interesting types. + Types.insert(SE.getEffectiveSCEVType(Stride->getType())); + + // Add the stride for this loop. + Strides.insert(Stride); + + // Add strides for other mentioned loops. + for (const SCEVAddRecExpr *AR = dyn_cast(UI->getOffset()); + AR; AR = dyn_cast(AR->getStart())) + Strides.insert(AR->getStepRecurrence(SE)); + } + + // Compute interesting factors from the set of interesting strides. + for (SmallSetVector::const_iterator + I = Strides.begin(), E = Strides.end(); I != E; ++I) + for (SmallSetVector::const_iterator NewStrideIter = + next(I); NewStrideIter != E; ++NewStrideIter) { + const SCEV *OldStride = *I; + const SCEV *NewStride = *NewStrideIter; + + if (SE.getTypeSizeInBits(OldStride->getType()) != + SE.getTypeSizeInBits(NewStride->getType())) { + if (SE.getTypeSizeInBits(OldStride->getType()) > + SE.getTypeSizeInBits(NewStride->getType())) + NewStride = SE.getSignExtendExpr(NewStride, OldStride->getType()); + else + OldStride = SE.getSignExtendExpr(OldStride, NewStride->getType()); + } + if (const SCEVConstant *Factor = + dyn_cast_or_null(getExactSDiv(NewStride, OldStride, + SE, true))) { + if (Factor->getValue()->getValue().getMinSignedBits() <= 64) + Factors.insert(Factor->getValue()->getValue().getSExtValue()); + } else if (const SCEVConstant *Factor = + dyn_cast_or_null(getExactSDiv(OldStride, + NewStride, + SE, true))) { + if (Factor->getValue()->getValue().getMinSignedBits() <= 64) + Factors.insert(Factor->getValue()->getValue().getSExtValue()); } } + + // If all uses use the same type, don't bother looking for truncation-based + // reuse. + if (Types.size() == 1) + Types.clear(); + + DEBUG(print_factors_and_types(dbgs())); +} + +void LSRInstance::CollectFixupsAndInitialFormulae() { + for (IVUsers::const_iterator UI = IU.begin(), E = IU.end(); UI != E; ++UI) { + // Record the uses. + LSRFixup &LF = getNewFixup(); + LF.UserInst = UI->getUser(); + LF.OperandValToReplace = UI->getOperandValToReplace(); + if (UI->isUseOfPostIncrementedValue()) + LF.PostIncLoop = L; + + LSRUse::KindType Kind = LSRUse::Basic; + const Type *AccessTy = 0; + if (isAddressUse(LF.UserInst, LF.OperandValToReplace)) { + Kind = LSRUse::Address; + AccessTy = getAccessType(LF.UserInst); + } + + const SCEV *S = IU.getCanonicalExpr(*UI); + + // Equality (== and !=) ICmps are special. We can rewrite (i == N) as + // (N - i == 0), and this allows (N - i) to be the expression that we work + // with rather than just N or i, so we can consider the register + // requirements for both N and i at the same time. Limiting this code to + // equality icmps is not a problem because all interesting loops use + // equality icmps, thanks to IndVarSimplify. + if (ICmpInst *CI = dyn_cast(LF.UserInst)) + if (CI->isEquality()) { + // Swap the operands if needed to put the OperandValToReplace on the + // left, for consistency. + Value *NV = CI->getOperand(1); + if (NV == LF.OperandValToReplace) { + CI->setOperand(1, CI->getOperand(0)); + CI->setOperand(0, NV); + } + + // x == y --> x - y == 0 + const SCEV *N = SE.getSCEV(NV); + if (N->isLoopInvariant(L)) { + Kind = LSRUse::ICmpZero; + S = SE.getMinusSCEV(N, S); + } + + // -1 and the negations of all interesting strides (except the negation + // of -1) are now also interesting. + for (size_t i = 0, e = Factors.size(); i != e; ++i) + if (Factors[i] != -1) + Factors.insert(-(uint64_t)Factors[i]); + Factors.insert(-1); + } + + // Set up the initial formula for this use. + std::pair P = getUse(S, Kind, AccessTy); + LF.LUIdx = P.first; + LF.Offset = P.second; + LSRUse &LU = Uses[LF.LUIdx]; + LU.AllFixupsOutsideLoop &= !L->contains(LF.UserInst); + + // If this is the first use of this LSRUse, give it a formula. + if (LU.Formulae.empty()) { + InsertInitialFormula(S, LU, LF.LUIdx); + CountRegisters(LU.Formulae.back(), LF.LUIdx); + } } - Changed |= ThisChanged; - return ThisChanged; + DEBUG(print_fixups(dbgs())); } -bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager &LPM) { - IU = &getAnalysis(); - SE = &getAnalysis(); - Changed = false; +void +LSRInstance::InsertInitialFormula(const SCEV *S, LSRUse &LU, size_t LUIdx) { + Formula F; + F.InitialMatch(S, L, SE, DT); + bool Inserted = InsertFormula(LU, LUIdx, F); + assert(Inserted && "Initial formula already exists!"); (void)Inserted; +} - // If LoopSimplify form is not available, stay out of trouble. - if (!L->getLoopPreheader() || !L->getLoopLatch()) +void +LSRInstance::InsertSupplementalFormula(const SCEV *S, + LSRUse &LU, size_t LUIdx) { + Formula F; + F.BaseRegs.push_back(S); + F.AM.HasBaseReg = true; + bool Inserted = InsertFormula(LU, LUIdx, F); + assert(Inserted && "Supplemental formula already exists!"); (void)Inserted; +} + +/// CountRegisters - Note which registers are used by the given formula, +/// updating RegUses. +void LSRInstance::CountRegisters(const Formula &F, size_t LUIdx) { + if (F.ScaledReg) + RegUses.CountRegister(F.ScaledReg, LUIdx); + for (SmallVectorImpl::const_iterator I = F.BaseRegs.begin(), + E = F.BaseRegs.end(); I != E; ++I) + RegUses.CountRegister(*I, LUIdx); +} + +/// InsertFormula - If the given formula has not yet been inserted, add it to +/// the list, and return true. Return false otherwise. +bool LSRInstance::InsertFormula(LSRUse &LU, unsigned LUIdx, const Formula &F) { + if (!LU.InsertFormula(F)) return false; - if (!IU->IVUsesByStride.empty()) { - DEBUG(dbgs() << "\nLSR on \"" << L->getHeader()->getParent()->getName() - << "\" "; - L->print(dbgs())); + CountRegisters(F, LUIdx); + return true; +} - // Sort the StrideOrder so we process larger strides first. - std::stable_sort(IU->StrideOrder.begin(), IU->StrideOrder.end(), - StrideCompare(SE)); +/// CollectLoopInvariantFixupsAndFormulae - Check for other uses of +/// loop-invariant values which we're tracking. These other uses will pin these +/// values in registers, making them less profitable for elimination. +/// TODO: This currently misses non-constant addrec step registers. +/// TODO: Should this give more weight to users inside the loop? +void +LSRInstance::CollectLoopInvariantFixupsAndFormulae() { + SmallVector Worklist(RegUses.begin(), RegUses.end()); + SmallPtrSet Inserted; + + while (!Worklist.empty()) { + const SCEV *S = Worklist.pop_back_val(); + + if (const SCEVNAryExpr *N = dyn_cast(S)) + Worklist.insert(Worklist.end(), N->op_begin(), N->op_end()); + else if (const SCEVCastExpr *C = dyn_cast(S)) + Worklist.push_back(C->getOperand()); + else if (const SCEVUDivExpr *D = dyn_cast(S)) { + Worklist.push_back(D->getLHS()); + Worklist.push_back(D->getRHS()); + } else if (const SCEVUnknown *U = dyn_cast(S)) { + if (!Inserted.insert(U)) continue; + const Value *V = U->getValue(); + if (const Instruction *Inst = dyn_cast(V)) + if (L->contains(Inst)) continue; + for (Value::use_const_iterator UI = V->use_begin(), UE = V->use_end(); + UI != UE; ++UI) { + const Instruction *UserInst = dyn_cast(*UI); + // Ignore non-instructions. + if (!UserInst) + continue; + // Ignore instructions in other functions (as can happen with + // Constants). + if (UserInst->getParent()->getParent() != L->getHeader()->getParent()) + continue; + // Ignore instructions not dominated by the loop. + const BasicBlock *UseBB = !isa(UserInst) ? + UserInst->getParent() : + cast(UserInst)->getIncomingBlock( + PHINode::getIncomingValueNumForOperand(UI.getOperandNo())); + if (!DT.dominates(L->getHeader(), UseBB)) + continue; + // Ignore uses which are part of other SCEV expressions, to avoid + // analyzing them multiple times. + if (SE.isSCEVable(UserInst->getType()) && + !isa(SE.getSCEV(const_cast(UserInst)))) + continue; + // Ignore icmp instructions which are already being analyzed. + if (const ICmpInst *ICI = dyn_cast(UserInst)) { + unsigned OtherIdx = !UI.getOperandNo(); + Value *OtherOp = const_cast(ICI->getOperand(OtherIdx)); + if (SE.getSCEV(OtherOp)->hasComputableLoopEvolution(L)) + continue; + } - // Optimize induction variables. Some indvar uses can be transformed to use - // strides that will be needed for other purposes. A common example of this - // is the exit test for the loop, which can often be rewritten to use the - // computation of some other indvar to decide when to terminate the loop. - OptimizeIndvars(L); + LSRFixup &LF = getNewFixup(); + LF.UserInst = const_cast(UserInst); + LF.OperandValToReplace = UI.getUse(); + std::pair P = getUse(S, LSRUse::Basic, 0); + LF.LUIdx = P.first; + LF.Offset = P.second; + LSRUse &LU = Uses[LF.LUIdx]; + LU.AllFixupsOutsideLoop &= L->contains(LF.UserInst); + InsertSupplementalFormula(U, LU, LF.LUIdx); + CountRegisters(LU.Formulae.back(), Uses.size() - 1); + break; + } + } + } +} + +/// CollectSubexprs - Split S into subexpressions which can be pulled out into +/// separate registers. If C is non-null, multiply each subexpression by C. +static void CollectSubexprs(const SCEV *S, const SCEVConstant *C, + SmallVectorImpl &Ops, + ScalarEvolution &SE) { + if (const SCEVAddExpr *Add = dyn_cast(S)) { + // Break out add operands. + for (SCEVAddExpr::op_iterator I = Add->op_begin(), E = Add->op_end(); + I != E; ++I) + CollectSubexprs(*I, C, Ops, SE); + return; + } else if (const SCEVAddRecExpr *AR = dyn_cast(S)) { + // Split a non-zero base out of an addrec. + if (!AR->getStart()->isZero()) { + CollectSubexprs(SE.getAddRecExpr(SE.getIntegerSCEV(0, AR->getType()), + AR->getStepRecurrence(SE), + AR->getLoop()), C, Ops, SE); + CollectSubexprs(AR->getStart(), C, Ops, SE); + return; + } + } else if (const SCEVMulExpr *Mul = dyn_cast(S)) { + // Break (C * (a + b + c)) into C*a + C*b + C*c. + if (Mul->getNumOperands() == 2) + if (const SCEVConstant *Op0 = + dyn_cast(Mul->getOperand(0))) { + CollectSubexprs(Mul->getOperand(1), + C ? cast(SE.getMulExpr(C, Op0)) : Op0, + Ops, SE); + return; + } + } + + // Otherwise use the value itself. + Ops.push_back(C ? SE.getMulExpr(C, S) : S); +} + +/// GenerateReassociations - Split out subexpressions from adds and the bases of +/// addrecs. +void LSRInstance::GenerateReassociations(LSRUse &LU, unsigned LUIdx, + Formula Base, + unsigned Depth) { + // Arbitrarily cap recursion to protect compile time. + if (Depth >= 3) return; + + for (size_t i = 0, e = Base.BaseRegs.size(); i != e; ++i) { + const SCEV *BaseReg = Base.BaseRegs[i]; + + SmallVector AddOps; + CollectSubexprs(BaseReg, 0, AddOps, SE); + if (AddOps.size() == 1) continue; + + for (SmallVectorImpl::const_iterator J = AddOps.begin(), + JE = AddOps.end(); J != JE; ++J) { + // Don't pull a constant into a register if the constant could be folded + // into an immediate field. + if (isAlwaysFoldable(*J, LU.MinOffset, LU.MaxOffset, + Base.getNumRegs() > 1, + LU.Kind, LU.AccessTy, TLI, SE)) + continue; + + // Collect all operands except *J. + SmallVector InnerAddOps; + for (SmallVectorImpl::const_iterator K = AddOps.begin(), + KE = AddOps.end(); K != KE; ++K) + if (K != J) + InnerAddOps.push_back(*K); + + // Don't leave just a constant behind in a register if the constant could + // be folded into an immediate field. + if (InnerAddOps.size() == 1 && + isAlwaysFoldable(InnerAddOps[0], LU.MinOffset, LU.MaxOffset, + Base.getNumRegs() > 1, + LU.Kind, LU.AccessTy, TLI, SE)) + continue; + + Formula F = Base; + F.BaseRegs[i] = SE.getAddExpr(InnerAddOps); + F.BaseRegs.push_back(*J); + if (InsertFormula(LU, LUIdx, F)) + // If that formula hadn't been seen before, recurse to find more like + // it. + GenerateReassociations(LU, LUIdx, LU.Formulae.back(), Depth+1); + } + } +} - // Change loop terminating condition to use the postinc iv when possible - // and optimize loop terminating compare. FIXME: Move this after - // StrengthReduceIVUsersOfStride? - OptimizeLoopTermCond(L); +/// GenerateCombinations - Generate a formula consisting of all of the +/// loop-dominating registers added into a single register. +void LSRInstance::GenerateCombinations(LSRUse &LU, unsigned LUIdx, + Formula Base) { + // This method is only interesting on a plurality of registers. + if (Base.BaseRegs.size() <= 1) return; + + Formula F = Base; + F.BaseRegs.clear(); + SmallVector Ops; + for (SmallVectorImpl::const_iterator + I = Base.BaseRegs.begin(), E = Base.BaseRegs.end(); I != E; ++I) { + const SCEV *BaseReg = *I; + if (BaseReg->properlyDominates(L->getHeader(), &DT) && + !BaseReg->hasComputableLoopEvolution(L)) + Ops.push_back(BaseReg); + else + F.BaseRegs.push_back(BaseReg); + } + if (Ops.size() > 1) { + const SCEV *Sum = SE.getAddExpr(Ops); + // TODO: If Sum is zero, it probably means ScalarEvolution missed an + // opportunity to fold something. For now, just ignore such cases + // rather than proceed with zero in a register. + if (!Sum->isZero()) { + F.BaseRegs.push_back(Sum); + (void)InsertFormula(LU, LUIdx, F); + } + } +} - // FIXME: We can shrink overlarge IV's here. e.g. if the code has - // computation in i64 values and the target doesn't support i64, demote - // the computation to 32-bit if safe. +/// GenerateSymbolicOffsets - Generate reuse formulae using symbolic offsets. +void LSRInstance::GenerateSymbolicOffsets(LSRUse &LU, unsigned LUIdx, + Formula Base) { + // We can't add a symbolic offset if the address already contains one. + if (Base.AM.BaseGV) return; - // FIXME: Attempt to reuse values across multiple IV's. In particular, we - // could have something like "for(i) { foo(i*8); bar(i*16) }", which should - // be codegened as "for (j = 0;; j+=8) { foo(j); bar(j+j); }" on X86/PPC. - // Need to be careful that IV's are all the same type. Only works for - // intptr_t indvars. + for (size_t i = 0, e = Base.BaseRegs.size(); i != e; ++i) { + const SCEV *G = Base.BaseRegs[i]; + GlobalValue *GV = ExtractSymbol(G, SE); + if (G->isZero() || !GV) + continue; + Formula F = Base; + F.AM.BaseGV = GV; + if (!isLegalUse(F.AM, LU.MinOffset, LU.MaxOffset, + LU.Kind, LU.AccessTy, TLI)) + continue; + F.BaseRegs[i] = G; + (void)InsertFormula(LU, LUIdx, F); + } +} + +/// GenerateConstantOffsets - Generate reuse formulae using symbolic offsets. +void LSRInstance::GenerateConstantOffsets(LSRUse &LU, unsigned LUIdx, + Formula Base) { + // TODO: For now, just add the min and max offset, because it usually isn't + // worthwhile looking at everything inbetween. + SmallVector Worklist; + Worklist.push_back(LU.MinOffset); + if (LU.MaxOffset != LU.MinOffset) + Worklist.push_back(LU.MaxOffset); + + for (size_t i = 0, e = Base.BaseRegs.size(); i != e; ++i) { + const SCEV *G = Base.BaseRegs[i]; + + for (SmallVectorImpl::const_iterator I = Worklist.begin(), + E = Worklist.end(); I != E; ++I) { + Formula F = Base; + F.AM.BaseOffs = (uint64_t)Base.AM.BaseOffs - *I; + if (isLegalUse(F.AM, LU.MinOffset - *I, LU.MaxOffset - *I, + LU.Kind, LU.AccessTy, TLI)) { + F.BaseRegs[i] = SE.getAddExpr(G, SE.getIntegerSCEV(*I, G->getType())); + + (void)InsertFormula(LU, LUIdx, F); + } + } + + int64_t Imm = ExtractImmediate(G, SE); + if (G->isZero() || Imm == 0) + continue; + Formula F = Base; + F.AM.BaseOffs = (uint64_t)F.AM.BaseOffs + Imm; + if (!isLegalUse(F.AM, LU.MinOffset, LU.MaxOffset, + LU.Kind, LU.AccessTy, TLI)) + continue; + F.BaseRegs[i] = G; + (void)InsertFormula(LU, LUIdx, F); + } +} - // IVsByStride keeps IVs for one particular loop. - assert(IVsByStride.empty() && "Stale entries in IVsByStride?"); +/// GenerateICmpZeroScales - For ICmpZero, check to see if we can scale up +/// the comparison. For example, x == y -> x*c == y*c. +void LSRInstance::GenerateICmpZeroScales(LSRUse &LU, unsigned LUIdx, + Formula Base) { + if (LU.Kind != LSRUse::ICmpZero) return; - StrengthReduceIVUsers(L); + // Determine the integer type for the base formula. + const Type *IntTy = Base.getType(); + if (!IntTy) return; + if (SE.getTypeSizeInBits(IntTy) > 64) return; - // After all sharing is done, see if we can adjust the loop to test against - // zero instead of counting up to a maximum. This is usually faster. - OptimizeLoopCountIV(L); + // Don't do this if there is more than one offset. + if (LU.MinOffset != LU.MaxOffset) return; - // We're done analyzing this loop; release all the state we built up for it. - IVsByStride.clear(); + assert(!Base.AM.BaseGV && "ICmpZero use is not legal!"); - // Clean up after ourselves - DeleteTriviallyDeadInstructions(); + // Check each interesting stride. + for (SmallSetVector::const_iterator + I = Factors.begin(), E = Factors.end(); I != E; ++I) { + int64_t Factor = *I; + Formula F = Base; + + // Check that the multiplication doesn't overflow. + if (F.AM.BaseOffs == INT64_MIN && Factor == -1) + continue; + F.AM.BaseOffs = (uint64_t)Base.AM.BaseOffs * Factor; + if (F.AM.BaseOffs / Factor != Base.AM.BaseOffs) + continue; + + // Check that multiplying with the use offset doesn't overflow. + int64_t Offset = LU.MinOffset; + if (Offset == INT64_MIN && Factor == -1) + continue; + Offset = (uint64_t)Offset * Factor; + if (Offset / Factor != LU.MinOffset) + continue; + + // Check that this scale is legal. + if (!isLegalUse(F.AM, Offset, Offset, LU.Kind, LU.AccessTy, TLI)) + continue; + + // Compensate for the use having MinOffset built into it. + F.AM.BaseOffs = (uint64_t)F.AM.BaseOffs + Offset - LU.MinOffset; + + const SCEV *FactorS = SE.getIntegerSCEV(Factor, IntTy); + + // Check that multiplying with each base register doesn't overflow. + for (size_t i = 0, e = F.BaseRegs.size(); i != e; ++i) { + F.BaseRegs[i] = SE.getMulExpr(F.BaseRegs[i], FactorS); + if (getExactSDiv(F.BaseRegs[i], FactorS, SE) != Base.BaseRegs[i]) + goto next; + } + + // Check that multiplying with the scaled register doesn't overflow. + if (F.ScaledReg) { + F.ScaledReg = SE.getMulExpr(F.ScaledReg, FactorS); + if (getExactSDiv(F.ScaledReg, FactorS, SE) != Base.ScaledReg) + continue; + } + + // If we make it here and it's legal, add it. + (void)InsertFormula(LU, LUIdx, F); + next:; + } +} + +/// GenerateScales - Generate stride factor reuse formulae by making use of +/// scaled-offset address modes, for example. +void LSRInstance::GenerateScales(LSRUse &LU, unsigned LUIdx, + Formula Base) { + // Determine the integer type for the base formula. + const Type *IntTy = Base.getType(); + if (!IntTy) return; + + // If this Formula already has a scaled register, we can't add another one. + if (Base.AM.Scale != 0) return; + + // Check each interesting stride. + for (SmallSetVector::const_iterator + I = Factors.begin(), E = Factors.end(); I != E; ++I) { + int64_t Factor = *I; + + Base.AM.Scale = Factor; + Base.AM.HasBaseReg = Base.BaseRegs.size() > 1; + // Check whether this scale is going to be legal. + if (!isLegalUse(Base.AM, LU.MinOffset, LU.MaxOffset, + LU.Kind, LU.AccessTy, TLI)) { + // As a special-case, handle special out-of-loop Basic users specially. + // TODO: Reconsider this special case. + if (LU.Kind == LSRUse::Basic && + isLegalUse(Base.AM, LU.MinOffset, LU.MaxOffset, + LSRUse::Special, LU.AccessTy, TLI) && + LU.AllFixupsOutsideLoop) + LU.Kind = LSRUse::Special; + else + continue; + } + // For an ICmpZero, negating a solitary base register won't lead to + // new solutions. + if (LU.Kind == LSRUse::ICmpZero && + !Base.AM.HasBaseReg && Base.AM.BaseOffs == 0 && !Base.AM.BaseGV) + continue; + // For each addrec base reg, apply the scale, if possible. + for (size_t i = 0, e = Base.BaseRegs.size(); i != e; ++i) + if (const SCEVAddRecExpr *AR = + dyn_cast(Base.BaseRegs[i])) { + const SCEV *FactorS = SE.getIntegerSCEV(Factor, IntTy); + if (FactorS->isZero()) + continue; + // Divide out the factor, ignoring high bits, since we'll be + // scaling the value back up in the end. + if (const SCEV *Quotient = getExactSDiv(AR, FactorS, SE, true)) { + // TODO: This could be optimized to avoid all the copying. + Formula F = Base; + F.ScaledReg = Quotient; + std::swap(F.BaseRegs[i], F.BaseRegs.back()); + F.BaseRegs.pop_back(); + (void)InsertFormula(LU, LUIdx, F); + } + } + } +} + +/// GenerateTruncates - Generate reuse formulae from different IV types. +void LSRInstance::GenerateTruncates(LSRUse &LU, unsigned LUIdx, + Formula Base) { + // This requires TargetLowering to tell us which truncates are free. + if (!TLI) return; + + // Don't bother truncating symbolic values. + if (Base.AM.BaseGV) return; + + // Determine the integer type for the base formula. + const Type *DstTy = Base.getType(); + if (!DstTy) return; + DstTy = SE.getEffectiveSCEVType(DstTy); + + for (SmallSetVector::const_iterator + I = Types.begin(), E = Types.end(); I != E; ++I) { + const Type *SrcTy = *I; + if (SrcTy != DstTy && TLI->isTruncateFree(SrcTy, DstTy)) { + Formula F = Base; + + if (F.ScaledReg) F.ScaledReg = SE.getAnyExtendExpr(F.ScaledReg, *I); + for (SmallVectorImpl::iterator J = F.BaseRegs.begin(), + JE = F.BaseRegs.end(); J != JE; ++J) + *J = SE.getAnyExtendExpr(*J, SrcTy); + + // TODO: This assumes we've done basic processing on all uses and + // have an idea what the register usage is. + if (!F.hasRegsUsedByUsesOtherThan(LUIdx, RegUses)) + continue; + + (void)InsertFormula(LU, LUIdx, F); + } + } +} + +namespace { + +/// WorkItem - Helper class for GenerateCrossUseConstantOffsets. It's used to +/// defer modifications so that the search phase doesn't have to worry about +/// the data structures moving underneath it. +struct WorkItem { + size_t LUIdx; + int64_t Imm; + const SCEV *OrigReg; + + WorkItem(size_t LI, int64_t I, const SCEV *R) + : LUIdx(LI), Imm(I), OrigReg(R) {} + + void print(raw_ostream &OS) const; + void dump() const; +}; + +} + +void WorkItem::print(raw_ostream &OS) const { + OS << "in formulae referencing " << *OrigReg << " in use " << LUIdx + << " , add offset " << Imm; +} + +void WorkItem::dump() const { + print(errs()); errs() << '\n'; +} + +/// GenerateCrossUseConstantOffsets - Look for registers which are a constant +/// distance apart and try to form reuse opportunities between them. +void LSRInstance::GenerateCrossUseConstantOffsets() { + // Group the registers by their value without any added constant offset. + typedef std::map ImmMapTy; + typedef DenseMap RegMapTy; + RegMapTy Map; + DenseMap UsedByIndicesMap; + SmallVector Sequence; + for (RegUseTracker::const_iterator I = RegUses.begin(), E = RegUses.end(); + I != E; ++I) { + const SCEV *Reg = *I; + int64_t Imm = ExtractImmediate(Reg, SE); + std::pair Pair = + Map.insert(std::make_pair(Reg, ImmMapTy())); + if (Pair.second) + Sequence.push_back(Reg); + Pair.first->second.insert(std::make_pair(Imm, *I)); + UsedByIndicesMap[Reg] |= RegUses.getUsedByIndices(*I); + } + + // Now examine each set of registers with the same base value. Build up + // a list of work to do and do the work in a separate step so that we're + // not adding formulae and register counts while we're searching. + SmallVector WorkItems; + SmallSet, 32> UniqueItems; + for (SmallVectorImpl::const_iterator I = Sequence.begin(), + E = Sequence.end(); I != E; ++I) { + const SCEV *Reg = *I; + const ImmMapTy &Imms = Map.find(Reg)->second; + + // It's not worthwhile looking for reuse if there's only one offset. + if (Imms.size() == 1) + continue; + + DEBUG(dbgs() << "Generating cross-use offsets for " << *Reg << ':'; + for (ImmMapTy::const_iterator J = Imms.begin(), JE = Imms.end(); + J != JE; ++J) + dbgs() << ' ' << J->first; + dbgs() << '\n'); + + // Examine each offset. + for (ImmMapTy::const_iterator J = Imms.begin(), JE = Imms.end(); + J != JE; ++J) { + const SCEV *OrigReg = J->second; + + int64_t JImm = J->first; + const SmallBitVector &UsedByIndices = RegUses.getUsedByIndices(OrigReg); + + if (!isa(OrigReg) && + UsedByIndicesMap[Reg].count() == 1) { + DEBUG(dbgs() << "Skipping cross-use reuse for " << *OrigReg << '\n'); + continue; + } + + // Conservatively examine offsets between this orig reg a few selected + // other orig regs. + ImmMapTy::const_iterator OtherImms[] = { + Imms.begin(), prior(Imms.end()), + Imms.upper_bound((Imms.begin()->first + prior(Imms.end())->first) / 2) + }; + for (size_t i = 0, e = array_lengthof(OtherImms); i != e; ++i) { + ImmMapTy::const_iterator M = OtherImms[i]; + if (M == J || M == JE) continue; + + // Compute the difference between the two. + int64_t Imm = (uint64_t)JImm - M->first; + for (int LUIdx = UsedByIndices.find_first(); LUIdx != -1; + LUIdx = UsedByIndices.find_next(LUIdx)) + // Make a memo of this use, offset, and register tuple. + if (UniqueItems.insert(std::make_pair(LUIdx, Imm))) + WorkItems.push_back(WorkItem(LUIdx, Imm, OrigReg)); + } + } + } + + Map.clear(); + Sequence.clear(); + UsedByIndicesMap.clear(); + UniqueItems.clear(); + + // Now iterate through the worklist and add new formulae. + for (SmallVectorImpl::const_iterator I = WorkItems.begin(), + E = WorkItems.end(); I != E; ++I) { + const WorkItem &WI = *I; + size_t LUIdx = WI.LUIdx; + LSRUse &LU = Uses[LUIdx]; + int64_t Imm = WI.Imm; + const SCEV *OrigReg = WI.OrigReg; + + const Type *IntTy = SE.getEffectiveSCEVType(OrigReg->getType()); + const SCEV *NegImmS = SE.getSCEV(ConstantInt::get(IntTy, -(uint64_t)Imm)); + unsigned BitWidth = SE.getTypeSizeInBits(IntTy); + + // TODO: Use a more targeted data structure. + for (size_t L = 0, LE = LU.Formulae.size(); L != LE; ++L) { + Formula F = LU.Formulae[L]; + // Use the immediate in the scaled register. + if (F.ScaledReg == OrigReg) { + int64_t Offs = (uint64_t)F.AM.BaseOffs + + Imm * (uint64_t)F.AM.Scale; + // Don't create 50 + reg(-50). + if (F.referencesReg(SE.getSCEV( + ConstantInt::get(IntTy, -(uint64_t)Offs)))) + continue; + Formula NewF = F; + NewF.AM.BaseOffs = Offs; + if (!isLegalUse(NewF.AM, LU.MinOffset, LU.MaxOffset, + LU.Kind, LU.AccessTy, TLI)) + continue; + NewF.ScaledReg = SE.getAddExpr(NegImmS, NewF.ScaledReg); + + // If the new scale is a constant in a register, and adding the constant + // value to the immediate would produce a value closer to zero than the + // immediate itself, then the formula isn't worthwhile. + if (const SCEVConstant *C = dyn_cast(NewF.ScaledReg)) + if (C->getValue()->getValue().isNegative() != + (NewF.AM.BaseOffs < 0) && + (C->getValue()->getValue().abs() * APInt(BitWidth, F.AM.Scale)) + .ule(APInt(BitWidth, NewF.AM.BaseOffs).abs())) + continue; + + // OK, looks good. + (void)InsertFormula(LU, LUIdx, NewF); + } else { + // Use the immediate in a base register. + for (size_t N = 0, NE = F.BaseRegs.size(); N != NE; ++N) { + const SCEV *BaseReg = F.BaseRegs[N]; + if (BaseReg != OrigReg) + continue; + Formula NewF = F; + NewF.AM.BaseOffs = (uint64_t)NewF.AM.BaseOffs + Imm; + if (!isLegalUse(NewF.AM, LU.MinOffset, LU.MaxOffset, + LU.Kind, LU.AccessTy, TLI)) + continue; + NewF.BaseRegs[N] = SE.getAddExpr(NegImmS, BaseReg); + + // If the new formula has a constant in a register, and adding the + // constant value to the immediate would produce a value closer to + // zero than the immediate itself, then the formula isn't worthwhile. + for (SmallVectorImpl::const_iterator + J = NewF.BaseRegs.begin(), JE = NewF.BaseRegs.end(); + J != JE; ++J) + if (const SCEVConstant *C = dyn_cast(*J)) + if (C->getValue()->getValue().isNegative() != + (NewF.AM.BaseOffs < 0) && + C->getValue()->getValue().abs() + .ule(APInt(BitWidth, NewF.AM.BaseOffs).abs())) + goto skip_formula; + + // Ok, looks good. + (void)InsertFormula(LU, LUIdx, NewF); + break; + skip_formula:; + } + } + } + } +} + +/// GenerateAllReuseFormulae - Generate formulae for each use. +void +LSRInstance::GenerateAllReuseFormulae() { + // This is split into multiple loops so that hasRegsUsedByUsesOtherThan + // queries are more precise. + for (size_t LUIdx = 0, NumUses = Uses.size(); LUIdx != NumUses; ++LUIdx) { + LSRUse &LU = Uses[LUIdx]; + for (size_t i = 0, f = LU.Formulae.size(); i != f; ++i) + GenerateReassociations(LU, LUIdx, LU.Formulae[i]); + for (size_t i = 0, f = LU.Formulae.size(); i != f; ++i) + GenerateCombinations(LU, LUIdx, LU.Formulae[i]); + } + for (size_t LUIdx = 0, NumUses = Uses.size(); LUIdx != NumUses; ++LUIdx) { + LSRUse &LU = Uses[LUIdx]; + for (size_t i = 0, f = LU.Formulae.size(); i != f; ++i) + GenerateSymbolicOffsets(LU, LUIdx, LU.Formulae[i]); + for (size_t i = 0, f = LU.Formulae.size(); i != f; ++i) + GenerateConstantOffsets(LU, LUIdx, LU.Formulae[i]); + for (size_t i = 0, f = LU.Formulae.size(); i != f; ++i) + GenerateICmpZeroScales(LU, LUIdx, LU.Formulae[i]); + for (size_t i = 0, f = LU.Formulae.size(); i != f; ++i) + GenerateScales(LU, LUIdx, LU.Formulae[i]); } + for (size_t LUIdx = 0, NumUses = Uses.size(); LUIdx != NumUses; ++LUIdx) { + LSRUse &LU = Uses[LUIdx]; + for (size_t i = 0, f = LU.Formulae.size(); i != f; ++i) + GenerateTruncates(LU, LUIdx, LU.Formulae[i]); + } + + GenerateCrossUseConstantOffsets(); +} + +/// If their are multiple formulae with the same set of registers used +/// by other uses, pick the best one and delete the others. +void LSRInstance::FilterOutUndesirableDedicatedRegisters() { +#ifndef NDEBUG + bool Changed = false; +#endif + + // Collect the best formula for each unique set of shared registers. This + // is reset for each use. + typedef DenseMap, size_t, UniquifierDenseMapInfo> + BestFormulaeTy; + BestFormulaeTy BestFormulae; + + for (size_t LUIdx = 0, NumUses = Uses.size(); LUIdx != NumUses; ++LUIdx) { + LSRUse &LU = Uses[LUIdx]; + FormulaSorter Sorter(L, LU, SE, DT); + + // Clear out the set of used regs; it will be recomputed. + LU.Regs.clear(); + + for (size_t FIdx = 0, NumForms = LU.Formulae.size(); + FIdx != NumForms; ++FIdx) { + Formula &F = LU.Formulae[FIdx]; + + SmallVector Key; + for (SmallVectorImpl::const_iterator J = F.BaseRegs.begin(), + JE = F.BaseRegs.end(); J != JE; ++J) { + const SCEV *Reg = *J; + if (RegUses.isRegUsedByUsesOtherThan(Reg, LUIdx)) + Key.push_back(Reg); + } + if (F.ScaledReg && + RegUses.isRegUsedByUsesOtherThan(F.ScaledReg, LUIdx)) + Key.push_back(F.ScaledReg); + // Unstable sort by host order ok, because this is only used for + // uniquifying. + std::sort(Key.begin(), Key.end()); + + std::pair P = + BestFormulae.insert(std::make_pair(Key, FIdx)); + if (!P.second) { + Formula &Best = LU.Formulae[P.first->second]; + if (Sorter.operator()(F, Best)) + std::swap(F, Best); + DEBUG(dbgs() << "Filtering out "; F.print(dbgs()); + dbgs() << "\n" + " in favor of "; Best.print(dbgs()); + dbgs() << '\n'); +#ifndef NDEBUG + Changed = true; +#endif + std::swap(F, LU.Formulae.back()); + LU.Formulae.pop_back(); + --FIdx; + --NumForms; + continue; + } + if (F.ScaledReg) LU.Regs.insert(F.ScaledReg); + LU.Regs.insert(F.BaseRegs.begin(), F.BaseRegs.end()); + } + BestFormulae.clear(); + } + + DEBUG(if (Changed) { + dbgs() << "\n" + "After filtering out undesirable candidates:\n"; + print_uses(dbgs()); + }); +} + +/// NarrowSearchSpaceUsingHeuristics - If there are an extraordinary number of +/// formulae to choose from, use some rough heuristics to prune down the number +/// of formulae. This keeps the main solver from taking an extraordinary amount +/// of time in some worst-case scenarios. +void LSRInstance::NarrowSearchSpaceUsingHeuristics() { + // This is a rough guess that seems to work fairly well. + const size_t Limit = UINT16_MAX; + + SmallPtrSet Taken; + for (;;) { + // Estimate the worst-case number of solutions we might consider. We almost + // never consider this many solutions because we prune the search space, + // but the pruning isn't always sufficient. + uint32_t Power = 1; + for (SmallVectorImpl::const_iterator I = Uses.begin(), + E = Uses.end(); I != E; ++I) { + size_t FSize = I->Formulae.size(); + if (FSize >= Limit) { + Power = Limit; + break; + } + Power *= FSize; + if (Power >= Limit) + break; + } + if (Power < Limit) + break; + + // Ok, we have too many of formulae on our hands to conveniently handle. + // Use a rough heuristic to thin out the list. + + // Pick the register which is used by the most LSRUses, which is likely + // to be a good reuse register candidate. + const SCEV *Best = 0; + unsigned BestNum = 0; + for (RegUseTracker::const_iterator I = RegUses.begin(), E = RegUses.end(); + I != E; ++I) { + const SCEV *Reg = *I; + if (Taken.count(Reg)) + continue; + if (!Best) + Best = Reg; + else { + unsigned Count = RegUses.getUsedByIndices(Reg).count(); + if (Count > BestNum) { + Best = Reg; + BestNum = Count; + } + } + } + + DEBUG(dbgs() << "Narrowing the search space by assuming " << *Best + << " will yield profitable reuse.\n"); + Taken.insert(Best); + + // In any use with formulae which references this register, delete formulae + // which don't reference it. + for (SmallVectorImpl::iterator I = Uses.begin(), + E = Uses.end(); I != E; ++I) { + LSRUse &LU = *I; + if (!LU.Regs.count(Best)) continue; + + // Clear out the set of used regs; it will be recomputed. + LU.Regs.clear(); + + for (size_t i = 0, e = LU.Formulae.size(); i != e; ++i) { + Formula &F = LU.Formulae[i]; + if (!F.referencesReg(Best)) { + DEBUG(dbgs() << " Deleting "; F.print(dbgs()); dbgs() << '\n'); + std::swap(LU.Formulae.back(), F); + LU.Formulae.pop_back(); + --e; + --i; + continue; + } + + if (F.ScaledReg) LU.Regs.insert(F.ScaledReg); + LU.Regs.insert(F.BaseRegs.begin(), F.BaseRegs.end()); + } + } + + DEBUG(dbgs() << "After pre-selection:\n"; + print_uses(dbgs())); + } +} + +/// SolveRecurse - This is the recursive solver. +void LSRInstance::SolveRecurse(SmallVectorImpl &Solution, + Cost &SolutionCost, + SmallVectorImpl &Workspace, + const Cost &CurCost, + const SmallPtrSet &CurRegs, + DenseSet &VisitedRegs) const { + // Some ideas: + // - prune more: + // - use more aggressive filtering + // - sort the formula so that the most profitable solutions are found first + // - sort the uses too + // - search faster: + // - don't compute a cost, and then compare. compare while computing a cost + // and bail early. + // - track register sets with SmallBitVector + + const LSRUse &LU = Uses[Workspace.size()]; + + // If this use references any register that's already a part of the + // in-progress solution, consider it a requirement that a formula must + // reference that register in order to be considered. This prunes out + // unprofitable searching. + SmallSetVector ReqRegs; + for (SmallPtrSet::const_iterator I = CurRegs.begin(), + E = CurRegs.end(); I != E; ++I) + if (LU.Regs.count(*I)) + ReqRegs.insert(*I); + + bool AnySatisfiedReqRegs = false; + SmallPtrSet NewRegs; + Cost NewCost; +retry: + for (SmallVectorImpl::const_iterator I = LU.Formulae.begin(), + E = LU.Formulae.end(); I != E; ++I) { + const Formula &F = *I; + + // Ignore formulae which do not use any of the required registers. + for (SmallSetVector::const_iterator J = ReqRegs.begin(), + JE = ReqRegs.end(); J != JE; ++J) { + const SCEV *Reg = *J; + if ((!F.ScaledReg || F.ScaledReg != Reg) && + std::find(F.BaseRegs.begin(), F.BaseRegs.end(), Reg) == + F.BaseRegs.end()) + goto skip; + } + AnySatisfiedReqRegs = true; + + // Evaluate the cost of the current formula. If it's already worse than + // the current best, prune the search at that point. + NewCost = CurCost; + NewRegs = CurRegs; + NewCost.RateFormula(F, NewRegs, VisitedRegs, L, LU.Offsets, SE, DT); + if (NewCost < SolutionCost) { + Workspace.push_back(&F); + if (Workspace.size() != Uses.size()) { + SolveRecurse(Solution, SolutionCost, Workspace, NewCost, + NewRegs, VisitedRegs); + if (F.getNumRegs() == 1 && Workspace.size() == 1) + VisitedRegs.insert(F.ScaledReg ? F.ScaledReg : F.BaseRegs[0]); + } else { + DEBUG(dbgs() << "New best at "; NewCost.print(dbgs()); + dbgs() << ". Regs:"; + for (SmallPtrSet::const_iterator + I = NewRegs.begin(), E = NewRegs.end(); I != E; ++I) + dbgs() << ' ' << **I; + dbgs() << '\n'); + + SolutionCost = NewCost; + Solution = Workspace; + } + Workspace.pop_back(); + } + skip:; + } + + // If none of the formulae had all of the required registers, relax the + // constraint so that we don't exclude all formulae. + if (!AnySatisfiedReqRegs) { + ReqRegs.clear(); + goto retry; + } +} + +void LSRInstance::Solve(SmallVectorImpl &Solution) const { + SmallVector Workspace; + Cost SolutionCost; + SolutionCost.Loose(); + Cost CurCost; + SmallPtrSet CurRegs; + DenseSet VisitedRegs; + Workspace.reserve(Uses.size()); + + SolveRecurse(Solution, SolutionCost, Workspace, CurCost, + CurRegs, VisitedRegs); + + // Ok, we've now made all our decisions. + DEBUG(dbgs() << "\n" + "The chosen solution requires "; SolutionCost.print(dbgs()); + dbgs() << ":\n"; + for (size_t i = 0, e = Uses.size(); i != e; ++i) { + dbgs() << " "; + Uses[i].print(dbgs()); + dbgs() << "\n" + " "; + Solution[i]->print(dbgs()); + dbgs() << '\n'; + }); +} + +/// getImmediateDominator - A handy utility for the specific DominatorTree +/// query that we need here. +/// +static BasicBlock *getImmediateDominator(BasicBlock *BB, DominatorTree &DT) { + DomTreeNode *Node = DT.getNode(BB); + if (!Node) return 0; + Node = Node->getIDom(); + if (!Node) return 0; + return Node->getBlock(); +} + +Value *LSRInstance::Expand(const LSRFixup &LF, + const Formula &F, + BasicBlock::iterator IP, + SCEVExpander &Rewriter, + SmallVectorImpl &DeadInsts) const { + const LSRUse &LU = Uses[LF.LUIdx]; + + // Then, collect some instructions which we will remain dominated by when + // expanding the replacement. These must be dominated by any operands that + // will be required in the expansion. + SmallVector Inputs; + if (Instruction *I = dyn_cast(LF.OperandValToReplace)) + Inputs.push_back(I); + if (LU.Kind == LSRUse::ICmpZero) + if (Instruction *I = + dyn_cast(cast(LF.UserInst)->getOperand(1))) + Inputs.push_back(I); + if (LF.PostIncLoop) { + if (!L->contains(LF.UserInst)) + Inputs.push_back(L->getLoopLatch()->getTerminator()); + else + Inputs.push_back(IVIncInsertPos); + } + + // Then, climb up the immediate dominator tree as far as we can go while + // still being dominated by the input positions. + for (;;) { + bool AllDominate = true; + Instruction *BetterPos = 0; + BasicBlock *IDom = getImmediateDominator(IP->getParent(), DT); + if (!IDom) break; + Instruction *Tentative = IDom->getTerminator(); + for (SmallVectorImpl::const_iterator I = Inputs.begin(), + E = Inputs.end(); I != E; ++I) { + Instruction *Inst = *I; + if (Inst == Tentative || !DT.dominates(Inst, Tentative)) { + AllDominate = false; + break; + } + if (IDom == Inst->getParent() && + (!BetterPos || DT.dominates(BetterPos, Inst))) + BetterPos = next(BasicBlock::iterator(Inst)); + } + if (!AllDominate) + break; + if (BetterPos) + IP = BetterPos; + else + IP = Tentative; + } + while (isa(IP)) ++IP; + + // Inform the Rewriter if we have a post-increment use, so that it can + // perform an advantageous expansion. + Rewriter.setPostInc(LF.PostIncLoop); + + // This is the type that the user actually needs. + const Type *OpTy = LF.OperandValToReplace->getType(); + // This will be the type that we'll initially expand to. + const Type *Ty = F.getType(); + if (!Ty) + // No type known; just expand directly to the ultimate type. + Ty = OpTy; + else if (SE.getEffectiveSCEVType(Ty) == SE.getEffectiveSCEVType(OpTy)) + // Expand directly to the ultimate type if it's the right size. + Ty = OpTy; + // This is the type to do integer arithmetic in. + const Type *IntTy = SE.getEffectiveSCEVType(Ty); + + // Build up a list of operands to add together to form the full base. + SmallVector Ops; + + // Expand the BaseRegs portion. + for (SmallVectorImpl::const_iterator I = F.BaseRegs.begin(), + E = F.BaseRegs.end(); I != E; ++I) { + const SCEV *Reg = *I; + assert(!Reg->isZero() && "Zero allocated in a base register!"); + + // If we're expanding for a post-inc user for the add-rec's loop, make the + // post-inc adjustment. + const SCEV *Start = Reg; + while (const SCEVAddRecExpr *AR = dyn_cast(Start)) { + if (AR->getLoop() == LF.PostIncLoop) { + Reg = SE.getAddExpr(Reg, AR->getStepRecurrence(SE)); + // If the user is inside the loop, insert the code after the increment + // so that it is dominated by its operand. If the original insert point + // was already dominated by the increment, keep it, because there may + // be loop-variant operands that need to be respected also. + if (L->contains(LF.UserInst) && !DT.dominates(IVIncInsertPos, IP)) + IP = IVIncInsertPos; + break; + } + Start = AR->getStart(); + } + + Ops.push_back(SE.getUnknown(Rewriter.expandCodeFor(Reg, 0, IP))); + } + + // Flush the operand list to suppress SCEVExpander hoisting. + if (!Ops.empty()) { + Value *FullV = Rewriter.expandCodeFor(SE.getAddExpr(Ops), Ty, IP); + Ops.clear(); + Ops.push_back(SE.getUnknown(FullV)); + } + + // Expand the ScaledReg portion. + Value *ICmpScaledV = 0; + if (F.AM.Scale != 0) { + const SCEV *ScaledS = F.ScaledReg; + + // If we're expanding for a post-inc user for the add-rec's loop, make the + // post-inc adjustment. + if (const SCEVAddRecExpr *AR = dyn_cast(ScaledS)) + if (AR->getLoop() == LF.PostIncLoop) + ScaledS = SE.getAddExpr(ScaledS, AR->getStepRecurrence(SE)); + + if (LU.Kind == LSRUse::ICmpZero) { + // An interesting way of "folding" with an icmp is to use a negated + // scale, which we'll implement by inserting it into the other operand + // of the icmp. + assert(F.AM.Scale == -1 && + "The only scale supported by ICmpZero uses is -1!"); + ICmpScaledV = Rewriter.expandCodeFor(ScaledS, 0, IP); + } else { + // Otherwise just expand the scaled register and an explicit scale, + // which is expected to be matched as part of the address. + ScaledS = SE.getUnknown(Rewriter.expandCodeFor(ScaledS, 0, IP)); + ScaledS = SE.getMulExpr(ScaledS, + SE.getIntegerSCEV(F.AM.Scale, + ScaledS->getType())); + Ops.push_back(ScaledS); + + // Flush the operand list to suppress SCEVExpander hoisting. + Value *FullV = Rewriter.expandCodeFor(SE.getAddExpr(Ops), Ty, IP); + Ops.clear(); + Ops.push_back(SE.getUnknown(FullV)); + } + } + + // Expand the GV portion. + if (F.AM.BaseGV) { + Ops.push_back(SE.getUnknown(F.AM.BaseGV)); + + // Flush the operand list to suppress SCEVExpander hoisting. + Value *FullV = Rewriter.expandCodeFor(SE.getAddExpr(Ops), Ty, IP); + Ops.clear(); + Ops.push_back(SE.getUnknown(FullV)); + } + + // Expand the immediate portion. + int64_t Offset = (uint64_t)F.AM.BaseOffs + LF.Offset; + if (Offset != 0) { + if (LU.Kind == LSRUse::ICmpZero) { + // The other interesting way of "folding" with an ICmpZero is to use a + // negated immediate. + if (!ICmpScaledV) + ICmpScaledV = ConstantInt::get(IntTy, -Offset); + else { + Ops.push_back(SE.getUnknown(ICmpScaledV)); + ICmpScaledV = ConstantInt::get(IntTy, Offset); + } + } else { + // Just add the immediate values. These again are expected to be matched + // as part of the address. + Ops.push_back(SE.getUnknown(ConstantInt::getSigned(IntTy, Offset))); + } + } + + // Emit instructions summing all the operands. + const SCEV *FullS = Ops.empty() ? + SE.getIntegerSCEV(0, IntTy) : + SE.getAddExpr(Ops); + Value *FullV = Rewriter.expandCodeFor(FullS, Ty, IP); + + // We're done expanding now, so reset the rewriter. + Rewriter.setPostInc(0); + + // An ICmpZero Formula represents an ICmp which we're handling as a + // comparison against zero. Now that we've expanded an expression for that + // form, update the ICmp's other operand. + if (LU.Kind == LSRUse::ICmpZero) { + ICmpInst *CI = cast(LF.UserInst); + DeadInsts.push_back(CI->getOperand(1)); + assert(!F.AM.BaseGV && "ICmp does not support folding a global value and " + "a scale at the same time!"); + if (F.AM.Scale == -1) { + if (ICmpScaledV->getType() != OpTy) { + Instruction *Cast = + CastInst::Create(CastInst::getCastOpcode(ICmpScaledV, false, + OpTy, false), + ICmpScaledV, OpTy, "tmp", CI); + ICmpScaledV = Cast; + } + CI->setOperand(1, ICmpScaledV); + } else { + assert(F.AM.Scale == 0 && + "ICmp does not support folding a global value and " + "a scale at the same time!"); + Constant *C = ConstantInt::getSigned(SE.getEffectiveSCEVType(OpTy), + -(uint64_t)Offset); + if (C->getType() != OpTy) + C = ConstantExpr::getCast(CastInst::getCastOpcode(C, false, + OpTy, false), + C, OpTy); + + CI->setOperand(1, C); + } + } + + return FullV; +} + +/// RewriteForPHI - Helper for Rewrite. PHI nodes are special because the use +/// of their operands effectively happens in their predecessor blocks, so the +/// expression may need to be expanded in multiple places. +void LSRInstance::RewriteForPHI(PHINode *PN, + const LSRFixup &LF, + const Formula &F, + SCEVExpander &Rewriter, + SmallVectorImpl &DeadInsts, + Pass *P) const { + DenseMap Inserted; + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingValue(i) == LF.OperandValToReplace) { + BasicBlock *BB = PN->getIncomingBlock(i); + + // If this is a critical edge, split the edge so that we do not insert + // the code on all predecessor/successor paths. We do this unless this + // is the canonical backedge for this loop, which complicates post-inc + // users. + if (e != 1 && BB->getTerminator()->getNumSuccessors() > 1 && + !isa(BB->getTerminator()) && + (PN->getParent() != L->getHeader() || !L->contains(BB))) { + // Split the critical edge. + BasicBlock *NewBB = SplitCriticalEdge(BB, PN->getParent(), P); + + // If PN is outside of the loop and BB is in the loop, we want to + // move the block to be immediately before the PHI block, not + // immediately after BB. + if (L->contains(BB) && !L->contains(PN)) + NewBB->moveBefore(PN->getParent()); + + // Splitting the edge can reduce the number of PHI entries we have. + e = PN->getNumIncomingValues(); + BB = NewBB; + i = PN->getBasicBlockIndex(BB); + } + + std::pair::iterator, bool> Pair = + Inserted.insert(std::make_pair(BB, static_cast(0))); + if (!Pair.second) + PN->setIncomingValue(i, Pair.first->second); + else { + Value *FullV = Expand(LF, F, BB->getTerminator(), Rewriter, DeadInsts); + + // If this is reuse-by-noop-cast, insert the noop cast. + const Type *OpTy = LF.OperandValToReplace->getType(); + if (FullV->getType() != OpTy) + FullV = + CastInst::Create(CastInst::getCastOpcode(FullV, false, + OpTy, false), + FullV, LF.OperandValToReplace->getType(), + "tmp", BB->getTerminator()); + + PN->setIncomingValue(i, FullV); + Pair.first->second = FullV; + } + } +} + +/// Rewrite - Emit instructions for the leading candidate expression for this +/// LSRUse (this is called "expanding"), and update the UserInst to reference +/// the newly expanded value. +void LSRInstance::Rewrite(const LSRFixup &LF, + const Formula &F, + SCEVExpander &Rewriter, + SmallVectorImpl &DeadInsts, + Pass *P) const { + // First, find an insertion point that dominates UserInst. For PHI nodes, + // find the nearest block which dominates all the relevant uses. + if (PHINode *PN = dyn_cast(LF.UserInst)) { + RewriteForPHI(PN, LF, F, Rewriter, DeadInsts, P); + } else { + Value *FullV = Expand(LF, F, LF.UserInst, Rewriter, DeadInsts); + + // If this is reuse-by-noop-cast, insert the noop cast. + const Type *OpTy = LF.OperandValToReplace->getType(); + if (FullV->getType() != OpTy) { + Instruction *Cast = + CastInst::Create(CastInst::getCastOpcode(FullV, false, OpTy, false), + FullV, OpTy, "tmp", LF.UserInst); + FullV = Cast; + } + + // Update the user. ICmpZero is handled specially here (for now) because + // Expand may have updated one of the operands of the icmp already, and + // its new value may happen to be equal to LF.OperandValToReplace, in + // which case doing replaceUsesOfWith leads to replacing both operands + // with the same value. TODO: Reorganize this. + if (Uses[LF.LUIdx].Kind == LSRUse::ICmpZero) + LF.UserInst->setOperand(0, FullV); + else + LF.UserInst->replaceUsesOfWith(LF.OperandValToReplace, FullV); + } + + DeadInsts.push_back(LF.OperandValToReplace); +} + +void +LSRInstance::ImplementSolution(const SmallVectorImpl &Solution, + Pass *P) { + // Keep track of instructions we may have made dead, so that + // we can remove them after we are done working. + SmallVector DeadInsts; + + SCEVExpander Rewriter(SE); + Rewriter.disableCanonicalMode(); + Rewriter.setIVIncInsertPos(L, IVIncInsertPos); + + // Expand the new value definitions and update the users. + for (size_t i = 0, e = Fixups.size(); i != e; ++i) { + size_t LUIdx = Fixups[i].LUIdx; + + Rewrite(Fixups[i], *Solution[LUIdx], Rewriter, DeadInsts, P); + + Changed = true; + } + + // Clean up after ourselves. This must be done before deleting any + // instructions. + Rewriter.clear(); + + Changed |= DeleteTriviallyDeadInstructions(DeadInsts); +} + +LSRInstance::LSRInstance(const TargetLowering *tli, Loop *l, Pass *P) + : IU(P->getAnalysis()), + SE(P->getAnalysis()), + DT(P->getAnalysis()), + TLI(tli), L(l), Changed(false), IVIncInsertPos(0) { + + // If LoopSimplify form is not available, stay out of trouble. + if (!L->isLoopSimplifyForm()) return; + + // If there's no interesting work to be done, bail early. + if (IU.empty()) return; + + DEBUG(dbgs() << "\nLSR on loop "; + WriteAsOperand(dbgs(), L->getHeader(), /*PrintType=*/false); + dbgs() << ":\n"); + + /// OptimizeShadowIV - If IV is used in a int-to-float cast + /// inside the loop then try to eliminate the cast operation. + OptimizeShadowIV(); + + // Change loop terminating condition to use the postinc iv when possible. + Changed |= OptimizeLoopTermCond(); + + CollectInterestingTypesAndFactors(); + CollectFixupsAndInitialFormulae(); + CollectLoopInvariantFixupsAndFormulae(); + + DEBUG(dbgs() << "LSR found " << Uses.size() << " uses:\n"; + print_uses(dbgs())); + + // Now use the reuse data to generate a bunch of interesting ways + // to formulate the values needed for the uses. + GenerateAllReuseFormulae(); + + DEBUG(dbgs() << "\n" + "After generating reuse formulae:\n"; + print_uses(dbgs())); + + FilterOutUndesirableDedicatedRegisters(); + NarrowSearchSpaceUsingHeuristics(); + + SmallVector Solution; + Solve(Solution); + assert(Solution.size() == Uses.size() && "Malformed solution!"); + + // Release memory that is no longer needed. + Factors.clear(); + Types.clear(); + RegUses.clear(); + +#ifndef NDEBUG + // Formulae should be legal. + for (SmallVectorImpl::const_iterator I = Uses.begin(), + E = Uses.end(); I != E; ++I) { + const LSRUse &LU = *I; + for (SmallVectorImpl::const_iterator J = LU.Formulae.begin(), + JE = LU.Formulae.end(); J != JE; ++J) + assert(isLegalUse(J->AM, LU.MinOffset, LU.MaxOffset, + LU.Kind, LU.AccessTy, TLI) && + "Illegal formula generated!"); + }; +#endif + + // Now that we've decided what we want, make it so. + ImplementSolution(Solution, P); +} + +void LSRInstance::print_factors_and_types(raw_ostream &OS) const { + if (Factors.empty() && Types.empty()) return; + + OS << "LSR has identified the following interesting factors and types: "; + bool First = true; + + for (SmallSetVector::const_iterator + I = Factors.begin(), E = Factors.end(); I != E; ++I) { + if (!First) OS << ", "; + First = false; + OS << '*' << *I; + } + + for (SmallSetVector::const_iterator + I = Types.begin(), E = Types.end(); I != E; ++I) { + if (!First) OS << ", "; + First = false; + OS << '(' << **I << ')'; + } + OS << '\n'; +} + +void LSRInstance::print_fixups(raw_ostream &OS) const { + OS << "LSR is examining the following fixup sites:\n"; + for (SmallVectorImpl::const_iterator I = Fixups.begin(), + E = Fixups.end(); I != E; ++I) { + const LSRFixup &LF = *I; + dbgs() << " "; + LF.print(OS); + OS << '\n'; + } +} + +void LSRInstance::print_uses(raw_ostream &OS) const { + OS << "LSR is examining the following uses:\n"; + for (SmallVectorImpl::const_iterator I = Uses.begin(), + E = Uses.end(); I != E; ++I) { + const LSRUse &LU = *I; + dbgs() << " "; + LU.print(OS); + OS << '\n'; + for (SmallVectorImpl::const_iterator J = LU.Formulae.begin(), + JE = LU.Formulae.end(); J != JE; ++J) { + OS << " "; + J->print(OS); + OS << '\n'; + } + } +} + +void LSRInstance::print(raw_ostream &OS) const { + print_factors_and_types(OS); + print_fixups(OS); + print_uses(OS); +} + +void LSRInstance::dump() const { + print(errs()); errs() << '\n'; +} + +namespace { + +class LoopStrengthReduce : public LoopPass { + /// TLI - Keep a pointer of a TargetLowering to consult for determining + /// transformation profitability. + const TargetLowering *const TLI; + +public: + static char ID; // Pass ID, replacement for typeid + explicit LoopStrengthReduce(const TargetLowering *tli = 0); + +private: + bool runOnLoop(Loop *L, LPPassManager &LPM); + void getAnalysisUsage(AnalysisUsage &AU) const; +}; + +} + +char LoopStrengthReduce::ID = 0; +static RegisterPass +X("loop-reduce", "Loop Strength Reduction"); + +Pass *llvm::createLoopStrengthReducePass(const TargetLowering *TLI) { + return new LoopStrengthReduce(TLI); +} + +LoopStrengthReduce::LoopStrengthReduce(const TargetLowering *tli) + : LoopPass(&ID), TLI(tli) {} + +void LoopStrengthReduce::getAnalysisUsage(AnalysisUsage &AU) const { + // We split critical edges, so we change the CFG. However, we do update + // many analyses if they are around. + AU.addPreservedID(LoopSimplifyID); + AU.addPreserved(); + AU.addPreserved("domfrontier"); + + AU.addRequiredID(LoopSimplifyID); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); +} + +bool LoopStrengthReduce::runOnLoop(Loop *L, LPPassManager & /*LPM*/) { + bool Changed = false; + + // Run the main LSR transformation. + Changed |= LSRInstance(TLI, L, this).getChanged(); // At this point, it is worth checking to see if any recurrence PHIs are also // dead, so that we can remove them as well. diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp index e5fba28374..071e9b7c9e 100644 --- a/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -170,7 +170,7 @@ Pass *llvm::createLoopUnswitchPass(bool Os) { /// Otherwise, return null. static Value *FindLIVLoopCondition(Value *Cond, Loop *L, bool &Changed) { // We can never unswitch on vector conditions. - if (isa(Cond->getType())) + if (Cond->getType()->isVectorTy()) return 0; // Constants should be folded, not unswitched on! @@ -871,7 +871,7 @@ void LoopUnswitch::RewriteLoopBodyWithConditionConstant(Loop *L, Value *LIC, // If we know that LIC == Val, or that LIC == NotVal, just replace uses of LIC // in the loop with the appropriate one directly. if (IsEqual || (isa(Val) && - Val->getType()->isInteger(1))) { + Val->getType()->isIntegerTy(1))) { Value *Replacement; if (IsEqual) Replacement = Val; @@ -997,10 +997,10 @@ void LoopUnswitch::SimplifyCode(std::vector &Worklist, Loop *L) { case Instruction::And: if (isa(I->getOperand(0)) && // constant -> RHS - I->getOperand(0)->getType()->isInteger(1)) + I->getOperand(0)->getType()->isIntegerTy(1)) cast(I)->swapOperands(); if (ConstantInt *CB = dyn_cast(I->getOperand(1))) - if (CB->getType()->isInteger(1)) { + if (CB->getType()->isIntegerTy(1)) { if (CB->isOne()) // X & 1 -> X ReplaceUsesOfWith(I, I->getOperand(0), Worklist, L, LPM); else // X & 0 -> 0 @@ -1011,10 +1011,10 @@ void LoopUnswitch::SimplifyCode(std::vector &Worklist, Loop *L) { case Instruction::Or: if (isa(I->getOperand(0)) && // constant -> RHS - I->getOperand(0)->getType()->isInteger(1)) + I->getOperand(0)->getType()->isIntegerTy(1)) cast(I)->swapOperands(); if (ConstantInt *CB = dyn_cast(I->getOperand(1))) - if (CB->getType()->isInteger(1)) { + if (CB->getType()->isIntegerTy(1)) { if (CB->isOne()) // X | 1 -> 1 ReplaceUsesOfWith(I, I->getOperand(1), Worklist, L, LPM); else // X | 0 -> X diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp index e0aa49154f..62e2977058 100644 --- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -42,7 +42,7 @@ static Value *isBytewiseValue(Value *V) { LLVMContext &Context = V->getContext(); // All byte-wide stores are splatable, even of arbitrary variables. - if (V->getType()->isInteger(8)) return V; + if (V->getType()->isIntegerTy(8)) return V; // Constant float and double values can be handled as integer values if the // corresponding integer value is "byteable". An important case is 0.0. diff --git a/lib/Transforms/Scalar/Reassociate.cpp b/lib/Transforms/Scalar/Reassociate.cpp index bbd4b451fb..5aca9cdc65 100644 --- a/lib/Transforms/Scalar/Reassociate.cpp +++ b/lib/Transforms/Scalar/Reassociate.cpp @@ -182,7 +182,7 @@ unsigned Reassociate::getRank(Value *V) { // If this is a not or neg instruction, do not count it for rank. This // assures us that X and ~X will have the same rank. - if (!I->getType()->isInteger() || + if (!I->getType()->isIntegerTy() || (!BinaryOperator::isNot(I) && !BinaryOperator::isNeg(I))) ++Rank; @@ -597,19 +597,35 @@ Value *Reassociate::RemoveFactorFromExpression(Value *V, Value *Factor) { /// FindSingleUseMultiplyFactors - If V is a single-use multiply, recursively /// add its operands as factors, otherwise add V to the list of factors. +/// +/// Ops is the top-level list of add operands we're trying to factor. static void FindSingleUseMultiplyFactors(Value *V, - SmallVectorImpl &Factors) { + SmallVectorImpl &Factors, + const SmallVectorImpl &Ops, + bool IsRoot) { BinaryOperator *BO; - if ((!V->hasOneUse() && !V->use_empty()) || + if (!(V->hasOneUse() || V->use_empty()) || // More than one use. !(BO = dyn_cast(V)) || BO->getOpcode() != Instruction::Mul) { Factors.push_back(V); return; } + // If this value has a single use because it is another input to the add + // tree we're reassociating and we dropped its use, it actually has two + // uses and we can't factor it. + if (!IsRoot) { + for (unsigned i = 0, e = Ops.size(); i != e; ++i) + if (Ops[i].Op == V) { + Factors.push_back(V); + return; + } + } + + // Otherwise, add the LHS and RHS to the list of factors. - FindSingleUseMultiplyFactors(BO->getOperand(1), Factors); - FindSingleUseMultiplyFactors(BO->getOperand(0), Factors); + FindSingleUseMultiplyFactors(BO->getOperand(1), Factors, Ops, false); + FindSingleUseMultiplyFactors(BO->getOperand(0), Factors, Ops, false); } /// OptimizeAndOrXor - Optimize a series of operands to an 'and', 'or', or 'xor' @@ -753,7 +769,7 @@ Value *Reassociate::OptimizeAdd(Instruction *I, // Compute all of the factors of this added value. SmallVector Factors; - FindSingleUseMultiplyFactors(BOp, Factors); + FindSingleUseMultiplyFactors(BOp, Factors, Ops, true); assert(Factors.size() > 1 && "Bad linearize!"); // Add one to FactorOccurrences for each unique factor in this op. @@ -929,8 +945,8 @@ void Reassociate::ReassociateBB(BasicBlock *BB) { } // Reject cases where it is pointless to do this. - if (!isa(BI) || BI->getType()->isFloatingPoint() || - isa(BI->getType())) + if (!isa(BI) || BI->getType()->isFloatingPointTy() || + BI->getType()->isVectorTy()) continue; // Floating point ops are not associative. // Do not reassociate boolean (i1) expressions. We want to preserve the @@ -939,7 +955,7 @@ void Reassociate::ReassociateBB(BasicBlock *BB) { // is not further optimized, it is likely to be transformed back to a // short-circuited form for code gen, and the source order may have been // optimized for the most likely conditions. - if (BI->getType()->isInteger(1)) + if (BI->getType()->isIntegerTy(1)) continue; // If this is a subtract instruction which is not already in negate form, diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index 02b45a1483..7e37938868 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -295,7 +295,7 @@ public: } void markOverdefined(Value *V) { - assert(!isa(V->getType()) && "Should use other method"); + assert(!V->getType()->isStructTy() && "Should use other method"); markOverdefined(ValueState[V], V); } @@ -321,12 +321,12 @@ private: } void markConstant(Value *V, Constant *C) { - assert(!isa(V->getType()) && "Should use other method"); + assert(!V->getType()->isStructTy() && "Should use other method"); markConstant(ValueState[V], V, C); } void markForcedConstant(Value *V, Constant *C) { - assert(!isa(V->getType()) && "Should use other method"); + assert(!V->getType()->isStructTy() && "Should use other method"); ValueState[V].markForcedConstant(C); DEBUG(dbgs() << "markForcedConstant: " << *C << ": " << *V << '\n'); InstWorkList.push_back(V); @@ -360,7 +360,7 @@ private: } void mergeInValue(Value *V, LatticeVal MergeWithV) { - assert(!isa(V->getType()) && "Should use other method"); + assert(!V->getType()->isStructTy() && "Should use other method"); mergeInValue(ValueState[V], V, MergeWithV); } @@ -369,7 +369,7 @@ private: /// value. This function handles the case when the value hasn't been seen yet /// by properly seeding constants etc. LatticeVal &getValueState(Value *V) { - assert(!isa(V->getType()) && "Should use getStructValueState"); + assert(!V->getType()->isStructTy() && "Should use getStructValueState"); std::pair::iterator, bool> I = ValueState.insert(std::make_pair(V, LatticeVal())); @@ -392,7 +392,7 @@ private: /// value/field pair. This function handles the case when the value hasn't /// been seen yet by properly seeding constants etc. LatticeVal &getStructValueState(Value *V, unsigned i) { - assert(isa(V->getType()) && "Should use getValueState"); + assert(V->getType()->isStructTy() && "Should use getValueState"); assert(i < cast(V->getType())->getNumElements() && "Invalid element #"); @@ -666,7 +666,7 @@ bool SCCPSolver::isEdgeFeasible(BasicBlock *From, BasicBlock *To) { void SCCPSolver::visitPHINode(PHINode &PN) { // If this PN returns a struct, just mark the result overdefined. // TODO: We could do a lot better than this if code actually uses this. - if (isa(PN.getType())) + if (PN.getType()->isStructTy()) return markAnythingOverdefined(&PN); if (getValueState(&PN).isOverdefined()) { @@ -742,7 +742,7 @@ void SCCPSolver::visitReturnInst(ReturnInst &I) { Value *ResultOp = I.getOperand(0); // If we are tracking the return value of this function, merge it in. - if (!TrackedRetVals.empty() && !isa(ResultOp->getType())) { + if (!TrackedRetVals.empty() && !ResultOp->getType()->isStructTy()) { DenseMap::iterator TFRVI = TrackedRetVals.find(F); if (TFRVI != TrackedRetVals.end()) { @@ -787,7 +787,7 @@ void SCCPSolver::visitCastInst(CastInst &I) { void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) { // If this returns a struct, mark all elements over defined, we don't track // structs in structs. - if (isa(EVI.getType())) + if (EVI.getType()->isStructTy()) return markAnythingOverdefined(&EVI); // If this is extracting from more than one level of struct, we don't know. @@ -795,7 +795,7 @@ void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) { return markOverdefined(&EVI); Value *AggVal = EVI.getAggregateOperand(); - if (isa(AggVal->getType())) { + if (AggVal->getType()->isStructTy()) { unsigned i = *EVI.idx_begin(); LatticeVal EltVal = getStructValueState(AggVal, i); mergeInValue(getValueState(&EVI), &EVI, EltVal); @@ -828,7 +828,7 @@ void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) { } Value *Val = IVI.getInsertedValueOperand(); - if (isa(Val->getType())) + if (Val->getType()->isStructTy()) // We don't track structs in structs. markOverdefined(getStructValueState(&IVI, i), &IVI); else { @@ -841,7 +841,7 @@ void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) { void SCCPSolver::visitSelectInst(SelectInst &I) { // If this select returns a struct, just mark the result overdefined. // TODO: We could do a lot better than this if code actually uses this. - if (isa(I.getType())) + if (I.getType()->isStructTy()) return markAnythingOverdefined(&I); LatticeVal CondValue = getValueState(I.getCondition()); @@ -1166,7 +1166,7 @@ void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) { void SCCPSolver::visitStoreInst(StoreInst &SI) { // If this store is of a struct, ignore it. - if (isa(SI.getOperand(0)->getType())) + if (SI.getOperand(0)->getType()->isStructTy()) return; if (TrackedGlobals.empty() || !isa(SI.getOperand(1))) @@ -1187,7 +1187,7 @@ void SCCPSolver::visitStoreInst(StoreInst &SI) { // global, we can replace the load with the loaded constant value! void SCCPSolver::visitLoadInst(LoadInst &I) { // If this load is of a struct, just mark the result overdefined. - if (isa(I.getType())) + if (I.getType()->isStructTy()) return markAnythingOverdefined(&I); LatticeVal PtrVal = getValueState(I.getOperand(0)); @@ -1241,7 +1241,7 @@ CallOverdefined: // Otherwise, if we have a single return value case, and if the function is // a declaration, maybe we can constant fold it. - if (F && F->isDeclaration() && !isa(I->getType()) && + if (F && F->isDeclaration() && !I->getType()->isStructTy() && canConstantFoldCallTo(F)) { SmallVector Operands; @@ -1352,7 +1352,7 @@ void SCCPSolver::Solve() { // since all of its users will have already been marked as overdefined. // Update all of the users of this instruction's value. // - if (isa(I->getType()) || !getValueState(I).isOverdefined()) + if (I->getType()->isStructTy() || !getValueState(I).isOverdefined()) for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ++UI) if (Instruction *I = dyn_cast(*UI)) @@ -1418,7 +1418,7 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) { if (!LV.isUndefined()) continue; // No instructions using structs need disambiguation. - if (isa(I->getOperand(0)->getType())) + if (I->getOperand(0)->getType()->isStructTy()) continue; // Get the lattice values of the first two operands for use below. @@ -1426,7 +1426,7 @@ bool SCCPSolver::ResolvedUndefsIn(Function &F) { LatticeVal Op1LV; if (I->getNumOperands() == 2) { // No instructions using structs need disambiguation. - if (isa(I->getOperand(1)->getType())) + if (I->getOperand(1)->getType()->isStructTy()) continue; // If this is a two-operand instruction, and if both operands are @@ -1656,7 +1656,7 @@ bool SCCP::runOnFunction(Function &F) { continue; // TODO: Reconstruct structs from their elements. - if (isa(Inst->getType())) + if (Inst->getType()->isStructTy()) continue; LatticeVal IV = Solver.getLatticeValueFor(Inst); @@ -1792,7 +1792,7 @@ bool IPSCCP::runOnModule(Module &M) { if (Solver.isBlockExecutable(F->begin())) { for (Function::arg_iterator AI = F->arg_begin(), E = F->arg_end(); AI != E; ++AI) { - if (AI->use_empty() || isa(AI->getType())) continue; + if (AI->use_empty() || AI->getType()->isStructTy()) continue; // TODO: Could use getStructLatticeValueFor to find out if the entire // result is a constant and replace it entirely if so. @@ -1835,7 +1835,7 @@ bool IPSCCP::runOnModule(Module &M) { for (BasicBlock::iterator BI = BB->begin(), E = BB->end(); BI != E; ) { Instruction *Inst = BI++; - if (Inst->getType()->isVoidTy() || isa(Inst->getType())) + if (Inst->getType()->isVoidTy() || Inst->getType()->isStructTy()) continue; // TODO: Could use getStructLatticeValueFor to find out if the entire @@ -1918,6 +1918,14 @@ bool IPSCCP::runOnModule(Module &M) { // all call uses with the inferred value. This means we don't need to bother // actually returning anything from the function. Replace all return // instructions with return undef. + // + // Do this in two stages: first identify the functions we should process, then + // actually zap their returns. This is important because we can only do this + // if the address of the function isn't taken. In cases where a return is the + // last use of a function, the order of processing functions would affect + // whether other functions are optimizable. + SmallVector ReturnsToZap; + // TODO: Process multiple value ret instructions also. const DenseMap &RV = Solver.getTrackedRetVals(); for (DenseMap::const_iterator I = RV.begin(), @@ -1933,7 +1941,13 @@ bool IPSCCP::runOnModule(Module &M) { for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) if (!isa(RI->getOperand(0))) - RI->setOperand(0, UndefValue::get(F->getReturnType())); + ReturnsToZap.push_back(RI); + } + + // Zap all returns which we've identified as zap to change. + for (unsigned i = 0, e = ReturnsToZap.size(); i != e; ++i) { + Function *F = ReturnsToZap[i]->getParent()->getParent(); + ReturnsToZap[i]->setOperand(0, UndefValue::get(F->getReturnType())); } // If we infered constant or undef values for globals variables, we can delete diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index 900d119cb4..bbe6270655 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -302,7 +302,7 @@ bool SROA::performScalarRepl(Function &F) { // random stuff that doesn't use vectors (e.g. <9 x double>) because then // we just get a lot of insert/extracts. If at least one vector is // involved, then we probably really do have a union of vector/array. - if (VectorTy && isa(VectorTy) && HadAVector) { + if (VectorTy && VectorTy->isVectorTy() && HadAVector) { DEBUG(dbgs() << "CONVERT TO VECTOR: " << *AI << "\n TYPE = " << *VectorTy << '\n'); @@ -449,7 +449,7 @@ void SROA::isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, // into. for (; GEPIt != E; ++GEPIt) { // Ignore struct elements, no extra checking needed for these. - if (isa(*GEPIt)) + if ((*GEPIt)->isStructTy()) continue; ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand()); @@ -480,7 +480,7 @@ void SROA::isSafeMemAccess(AllocaInst *AI, uint64_t Offset, uint64_t MemSize, // (which are essentially the same as the MemIntrinsics, especially with // regard to copying padding between elements), or references using the // aggregate type of the alloca. - if (!MemOpType || isa(MemOpType) || UsesAggregateType) { + if (!MemOpType || MemOpType->isIntegerTy() || UsesAggregateType) { if (!UsesAggregateType) { if (isStore) Info.isMemCpyDst = true; @@ -565,7 +565,7 @@ void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, } LI->replaceAllUsesWith(Insert); DeadInsts.push_back(LI); - } else if (isa(LIType) && + } else if (LIType->isIntegerTy() && TD->getTypeAllocSize(LIType) == TD->getTypeAllocSize(AI->getAllocatedType())) { // If this is a load of the entire alloca to an integer, rewrite it. @@ -588,7 +588,7 @@ void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset, new StoreInst(Extract, NewElts[i], SI); } DeadInsts.push_back(SI); - } else if (isa(SIType) && + } else if (SIType->isIntegerTy() && TD->getTypeAllocSize(SIType) == TD->getTypeAllocSize(AI->getAllocatedType())) { // If this is a store of the entire alloca from an integer, rewrite it. @@ -833,9 +833,9 @@ void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst, // Convert the integer value to the appropriate type. StoreVal = ConstantInt::get(Context, TotalVal); - if (isa(ValTy)) + if (ValTy->isPointerTy()) StoreVal = ConstantExpr::getIntToPtr(StoreVal, ValTy); - else if (ValTy->isFloatingPoint()) + else if (ValTy->isFloatingPointTy()) StoreVal = ConstantExpr::getBitCast(StoreVal, ValTy); assert(StoreVal->getType() == ValTy && "Type mismatch!"); @@ -939,7 +939,7 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, Value *DestField = NewElts[i]; if (EltVal->getType() == FieldTy) { // Storing to an integer field of this size, just do it. - } else if (FieldTy->isFloatingPoint() || isa(FieldTy)) { + } else if (FieldTy->isFloatingPointTy() || FieldTy->isVectorTy()) { // Bitcast to the right element type (for fp/vector values). EltVal = new BitCastInst(EltVal, FieldTy, "", SI); } else { @@ -983,7 +983,8 @@ void SROA::RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI, Value *DestField = NewElts[i]; if (EltVal->getType() == ArrayEltTy) { // Storing to an integer field of this size, just do it. - } else if (ArrayEltTy->isFloatingPoint() || isa(ArrayEltTy)) { + } else if (ArrayEltTy->isFloatingPointTy() || + ArrayEltTy->isVectorTy()) { // Bitcast to the right element type (for fp/vector values). EltVal = new BitCastInst(EltVal, ArrayEltTy, "", SI); } else { @@ -1043,8 +1044,8 @@ void SROA::RewriteLoadUserOfWholeAlloca(LoadInst *LI, AllocaInst *AI, const IntegerType *FieldIntTy = IntegerType::get(LI->getContext(), FieldSizeBits); - if (!isa(FieldTy) && !FieldTy->isFloatingPoint() && - !isa(FieldTy)) + if (!FieldTy->isIntegerTy() && !FieldTy->isFloatingPointTy() && + !FieldTy->isVectorTy()) SrcField = new BitCastInst(SrcField, PointerType::getUnqual(FieldIntTy), "", LI); @@ -1182,7 +1183,7 @@ static void MergeInType(const Type *In, uint64_t Offset, const Type *&VecTy, return; } } else if (In->isFloatTy() || In->isDoubleTy() || - (isa(In) && In->getPrimitiveSizeInBits() >= 8 && + (In->isIntegerTy() && In->getPrimitiveSizeInBits() >= 8 && isPowerOf2_32(In->getPrimitiveSizeInBits()))) { // If we're accessing something that could be an element of a vector, see // if the implied vector agrees with what we already have and if Offset is @@ -1226,7 +1227,7 @@ bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy, return false; MergeInType(LI->getType(), Offset, VecTy, AllocaSize, *TD, V->getContext()); - SawVec |= isa(LI->getType()); + SawVec |= LI->getType()->isVectorTy(); continue; } @@ -1235,7 +1236,7 @@ bool SROA::CanConvertToScalar(Value *V, bool &IsNotTrivial, const Type *&VecTy, if (SI->getOperand(0) == V || SI->isVolatile()) return 0; MergeInType(SI->getOperand(0)->getType(), Offset, VecTy, AllocaSize, *TD, V->getContext()); - SawVec |= isa(SI->getOperand(0)->getType()); + SawVec |= SI->getOperand(0)->getType()->isVectorTy(); continue; } @@ -1437,7 +1438,7 @@ Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, // If the result alloca is a vector type, this is either an element // access or a bitcast to another vector type of the same size. if (const VectorType *VTy = dyn_cast(FromVal->getType())) { - if (isa(ToType)) + if (ToType->isVectorTy()) return Builder.CreateBitCast(FromVal, ToType, "tmp"); // Otherwise it must be an element access. @@ -1520,9 +1521,9 @@ Value *SROA::ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, LIBitWidth), "tmp"); // If the result is an integer, this is a trunc or bitcast. - if (isa(ToType)) { + if (ToType->isIntegerTy()) { // Should be done. - } else if (ToType->isFloatingPoint() || isa(ToType)) { + } else if (ToType->isFloatingPointTy() || ToType->isVectorTy()) { // Just do a bitcast, we know the sizes match up. FromVal = Builder.CreateBitCast(FromVal, ToType, "tmp"); } else { @@ -1600,10 +1601,10 @@ Value *SROA::ConvertScalar_InsertValue(Value *SV, Value *Old, unsigned DestWidth = TD->getTypeSizeInBits(AllocaType); unsigned SrcStoreWidth = TD->getTypeStoreSizeInBits(SV->getType()); unsigned DestStoreWidth = TD->getTypeStoreSizeInBits(AllocaType); - if (SV->getType()->isFloatingPoint() || isa(SV->getType())) + if (SV->getType()->isFloatingPointTy() || SV->getType()->isVectorTy()) SV = Builder.CreateBitCast(SV, IntegerType::get(SV->getContext(),SrcWidth), "tmp"); - else if (isa(SV->getType())) + else if (SV->getType()->isPointerTy()) SV = Builder.CreatePtrToInt(SV, TD->getIntPtrType(SV->getContext()), "tmp"); // Zero extend or truncate the value if needed. diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 4216e8f995..05027ae528 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -17,6 +17,7 @@ #define DEBUG_TYPE "simplify-libcalls" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/BuildLibCalls.h" #include "llvm/Intrinsics.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" @@ -67,496 +68,14 @@ public: Context = &CI->getCalledFunction()->getContext(); return CallOptimizer(CI->getCalledFunction(), CI, B); } - - /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. - Value *CastToCStr(Value *V, IRBuilder<> &B); - - /// EmitStrLen - Emit a call to the strlen function to the builder, for the - /// specified pointer. Ptr is required to be some pointer type, and the - /// return value has 'intptr_t' type. - Value *EmitStrLen(Value *Ptr, IRBuilder<> &B); - - /// EmitStrChr - Emit a call to the strchr function to the builder, for the - /// specified pointer and character. Ptr is required to be some pointer type, - /// and the return value has 'i8*' type. - Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B); - - /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the - /// specified pointer arguments. - Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B); - - /// EmitMemCpy - Emit a call to the memcpy function to the builder. This - /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, - unsigned Align, IRBuilder<> &B); - - /// EmitMemMove - Emit a call to the memmove function to the builder. This - /// always expects that the size has type 'intptr_t' and Dst/Src are pointers. - Value *EmitMemMove(Value *Dst, Value *Src, Value *Len, - unsigned Align, IRBuilder<> &B); - - /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is - /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. - Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B); - - /// EmitMemCmp - Emit a call to the memcmp function. - Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B); - - /// EmitMemSet - Emit a call to the memset function - Value *EmitMemSet(Value *Dst, Value *Val, Value *Len, IRBuilder<> &B); - - /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' - /// (e.g. 'floor'). This function is known to take a single of type matching - /// 'Op' and returns one value with the same type. If 'Op' is a long double, - /// 'l' is added as the suffix of name, if 'Op' is a float, we add a 'f' - /// suffix. - Value *EmitUnaryFloatFnCall(Value *Op, const char *Name, IRBuilder<> &B, - const AttrListPtr &Attrs); - - /// EmitPutChar - Emit a call to the putchar function. This assumes that Char - /// is an integer. - Value *EmitPutChar(Value *Char, IRBuilder<> &B); - - /// EmitPutS - Emit a call to the puts function. This assumes that Str is - /// some pointer. - void EmitPutS(Value *Str, IRBuilder<> &B); - - /// EmitFPutC - Emit a call to the fputc function. This assumes that Char is - /// an i32, and File is a pointer to FILE. - void EmitFPutC(Value *Char, Value *File, IRBuilder<> &B); - - /// EmitFPutS - Emit a call to the puts function. Str is required to be a - /// pointer and File is a pointer to FILE. - void EmitFPutS(Value *Str, Value *File, IRBuilder<> &B); - - /// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is - /// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. - void EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B); - }; } // End anonymous namespace. -/// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. -Value *LibCallOptimization::CastToCStr(Value *V, IRBuilder<> &B) { - return B.CreateBitCast(V, Type::getInt8PtrTy(*Context), "cstr"); -} - -/// EmitStrLen - Emit a call to the strlen function to the builder, for the -/// specified pointer. This always returns an integer value of size intptr_t. -Value *LibCallOptimization::EmitStrLen(Value *Ptr, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI[2]; - AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); - AWI[1] = AttributeWithIndex::get(~0u, Attribute::ReadOnly | - Attribute::NoUnwind); - - Constant *StrLen =M->getOrInsertFunction("strlen", AttrListPtr::get(AWI, 2), - TD->getIntPtrType(*Context), - Type::getInt8PtrTy(*Context), - NULL); - CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen"); - if (const Function *F = dyn_cast(StrLen->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - - return CI; -} - -/// EmitStrChr - Emit a call to the strchr function to the builder, for the -/// specified pointer and character. Ptr is required to be some pointer type, -/// and the return value has 'i8*' type. -Value *LibCallOptimization::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI = - AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); - - const Type *I8Ptr = Type::getInt8PtrTy(*Context); - const Type *I32Ty = Type::getInt32Ty(*Context); - Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(&AWI, 1), - I8Ptr, I8Ptr, I32Ty, NULL); - CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B), - ConstantInt::get(I32Ty, C), "strchr"); - if (const Function *F = dyn_cast(StrChr->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - return CI; -} - -/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the -/// specified pointer arguments. -Value *LibCallOptimization::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI[2]; - AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture); - AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); - const Type *I8Ptr = Type::getInt8PtrTy(*Context); - Value *StrCpy = M->getOrInsertFunction("strcpy", AttrListPtr::get(AWI, 2), - I8Ptr, I8Ptr, I8Ptr, NULL); - CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B), - "strcpy"); - if (const Function *F = dyn_cast(StrCpy->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - return CI; -} - -/// EmitMemCpy - Emit a call to the memcpy function to the builder. This always -/// expects that the size has type 'intptr_t' and Dst/Src are pointers. -Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len, - unsigned Align, IRBuilder<> &B) { - Module *M = Caller->getParent(); - const Type *Ty = Len->getType(); - Value *MemCpy = Intrinsic::getDeclaration(M, Intrinsic::memcpy, &Ty, 1); - Dst = CastToCStr(Dst, B); - Src = CastToCStr(Src, B); - return B.CreateCall4(MemCpy, Dst, Src, Len, - ConstantInt::get(Type::getInt32Ty(*Context), Align)); -} - -/// EmitMemMove - Emit a call to the memmove function to the builder. This -/// always expects that the size has type 'intptr_t' and Dst/Src are pointers. -Value *LibCallOptimization::EmitMemMove(Value *Dst, Value *Src, Value *Len, - unsigned Align, IRBuilder<> &B) { - Module *M = Caller->getParent(); - const Type *Ty = TD->getIntPtrType(*Context); - Value *MemMove = Intrinsic::getDeclaration(M, Intrinsic::memmove, &Ty, 1); - Dst = CastToCStr(Dst, B); - Src = CastToCStr(Src, B); - Value *A = ConstantInt::get(Type::getInt32Ty(*Context), Align); - return B.CreateCall4(MemMove, Dst, Src, Len, A); -} - -/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is -/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. -Value *LibCallOptimization::EmitMemChr(Value *Ptr, Value *Val, - Value *Len, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI; - AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); - - Value *MemChr = M->getOrInsertFunction("memchr", AttrListPtr::get(&AWI, 1), - Type::getInt8PtrTy(*Context), - Type::getInt8PtrTy(*Context), - Type::getInt32Ty(*Context), - TD->getIntPtrType(*Context), - NULL); - CallInst *CI = B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr"); - - if (const Function *F = dyn_cast(MemChr->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - - return CI; -} - -/// EmitMemCmp - Emit a call to the memcmp function. -Value *LibCallOptimization::EmitMemCmp(Value *Ptr1, Value *Ptr2, - Value *Len, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI[3]; - AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); - AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture); - AWI[2] = AttributeWithIndex::get(~0u, Attribute::ReadOnly | - Attribute::NoUnwind); - - Value *MemCmp = M->getOrInsertFunction("memcmp", AttrListPtr::get(AWI, 3), - Type::getInt32Ty(*Context), - Type::getInt8PtrTy(*Context), - Type::getInt8PtrTy(*Context), - TD->getIntPtrType(*Context), NULL); - CallInst *CI = B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B), - Len, "memcmp"); - - if (const Function *F = dyn_cast(MemCmp->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - - return CI; -} - -/// EmitMemSet - Emit a call to the memset function -Value *LibCallOptimization::EmitMemSet(Value *Dst, Value *Val, - Value *Len, IRBuilder<> &B) { - Module *M = Caller->getParent(); - Intrinsic::ID IID = Intrinsic::memset; - const Type *Tys[1]; - Tys[0] = Len->getType(); - Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 1); - Value *Align = ConstantInt::get(Type::getInt32Ty(*Context), 1); - return B.CreateCall4(MemSet, CastToCStr(Dst, B), Val, Len, Align); -} - -/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g. -/// 'floor'). This function is known to take a single of type matching 'Op' and -/// returns one value with the same type. If 'Op' is a long double, 'l' is -/// added as the suffix of name, if 'Op' is a float, we add a 'f' suffix. -Value *LibCallOptimization::EmitUnaryFloatFnCall(Value *Op, const char *Name, - IRBuilder<> &B, - const AttrListPtr &Attrs) { - char NameBuffer[20]; - if (!Op->getType()->isDoubleTy()) { - // If we need to add a suffix, copy into NameBuffer. - unsigned NameLen = strlen(Name); - assert(NameLen < sizeof(NameBuffer)-2); - memcpy(NameBuffer, Name, NameLen); - if (Op->getType()->isFloatTy()) - NameBuffer[NameLen] = 'f'; // floorf - else - NameBuffer[NameLen] = 'l'; // floorl - NameBuffer[NameLen+1] = 0; - Name = NameBuffer; - } - - Module *M = Caller->getParent(); - Value *Callee = M->getOrInsertFunction(Name, Op->getType(), - Op->getType(), NULL); - CallInst *CI = B.CreateCall(Callee, Op, Name); - CI->setAttributes(Attrs); - if (const Function *F = dyn_cast(Callee->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - - return CI; -} - -/// EmitPutChar - Emit a call to the putchar function. This assumes that Char -/// is an integer. -Value *LibCallOptimization::EmitPutChar(Value *Char, IRBuilder<> &B) { - Module *M = Caller->getParent(); - Value *PutChar = M->getOrInsertFunction("putchar", Type::getInt32Ty(*Context), - Type::getInt32Ty(*Context), NULL); - CallInst *CI = B.CreateCall(PutChar, - B.CreateIntCast(Char, - Type::getInt32Ty(*Context), - /*isSigned*/true, - "chari"), - "putchar"); - - if (const Function *F = dyn_cast(PutChar->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - return CI; -} - -/// EmitPutS - Emit a call to the puts function. This assumes that Str is -/// some pointer. -void LibCallOptimization::EmitPutS(Value *Str, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI[2]; - AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); - AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); - - Value *PutS = M->getOrInsertFunction("puts", AttrListPtr::get(AWI, 2), - Type::getInt32Ty(*Context), - Type::getInt8PtrTy(*Context), - NULL); - CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts"); - if (const Function *F = dyn_cast(PutS->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - -} - -/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is -/// an integer and File is a pointer to FILE. -void LibCallOptimization::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI[2]; - AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture); - AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); - Constant *F; - if (isa(File->getType())) - F = M->getOrInsertFunction("fputc", AttrListPtr::get(AWI, 2), - Type::getInt32Ty(*Context), - Type::getInt32Ty(*Context), File->getType(), - NULL); - else - F = M->getOrInsertFunction("fputc", - Type::getInt32Ty(*Context), - Type::getInt32Ty(*Context), - File->getType(), NULL); - Char = B.CreateIntCast(Char, Type::getInt32Ty(*Context), /*isSigned*/true, - "chari"); - CallInst *CI = B.CreateCall2(F, Char, File, "fputc"); - - if (const Function *Fn = dyn_cast(F->stripPointerCasts())) - CI->setCallingConv(Fn->getCallingConv()); -} - -/// EmitFPutS - Emit a call to the puts function. Str is required to be a -/// pointer and File is a pointer to FILE. -void LibCallOptimization::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI[3]; - AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); - AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture); - AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); - Constant *F; - if (isa(File->getType())) - F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3), - Type::getInt32Ty(*Context), - Type::getInt8PtrTy(*Context), - File->getType(), NULL); - else - F = M->getOrInsertFunction("fputs", Type::getInt32Ty(*Context), - Type::getInt8PtrTy(*Context), - File->getType(), NULL); - CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs"); - - if (const Function *Fn = dyn_cast(F->stripPointerCasts())) - CI->setCallingConv(Fn->getCallingConv()); -} - -/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is -/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. -void LibCallOptimization::EmitFWrite(Value *Ptr, Value *Size, Value *File, - IRBuilder<> &B) { - Module *M = Caller->getParent(); - AttributeWithIndex AWI[3]; - AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); - AWI[1] = AttributeWithIndex::get(4, Attribute::NoCapture); - AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); - Constant *F; - if (isa(File->getType())) - F = M->getOrInsertFunction("fwrite", AttrListPtr::get(AWI, 3), - TD->getIntPtrType(*Context), - Type::getInt8PtrTy(*Context), - TD->getIntPtrType(*Context), - TD->getIntPtrType(*Context), - File->getType(), NULL); - else - F = M->getOrInsertFunction("fwrite", TD->getIntPtrType(*Context), - Type::getInt8PtrTy(*Context), - TD->getIntPtrType(*Context), - TD->getIntPtrType(*Context), - File->getType(), NULL); - CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size, - ConstantInt::get(TD->getIntPtrType(*Context), 1), File); - - if (const Function *Fn = dyn_cast(F->stripPointerCasts())) - CI->setCallingConv(Fn->getCallingConv()); -} //===----------------------------------------------------------------------===// // Helper Functions //===----------------------------------------------------------------------===// -/// GetStringLengthH - If we can compute the length of the string pointed to by -/// the specified pointer, return 'len+1'. If we can't, return 0. -static uint64_t GetStringLengthH(Value *V, SmallPtrSet &PHIs) { - // Look through noop bitcast instructions. - if (BitCastInst *BCI = dyn_cast(V)) - return GetStringLengthH(BCI->getOperand(0), PHIs); - - // If this is a PHI node, there are two cases: either we have already seen it - // or we haven't. - if (PHINode *PN = dyn_cast(V)) { - if (!PHIs.insert(PN)) - return ~0ULL; // already in the set. - - // If it was new, see if all the input strings are the same length. - uint64_t LenSoFar = ~0ULL; - for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { - uint64_t Len = GetStringLengthH(PN->getIncomingValue(i), PHIs); - if (Len == 0) return 0; // Unknown length -> unknown. - - if (Len == ~0ULL) continue; - - if (Len != LenSoFar && LenSoFar != ~0ULL) - return 0; // Disagree -> unknown. - LenSoFar = Len; - } - - // Success, all agree. - return LenSoFar; - } - - // strlen(select(c,x,y)) -> strlen(x) ^ strlen(y) - if (SelectInst *SI = dyn_cast(V)) { - uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs); - if (Len1 == 0) return 0; - uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs); - if (Len2 == 0) return 0; - if (Len1 == ~0ULL) return Len2; - if (Len2 == ~0ULL) return Len1; - if (Len1 != Len2) return 0; - return Len1; - } - - // If the value is not a GEP instruction nor a constant expression with a - // GEP instruction, then return unknown. - User *GEP = 0; - if (GetElementPtrInst *GEPI = dyn_cast(V)) { - GEP = GEPI; - } else if (ConstantExpr *CE = dyn_cast(V)) { - if (CE->getOpcode() != Instruction::GetElementPtr) - return 0; - GEP = CE; - } else { - return 0; - } - - // Make sure the GEP has exactly three arguments. - if (GEP->getNumOperands() != 3) - return 0; - - // Check to make sure that the first operand of the GEP is an integer and - // has value 0 so that we are sure we're indexing into the initializer. - if (ConstantInt *Idx = dyn_cast(GEP->getOperand(1))) { - if (!Idx->isZero()) - return 0; - } else - return 0; - - // If the second index isn't a ConstantInt, then this is a variable index - // into the array. If this occurs, we can't say anything meaningful about - // the string. - uint64_t StartIdx = 0; - if (ConstantInt *CI = dyn_cast(GEP->getOperand(2))) - StartIdx = CI->getZExtValue(); - else - return 0; - - // The GEP instruction, constant or instruction, must reference a global - // variable that is a constant and is initialized. The referenced constant - // initializer is the array that we'll use for optimization. - GlobalVariable* GV = dyn_cast(GEP->getOperand(0)); - if (!GV || !GV->isConstant() || !GV->hasInitializer() || - GV->mayBeOverridden()) - return 0; - Constant *GlobalInit = GV->getInitializer(); - - // Handle the ConstantAggregateZero case, which is a degenerate case. The - // initializer is constant zero so the length of the string must be zero. - if (isa(GlobalInit)) - return 1; // Len = 0 offset by 1. - - // Must be a Constant Array - ConstantArray *Array = dyn_cast(GlobalInit); - if (!Array || !Array->getType()->getElementType()->isInteger(8)) - return false; - - // Get the number of elements in the array - uint64_t NumElts = Array->getType()->getNumElements(); - - // Traverse the constant array from StartIdx (derived above) which is - // the place the GEP refers to in the array. - for (unsigned i = StartIdx; i != NumElts; ++i) { - Constant *Elt = Array->getOperand(i); - ConstantInt *CI = dyn_cast(Elt); - if (!CI) // This array isn't suitable, non-int initializer. - return 0; - if (CI->isZero()) - return i-StartIdx+1; // We found end of string, success! - } - - return 0; // The array isn't null terminated, conservatively return 'unknown'. -} - -/// GetStringLength - If we can compute the length of the string pointed to by -/// the specified pointer, return 'len+1'. If we can't, return 0. -static uint64_t GetStringLength(Value *V) { - if (!isa(V->getType())) return 0; - - SmallPtrSet PHIs; - uint64_t Len = GetStringLengthH(V, PHIs); - // If Len is ~0ULL, we had an infinite phi cycle: this is dead code, so return - // an empty string as a length. - return Len == ~0ULL ? 1 : Len; -} - /// IsOnlyUsedInZeroEqualityComparison - Return true if it only matters that the /// value is equal or not-equal to zero. static bool IsOnlyUsedInZeroEqualityComparison(Value *V) { @@ -613,7 +132,7 @@ struct StrCatOpt : public LibCallOptimization { void EmitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B) { // We need to find the end of the destination string. That's where the // memory is to be moved to. We just generate a call to strlen. - Value *DstLen = EmitStrLen(Dst, B); + Value *DstLen = EmitStrLen(Dst, B, TD); // Now that we have the destination's length, we must index into the // destination's pointer to get the actual memcpy destination (end of @@ -623,7 +142,7 @@ struct StrCatOpt : public LibCallOptimization { // We have enough information to now generate the memcpy call to do the // concatenation for us. Make a memcpy to copy the nul byte with align = 1. EmitMemCpy(CpyDst, Src, - ConstantInt::get(TD->getIntPtrType(*Context), Len+1), 1, B); + ConstantInt::get(TD->getIntPtrType(*Context), Len+1), 1, B, TD); } }; @@ -638,7 +157,7 @@ struct StrNCatOpt : public StrCatOpt { FT->getReturnType() != Type::getInt8PtrTy(*Context) || FT->getParamType(0) != FT->getReturnType() || FT->getParamType(1) != FT->getReturnType() || - !isa(FT->getParamType(2))) + !FT->getParamType(2)->isIntegerTy()) return 0; // Extract some information from the instruction @@ -697,11 +216,12 @@ struct StrChrOpt : public LibCallOptimization { if (!TD) return 0; uint64_t Len = GetStringLength(SrcStr); - if (Len == 0 || !FT->getParamType(1)->isInteger(32)) // memchr needs i32. + if (Len == 0 || !FT->getParamType(1)->isIntegerTy(32))// memchr needs i32. return 0; return EmitMemChr(SrcStr, CI->getOperand(2), // include nul. - ConstantInt::get(TD->getIntPtrType(*Context), Len), B); + ConstantInt::get(TD->getIntPtrType(*Context), Len), + B, TD); } // Otherwise, the character is a constant, see if the first argument is @@ -739,7 +259,7 @@ struct StrCmpOpt : public LibCallOptimization { // Verify the "strcmp" function prototype. const FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 2 || - !FT->getReturnType()->isInteger(32) || + !FT->getReturnType()->isIntegerTy(32) || FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != Type::getInt8PtrTy(*Context)) return 0; @@ -772,7 +292,7 @@ struct StrCmpOpt : public LibCallOptimization { return EmitMemCmp(Str1P, Str2P, ConstantInt::get(TD->getIntPtrType(*Context), - std::min(Len1, Len2)), B); + std::min(Len1, Len2)), B, TD); } return 0; @@ -787,10 +307,10 @@ struct StrNCmpOpt : public LibCallOptimization { // Verify the "strncmp" function prototype. const FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 3 || - !FT->getReturnType()->isInteger(32) || + !FT->getReturnType()->isIntegerTy(32) || FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != Type::getInt8PtrTy(*Context) || - !isa(FT->getParamType(2))) + !FT->getParamType(2)->isIntegerTy()) return 0; Value *Str1P = CI->getOperand(1), *Str2P = CI->getOperand(2); @@ -852,7 +372,7 @@ struct StrCpyOpt : public LibCallOptimization { // We have enough information to now generate the memcpy call to do the // concatenation for us. Make a memcpy to copy the nul byte with align = 1. EmitMemCpy(Dst, Src, - ConstantInt::get(TD->getIntPtrType(*Context), Len), 1, B); + ConstantInt::get(TD->getIntPtrType(*Context), Len), 1, B, TD); return Dst; } }; @@ -866,7 +386,7 @@ struct StrNCpyOpt : public LibCallOptimization { if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || FT->getParamType(0) != FT->getParamType(1) || FT->getParamType(0) != Type::getInt8PtrTy(*Context) || - !isa(FT->getParamType(2))) + !FT->getParamType(2)->isIntegerTy()) return 0; Value *Dst = CI->getOperand(1); @@ -881,7 +401,7 @@ struct StrNCpyOpt : public LibCallOptimization { if (SrcLen == 0) { // strncpy(x, "", y) -> memset(x, '\0', y, 1) EmitMemSet(Dst, ConstantInt::get(Type::getInt8Ty(*Context), '\0'), LenOp, - B); + B, TD); return Dst; } @@ -901,7 +421,7 @@ struct StrNCpyOpt : public LibCallOptimization { // strncpy(x, s, c) -> memcpy(x, s, c, 1) [s and c are constant] EmitMemCpy(Dst, Src, - ConstantInt::get(TD->getIntPtrType(*Context), Len), 1, B); + ConstantInt::get(TD->getIntPtrType(*Context), Len), 1, B, TD); return Dst; } @@ -915,7 +435,7 @@ struct StrLenOpt : public LibCallOptimization { const FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 1 || FT->getParamType(0) != Type::getInt8PtrTy(*Context) || - !isa(FT->getReturnType())) + !FT->getReturnType()->isIntegerTy()) return 0; Value *Src = CI->getOperand(1); @@ -939,8 +459,8 @@ struct StrToOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { const FunctionType *FT = Callee->getFunctionType(); if ((FT->getNumParams() != 2 && FT->getNumParams() != 3) || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1))) + !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy()) return 0; Value *EndPtr = CI->getOperand(2); @@ -960,9 +480,9 @@ struct StrStrOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { const FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 2 || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !isa(FT->getReturnType())) + !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || + !FT->getReturnType()->isPointerTy()) return 0; // fold strstr(x, x) -> x. @@ -993,7 +513,7 @@ struct StrStrOpt : public LibCallOptimization { // fold strstr(x, "y") -> strchr(x, 'y'). if (HasStr2 && ToFindStr.size() == 1) - return B.CreateBitCast(EmitStrChr(CI->getOperand(1), ToFindStr[0], B), + return B.CreateBitCast(EmitStrChr(CI->getOperand(1), ToFindStr[0], B, TD), CI->getType()); return 0; } @@ -1006,9 +526,9 @@ struct StrStrOpt : public LibCallOptimization { struct MemCmpOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 3 || !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !FT->getReturnType()->isInteger(32)) + if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || + !FT->getReturnType()->isIntegerTy(32)) return 0; Value *LHS = CI->getOperand(1), *RHS = CI->getOperand(2); @@ -1055,13 +575,14 @@ struct MemCpyOpt : public LibCallOptimization { const FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || + !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || FT->getParamType(2) != TD->getIntPtrType(*Context)) return 0; // memcpy(x, y, n) -> llvm.memcpy(x, y, n, 1) - EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), + CI->getOperand(3), 1, B, TD); return CI->getOperand(1); } }; @@ -1076,13 +597,14 @@ struct MemMoveOpt : public LibCallOptimization { const FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || + !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || FT->getParamType(2) != TD->getIntPtrType(*Context)) return 0; // memmove(x, y, n) -> llvm.memmove(x, y, n, 1) - EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); + EmitMemMove(CI->getOperand(1), CI->getOperand(2), + CI->getOperand(3), 1, B, TD); return CI->getOperand(1); } }; @@ -1097,136 +619,19 @@ struct MemSetOpt : public LibCallOptimization { const FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || + !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isIntegerTy() || FT->getParamType(2) != TD->getIntPtrType(*Context)) return 0; // memset(p, v, n) -> llvm.memset(p, v, n, 1) Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), false); - EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); return CI->getOperand(1); } }; -//===----------------------------------------------------------------------===// -// Object Size Checking Optimizations -//===----------------------------------------------------------------------===// - -//===---------------------------------------===// -// 'memcpy_chk' Optimizations - -struct MemCpyChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // These optimizations require TargetData. - if (!TD) return 0; - - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !isa(FT->getParamType(3)) || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); - if (!SizeCI) - return 0; - if (SizeCI->isAllOnesValue()) { - EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); - return CI->getOperand(1); - } - - return 0; - } -}; - -//===---------------------------------------===// -// 'memset_chk' Optimizations - -struct MemSetChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // These optimizations require TargetData. - if (!TD) return 0; - - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !isa(FT->getParamType(3)) || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); - if (!SizeCI) - return 0; - if (SizeCI->isAllOnesValue()) { - Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), - false); - EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B); - return CI->getOperand(1); - } - - return 0; - } -}; - -//===---------------------------------------===// -// 'memmove_chk' Optimizations - -struct MemMoveChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - // These optimizations require TargetData. - if (!TD) return 0; - - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !isa(FT->getParamType(3)) || - FT->getParamType(2) != TD->getIntPtrType(*Context)) - return 0; - - ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); - if (!SizeCI) - return 0; - if (SizeCI->isAllOnesValue()) { - EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), - 1, B); - return CI->getOperand(1); - } - - return 0; - } -}; - -struct StrCpyChkOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || - !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1))) - return 0; - - ConstantInt *SizeCI = dyn_cast(CI->getOperand(3)); - if (!SizeCI) - return 0; - - // If a) we don't have any length information, or b) we know this will - // fit then just lower to a plain strcpy. Otherwise we'll keep our - // strcpy_chk call which may fail at runtime if the size is too long. - // TODO: It might be nice to get a maximum length out of the possible - // string lengths for varying. - if (SizeCI->isAllOnesValue() || - SizeCI->getZExtValue() >= GetStringLength(CI->getOperand(2))) - return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B); - - return 0; - } -}; - - //===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -1241,7 +646,7 @@ struct PowOpt : public LibCallOptimization { // result type. if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) || FT->getParamType(0) != FT->getParamType(1) || - !FT->getParamType(0)->isFloatingPoint()) + !FT->getParamType(0)->isFloatingPointTy()) return 0; Value *Op1 = CI->getOperand(1), *Op2 = CI->getOperand(2); @@ -1295,7 +700,7 @@ struct Exp2Opt : public LibCallOptimization { // Just make sure this has 1 argument of FP type, which matches the // result type. if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isFloatingPoint()) + !FT->getParamType(0)->isFloatingPointTy()) return 0; Value *Op = CI->getOperand(1); @@ -1375,8 +780,8 @@ struct FFSOpt : public LibCallOptimization { // Just make sure this has 2 arguments of the same FP type, which match the // result type. if (FT->getNumParams() != 1 || - !FT->getReturnType()->isInteger(32) || - !isa(FT->getParamType(0))) + !FT->getReturnType()->isIntegerTy(32) || + !FT->getParamType(0)->isIntegerTy()) return 0; Value *Op = CI->getOperand(1); @@ -1410,8 +815,8 @@ struct IsDigitOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { const FunctionType *FT = Callee->getFunctionType(); // We require integer(i32) - if (FT->getNumParams() != 1 || !isa(FT->getReturnType()) || - !FT->getParamType(0)->isInteger(32)) + if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() || + !FT->getParamType(0)->isIntegerTy(32)) return 0; // isdigit(c) -> (c-'0') &B) { const FunctionType *FT = Callee->getFunctionType(); // We require integer(i32) - if (FT->getNumParams() != 1 || !isa(FT->getReturnType()) || - !FT->getParamType(0)->isInteger(32)) + if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() || + !FT->getParamType(0)->isIntegerTy(32)) return 0; // isascii(c) -> c &B) { const FunctionType *FT = Callee->getFunctionType(); // We require integer(integer) where the types agree. - if (FT->getNumParams() != 1 || !isa(FT->getReturnType()) || + if (FT->getNumParams() != 1 || !FT->getReturnType()->isIntegerTy() || FT->getParamType(0) != FT->getReturnType()) return 0; @@ -1473,7 +878,7 @@ struct ToAsciiOpt : public LibCallOptimization { const FunctionType *FT = Callee->getFunctionType(); // We require i32(i32) if (FT->getNumParams() != 1 || FT->getReturnType() != FT->getParamType(0) || - !FT->getParamType(0)->isInteger(32)) + !FT->getParamType(0)->isIntegerTy(32)) return 0; // isascii(c) -> c & 0x7f @@ -1493,8 +898,8 @@ struct PrintFOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { // Require one fixed pointer argument and an integer/void result. const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() < 1 || !isa(FT->getParamType(0)) || - !(isa(FT->getReturnType()) || + if (FT->getNumParams() < 1 || !FT->getParamType(0)->isPointerTy() || + !(FT->getReturnType()->isIntegerTy() || FT->getReturnType()->isVoidTy())) return 0; @@ -1512,7 +917,7 @@ struct PrintFOpt : public LibCallOptimization { // in case there is an error writing to stdout. if (FormatStr.size() == 1) { Value *Res = EmitPutChar(ConstantInt::get(Type::getInt32Ty(*Context), - FormatStr[0]), B); + FormatStr[0]), B, TD); if (CI->use_empty()) return CI; return B.CreateIntCast(Res, CI->getType(), true); } @@ -1526,7 +931,7 @@ struct PrintFOpt : public LibCallOptimization { Constant *C = ConstantArray::get(*Context, FormatStr, true); C = new GlobalVariable(*Callee->getParent(), C->getType(), true, GlobalVariable::InternalLinkage, C, "str"); - EmitPutS(C, B); + EmitPutS(C, B, TD); return CI->use_empty() ? (Value*)CI : ConstantInt::get(CI->getType(), FormatStr.size()+1); } @@ -1534,8 +939,8 @@ struct PrintFOpt : public LibCallOptimization { // Optimize specific format strings. // printf("%c", chr) --> putchar(*(i8*)dst) if (FormatStr == "%c" && CI->getNumOperands() > 2 && - isa(CI->getOperand(2)->getType())) { - Value *Res = EmitPutChar(CI->getOperand(2), B); + CI->getOperand(2)->getType()->isIntegerTy()) { + Value *Res = EmitPutChar(CI->getOperand(2), B, TD); if (CI->use_empty()) return CI; return B.CreateIntCast(Res, CI->getType(), true); @@ -1543,9 +948,9 @@ struct PrintFOpt : public LibCallOptimization { // printf("%s\n", str) --> puts(str) if (FormatStr == "%s\n" && CI->getNumOperands() > 2 && - isa(CI->getOperand(2)->getType()) && + CI->getOperand(2)->getType()->isPointerTy() && CI->use_empty()) { - EmitPutS(CI->getOperand(2), B); + EmitPutS(CI->getOperand(2), B, TD); return CI; } return 0; @@ -1559,9 +964,9 @@ struct SPrintFOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { // Require two fixed pointer arguments and an integer result. const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 2 || !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !isa(FT->getReturnType())) + if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || + !FT->getReturnType()->isIntegerTy()) return 0; // Check for a fixed format string. @@ -1582,8 +987,8 @@ struct SPrintFOpt : public LibCallOptimization { // sprintf(str, fmt) -> llvm.memcpy(str, fmt, strlen(fmt)+1, 1) EmitMemCpy(CI->getOperand(1), CI->getOperand(2), // Copy the nul byte. - ConstantInt::get - (TD->getIntPtrType(*Context), FormatStr.size()+1),1,B); + ConstantInt::get(TD->getIntPtrType(*Context), + FormatStr.size()+1), 1, B, TD); return ConstantInt::get(CI->getType(), FormatStr.size()); } @@ -1595,7 +1000,7 @@ struct SPrintFOpt : public LibCallOptimization { // Decode the second character of the format string. if (FormatStr[1] == 'c') { // sprintf(dst, "%c", chr) --> *(i8*)dst = chr; *((i8*)dst+1) = 0 - if (!isa(CI->getOperand(3)->getType())) return 0; + if (!CI->getOperand(3)->getType()->isIntegerTy()) return 0; Value *V = B.CreateTrunc(CI->getOperand(3), Type::getInt8Ty(*Context), "char"); Value *Ptr = CastToCStr(CI->getOperand(1), B); @@ -1612,13 +1017,13 @@ struct SPrintFOpt : public LibCallOptimization { if (!TD) return 0; // sprintf(dest, "%s", str) -> llvm.memcpy(dest, str, strlen(str)+1, 1) - if (!isa(CI->getOperand(3)->getType())) return 0; + if (!CI->getOperand(3)->getType()->isPointerTy()) return 0; - Value *Len = EmitStrLen(CI->getOperand(3), B); + Value *Len = EmitStrLen(CI->getOperand(3), B, TD); Value *IncLen = B.CreateAdd(Len, ConstantInt::get(Len->getType(), 1), "leninc"); - EmitMemCpy(CI->getOperand(1), CI->getOperand(3), IncLen, 1, B); + EmitMemCpy(CI->getOperand(1), CI->getOperand(3), IncLen, 1, B, TD); // The sprintf result is the unincremented number of bytes in the string. return B.CreateIntCast(Len, CI->getType(), false); @@ -1634,11 +1039,11 @@ struct FWriteOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { // Require a pointer, an integer, an integer, a pointer, returning integer. const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 4 || !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !isa(FT->getParamType(2)) || - !isa(FT->getParamType(3)) || - !isa(FT->getReturnType())) + if (FT->getNumParams() != 4 || !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isIntegerTy() || + !FT->getParamType(2)->isIntegerTy() || + !FT->getParamType(3)->isPointerTy() || + !FT->getReturnType()->isIntegerTy()) return 0; // Get the element size and count. @@ -1654,7 +1059,7 @@ struct FWriteOpt : public LibCallOptimization { // If this is writing one byte, turn it into fputc. if (Bytes == 1) { // fwrite(S,1,1,F) -> fputc(S[0],F) Value *Char = B.CreateLoad(CastToCStr(CI->getOperand(1), B), "char"); - EmitFPutC(Char, CI->getOperand(4), B); + EmitFPutC(Char, CI->getOperand(4), B, TD); return ConstantInt::get(CI->getType(), 1); } @@ -1672,8 +1077,8 @@ struct FPutsOpt : public LibCallOptimization { // Require two pointers. Also, we can't optimize if return value is used. const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 2 || !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || + if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || !CI->use_empty()) return 0; @@ -1682,7 +1087,7 @@ struct FPutsOpt : public LibCallOptimization { if (!Len) return 0; EmitFWrite(CI->getOperand(1), ConstantInt::get(TD->getIntPtrType(*Context), Len-1), - CI->getOperand(2), B); + CI->getOperand(2), B, TD); return CI; // Known to have no uses (see above). } }; @@ -1694,9 +1099,9 @@ struct FPrintFOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { // Require two fixed paramters as pointers and integer result. const FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 2 || !isa(FT->getParamType(0)) || - !isa(FT->getParamType(1)) || - !isa(FT->getReturnType())) + if (FT->getNumParams() != 2 || !FT->getParamType(0)->isPointerTy() || + !FT->getParamType(1)->isPointerTy() || + !FT->getReturnType()->isIntegerTy()) return 0; // All the optimizations depend on the format string. @@ -1716,7 +1121,7 @@ struct FPrintFOpt : public LibCallOptimization { EmitFWrite(CI->getOperand(2), ConstantInt::get(TD->getIntPtrType(*Context), FormatStr.size()), - CI->getOperand(1), B); + CI->getOperand(1), B, TD); return ConstantInt::get(CI->getType(), FormatStr.size()); } @@ -1728,16 +1133,16 @@ struct FPrintFOpt : public LibCallOptimization { // Decode the second character of the format string. if (FormatStr[1] == 'c') { // fprintf(F, "%c", chr) --> *(i8*)dst = chr - if (!isa(CI->getOperand(3)->getType())) return 0; - EmitFPutC(CI->getOperand(3), CI->getOperand(1), B); + if (!CI->getOperand(3)->getType()->isIntegerTy()) return 0; + EmitFPutC(CI->getOperand(3), CI->getOperand(1), B, TD); return ConstantInt::get(CI->getType(), 1); } if (FormatStr[1] == 's') { // fprintf(F, "%s", str) -> fputs(str, F) - if (!isa(CI->getOperand(3)->getType()) || !CI->use_empty()) + if (!CI->getOperand(3)->getType()->isPointerTy() || !CI->use_empty()) return 0; - EmitFPutS(CI->getOperand(3), CI->getOperand(1), B); + EmitFPutS(CI->getOperand(3), CI->getOperand(1), B, TD); return CI; } return 0; @@ -1769,10 +1174,6 @@ namespace { SPrintFOpt SPrintF; PrintFOpt PrintF; FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF; - // Object Size Checking - MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk; - StrCpyChkOpt StrCpyChk; - bool Modified; // This is only used by doInitialization. public: static char ID; // Pass identification @@ -1878,12 +1279,6 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["fwrite"] = &FWrite; Optimizations["fputs"] = &FPuts; Optimizations["fprintf"] = &FPrintF; - - // Object Size Checking - Optimizations["__memcpy_chk"] = &MemCpyChk; - Optimizations["__memset_chk"] = &MemSetChk; - Optimizations["__memmove_chk"] = &MemMoveChk; - Optimizations["__strcpy_chk"] = &StrCpyChk; } @@ -2000,7 +1395,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 's': if (Name == "strlen") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setOnlyReadsMemory(F); setDoesNotThrow(F); @@ -2018,14 +1413,14 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "strncpy" || Name == "strtoull") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); } else if (Name == "strxfrm") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2038,8 +1433,8 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "strcasecmp" || Name == "strncasecmp") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setOnlyReadsMemory(F); setDoesNotThrow(F); @@ -2048,7 +1443,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { } else if (Name == "strstr" || Name == "strpbrk") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setOnlyReadsMemory(F); setDoesNotThrow(F); @@ -2056,7 +1451,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { } else if (Name == "strtok" || Name == "strtok_r") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); @@ -2064,15 +1459,15 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "setbuf" || Name == "setvbuf") { if (FTy->getNumParams() < 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "strdup" || Name == "strndup") { if (FTy->getNumParams() < 1 || - !isa(FTy->getReturnType()) || - !isa(FTy->getParamType(0))) + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); @@ -2082,31 +1477,31 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "sprintf" || Name == "statvfs") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); setDoesNotCapture(F, 2); } else if (Name == "snprintf") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(2))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); setDoesNotCapture(F, 3); } else if (Name == "setitimer") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(1)) || - !isa(FTy->getParamType(2))) + !FTy->getParamType(1)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); setDoesNotCapture(F, 3); } else if (Name == "system") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; // May throw; "system" is a valid pthread cancellation point. setDoesNotCapture(F, 1); @@ -2115,14 +1510,14 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'm': if (Name == "malloc") { if (FTy->getNumParams() != 1 || - !isa(FTy->getReturnType())) + !FTy->getReturnType()->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); } else if (Name == "memcmp") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setOnlyReadsMemory(F); setDoesNotThrow(F); @@ -2141,18 +1536,18 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "memccpy" || Name == "memmove") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); } else if (Name == "memalign") { - if (!isa(FTy->getReturnType())) + if (!FTy->getReturnType()->isPointerTy()) continue; setDoesNotAlias(F, 0); } else if (Name == "mkdir" || Name == "mktime") { if (FTy->getNumParams() == 0 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2161,15 +1556,15 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'r': if (Name == "realloc") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getReturnType())) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getReturnType()->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); setDoesNotCapture(F, 1); } else if (Name == "read") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; // May throw; "read" is a valid pthread cancellation point. setDoesNotCapture(F, 2); @@ -2178,15 +1573,15 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "remove" || Name == "realpath") { if (FTy->getNumParams() < 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "rename" || Name == "readlink") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2196,7 +1591,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'w': if (Name == "write") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; // May throw; "write" is a valid pthread cancellation point. setDoesNotCapture(F, 2); @@ -2205,16 +1600,16 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'b': if (Name == "bcopy") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); setDoesNotCapture(F, 2); } else if (Name == "bcmp") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setOnlyReadsMemory(F); @@ -2222,7 +1617,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { setDoesNotCapture(F, 2); } else if (Name == "bzero") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2231,7 +1626,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'c': if (Name == "calloc") { if (FTy->getNumParams() != 2 || - !isa(FTy->getReturnType())) + !FTy->getReturnType()->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); @@ -2241,7 +1636,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "clearerr" || Name == "closedir") { if (FTy->getNumParams() == 0 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2253,14 +1648,14 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "atof" || Name == "atoll") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setOnlyReadsMemory(F); setDoesNotCapture(F, 1); } else if (Name == "access") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2269,9 +1664,9 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'f': if (Name == "fopen") { if (FTy->getNumParams() != 2 || - !isa(FTy->getReturnType()) || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); @@ -2279,8 +1674,8 @@ bool SimplifyLibCalls::doInitialization(Module &M) { setDoesNotCapture(F, 2); } else if (Name == "fdopen") { if (FTy->getNumParams() != 2 || - !isa(FTy->getReturnType()) || - !isa(FTy->getParamType(1))) + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); @@ -2300,13 +1695,13 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "funlockfile" || Name == "ftrylockfile") { if (FTy->getNumParams() == 0 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "ferror") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2318,22 +1713,22 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "frexpl" || Name == "fstatvfs") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); } else if (Name == "fgets") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(2))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 3); } else if (Name == "fread" || Name == "fwrite") { if (FTy->getNumParams() != 4 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(3))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(3)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2343,8 +1738,8 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "fprintf" || Name == "fgetpos") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2356,13 +1751,13 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "getlogin_r" || Name == "getc_unlocked") { if (FTy->getNumParams() == 0 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "getenv") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setOnlyReadsMemory(F); @@ -2372,13 +1767,13 @@ bool SimplifyLibCalls::doInitialization(Module &M) { setDoesNotThrow(F); } else if (Name == "getitimer") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); } else if (Name == "getpwnam") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2387,7 +1782,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'u': if (Name == "ungetc") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); @@ -2395,15 +1790,15 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "unlink" || Name == "unsetenv") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "utime" || Name == "utimes") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2413,7 +1808,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'p': if (Name == "putc") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); @@ -2421,14 +1816,14 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "printf" || Name == "perror") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "pread" || Name == "pwrite") { if (FTy->getNumParams() != 4 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; // May throw; these are valid pthread cancellation points. setDoesNotCapture(F, 2); @@ -2436,9 +1831,9 @@ bool SimplifyLibCalls::doInitialization(Module &M) { setDoesNotThrow(F); } else if (Name == "popen") { if (FTy->getNumParams() != 2 || - !isa(FTy->getReturnType()) || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); @@ -2446,7 +1841,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { setDoesNotCapture(F, 2); } else if (Name == "pclose") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2455,43 +1850,43 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'v': if (Name == "vscanf") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "vsscanf" || Name == "vfscanf") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(1)) || - !isa(FTy->getParamType(2))) + !FTy->getParamType(1)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); setDoesNotCapture(F, 2); } else if (Name == "valloc") { - if (!isa(FTy->getReturnType())) + if (!FTy->getReturnType()->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); } else if (Name == "vprintf") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "vfprintf" || Name == "vsprintf") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); setDoesNotCapture(F, 2); } else if (Name == "vsnprintf") { if (FTy->getNumParams() != 4 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(2))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(2)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2501,14 +1896,14 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'o': if (Name == "open") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; // May throw; "open" is a valid pthread cancellation point. setDoesNotCapture(F, 1); } else if (Name == "opendir") { if (FTy->getNumParams() != 1 || - !isa(FTy->getReturnType()) || - !isa(FTy->getParamType(0))) + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); @@ -2517,13 +1912,13 @@ bool SimplifyLibCalls::doInitialization(Module &M) { break; case 't': if (Name == "tmpfile") { - if (!isa(FTy->getReturnType())) + if (!FTy->getReturnType()->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); } else if (Name == "times") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2546,15 +1941,15 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'l': if (Name == "lstat") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); setDoesNotCapture(F, 2); } else if (Name == "lchown") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2563,7 +1958,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 'q': if (Name == "qsort") { if (FTy->getNumParams() != 4 || - !isa(FTy->getParamType(3))) + !FTy->getParamType(3)->isPointerTy()) continue; // May throw; places call through function pointer. setDoesNotCapture(F, 4); @@ -2573,27 +1968,27 @@ bool SimplifyLibCalls::doInitialization(Module &M) { if (Name == "__strdup" || Name == "__strndup") { if (FTy->getNumParams() < 1 || - !isa(FTy->getReturnType()) || - !isa(FTy->getParamType(0))) + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); setDoesNotCapture(F, 1); } else if (Name == "__strtok_r") { if (FTy->getNumParams() != 3 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); } else if (Name == "_IO_getc") { if (FTy->getNumParams() != 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "_IO_putc") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); @@ -2602,7 +1997,7 @@ bool SimplifyLibCalls::doInitialization(Module &M) { case 1: if (Name == "\1__isoc99_scanf") { if (FTy->getNumParams() < 1 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); @@ -2611,17 +2006,17 @@ bool SimplifyLibCalls::doInitialization(Module &M) { Name == "\1statvfs64" || Name == "\1__isoc99_sscanf") { if (FTy->getNumParams() < 1 || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); setDoesNotCapture(F, 2); } else if (Name == "\1fopen64") { if (FTy->getNumParams() != 2 || - !isa(FTy->getReturnType()) || - !isa(FTy->getParamType(0)) || - !isa(FTy->getParamType(1))) + !FTy->getReturnType()->isPointerTy() || + !FTy->getParamType(0)->isPointerTy() || + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); @@ -2630,25 +2025,25 @@ bool SimplifyLibCalls::doInitialization(Module &M) { } else if (Name == "\1fseeko64" || Name == "\1ftello64") { if (FTy->getNumParams() == 0 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 1); } else if (Name == "\1tmpfile64") { - if (!isa(FTy->getReturnType())) + if (!FTy->getReturnType()->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotAlias(F, 0); } else if (Name == "\1fstat64" || Name == "\1fstatvfs64") { if (FTy->getNumParams() != 2 || - !isa(FTy->getParamType(1))) + !FTy->getParamType(1)->isPointerTy()) continue; setDoesNotThrow(F); setDoesNotCapture(F, 2); } else if (Name == "\1open64") { if (FTy->getNumParams() < 2 || - !isa(FTy->getParamType(0))) + !FTy->getParamType(0)->isPointerTy()) continue; // May throw; "open" is a valid pthread cancellation point. setDoesNotCapture(F, 1); diff --git a/lib/Transforms/Utils/AddrModeMatcher.cpp b/lib/Transforms/Utils/AddrModeMatcher.cpp index 8c4aa592dd..be6b3834f2 100644 --- a/lib/Transforms/Utils/AddrModeMatcher.cpp +++ b/lib/Transforms/Utils/AddrModeMatcher.cpp @@ -125,7 +125,7 @@ static bool MightBeFoldableInst(Instruction *I) { // Don't touch identity bitcasts. if (I->getType() == I->getOperand(0)->getType()) return false; - return isa(I->getType()) || isa(I->getType()); + return I->getType()->isPointerTy() || I->getType()->isIntegerTy(); case Instruction::PtrToInt: // PtrToInt is always a noop, as we know that the int type is pointer sized. return true; @@ -167,8 +167,8 @@ bool AddressingModeMatcher::MatchOperationAddr(User *AddrInst, unsigned Opcode, case Instruction::BitCast: // BitCast is always a noop, and we can handle it as long as it is // int->int or pointer->pointer (we don't want int<->fp or something). - if ((isa(AddrInst->getOperand(0)->getType()) || - isa(AddrInst->getOperand(0)->getType())) && + if ((AddrInst->getOperand(0)->getType()->isPointerTy() || + AddrInst->getOperand(0)->getType()->isIntegerTy()) && // Don't touch identity bitcasts. These were probably put here by LSR, // and we don't want to mess around with them. Assume it knows what it // is doing. @@ -569,7 +569,7 @@ IsProfitableToFoldIntoAddressingMode(Instruction *I, ExtAddrMode &AMBefore, // Get the access type of this use. If the use isn't a pointer, we don't // know what it accesses. Value *Address = User->getOperand(OpNo); - if (!isa(Address->getType())) + if (!Address->getType()->isPointerTy()) return false; const Type *AddressAccessTy = cast(Address->getType())->getElementType(); diff --git a/lib/Transforms/Utils/Android.mk b/lib/Transforms/Utils/Android.mk new file mode 100644 index 0000000000..d9f31d7c3f --- /dev/null +++ b/lib/Transforms/Utils/Android.mk @@ -0,0 +1,49 @@ +LOCAL_PATH:= $(call my-dir) + +transforms_utils_SRC_FILES := \ + AddrModeMatcher.cpp \ + BasicBlockUtils.cpp \ + BasicInliner.cpp \ + BreakCriticalEdges.cpp \ + CloneFunction.cpp \ + CloneLoop.cpp \ + CloneModule.cpp \ + CodeExtractor.cpp \ + DemoteRegToStack.cpp \ + InlineFunction.cpp \ + InstructionNamer.cpp \ + LCSSA.cpp \ + Local.cpp \ + LoopSimplify.cpp \ + LoopUnroll.cpp \ + LowerInvoke.cpp \ + LowerSwitch.cpp \ + Mem2Reg.cpp \ + PromoteMemoryToRegister.cpp \ + SSAUpdater.cpp \ + SSI.cpp \ + SimplifyCFG.cpp \ + UnifyFunctionExitNodes.cpp \ + ValueMapper.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(transforms_utils_SRC_FILES) +LOCAL_MODULE:= libLLVMTransformUtils + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(transforms_utils_SRC_FILES) +LOCAL_MODULE:= libLLVMTransformUtils + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp index 7bc4fcdf36..1f62dabb20 100644 --- a/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -274,24 +274,31 @@ void llvm::RemoveSuccessor(TerminatorInst *TI, unsigned SuccNum) { ReplaceInstWithInst(TI, NewTI); } -/// SplitEdge - Split the edge connecting specified block. Pass P must -/// not be NULL. -BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, Pass *P) { - TerminatorInst *LatchTerm = BB->getTerminator(); - unsigned SuccNum = 0; +/// GetSuccessorNumber - Search for the specified successor of basic block BB +/// and return its position in the terminator instruction's list of +/// successors. It is an error to call this with a block that is not a +/// successor. +unsigned llvm::GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ) { + TerminatorInst *Term = BB->getTerminator(); #ifndef NDEBUG - unsigned e = LatchTerm->getNumSuccessors(); + unsigned e = Term->getNumSuccessors(); #endif for (unsigned i = 0; ; ++i) { assert(i != e && "Didn't find edge?"); - if (LatchTerm->getSuccessor(i) == Succ) { - SuccNum = i; - break; - } + if (Term->getSuccessor(i) == Succ) + return i; } + return 0; +} + +/// SplitEdge - Split the edge connecting specified block. Pass P must +/// not be NULL. +BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, Pass *P) { + unsigned SuccNum = GetSuccessorNumber(BB, Succ); // If this is a critical edge, let SplitCriticalEdge do it. - if (SplitCriticalEdge(BB->getTerminator(), SuccNum, P)) + TerminatorInst *LatchTerm = BB->getTerminator(); + if (SplitCriticalEdge(LatchTerm, SuccNum, P)) return LatchTerm->getSuccessor(SuccNum); // If the edge isn't critical, then BB has a single successor or Succ has a diff --git a/lib/Transforms/Utils/BreakCriticalEdges.cpp b/lib/Transforms/Utils/BreakCriticalEdges.cpp index 19c7206e39..3657390622 100644 --- a/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -179,7 +179,7 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, // Create a new basic block, linking it into the CFG. BasicBlock *NewBB = BasicBlock::Create(TI->getContext(), TIBB->getName() + "." + DestBB->getName() + "_crit_edge"); - // Create our unconditional branch... + // Create our unconditional branch. BranchInst::Create(DestBB, NewBB); // Branch to the new block, breaking the edge. @@ -192,16 +192,47 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, // If there are any PHI nodes in DestBB, we need to update them so that they // merge incoming values from NewBB instead of from TIBB. - // - for (BasicBlock::iterator I = DestBB->begin(); isa(I); ++I) { - PHINode *PN = cast(I); - // We no longer enter through TIBB, now we come in through NewBB. Revector - // exactly one entry in the PHI node that used to come from TIBB to come - // from NewBB. - int BBIdx = PN->getBasicBlockIndex(TIBB); - PN->setIncomingBlock(BBIdx, NewBB); + if (PHINode *APHI = dyn_cast(DestBB->begin())) { + // This conceptually does: + // foreach (PHINode *PN in DestBB) + // PN->setIncomingBlock(PN->getIncomingBlock(TIBB), NewBB); + // but is optimized for two cases. + + if (APHI->getNumIncomingValues() <= 8) { // Small # preds case. + unsigned BBIdx = 0; + for (BasicBlock::iterator I = DestBB->begin(); isa(I); ++I) { + // We no longer enter through TIBB, now we come in through NewBB. + // Revector exactly one entry in the PHI node that used to come from + // TIBB to come from NewBB. + PHINode *PN = cast(I); + + // Reuse the previous value of BBIdx if it lines up. In cases where we + // have multiple phi nodes with *lots* of predecessors, this is a speed + // win because we don't have to scan the PHI looking for TIBB. This + // happens because the BB list of PHI nodes are usually in the same + // order. + if (PN->getIncomingBlock(BBIdx) != TIBB) + BBIdx = PN->getBasicBlockIndex(TIBB); + PN->setIncomingBlock(BBIdx, NewBB); + } + } else { + // However, the foreach loop is slow for blocks with lots of predecessors + // because PHINode::getIncomingBlock is O(n) in # preds. Instead, walk + // the user list of TIBB to find the PHI nodes. + SmallPtrSet UpdatedPHIs; + + for (Value::use_iterator UI = TIBB->use_begin(), E = TIBB->use_end(); + UI != E; ) { + Value::use_iterator Use = UI++; + if (PHINode *PN = dyn_cast(Use)) { + // Remove one entry from each PHI. + if (PN->getParent() == DestBB && UpdatedPHIs.insert(PN)) + PN->setOperand(Use.getOperandNo(), NewBB); + } + } + } } - + // If there are any other edges from TIBB to DestBB, update those to go // through the split block, making those edges non-critical as well (and // reducing the number of phi entries in the DestBB if relevant). @@ -221,6 +252,15 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, // If we don't have a pass object, we can't update anything... if (P == 0) return NewBB; + + DominatorTree *DT = P->getAnalysisIfAvailable(); + DominanceFrontier *DF = P->getAnalysisIfAvailable(); + LoopInfo *LI = P->getAnalysisIfAvailable(); + ProfileInfo *PI = P->getAnalysisIfAvailable(); + + // If we have nothing to update, just return. + if (DT == 0 && DF == 0 && LI == 0 && PI == 0) + return NewBB; // Now update analysis information. Since the only predecessor of NewBB is // the TIBB, TIBB clearly dominates NewBB. TIBB usually doesn't dominate @@ -229,14 +269,23 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, // loop header) then NewBB dominates DestBB. SmallVector OtherPreds; - for (pred_iterator I = pred_begin(DestBB), E = pred_end(DestBB); I != E; ++I) - if (*I != NewBB) - OtherPreds.push_back(*I); + // If there is a PHI in the block, loop over predecessors with it, which is + // faster than iterating pred_begin/end. + if (PHINode *PN = dyn_cast(DestBB->begin())) { + for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) + if (PN->getIncomingBlock(i) != NewBB) + OtherPreds.push_back(PN->getIncomingBlock(i)); + } else { + for (pred_iterator I = pred_begin(DestBB), E = pred_end(DestBB); + I != E; ++I) + if (*I != NewBB) + OtherPreds.push_back(*I); + } bool NewBBDominatesDestBB = true; // Should we update DominatorTree information? - if (DominatorTree *DT = P->getAnalysisIfAvailable()) { + if (DT) { DomTreeNode *TINode = DT->getNode(TIBB); // The new block is not the immediate dominator for any other nodes, but @@ -267,7 +316,7 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, } // Should we update DominanceFrontier information? - if (DominanceFrontier *DF = P->getAnalysisIfAvailable()) { + if (DF) { // If NewBBDominatesDestBB hasn't been computed yet, do so with DF. if (!OtherPreds.empty()) { // FIXME: IMPLEMENT THIS! @@ -301,7 +350,7 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, } // Update LoopInfo if it is around. - if (LoopInfo *LI = P->getAnalysisIfAvailable()) { + if (LI) { if (Loop *TIL = LI->getLoopFor(TIBB)) { // If one or the other blocks were not in a loop, the new block is not // either, and thus LI doesn't need to be updated. @@ -382,9 +431,8 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, } // Update ProfileInfo if it is around. - if (ProfileInfo *PI = P->getAnalysisIfAvailable()) { - PI->splitEdge(TIBB,DestBB,NewBB,MergeIdenticalEdges); - } + if (PI) + PI->splitEdge(TIBB, DestBB, NewBB, MergeIdenticalEdges); return NewBB; } diff --git a/lib/Transforms/Utils/BuildLibCalls.cpp b/lib/Transforms/Utils/BuildLibCalls.cpp new file mode 100644 index 0000000000..2ea4bb6dc9 --- /dev/null +++ b/lib/Transforms/Utils/BuildLibCalls.cpp @@ -0,0 +1,324 @@ +//===- BuildLibCalls.cpp - Utility builder for libcalls -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements some functions that will create standard C libcalls. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/BuildLibCalls.h" +#include "llvm/Type.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/Target/TargetData.h" +#include "llvm/LLVMContext.h" +#include "llvm/Intrinsics.h" + +using namespace llvm; + +/// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. +Value *llvm::CastToCStr(Value *V, IRBuilder<> &B) { + return B.CreateBitCast(V, B.getInt8PtrTy(), "cstr"); +} + +/// EmitStrLen - Emit a call to the strlen function to the builder, for the +/// specified pointer. This always returns an integer value of size intptr_t. +Value *llvm::EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::ReadOnly | + Attribute::NoUnwind); + + LLVMContext &Context = B.GetInsertBlock()->getContext(); + Constant *StrLen = M->getOrInsertFunction("strlen", AttrListPtr::get(AWI, 2), + TD->getIntPtrType(Context), + B.getInt8PtrTy(), + NULL); + CallInst *CI = B.CreateCall(StrLen, CastToCStr(Ptr, B), "strlen"); + if (const Function *F = dyn_cast(StrLen->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +/// EmitStrChr - Emit a call to the strchr function to the builder, for the +/// specified pointer and character. Ptr is required to be some pointer type, +/// and the return value has 'i8*' type. +Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, + const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI = + AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); + + const Type *I8Ptr = B.getInt8PtrTy(); + const Type *I32Ty = B.getInt32Ty(); + Constant *StrChr = M->getOrInsertFunction("strchr", AttrListPtr::get(&AWI, 1), + I8Ptr, I8Ptr, I32Ty, NULL); + CallInst *CI = B.CreateCall2(StrChr, CastToCStr(Ptr, B), + ConstantInt::get(I32Ty, C), "strchr"); + if (const Function *F = dyn_cast(StrChr->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + return CI; +} + +/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the +/// specified pointer arguments. +Value *llvm::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B, + const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + const Type *I8Ptr = B.getInt8PtrTy(); + Value *StrCpy = M->getOrInsertFunction("strcpy", AttrListPtr::get(AWI, 2), + I8Ptr, I8Ptr, I8Ptr, NULL); + CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B), + "strcpy"); + if (const Function *F = dyn_cast(StrCpy->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + return CI; +} + +/// EmitMemCpy - Emit a call to the memcpy function to the builder. This always +/// expects that the size has type 'intptr_t' and Dst/Src are pointers. +Value *llvm::EmitMemCpy(Value *Dst, Value *Src, Value *Len, + unsigned Align, IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + const Type *Ty = Len->getType(); + Value *MemCpy = Intrinsic::getDeclaration(M, Intrinsic::memcpy, &Ty, 1); + Dst = CastToCStr(Dst, B); + Src = CastToCStr(Src, B); + return B.CreateCall4(MemCpy, Dst, Src, Len, + ConstantInt::get(B.getInt32Ty(), Align)); +} + +/// EmitMemMove - Emit a call to the memmove function to the builder. This +/// always expects that the size has type 'intptr_t' and Dst/Src are pointers. +Value *llvm::EmitMemMove(Value *Dst, Value *Src, Value *Len, + unsigned Align, IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + LLVMContext &Context = B.GetInsertBlock()->getContext(); + const Type *Ty = TD->getIntPtrType(Context); + Value *MemMove = Intrinsic::getDeclaration(M, Intrinsic::memmove, &Ty, 1); + Dst = CastToCStr(Dst, B); + Src = CastToCStr(Src, B); + Value *A = ConstantInt::get(B.getInt32Ty(), Align); + return B.CreateCall4(MemMove, Dst, Src, Len, A); +} + +/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is +/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. +Value *llvm::EmitMemChr(Value *Ptr, Value *Val, + Value *Len, IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI; + AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind); + LLVMContext &Context = B.GetInsertBlock()->getContext(); + Value *MemChr = M->getOrInsertFunction("memchr", AttrListPtr::get(&AWI, 1), + B.getInt8PtrTy(), + B.getInt8PtrTy(), + B.getInt32Ty(), + TD->getIntPtrType(Context), + NULL); + CallInst *CI = B.CreateCall3(MemChr, CastToCStr(Ptr, B), Val, Len, "memchr"); + + if (const Function *F = dyn_cast(MemChr->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +/// EmitMemCmp - Emit a call to the memcmp function. +Value *llvm::EmitMemCmp(Value *Ptr1, Value *Ptr2, + Value *Len, IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI[3]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[2] = AttributeWithIndex::get(~0u, Attribute::ReadOnly | + Attribute::NoUnwind); + + LLVMContext &Context = B.GetInsertBlock()->getContext(); + Value *MemCmp = M->getOrInsertFunction("memcmp", AttrListPtr::get(AWI, 3), + B.getInt32Ty(), + B.getInt8PtrTy(), + B.getInt8PtrTy(), + TD->getIntPtrType(Context), NULL); + CallInst *CI = B.CreateCall3(MemCmp, CastToCStr(Ptr1, B), CastToCStr(Ptr2, B), + Len, "memcmp"); + + if (const Function *F = dyn_cast(MemCmp->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +/// EmitMemSet - Emit a call to the memset function +Value *llvm::EmitMemSet(Value *Dst, Value *Val, + Value *Len, IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Intrinsic::ID IID = Intrinsic::memset; + const Type *Tys[1]; + Tys[0] = Len->getType(); + Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 1); + Value *Align = ConstantInt::get(B.getInt32Ty(), 1); + return B.CreateCall4(MemSet, CastToCStr(Dst, B), Val, Len, Align); +} + +/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g. +/// 'floor'). This function is known to take a single of type matching 'Op' and +/// returns one value with the same type. If 'Op' is a long double, 'l' is +/// added as the suffix of name, if 'Op' is a float, we add a 'f' suffix. +Value *llvm::EmitUnaryFloatFnCall(Value *Op, const char *Name, + IRBuilder<> &B, const AttrListPtr &Attrs) { + char NameBuffer[20]; + if (!Op->getType()->isDoubleTy()) { + // If we need to add a suffix, copy into NameBuffer. + unsigned NameLen = strlen(Name); + assert(NameLen < sizeof(NameBuffer)-2); + memcpy(NameBuffer, Name, NameLen); + if (Op->getType()->isFloatTy()) + NameBuffer[NameLen] = 'f'; // floorf + else + NameBuffer[NameLen] = 'l'; // floorl + NameBuffer[NameLen+1] = 0; + Name = NameBuffer; + } + + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Value *Callee = M->getOrInsertFunction(Name, Op->getType(), + Op->getType(), NULL); + CallInst *CI = B.CreateCall(Callee, Op, Name); + CI->setAttributes(Attrs); + if (const Function *F = dyn_cast(Callee->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +/// EmitPutChar - Emit a call to the putchar function. This assumes that Char +/// is an integer. +Value *llvm::EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + Value *PutChar = M->getOrInsertFunction("putchar", B.getInt32Ty(), + B.getInt32Ty(), NULL); + CallInst *CI = B.CreateCall(PutChar, + B.CreateIntCast(Char, + B.getInt32Ty(), + /*isSigned*/true, + "chari"), + "putchar"); + + if (const Function *F = dyn_cast(PutChar->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + return CI; +} + +/// EmitPutS - Emit a call to the puts function. This assumes that Str is +/// some pointer. +void llvm::EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + + Value *PutS = M->getOrInsertFunction("puts", AttrListPtr::get(AWI, 2), + B.getInt32Ty(), + B.getInt8PtrTy(), + NULL); + CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts"); + if (const Function *F = dyn_cast(PutS->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + +} + +/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is +/// an integer and File is a pointer to FILE. +void llvm::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B, + const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI[2]; + AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + Constant *F; + if (File->getType()->isPointerTy()) + F = M->getOrInsertFunction("fputc", AttrListPtr::get(AWI, 2), + B.getInt32Ty(), + B.getInt32Ty(), File->getType(), + NULL); + else + F = M->getOrInsertFunction("fputc", + B.getInt32Ty(), + B.getInt32Ty(), + File->getType(), NULL); + Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true, + "chari"); + CallInst *CI = B.CreateCall2(F, Char, File, "fputc"); + + if (const Function *Fn = dyn_cast(F->stripPointerCasts())) + CI->setCallingConv(Fn->getCallingConv()); +} + +/// EmitFPutS - Emit a call to the puts function. Str is required to be a +/// pointer and File is a pointer to FILE. +void llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, + const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI[3]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture); + AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + Constant *F; + if (File->getType()->isPointerTy()) + F = M->getOrInsertFunction("fputs", AttrListPtr::get(AWI, 3), + B.getInt32Ty(), + B.getInt8PtrTy(), + File->getType(), NULL); + else + F = M->getOrInsertFunction("fputs", B.getInt32Ty(), + B.getInt8PtrTy(), + File->getType(), NULL); + CallInst *CI = B.CreateCall2(F, CastToCStr(Str, B), File, "fputs"); + + if (const Function *Fn = dyn_cast(F->stripPointerCasts())) + CI->setCallingConv(Fn->getCallingConv()); +} + +/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is +/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE. +void llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File, + IRBuilder<> &B, const TargetData *TD) { + Module *M = B.GetInsertBlock()->getParent()->getParent(); + AttributeWithIndex AWI[3]; + AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture); + AWI[1] = AttributeWithIndex::get(4, Attribute::NoCapture); + AWI[2] = AttributeWithIndex::get(~0u, Attribute::NoUnwind); + LLVMContext &Context = B.GetInsertBlock()->getContext(); + Constant *F; + if (File->getType()->isPointerTy()) + F = M->getOrInsertFunction("fwrite", AttrListPtr::get(AWI, 3), + TD->getIntPtrType(Context), + B.getInt8PtrTy(), + TD->getIntPtrType(Context), + TD->getIntPtrType(Context), + File->getType(), NULL); + else + F = M->getOrInsertFunction("fwrite", TD->getIntPtrType(Context), + B.getInt8PtrTy(), + TD->getIntPtrType(Context), + TD->getIntPtrType(Context), + File->getType(), NULL); + CallInst *CI = B.CreateCall4(F, CastToCStr(Ptr, B), Size, + ConstantInt::get(TD->getIntPtrType(Context), 1), File); + + if (const Function *Fn = dyn_cast(F->stripPointerCasts())) + CI->setCallingConv(Fn->getCallingConv()); +} diff --git a/lib/Transforms/Utils/CMakeLists.txt b/lib/Transforms/Utils/CMakeLists.txt index 93577b47ff..dec227acaf 100644 --- a/lib/Transforms/Utils/CMakeLists.txt +++ b/lib/Transforms/Utils/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(LLVMTransformUtils BasicBlockUtils.cpp BasicInliner.cpp BreakCriticalEdges.cpp + BuildLibCalls.cpp CloneFunction.cpp CloneLoop.cpp CloneModule.cpp diff --git a/lib/Transforms/Utils/Local.cpp b/lib/Transforms/Utils/Local.cpp index 7e7973ae0b..d03f7a69c5 100644 --- a/lib/Transforms/Utils/Local.cpp +++ b/lib/Transforms/Utils/Local.cpp @@ -46,7 +46,7 @@ using namespace llvm; static Value *getUnderlyingObjectWithOffset(Value *V, const TargetData *TD, uint64_t &ByteOffset, unsigned MaxLookup = 6) { - if (!isa(V->getType())) + if (!V->getType()->isPointerTy()) return V; for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { if (GEPOperator *GEP = dyn_cast(V)) { @@ -65,7 +65,7 @@ static Value *getUnderlyingObjectWithOffset(Value *V, const TargetData *TD, } else { return V; } - assert(isa(V->getType()) && "Unexpected operand type!"); + assert(V->getType()->isPointerTy() && "Unexpected operand type!"); } return V; } @@ -490,6 +490,17 @@ void llvm::MergeBasicBlockIntoOnlyPred(BasicBlock *DestBB, Pass *P) { // Splice all the instructions from PredBB to DestBB. PredBB->getTerminator()->eraseFromParent(); DestBB->getInstList().splice(DestBB->begin(), PredBB->getInstList()); + + // Zap anything that took the address of DestBB. Not doing this will give the + // address an invalid value. + if (DestBB->hasAddressTaken()) { + BlockAddress *BA = BlockAddress::get(DestBB); + Constant *Replacement = + ConstantInt::get(llvm::Type::getInt32Ty(BA->getContext()), 1); + BA->replaceAllUsesWith(ConstantExpr::getIntToPtr(Replacement, + BA->getType())); + BA->destroyConstant(); + } // Anything that branched to PredBB now branches to DestBB. PredBB->replaceAllUsesWith(DestBB); diff --git a/lib/Transforms/Utils/LoopSimplify.cpp b/lib/Transforms/Utils/LoopSimplify.cpp index 57bab60e6b..924b744f02 100644 --- a/lib/Transforms/Utils/LoopSimplify.cpp +++ b/lib/Transforms/Utils/LoopSimplify.cpp @@ -51,6 +51,7 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Support/CFG.h" +#include "llvm/Support/Debug.h" #include "llvm/ADT/SetOperations.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" @@ -147,6 +148,11 @@ ReprocessLoop: // Delete each unique out-of-loop (and thus dead) predecessor. for (SmallPtrSet::iterator I = BadPreds.begin(), E = BadPreds.end(); I != E; ++I) { + + DEBUG(dbgs() << "LoopSimplify: Deleting edge from dead predecessor "; + WriteAsOperand(dbgs(), *I, false); + dbgs() << "\n"); + // Inform each successor of each dead pred. for (succ_iterator SI = succ_begin(*I), SE = succ_end(*I); SI != SE; ++SI) (*SI)->removePredecessor(*I); @@ -159,6 +165,27 @@ ReprocessLoop: } } + // If there are exiting blocks with branches on undef, resolve the undef in + // the direction which will exit the loop. This will help simplify loop + // trip count computations. + SmallVector ExitingBlocks; + L->getExitingBlocks(ExitingBlocks); + for (SmallVectorImpl::iterator I = ExitingBlocks.begin(), + E = ExitingBlocks.end(); I != E; ++I) + if (BranchInst *BI = dyn_cast((*I)->getTerminator())) + if (BI->isConditional()) { + if (UndefValue *Cond = dyn_cast(BI->getCondition())) { + + DEBUG(dbgs() << "LoopSimplify: Resolving \"br i1 undef\" to exit in "; + WriteAsOperand(dbgs(), *I, false); + dbgs() << "\n"); + + BI->setCondition(ConstantInt::get(Cond->getType(), + !L->contains(BI->getSuccessor(0)))); + Changed = true; + } + } + // Does the loop already have a preheader? If so, don't insert one. BasicBlock *Preheader = L->getLoopPreheader(); if (!Preheader) { @@ -250,8 +277,6 @@ ReprocessLoop: break; } if (UniqueExit) { - SmallVector ExitingBlocks; - L->getExitingBlocks(ExitingBlocks); for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) { BasicBlock *ExitingBlock = ExitingBlocks[i]; if (!ExitingBlock->getSinglePredecessor()) continue; @@ -282,6 +307,11 @@ ReprocessLoop: // Success. The block is now dead, so remove it from the loop, // update the dominator tree and dominance frontier, and delete it. + + DEBUG(dbgs() << "LoopSimplify: Eliminating exiting block "; + WriteAsOperand(dbgs(), ExitingBlock, false); + dbgs() << "\n"); + assert(pred_begin(ExitingBlock) == pred_end(ExitingBlock)); Changed = true; LI->removeBlock(ExitingBlock); @@ -335,6 +365,10 @@ BasicBlock *LoopSimplify::InsertPreheaderForLoop(Loop *L) { SplitBlockPredecessors(Header, &OutsideBlocks[0], OutsideBlocks.size(), ".preheader", this); + DEBUG(dbgs() << "LoopSimplify: Creating pre-header "; + WriteAsOperand(dbgs(), NewBB, false); + dbgs() << "\n"); + // Make sure that NewBB is put someplace intelligent, which doesn't mess up // code layout too horribly. PlaceSplitBlockCarefully(NewBB, OutsideBlocks, L); @@ -360,6 +394,10 @@ BasicBlock *LoopSimplify::RewriteLoopExitBlock(Loop *L, BasicBlock *Exit) { LoopBlocks.size(), ".loopexit", this); + DEBUG(dbgs() << "LoopSimplify: Creating dedicated exit block "; + WriteAsOperand(dbgs(), NewBB, false); + dbgs() << "\n"); + return NewBB; } @@ -480,6 +518,8 @@ Loop *LoopSimplify::SeparateNestedLoop(Loop *L, LPPassManager &LPM) { OuterLoopPreds.push_back(PN->getIncomingBlock(i)); } + DEBUG(dbgs() << "LoopSimplify: Splitting out a new outer loop\n"); + BasicBlock *Header = L->getHeader(); BasicBlock *NewBB = SplitBlockPredecessors(Header, &OuterLoopPreds[0], OuterLoopPreds.size(), @@ -574,6 +614,10 @@ LoopSimplify::InsertUniqueBackedgeBlock(Loop *L, BasicBlock *Preheader) { Header->getName()+".backedge", F); BranchInst *BETerminator = BranchInst::Create(Header, BEBlock); + DEBUG(dbgs() << "LoopSimplify: Inserting unique backedge block "; + WriteAsOperand(dbgs(), BEBlock, false); + dbgs() << "\n"); + // Move the new backedge block to right after the last backedge block. Function::iterator InsertPos = BackedgeBlocks.back(); ++InsertPos; F->getBasicBlockList().splice(InsertPos, F->getBasicBlockList(), BEBlock); diff --git a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp index 544e20ba6b..4f5a70b3b2 100644 --- a/lib/Transforms/Utils/PromoteMemoryToRegister.cpp +++ b/lib/Transforms/Utils/PromoteMemoryToRegister.cpp @@ -518,7 +518,7 @@ void PromoteMem2Reg::run() { // If this PHI node merges one value and/or undefs, get the value. if (Value *V = PN->hasConstantValue(&DT)) { - if (AST && isa(PN->getType())) + if (AST && PN->getType()->isPointerTy()) AST->deleteValue(PN); PN->replaceAllUsesWith(V); PN->eraseFromParent(); @@ -780,7 +780,7 @@ void PromoteMem2Reg::RewriteSingleStoreAlloca(AllocaInst *AI, if (ReplVal == LI) ReplVal = UndefValue::get(LI->getType()); LI->replaceAllUsesWith(ReplVal); - if (AST && isa(LI->getType())) + if (AST && LI->getType()->isPointerTy()) AST->deleteValue(LI); LI->eraseFromParent(); LBI.deleteValue(LI); @@ -838,7 +838,7 @@ void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end(); UI != E;) if (LoadInst *LI = dyn_cast(*UI++)) { LI->replaceAllUsesWith(UndefValue::get(LI->getType())); - if (AST && isa(LI->getType())) + if (AST && LI->getType()->isPointerTy()) AST->deleteValue(LI); LBI.deleteValue(LI); LI->eraseFromParent(); @@ -874,7 +874,7 @@ void PromoteMem2Reg::PromoteSingleBlockAlloca(AllocaInst *AI, AllocaInfo &Info, // Otherwise, there was a store before this load, the load takes its value. --I; LI->replaceAllUsesWith(I->second->getOperand(0)); - if (AST && isa(LI->getType())) + if (AST && LI->getType()->isPointerTy()) AST->deleteValue(LI); LI->eraseFromParent(); LBI.deleteValue(LI); @@ -922,7 +922,7 @@ bool PromoteMem2Reg::QueuePhiNode(BasicBlock *BB, unsigned AllocaNo, InsertedPHINodes.insert(PN); - if (AST && isa(PN->getType())) + if (AST && PN->getType()->isPointerTy()) AST->copyValue(PointerAllocaValues[AllocaNo], PN); return true; @@ -996,7 +996,7 @@ NextIteration: // Anything using the load now uses the current value. LI->replaceAllUsesWith(V); - if (AST && isa(LI->getType())) + if (AST && LI->getType()->isPointerTy()) AST->deleteValue(LI); BB->getInstList().erase(LI); } else if (StoreInst *SI = dyn_cast(I)) { diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index 795b6bfd6e..f343c3811d 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -271,7 +271,7 @@ static bool DominatesMergePoint(Value *V, BasicBlock *BB, ConstantInt *SimplifyCFGOpt::GetConstantInt(Value *V) { // Normal constant int. ConstantInt *CI = dyn_cast(V); - if (CI || !TD || !isa(V) || !isa(V->getType())) + if (CI || !TD || !isa(V) || !V->getType()->isPointerTy()) return CI; // This is some kind of pointer constant. Turn it into a pointer-sized @@ -701,7 +701,7 @@ bool SimplifyCFGOpt::FoldValueComparisonIntoPredecessors(TerminatorInst *TI) { AddPredecessorToBlock(NewSuccessors[i], Pred, BB); // Convert pointer to int before we switch. - if (isa(CV->getType())) { + if (CV->getType()->isPointerTy()) { assert(TD && "Cannot switch on pointer without TargetData"); CV = new PtrToIntInst(CV, TD->getIntPtrType(CV->getContext()), "magicptr", PTI); @@ -915,7 +915,7 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *BB1) { case Instruction::Add: case Instruction::Sub: // Not worth doing for vector ops. - if (isa(HInst->getType())) + if (HInst->getType()->isVectorTy()) return false; break; case Instruction::And: @@ -925,7 +925,7 @@ static bool SpeculativelyExecuteBB(BranchInst *BI, BasicBlock *BB1) { case Instruction::LShr: case Instruction::AShr: // Don't mess with vector operations. - if (isa(HInst->getType())) + if (HInst->getType()->isVectorTy()) return false; break; // These are all cheap and non-trapping instructions. } @@ -1077,7 +1077,7 @@ static bool FoldCondBranchOnPHI(BranchInst *BI) { for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { ConstantInt *CB; if ((CB = dyn_cast(PN->getIncomingValue(i))) && - CB->getType()->isInteger(1)) { + CB->getType()->isIntegerTy(1)) { // Okay, we now know that all edges from PredBB should be revectored to // branch to RealDest. BasicBlock *PredBB = PN->getIncomingBlock(i); @@ -2068,7 +2068,7 @@ bool SimplifyCFGOpt::run(BasicBlock *BB) { if (!TrueWhenEqual) std::swap(DefaultBB, EdgeBB); // Convert pointer to int before we switch. - if (isa(CompVal->getType())) { + if (CompVal->getType()->isPointerTy()) { assert(TD && "Cannot switch on pointer without TargetData"); CompVal = new PtrToIntInst(CompVal, TD->getIntPtrType(CompVal->getContext()), diff --git a/lib/VMCore/Android.mk b/lib/VMCore/Android.mk new file mode 100644 index 0000000000..4784684ae9 --- /dev/null +++ b/lib/VMCore/Android.mk @@ -0,0 +1,61 @@ +LOCAL_PATH:= $(call my-dir) + +vmcore_SRC_FILES := \ + AsmWriter.cpp \ + Attributes.cpp \ + AutoUpgrade.cpp \ + BasicBlock.cpp \ + ConstantFold.cpp \ + Constants.cpp \ + Core.cpp \ + Dominators.cpp \ + Function.cpp \ + GVMaterializer.cpp \ + Globals.cpp \ + IRBuilder.cpp \ + InlineAsm.cpp \ + Instruction.cpp \ + Instructions.cpp \ + IntrinsicInst.cpp \ + LLVMContext.cpp \ + LeakDetector.cpp \ + Metadata.cpp \ + Module.cpp \ + Pass.cpp \ + PassManager.cpp \ + PrintModulePass.cpp \ + Type.cpp \ + TypeSymbolTable.cpp \ + Use.cpp \ + Value.cpp \ + ValueSymbolTable.cpp \ + ValueTypes.cpp \ + Verifier.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(vmcore_SRC_FILES) + +LOCAL_MODULE:= libLLVMCore + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +include $(CLEAR_VARS) + +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(vmcore_SRC_FILES) + +LOCAL_MODULE:= libLLVMCore + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) diff --git a/lib/VMCore/AsmWriter.cpp b/lib/VMCore/AsmWriter.cpp index ab5f45a2b9..fd742413ab 100644 --- a/lib/VMCore/AsmWriter.cpp +++ b/lib/VMCore/AsmWriter.cpp @@ -17,6 +17,7 @@ #include "llvm/Assembly/Writer.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Assembly/AsmAnnotationWriter.h" +#include "llvm/LLVMContext.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -239,6 +240,19 @@ void TypePrinting::CalcTypeName(const Type *Ty, OS << '>'; break; } + case Type::UnionTyID: { + const UnionType *UTy = cast(Ty); + OS << "union { "; + for (StructType::element_iterator I = UTy->element_begin(), + E = UTy->element_end(); I != E; ++I) { + CalcTypeName(*I, TypeStack, OS); + if (next(I) != UTy->element_end()) + OS << ','; + OS << ' '; + } + OS << '}'; + break; + } case Type::PointerTyID: { const PointerType *PTy = cast(Ty); CalcTypeName(PTy->getElementType(), TypeStack, OS); @@ -363,8 +377,8 @@ namespace { return; // If this is a structure or opaque type, add a name for the type. - if (((isa(Ty) && cast(Ty)->getNumElements()) - || isa(Ty)) && !TP.hasTypeName(Ty)) { + if (((Ty->isStructTy() && cast(Ty)->getNumElements()) + || Ty->isOpaqueTy()) && !TP.hasTypeName(Ty)) { TP.addTypeName(Ty, "%"+utostr(unsigned(NumberedTypes.size()))); NumberedTypes.push_back(Ty); } @@ -418,13 +432,13 @@ static void AddModuleTypesToPrinter(TypePrinting &TP, // they are used too often to have a single useful name. if (const PointerType *PTy = dyn_cast(Ty)) { const Type *PETy = PTy->getElementType(); - if ((PETy->isPrimitiveType() || PETy->isInteger()) && - !isa(PETy)) + if ((PETy->isPrimitiveType() || PETy->isIntegerTy()) && + !PETy->isOpaqueTy()) continue; } // Likewise don't insert primitives either. - if (Ty->isInteger() || Ty->isPrimitiveType()) + if (Ty->isIntegerTy() || Ty->isPrimitiveType()) continue; // Get the name as a string and insert it into TypeNames. @@ -836,7 +850,7 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) { static void WriteConstantInt(raw_ostream &Out, const Constant *CV, TypePrinting &TypePrinter, SlotTracker *Machine) { if (const ConstantInt *CI = dyn_cast(CV)) { - if (CI->getType()->isInteger(1)) { + if (CI->getType()->isIntegerTy(1)) { Out << (CI->getZExtValue() ? "true" : "false"); return; } @@ -1223,7 +1237,6 @@ class AssemblyWriter { TypePrinting TypePrinter; AssemblyAnnotationWriter *AnnotationWriter; std::vector NumberedTypes; - SmallVector MDNames; public: inline AssemblyWriter(formatted_raw_ostream &o, SlotTracker &Mac, @@ -1231,8 +1244,6 @@ public: AssemblyAnnotationWriter *AAW) : Out(o), Machine(Mac), TheModule(M), AnnotationWriter(AAW) { AddModuleTypesToPrinter(TypePrinter, NumberedTypes, M); - if (M) - M->getMDKindNames(MDNames); } void printMDNodeBody(const MDNode *MD); @@ -1252,15 +1263,14 @@ public: void printArgument(const Argument *FA, Attributes Attrs); void printBasicBlock(const BasicBlock *BB); void printInstruction(const Instruction &I); -private: +private: // printInfoComment - Print a little comment after the instruction indicating // which slot it occupies. void printInfoComment(const Value &V); }; } // end of anonymous namespace - void AssemblyWriter::writeOperand(const Value *Operand, bool PrintType) { if (Operand == 0) { Out << ""; @@ -1689,11 +1699,15 @@ void AssemblyWriter::printBasicBlock(const BasicBlock *BB) { if (AnnotationWriter) AnnotationWriter->emitBasicBlockEndAnnot(BB, Out); } - /// printInfoComment - Print a little comment after the instruction indicating /// which slot it occupies. /// void AssemblyWriter::printInfoComment(const Value &V) { + if (AnnotationWriter) { + AnnotationWriter->printInfoComment(V, Out); + return; + } + if (V.getType()->isVoidTy()) return; Out.PadToColumn(50); @@ -1834,8 +1848,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { // Out << ' '; if (!FTy->isVarArg() && - (!isa(RetTy) || - !isa(cast(RetTy)->getElementType()))) { + (!RetTy->isPointerTy() || + !cast(RetTy)->getElementType()->isFunctionTy())) { TypePrinter.print(RetTy, Out); Out << ' '; writeOperand(Operand, false); @@ -1880,8 +1894,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) { // Out << ' '; if (!FTy->isVarArg() && - (!isa(RetTy) || - !isa(cast(RetTy)->getElementType()))) { + (!RetTy->isPointerTy() || + !cast(RetTy)->getElementType()->isFunctionTy())) { TypePrinter.print(RetTy, Out); Out << ' '; writeOperand(Operand, false); @@ -1972,12 +1986,20 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } // Print Metadata info. - if (!MDNames.empty()) { - SmallVector, 4> InstMD; - I.getAllMetadata(InstMD); - for (unsigned i = 0, e = InstMD.size(); i != e; ++i) - Out << ", !" << MDNames[InstMD[i].first] - << " !" << Machine.getMetadataSlot(InstMD[i].second); + SmallVector, 4> InstMD; + I.getAllMetadata(InstMD); + if (!InstMD.empty()) { + SmallVector MDNames; + I.getType()->getContext().getMDKindNames(MDNames); + for (unsigned i = 0, e = InstMD.size(); i != e; ++i) { + unsigned Kind = InstMD[i].first; + if (Kind < MDNames.size()) { + Out << ", !" << MDNames[Kind]; + } else { + Out << ", !"; + } + Out << " !" << Machine.getMetadataSlot(InstMD[i].second); + } } printInfoComment(I); } diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index a371c6f92e..a000aee2ab 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -70,6 +70,11 @@ std::string Attribute::getAsString(Attributes Attrs) { Result += "noimplicitfloat "; if (Attrs & Attribute::Naked) Result += "naked "; + if (Attrs & Attribute::StackAlignment) { + Result += "alignstack("; + Result += utostr(Attribute::getStackAlignmentFromAttrs(Attrs)); + Result += ") "; + } if (Attrs & Attribute::Alignment) { Result += "align "; Result += utostr(Attribute::getAlignmentFromAttrs(Attrs)); @@ -84,11 +89,11 @@ std::string Attribute::getAsString(Attributes Attrs) { Attributes Attribute::typeIncompatible(const Type *Ty) { Attributes Incompatible = None; - if (!Ty->isInteger()) + if (!Ty->isIntegerTy()) // Attributes that only apply to integers. Incompatible |= SExt | ZExt; - if (!isa(Ty)) + if (!Ty->isPointerTy()) // Attributes that only apply to pointers. Incompatible |= ByVal | Nest | NoAlias | StructRet | NoCapture; diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index 5c117d8a18..549977c234 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -112,7 +112,7 @@ static Constant *FoldBitCast(Constant *V, const Type *DestTy) { IdxList.push_back(Zero); } else if (const SequentialType *STy = dyn_cast(ElTy)) { - if (isa(ElTy)) break; // Can't index into pointers! + if (ElTy->isPointerTy()) break; // Can't index into pointers! ElTy = STy->getElementType(); IdxList.push_back(Zero); } else { @@ -155,12 +155,12 @@ static Constant *FoldBitCast(Constant *V, const Type *DestTy) { // Handle integral constant input. if (ConstantInt *CI = dyn_cast(V)) { - if (DestTy->isInteger()) + if (DestTy->isIntegerTy()) // Integral -> Integral. This is a no-op because the bit widths must // be the same. Consequently, we just fold to V. return V; - if (DestTy->isFloatingPoint()) + if (DestTy->isFloatingPointTy()) return ConstantFP::get(DestTy->getContext(), APFloat(CI->getValue(), !DestTy->isPPC_FP128Ty())); @@ -189,7 +189,7 @@ static Constant *FoldBitCast(Constant *V, const Type *DestTy) { /// static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart, unsigned ByteSize) { - assert(isa(C->getType()) && + assert(C->getType()->isIntegerTy() && (cast(C->getType())->getBitWidth() & 7) == 0 && "Non-byte sized integer input"); unsigned CSize = cast(C->getType())->getBitWidth()/8; @@ -334,11 +334,7 @@ static Constant *getFoldedSizeOf(const Type *Ty, const Type *DestTy, Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true); return ConstantExpr::getNUWMul(E, N); } - if (const VectorType *VTy = dyn_cast(Ty)) { - Constant *N = ConstantInt::get(DestTy, VTy->getNumElements()); - Constant *E = getFoldedSizeOf(VTy->getElementType(), DestTy, true); - return ConstantExpr::getNUWMul(E, N); - } + if (const StructType *STy = dyn_cast(Ty)) if (!STy->isPacked()) { unsigned NumElems = STy->getNumElements(); @@ -361,10 +357,26 @@ static Constant *getFoldedSizeOf(const Type *Ty, const Type *DestTy, } } + if (const UnionType *UTy = dyn_cast(Ty)) { + unsigned NumElems = UTy->getNumElements(); + // Check for a union with all members having the same size. + Constant *MemberSize = + getFoldedSizeOf(UTy->getElementType(0), DestTy, true); + bool AllSame = true; + for (unsigned i = 1; i != NumElems; ++i) + if (MemberSize != + getFoldedSizeOf(UTy->getElementType(i), DestTy, true)) { + AllSame = false; + break; + } + if (AllSame) + return MemberSize; + } + // Pointer size doesn't depend on the pointee type, so canonicalize them // to an arbitrary pointee. if (const PointerType *PTy = dyn_cast(Ty)) - if (!PTy->getElementType()->isInteger(1)) + if (!PTy->getElementType()->isIntegerTy(1)) return getFoldedSizeOf(PointerType::get(IntegerType::get(PTy->getContext(), 1), PTy->getAddressSpace()), @@ -426,10 +438,28 @@ static Constant *getFoldedAlignOf(const Type *Ty, const Type *DestTy, return MemberAlign; } + if (const UnionType *UTy = dyn_cast(Ty)) { + // Union alignment is the maximum alignment of any member. + // Without target data, we can't compare much, but we can check to see + // if all the members have the same alignment. + unsigned NumElems = UTy->getNumElements(); + // Check for a union with all members having the same alignment. + Constant *MemberAlign = + getFoldedAlignOf(UTy->getElementType(0), DestTy, true); + bool AllSame = true; + for (unsigned i = 1; i != NumElems; ++i) + if (MemberAlign != getFoldedAlignOf(UTy->getElementType(i), DestTy, true)) { + AllSame = false; + break; + } + if (AllSame) + return MemberAlign; + } + // Pointer alignment doesn't depend on the pointee type, so canonicalize them // to an arbitrary pointee. if (const PointerType *PTy = dyn_cast(Ty)) - if (!PTy->getElementType()->isInteger(1)) + if (!PTy->getElementType()->isIntegerTy(1)) return getFoldedAlignOf(PointerType::get(IntegerType::get(PTy->getContext(), 1), @@ -464,13 +494,7 @@ static Constant *getFoldedOffsetOf(const Type *Ty, Constant *FieldNo, Constant *E = getFoldedSizeOf(ATy->getElementType(), DestTy, true); return ConstantExpr::getNUWMul(E, N); } - if (const VectorType *VTy = dyn_cast(Ty)) { - Constant *N = ConstantExpr::getCast(CastInst::getCastOpcode(FieldNo, false, - DestTy, false), - FieldNo, DestTy); - Constant *E = getFoldedSizeOf(VTy->getElementType(), DestTy, true); - return ConstantExpr::getNUWMul(E, N); - } + if (const StructType *STy = dyn_cast(Ty)) if (!STy->isPacked()) { unsigned NumElems = STy->getNumElements(); @@ -551,7 +575,7 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, // operating on each element. In the cast of bitcasts, the element // count may be mismatched; don't attempt to handle that here. if (ConstantVector *CV = dyn_cast(V)) - if (isa(DestTy) && + if (DestTy->isVectorTy() && cast(DestTy)->getNumElements() == CV->getType()->getNumElements()) { std::vector res; @@ -629,12 +653,12 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, ConstantInt *CI = cast(CE->getOperand(2)); if (CI->isOne() && STy->getNumElements() == 2 && - STy->getElementType(0)->isInteger(1)) { + STy->getElementType(0)->isIntegerTy(1)) { return getFoldedAlignOf(STy->getElementType(1), DestTy, false); } } // Handle an offsetof-like expression. - if (isa(Ty) || isa(Ty) || isa(Ty)){ + if (Ty->isStructTy() || Ty->isArrayTy() || Ty->isVectorTy()){ if (Constant *C = getFoldedOffsetOf(Ty, CE->getOperand(2), DestTy, false)) return C; @@ -885,6 +909,8 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg, unsigned numOps; if (const ArrayType *AR = dyn_cast(AggTy)) numOps = AR->getNumElements(); + else if (AggTy->isUnionTy()) + numOps = 1; else numOps = cast(AggTy)->getNumElements(); @@ -901,6 +927,10 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg, if (const StructType* ST = dyn_cast(AggTy)) return ConstantStruct::get(ST->getContext(), Ops, ST->isPacked()); + if (const UnionType* UT = dyn_cast(AggTy)) { + assert(Ops.size() == 1 && "Union can only contain a single value!"); + return ConstantUnion::get(UT, Ops[0]); + } return ConstantArray::get(cast(AggTy), Ops); } @@ -1099,6 +1129,10 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, return ConstantExpr::getLShr(C1, C2); break; } + } else if (isa(C1)) { + // If C1 is a ConstantInt and C2 is not, swap the operands. + if (Instruction::isCommutative(Opcode)) + return ConstantExpr::get(Opcode, C2, C1); } // At this point we know neither constant is an UndefValue. @@ -1358,35 +1392,12 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, } else if (isa(C2)) { // If C2 is a constant expr and C1 isn't, flop them around and fold the // other way if possible. - switch (Opcode) { - case Instruction::Add: - case Instruction::FAdd: - case Instruction::Mul: - case Instruction::FMul: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - // No change of opcode required. + if (Instruction::isCommutative(Opcode)) return ConstantFoldBinaryInstruction(Opcode, C2, C1); - - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: - case Instruction::Sub: - case Instruction::FSub: - case Instruction::SDiv: - case Instruction::UDiv: - case Instruction::FDiv: - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - default: // These instructions cannot be flopped around. - break; - } } // i1 can be simplified in many cases. - if (C1->getType()->isInteger(1)) { + if (C1->getType()->isIntegerTy(1)) { switch (Opcode) { case Instruction::Add: case Instruction::Sub: @@ -1421,7 +1432,7 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, /// isZeroSizedType - This type is zero sized if its an array or structure of /// zero sized types. The only leaf zero sized type is an empty structure. static bool isMaybeZeroSizedType(const Type *Ty) { - if (isa(Ty)) return true; // Can't say. + if (Ty->isOpaqueTy()) return true; // Can't say. if (const StructType *STy = dyn_cast(Ty)) { // If all of elements have zero size, this does too. @@ -1452,10 +1463,10 @@ static int IdxCompare(Constant *C1, Constant *C2, const Type *ElTy) { // Ok, we have two differing integer indices. Sign extend them to be the same // type. Long is always big enough, so we use it. - if (!C1->getType()->isInteger(64)) + if (!C1->getType()->isIntegerTy(64)) C1 = ConstantExpr::getSExt(C1, Type::getInt64Ty(C1->getContext())); - if (!C2->getType()->isInteger(64)) + if (!C2->getType()->isIntegerTy(64)) C2 = ConstantExpr::getSExt(C2, Type::getInt64Ty(C1->getContext())); if (C1 == C2) return 0; // They are equal @@ -1661,7 +1672,7 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2, // If the cast is not actually changing bits, and the second operand is a // null pointer, do the comparison with the pre-casted value. if (V2->isNullValue() && - (isa(CE1->getType()) || CE1->getType()->isInteger())) { + (CE1->getType()->isPointerTy() || CE1->getType()->isIntegerTy())) { if (CE1->getOpcode() == Instruction::ZExt) isSigned = false; if (CE1->getOpcode() == Instruction::SExt) isSigned = true; return evaluateICmpRelation(CE1Op0, @@ -1807,7 +1818,7 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, // Handle some degenerate cases first if (isa(C1) || isa(C2)) - return UndefValue::get(ResultTy); + return ConstantInt::get(ResultTy, CmpInst::isTrueWhenEqual(pred)); // No compile-time operations on this type yet. if (C1->getType()->isPPC_FP128Ty()) @@ -1836,7 +1847,7 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, } // If the comparison is a comparison between two i1's, simplify it. - if (C1->getType()->isInteger(1)) { + if (C1->getType()->isIntegerTy(1)) { switch(pred) { case ICmpInst::ICMP_EQ: if (isa(C2)) @@ -1908,7 +1919,7 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, return ConstantInt::get(ResultTy, R==APFloat::cmpGreaterThan || R==APFloat::cmpEqual); } - } else if (isa(C1->getType())) { + } else if (C1->getType()->isVectorTy()) { SmallVector C1Elts, C2Elts; C1->getVectorElements(C1Elts); C2->getVectorElements(C2Elts); @@ -1925,7 +1936,7 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, return ConstantVector::get(&ResElts[0], ResElts.size()); } - if (C1->getType()->isFloatingPoint()) { + if (C1->getType()->isFloatingPointTy()) { int Result = -1; // -1 = unknown, 0 = known false, 1 = known true. switch (evaluateFCmpRelation(C1, C2)) { default: llvm_unreachable("Unknown relation!"); @@ -2059,7 +2070,7 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, if (ConstantExpr *CE2 = dyn_cast(C2)) { Constant *CE2Op0 = CE2->getOperand(0); if (CE2->getOpcode() == Instruction::BitCast && - isa(CE2->getType())==isa(CE2Op0->getType())) { + CE2->getType()->isVectorTy() == CE2Op0->getType()->isVectorTy()) { Constant *Inverse = ConstantExpr::getBitCast(C1, CE2Op0->getType()); return ConstantExpr::getICmp(pred, Inverse, CE2Op0); } @@ -2067,8 +2078,8 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, // If the left hand side is an extension, try eliminating it. if (ConstantExpr *CE1 = dyn_cast(C1)) { - if (CE1->getOpcode() == Instruction::SExt || - CE1->getOpcode() == Instruction::ZExt) { + if ((CE1->getOpcode() == Instruction::SExt && ICmpInst::isSigned(pred)) || + (CE1->getOpcode() == Instruction::ZExt && !ICmpInst::isSigned(pred))){ Constant *CE1Op0 = CE1->getOperand(0); Constant *CE1Inverse = ConstantExpr::getTrunc(CE1, CE1Op0->getType()); if (CE1Inverse == CE1Op0) { @@ -2086,27 +2097,8 @@ Constant *llvm::ConstantFoldCompareInstruction(unsigned short pred, // If C2 is a constant expr and C1 isn't, flip them around and fold the // other way if possible. // Also, if C1 is null and C2 isn't, flip them around. - switch (pred) { - case ICmpInst::ICMP_EQ: - case ICmpInst::ICMP_NE: - // No change of predicate required. - return ConstantExpr::getICmp(pred, C2, C1); - - case ICmpInst::ICMP_ULT: - case ICmpInst::ICMP_SLT: - case ICmpInst::ICMP_UGT: - case ICmpInst::ICMP_SGT: - case ICmpInst::ICMP_ULE: - case ICmpInst::ICMP_SLE: - case ICmpInst::ICMP_UGE: - case ICmpInst::ICMP_SGE: - // Change the predicate as necessary to swap the operands. - pred = ICmpInst::getSwappedPredicate((ICmpInst::Predicate)pred); - return ConstantExpr::getICmp(pred, C2, C1); - - default: // These predicates cannot be flopped around. - break; - } + pred = ICmpInst::getSwappedPredicate((ICmpInst::Predicate)pred); + return ConstantExpr::getICmp(pred, C2, C1); } } return 0; @@ -2178,7 +2170,7 @@ Constant *llvm::ConstantFoldGetElementPtr(Constant *C, I != E; ++I) LastTy = *I; - if ((LastTy && isa(LastTy)) || Idx0->isNullValue()) { + if ((LastTy && LastTy->isArrayTy()) || Idx0->isNullValue()) { SmallVector NewIndices; NewIndices.reserve(NumIdx + CE->getNumOperands()); for (unsigned i = 1, e = CE->getNumOperands()-1; i != e; ++i) @@ -2260,10 +2252,10 @@ Constant *llvm::ConstantFoldGetElementPtr(Constant *C, // Before adding, extend both operands to i64 to avoid // overflow trouble. - if (!PrevIdx->getType()->isInteger(64)) + if (!PrevIdx->getType()->isIntegerTy(64)) PrevIdx = ConstantExpr::getSExt(PrevIdx, Type::getInt64Ty(Div->getContext())); - if (!Div->getType()->isInteger(64)) + if (!Div->getType()->isIntegerTy(64)) Div = ConstantExpr::getSExt(Div, Type::getInt64Ty(Div->getContext())); diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 2250626051..10f88794f5 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -229,7 +229,7 @@ Constant::PossibleRelocationsTy Constant::getRelocationInfo() const { /// This handles breaking down a vector undef into undef elements, etc. For /// constant exprs and other cases we can't handle, we return an empty vector. void Constant::getVectorElements(SmallVectorImpl &Elts) const { - assert(isa(getType()) && "Not a vector constant!"); + assert(getType()->isVectorTy() && "Not a vector constant!"); if (const ConstantVector *CV = dyn_cast(this)) { for (unsigned i = 0, e = CV->getNumOperands(); i != e; ++i) @@ -404,13 +404,13 @@ ConstantFP* ConstantFP::getNegativeZero(const Type* Ty) { Constant* ConstantFP::getZeroValueForNegation(const Type* Ty) { if (const VectorType *PTy = dyn_cast(Ty)) - if (PTy->getElementType()->isFloatingPoint()) { + if (PTy->getElementType()->isFloatingPointTy()) { std::vector zeros(PTy->getNumElements(), getNegativeZero(PTy->getElementType())); return ConstantVector::get(PTy, zeros); } - if (Ty->isFloatingPoint()) + if (Ty->isFloatingPointTy()) return getNegativeZero(Ty); return Constant::getNullValue(Ty); @@ -585,6 +585,27 @@ Constant* ConstantStruct::get(LLVMContext &Context, return get(Context, std::vector(Vals, Vals+NumVals), Packed); } +ConstantUnion::ConstantUnion(const UnionType *T, Constant* V) + : Constant(T, ConstantUnionVal, + OperandTraits::op_end(this) - 1, 1) { + Use *OL = OperandList; + assert(T->getElementTypeIndex(V->getType()) >= 0 && + "Initializer for union element isn't a member of union type!"); + *OL = V; +} + +// ConstantUnion accessors. +Constant* ConstantUnion::get(const UnionType* T, Constant* V) { + LLVMContextImpl* pImpl = T->getContext().pImpl; + + // Create a ConstantAggregateZero value if all elements are zeros... + if (!V->isNullValue()) + return pImpl->UnionConstants.getOrCreate(T, V); + + return ConstantAggregateZero::get(T); +} + + ConstantVector::ConstantVector(const VectorType *T, const std::vector &V) : Constant(T, ConstantVectorVal, @@ -640,13 +661,13 @@ Constant* ConstantVector::get(Constant* const* Vals, unsigned NumVals) { } Constant* ConstantExpr::getNSWNeg(Constant* C) { - assert(C->getType()->isIntOrIntVector() && + assert(C->getType()->isIntOrIntVectorTy() && "Cannot NEG a nonintegral value!"); return getNSWSub(ConstantFP::getZeroValueForNegation(C->getType()), C); } Constant* ConstantExpr::getNUWNeg(Constant* C) { - assert(C->getType()->isIntOrIntVector() && + assert(C->getType()->isIntOrIntVectorTy() && "Cannot NEG a nonintegral value!"); return getNUWSub(ConstantFP::getZeroValueForNegation(C->getType()), C); } @@ -923,7 +944,7 @@ bool ConstantFP::isValueValidForType(const Type *Ty, const APFloat& Val) { // Factory Function Implementation ConstantAggregateZero* ConstantAggregateZero::get(const Type* Ty) { - assert((isa(Ty) || isa(Ty) || isa(Ty)) && + assert((Ty->isStructTy() || Ty->isArrayTy() || Ty->isVectorTy()) && "Cannot create an aggregate zero of non-aggregate type!"); LLVMContextImpl *pImpl = Ty->getContext().pImpl; @@ -948,7 +969,7 @@ void ConstantArray::destroyConstant() { /// if the elements of the array are all ConstantInt's. bool ConstantArray::isString() const { // Check the element type for i8... - if (!getType()->getElementType()->isInteger(8)) + if (!getType()->getElementType()->isIntegerTy(8)) return false; // Check the elements to make sure they are all integers, not constant // expressions. @@ -963,7 +984,7 @@ bool ConstantArray::isString() const { /// null bytes except its terminator. bool ConstantArray::isCString() const { // Check the element type for i8... - if (!getType()->getElementType()->isInteger(8)) + if (!getType()->getElementType()->isIntegerTy(8)) return false; // Last element must be a null. @@ -1008,6 +1029,13 @@ void ConstantStruct::destroyConstant() { destroyConstantImpl(); } +// destroyConstant - Remove the constant from the constant table... +// +void ConstantUnion::destroyConstant() { + getType()->getContext().pImpl->UnionConstants.remove(this); + destroyConstantImpl(); +} + // destroyConstant - Remove the constant from the constant table... // void ConstantVector::destroyConstant() { @@ -1211,18 +1239,18 @@ Constant *ConstantExpr::getTruncOrBitCast(Constant *C, const Type *Ty) { } Constant *ConstantExpr::getPointerCast(Constant *S, const Type *Ty) { - assert(isa(S->getType()) && "Invalid cast"); - assert((Ty->isInteger() || isa(Ty)) && "Invalid cast"); + assert(S->getType()->isPointerTy() && "Invalid cast"); + assert((Ty->isIntegerTy() || Ty->isPointerTy()) && "Invalid cast"); - if (Ty->isInteger()) + if (Ty->isIntegerTy()) return getCast(Instruction::PtrToInt, S, Ty); return getCast(Instruction::BitCast, S, Ty); } Constant *ConstantExpr::getIntegerCast(Constant *C, const Type *Ty, bool isSigned) { - assert(C->getType()->isIntOrIntVector() && - Ty->isIntOrIntVector() && "Invalid cast"); + assert(C->getType()->isIntOrIntVectorTy() && + Ty->isIntOrIntVectorTy() && "Invalid cast"); unsigned SrcBits = C->getType()->getScalarSizeInBits(); unsigned DstBits = Ty->getScalarSizeInBits(); Instruction::CastOps opcode = @@ -1233,7 +1261,7 @@ Constant *ConstantExpr::getIntegerCast(Constant *C, const Type *Ty, } Constant *ConstantExpr::getFPCast(Constant *C, const Type *Ty) { - assert(C->getType()->isFPOrFPVector() && Ty->isFPOrFPVector() && + assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && "Invalid cast"); unsigned SrcBits = C->getType()->getScalarSizeInBits(); unsigned DstBits = Ty->getScalarSizeInBits(); @@ -1250,8 +1278,8 @@ Constant *ConstantExpr::getTrunc(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isIntOrIntVector() && "Trunc operand must be integer"); - assert(Ty->isIntOrIntVector() && "Trunc produces only integral"); + assert(C->getType()->isIntOrIntVectorTy() && "Trunc operand must be integer"); + assert(Ty->isIntOrIntVectorTy() && "Trunc produces only integral"); assert(C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&& "SrcTy must be larger than DestTy for Trunc!"); @@ -1264,8 +1292,8 @@ Constant *ConstantExpr::getSExt(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isIntOrIntVector() && "SExt operand must be integral"); - assert(Ty->isIntOrIntVector() && "SExt produces only integer"); + assert(C->getType()->isIntOrIntVectorTy() && "SExt operand must be integral"); + assert(Ty->isIntOrIntVectorTy() && "SExt produces only integer"); assert(C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "SrcTy must be smaller than DestTy for SExt!"); @@ -1278,8 +1306,8 @@ Constant *ConstantExpr::getZExt(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isIntOrIntVector() && "ZEXt operand must be integral"); - assert(Ty->isIntOrIntVector() && "ZExt produces only integer"); + assert(C->getType()->isIntOrIntVectorTy() && "ZEXt operand must be integral"); + assert(Ty->isIntOrIntVectorTy() && "ZExt produces only integer"); assert(C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "SrcTy must be smaller than DestTy for ZExt!"); @@ -1292,7 +1320,7 @@ Constant *ConstantExpr::getFPTrunc(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isFPOrFPVector() && Ty->isFPOrFPVector() && + assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&& "This is an illegal floating point truncation!"); return getFoldedCast(Instruction::FPTrunc, C, Ty); @@ -1304,7 +1332,7 @@ Constant *ConstantExpr::getFPExtend(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isFPOrFPVector() && Ty->isFPOrFPVector() && + assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "This is an illegal floating point extension!"); return getFoldedCast(Instruction::FPExt, C, Ty); @@ -1316,7 +1344,7 @@ Constant *ConstantExpr::getUIToFP(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isIntOrIntVector() && Ty->isFPOrFPVector() && + assert(C->getType()->isIntOrIntVectorTy() && Ty->isFPOrFPVectorTy() && "This is an illegal uint to floating point cast!"); return getFoldedCast(Instruction::UIToFP, C, Ty); } @@ -1327,7 +1355,7 @@ Constant *ConstantExpr::getSIToFP(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isIntOrIntVector() && Ty->isFPOrFPVector() && + assert(C->getType()->isIntOrIntVectorTy() && Ty->isFPOrFPVectorTy() && "This is an illegal sint to floating point cast!"); return getFoldedCast(Instruction::SIToFP, C, Ty); } @@ -1338,7 +1366,7 @@ Constant *ConstantExpr::getFPToUI(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isFPOrFPVector() && Ty->isIntOrIntVector() && + assert(C->getType()->isFPOrFPVectorTy() && Ty->isIntOrIntVectorTy() && "This is an illegal floating point to uint cast!"); return getFoldedCast(Instruction::FPToUI, C, Ty); } @@ -1349,20 +1377,20 @@ Constant *ConstantExpr::getFPToSI(Constant *C, const Type *Ty) { bool toVec = Ty->getTypeID() == Type::VectorTyID; #endif assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); - assert(C->getType()->isFPOrFPVector() && Ty->isIntOrIntVector() && + assert(C->getType()->isFPOrFPVectorTy() && Ty->isIntOrIntVectorTy() && "This is an illegal floating point to sint cast!"); return getFoldedCast(Instruction::FPToSI, C, Ty); } Constant *ConstantExpr::getPtrToInt(Constant *C, const Type *DstTy) { - assert(isa(C->getType()) && "PtrToInt source must be pointer"); - assert(DstTy->isInteger() && "PtrToInt destination must be integral"); + assert(C->getType()->isPointerTy() && "PtrToInt source must be pointer"); + assert(DstTy->isIntegerTy() && "PtrToInt destination must be integral"); return getFoldedCast(Instruction::PtrToInt, C, DstTy); } Constant *ConstantExpr::getIntToPtr(Constant *C, const Type *DstTy) { - assert(C->getType()->isInteger() && "IntToPtr source must be integral"); - assert(isa(DstTy) && "IntToPtr destination must be a pointer"); + assert(C->getType()->isIntegerTy() && "IntToPtr source must be integral"); + assert(DstTy->isPointerTy() && "IntToPtr destination must be a pointer"); return getFoldedCast(Instruction::IntToPtr, C, DstTy); } @@ -1421,7 +1449,7 @@ Constant *ConstantExpr::getCompareTy(unsigned short predicate, Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, unsigned Flags) { // API compatibility: Adjust integer opcodes to floating-point opcodes. - if (C1->getType()->isFPOrFPVector()) { + if (C1->getType()->isFPOrFPVectorTy()) { if (Opcode == Instruction::Add) Opcode = Instruction::FAdd; else if (Opcode == Instruction::Sub) Opcode = Instruction::FSub; else if (Opcode == Instruction::Mul) Opcode = Instruction::FMul; @@ -1432,51 +1460,51 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, case Instruction::Sub: case Instruction::Mul: assert(C1->getType() == C2->getType() && "Op types should be identical!"); - assert(C1->getType()->isIntOrIntVector() && + assert(C1->getType()->isIntOrIntVectorTy() && "Tried to create an integer operation on a non-integer type!"); break; case Instruction::FAdd: case Instruction::FSub: case Instruction::FMul: assert(C1->getType() == C2->getType() && "Op types should be identical!"); - assert(C1->getType()->isFPOrFPVector() && + assert(C1->getType()->isFPOrFPVectorTy() && "Tried to create a floating-point operation on a " "non-floating-point type!"); break; case Instruction::UDiv: case Instruction::SDiv: assert(C1->getType() == C2->getType() && "Op types should be identical!"); - assert(C1->getType()->isIntOrIntVector() && + assert(C1->getType()->isIntOrIntVectorTy() && "Tried to create an arithmetic operation on a non-arithmetic type!"); break; case Instruction::FDiv: assert(C1->getType() == C2->getType() && "Op types should be identical!"); - assert(C1->getType()->isFPOrFPVector() && + assert(C1->getType()->isFPOrFPVectorTy() && "Tried to create an arithmetic operation on a non-arithmetic type!"); break; case Instruction::URem: case Instruction::SRem: assert(C1->getType() == C2->getType() && "Op types should be identical!"); - assert(C1->getType()->isIntOrIntVector() && + assert(C1->getType()->isIntOrIntVectorTy() && "Tried to create an arithmetic operation on a non-arithmetic type!"); break; case Instruction::FRem: assert(C1->getType() == C2->getType() && "Op types should be identical!"); - assert(C1->getType()->isFPOrFPVector() && + assert(C1->getType()->isFPOrFPVectorTy() && "Tried to create an arithmetic operation on a non-arithmetic type!"); break; case Instruction::And: case Instruction::Or: case Instruction::Xor: assert(C1->getType() == C2->getType() && "Op types should be identical!"); - assert(C1->getType()->isIntOrIntVector() && + assert(C1->getType()->isIntOrIntVectorTy() && "Tried to create a logical operation on a non-integral type!"); break; case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: assert(C1->getType() == C2->getType() && "Op types should be identical!"); - assert(C1->getType()->isIntOrIntVector() && + assert(C1->getType()->isIntOrIntVectorTy() && "Tried to create a shift operation on a non-integer type!"); break; default: @@ -1564,7 +1592,7 @@ Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C, (Constant**)Idxs, NumIdx)) return FC; // Fold a few common cases... - assert(isa(C->getType()) && + assert(C->getType()->isPointerTy() && "Non-pointer type for constant GetElementPtr expression"); // Look up the constant in the table first to ensure uniqueness std::vector ArgVec; @@ -1591,7 +1619,7 @@ Constant *ConstantExpr::getInBoundsGetElementPtrTy(const Type *ReqTy, (Constant**)Idxs, NumIdx)) return FC; // Fold a few common cases... - assert(isa(C->getType()) && + assert(C->getType()->isPointerTy() && "Non-pointer type for constant GetElementPtr expression"); // Look up the constant in the table first to ensure uniqueness std::vector ArgVec; @@ -1699,9 +1727,9 @@ Constant *ConstantExpr::getExtractElementTy(const Type *ReqTy, Constant *Val, } Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) { - assert(isa(Val->getType()) && + assert(Val->getType()->isVectorTy() && "Tried to create extractelement operation on non-vector type!"); - assert(Idx->getType()->isInteger(32) && + assert(Idx->getType()->isIntegerTy(32) && "Extractelement index must be i32 type!"); return getExtractElementTy(cast(Val->getType())->getElementType(), Val, Idx); @@ -1723,11 +1751,11 @@ Constant *ConstantExpr::getInsertElementTy(const Type *ReqTy, Constant *Val, Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, Constant *Idx) { - assert(isa(Val->getType()) && + assert(Val->getType()->isVectorTy() && "Tried to create insertelement operation on non-vector type!"); assert(Elt->getType() == cast(Val->getType())->getElementType() && "Insertelement types must match!"); - assert(Idx->getType()->isInteger(32) && + assert(Idx->getType()->isIntegerTy(32) && "Insertelement index must be i32 type!"); return getInsertElementTy(Val->getType(), Val, Elt, Idx); } @@ -1811,9 +1839,9 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg, Constant* ConstantExpr::getNeg(Constant* C) { // API compatibility: Adjust integer opcodes to floating-point opcodes. - if (C->getType()->isFPOrFPVector()) + if (C->getType()->isFPOrFPVectorTy()) return getFNeg(C); - assert(C->getType()->isIntOrIntVector() && + assert(C->getType()->isIntOrIntVectorTy() && "Cannot NEG a nonintegral value!"); return get(Instruction::Sub, ConstantFP::getZeroValueForNegation(C->getType()), @@ -1821,7 +1849,7 @@ Constant* ConstantExpr::getNeg(Constant* C) { } Constant* ConstantExpr::getFNeg(Constant* C) { - assert(C->getType()->isFPOrFPVector() && + assert(C->getType()->isFPOrFPVectorTy() && "Cannot FNEG a non-floating-point value!"); return get(Instruction::FSub, ConstantFP::getZeroValueForNegation(C->getType()), @@ -1829,7 +1857,7 @@ Constant* ConstantExpr::getFNeg(Constant* C) { } Constant* ConstantExpr::getNot(Constant* C) { - assert(C->getType()->isIntOrIntVector() && + assert(C->getType()->isIntOrIntVectorTy() && "Cannot NOT a nonintegral value!"); return get(Instruction::Xor, C, Constant::getAllOnesValue(C->getType())); } @@ -2083,6 +2111,56 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, destroyConstant(); } +void ConstantUnion::replaceUsesOfWithOnConstant(Value *From, Value *To, + Use *U) { + assert(isa(To) && "Cannot make Constant refer to non-constant!"); + Constant *ToC = cast(To); + + assert(U == OperandList && "Union constants can only have one use!"); + assert(getNumOperands() == 1 && "Union constants can only have one use!"); + assert(getOperand(0) == From && "ReplaceAllUsesWith broken!"); + + std::pair Lookup; + Lookup.first.first = getType(); + Lookup.second = this; + Lookup.first.second = ToC; + + LLVMContext &Context = getType()->getContext(); + LLVMContextImpl *pImpl = Context.pImpl; + + Constant *Replacement = 0; + if (ToC->isNullValue()) { + Replacement = ConstantAggregateZero::get(getType()); + } else { + // Check to see if we have this union type already. + bool Exists; + LLVMContextImpl::UnionConstantsTy::MapTy::iterator I = + pImpl->UnionConstants.InsertOrGetItem(Lookup, Exists); + + if (Exists) { + Replacement = I->second; + } else { + // Okay, the new shape doesn't exist in the system yet. Instead of + // creating a new constant union, inserting it, replaceallusesof'ing the + // old with the new, then deleting the old... just update the current one + // in place! + pImpl->UnionConstants.MoveConstantToNewSlot(this, I); + + // Update to the new value. + setOperand(0, ToC); + return; + } + } + + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement. + uncheckedReplaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); diff --git a/lib/VMCore/ConstantsContext.h b/lib/VMCore/ConstantsContext.h index 08224e4488..c798ba2664 100644 --- a/lib/VMCore/ConstantsContext.h +++ b/lib/VMCore/ConstantsContext.h @@ -341,6 +341,13 @@ struct ConstantTraits< std::vector > { } }; +template<> +struct ConstantTraits { + static unsigned uses(Constant * const & v) { + return 1; + } +}; + template struct ConstantCreator { static ConstantClass *create(const TypeClass *Ty, const ValType &V) { @@ -470,6 +477,14 @@ struct ConstantKeyData { } }; +template<> +struct ConstantKeyData { + typedef Constant* ValType; + static ValType getValType(ConstantUnion *CU) { + return cast(CU->getOperand(0)); + } +}; + // ConstantPointerNull does not take extra "value" argument... template struct ConstantCreator { diff --git a/lib/VMCore/Core.cpp b/lib/VMCore/Core.cpp index 1755cd213e..f4f65c5409 100644 --- a/lib/VMCore/Core.cpp +++ b/lib/VMCore/Core.cpp @@ -55,6 +55,15 @@ void LLVMContextDispose(LLVMContextRef C) { delete unwrap(C); } +unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char* Name, + unsigned SLen) { + return unwrap(C)->getMDKindID(StringRef(Name, SLen)); +} + +unsigned LLVMGetMDKindID(const char* Name, unsigned SLen) { + return LLVMGetMDKindIDInContext(LLVMGetGlobalContext(), Name, SLen); +} + /*===-- Operations on modules ---------------------------------------------===*/ @@ -141,6 +150,8 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) { return LLVMFunctionTypeKind; case Type::StructTyID: return LLVMStructTypeKind; + case Type::UnionTyID: + return LLVMUnionTypeKind; case Type::ArrayTyID: return LLVMArrayTypeKind; case Type::PointerTyID: @@ -299,6 +310,35 @@ LLVMBool LLVMIsPackedStruct(LLVMTypeRef StructTy) { return unwrap(StructTy)->isPacked(); } +/*--.. Operations on union types ..........................................--*/ + +LLVMTypeRef LLVMUnionTypeInContext(LLVMContextRef C, LLVMTypeRef *ElementTypes, + unsigned ElementCount) { + SmallVector Tys; + for (LLVMTypeRef *I = ElementTypes, + *E = ElementTypes + ElementCount; I != E; ++I) + Tys.push_back(unwrap(*I)); + + return wrap(UnionType::get(&Tys[0], Tys.size())); +} + +LLVMTypeRef LLVMUnionType(LLVMTypeRef *ElementTypes, + unsigned ElementCount, int Packed) { + return LLVMUnionTypeInContext(LLVMGetGlobalContext(), ElementTypes, + ElementCount); +} + +unsigned LLVMCountUnionElementTypes(LLVMTypeRef UnionTy) { + return unwrap(UnionTy)->getNumElements(); +} + +void LLVMGetUnionElementTypes(LLVMTypeRef UnionTy, LLVMTypeRef *Dest) { + UnionType *Ty = unwrap(UnionTy); + for (FunctionType::param_iterator I = Ty->element_begin(), + E = Ty->element_end(); I != E; ++I) + *Dest++ = wrap(*I); +} + /*--.. Operations on array, pointer, and vector types (sequence types) .....--*/ LLVMTypeRef LLVMArrayType(LLVMTypeRef ElementType, unsigned ElementCount) { @@ -394,6 +434,18 @@ void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal) { unwrap(OldVal)->replaceAllUsesWith(unwrap(NewVal)); } +int LLVMHasMetadata(LLVMValueRef Inst) { + return unwrap(Inst)->hasMetadata(); +} + +LLVMValueRef LLVMGetMetadata(LLVMValueRef Inst, unsigned KindID) { + return wrap(unwrap(Inst)->getMetadata(KindID)); +} + +void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef MD) { + unwrap(Inst)->setMetadata(KindID, MD? unwrap(MD) : NULL); +} + /*--.. Conversion functions ................................................--*/ #define LLVM_DEFINE_VALUE_CAST(name) \ @@ -404,7 +456,7 @@ void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal) { LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DEFINE_VALUE_CAST) /*--.. Operations on Uses ..................................................--*/ -LLVMUseIteratorRef LLVMGetFirstUse(LLVMValueRef Val) { +LLVMUseRef LLVMGetFirstUse(LLVMValueRef Val) { Value *V = unwrap(Val); Value::use_iterator I = V->use_begin(); if (I == V->use_end()) @@ -412,16 +464,19 @@ LLVMUseIteratorRef LLVMGetFirstUse(LLVMValueRef Val) { return wrap(&(I.getUse())); } -LLVMUseIteratorRef LLVMGetNextUse(LLVMUseIteratorRef UR) { - return wrap(unwrap(UR)->getNext()); +LLVMUseRef LLVMGetNextUse(LLVMUseRef U) { + Use *Next = unwrap(U)->getNext(); + if (Next) + return wrap(Next); + return 0; } -LLVMValueRef LLVMGetUser(LLVMUseIteratorRef UR) { - return wrap(unwrap(UR)->getUser()); +LLVMValueRef LLVMGetUser(LLVMUseRef U) { + return wrap(unwrap(U)->getUser()); } -LLVMValueRef LLVMGetUsedValue(LLVMUseIteratorRef UR) { - return wrap(unwrap(UR)->get()); +LLVMValueRef LLVMGetUsedValue(LLVMUseRef U) { + return wrap(unwrap(U)->get()); } /*--.. Operations on Users .................................................--*/ @@ -462,6 +517,26 @@ LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty) { wrap(ConstantPointerNull::get(unwrap(Ty))); } +/*--.. Operations on metadata nodes ........................................--*/ + +LLVMValueRef LLVMMDStringInContext(LLVMContextRef C, const char *Str, + unsigned SLen) { + return wrap(MDString::get(*unwrap(C), StringRef(Str, SLen))); +} + +LLVMValueRef LLVMMDString(const char *Str, unsigned SLen) { + return LLVMMDStringInContext(LLVMGetGlobalContext(), Str, SLen); +} + +LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals, + unsigned Count) { + return wrap(MDNode::get(*unwrap(C), unwrap(Vals, Count), Count)); +} + +LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count) { + return LLVMMDNodeInContext(LLVMGetGlobalContext(), Vals, Count); +} + /*--.. Operations on scalar constants ......................................--*/ LLVMValueRef LLVMConstInt(LLVMTypeRef IntTy, unsigned long long N, @@ -536,11 +611,13 @@ LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count, return LLVMConstStructInContext(LLVMGetGlobalContext(), ConstantVals, Count, Packed); } - LLVMValueRef LLVMConstVector(LLVMValueRef *ScalarConstantVals, unsigned Size) { return wrap(ConstantVector::get( unwrap(ScalarConstantVals, Size), Size)); } +LLVMValueRef LLVMConstUnion(LLVMTypeRef Ty, LLVMValueRef Val) { + return wrap(ConstantUnion::get(unwrap(Ty), unwrap(Val))); +} /*--.. Constant expressions ................................................--*/ @@ -561,6 +638,17 @@ LLVMValueRef LLVMConstNeg(LLVMValueRef ConstantVal) { unwrap(ConstantVal))); } +LLVMValueRef LLVMConstNSWNeg(LLVMValueRef ConstantVal) { + return wrap(ConstantExpr::getNSWNeg( + unwrap(ConstantVal))); +} + +LLVMValueRef LLVMConstNUWNeg(LLVMValueRef ConstantVal) { + return wrap(ConstantExpr::getNUWNeg( + unwrap(ConstantVal))); +} + + LLVMValueRef LLVMConstFNeg(LLVMValueRef ConstantVal) { return wrap(ConstantExpr::getFNeg( unwrap(ConstantVal))); @@ -584,6 +672,13 @@ LLVMValueRef LLVMConstNSWAdd(LLVMValueRef LHSConstant, unwrap(RHSConstant))); } +LLVMValueRef LLVMConstNUWAdd(LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return wrap(ConstantExpr::getNUWAdd( + unwrap(LHSConstant), + unwrap(RHSConstant))); +} + LLVMValueRef LLVMConstFAdd(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) { return wrap(ConstantExpr::getFAdd( unwrap(LHSConstant), @@ -596,6 +691,20 @@ LLVMValueRef LLVMConstSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) { unwrap(RHSConstant))); } +LLVMValueRef LLVMConstNSWSub(LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return wrap(ConstantExpr::getNSWSub( + unwrap(LHSConstant), + unwrap(RHSConstant))); +} + +LLVMValueRef LLVMConstNUWSub(LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return wrap(ConstantExpr::getNUWSub( + unwrap(LHSConstant), + unwrap(RHSConstant))); +} + LLVMValueRef LLVMConstFSub(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) { return wrap(ConstantExpr::getFSub(unwrap(LHSConstant), unwrap(RHSConstant))); @@ -607,6 +716,20 @@ LLVMValueRef LLVMConstMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) { unwrap(RHSConstant))); } +LLVMValueRef LLVMConstNSWMul(LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return wrap(ConstantExpr::getNSWMul( + unwrap(LHSConstant), + unwrap(RHSConstant))); +} + +LLVMValueRef LLVMConstNUWMul(LLVMValueRef LHSConstant, + LLVMValueRef RHSConstant) { + return wrap(ConstantExpr::getNUWMul( + unwrap(LHSConstant), + unwrap(RHSConstant))); +} + LLVMValueRef LLVMConstFMul(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) { return wrap(ConstantExpr::getFMul( unwrap(LHSConstant), @@ -893,6 +1016,10 @@ LLVMValueRef LLVMConstInlineAsm(LLVMTypeRef Ty, const char *AsmString, Constraints, HasSideEffects, IsAlignStack)); } +LLVMValueRef LLVMBlockAddress(LLVMValueRef F, LLVMBasicBlockRef BB) { + return wrap(BlockAddress::get(unwrap(F), unwrap(BB))); +} + /*--.. Operations on global variables, functions, and aliases (globals) ....--*/ LLVMModuleRef LLVMGetGlobalParent(LLVMValueRef Global) { @@ -1029,6 +1156,14 @@ LLVMValueRef LLVMAddGlobal(LLVMModuleRef M, LLVMTypeRef Ty, const char *Name) { GlobalValue::ExternalLinkage, 0, Name)); } +LLVMValueRef LLVMAddGlobalInAddressSpace(LLVMModuleRef M, LLVMTypeRef Ty, + const char *Name, + unsigned AddressSpace) { + return wrap(new GlobalVariable(*unwrap(M), unwrap(Ty), false, + GlobalValue::ExternalLinkage, 0, Name, 0, + false, AddressSpace)); +} + LLVMValueRef LLVMGetNamedGlobal(LLVMModuleRef M, const char *Name) { return wrap(unwrap(M)->getNamedGlobal(Name)); } @@ -1184,14 +1319,14 @@ void LLVMSetGC(LLVMValueRef Fn, const char *GC) { void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA) { Function *Func = unwrap(Fn); const AttrListPtr PAL = Func->getAttributes(); - const AttrListPtr PALnew = PAL.addAttr(0, PA); + const AttrListPtr PALnew = PAL.addAttr(~0U, PA); Func->setAttributes(PALnew); } void LLVMRemoveFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA) { Function *Func = unwrap(Fn); const AttrListPtr PAL = Func->getAttributes(); - const AttrListPtr PALnew = PAL.removeAttr(0, PA); + const AttrListPtr PALnew = PAL.removeAttr(~0U, PA); Func->setAttributes(PALnew); } @@ -1532,6 +1667,21 @@ void LLVMDisposeBuilder(LLVMBuilderRef Builder) { delete unwrap(Builder); } +/*--.. Metadata builders ...................................................--*/ + +void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L) { + unwrap(Builder)->SetCurrentDebugLocation(L? unwrap(L) : NULL); +} + +LLVMValueRef LLVMGetCurrentDebugLocation(LLVMBuilderRef Builder) { + return wrap(unwrap(Builder)->getCurrentDebugLocation()); +} + +void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst) { + unwrap(Builder)->SetInstDebugLocation(unwrap(Inst)); +} + + /*--.. Instruction builders ................................................--*/ LLVMValueRef LLVMBuildRetVoid(LLVMBuilderRef B) { @@ -1561,6 +1711,11 @@ LLVMValueRef LLVMBuildSwitch(LLVMBuilderRef B, LLVMValueRef V, return wrap(unwrap(B)->CreateSwitch(unwrap(V), unwrap(Else), NumCases)); } +LLVMValueRef LLVMBuildIndirectBr(LLVMBuilderRef B, LLVMValueRef Addr, + unsigned NumDests) { + return wrap(unwrap(B)->CreateIndirectBr(unwrap(Addr), NumDests)); +} + LLVMValueRef LLVMBuildInvoke(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch, @@ -1583,6 +1738,10 @@ void LLVMAddCase(LLVMValueRef Switch, LLVMValueRef OnVal, unwrap(Switch)->addCase(unwrap(OnVal), unwrap(Dest)); } +void LLVMAddDestination(LLVMValueRef IndirectBr, LLVMBasicBlockRef Dest) { + unwrap(IndirectBr)->addDestination(unwrap(Dest)); +} + /*--.. Arithmetic ..........................................................--*/ LLVMValueRef LLVMBuildAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, @@ -1595,6 +1754,11 @@ LLVMValueRef LLVMBuildNSWAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RH return wrap(unwrap(B)->CreateNSWAdd(unwrap(LHS), unwrap(RHS), Name)); } +LLVMValueRef LLVMBuildNUWAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name) { + return wrap(unwrap(B)->CreateNUWAdd(unwrap(LHS), unwrap(RHS), Name)); +} + LLVMValueRef LLVMBuildFAdd(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name) { return wrap(unwrap(B)->CreateFAdd(unwrap(LHS), unwrap(RHS), Name)); @@ -1605,6 +1769,16 @@ LLVMValueRef LLVMBuildSub(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, return wrap(unwrap(B)->CreateSub(unwrap(LHS), unwrap(RHS), Name)); } +LLVMValueRef LLVMBuildNSWSub(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name) { + return wrap(unwrap(B)->CreateNSWSub(unwrap(LHS), unwrap(RHS), Name)); +} + +LLVMValueRef LLVMBuildNUWSub(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name) { + return wrap(unwrap(B)->CreateNUWSub(unwrap(LHS), unwrap(RHS), Name)); +} + LLVMValueRef LLVMBuildFSub(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name) { return wrap(unwrap(B)->CreateFSub(unwrap(LHS), unwrap(RHS), Name)); @@ -1615,6 +1789,16 @@ LLVMValueRef LLVMBuildMul(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, return wrap(unwrap(B)->CreateMul(unwrap(LHS), unwrap(RHS), Name)); } +LLVMValueRef LLVMBuildNSWMul(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name) { + return wrap(unwrap(B)->CreateNSWMul(unwrap(LHS), unwrap(RHS), Name)); +} + +LLVMValueRef LLVMBuildNUWMul(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name) { + return wrap(unwrap(B)->CreateNUWMul(unwrap(LHS), unwrap(RHS), Name)); +} + LLVMValueRef LLVMBuildFMul(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, const char *Name) { return wrap(unwrap(B)->CreateFMul(unwrap(LHS), unwrap(RHS), Name)); @@ -1685,10 +1869,27 @@ LLVMValueRef LLVMBuildXor(LLVMBuilderRef B, LLVMValueRef LHS, LLVMValueRef RHS, return wrap(unwrap(B)->CreateXor(unwrap(LHS), unwrap(RHS), Name)); } +LLVMValueRef LLVMBuildBinOp(LLVMBuilderRef B, LLVMOpcode Op, + LLVMValueRef LHS, LLVMValueRef RHS, + const char *Name) { + return wrap(unwrap(B)->CreateBinOp(Instruction::BinaryOps(Op), unwrap(LHS), + unwrap(RHS), Name)); +} + LLVMValueRef LLVMBuildNeg(LLVMBuilderRef B, LLVMValueRef V, const char *Name) { return wrap(unwrap(B)->CreateNeg(unwrap(V), Name)); } +LLVMValueRef LLVMBuildNSWNeg(LLVMBuilderRef B, LLVMValueRef V, + const char *Name) { + return wrap(unwrap(B)->CreateNSWNeg(unwrap(V), Name)); +} + +LLVMValueRef LLVMBuildNUWNeg(LLVMBuilderRef B, LLVMValueRef V, + const char *Name) { + return wrap(unwrap(B)->CreateNUWNeg(unwrap(V), Name)); +} + LLVMValueRef LLVMBuildFNeg(LLVMBuilderRef B, LLVMValueRef V, const char *Name) { return wrap(unwrap(B)->CreateFNeg(unwrap(V), Name)); } @@ -1856,6 +2057,12 @@ LLVMValueRef LLVMBuildTruncOrBitCast(LLVMBuilderRef B, LLVMValueRef Val, Name)); } +LLVMValueRef LLVMBuildCast(LLVMBuilderRef B, LLVMOpcode Op, LLVMValueRef Val, + LLVMTypeRef DestTy, const char *Name) { + return wrap(unwrap(B)->CreateCast(Instruction::CastOps(Op), unwrap(Val), + unwrap(DestTy), Name)); +} + LLVMValueRef LLVMBuildPointerCast(LLVMBuilderRef B, LLVMValueRef Val, LLVMTypeRef DestTy, const char *Name) { return wrap(unwrap(B)->CreatePointerCast(unwrap(Val), unwrap(DestTy), Name)); diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp index f00f6ee11f..dbc283e49a 100644 --- a/lib/VMCore/Function.cpp +++ b/lib/VMCore/Function.cpp @@ -73,35 +73,35 @@ unsigned Argument::getArgNo() const { /// hasByValAttr - Return true if this argument has the byval attribute on it /// in its containing function. bool Argument::hasByValAttr() const { - if (!isa(getType())) return false; + if (!getType()->isPointerTy()) return false; return getParent()->paramHasAttr(getArgNo()+1, Attribute::ByVal); } /// hasNestAttr - Return true if this argument has the nest attribute on /// it in its containing function. bool Argument::hasNestAttr() const { - if (!isa(getType())) return false; + if (!getType()->isPointerTy()) return false; return getParent()->paramHasAttr(getArgNo()+1, Attribute::Nest); } /// hasNoAliasAttr - Return true if this argument has the noalias attribute on /// it in its containing function. bool Argument::hasNoAliasAttr() const { - if (!isa(getType())) return false; + if (!getType()->isPointerTy()) return false; return getParent()->paramHasAttr(getArgNo()+1, Attribute::NoAlias); } /// hasNoCaptureAttr - Return true if this argument has the nocapture attribute /// on it in its containing function. bool Argument::hasNoCaptureAttr() const { - if (!isa(getType())) return false; + if (!getType()->isPointerTy()) return false; return getParent()->paramHasAttr(getArgNo()+1, Attribute::NoCapture); } /// hasSRetAttr - Return true if this argument has the sret attribute on /// it in its containing function. bool Argument::hasStructRetAttr() const { - if (!isa(getType())) return false; + if (!getType()->isPointerTy()) return false; if (this != getParent()->arg_begin()) return false; // StructRet param must be first param return getParent()->paramHasAttr(1, Attribute::StructRet); @@ -155,7 +155,7 @@ Function::Function(const FunctionType *Ty, LinkageTypes Linkage, : GlobalValue(PointerType::getUnqual(Ty), Value::FunctionVal, 0, 0, Linkage, name) { assert(FunctionType::isValidReturnType(getReturnType()) && - !isa(getReturnType()) && "invalid return type"); + !getReturnType()->isOpaqueTy() && "invalid return type"); SymTab = new ValueSymbolTable(); // If the function has arguments, mark them as lazily built. diff --git a/lib/VMCore/Globals.cpp b/lib/VMCore/Globals.cpp index f149c446b4..489ec650e0 100644 --- a/lib/VMCore/Globals.cpp +++ b/lib/VMCore/Globals.cpp @@ -44,10 +44,10 @@ static bool removeDeadUsersOfConstant(const Constant *C) { } bool GlobalValue::isMaterializable() const { - return getParent()->isMaterializable(this); + return getParent() && getParent()->isMaterializable(this); } bool GlobalValue::isDematerializable() const { - return getParent()->isDematerializable(this); + return getParent() && getParent()->isDematerializable(this); } bool GlobalValue::Materialize(std::string *ErrInfo) { return getParent()->Materialize(this, ErrInfo); diff --git a/lib/VMCore/IRBuilder.cpp b/lib/VMCore/IRBuilder.cpp index 4bc3cbb2d6..9f2786e4e3 100644 --- a/lib/VMCore/IRBuilder.cpp +++ b/lib/VMCore/IRBuilder.cpp @@ -19,7 +19,7 @@ using namespace llvm; /// CreateGlobalString - Make a new global variable with an initializer that -/// has array of i8 type filled in the nul terminated string value +/// has array of i8 type filled in with the nul terminated string value /// specified. If Name is specified, it is the name of the global variable /// created. Value *IRBuilderBase::CreateGlobalString(const char *Str, const Twine &Name) { diff --git a/lib/VMCore/InlineAsm.cpp b/lib/VMCore/InlineAsm.cpp index ec21773d83..6355834880 100644 --- a/lib/VMCore/InlineAsm.cpp +++ b/lib/VMCore/InlineAsm.cpp @@ -220,7 +220,7 @@ bool InlineAsm::Verify(const FunctionType *Ty, StringRef ConstStr) { if (!Ty->getReturnType()->isVoidTy()) return false; break; case 1: - if (isa(Ty->getReturnType())) return false; + if (Ty->getReturnType()->isStructTy()) return false; break; default: const StructType *STy = dyn_cast(Ty->getReturnType()); diff --git a/lib/VMCore/Instructions.cpp b/lib/VMCore/Instructions.cpp index 4ec82953c1..8f4763f5a4 100644 --- a/lib/VMCore/Instructions.cpp +++ b/lib/VMCore/Instructions.cpp @@ -562,7 +562,7 @@ static Instruction* createFree(Value* Source, Instruction *InsertBefore, BasicBlock *InsertAtEnd) { assert(((!InsertBefore && InsertAtEnd) || (InsertBefore && !InsertAtEnd)) && "createFree needs either InsertBefore or InsertAtEnd"); - assert(isa(Source->getType()) && + assert(Source->getType()->isPointerTy() && "Can not free something of nonpointer type!"); BasicBlock* BB = InsertBefore ? InsertBefore->getParent() : InsertAtEnd; @@ -787,7 +787,7 @@ BasicBlock *UnreachableInst::getSuccessorV(unsigned idx) const { void BranchInst::AssertOK() { if (isConditional()) - assert(getCondition()->getType()->isInteger(1) && + assert(getCondition()->getType()->isIntegerTy(1) && "May only branch on boolean predicates!"); } @@ -892,7 +892,7 @@ static Value *getAISize(LLVMContext &Context, Value *Amt) { else { assert(!isa(Amt) && "Passed basic block into allocation size parameter! Use other ctor"); - assert(Amt->getType()->isInteger(32) && + assert(Amt->getType()->isIntegerTy(32) && "Allocation array size is not a 32-bit integer!"); } return Amt; @@ -989,7 +989,7 @@ bool AllocaInst::isStaticAlloca() const { //===----------------------------------------------------------------------===// void LoadInst::AssertOK() { - assert(isa(getOperand(0)->getType()) && + assert(getOperand(0)->getType()->isPointerTy() && "Ptr must have pointer type."); } @@ -1103,7 +1103,7 @@ void LoadInst::setAlignment(unsigned Align) { void StoreInst::AssertOK() { assert(getOperand(0) && getOperand(1) && "Both operands must be non-null!"); - assert(isa(getOperand(1)->getType()) && + assert(getOperand(1)->getType()->isPointerTy() && "Ptr must have pointer type!"); assert(getOperand(0)->getType() == cast(getOperand(1)->getType())->getElementType() @@ -1285,7 +1285,7 @@ static const Type* getIndexedTypeInternal(const Type *Ptr, IndexTy const *Idxs, unsigned CurIdx = 1; for (; CurIdx != NumIdx; ++CurIdx) { const CompositeType *CT = dyn_cast(Agg); - if (!CT || isa(CT)) return 0; + if (!CT || CT->isPointerTy()) return 0; IndexTy Index = Idxs[CurIdx]; if (!CT->indexValid(Index)) return 0; Agg = CT->getTypeAtIndex(Index); @@ -1391,7 +1391,7 @@ ExtractElementInst::ExtractElementInst(Value *Val, Value *Index, bool ExtractElementInst::isValidOperands(const Value *Val, const Value *Index) { - if (!isa(Val->getType()) || !Index->getType()->isInteger(32)) + if (!Val->getType()->isVectorTy() || !Index->getType()->isIntegerTy(32)) return false; return true; } @@ -1432,13 +1432,13 @@ InsertElementInst::InsertElementInst(Value *Vec, Value *Elt, Value *Index, bool InsertElementInst::isValidOperands(const Value *Vec, const Value *Elt, const Value *Index) { - if (!isa(Vec->getType())) + if (!Vec->getType()->isVectorTy()) return false; // First operand of insertelement must be vector type. if (Elt->getType() != cast(Vec->getType())->getElementType()) return false;// Second operand of insertelement must be vector element type. - if (!Index->getType()->isInteger(32)) + if (!Index->getType()->isIntegerTy(32)) return false; // Third operand of insertelement must be i32. return true; } @@ -1485,12 +1485,12 @@ ShuffleVectorInst::ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2, const Value *Mask) { - if (!isa(V1->getType()) || V1->getType() != V2->getType()) + if (!V1->getType()->isVectorTy() || V1->getType() != V2->getType()) return false; const VectorType *MaskTy = dyn_cast(Mask->getType()); if (!isa(Mask) || MaskTy == 0 || - !MaskTy->getElementType()->isInteger(32)) + !MaskTy->getElementType()->isIntegerTy(32)) return false; return true; } @@ -1602,7 +1602,7 @@ const Type* ExtractValueInst::getIndexedType(const Type *Agg, unsigned CurIdx = 0; for (; CurIdx != NumIdx; ++CurIdx) { const CompositeType *CT = dyn_cast(Agg); - if (!CT || isa(CT) || isa(CT)) return 0; + if (!CT || CT->isPointerTy() || CT->isVectorTy()) return 0; unsigned Index = Idxs[CurIdx]; if (!CT->indexValid(Index)) return 0; Agg = CT->getTypeAtIndex(Index); @@ -1632,7 +1632,7 @@ const Type* ExtractValueInst::getIndexedType(const Type *Agg, static BinaryOperator::BinaryOps AdjustIType(BinaryOperator::BinaryOps iType, const Type *Ty) { // API compatibility: Adjust integer opcodes to floating-point opcodes. - if (Ty->isFPOrFPVector()) { + if (Ty->isFPOrFPVectorTy()) { if (iType == BinaryOperator::Add) iType = BinaryOperator::FAdd; else if (iType == BinaryOperator::Sub) iType = BinaryOperator::FSub; else if (iType == BinaryOperator::Mul) iType = BinaryOperator::FMul; @@ -1678,14 +1678,14 @@ void BinaryOperator::init(BinaryOps iType) { case Mul: assert(getType() == LHS->getType() && "Arithmetic operation should return same type as operands!"); - assert(getType()->isIntOrIntVector() && + assert(getType()->isIntOrIntVectorTy() && "Tried to create an integer operation on a non-integer type!"); break; case FAdd: case FSub: case FMul: assert(getType() == LHS->getType() && "Arithmetic operation should return same type as operands!"); - assert(getType()->isFPOrFPVector() && + assert(getType()->isFPOrFPVectorTy() && "Tried to create a floating-point operation on a " "non-floating-point type!"); break; @@ -1693,28 +1693,28 @@ void BinaryOperator::init(BinaryOps iType) { case SDiv: assert(getType() == LHS->getType() && "Arithmetic operation should return same type as operands!"); - assert((getType()->isInteger() || (isa(getType()) && - cast(getType())->getElementType()->isInteger())) && + assert((getType()->isIntegerTy() || (getType()->isVectorTy() && + cast(getType())->getElementType()->isIntegerTy())) && "Incorrect operand type (not integer) for S/UDIV"); break; case FDiv: assert(getType() == LHS->getType() && "Arithmetic operation should return same type as operands!"); - assert(getType()->isFPOrFPVector() && + assert(getType()->isFPOrFPVectorTy() && "Incorrect operand type (not floating point) for FDIV"); break; case URem: case SRem: assert(getType() == LHS->getType() && "Arithmetic operation should return same type as operands!"); - assert((getType()->isInteger() || (isa(getType()) && - cast(getType())->getElementType()->isInteger())) && + assert((getType()->isIntegerTy() || (getType()->isVectorTy() && + cast(getType())->getElementType()->isIntegerTy())) && "Incorrect operand type (not integer) for S/UREM"); break; case FRem: assert(getType() == LHS->getType() && "Arithmetic operation should return same type as operands!"); - assert(getType()->isFPOrFPVector() && + assert(getType()->isFPOrFPVectorTy() && "Incorrect operand type (not floating point) for FREM"); break; case Shl: @@ -1722,18 +1722,18 @@ void BinaryOperator::init(BinaryOps iType) { case AShr: assert(getType() == LHS->getType() && "Shift operation should return same type as operands!"); - assert((getType()->isInteger() || - (isa(getType()) && - cast(getType())->getElementType()->isInteger())) && + assert((getType()->isIntegerTy() || + (getType()->isVectorTy() && + cast(getType())->getElementType()->isIntegerTy())) && "Tried to create a shift operation on a non-integral type!"); break; case And: case Or: case Xor: assert(getType() == LHS->getType() && "Logical operation should return same type as operands!"); - assert((getType()->isInteger() || - (isa(getType()) && - cast(getType())->getElementType()->isInteger())) && + assert((getType()->isIntegerTy() || + (getType()->isVectorTy() && + cast(getType())->getElementType()->isIntegerTy())) && "Tried to create a logical operation on a non-integral type!"); break; default: @@ -1960,7 +1960,8 @@ bool CastInst::isIntegerCast() const { case Instruction::Trunc: return true; case Instruction::BitCast: - return getOperand(0)->getType()->isInteger() && getType()->isInteger(); + return getOperand(0)->getType()->isIntegerTy() && + getType()->isIntegerTy(); } } @@ -1976,8 +1977,8 @@ bool CastInst::isLosslessCast() const { return true; // Pointer to pointer is always lossless. - if (isa(SrcTy)) - return isa(DstTy); + if (SrcTy->isPointerTy()) + return DstTy->isPointerTy(); return false; // Other types have no identity values } @@ -2093,25 +2094,25 @@ unsigned CastInst::isEliminableCastPair( // no-op cast in second op implies firstOp as long as the DestTy // is integer and we are not converting between a vector and a // non vector type. - if (!isa(SrcTy) && DstTy->isInteger()) + if (!SrcTy->isVectorTy() && DstTy->isIntegerTy()) return firstOp; return 0; case 4: // no-op cast in second op implies firstOp as long as the DestTy // is floating point. - if (DstTy->isFloatingPoint()) + if (DstTy->isFloatingPointTy()) return firstOp; return 0; case 5: // no-op cast in first op implies secondOp as long as the SrcTy // is an integer. - if (SrcTy->isInteger()) + if (SrcTy->isIntegerTy()) return secondOp; return 0; case 6: // no-op cast in first op implies secondOp as long as the SrcTy // is a floating point. - if (SrcTy->isFloatingPoint()) + if (SrcTy->isFloatingPointTy()) return secondOp; return 0; case 7: { @@ -2147,12 +2148,12 @@ unsigned CastInst::isEliminableCastPair( case 11: // bitcast followed by ptrtoint is allowed as long as the bitcast // is a pointer to pointer cast. - if (isa(SrcTy) && isa(MidTy)) + if (SrcTy->isPointerTy() && MidTy->isPointerTy()) return secondOp; return 0; case 12: // inttoptr, bitcast -> intptr if bitcast is a ptr to ptr cast - if (isa(MidTy) && isa(DstTy)) + if (MidTy->isPointerTy() && DstTy->isPointerTy()) return firstOp; return 0; case 13: { @@ -2273,11 +2274,11 @@ CastInst *CastInst::CreateTruncOrBitCast(Value *S, const Type *Ty, CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd) { - assert(isa(S->getType()) && "Invalid cast"); - assert((Ty->isInteger() || isa(Ty)) && + assert(S->getType()->isPointerTy() && "Invalid cast"); + assert((Ty->isIntegerTy() || Ty->isPointerTy()) && "Invalid cast"); - if (Ty->isInteger()) + if (Ty->isIntegerTy()) return Create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd); return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd); } @@ -2286,11 +2287,11 @@ CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty, CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty, const Twine &Name, Instruction *InsertBefore) { - assert(isa(S->getType()) && "Invalid cast"); - assert((Ty->isInteger() || isa(Ty)) && + assert(S->getType()->isPointerTy() && "Invalid cast"); + assert((Ty->isIntegerTy() || Ty->isPointerTy()) && "Invalid cast"); - if (Ty->isInteger()) + if (Ty->isIntegerTy()) return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore); return Create(Instruction::BitCast, S, Ty, Name, InsertBefore); } @@ -2298,7 +2299,7 @@ CastInst *CastInst::CreatePointerCast(Value *S, const Type *Ty, CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty, bool isSigned, const Twine &Name, Instruction *InsertBefore) { - assert(C->getType()->isIntOrIntVector() && Ty->isIntOrIntVector() && + assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() && "Invalid integer cast"); unsigned SrcBits = C->getType()->getScalarSizeInBits(); unsigned DstBits = Ty->getScalarSizeInBits(); @@ -2312,7 +2313,7 @@ CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty, CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty, bool isSigned, const Twine &Name, BasicBlock *InsertAtEnd) { - assert(C->getType()->isIntOrIntVector() && Ty->isIntOrIntVector() && + assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() && "Invalid cast"); unsigned SrcBits = C->getType()->getScalarSizeInBits(); unsigned DstBits = Ty->getScalarSizeInBits(); @@ -2326,7 +2327,7 @@ CastInst *CastInst::CreateIntegerCast(Value *C, const Type *Ty, CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty, const Twine &Name, Instruction *InsertBefore) { - assert(C->getType()->isFPOrFPVector() && Ty->isFPOrFPVector() && + assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && "Invalid cast"); unsigned SrcBits = C->getType()->getScalarSizeInBits(); unsigned DstBits = Ty->getScalarSizeInBits(); @@ -2339,7 +2340,7 @@ CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty, CastInst *CastInst::CreateFPCast(Value *C, const Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd) { - assert(C->getType()->isFPOrFPVector() && Ty->isFPOrFPVector() && + assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && "Invalid cast"); unsigned SrcBits = C->getType()->getScalarSizeInBits(); unsigned DstBits = Ty->getScalarSizeInBits(); @@ -2363,21 +2364,21 @@ bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) { unsigned DestBits = DestTy->getScalarSizeInBits(); // 0 for ptr // Run through the possibilities ... - if (DestTy->isInteger()) { // Casting to integral - if (SrcTy->isInteger()) { // Casting from integral + if (DestTy->isIntegerTy()) { // Casting to integral + if (SrcTy->isIntegerTy()) { // Casting from integral return true; - } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt + } else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt return true; } else if (const VectorType *PTy = dyn_cast(SrcTy)) { // Casting from vector return DestBits == PTy->getBitWidth(); } else { // Casting from something else - return isa(SrcTy); + return SrcTy->isPointerTy(); } - } else if (DestTy->isFloatingPoint()) { // Casting to floating pt - if (SrcTy->isInteger()) { // Casting from integral + } else if (DestTy->isFloatingPointTy()) { // Casting to floating pt + if (SrcTy->isIntegerTy()) { // Casting from integral return true; - } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt + } else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt return true; } else if (const VectorType *PTy = dyn_cast(SrcTy)) { // Casting from vector @@ -2393,10 +2394,10 @@ bool CastInst::isCastable(const Type *SrcTy, const Type *DestTy) { } else { // Casting from something else return DestPTy->getBitWidth() == SrcBits; } - } else if (isa(DestTy)) { // Casting to pointer - if (isa(SrcTy)) { // Casting from pointer + } else if (DestTy->isPointerTy()) { // Casting to pointer + if (SrcTy->isPointerTy()) { // Casting from pointer return true; - } else if (SrcTy->isInteger()) { // Casting from integral + } else if (SrcTy->isIntegerTy()) { // Casting from integral return true; } else { // Casting from something else return false; @@ -2425,8 +2426,8 @@ CastInst::getCastOpcode( "Only first class types are castable!"); // Run through the possibilities ... - if (DestTy->isInteger()) { // Casting to integral - if (SrcTy->isInteger()) { // Casting from integral + if (DestTy->isIntegerTy()) { // Casting to integral + if (SrcTy->isIntegerTy()) { // Casting from integral if (DestBits < SrcBits) return Trunc; // int -> smaller int else if (DestBits > SrcBits) { // its an extension @@ -2437,7 +2438,7 @@ CastInst::getCastOpcode( } else { return BitCast; // Same size, No-op cast } - } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt + } else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt if (DestIsSigned) return FPToSI; // FP -> sint else @@ -2448,17 +2449,17 @@ CastInst::getCastOpcode( PTy = NULL; return BitCast; // Same size, no-op cast } else { - assert(isa(SrcTy) && + assert(SrcTy->isPointerTy() && "Casting from a value that is not first-class type"); return PtrToInt; // ptr -> int } - } else if (DestTy->isFloatingPoint()) { // Casting to floating pt - if (SrcTy->isInteger()) { // Casting from integral + } else if (DestTy->isFloatingPointTy()) { // Casting to floating pt + if (SrcTy->isIntegerTy()) { // Casting from integral if (SrcIsSigned) return SIToFP; // sint -> FP else return UIToFP; // uint -> FP - } else if (SrcTy->isFloatingPoint()) { // Casting from floating pt + } else if (SrcTy->isFloatingPointTy()) { // Casting from floating pt if (DestBits < SrcBits) { return FPTrunc; // FP -> smaller FP } else if (DestBits > SrcBits) { @@ -2485,10 +2486,10 @@ CastInst::getCastOpcode( } else { assert(!"Illegal cast to vector (wrong type or size)"); } - } else if (isa(DestTy)) { - if (isa(SrcTy)) { + } else if (DestTy->isPointerTy()) { + if (SrcTy->isPointerTy()) { return BitCast; // ptr -> ptr - } else if (SrcTy->isInteger()) { + } else if (SrcTy->isIntegerTy()) { return IntToPtr; // int -> ptr } else { assert(!"Casting pointer to other than pointer or int"); @@ -2528,50 +2529,50 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy) { switch (op) { default: return false; // This is an input error case Instruction::Trunc: - return SrcTy->isIntOrIntVector() && - DstTy->isIntOrIntVector()&& SrcBitSize > DstBitSize; + return SrcTy->isIntOrIntVectorTy() && + DstTy->isIntOrIntVectorTy()&& SrcBitSize > DstBitSize; case Instruction::ZExt: - return SrcTy->isIntOrIntVector() && - DstTy->isIntOrIntVector()&& SrcBitSize < DstBitSize; + return SrcTy->isIntOrIntVectorTy() && + DstTy->isIntOrIntVectorTy()&& SrcBitSize < DstBitSize; case Instruction::SExt: - return SrcTy->isIntOrIntVector() && - DstTy->isIntOrIntVector()&& SrcBitSize < DstBitSize; + return SrcTy->isIntOrIntVectorTy() && + DstTy->isIntOrIntVectorTy()&& SrcBitSize < DstBitSize; case Instruction::FPTrunc: - return SrcTy->isFPOrFPVector() && - DstTy->isFPOrFPVector() && + return SrcTy->isFPOrFPVectorTy() && + DstTy->isFPOrFPVectorTy() && SrcBitSize > DstBitSize; case Instruction::FPExt: - return SrcTy->isFPOrFPVector() && - DstTy->isFPOrFPVector() && + return SrcTy->isFPOrFPVectorTy() && + DstTy->isFPOrFPVectorTy() && SrcBitSize < DstBitSize; case Instruction::UIToFP: case Instruction::SIToFP: if (const VectorType *SVTy = dyn_cast(SrcTy)) { if (const VectorType *DVTy = dyn_cast(DstTy)) { - return SVTy->getElementType()->isIntOrIntVector() && - DVTy->getElementType()->isFPOrFPVector() && + return SVTy->getElementType()->isIntOrIntVectorTy() && + DVTy->getElementType()->isFPOrFPVectorTy() && SVTy->getNumElements() == DVTy->getNumElements(); } } - return SrcTy->isIntOrIntVector() && DstTy->isFPOrFPVector(); + return SrcTy->isIntOrIntVectorTy() && DstTy->isFPOrFPVectorTy(); case Instruction::FPToUI: case Instruction::FPToSI: if (const VectorType *SVTy = dyn_cast(SrcTy)) { if (const VectorType *DVTy = dyn_cast(DstTy)) { - return SVTy->getElementType()->isFPOrFPVector() && - DVTy->getElementType()->isIntOrIntVector() && + return SVTy->getElementType()->isFPOrFPVectorTy() && + DVTy->getElementType()->isIntOrIntVectorTy() && SVTy->getNumElements() == DVTy->getNumElements(); } } - return SrcTy->isFPOrFPVector() && DstTy->isIntOrIntVector(); + return SrcTy->isFPOrFPVectorTy() && DstTy->isIntOrIntVectorTy(); case Instruction::PtrToInt: - return isa(SrcTy) && DstTy->isInteger(); + return SrcTy->isPointerTy() && DstTy->isIntegerTy(); case Instruction::IntToPtr: - return SrcTy->isInteger() && isa(DstTy); + return SrcTy->isIntegerTy() && DstTy->isPointerTy(); case Instruction::BitCast: // BitCast implies a no-op cast of type only. No bits change. // However, you can't cast pointers to anything but pointers. - if (isa(SrcTy) != isa(DstTy)) + if (SrcTy->isPointerTy() != DstTy->isPointerTy()) return false; // Now we know we're not dealing with a pointer/non-pointer mismatch. In all @@ -3149,7 +3150,7 @@ void SwitchInst::setSuccessorV(unsigned idx, BasicBlock *B) { //===----------------------------------------------------------------------===// void IndirectBrInst::init(Value *Address, unsigned NumDests) { - assert(Address && isa(Address->getType()) && + assert(Address && Address->getType()->isPointerTy() && "Address of indirectbr must be a pointer"); ReservedSpace = 1+NumDests; NumOperands = 1; diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index ccca789209..9887f28821 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -116,6 +116,10 @@ public: ConstantStruct, true /*largekey*/> StructConstantsTy; StructConstantsTy StructConstants; + typedef ConstantUniqueMap + UnionConstantsTy; + UnionConstantsTy UnionConstants; + typedef ConstantUniqueMap, VectorType, ConstantVector> VectorConstantsTy; VectorConstantsTy VectorConstants; @@ -159,12 +163,16 @@ public: TypeMap PointerTypes; TypeMap FunctionTypes; TypeMap StructTypes; + TypeMap UnionTypes; TypeMap IntegerTypes; // Opaque types are not structurally uniqued, so don't use TypeMap. typedef SmallPtrSet OpaqueTypesTy; OpaqueTypesTy OpaqueTypes; - + + /// Used as an abstract type that will never be resolved. + OpaqueType *const AlwaysOpaqueTy; + /// ValueHandles - This map keeps track of all of the value handles that are /// watching a Value*. The Value::HasValueHandle bit is used to know @@ -196,7 +204,12 @@ public: Int8Ty(C, 8), Int16Ty(C, 16), Int32Ty(C, 32), - Int64Ty(C, 64) { } + Int64Ty(C, 64), + AlwaysOpaqueTy(new OpaqueType(C)) { + // Make sure the AlwaysOpaqueTy stays alive as long as the Context. + AlwaysOpaqueTy->addRef(); + OpaqueTypes.insert(AlwaysOpaqueTy); + } ~LLVMContextImpl() { ExprConstants.freeConstants(); @@ -216,12 +229,28 @@ public: if (I->second->use_empty()) delete I->second; } - MDNodeSet.clear(); + AlwaysOpaqueTy->dropRef(); for (OpaqueTypesTy::iterator I = OpaqueTypes.begin(), E = OpaqueTypes.end(); I != E; ++I) { (*I)->AbstractTypeUsers.clear(); delete *I; } + // Destroy MDNode operands first. + for (FoldingSetIterator I = MDNodeSet.begin(), E = MDNodeSet.end(); + I != E;) { + MDNode *N = &(*I); + ++I; + N->replaceAllOperandsWithNull(); + } + while (!MDNodeSet.empty()) { + MDNode *N = &(*MDNodeSet.begin()); + N->destroy(); + } + // Destroy MDStrings. + for (StringMap::iterator I = MDStringCache.begin(), + E = MDStringCache.end(); I != E; ++I) { + delete I->second; + } } }; diff --git a/lib/VMCore/Makefile b/lib/VMCore/Makefile index bc5e77d22d..4395ecfda0 100644 --- a/lib/VMCore/Makefile +++ b/lib/VMCore/Makefile @@ -30,5 +30,5 @@ $(GENFILE): $(ObjDir)/Intrinsics.gen.tmp changed significantly. ) install-local:: $(GENFILE) - $(Echo) Installing $(PROJ_includedir)/llvm/Intrinsics.gen - $(Verb) $(DataInstall) $(GENFILE) $(PROJ_includedir)/llvm/Intrinsics.gen + $(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/Intrinsics.gen + $(Verb) $(DataInstall) $(GENFILE) $(DESTDIR)$(PROJ_includedir)/llvm/Intrinsics.gen diff --git a/lib/VMCore/Metadata.cpp b/lib/VMCore/Metadata.cpp index 07a5f3c539..a08c45480b 100644 --- a/lib/VMCore/Metadata.cpp +++ b/lib/VMCore/Metadata.cpp @@ -257,6 +257,13 @@ void MDNode::Profile(FoldingSetNodeID &ID) const { ID.AddPointer(getOperand(i)); } +// replaceAllOperandsWithNull - This is used while destroying llvm context to +// gracefully delete all nodes. This method replaces all operands with null. +void MDNode::replaceAllOperandsWithNull() { + for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op+NumOperands; + Op != E; ++Op) + replaceOperand(Op, 0); +} // Replace value from this node's operand list. void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) { diff --git a/lib/VMCore/Pass.cpp b/lib/VMCore/Pass.cpp index 2b0b23510a..a782e5a82e 100644 --- a/lib/VMCore/Pass.cpp +++ b/lib/VMCore/Pass.cpp @@ -194,6 +194,9 @@ PassManagerType BasicBlockPass::getPotentialPassManagerType() const { // namespace { class PassRegistrar { + /// Guards the contents of this class. + mutable sys::SmartMutex Lock; + /// PassInfoMap - Keep track of the passinfo object for each registered llvm /// pass. typedef std::map MapType; @@ -213,16 +216,19 @@ class PassRegistrar { public: const PassInfo *GetPassInfo(intptr_t TI) const { + sys::SmartScopedLock Guard(Lock); MapType::const_iterator I = PassInfoMap.find(TI); return I != PassInfoMap.end() ? I->second : 0; } const PassInfo *GetPassInfo(StringRef Arg) const { + sys::SmartScopedLock Guard(Lock); StringMapType::const_iterator I = PassInfoStringMap.find(Arg); return I != PassInfoStringMap.end() ? I->second : 0; } void RegisterPass(const PassInfo &PI) { + sys::SmartScopedLock Guard(Lock); bool Inserted = PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second; assert(Inserted && "Pass registered multiple times!"); Inserted=Inserted; @@ -230,6 +236,7 @@ public: } void UnregisterPass(const PassInfo &PI) { + sys::SmartScopedLock Guard(Lock); MapType::iterator I = PassInfoMap.find(PI.getTypeInfo()); assert(I != PassInfoMap.end() && "Pass registered but not in map!"); @@ -239,6 +246,7 @@ public: } void EnumerateWith(PassRegistrationListener *L) { + sys::SmartScopedLock Guard(Lock); for (MapType::const_iterator I = PassInfoMap.begin(), E = PassInfoMap.end(); I != E; ++I) L->passEnumerate(I->second); @@ -249,6 +257,7 @@ public: void RegisterAnalysisGroup(PassInfo *InterfaceInfo, const PassInfo *ImplementationInfo, bool isDefault) { + sys::SmartScopedLock Guard(Lock); AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo]; assert(AGI.Implementations.count(ImplementationInfo) == 0 && "Cannot add a pass to the same analysis group more than once!"); diff --git a/lib/VMCore/PassManager.cpp b/lib/VMCore/PassManager.cpp index a1d554e4ff..c4dfe1409b 100644 --- a/lib/VMCore/PassManager.cpp +++ b/lib/VMCore/PassManager.cpp @@ -1118,6 +1118,7 @@ bool BBPassManager::runOnFunction(Function &F) { for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { BasicBlockPass *BP = getContainedPass(Index); + bool LocalChanged = false; dumpPassInfo(BP, EXECUTION_MSG, ON_BASICBLOCK_MSG, I->getName()); dumpRequiredSet(BP); @@ -1129,11 +1130,12 @@ bool BBPassManager::runOnFunction(Function &F) { PassManagerPrettyStackEntry X(BP, *I); Timer *T = StartPassTimer(BP); - Changed |= BP->runOnBasicBlock(*I); + LocalChanged |= BP->runOnBasicBlock(*I); StopPassTimer(BP, T); } - if (Changed) + Changed |= LocalChanged; + if (LocalChanged) dumpPassInfo(BP, MODIFICATION_MSG, ON_BASICBLOCK_MSG, I->getName()); dumpPreservedSet(BP); @@ -1220,9 +1222,11 @@ void FunctionPassManager::add(Pass *P) { /// so, return true. /// bool FunctionPassManager::run(Function &F) { - std::string errstr; - if (F.Materialize(&errstr)) { - llvm_report_error("Error reading bitcode file: " + errstr); + if (F.isMaterializable()) { + std::string errstr; + if (F.Materialize(&errstr)) { + llvm_report_error("Error reading bitcode file: " + errstr); + } } return FPM->run(F); } @@ -1332,6 +1336,7 @@ bool FPPassManager::runOnFunction(Function &F) { for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { FunctionPass *FP = getContainedPass(Index); + bool LocalChanged = false; dumpPassInfo(FP, EXECUTION_MSG, ON_FUNCTION_MSG, F.getName()); dumpRequiredSet(FP); @@ -1342,11 +1347,12 @@ bool FPPassManager::runOnFunction(Function &F) { PassManagerPrettyStackEntry X(FP, F); Timer *T = StartPassTimer(FP); - Changed |= FP->runOnFunction(F); + LocalChanged |= FP->runOnFunction(F); StopPassTimer(FP, T); } - if (Changed) + Changed |= LocalChanged; + if (LocalChanged) dumpPassInfo(FP, MODIFICATION_MSG, ON_FUNCTION_MSG, F.getName()); dumpPreservedSet(FP); @@ -1405,6 +1411,7 @@ MPPassManager::runOnModule(Module &M) { for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { ModulePass *MP = getContainedPass(Index); + bool LocalChanged = false; dumpPassInfo(MP, EXECUTION_MSG, ON_MODULE_MSG, M.getModuleIdentifier()); dumpRequiredSet(MP); @@ -1414,11 +1421,12 @@ MPPassManager::runOnModule(Module &M) { { PassManagerPrettyStackEntry X(MP, M); Timer *T = StartPassTimer(MP); - Changed |= MP->runOnModule(M); + LocalChanged |= MP->runOnModule(M); StopPassTimer(MP, T); } - if (Changed) + Changed |= LocalChanged; + if (LocalChanged) dumpPassInfo(MP, MODIFICATION_MSG, ON_MODULE_MSG, M.getModuleIdentifier()); dumpPreservedSet(MP); @@ -1704,8 +1712,13 @@ LLVMPassManagerRef LLVMCreatePassManager() { return wrap(new PassManager()); } +LLVMPassManagerRef LLVMCreateFunctionPassManagerForModule(LLVMModuleRef M) { + return wrap(new FunctionPassManager(unwrap(M))); +} + LLVMPassManagerRef LLVMCreateFunctionPassManager(LLVMModuleProviderRef P) { - return wrap(new FunctionPassManager(unwrap(P))); + return LLVMCreateFunctionPassManagerForModule( + reinterpret_cast(P)); } LLVMBool LLVMRunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp index 044de4fb39..9b2c2cab81 100644 --- a/lib/VMCore/Type.cpp +++ b/lib/VMCore/Type.cpp @@ -50,8 +50,8 @@ void AbstractTypeUser::setType(Value *V, const Type *NewTy) { /// Because of the way Type subclasses are allocated, this function is necessary /// to use the correct kind of "delete" operator to deallocate the Type object. -/// Some type objects (FunctionTy, StructTy) allocate additional space after -/// the space for their derived type to hold the contained types array of +/// Some type objects (FunctionTy, StructTy, UnionTy) allocate additional space +/// after the space for their derived type to hold the contained types array of /// PATypeHandles. Using this allocation scheme means all the PATypeHandles are /// allocated with the type object, decreasing allocations and eliminating the /// need for a std::vector to be used in the Type class itself. @@ -61,7 +61,8 @@ void Type::destroy() const { // Structures and Functions allocate their contained types past the end of // the type object itself. These need to be destroyed differently than the // other types. - if (isa(this) || isa(this)) { + if (this->isFunctionTy() || this->isStructTy() || + this->isUnionTy()) { // First, make sure we destruct any PATypeHandles allocated by these // subclasses. They must be manually destructed. for (unsigned i = 0; i < NumContainedTys; ++i) @@ -69,10 +70,12 @@ void Type::destroy() const { // Now call the destructor for the subclass directly because we're going // to delete this as an array of char. - if (isa(this)) + if (this->isFunctionTy()) static_cast(this)->FunctionType::~FunctionType(); - else + else if (this->isStructTy()) static_cast(this)->StructType::~StructType(); + else + static_cast(this)->UnionType::~UnionType(); // Finally, remove the memory as an array deallocation of the chars it was // constructed from. @@ -124,32 +127,32 @@ const Type *Type::getScalarType() const { return this; } -/// isInteger - Return true if this is an IntegerType of the specified width. -bool Type::isInteger(unsigned Bitwidth) const { - return isInteger() && cast(this)->getBitWidth() == Bitwidth; +/// isIntegerTy - Return true if this is an IntegerType of the specified width. +bool Type::isIntegerTy(unsigned Bitwidth) const { + return isIntegerTy() && cast(this)->getBitWidth() == Bitwidth; } -/// isIntOrIntVector - Return true if this is an integer type or a vector of +/// isIntOrIntVectorTy - Return true if this is an integer type or a vector of /// integer types. /// -bool Type::isIntOrIntVector() const { - if (isInteger()) +bool Type::isIntOrIntVectorTy() const { + if (isIntegerTy()) return true; if (ID != Type::VectorTyID) return false; - return cast(this)->getElementType()->isInteger(); + return cast(this)->getElementType()->isIntegerTy(); } -/// isFPOrFPVector - Return true if this is a FP type or a vector of FP types. +/// isFPOrFPVectorTy - Return true if this is a FP type or a vector of FP types. /// -bool Type::isFPOrFPVector() const { +bool Type::isFPOrFPVectorTy() const { if (ID == Type::FloatTyID || ID == Type::DoubleTyID || ID == Type::FP128TyID || ID == Type::X86_FP80TyID || ID == Type::PPC_FP128TyID) return true; if (ID != Type::VectorTyID) return false; - return cast(this)->getElementType()->isFloatingPoint(); + return cast(this)->getElementType()->isFloatingPointTy(); } // canLosslesslyBitCastTo - Return true if this type can be converted to @@ -173,8 +176,8 @@ bool Type::canLosslesslyBitCastTo(const Type *Ty) const { // At this point we have only various mismatches of the first class types // remaining and ptr->ptr. Just select the lossless conversions. Everything // else is not lossless. - if (isa(this)) - return isa(Ty); + if (this->isPointerTy()) + return Ty->isPointerTy(); return false; // Other types have no identity values } @@ -204,7 +207,7 @@ unsigned Type::getScalarSizeInBits() const { int Type::getFPMantissaWidth() const { if (const VectorType *VTy = dyn_cast(this)) return VTy->getElementType()->getFPMantissaWidth(); - assert(isFloatingPoint() && "Not a floating point type!"); + assert(isFloatingPointTy() && "Not a floating point type!"); if (ID == FloatTyID) return 24; if (ID == DoubleTyID) return 53; if (ID == X86_FP80TyID) return 64; @@ -217,7 +220,7 @@ int Type::getFPMantissaWidth() const { /// iff all of the members of the type are sized as well. Since asking for /// their size is relatively uncommon, move this operation out of line. bool Type::isSizedDerivedType() const { - if (isa(this)) + if (this->isIntegerTy()) return true; if (const ArrayType *ATy = dyn_cast(this)) @@ -226,7 +229,7 @@ bool Type::isSizedDerivedType() const { if (const VectorType *PTy = dyn_cast(this)) return PTy->getElementType()->isSized(); - if (!isa(this)) + if (!this->isStructTy() && !this->isUnionTy()) return false; // Okay, our struct is sized if all of the elements are... @@ -285,7 +288,7 @@ std::string Type::getDescription() const { bool StructType::indexValid(const Value *V) const { // Structure indexes require 32-bit integer constants. - if (V->getType()->isInteger(32)) + if (V->getType()->isIntegerTy(32)) if (const ConstantInt *CU = dyn_cast(V)) return indexValid(CU->getZExtValue()); return false; @@ -308,6 +311,32 @@ const Type *StructType::getTypeAtIndex(unsigned Idx) const { return ContainedTys[Idx]; } + +bool UnionType::indexValid(const Value *V) const { + // Union indexes require 32-bit integer constants. + if (V->getType()->isIntegerTy(32)) + if (const ConstantInt *CU = dyn_cast(V)) + return indexValid(CU->getZExtValue()); + return false; +} + +bool UnionType::indexValid(unsigned V) const { + return V < NumContainedTys; +} + +// getTypeAtIndex - Given an index value into the type, return the type of the +// element. For a structure type, this must be a constant value... +// +const Type *UnionType::getTypeAtIndex(const Value *V) const { + unsigned Idx = (unsigned)cast(V)->getZExtValue(); + return getTypeAtIndex(Idx); +} + +const Type *UnionType::getTypeAtIndex(unsigned Idx) const { + assert(indexValid(Idx) && "Invalid structure index!"); + return ContainedTys[Idx]; +} + //===----------------------------------------------------------------------===// // Primitive 'Type' data //===----------------------------------------------------------------------===// @@ -418,7 +447,7 @@ bool FunctionType::isValidReturnType(const Type *RetTy) { /// isValidArgumentType - Return true if the specified type is valid as an /// argument type. bool FunctionType::isValidArgumentType(const Type *ArgTy) { - return ArgTy->isFirstClassType() || isa(ArgTy); + return ArgTy->isFirstClassType() || ArgTy->isOpaqueTy(); } FunctionType::FunctionType(const Type *Result, @@ -463,6 +492,23 @@ StructType::StructType(LLVMContext &C, setAbstract(isAbstract); } +UnionType::UnionType(LLVMContext &C,const Type* const* Types, unsigned NumTypes) + : CompositeType(C, UnionTyID) { + ContainedTys = reinterpret_cast(this + 1); + NumContainedTys = NumTypes; + bool isAbstract = false; + for (unsigned i = 0; i < NumTypes; ++i) { + assert(Types[i] && " type for union field!"); + assert(isValidElementType(Types[i]) && + "Invalid type for union element!"); + new (&ContainedTys[i]) PATypeHandle(Types[i], this); + isAbstract |= Types[i]->isAbstract(); + } + + // Calculate whether or not this type is abstract + setAbstract(isAbstract); +} + ArrayType::ArrayType(const Type *ElType, uint64_t NumEl) : SequentialType(ArrayTyID, ElType) { NumElements = NumEl; @@ -507,30 +553,7 @@ void DerivedType::dropAllTypeUses() { if (NumContainedTys != 0) { // The type must stay abstract. To do this, we insert a pointer to a type // that will never get resolved, thus will always be abstract. - static Type *AlwaysOpaqueTy = 0; - static PATypeHolder* Holder = 0; - Type *tmp = AlwaysOpaqueTy; - if (llvm_is_multithreaded()) { - sys::MemoryFence(); - if (!tmp) { - llvm_acquire_global_lock(); - tmp = AlwaysOpaqueTy; - if (!tmp) { - tmp = OpaqueType::get(getContext()); - PATypeHolder* tmp2 = new PATypeHolder(tmp); - sys::MemoryFence(); - AlwaysOpaqueTy = tmp; - Holder = tmp2; - } - - llvm_release_global_lock(); - } - } else if (!AlwaysOpaqueTy) { - AlwaysOpaqueTy = OpaqueType::get(getContext()); - Holder = new PATypeHolder(AlwaysOpaqueTy); - } - - ContainedTys[0] = AlwaysOpaqueTy; + ContainedTys[0] = getContext().pImpl->AlwaysOpaqueTy; // Change the rest of the types to be Int32Ty's. It doesn't matter what we // pick so long as it doesn't point back to this type. We choose something @@ -590,7 +613,7 @@ void Type::PromoteAbstractToConcrete() { // Concrete types are leaves in the tree. Since an SCC will either be all // abstract or all concrete, we only need to check one type. if (SCC[0]->isAbstract()) { - if (isa(SCC[0])) + if (SCC[0]->isOpaqueTy()) return; // Not going to be concrete, sorry. // If all of the children of all of the types in this SCC are concrete, @@ -637,7 +660,7 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, std::map &EqTypes) { if (Ty == Ty2) return true; if (Ty->getTypeID() != Ty2->getTypeID()) return false; - if (isa(Ty)) + if (Ty->isOpaqueTy()) return false; // Two unequal opaque types are never equal std::map::iterator It = EqTypes.find(Ty); @@ -667,6 +690,13 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2, if (!TypesEqual(STy->getElementType(i), STy2->getElementType(i), EqTypes)) return false; return true; + } else if (const UnionType *UTy = dyn_cast(Ty)) { + const UnionType *UTy2 = cast(Ty2); + if (UTy->getNumElements() != UTy2->getNumElements()) return false; + for (unsigned i = 0, e = UTy2->getNumElements(); i != e; ++i) + if (!TypesEqual(UTy->getElementType(i), UTy2->getElementType(i), EqTypes)) + return false; + return true; } else if (const ArrayType *ATy = dyn_cast(Ty)) { const ArrayType *ATy2 = cast(Ty2); return ATy->getNumElements() == ATy2->getNumElements() && @@ -858,7 +888,7 @@ ArrayType *ArrayType::get(const Type *ElementType, uint64_t NumElements) { bool ArrayType::isValidElementType(const Type *ElemTy) { return ElemTy->getTypeID() != VoidTyID && ElemTy->getTypeID() != LabelTyID && - ElemTy->getTypeID() != MetadataTyID && !isa(ElemTy); + ElemTy->getTypeID() != MetadataTyID && !ElemTy->isFunctionTy(); } VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { @@ -881,8 +911,8 @@ VectorType *VectorType::get(const Type *ElementType, unsigned NumElements) { } bool VectorType::isValidElementType(const Type *ElemTy) { - return ElemTy->isInteger() || ElemTy->isFloatingPoint() || - isa(ElemTy); + return ElemTy->isIntegerTy() || ElemTy->isFloatingPointTy() || + ElemTy->isOpaqueTy(); } //===----------------------------------------------------------------------===// @@ -924,11 +954,65 @@ StructType *StructType::get(LLVMContext &Context, const Type *type, ...) { } bool StructType::isValidElementType(const Type *ElemTy) { - return ElemTy->getTypeID() != VoidTyID && ElemTy->getTypeID() != LabelTyID && - ElemTy->getTypeID() != MetadataTyID && !isa(ElemTy); + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); } +//===----------------------------------------------------------------------===// +// Union Type Factory... +// + +UnionType *UnionType::get(const Type* const* Types, unsigned NumTypes) { + assert(NumTypes > 0 && "union must have at least one member type!"); + UnionValType UTV(Types, NumTypes); + UnionType *UT = 0; + + LLVMContextImpl *pImpl = Types[0]->getContext().pImpl; + + UT = pImpl->UnionTypes.get(UTV); + + if (!UT) { + // Value not found. Derive a new type! + UT = (UnionType*) operator new(sizeof(UnionType) + + sizeof(PATypeHandle) * NumTypes); + new (UT) UnionType(Types[0]->getContext(), Types, NumTypes); + pImpl->UnionTypes.add(UTV, UT); + } +#ifdef DEBUG_MERGE_TYPES + DEBUG(dbgs() << "Derived new type: " << *UT << "\n"); +#endif + return UT; +} + +UnionType *UnionType::get(const Type *type, ...) { + va_list ap; + SmallVector UnionFields; + va_start(ap, type); + while (type) { + UnionFields.push_back(type); + type = va_arg(ap, llvm::Type*); + } + unsigned NumTypes = UnionFields.size(); + assert(NumTypes > 0 && "union must have at least one member type!"); + return llvm::UnionType::get(&UnionFields[0], NumTypes); +} + +bool UnionType::isValidElementType(const Type *ElemTy) { + return !ElemTy->isVoidTy() && !ElemTy->isLabelTy() && + !ElemTy->isMetadataTy() && !ElemTy->isFunctionTy(); +} + +int UnionType::getElementTypeIndex(const Type *ElemTy) const { + int index = 0; + for (UnionType::element_iterator I = element_begin(), E = element_end(); + I != E; ++I, ++index) { + if (ElemTy == *I) return index; + } + + return -1; +} + //===----------------------------------------------------------------------===// // Pointer Type Factory... // @@ -1188,6 +1272,21 @@ void StructType::typeBecameConcrete(const DerivedType *AbsTy) { pImpl->StructTypes.TypeBecameConcrete(this, AbsTy); } +// refineAbstractType - Called when a contained type is found to be more +// concrete - this could potentially change us from an abstract type to a +// concrete type. +// +void UnionType::refineAbstractType(const DerivedType *OldType, + const Type *NewType) { + LLVMContextImpl *pImpl = OldType->getContext().pImpl; + pImpl->UnionTypes.RefineAbstractType(this, OldType, NewType); +} + +void UnionType::typeBecameConcrete(const DerivedType *AbsTy) { + LLVMContextImpl *pImpl = AbsTy->getContext().pImpl; + pImpl->UnionTypes.TypeBecameConcrete(this, AbsTy); +} + // refineAbstractType - Called when a contained type is found to be more // concrete - this could potentially change us from an abstract type to a // concrete type. @@ -1204,7 +1303,7 @@ void PointerType::typeBecameConcrete(const DerivedType *AbsTy) { } bool SequentialType::indexValid(const Value *V) const { - if (isa(V->getType())) + if (V->getType()->isIntegerTy()) return true; return false; } diff --git a/lib/VMCore/TypesContext.h b/lib/VMCore/TypesContext.h index 484284551f..02ab1135b3 100644 --- a/lib/VMCore/TypesContext.h +++ b/lib/VMCore/TypesContext.h @@ -180,6 +180,32 @@ public: } }; +// UnionValType - Define a class to hold the key that goes into the TypeMap +// +class UnionValType { + std::vector ElTypes; +public: + UnionValType(const Type* const* Types, unsigned NumTypes) + : ElTypes(&Types[0], &Types[NumTypes]) {} + + static UnionValType get(const UnionType *UT) { + std::vector ElTypes; + ElTypes.reserve(UT->getNumElements()); + for (unsigned i = 0, e = UT->getNumElements(); i != e; ++i) + ElTypes.push_back(UT->getElementType(i)); + + return UnionValType(&ElTypes[0], ElTypes.size()); + } + + static unsigned hashTypeStructure(const UnionType *UT) { + return UT->getNumElements(); + } + + inline bool operator<(const UnionValType &UTV) const { + return (ElTypes < UTV.ElTypes); + } +}; + // FunctionValType - Define a class to hold the key that goes into the TypeMap // class FunctionValType { diff --git a/lib/VMCore/Value.cpp b/lib/VMCore/Value.cpp index 3759b8a7cb..a36d262825 100644 --- a/lib/VMCore/Value.cpp +++ b/lib/VMCore/Value.cpp @@ -45,11 +45,11 @@ Value::Value(const Type *ty, unsigned scid) UseList(0), Name(0) { if (isa(this) || isa(this)) assert((VTy->isFirstClassType() || VTy->isVoidTy() || - isa(ty) || VTy->getTypeID() == Type::StructTyID) && + ty->isOpaqueTy() || VTy->isStructTy()) && "invalid CallInst type!"); else if (!isa(this) && !isa(this)) assert((VTy->isFirstClassType() || VTy->isVoidTy() || - isa(ty)) && + ty->isOpaqueTy()) && "Cannot create non-first-class values except for constants!"); } @@ -320,7 +320,7 @@ void Value::replaceAllUsesWith(Value *New) { } Value *Value::stripPointerCasts() { - if (!isa(getType())) + if (!getType()->isPointerTy()) return this; Value *V = this; do { @@ -337,12 +337,12 @@ Value *Value::stripPointerCasts() { } else { return V; } - assert(isa(V->getType()) && "Unexpected operand type!"); + assert(V->getType()->isPointerTy() && "Unexpected operand type!"); } while (1); } Value *Value::getUnderlyingObject(unsigned MaxLookup) { - if (!isa(getType())) + if (!getType()->isPointerTy()) return this; Value *V = this; for (unsigned Count = 0; MaxLookup == 0 || Count < MaxLookup; ++Count) { @@ -357,7 +357,7 @@ Value *Value::getUnderlyingObject(unsigned MaxLookup) { } else { return V; } - assert(isa(V->getType()) && "Unexpected operand type!"); + assert(V->getType()->isPointerTy() && "Unexpected operand type!"); } return V; } diff --git a/lib/VMCore/ValueTypes.cpp b/lib/VMCore/ValueTypes.cpp index 7f9a6cde2d..a092cd1a84 100644 --- a/lib/VMCore/ValueTypes.cpp +++ b/lib/VMCore/ValueTypes.cpp @@ -36,17 +36,17 @@ EVT EVT::getExtendedVectorVT(LLVMContext &Context, EVT VT, bool EVT::isExtendedFloatingPoint() const { assert(isExtended() && "Type is not extended!"); - return LLVMTy->isFPOrFPVector(); + return LLVMTy->isFPOrFPVectorTy(); } bool EVT::isExtendedInteger() const { assert(isExtended() && "Type is not extended!"); - return LLVMTy->isIntOrIntVector(); + return LLVMTy->isIntOrIntVectorTy(); } bool EVT::isExtendedVector() const { assert(isExtended() && "Type is not extended!"); - return isa(LLVMTy); + return LLVMTy->isVectorTy(); } bool EVT::isExtended64BitVector() const { @@ -126,6 +126,7 @@ std::string EVT::getEVTString() const { case MVT::v8f32: return "v8f32"; case MVT::v2f64: return "v2f64"; case MVT::v4f64: return "v4f64"; + case MVT::Metadata:return "Metadata"; } } diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp index d0e8d30578..721e96a0f5 100644 --- a/lib/VMCore/Verifier.cpp +++ b/lib/VMCore/Verifier.cpp @@ -161,7 +161,8 @@ namespace { VerifierFailureAction action; // What to do if verification fails. Module *Mod; // Module we are verifying right now - DominatorTree *DT; // Dominator Tree, caution can be null! + LLVMContext *Context; // Context within which we are verifying + DominatorTree *DT; // Dominator Tree, caution can be null! std::string Messages; raw_string_ostream MessagesStr; @@ -178,24 +179,25 @@ namespace { Verifier() : FunctionPass(&ID), Broken(false), RealPass(true), action(AbortProcessAction), - DT(0), MessagesStr(Messages) {} + Mod(0), Context(0), DT(0), MessagesStr(Messages) {} explicit Verifier(VerifierFailureAction ctn) : FunctionPass(&ID), - Broken(false), RealPass(true), action(ctn), DT(0), + Broken(false), RealPass(true), action(ctn), Mod(0), Context(0), DT(0), MessagesStr(Messages) {} explicit Verifier(bool AB) : FunctionPass(&ID), Broken(false), RealPass(true), - action( AB ? AbortProcessAction : PrintMessageAction), DT(0), - MessagesStr(Messages) {} + action( AB ? AbortProcessAction : PrintMessageAction), Mod(0), + Context(0), DT(0), MessagesStr(Messages) {} explicit Verifier(DominatorTree &dt) : FunctionPass(&ID), - Broken(false), RealPass(false), action(PrintMessageAction), - DT(&dt), MessagesStr(Messages) {} + Broken(false), RealPass(false), action(PrintMessageAction), Mod(0), + Context(0), DT(&dt), MessagesStr(Messages) {} bool doInitialization(Module &M) { Mod = &M; + Context = &M.getContext(); verifyTypeSymbolTable(M.getTypeSymbolTable()); // If this is a real pass, in a pass manager, we must abort before @@ -211,6 +213,7 @@ namespace { if (RealPass) DT = &getAnalysis(); Mod = F.getParent(); + if (!Context) Context = &F.getContext(); visit(F); InstsInThisBlock.clear(); @@ -314,6 +317,7 @@ namespace { void visitStoreInst(StoreInst &SI); void visitInstruction(Instruction &I); void visitTerminatorInst(TerminatorInst &I); + void visitBranchInst(BranchInst &BI); void visitReturnInst(ReturnInst &RI); void visitSwitchInst(SwitchInst &SI); void visitSelectInst(SelectInst &SI); @@ -429,7 +433,7 @@ void Verifier::visitGlobalValue(GlobalValue &GV) { if (GV.hasAppendingLinkage()) { GlobalVariable *GVar = dyn_cast(&GV); - Assert1(GVar && isa(GVar->getType()->getElementType()), + Assert1(GVar && GVar->getType()->getElementType()->isArrayTy(), "Only global arrays can have appending linkage!", GVar); } } @@ -596,13 +600,16 @@ void Verifier::visitFunction(Function &F) { const FunctionType *FT = F.getFunctionType(); unsigned NumArgs = F.arg_size(); + Assert1(Context == &F.getContext(), + "Function context does not match Module context!", &F); + Assert1(!F.hasCommonLinkage(), "Functions may not have common linkage", &F); Assert2(FT->getNumParams() == NumArgs, "# formal arguments must match # of arguments for function type!", &F, FT); Assert1(F.getReturnType()->isFirstClassType() || F.getReturnType()->isVoidTy() || - isa(F.getReturnType()), + F.getReturnType()->isStructTy(), "Functions cannot return aggregate values!", &F); Assert1(!F.hasStructRetAttr() || F.getReturnType()->isVoidTy(), @@ -743,6 +750,14 @@ void Verifier::visitTerminatorInst(TerminatorInst &I) { visitInstruction(I); } +void Verifier::visitBranchInst(BranchInst &BI) { + if (BI.isConditional()) { + Assert2(BI.getCondition()->getType()->isIntegerTy(1), + "Branch condition is not 'i1' type!", &BI, BI.getCondition()); + } + visitTerminatorInst(BI); +} + void Verifier::visitReturnInst(ReturnInst &RI) { Function *F = RI.getParent()->getParent(); unsigned N = RI.getNumOperands(); @@ -821,9 +836,9 @@ void Verifier::visitTruncInst(TruncInst &I) { unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcTy->isIntOrIntVector(), "Trunc only operates on integer", &I); - Assert1(DestTy->isIntOrIntVector(), "Trunc only produces integer", &I); - Assert1(isa(SrcTy) == isa(DestTy), + Assert1(SrcTy->isIntOrIntVectorTy(), "Trunc only operates on integer", &I); + Assert1(DestTy->isIntOrIntVectorTy(), "Trunc only produces integer", &I); + Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), "trunc source and destination must both be a vector or neither", &I); Assert1(SrcBitSize > DestBitSize,"DestTy too big for Trunc", &I); @@ -836,9 +851,9 @@ void Verifier::visitZExtInst(ZExtInst &I) { const Type *DestTy = I.getType(); // Get the size of the types in bits, we'll need this later - Assert1(SrcTy->isIntOrIntVector(), "ZExt only operates on integer", &I); - Assert1(DestTy->isIntOrIntVector(), "ZExt only produces an integer", &I); - Assert1(isa(SrcTy) == isa(DestTy), + Assert1(SrcTy->isIntOrIntVectorTy(), "ZExt only operates on integer", &I); + Assert1(DestTy->isIntOrIntVectorTy(), "ZExt only produces an integer", &I); + Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), "zext source and destination must both be a vector or neither", &I); unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); @@ -857,9 +872,9 @@ void Verifier::visitSExtInst(SExtInst &I) { unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcTy->isIntOrIntVector(), "SExt only operates on integer", &I); - Assert1(DestTy->isIntOrIntVector(), "SExt only produces an integer", &I); - Assert1(isa(SrcTy) == isa(DestTy), + Assert1(SrcTy->isIntOrIntVectorTy(), "SExt only operates on integer", &I); + Assert1(DestTy->isIntOrIntVectorTy(), "SExt only produces an integer", &I); + Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), "sext source and destination must both be a vector or neither", &I); Assert1(SrcBitSize < DestBitSize,"Type too small for SExt", &I); @@ -874,9 +889,9 @@ void Verifier::visitFPTruncInst(FPTruncInst &I) { unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcTy->isFPOrFPVector(),"FPTrunc only operates on FP", &I); - Assert1(DestTy->isFPOrFPVector(),"FPTrunc only produces an FP", &I); - Assert1(isa(SrcTy) == isa(DestTy), + Assert1(SrcTy->isFPOrFPVectorTy(),"FPTrunc only operates on FP", &I); + Assert1(DestTy->isFPOrFPVectorTy(),"FPTrunc only produces an FP", &I); + Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), "fptrunc source and destination must both be a vector or neither",&I); Assert1(SrcBitSize > DestBitSize,"DestTy too big for FPTrunc", &I); @@ -892,9 +907,9 @@ void Verifier::visitFPExtInst(FPExtInst &I) { unsigned SrcBitSize = SrcTy->getScalarSizeInBits(); unsigned DestBitSize = DestTy->getScalarSizeInBits(); - Assert1(SrcTy->isFPOrFPVector(),"FPExt only operates on FP", &I); - Assert1(DestTy->isFPOrFPVector(),"FPExt only produces an FP", &I); - Assert1(isa(SrcTy) == isa(DestTy), + Assert1(SrcTy->isFPOrFPVectorTy(),"FPExt only operates on FP", &I); + Assert1(DestTy->isFPOrFPVectorTy(),"FPExt only produces an FP", &I); + Assert1(SrcTy->isVectorTy() == DestTy->isVectorTy(), "fpext source and destination must both be a vector or neither", &I); Assert1(SrcBitSize < DestBitSize,"DestTy too small for FPExt", &I); @@ -906,14 +921,14 @@ void Verifier::visitUIToFPInst(UIToFPInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - bool SrcVec = isa(SrcTy); - bool DstVec = isa(DestTy); + bool SrcVec = SrcTy->isVectorTy(); + bool DstVec = DestTy->isVectorTy(); Assert1(SrcVec == DstVec, "UIToFP source and dest must both be vector or scalar", &I); - Assert1(SrcTy->isIntOrIntVector(), + Assert1(SrcTy->isIntOrIntVectorTy(), "UIToFP source must be integer or integer vector", &I); - Assert1(DestTy->isFPOrFPVector(), + Assert1(DestTy->isFPOrFPVectorTy(), "UIToFP result must be FP or FP vector", &I); if (SrcVec && DstVec) @@ -929,14 +944,14 @@ void Verifier::visitSIToFPInst(SIToFPInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - bool SrcVec = isa(SrcTy); - bool DstVec = isa(DestTy); + bool SrcVec = SrcTy->isVectorTy(); + bool DstVec = DestTy->isVectorTy(); Assert1(SrcVec == DstVec, "SIToFP source and dest must both be vector or scalar", &I); - Assert1(SrcTy->isIntOrIntVector(), + Assert1(SrcTy->isIntOrIntVectorTy(), "SIToFP source must be integer or integer vector", &I); - Assert1(DestTy->isFPOrFPVector(), + Assert1(DestTy->isFPOrFPVectorTy(), "SIToFP result must be FP or FP vector", &I); if (SrcVec && DstVec) @@ -952,13 +967,14 @@ void Verifier::visitFPToUIInst(FPToUIInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - bool SrcVec = isa(SrcTy); - bool DstVec = isa(DestTy); + bool SrcVec = SrcTy->isVectorTy(); + bool DstVec = DestTy->isVectorTy(); Assert1(SrcVec == DstVec, "FPToUI source and dest must both be vector or scalar", &I); - Assert1(SrcTy->isFPOrFPVector(), "FPToUI source must be FP or FP vector", &I); - Assert1(DestTy->isIntOrIntVector(), + Assert1(SrcTy->isFPOrFPVectorTy(), "FPToUI source must be FP or FP vector", + &I); + Assert1(DestTy->isIntOrIntVectorTy(), "FPToUI result must be integer or integer vector", &I); if (SrcVec && DstVec) @@ -974,14 +990,14 @@ void Verifier::visitFPToSIInst(FPToSIInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - bool SrcVec = isa(SrcTy); - bool DstVec = isa(DestTy); + bool SrcVec = SrcTy->isVectorTy(); + bool DstVec = DestTy->isVectorTy(); Assert1(SrcVec == DstVec, "FPToSI source and dest must both be vector or scalar", &I); - Assert1(SrcTy->isFPOrFPVector(), + Assert1(SrcTy->isFPOrFPVectorTy(), "FPToSI source must be FP or FP vector", &I); - Assert1(DestTy->isIntOrIntVector(), + Assert1(DestTy->isIntOrIntVectorTy(), "FPToSI result must be integer or integer vector", &I); if (SrcVec && DstVec) @@ -997,8 +1013,8 @@ void Verifier::visitPtrToIntInst(PtrToIntInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - Assert1(isa(SrcTy), "PtrToInt source must be pointer", &I); - Assert1(DestTy->isInteger(), "PtrToInt result must be integral", &I); + Assert1(SrcTy->isPointerTy(), "PtrToInt source must be pointer", &I); + Assert1(DestTy->isIntegerTy(), "PtrToInt result must be integral", &I); visitInstruction(I); } @@ -1008,8 +1024,8 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) { const Type *SrcTy = I.getOperand(0)->getType(); const Type *DestTy = I.getType(); - Assert1(SrcTy->isInteger(), "IntToPtr source must be an integral", &I); - Assert1(isa(DestTy), "IntToPtr result must be a pointer",&I); + Assert1(SrcTy->isIntegerTy(), "IntToPtr source must be an integral", &I); + Assert1(DestTy->isPointerTy(), "IntToPtr result must be a pointer",&I); visitInstruction(I); } @@ -1025,7 +1041,7 @@ void Verifier::visitBitCastInst(BitCastInst &I) { // BitCast implies a no-op cast of type only. No bits change. // However, you can't cast pointers to anything but pointers. - Assert1(isa(DestTy) == isa(DestTy), + Assert1(DestTy->isPointerTy() == DestTy->isPointerTy(), "Bitcast requires both operands to be pointer or neither", &I); Assert1(SrcBitSize == DestBitSize, "Bitcast requires types of same width",&I); @@ -1068,11 +1084,11 @@ void Verifier::visitPHINode(PHINode &PN) { void Verifier::VerifyCallSite(CallSite CS) { Instruction *I = CS.getInstruction(); - Assert1(isa(CS.getCalledValue()->getType()), + Assert1(CS.getCalledValue()->getType()->isPointerTy(), "Called function must be a pointer!", I); const PointerType *FPTy = cast(CS.getCalledValue()->getType()); - Assert1(isa(FPTy->getElementType()), + Assert1(FPTy->getElementType()->isFunctionTy(), "Called function is not pointer to function type!", I); const FunctionType *FTy = cast(FPTy->getElementType()); @@ -1151,7 +1167,7 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) { case Instruction::UDiv: case Instruction::SRem: case Instruction::URem: - Assert1(B.getType()->isIntOrIntVector(), + Assert1(B.getType()->isIntOrIntVectorTy(), "Integer arithmetic operators only work with integral types!", &B); Assert1(B.getType() == B.getOperand(0)->getType(), "Integer arithmetic operators must have same type " @@ -1164,7 +1180,7 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) { case Instruction::FMul: case Instruction::FDiv: case Instruction::FRem: - Assert1(B.getType()->isFPOrFPVector(), + Assert1(B.getType()->isFPOrFPVectorTy(), "Floating-point arithmetic operators only work with " "floating-point types!", &B); Assert1(B.getType() == B.getOperand(0)->getType(), @@ -1175,7 +1191,7 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) { case Instruction::And: case Instruction::Or: case Instruction::Xor: - Assert1(B.getType()->isIntOrIntVector(), + Assert1(B.getType()->isIntOrIntVectorTy(), "Logical operators only work with integral types!", &B); Assert1(B.getType() == B.getOperand(0)->getType(), "Logical operators must have same type for operands and result!", @@ -1184,7 +1200,7 @@ void Verifier::visitBinaryOperator(BinaryOperator &B) { case Instruction::Shl: case Instruction::LShr: case Instruction::AShr: - Assert1(B.getType()->isIntOrIntVector(), + Assert1(B.getType()->isIntOrIntVectorTy(), "Shifts only work with integral types!", &B); Assert1(B.getType() == B.getOperand(0)->getType(), "Shift return type must be same as operands!", &B); @@ -1203,7 +1219,7 @@ void Verifier::visitICmpInst(ICmpInst& IC) { Assert1(Op0Ty == Op1Ty, "Both operands to ICmp instruction are not of the same type!", &IC); // Check that the operands are the right type - Assert1(Op0Ty->isIntOrIntVector() || isa(Op0Ty), + Assert1(Op0Ty->isIntOrIntVectorTy() || Op0Ty->isPointerTy(), "Invalid operand types for ICmp instruction", &IC); visitInstruction(IC); @@ -1216,7 +1232,7 @@ void Verifier::visitFCmpInst(FCmpInst& FC) { Assert1(Op0Ty == Op1Ty, "Both operands to FCmp instruction are not of the same type!", &FC); // Check that the operands are the right type - Assert1(Op0Ty->isFPOrFPVector(), + Assert1(Op0Ty->isFPOrFPVectorTy(), "Invalid operand types for FCmp instruction", &FC); visitInstruction(FC); } @@ -1270,7 +1286,7 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) { GetElementPtrInst::getIndexedType(GEP.getOperand(0)->getType(), Idxs.begin(), Idxs.end()); Assert1(ElTy, "Invalid indices for GEP pointer type!", &GEP); - Assert2(isa(GEP.getType()) && + Assert2(GEP.getType()->isPointerTy() && cast(GEP.getType())->getElementType() == ElTy, "GEP is not of right type for indices!", &GEP, ElTy); visitInstruction(GEP); @@ -1302,7 +1318,7 @@ void Verifier::visitAllocaInst(AllocaInst &AI) { &AI); Assert1(PTy->getElementType()->isSized(), "Cannot allocate unsized type", &AI); - Assert1(AI.getArraySize()->getType()->isInteger(32), + Assert1(AI.getArraySize()->getType()->isIntegerTy(32), "Alloca array size must be i32", &AI); visitInstruction(AI); } @@ -1481,7 +1497,7 @@ void Verifier::visitInstruction(Instruction &I) { void Verifier::VerifyType(const Type *Ty) { if (!Types.insert(Ty)) return; - Assert1(&Mod->getContext() == &Ty->getContext(), + Assert1(Context == &Ty->getContext(), "Type context does not match Module context!", Ty); switch (Ty->getTypeID()) { @@ -1509,6 +1525,15 @@ void Verifier::VerifyType(const Type *Ty) { VerifyType(ElTy); } } break; + case Type::UnionTyID: { + const UnionType *UTy = cast(Ty); + for (unsigned i = 0, e = UTy->getNumElements(); i != e; ++i) { + const Type *ElTy = UTy->getElementType(i); + Assert2(UnionType::isValidElementType(ElTy), + "Union type with invalid element type", ElTy, UTy); + VerifyType(ElTy); + } + } break; case Type::ArrayTyID: { const ArrayType *ATy = cast(Ty); Assert1(ArrayType::isValidElementType(ATy->getElementType()), @@ -1616,7 +1641,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { if (ID == Intrinsic::gcroot) { AllocaInst *AI = dyn_cast(CI.getOperand(1)->stripPointerCasts()); - Assert1(AI && isa(AI->getType()->getElementType()), + Assert1(AI && AI->getType()->getElementType()->isPointerTy(), "llvm.gcroot parameter #1 must be a pointer alloca.", &CI); Assert1(isa(CI.getOperand(2)), "llvm.gcroot parameter #2 must be a constant.", &CI); @@ -1734,7 +1759,7 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty, } } } else if (VT == MVT::iAny) { - if (!EltTy->isInteger()) { + if (!EltTy->isIntegerTy()) { CheckFailed(IntrinsicParam(ArgNo, NumRets) + " is not " "an integer type.", F); return false; @@ -1759,7 +1784,7 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty, break; } } else if (VT == MVT::fAny) { - if (!EltTy->isFloatingPoint()) { + if (!EltTy->isFloatingPointTy()) { CheckFailed(IntrinsicParam(ArgNo, NumRets) + " is not " "a floating-point type.", F); return false; @@ -1778,7 +1803,7 @@ bool Verifier::PerformTypeCheck(Intrinsic::ID ID, Function *F, const Type *Ty, } Suffix += ".v" + utostr(NumElts) + EVT::getEVT(EltTy).getEVTString(); } else if (VT == MVT::iPTR) { - if (!isa(Ty)) { + if (!Ty->isPointerTy()) { CheckFailed(IntrinsicParam(ArgNo, NumRets) + " is not a " "pointer and a pointer is required.", F); return false; diff --git a/llvm-device-build.mk b/llvm-device-build.mk new file mode 100644 index 0000000000..d7c7e3d631 --- /dev/null +++ b/llvm-device-build.mk @@ -0,0 +1,52 @@ +LOCAL_CFLAGS := \ + -D_DEBUG \ + -D_GNU_SOURCE \ + -D__STDC_LIMIT_MACROS \ + -D__STDC_CONSTANT_MACROS \ + -DANDROID_TARGET_BUILD \ + -O2 \ + -fomit-frame-pointer \ + -Woverloaded-virtual \ + -Wall \ + -W \ + -Wno-unused-parameter \ + -Wwrite-strings \ + $(LOCAL_CFLAGS) + +ifneq ($(REQUIRES_EH),1) +LOCAL_CFLAGS += -fno-exceptions +else +# No action. The device target should not have exception enabled since bionic +# doesn't support it +REQUIRES_EH := 0 +endif + +ifneq ($(REQUIRES_RTTI),1) +LOCAL_CFLAGS += -fno-rtti +else +REQUIRES_RTTI := 0 +endif + +# Make sure bionic is first so we can include system headers. +LOCAL_C_INCLUDES := \ + bionic \ + external/stlport/stlport \ + $(LLVM_ROOT_PATH) \ + $(LLVM_ROOT_PATH)/include \ + $(LLVM_ROOT_PATH)/device/include \ + $(LOCAL_C_INCLUDES) + +########################################################### +## Commands for running tblgen to compile a td file +########################################################### +define transform-device-td-to-out +@mkdir -p $(dir $@) +@echo "Device TableGen (gen-$(1)): $(LOCAL_MODULE) <= $<" +$(hide) $(TBLGEN) \ + -I $(dir $<) \ + -I $(LLVM_ROOT_PATH)/include \ + -I $(LLVM_ROOT_PATH)/device/include \ + -I $(LLVM_ROOT_PATH)/lib/Target \ + -gen-$(strip $(1)) \ + -o $@ $< +endef diff --git a/llvm-gen-intrinsics.mk b/llvm-gen-intrinsics.mk new file mode 100644 index 0000000000..decccdd591 --- /dev/null +++ b/llvm-gen-intrinsics.mk @@ -0,0 +1,18 @@ +# We treat Intrinsics.td as a very special target just like what lib/VMCore/Makefile does +INTRINSICTD := $(LLVM_ROOT_PATH)/include/llvm/Intrinsics.td +INTRINSICTDS := $(wildcard $(dir $(INTRINSICTD))/Intrinsics*.td) + +LOCAL_SRC_FILES := $(INTRINSICTD) $(LOCAL_SRC_FILES) + +ifeq ($(LOCAL_MODULE_CLASS),) + LOCAL_MODULE_CLASS := STATIC_LIBRARIES +endif + +GENFILE := $(addprefix $(call local-intermediates-dir)/llvm/,Intrinsics.gen) +LOCAL_GENERATED_SOURCES += $(GENFILE) +$(GENFILE): $(INTRINSICTD) $(INTRINSICTDS) $(TBLGEN) +ifeq ($(LOCAL_IS_HOST_MODULE),true) + $(call transform-host-td-to-out,intrinsic) +else + $(call transform-device-td-to-out,intrinsic) +endif diff --git a/llvm-host-build.mk b/llvm-host-build.mk new file mode 100644 index 0000000000..263afe7f89 --- /dev/null +++ b/llvm-host-build.mk @@ -0,0 +1,50 @@ +LOCAL_CFLAGS := \ + -D_DEBUG \ + -D_GNU_SOURCE \ + -D__STDC_LIMIT_MACROS \ + -D__STDC_CONSTANT_MACROS \ + -O2 \ + -fomit-frame-pointer \ + -Woverloaded-virtual \ + -Wall \ + -W \ + -Wno-unused-parameter \ + -Wwrite-strings \ + $(LOCAL_CFLAGS) + +ifneq ($(REQUIRES_EH),1) +LOCAL_CFLAGS += -fno-exceptions +else +REQUIRES_EH := 0 +LOCAL_CFLAGS += -fexceptions +endif + +ifneq ($(REQUIRES_RTTI),1) +LOCAL_CFLAGS += -fno-rtti +else +REQUIRES_RTTI := 0 +endif + +# Make sure bionic is first so we can include system headers. +LOCAL_C_INCLUDES := \ + $(LLVM_ROOT_PATH) \ + $(LLVM_ROOT_PATH)/include \ + $(LLVM_ROOT_PATH)/host/include \ + $(LOCAL_C_INCLUDES) + +LOCAL_IS_HOST_MODULE := true + +########################################################### +## Commands for running tblgen to compile a td file +########################################################### +define transform-host-td-to-out +@mkdir -p $(dir $@) +@echo "Host TableGen: $(LOCAL_MODULE) (gen-$(1)) <= $<" +$(hide) $(TBLGEN) \ + -I $(dir $<) \ + -I $(LLVM_ROOT_PATH)/include \ + -I $(LLVM_ROOT_PATH)/host/include \ + -I $(LLVM_ROOT_PATH)/lib/Target \ + -gen-$(strip $(1)) \ + -o $@ $< +endef diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt index 1a286db9ec..415530e332 100644 --- a/projects/CMakeLists.txt +++ b/projects/CMakeLists.txt @@ -4,7 +4,7 @@ file(GLOB entries *) foreach(entry ${entries}) if(IS_DIRECTORY ${entry} AND EXISTS ${entry}/CMakeLists.txt) - if(NOT (${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/compiler-rt)) + if(NOT ${entry} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}/compiler-rt) add_subdirectory(${entry}) endif() endif() diff --git a/projects/sample/configure b/projects/sample/configure index f6aa8476ea..5a13388871 100755 --- a/projects/sample/configure +++ b/projects/sample/configure @@ -2362,3 +2362,4 @@ if test "$no_create" != yes; then $ac_cs_success || { (exit 1); exit 1; } fi + diff --git a/runtime/Makefile b/runtime/Makefile index 1e10451425..7209867c2f 100644 --- a/runtime/Makefile +++ b/runtime/Makefile @@ -20,6 +20,10 @@ ifeq ($(ARCH), Sparc) PARALLEL_DIRS := $(filter-out libprofile, $(PARALLEL_DIRS)) endif +ifeq ($(TARGET_OS), $(filter $(TARGET_OS), Cygwin MingW)) +PARALLEL_DIRS := $(filter-out libprofile, $(PARALLEL_DIRS)) +endif + endif include $(LEVEL)/Makefile.common diff --git a/runtime/libprofile/Makefile b/runtime/libprofile/Makefile index 92a85584db..15e6779512 100644 --- a/runtime/libprofile/Makefile +++ b/runtime/libprofile/Makefile @@ -10,7 +10,7 @@ LEVEL = ../.. include $(LEVEL)/Makefile.config -ifneq ($(wildcard $(LLVMGCC)),) +ifneq ($(strip $(LLVMCC)),) BYTECODE_LIBRARY = 1 endif SHARED_LIBRARY = 1 diff --git a/tblgen-rules.mk b/tblgen-rules.mk new file mode 100644 index 0000000000..435bc42eef --- /dev/null +++ b/tblgen-rules.mk @@ -0,0 +1,108 @@ +########################################################### +## Commands for running tblgen to compile a td file +########################################################## +define transform-td-to-out +$(if $(LOCAL_IS_HOST_MODULE), \ + $(call transform-host-td-to-out,$(1)), \ + $(call transform-device-td-to-out,$(1))) +endef + +########################################################### +## TableGen: Compile .td files to .inc. +########################################################### +ifeq ($(LOCAL_MODULE_CLASS),) + LOCAL_MODULE_CLASS := STATIC_LIBRARIES +endif + +ifneq ($(strip $(TBLGEN_TABLES)),) + +intermediates := $(call local-intermediates-dir) +tblgen_gen_tables := $(addprefix $(intermediates)/,$(TBLGEN_TABLES)) +LOCAL_GENERATED_SOURCES += $(tblgen_gen_tables) + +tblgen_source_dir := $(LOCAL_PATH) +ifneq ($(TBLGEN_TD_DIR),) +tblgen_source_dir := $(TBLGEN_TD_DIR) +endif + +ifneq ($(filter %GenRegisterNames.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenRegisterNames.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,register-enums) +endif + +ifneq ($(filter %GenRegisterInfo.h.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenRegisterInfo.h.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,register-desc-header) +endif + +ifneq ($(filter %GenRegisterInfo.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenRegisterInfo.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,register-desc) +endif + +ifneq ($(filter %GenInstrNames.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenInstrNames.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,instr-enums) +endif + +ifneq ($(filter %GenInstrInfo.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenInstrInfo.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,instr-desc) +endif + +ifneq ($(filter %GenAsmWriter.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenAsmWriter.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,asm-writer) +endif + +ifneq ($(filter %GenAsmWriter1.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenAsmWriter1.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,asm-writer -asmwriternum=1) +endif + +ifneq ($(filter %GenAsmMatcher.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenAsmMatcher.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,asm-matcher) +endif + +ifneq ($(filter %GenCodeEmitter.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenCodeEmitter.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,emitter) +endif + +ifneq ($(filter %GenDAGISel.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenDAGISel.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,dag-isel) +endif + +ifneq ($(filter %GenDisassemblerTables.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenDisassemblerTables.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,disassembler) +endif + +ifneq ($(filter %GenEDInfo.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenEDInfo.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,enhanced-disassembly-info) +endif + +ifneq ($(filter %GenFastISel.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenFastISel.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,fast-isel) +endif + +ifneq ($(filter %GenSubtarget.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenSubtarget.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,subtarget) +endif + +ifneq ($(filter %GenCallingConv.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenCallingConv.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,callingconv) +endif + +ifneq ($(filter %GenIntrinsics.inc,$(tblgen_gen_tables)),) +$(intermediates)/%GenIntrinsics.inc: $(tblgen_source_dir)/%.td $(TBLGEN) + $(call transform-td-to-out,tgt_intrinsics) +endif + +endif diff --git a/test/Analysis/Andersens/2007-11-19-InlineAsm.ll b/test/Analysis/Andersens/2007-11-19-InlineAsm.ll deleted file mode 100644 index 5ba34997e9..0000000000 --- a/test/Analysis/Andersens/2007-11-19-InlineAsm.ll +++ /dev/null @@ -1,8 +0,0 @@ -; RUN: opt < %s -anders-aa -disable-output - -define void @x(i16 %Y) { -entry: - %tmp = call i16 asm "bswap $0", "=r,r"(i16 %Y) - ret void -} - diff --git a/test/Analysis/Andersens/2008-03-19-External.ll b/test/Analysis/Andersens/2008-03-19-External.ll deleted file mode 100644 index a973103766..0000000000 --- a/test/Analysis/Andersens/2008-03-19-External.ll +++ /dev/null @@ -1,12 +0,0 @@ -; RUN: opt < %s -anders-aa -gvn -S | not grep undef -; PR2160 - -declare void @f(i32*) - -define i32 @g() { -entry: - %tmp = alloca i32 ; [#uses=2] - call void @f( i32* %tmp ) - %tmp2 = load i32* %tmp ; [#uses=1] - ret i32 %tmp2 -} diff --git a/test/Analysis/Andersens/2008-04-07-Memcpy.ll b/test/Analysis/Andersens/2008-04-07-Memcpy.ll deleted file mode 100644 index 5a50dd5621..0000000000 --- a/test/Analysis/Andersens/2008-04-07-Memcpy.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: opt < %s -anders-aa -gvn -S | not grep undef -; PR2169 - -declare void @llvm.memcpy.i32(i8*, i8*, i32, i32) nounwind -declare void @use(i8) - -define void @f(i8* %x) { -entry: - %copy = alloca i8 ; [#uses=6] - call void @llvm.memcpy.i32( i8* %copy, i8* %x, i32 1, i32 4 ) - %tmp = load i8* %copy ; [#uses=1] - call void @use(i8 %tmp) - ret void -} diff --git a/test/Analysis/Andersens/2008-12-27-BuiltinWrongType.ll b/test/Analysis/Andersens/2008-12-27-BuiltinWrongType.ll deleted file mode 100644 index da6751139f..0000000000 --- a/test/Analysis/Andersens/2008-12-27-BuiltinWrongType.ll +++ /dev/null @@ -1,19 +0,0 @@ -; RUN: opt < %s -anders-aa -; PR3262 - -@.str15 = external global [3 x i8] ; <[3 x i8]*> [#uses=1] - -declare i8* @strtok(...) -declare i8* @memmove(...) - -define void @test1(i8* %want1) nounwind { -entry: - %0 = call i8* (...)* @strtok(i32 0, i8* getelementptr ([3 x i8]* @.str15, i32 0, i32 0)) nounwind ; [#uses=0] - unreachable -} - -define void @test2() nounwind { -entry: - %0 = call i8* (...)* @memmove() - unreachable -} diff --git a/test/Analysis/Andersens/basictest.ll b/test/Analysis/Andersens/basictest.ll deleted file mode 100644 index 47226dd8da..0000000000 --- a/test/Analysis/Andersens/basictest.ll +++ /dev/null @@ -1,28 +0,0 @@ -; RUN: opt < %s -anders-aa -aa-eval 2>/dev/null - -define void @test1() { - %X = malloc i32* - %Y = malloc i32 - %Z = ptrtoint i32* %Y to i32 - %W = inttoptr i32 %Z to i32* - store i32* %W, i32** %X - ret void -} - -define void @test2(i32* %P) { - %X = malloc i32* - %Y = malloc i32 - store i32* %P, i32** %X - ret void -} - -define internal i32 *@test3(i32* %P) { - ret i32* %P -} - -define void @test4() { - %X = malloc i32 - %Y = call i32* @test3(i32* %X) - %ZZ = getelementptr i32* null, i32 17 - ret void -} diff --git a/test/Analysis/Andersens/dg.exp b/test/Analysis/Andersens/dg.exp deleted file mode 100644 index 1eb4755c41..0000000000 --- a/test/Analysis/Andersens/dg.exp +++ /dev/null @@ -1,4 +0,0 @@ -load_lib llvm.exp - -RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] - diff --git a/test/Analysis/Andersens/external.ll b/test/Analysis/Andersens/external.ll deleted file mode 100644 index 13c12dc558..0000000000 --- a/test/Analysis/Andersens/external.ll +++ /dev/null @@ -1,20 +0,0 @@ -; RUN: opt < %s -anders-aa -gvn -deadargelim -S | grep store | not grep null - -; Because the 'internal' function is passed to an external function, we don't -; know what the incoming values will alias. As such, we cannot do the -; optimization checked by the 'arg-must-alias.ll' test. - -declare void @external(i32(i32*)*) -@G = internal constant i32* null - -define internal i32 @internal(i32* %ARG) { - ;;; We *DON'T* know that ARG always points to null! - store i32* %ARG, i32** @G - ret i32 0 -} - -define i32 @foo() { - call void @external(i32(i32*)* @internal) - %V = call i32 @internal(i32* null) - ret i32 %V -} diff --git a/test/Analysis/Andersens/modreftest.ll b/test/Analysis/Andersens/modreftest.ll deleted file mode 100644 index e0c2edc4c2..0000000000 --- a/test/Analysis/Andersens/modreftest.ll +++ /dev/null @@ -1,15 +0,0 @@ -; RUN: opt < %s -anders-aa -gvn -instcombine -S \ -; RUN: | grep {ret i1 true} - -@G = internal global i32* null -declare i32 *@ext() - -define i1 @bar() { - %V1 = load i32** @G - %X2 = call i32 *@ext() - %V2 = load i32** @G - store i32* %X2, i32** @G - - %C = icmp eq i32* %V1, %V2 - ret i1 %C -} diff --git a/test/Analysis/Andersens/modreftest2.ll b/test/Analysis/Andersens/modreftest2.ll deleted file mode 100644 index 562c961e7d..0000000000 --- a/test/Analysis/Andersens/modreftest2.ll +++ /dev/null @@ -1,14 +0,0 @@ -; RUN: opt < %s -anders-aa -gvn -S \ -; RUN: | not grep {ret i32 undef} - -;; From PR 2160 -declare void @f(i32*) - -define i32 @g() { -entry: - %tmp = alloca i32 ; [#uses=2] - call void @f( i32* %tmp ) - %tmp2 = load i32* %tmp ; [#uses=1] - ret i32 %tmp2 -} - diff --git a/test/Analysis/Andersens/trivialtest.ll b/test/Analysis/Andersens/trivialtest.ll deleted file mode 100644 index f9f938f8f1..0000000000 --- a/test/Analysis/Andersens/trivialtest.ll +++ /dev/null @@ -1,3 +0,0 @@ -; RUN: opt < %s -anders-aa -disable-output - -define void @foo() { ret void } diff --git a/test/Analysis/ScalarEvolution/trip-count10.ll b/test/Analysis/ScalarEvolution/trip-count10.ll new file mode 100644 index 0000000000..0a992f952a --- /dev/null +++ b/test/Analysis/ScalarEvolution/trip-count10.ll @@ -0,0 +1,76 @@ +; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s + +; Trip counts with trivial exit conditions. + +; CHECK: Determining loop execution counts for: @a +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. + +; CHECK: Determining loop execution counts for: @b +; CHECK: Loop %loop: backedge-taken count is false +; CHECK: Loop %loop: max backedge-taken count is false + +; CHECK: Determining loop execution counts for: @c +; CHECK: Loop %loop: backedge-taken count is false +; CHECK: Loop %loop: max backedge-taken count is false + +; CHECK: Determining loop execution counts for: @d +; CHECK: Loop %loop: Unpredictable backedge-taken count. +; CHECK: Loop %loop: Unpredictable max backedge-taken count. + +define void @a(i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 false, label %return, label %loop + +return: + ret void +} +define void @b(i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 true, label %return, label %loop + +return: + ret void +} +define void @c(i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 false, label %loop, label %return + +return: + ret void +} +define void @d(i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 true, label %loop, label %return + +return: + ret void +} diff --git a/test/Archive/GNU.a b/test/Archive/GNU.a deleted file mode 100644 index 4c09881eb3..0000000000 Binary files a/test/Archive/GNU.a and /dev/null differ diff --git a/test/Archive/IsNAN.o b/test/Archive/IsNAN.o deleted file mode 100644 index 7b3a12a69d..0000000000 Binary files a/test/Archive/IsNAN.o and /dev/null differ diff --git a/test/Archive/MacOSX.a b/test/Archive/MacOSX.a deleted file mode 100644 index 8ba1e6d30e..0000000000 Binary files a/test/Archive/MacOSX.a and /dev/null differ diff --git a/test/Archive/SVR4.a b/test/Archive/SVR4.a deleted file mode 100644 index 3947813ac6..0000000000 Binary files a/test/Archive/SVR4.a and /dev/null differ diff --git a/test/Archive/xpg4.a b/test/Archive/xpg4.a deleted file mode 100644 index b2bdb51188..0000000000 Binary files a/test/Archive/xpg4.a and /dev/null differ diff --git a/test/Assembler/2010-01-06-UnionType.ll b/test/Assembler/2010-01-06-UnionType.ll new file mode 100644 index 0000000000..37130d6608 --- /dev/null +++ b/test/Assembler/2010-01-06-UnionType.ll @@ -0,0 +1,3 @@ +; RUN: llvm-as %s -o /dev/null + +%X = type union { i32, i32* } diff --git a/test/Bindings/Ocaml/bitreader.ml b/test/Bindings/Ocaml/bitreader.ml index 5c23041c80..112ca61830 100644 --- a/test/Bindings/Ocaml/bitreader.ml +++ b/test/Bindings/Ocaml/bitreader.ml @@ -41,16 +41,16 @@ let _ = true end; - (* get_module_provider *) + (* get_module *) begin let mb = Llvm.MemoryBuffer.of_file fn in - let mp = begin try - Llvm_bitreader.get_module_provider context mb + let m = begin try + Llvm_bitreader.get_module context mb with x -> Llvm.MemoryBuffer.dispose mb; raise x end in - Llvm.ModuleProvider.dispose mp + Llvm.dispose_module m end; (* corrupt the bitcode *) @@ -60,17 +60,17 @@ let _ = close_out oc end; - (* test get_module_provider exceptions *) + (* test get_module exceptions *) test begin try let mb = Llvm.MemoryBuffer.of_file fn in - let mp = begin try - Llvm_bitreader.get_module_provider context mb + let m = begin try + Llvm_bitreader.get_module context mb with x -> Llvm.MemoryBuffer.dispose mb; raise x end in - Llvm.ModuleProvider.dispose mp; + Llvm.dispose_module m; false with Llvm_bitreader.Error _ -> true diff --git a/test/Bindings/Ocaml/bitwriter.ml b/test/Bindings/Ocaml/bitwriter.ml index 57caac7cb9..ef1c9ab722 100644 --- a/test/Bindings/Ocaml/bitwriter.ml +++ b/test/Bindings/Ocaml/bitwriter.ml @@ -1,4 +1,4 @@ -(* RUN: %ocamlopt -warn-error A llvm.cmxa llvm_bitwriter.cmxa %s -o %t +(* RUN: %ocamlopt -warn-error A unix.cmxa llvm.cmxa llvm_bitwriter.cmxa %s -o %t * RUN: ./%t %t.bc * RUN: llvm-dis < %t.bc | grep caml_int_ty *) @@ -10,9 +10,37 @@ let context = Llvm.global_context () let test x = if not x then exit 1 else () +let read_file name = + let ic = open_in_bin name in + let len = in_channel_length ic in + let buf = String.create len in + + test ((input ic buf 0 len) = len); + + close_in ic; + + buf + +let temp_bitcode ?unbuffered m = + let temp_name, temp_oc = Filename.open_temp_file ~mode:[Open_binary] "" "" in + + test (Llvm_bitwriter.output_bitcode ?unbuffered temp_oc m); + flush temp_oc; + + let temp_buf = read_file temp_name in + + close_out temp_oc; + + temp_buf + let _ = let m = Llvm.create_module context "ocaml_test_module" in ignore (Llvm.define_type_name "caml_int_ty" (Llvm.i32_type context) m); - - test (Llvm_bitwriter.write_bitcode_file m Sys.argv.(1)) + + test (Llvm_bitwriter.write_bitcode_file m Sys.argv.(1)); + let file_buf = read_file Sys.argv.(1) in + + test (file_buf = temp_bitcode m); + test (file_buf = temp_bitcode ~unbuffered:false m); + test (file_buf = temp_bitcode ~unbuffered:true m) diff --git a/test/Bindings/Ocaml/executionengine.ml b/test/Bindings/Ocaml/executionengine.ml index ce56c50dcb..2caeb82aac 100644 --- a/test/Bindings/Ocaml/executionengine.ml +++ b/test/Bindings/Ocaml/executionengine.ml @@ -64,9 +64,8 @@ let test_executionengine () = let m2 = create_module (global_context ()) "test_module2" in define_plus m2; - let ee = ExecutionEngine.create (ModuleProvider.create m) in - let mp2 = ModuleProvider.create m2 in - ExecutionEngine.add_module_provider mp2 ee; + let ee = ExecutionEngine.create m in + ExecutionEngine.add_module m2 ee; (* run_static_ctors *) ExecutionEngine.run_static_ctors ee; @@ -94,8 +93,8 @@ let test_executionengine () = ee in if 4 != GenericValue.as_int res then bomb "plus did not work"; - (* remove_module_provider *) - Llvm.dispose_module (ExecutionEngine.remove_module_provider mp2 ee); + (* remove_module *) + Llvm.dispose_module (ExecutionEngine.remove_module m2 ee); (* run_static_dtors *) ExecutionEngine.run_static_dtors ee; diff --git a/test/Bindings/Ocaml/scalar_opts.ml b/test/Bindings/Ocaml/scalar_opts.ml index 0a65810105..f28eff28da 100644 --- a/test/Bindings/Ocaml/scalar_opts.ml +++ b/test/Bindings/Ocaml/scalar_opts.ml @@ -22,7 +22,6 @@ let suite name f = let filename = Sys.argv.(1) let m = create_module context filename -let mp = ModuleProvider.create m (*===-- Transforms --------------------------------------------------------===*) @@ -36,13 +35,30 @@ let test_transforms () = let td = TargetData.create (target_triple m) in - ignore (PassManager.create_function mp + ignore (PassManager.create_function m ++ TargetData.add td - ++ add_instruction_combining + ++ add_constant_propagation + ++ add_sccp + ++ add_dead_store_elimination + ++ add_aggressive_dce + ++ add_scalar_repl_aggregation + ++ add_ind_var_simplification + ++ add_instruction_combination + ++ add_licm + ++ add_loop_unswitch + ++ add_loop_unroll + ++ add_loop_rotation + ++ add_loop_index_split + ++ add_memory_to_register_promotion + ++ add_memory_to_register_demotion ++ add_reassociation - ++ add_gvn + ++ add_jump_threading ++ add_cfg_simplification - ++ add_constant_propagation + ++ add_tail_call_elimination + ++ add_gvn + ++ add_memcpy_opt + ++ add_loop_deletion + ++ add_lib_call_simplification ++ PassManager.initialize ++ PassManager.run_function fn ++ PassManager.finalize @@ -55,4 +71,4 @@ let test_transforms () = let _ = suite "transforms" test_transforms; - ModuleProvider.dispose mp + dispose_module m diff --git a/test/Bindings/Ocaml/vmcore.ml b/test/Bindings/Ocaml/vmcore.ml index dd0404a9f7..506bf50e2a 100644 --- a/test/Bindings/Ocaml/vmcore.ml +++ b/test/Bindings/Ocaml/vmcore.ml @@ -58,7 +58,6 @@ let suite name f = let filename = Sys.argv.(1) let m = create_module context filename -let mp = ModuleProvider.create m (*===-- Target ------------------------------------------------------------===*) @@ -83,181 +82,189 @@ let test_target () = (*===-- Types -------------------------------------------------------------===*) let test_types () = - (* RUN: grep {Ty01.*void} < %t.ll + (* RUN: grep {void_type.*void} < %t.ll *) group "void"; - insist (define_type_name "Ty01" void_type m); + insist (define_type_name "void_type" void_type m); insist (TypeKind.Void == classify_type void_type); - (* RUN: grep {Ty02.*i1} < %t.ll + (* RUN: grep {i1_type.*i1} < %t.ll *) group "i1"; - insist (define_type_name "Ty02" i1_type m); + insist (define_type_name "i1_type" i1_type m); insist (TypeKind.Integer == classify_type i1_type); - (* RUN: grep {Ty03.*i32} < %t.ll + (* RUN: grep {i32_type.*i32} < %t.ll *) group "i32"; - insist (define_type_name "Ty03" i32_type m); + insist (define_type_name "i32_type" i32_type m); - (* RUN: grep {Ty04.*i42} < %t.ll + (* RUN: grep {i42_type.*i42} < %t.ll *) group "i42"; let ty = integer_type context 42 in - insist (define_type_name "Ty04" ty m); + insist (define_type_name "i42_type" ty m); - (* RUN: grep {Ty05.*float} < %t.ll + (* RUN: grep {float_type.*float} < %t.ll *) group "float"; - insist (define_type_name "Ty05" float_type m); + insist (define_type_name "float_type" float_type m); insist (TypeKind.Float == classify_type float_type); - (* RUN: grep {Ty06.*double} < %t.ll + (* RUN: grep {double_type.*double} < %t.ll *) group "double"; - insist (define_type_name "Ty06" double_type m); + insist (define_type_name "double_type" double_type m); insist (TypeKind.Double == classify_type double_type); - (* RUN: grep {Ty07.*i32.*i1, double} < %t.ll + (* RUN: grep {function_type.*i32.*i1, double} < %t.ll *) group "function"; let ty = function_type i32_type [| i1_type; double_type |] in - insist (define_type_name "Ty07" ty m); + insist (define_type_name "function_type" ty m); insist (TypeKind.Function = classify_type ty); insist (not (is_var_arg ty)); insist (i32_type == return_type ty); insist (double_type == (param_types ty).(1)); - (* RUN: grep {Ty08.*\.\.\.} < %t.ll + (* RUN: grep {var_arg_type.*\.\.\.} < %t.ll *) group "var arg function"; let ty = var_arg_function_type void_type [| i32_type |] in - insist (define_type_name "Ty08" ty m); + insist (define_type_name "var_arg_type" ty m); insist (is_var_arg ty); - (* RUN: grep {Ty09.*\\\[7 x i8\\\]} < %t.ll + (* RUN: grep {array_type.*\\\[7 x i8\\\]} < %t.ll *) group "array"; let ty = array_type i8_type 7 in - insist (define_type_name "Ty09" ty m); + insist (define_type_name "array_type" ty m); insist (7 = array_length ty); insist (i8_type == element_type ty); insist (TypeKind.Array == classify_type ty); begin group "pointer"; - (* RUN: grep {UnqualPtrTy.*float\*} < %t.ll + (* RUN: grep {pointer_type.*float\*} < %t.ll *) let ty = pointer_type float_type in - insist (define_type_name "UnqualPtrTy" ty m); + insist (define_type_name "pointer_type" ty m); insist (float_type == element_type ty); insist (0 == address_space ty); insist (TypeKind.Pointer == classify_type ty) end; begin group "qualified_pointer"; - (* RUN: grep {QualPtrTy.*i8.*3.*\*} < %t.ll + (* RUN: grep {qualified_pointer_type.*i8.*3.*\*} < %t.ll *) let ty = qualified_pointer_type i8_type 3 in - insist (define_type_name "QualPtrTy" ty m); + insist (define_type_name "qualified_pointer_type" ty m); insist (i8_type == element_type ty); insist (3 == address_space ty) end; - (* RUN: grep {Ty11.*\<4 x i16\>} < %t.ll + (* RUN: grep {vector_type.*\<4 x i16\>} < %t.ll *) group "vector"; let ty = vector_type i16_type 4 in - insist (define_type_name "Ty11" ty m); + insist (define_type_name "vector_type" ty m); insist (i16_type == element_type ty); insist (4 = vector_size ty); - (* RUN: grep {Ty12.*opaque} < %t.ll + (* RUN: grep {opaque_type.*opaque} < %t.ll *) group "opaque"; let ty = opaque_type context in - insist (define_type_name "Ty12" ty m); + insist (define_type_name "opaque_type" ty m); insist (ty == ty); insist (ty <> opaque_type context); - (* RUN: grep -v {Ty13} < %t.ll + (* RUN: grep -v {delete_type} < %t.ll *) group "delete"; let ty = opaque_type context in - insist (define_type_name "Ty13" ty m); - delete_type_name "Ty13" m; + insist (define_type_name "delete_type" ty m); + delete_type_name "delete_type" m; + + (* RUN: grep {type_name.*opaque} < %t.ll + *) + group "type_name"; begin + let ty = opaque_type context in + insist (define_type_name "type_name" ty m); + insist ((type_by_name m "type_name") = Some ty) + end; - (* RUN: grep -v {RecursiveTy.*RecursiveTy} < %t.ll + (* RUN: grep -v {recursive_type.*recursive_type} < %t.ll *) group "recursive"; let ty = opaque_type context in let th = handle_to_type ty in refine_type ty (pointer_type ty); let ty = type_of_handle th in - insist (define_type_name "RecursiveTy" ty m); + insist (define_type_name "recursive_type" ty m); insist (ty == element_type ty) (*===-- Constants ---------------------------------------------------------===*) let test_constants () = - (* RUN: grep {Const01.*i32.*-1} < %t.ll + (* RUN: grep {const_int.*i32.*-1} < %t.ll *) group "int"; let c = const_int i32_type (-1) in - ignore (define_global "Const01" c m); + ignore (define_global "const_int" c m); insist (i32_type = type_of c); insist (is_constant c); - (* RUN: grep {Const02.*i64.*-1} < %t.ll + (* RUN: grep {const_sext_int.*i64.*-1} < %t.ll *) group "sext int"; let c = const_int i64_type (-1) in - ignore (define_global "Const02" c m); + ignore (define_global "const_sext_int" c m); insist (i64_type = type_of c); - (* RUN: grep {Const03.*i64.*4294967295} < %t.ll + (* RUN: grep {const_zext_int64.*i64.*4294967295} < %t.ll *) group "zext int64"; let c = const_of_int64 i64_type (Int64.of_string "4294967295") false in - ignore (define_global "Const03" c m); + ignore (define_global "const_zext_int64" c m); insist (i64_type = type_of c); - (* RUN: grep {ConstIntString.*i32.*-1} < %t.ll + (* RUN: grep {const_int_string.*i32.*-1} < %t.ll *) group "int string"; let c = const_int_of_string i32_type "-1" 10 in - ignore (define_global "ConstIntString" c m); + ignore (define_global "const_int_string" c m); insist (i32_type = type_of c); - (* RUN: grep {Const04.*"cruel\\\\00world"} < %t.ll + (* RUN: grep {const_string.*"cruel\\\\00world"} < %t.ll *) group "string"; let c = const_string context "cruel\000world" in - ignore (define_global "Const04" c m); + ignore (define_global "const_string" c m); insist ((array_type i8_type 11) = type_of c); - (* RUN: grep {Const05.*"hi\\\\00again\\\\00"} < %t.ll + (* RUN: grep {const_stringz.*"hi\\\\00again\\\\00"} < %t.ll *) group "stringz"; let c = const_stringz context "hi\000again" in - ignore (define_global "Const05" c m); + ignore (define_global "const_stringz" c m); insist ((array_type i8_type 9) = type_of c); - (* RUN: grep {ConstSingle.*2.75} < %t.ll - * RUN: grep {ConstDouble.*3.1459} < %t.ll - * RUN: grep {ConstDoubleString.*1.25} < %t.ll + (* RUN: grep {const_single.*2.75} < %t.ll + * RUN: grep {const_double.*3.1459} < %t.ll + * RUN: grep {const_double_string.*1.25} < %t.ll *) begin group "real"; let cs = const_float float_type 2.75 in - ignore (define_global "ConstSingle" cs m); + ignore (define_global "const_single" cs m); insist (float_type = type_of cs); let cd = const_float double_type 3.1459 in - ignore (define_global "ConstDouble" cd m); + ignore (define_global "const_double" cd m); insist (double_type = type_of cd); let cd = const_float_of_string double_type "1.25" in - ignore (define_global "ConstDoubleString" cd m); + ignore (define_global "const_double_string" cd m); insist (double_type = type_of cd) end; @@ -266,67 +273,93 @@ let test_constants () = let three = const_int i32_type 3 in let four = const_int i32_type 4 in - (* RUN: grep {Const07.*\\\[i32 3, i32 4\\\]} < %t.ll + (* RUN: grep {const_array.*\\\[i32 3, i32 4\\\]} < %t.ll *) group "array"; let c = const_array i32_type [| three; four |] in - ignore (define_global "Const07" c m); + ignore (define_global "const_array" c m); insist ((array_type i32_type 2) = (type_of c)); - (* RUN: grep {Const08.*} < %t.ll + (* RUN: grep {const_vector.*} < %t.ll *) group "vector"; let c = const_vector [| one; two; one; two; one; two; one; two |] in - ignore (define_global "Const08" c m); + ignore (define_global "const_vector" c m); insist ((vector_type i16_type 8) = (type_of c)); - (* RUN: grep {Const09.*.i16 1, i16 2, i32 3, i32 4} < %t.ll + (* RUN: grep {const_structure.*.i16 1, i16 2, i32 3, i32 4} < %t.ll *) group "structure"; let c = const_struct context [| one; two; three; four |] in - ignore (define_global "Const09" c m); + ignore (define_global "const_structure" c m); insist ((struct_type context [| i16_type; i16_type; i32_type; i32_type |]) = (type_of c)); + + group "union"; + let t = union_type context [| i1_type; i16_type; i64_type; double_type |] in + let c = const_union t one in + ignore (define_global "const_union" c m); + insist (t = (type_of c)); - (* RUN: grep {Const10.*zeroinit} < %t.ll + (* RUN: grep {const_null.*zeroinit} < %t.ll *) group "null"; let c = const_null (packed_struct_type context [| i1_type; i8_type; i64_type; double_type |]) in - ignore (define_global "Const10" c m); + ignore (define_global "const_null" c m); - (* RUN: grep {Const11.*-1} < %t.ll + (* RUN: grep {const_all_ones.*-1} < %t.ll *) group "all ones"; let c = const_all_ones i64_type in - ignore (define_global "Const11" c m); + ignore (define_global "const_all_ones" c m); + + group "pointer null"; begin + (* RUN: grep {const_pointer_null = global i64\\* null} < %t.ll + *) + let c = const_pointer_null (pointer_type i64_type) in + ignore (define_global "const_pointer_null" c m); + end; - (* RUN: grep {Const12.*undef} < %t.ll + (* RUN: grep {const_undef.*undef} < %t.ll *) group "undef"; let c = undef i1_type in - ignore (define_global "Const12" c m); + ignore (define_global "const_undef" c m); insist (i1_type = type_of c); insist (is_undef c); group "constant arithmetic"; - (* RUN: grep {ConstNeg.*sub} < %t.ll - * RUN: grep {ConstNot.*xor} < %t.ll - * RUN: grep {ConstAdd.*add} < %t.ll - * RUN: grep {ConstSub.*sub} < %t.ll - * RUN: grep {ConstMul.*mul} < %t.ll - * RUN: grep {ConstUDiv.*udiv} < %t.ll - * RUN: grep {ConstSDiv.*sdiv} < %t.ll - * RUN: grep {ConstFDiv.*fdiv} < %t.ll - * RUN: grep {ConstURem.*urem} < %t.ll - * RUN: grep {ConstSRem.*srem} < %t.ll - * RUN: grep {ConstFRem.*frem} < %t.ll - * RUN: grep {ConstAnd.*and} < %t.ll - * RUN: grep {ConstOr.*or} < %t.ll - * RUN: grep {ConstXor.*xor} < %t.ll - * RUN: grep {ConstICmp.*icmp} < %t.ll - * RUN: grep {ConstFCmp.*fcmp} < %t.ll + (* RUN: grep {@const_neg = global i64 sub} < %t.ll + * RUN: grep {@const_nsw_neg = global i64 sub nsw } < %t.ll + * RUN: grep {@const_nuw_neg = global i64 sub nuw } < %t.ll + * RUN: grep {@const_fneg = global double fsub } < %t.ll + * RUN: grep {@const_not = global i64 xor } < %t.ll + * RUN: grep {@const_add = global i64 add } < %t.ll + * RUN: grep {@const_nsw_add = global i64 add nsw } < %t.ll + * RUN: grep {@const_nuw_add = global i64 add nuw } < %t.ll + * RUN: grep {@const_fadd = global double fadd } < %t.ll + * RUN: grep {@const_sub = global i64 sub } < %t.ll + * RUN: grep {@const_nsw_sub = global i64 sub nsw } < %t.ll + * RUN: grep {@const_nuw_sub = global i64 sub nuw } < %t.ll + * RUN: grep {@const_fsub = global double fsub } < %t.ll + * RUN: grep {@const_mul = global i64 mul } < %t.ll + * RUN: grep {@const_nsw_mul = global i64 mul nsw } < %t.ll + * RUN: grep {@const_nuw_mul = global i64 mul nuw } < %t.ll + * RUN: grep {@const_fmul = global double fmul } < %t.ll + * RUN: grep {@const_udiv = global i64 udiv } < %t.ll + * RUN: grep {@const_sdiv = global i64 sdiv } < %t.ll + * RUN: grep {@const_exact_sdiv = global i64 sdiv exact } < %t.ll + * RUN: grep {@const_fdiv = global double fdiv } < %t.ll + * RUN: grep {@const_urem = global i64 urem } < %t.ll + * RUN: grep {@const_srem = global i64 srem } < %t.ll + * RUN: grep {@const_frem = global double frem } < %t.ll + * RUN: grep {@const_and = global i64 and } < %t.ll + * RUN: grep {@const_or = global i64 or } < %t.ll + * RUN: grep {@const_xor = global i64 xor } < %t.ll + * RUN: grep {@const_icmp = global i1 icmp sle } < %t.ll + * RUN: grep {@const_fcmp = global i1 fcmp ole } < %t.ll *) let void_ptr = pointer_type i8_type in let five = const_int i64_type 5 in @@ -334,82 +367,105 @@ let test_constants () = let foldbomb_gv = define_global "FoldBomb" (const_null i8_type) m in let foldbomb = const_ptrtoint foldbomb_gv i64_type in let ffoldbomb = const_uitofp foldbomb double_type in - ignore (define_global "ConstNeg" (const_neg foldbomb) m); - ignore (define_global "ConstNot" (const_not foldbomb) m); - ignore (define_global "ConstAdd" (const_add foldbomb five) m); - ignore (define_global "ConstSub" (const_sub foldbomb five) m); - ignore (define_global "ConstMul" (const_mul foldbomb five) m); - ignore (define_global "ConstUDiv" (const_udiv foldbomb five) m); - ignore (define_global "ConstSDiv" (const_sdiv foldbomb five) m); - ignore (define_global "ConstFDiv" (const_fdiv ffoldbomb ffive) m); - ignore (define_global "ConstURem" (const_urem foldbomb five) m); - ignore (define_global "ConstSRem" (const_srem foldbomb five) m); - ignore (define_global "ConstFRem" (const_frem ffoldbomb ffive) m); - ignore (define_global "ConstAnd" (const_and foldbomb five) m); - ignore (define_global "ConstOr" (const_or foldbomb five) m); - ignore (define_global "ConstXor" (const_xor foldbomb five) m); - ignore (define_global "ConstICmp" (const_icmp Icmp.Sle foldbomb five) m); - ignore (define_global "ConstFCmp" (const_fcmp Fcmp.Ole ffoldbomb ffive) m); + ignore (define_global "const_neg" (const_neg foldbomb) m); + ignore (define_global "const_nsw_neg" (const_nsw_neg foldbomb) m); + ignore (define_global "const_nuw_neg" (const_nuw_neg foldbomb) m); + ignore (define_global "const_fneg" (const_fneg ffoldbomb) m); + ignore (define_global "const_not" (const_not foldbomb) m); + ignore (define_global "const_add" (const_add foldbomb five) m); + ignore (define_global "const_nsw_add" (const_nsw_add foldbomb five) m); + ignore (define_global "const_nuw_add" (const_nuw_add foldbomb five) m); + ignore (define_global "const_fadd" (const_fadd ffoldbomb ffive) m); + ignore (define_global "const_sub" (const_sub foldbomb five) m); + ignore (define_global "const_nsw_sub" (const_nsw_sub foldbomb five) m); + ignore (define_global "const_nuw_sub" (const_nuw_sub foldbomb five) m); + ignore (define_global "const_fsub" (const_fsub ffoldbomb ffive) m); + ignore (define_global "const_mul" (const_mul foldbomb five) m); + ignore (define_global "const_nsw_mul" (const_nsw_mul foldbomb five) m); + ignore (define_global "const_nuw_mul" (const_nuw_mul foldbomb five) m); + ignore (define_global "const_fmul" (const_fmul ffoldbomb ffive) m); + ignore (define_global "const_udiv" (const_udiv foldbomb five) m); + ignore (define_global "const_sdiv" (const_sdiv foldbomb five) m); + ignore (define_global "const_exact_sdiv" (const_exact_sdiv foldbomb five) m); + ignore (define_global "const_fdiv" (const_fdiv ffoldbomb ffive) m); + ignore (define_global "const_urem" (const_urem foldbomb five) m); + ignore (define_global "const_srem" (const_srem foldbomb five) m); + ignore (define_global "const_frem" (const_frem ffoldbomb ffive) m); + ignore (define_global "const_and" (const_and foldbomb five) m); + ignore (define_global "const_or" (const_or foldbomb five) m); + ignore (define_global "const_xor" (const_xor foldbomb five) m); + ignore (define_global "const_icmp" (const_icmp Icmp.Sle foldbomb five) m); + ignore (define_global "const_fcmp" (const_fcmp Fcmp.Ole ffoldbomb ffive) m); group "constant casts"; - (* RUN: grep {ConstTrunc.*trunc} < %t.ll - * RUN: grep {ConstSExt.*sext} < %t.ll - * RUN: grep {ConstZExt.*zext} < %t.ll - * RUN: grep {ConstFPTrunc.*fptrunc} < %t.ll - * RUN: grep {ConstFPExt.*fpext} < %t.ll - * RUN: grep {ConstUIToFP.*uitofp} < %t.ll - * RUN: grep {ConstSIToFP.*sitofp} < %t.ll - * RUN: grep {ConstFPToUI.*fptoui} < %t.ll - * RUN: grep {ConstFPToSI.*fptosi} < %t.ll - * RUN: grep {ConstPtrToInt.*ptrtoint} < %t.ll - * RUN: grep {ConstIntToPtr.*inttoptr} < %t.ll - * RUN: grep {ConstBitCast.*bitcast} < %t.ll + (* RUN: grep {const_trunc.*trunc} < %t.ll + * RUN: grep {const_sext.*sext} < %t.ll + * RUN: grep {const_zext.*zext} < %t.ll + * RUN: grep {const_fptrunc.*fptrunc} < %t.ll + * RUN: grep {const_fpext.*fpext} < %t.ll + * RUN: grep {const_uitofp.*uitofp} < %t.ll + * RUN: grep {const_sitofp.*sitofp} < %t.ll + * RUN: grep {const_fptoui.*fptoui} < %t.ll + * RUN: grep {const_fptosi.*fptosi} < %t.ll + * RUN: grep {const_ptrtoint.*ptrtoint} < %t.ll + * RUN: grep {const_inttoptr.*inttoptr} < %t.ll + * RUN: grep {const_bitcast.*bitcast} < %t.ll *) let i128_type = integer_type context 128 in - ignore (define_global "ConstTrunc" (const_trunc (const_add foldbomb five) + ignore (define_global "const_trunc" (const_trunc (const_add foldbomb five) i8_type) m); - ignore (define_global "ConstSExt" (const_sext foldbomb i128_type) m); - ignore (define_global "ConstZExt" (const_zext foldbomb i128_type) m); - ignore (define_global "ConstFPTrunc" (const_fptrunc ffoldbomb float_type) m); - ignore (define_global "ConstFPExt" (const_fpext ffoldbomb fp128_type) m); - ignore (define_global "ConstUIToFP" (const_uitofp foldbomb double_type) m); - ignore (define_global "ConstSIToFP" (const_sitofp foldbomb double_type) m); - ignore (define_global "ConstFPToUI" (const_fptoui ffoldbomb i32_type) m); - ignore (define_global "ConstFPToSI" (const_fptosi ffoldbomb i32_type) m); - ignore (define_global "ConstPtrToInt" (const_ptrtoint + ignore (define_global "const_sext" (const_sext foldbomb i128_type) m); + ignore (define_global "const_zext" (const_zext foldbomb i128_type) m); + ignore (define_global "const_fptrunc" (const_fptrunc ffoldbomb float_type) m); + ignore (define_global "const_fpext" (const_fpext ffoldbomb fp128_type) m); + ignore (define_global "const_uitofp" (const_uitofp foldbomb double_type) m); + ignore (define_global "const_sitofp" (const_sitofp foldbomb double_type) m); + ignore (define_global "const_fptoui" (const_fptoui ffoldbomb i32_type) m); + ignore (define_global "const_fptosi" (const_fptosi ffoldbomb i32_type) m); + ignore (define_global "const_ptrtoint" (const_ptrtoint (const_gep (const_null (pointer_type i8_type)) [| const_int i32_type 1 |]) i32_type) m); - ignore (define_global "ConstIntToPtr" (const_inttoptr (const_add foldbomb five) + ignore (define_global "const_inttoptr" (const_inttoptr (const_add foldbomb five) void_ptr) m); - ignore (define_global "ConstBitCast" (const_bitcast ffoldbomb i64_type) m); + ignore (define_global "const_bitcast" (const_bitcast ffoldbomb i64_type) m); group "misc constants"; - (* RUN: grep {ConstSizeOf.*getelementptr.*null} < %t.ll - * RUN: grep {ConstGEP.*getelementptr} < %t.ll - * RUN: grep {ConstSelect.*select} < %t.ll - * RUN: grep {ConstExtractElement.*extractelement} < %t.ll - * RUN: grep {ConstInsertElement.*insertelement} < %t.ll - * RUN: grep {ConstShuffleVector.*shufflevector} < %t.ll + (* RUN: grep {const_size_of.*getelementptr.*null} < %t.ll + * RUN: grep {const_gep.*getelementptr} < %t.ll + * RUN: grep {const_select.*select} < %t.ll + * RUN: grep {const_extractelement.*extractelement} < %t.ll + * RUN: grep {const_insertelement.*insertelement} < %t.ll + * RUN: grep {const_shufflevector.*shufflevector} < %t.ll *) - ignore (define_global "ConstSizeOf" (size_of (pointer_type i8_type)) m); - ignore (define_global "ConstGEP" (const_gep foldbomb_gv [| five |]) m); - ignore (define_global "ConstSelect" (const_select + ignore (define_global "const_size_of" (size_of (pointer_type i8_type)) m); + ignore (define_global "const_gep" (const_gep foldbomb_gv [| five |]) m); + ignore (define_global "const_select" (const_select (const_icmp Icmp.Sle foldbomb five) (const_int i8_type (-1)) (const_int i8_type 0)) m); let zero = const_int i32_type 0 in let one = const_int i32_type 1 in - ignore (define_global "ConstExtractElement" (const_extractelement + ignore (define_global "const_extractelement" (const_extractelement (const_vector [| zero; one; zero; one |]) (const_trunc foldbomb i32_type)) m); - ignore (define_global "ConstInsertElement" (const_insertelement + ignore (define_global "const_insertelement" (const_insertelement (const_vector [| zero; one; zero; one |]) zero (const_trunc foldbomb i32_type)) m); - ignore (define_global "ConstShuffleVector" (const_shufflevector + ignore (define_global "const_shufflevector" (const_shufflevector (const_vector [| zero; one |]) (const_vector [| one; zero |]) - (const_bitcast foldbomb (vector_type i32_type 2))) m) + (const_bitcast foldbomb (vector_type i32_type 2))) m); + + group "asm"; begin + let ft = function_type void_type [| i32_type; i32_type; i32_type |] in + ignore (const_inline_asm + ft + "" + "{cx},{ax},{di},~{dirflag},~{fpsr},~{flags},~{edi},~{ecx}" + true + false) + end (*===-- Global Values -----------------------------------------------------===*) @@ -461,28 +517,46 @@ let test_global_variables () = let (++) x f = f x; x in let fourty_two32 = const_int i32_type 42 in - (* RUN: grep {GVar01.*external} < %t.ll - *) - group "declarations"; - insist (None == lookup_global "GVar01" m); - let g = declare_global i32_type "GVar01" m in - insist (is_declaration g); - insist (pointer_type float_type == - type_of (declare_global float_type "GVar01" m)); - insist (g == declare_global i32_type "GVar01" m); - insist (match lookup_global "GVar01" m with Some x -> x = g - | None -> false); + group "declarations"; begin + (* RUN: grep {GVar01.*external} < %t.ll + *) + insist (None == lookup_global "GVar01" m); + let g = declare_global i32_type "GVar01" m in + insist (is_declaration g); + insist (pointer_type float_type == + type_of (declare_global float_type "GVar01" m)); + insist (g == declare_global i32_type "GVar01" m); + insist (match lookup_global "GVar01" m with Some x -> x = g + | None -> false); + + insist (None == lookup_global "QGVar01" m); + let g = declare_qualified_global i32_type "QGVar01" 3 m in + insist (is_declaration g); + insist (qualified_pointer_type float_type 3 == + type_of (declare_qualified_global float_type "QGVar01" 3 m)); + insist (g == declare_qualified_global i32_type "QGVar01" 3 m); + insist (match lookup_global "QGVar01" m with Some x -> x = g + | None -> false); + end; - (* RUN: grep {GVar02.*42} < %t.ll - * RUN: grep {GVar03.*42} < %t.ll - *) - group "definitions"; - let g = define_global "GVar02" fourty_two32 m in - let g2 = declare_global i32_type "GVar03" m ++ + group "definitions"; begin + (* RUN: grep {GVar02.*42} < %t.ll + * RUN: grep {GVar03.*42} < %t.ll + *) + let g = define_global "GVar02" fourty_two32 m in + let g2 = declare_global i32_type "GVar03" m ++ + set_initializer fourty_two32 in + insist (not (is_declaration g)); + insist (not (is_declaration g2)); + insist ((global_initializer g) == (global_initializer g2)); + + let g = define_qualified_global "QGVar02" fourty_two32 3 m in + let g2 = declare_qualified_global i32_type "QGVar03" 3 m ++ set_initializer fourty_two32 in - insist (not (is_declaration g)); - insist (not (is_declaration g2)); - insist ((global_initializer g) == (global_initializer g2)); + insist (not (is_declaration g)); + insist (not (is_declaration g2)); + insist ((global_initializer g) == (global_initializer g2)); + end; (* RUN: grep {GVar04.*thread_local} < %t.ll *) @@ -532,6 +606,59 @@ let test_global_variables () = end +(*===-- Uses --------------------------------------------------------------===*) + +let test_uses () = + let ty = function_type i32_type [| i32_type; i32_type |] in + let fn = define_function "use_function" ty m in + let b = builder_at_end context (entry_block fn) in + + let p1 = param fn 0 in + let p2 = param fn 1 in + let v1 = build_add p1 p2 "v1" b in + let v2 = build_add p1 v1 "v2" b in + let _ = build_add v1 v2 "v3" b in + + let lf s u = value_name (user u) ^ "->" ^ s in + insist ("v2->v3->" = fold_left_uses lf "" v1); + let rf u s = value_name (user u) ^ "<-" ^ s in + insist ("v3<-v2<-" = fold_right_uses rf v1 ""); + + let lf s u = value_name (used_value u) ^ "->" ^ s in + insist ("v1->v1->" = fold_left_uses lf "" v1); + + let rf u s = value_name (used_value u) ^ "<-" ^ s in + insist ("v1<-v1<-" = fold_right_uses rf v1 ""); + + ignore (build_unreachable b) + + +(*===-- Users -------------------------------------------------------------===*) + +let test_users () = + let ty = function_type i32_type [| i32_type; i32_type |] in + let fn = define_function "user_function" ty m in + let b = builder_at_end context (entry_block fn) in + + let p1 = param fn 0 in + let p2 = param fn 1 in + let i = build_add p1 p2 "sum" b in + + insist ((operand i 0) = p1); + insist ((operand i 1) = p2); + + ignore (build_unreachable b) + + +(*===-- Aliases -----------------------------------------------------------===*) + +let test_aliases () = + (* RUN: grep {@alias = alias i32\\* @aliasee} < %t.ll + *) + let v = declare_global i32_type "aliasee" m in + ignore (add_alias m (pointer_type i32_type) v "alias") + + (*===-- Functions ---------------------------------------------------------===*) let test_functions () = @@ -845,11 +972,11 @@ let test_builder () = end; group "cond_br"; begin - (* RUN: grep {br.*Inst01.*Bb03.*Bb00} < %t.ll + (* RUN: grep {br.*build_br.*Bb03.*Bb00} < %t.ll *) let bb03 = append_block context "Bb03" fn in let b = builder_at_end context bb03 in - let cond = build_trunc p1 i1_type "Inst01" b in + let cond = build_trunc p1 i1_type "build_br" b in ignore (build_cond_br cond bb03 bb00 b) end; @@ -865,14 +992,31 @@ let test_builder () = let si = build_switch p1 bb3 1 (builder_at_end context bb1) in ignore (add_case si (const_int i32_type 2) bb2) end; + + group "indirectbr"; begin + (* RUN: grep {indirectbr i8\\* blockaddress(@X7, %IBRBlock2), \\\[label %IBRBlock2, label %IBRBlock3\\\]} < %t.ll + *) + let bb1 = append_block context "IBRBlock1" fn in + + let bb2 = append_block context "IBRBlock2" fn in + ignore (build_unreachable (builder_at_end context bb2)); + + let bb3 = append_block context "IBRBlock3" fn in + ignore (build_unreachable (builder_at_end context bb3)); + + let addr = block_address fn bb2 in + let ibr = build_indirect_br addr 2 (builder_at_end context bb1) in + ignore (add_destination ibr bb2); + ignore (add_destination ibr bb3) + end; group "invoke"; begin - (* RUN: grep {Inst02.*invoke.*P1.*P2} < %t.ll + (* RUN: grep {build_invoke.*invoke.*P1.*P2} < %t.ll * RUN: grep {to.*Bb04.*unwind.*Bb00} < %t.ll *) let bb04 = append_block context "Bb04" fn in let b = builder_at_end context bb04 in - ignore (build_invoke fn [| p1; p2 |] bb04 bb00 "Inst02" b) + ignore (build_invoke fn [| p1; p2 |] bb04 bb00 "build_invoke" b) end; group "unwind"; begin @@ -895,121 +1039,139 @@ let test_builder () = let bb07 = append_block context "Bb07" fn in let b = builder_at_end context bb07 in - (* RUN: grep {Inst03.*add.*P1.*P2} < %t.ll - * RUN: grep {Inst04.*sub.*P1.*Inst03} < %t.ll - * RUN: grep {Inst05.*mul.*P1.*Inst04} < %t.ll - * RUN: grep {Inst06.*udiv.*P1.*Inst05} < %t.ll - * RUN: grep {Inst07.*sdiv.*P1.*Inst06} < %t.ll - * RUN: grep {Inst08.*fdiv.*F1.*F2} < %t.ll - * RUN: grep {Inst09.*urem.*P1.*Inst07} < %t.ll - * RUN: grep {Inst10.*srem.*P1.*Inst09} < %t.ll - * RUN: grep {Inst11.*frem.*F1.*Inst08} < %t.ll - * RUN: grep {Inst12.*shl.*P1.*Inst10} < %t.ll - * RUN: grep {Inst13.*lshr.*P1.*Inst12} < %t.ll - * RUN: grep {Inst14.*ashr.*P1.*Inst13} < %t.ll - * RUN: grep {Inst15.*and.*P1.*Inst14} < %t.ll - * RUN: grep {Inst16.*or.*P1.*Inst15} < %t.ll - * RUN: grep {Inst17.*xor.*P1.*Inst16} < %t.ll - * RUN: grep {Inst18.*sub.*0.*Inst17} < %t.ll - * RUN: grep {Inst19.*xor.*Inst18.*-1} < %t.ll + (* RUN: grep {%build_add = add i32 %P1, %P2} < %t.ll + * RUN: grep {%build_nsw_add = add nsw i32 %P1, %P2} < %t.ll + * RUN: grep {%build_nuw_add = add nuw i32 %P1, %P2} < %t.ll + * RUN: grep {%build_fadd = fadd float %F1, %F2} < %t.ll + * RUN: grep {%build_sub = sub i32 %P1, %P2} < %t.ll + * RUN: grep {%build_nsw_sub = sub nsw i32 %P1, %P2} < %t.ll + * RUN: grep {%build_nuw_sub = sub nuw i32 %P1, %P2} < %t.ll + * RUN: grep {%build_fsub = fsub float %F1, %F2} < %t.ll + * RUN: grep {%build_mul = mul i32 %P1, %P2} < %t.ll + * RUN: grep {%build_nsw_mul = mul nsw i32 %P1, %P2} < %t.ll + * RUN: grep {%build_nuw_mul = mul nuw i32 %P1, %P2} < %t.ll + * RUN: grep {%build_fmul = fmul float %F1, %F2} < %t.ll + * RUN: grep {%build_udiv = udiv i32 %P1, %P2} < %t.ll + * RUN: grep {%build_sdiv = sdiv i32 %P1, %P2} < %t.ll + * RUN: grep {%build_exact_sdiv = sdiv exact i32 %P1, %P2} < %t.ll + * RUN: grep {%build_fdiv = fdiv float %F1, %F2} < %t.ll + * RUN: grep {%build_urem = urem i32 %P1, %P2} < %t.ll + * RUN: grep {%build_srem = srem i32 %P1, %P2} < %t.ll + * RUN: grep {%build_frem = frem float %F1, %F2} < %t.ll + * RUN: grep {%build_shl = shl i32 %P1, %P2} < %t.ll + * RUN: grep {%build_lshl = lshr i32 %P1, %P2} < %t.ll + * RUN: grep {%build_ashl = ashr i32 %P1, %P2} < %t.ll + * RUN: grep {%build_and = and i32 %P1, %P2} < %t.ll + * RUN: grep {%build_or = or i32 %P1, %P2} < %t.ll + * RUN: grep {%build_xor = xor i32 %P1, %P2} < %t.ll + * RUN: grep {%build_neg = sub i32 0, %P1} < %t.ll + * RUN: grep {%build_nsw_neg = sub nsw i32 0, %P1} < %t.ll + * RUN: grep {%build_nuw_neg = sub nuw i32 0, %P1} < %t.ll + * RUN: grep {%build_fneg = fsub float .*0.*, %F1} < %t.ll + * RUN: grep {%build_not = xor i32 %P1, -1} < %t.ll *) - let inst03 = build_add p1 p2 "Inst03" b in - let inst04 = build_sub p1 inst03 "Inst04" b in - let inst05 = build_mul p1 inst04 "Inst05" b in - let inst06 = build_udiv p1 inst05 "Inst06" b in - let inst07 = build_sdiv p1 inst06 "Inst07" b in - let inst08 = build_fdiv f1 f2 "Inst08" b in - let inst09 = build_urem p1 inst07 "Inst09" b in - let inst10 = build_srem p1 inst09 "Inst10" b in - ignore(build_frem f1 inst08 "Inst11" b); - let inst12 = build_shl p1 inst10 "Inst12" b in - let inst13 = build_lshr p1 inst12 "Inst13" b in - let inst14 = build_ashr p1 inst13 "Inst14" b in - let inst15 = build_and p1 inst14 "Inst15" b in - let inst16 = build_or p1 inst15 "Inst16" b in - let inst17 = build_xor p1 inst16 "Inst17" b in - let inst18 = build_neg inst17 "Inst18" b in - ignore (build_not inst18 "Inst19" b); - ignore (build_unreachable b) + ignore (build_add p1 p2 "build_add" b); + ignore (build_nsw_add p1 p2 "build_nsw_add" b); + ignore (build_nuw_add p1 p2 "build_nuw_add" b); + ignore (build_fadd f1 f2 "build_fadd" b); + ignore (build_sub p1 p2 "build_sub" b); + ignore (build_nsw_sub p1 p2 "build_nsw_sub" b); + ignore (build_nuw_sub p1 p2 "build_nuw_sub" b); + ignore (build_fsub f1 f2 "build_fsub" b); + ignore (build_mul p1 p2 "build_mul" b); + ignore (build_nsw_mul p1 p2 "build_nsw_mul" b); + ignore (build_nuw_mul p1 p2 "build_nuw_mul" b); + ignore (build_fmul f1 f2 "build_fmul" b); + ignore (build_udiv p1 p2 "build_udiv" b); + ignore (build_sdiv p1 p2 "build_sdiv" b); + ignore (build_exact_sdiv p1 p2 "build_exact_sdiv" b); + ignore (build_fdiv f1 f2 "build_fdiv" b); + ignore (build_urem p1 p2 "build_urem" b); + ignore (build_srem p1 p2 "build_srem" b); + ignore (build_frem f1 f2 "build_frem" b); + ignore (build_shl p1 p2 "build_shl" b); + ignore (build_lshr p1 p2 "build_lshl" b); + ignore (build_ashr p1 p2 "build_ashl" b); + ignore (build_and p1 p2 "build_and" b); + ignore (build_or p1 p2 "build_or" b); + ignore (build_xor p1 p2 "build_xor" b); + ignore (build_neg p1 "build_neg" b); + ignore (build_nsw_neg p1 "build_nsw_neg" b); + ignore (build_nuw_neg p1 "build_nuw_neg" b); + ignore (build_fneg f1 "build_fneg" b); + ignore (build_not p1 "build_not" b); + ignore (build_unreachable b) end; group "memory"; begin let bb08 = append_block context "Bb08" fn in let b = builder_at_end context bb08 in - (* RUN: grep {Inst20.*malloc} < %t.ll - * RUN: grep {Inst21.*malloc} < %t.ll - * RUN: grep {Inst22.*alloca.*i32 } < %t.ll - * RUN: grep {Inst23.*alloca.*i32.*P2} < %t.ll - * RUN: grep {free.*Inst20} < %t.ll - * RUN: grep {Inst25.*load.*Inst21} < %t.ll - * RUN: grep {store.*P2.*Inst22} < %t.ll - * RUN: grep {Inst27.*getelementptr.*Inst23.*P2} < %t.ll + (* RUN: grep {%build_alloca = alloca i32} < %t.ll + * RUN: grep {%build_array_alloca = alloca i32, i32 %P2} < %t.ll + * RUN: grep {%build_load = load i32\\* %build_array_alloca} < %t.ll + * RUN: grep {store i32 %P2, i32\\* %build_alloca} < %t.ll + * RUN: grep {%build_gep = getelementptr i32\\* %build_array_alloca, i32 %P2} < %t.ll *) - let inst20 = build_malloc i8_type "Inst20" b in - let inst21 = build_array_malloc i8_type p1 "Inst21" b in - let inst22 = build_alloca i32_type "Inst22" b in - let inst23 = build_array_alloca i32_type p2 "Inst23" b in - ignore(build_free inst20 b); - ignore(build_load inst21 "Inst25" b); - ignore(build_store p2 inst22 b); - ignore(build_gep inst23 [| p2 |] "Inst27" b); - ignore(build_unreachable b) + let alloca = build_alloca i32_type "build_alloca" b in + let array_alloca = build_array_alloca i32_type p2 "build_array_alloca" b in + ignore(build_load array_alloca "build_load" b); + ignore(build_store p2 alloca b); + ignore(build_gep array_alloca [| p2 |] "build_gep" b); + ignore(build_unreachable b) end; group "casts"; begin let void_ptr = pointer_type i8_type in - (* RUN: grep {Inst28.*trunc.*P1.*i8} < %t.ll - * RUN: grep {Inst29.*zext.*Inst28.*i32} < %t.ll - * RUN: grep {Inst30.*sext.*Inst29.*i64} < %t.ll - * RUN: grep {Inst31.*uitofp.*Inst30.*float} < %t.ll - * RUN: grep {Inst32.*sitofp.*Inst29.*double} < %t.ll - * RUN: grep {Inst33.*fptoui.*Inst31.*i32} < %t.ll - * RUN: grep {Inst34.*fptosi.*Inst32.*i64} < %t.ll - * RUN: grep {Inst35.*fptrunc.*Inst32.*float} < %t.ll - * RUN: grep {Inst36.*fpext.*Inst35.*double} < %t.ll - * RUN: grep {Inst37.*inttoptr.*P1.*i8\*} < %t.ll - * RUN: grep {Inst38.*ptrtoint.*Inst37.*i64} < %t.ll - * RUN: grep {Inst39.*bitcast.*Inst38.*double} < %t.ll + (* RUN: grep {%build_trunc = trunc i32 %P1 to i8} < %t.ll + * RUN: grep {%build_zext = zext i8 %build_trunc to i32} < %t.ll + * RUN: grep {%build_sext = sext i32 %build_zext to i64} < %t.ll + * RUN: grep {%build_uitofp = uitofp i64 %build_sext to float} < %t.ll + * RUN: grep {%build_sitofp = sitofp i32 %build_zext to double} < %t.ll + * RUN: grep {%build_fptoui = fptoui float %build_uitofp to i32} < %t.ll + * RUN: grep {%build_fptosi = fptosi double %build_sitofp to i64} < %t.ll + * RUN: grep {%build_fptrunc = fptrunc double %build_sitofp to float} < %t.ll + * RUN: grep {%build_fpext = fpext float %build_fptrunc to double} < %t.ll + * RUN: grep {%build_inttoptr = inttoptr i32 %P1 to i8\\*} < %t.ll + * RUN: grep {%build_ptrtoint = ptrtoint i8\\* %build_inttoptr to i64} < %t.ll + * RUN: grep {%build_bitcast = bitcast i64 %build_ptrtoint to double} < %t.ll *) - let inst28 = build_trunc p1 i8_type "Inst28" atentry in - let inst29 = build_zext inst28 i32_type "Inst29" atentry in - let inst30 = build_sext inst29 i64_type "Inst30" atentry in - let inst31 = build_uitofp inst30 float_type "Inst31" atentry in - let inst32 = build_sitofp inst29 double_type "Inst32" atentry in - ignore(build_fptoui inst31 i32_type "Inst33" atentry); - ignore(build_fptosi inst32 i64_type "Inst34" atentry); - let inst35 = build_fptrunc inst32 float_type "Inst35" atentry in - ignore(build_fpext inst35 double_type "Inst36" atentry); - let inst37 = build_inttoptr p1 void_ptr "Inst37" atentry in - let inst38 = build_ptrtoint inst37 i64_type "Inst38" atentry in - ignore(build_bitcast inst38 double_type "Inst39" atentry) + let inst28 = build_trunc p1 i8_type "build_trunc" atentry in + let inst29 = build_zext inst28 i32_type "build_zext" atentry in + let inst30 = build_sext inst29 i64_type "build_sext" atentry in + let inst31 = build_uitofp inst30 float_type "build_uitofp" atentry in + let inst32 = build_sitofp inst29 double_type "build_sitofp" atentry in + ignore(build_fptoui inst31 i32_type "build_fptoui" atentry); + ignore(build_fptosi inst32 i64_type "build_fptosi" atentry); + let inst35 = build_fptrunc inst32 float_type "build_fptrunc" atentry in + ignore(build_fpext inst35 double_type "build_fpext" atentry); + let inst37 = build_inttoptr p1 void_ptr "build_inttoptr" atentry in + let inst38 = build_ptrtoint inst37 i64_type "build_ptrtoint" atentry in + ignore(build_bitcast inst38 double_type "build_bitcast" atentry) end; group "comparisons"; begin - (* RUN: grep {Inst40.*icmp.*ne.*P1.*P2} < %t.ll - * RUN: grep {Inst41.*icmp.*sle.*P2.*P1} < %t.ll - * RUN: grep {Inst42.*fcmp.*false.*F1.*F2} < %t.ll - * RUN: grep {Inst43.*fcmp.*true.*F2.*F1} < %t.ll + (* RUN: grep {%build_icmp_ne = icmp ne i32 %P1, %P2} < %t.ll + * RUN: grep {%build_icmp_sle = icmp sle i32 %P2, %P1} < %t.ll + * RUN: grep {%build_icmp_false = fcmp false float %F1, %F2} < %t.ll + * RUN: grep {%build_icmp_true = fcmp true float %F2, %F1} < %t.ll *) - ignore (build_icmp Icmp.Ne p1 p2 "Inst40" atentry); - ignore (build_icmp Icmp.Sle p2 p1 "Inst41" atentry); - ignore (build_fcmp Fcmp.False f1 f2 "Inst42" atentry); - ignore (build_fcmp Fcmp.True f2 f1 "Inst43" atentry) + ignore (build_icmp Icmp.Ne p1 p2 "build_icmp_ne" atentry); + ignore (build_icmp Icmp.Sle p2 p1 "build_icmp_sle" atentry); + ignore (build_fcmp Fcmp.False f1 f2 "build_icmp_false" atentry); + ignore (build_fcmp Fcmp.True f2 f1 "build_icmp_true" atentry) end; group "miscellaneous"; begin - (* RUN: grep {CallInst.*call.*P2.*P1} < %t.ll - * RUN: grep {CallInst.*cc63} < %t.ll - * RUN: grep {Inst47.*select.*Inst46.*P1.*P2} < %t.ll - * RUN: grep {Inst48.*va_arg.*null.*i32} < %t.ll - * RUN: grep {Inst49.*extractelement.*Vec1.*P2} < %t.ll - * RUN: grep {Inst50.*insertelement.*Vec1.*P1.*P2} < %t.ll - * RUN: grep {Inst51.*shufflevector.*Vec1.*Vec2.*1.*1.*0.*0} < %t.ll - * RUN: grep {CallInst.*tail call} < %t.ll + (* RUN: grep {%build_call = tail call cc63 i32 @.*(i32 signext %P2, i32 %P1)} < %t.ll + * RUN: grep {%build_select = select i1 %build_icmp, i32 %P1, i32 %P2} < %t.ll + * RUN: grep {%build_va_arg = va_arg i8\\*\\* null, i32} < %t.ll + * RUN: grep {%build_extractelement = extractelement <4 x i32> %Vec1, i32 %P2} < %t.ll + * RUN: grep {%build_insertelement = insertelement <4 x i32> %Vec1, i32 %P1, i32 %P2} < %t.ll + * RUN: grep {%build_shufflevector = shufflevector <4 x i32> %Vec1, <4 x i32> %Vec2, <4 x i32> } < %t.ll *) - let ci = build_call fn [| p2; p1 |] "CallInst" atentry in + let ci = build_call fn [| p2; p1 |] "build_call" atentry in insist (CallConv.c = instruction_call_conv ci); set_instruction_call_conv 63 ci; insist (63 = instruction_call_conv ci); @@ -1020,11 +1182,11 @@ let test_builder () = add_instruction_param_attr ci 2 Attribute.Noalias; remove_instruction_param_attr ci 2 Attribute.Noalias; - let inst46 = build_icmp Icmp.Eq p1 p2 "Inst46" atentry in - ignore (build_select inst46 p1 p2 "Inst47" atentry); - ignore (build_va_arg - (const_null (pointer_type (pointer_type i8_type))) - i32_type "Inst48" atentry); + let inst46 = build_icmp Icmp.Eq p1 p2 "build_icmp" atentry in + ignore (build_select inst46 p1 p2 "build_select" atentry); + ignore (build_va_arg + (const_null (pointer_type (pointer_type i8_type))) + i32_type "build_va_arg" atentry); (* Set up some vector vregs. *) let one = const_int i32_type 1 in @@ -1035,9 +1197,49 @@ let test_builder () = let vec1 = build_insertelement t1 p1 p2 "Vec1" atentry in let vec2 = build_insertelement t2 p1 p2 "Vec2" atentry in - ignore (build_extractelement vec1 p2 "Inst49" atentry); - ignore (build_insertelement vec1 p1 p2 "Inst50" atentry); - ignore (build_shufflevector vec1 vec2 t3 "Inst51" atentry); + ignore (build_extractelement vec1 p2 "build_extractelement" atentry); + ignore (build_insertelement vec1 p1 p2 "build_insertelement" atentry); + ignore (build_shufflevector vec1 vec2 t3 "build_shufflevector" atentry); + end; + + group "metadata"; begin + (* RUN: grep {%metadata = add i32 %P1, %P2, !test !0} < %t.ll + * RUN: grep {!0 = metadata !\{i32 1, metadata !"metadata test"\}} < %t.ll + *) + let i = build_add p1 p2 "metadata" atentry in + insist ((has_metadata i) = false); + + let m1 = const_int i32_type 1 in + let m2 = mdstring context "metadata test" in + let md = mdnode context [| m1; m2 |] in + + let kind = mdkind_id context "test" in + set_metadata i kind md; + + insist ((has_metadata i) = true); + insist ((metadata i kind) = Some md); + + clear_metadata i kind; + + insist ((has_metadata i) = false); + insist ((metadata i kind) = None); + + set_metadata i kind md + end; + + group "dbg"; begin + (* RUN: grep {%dbg = add i32 %P1, %P2, !dbg !1} < %t.ll + * RUN: grep {!1 = metadata !\{i32 2, metadata !"dbg test"\}} < %t.ll + *) + let m1 = const_int i32_type 2 in + let m2 = mdstring context "dbg test" in + let md = mdnode context [| m1; m2 |] in + set_current_debug_location atentry md; + + let i = build_add p1 p2 "dbg" atentry in + insist ((has_metadata i) = true); + + clear_current_debug_location atentry end; group "phi"; begin @@ -1061,14 +1263,6 @@ let test_builder () = end -(*===-- Module Provider ---------------------------------------------------===*) - -let test_module_provider () = - let m = create_module context "test" in - let mp = ModuleProvider.create m in - ModuleProvider.dispose mp - - (*===-- Pass Managers -----------------------------------------------------===*) let test_pass_manager () = @@ -1085,7 +1279,7 @@ let test_pass_manager () = let fn = define_function "FunctionPassManager" fty m in ignore (build_ret_void (builder_at_end context (entry_block fn))); - ignore (PassManager.create_function mp + ignore (PassManager.create_function m ++ PassManager.initialize ++ PassManager.run_function fn ++ PassManager.finalize @@ -1104,7 +1298,7 @@ let test_writer () = group "writer"; insist (write_bitcode_file m filename); - ModuleProvider.dispose mp + dispose_module m (*===-- Driver ------------------------------------------------------------===*) @@ -1115,12 +1309,14 @@ let _ = suite "constants" test_constants; suite "global values" test_global_values; suite "global variables" test_global_variables; + suite "uses" test_uses; + suite "users" test_users; + suite "aliases" test_aliases; suite "functions" test_functions; suite "params" test_params; suite "basic blocks" test_basic_blocks; suite "instructions" test_instructions; suite "builder" test_builder; - suite "module provider" test_module_provider; suite "pass manager" test_pass_manager; suite "writer" test_writer; (* Keep this last; it disposes m. *) exit !exit_status diff --git a/test/CodeGen/ARM/2010-03-04-eabi-fp-spill.ll b/test/CodeGen/ARM/2010-03-04-eabi-fp-spill.ll new file mode 100644 index 0000000000..f7adf73263 --- /dev/null +++ b/test/CodeGen/ARM/2010-03-04-eabi-fp-spill.ll @@ -0,0 +1,65 @@ +; RUN: llc < %s -mtriple=arm-unknown-linux-gnueabi + +define void @"java.lang.String::getChars"([84 x i8]* %method, i32 %base_pc, [788 x i8]* %thread) { + %1 = load i32* undef ; [#uses=1] + %2 = sub i32 %1, 48 ; [#uses=1] + br i1 undef, label %stack_overflow, label %no_overflow + +stack_overflow: ; preds = %0 + unreachable + +no_overflow: ; preds = %0 + %frame = inttoptr i32 %2 to [17 x i32]* ; <[17 x i32]*> [#uses=4] + %3 = load i32* undef ; [#uses=1] + %4 = load i32* null ; [#uses=1] + %5 = getelementptr inbounds [17 x i32]* %frame, i32 0, i32 13 ; [#uses=1] + %6 = bitcast i32* %5 to [8 x i8]** ; <[8 x i8]**> [#uses=1] + %7 = load [8 x i8]** %6 ; <[8 x i8]*> [#uses=1] + %8 = getelementptr inbounds [17 x i32]* %frame, i32 0, i32 12 ; [#uses=1] + %9 = load i32* %8 ; [#uses=1] + br i1 undef, label %bci_13, label %bci_4 + +bci_13: ; preds = %no_overflow + br i1 undef, label %bci_30, label %bci_21 + +bci_30: ; preds = %bci_13 + br i1 undef, label %bci_46, label %bci_35 + +bci_46: ; preds = %bci_30 + %10 = sub i32 %4, %3 ; [#uses=1] + %11 = load [8 x i8]** null ; <[8 x i8]*> [#uses=1] + %callee = bitcast [8 x i8]* %11 to [84 x i8]* ; <[84 x i8]*> [#uses=1] + %12 = bitcast i8* undef to i32* ; [#uses=1] + %base_pc7 = load i32* %12 ; [#uses=2] + %13 = add i32 %base_pc7, 0 ; [#uses=1] + %14 = inttoptr i32 %13 to void ([84 x i8]*, i32, [788 x i8]*)** ; [#uses=1] + %entry_point = load void ([84 x i8]*, i32, [788 x i8]*)** %14 ; [#uses=1] + %15 = getelementptr inbounds [17 x i32]* %frame, i32 0, i32 1 ; [#uses=1] + %16 = ptrtoint i32* %15 to i32 ; [#uses=1] + %stack_pointer_addr9 = bitcast i8* undef to i32* ; [#uses=1] + store i32 %16, i32* %stack_pointer_addr9 + %17 = getelementptr inbounds [17 x i32]* %frame, i32 0, i32 2 ; [#uses=1] + store i32 %9, i32* %17 + store i32 %10, i32* undef + store [84 x i8]* %method, [84 x i8]** undef + %18 = add i32 %base_pc, 20 ; [#uses=1] + store i32 %18, i32* undef + store [8 x i8]* %7, [8 x i8]** undef + call void %entry_point([84 x i8]* %callee, i32 %base_pc7, [788 x i8]* %thread) + br i1 undef, label %no_exception, label %exception + +exception: ; preds = %bci_46 + ret void + +no_exception: ; preds = %bci_46 + ret void + +bci_35: ; preds = %bci_30 + ret void + +bci_21: ; preds = %bci_13 + ret void + +bci_4: ; preds = %no_overflow + ret void +} diff --git a/test/CodeGen/ARM/2010-03-04-stm-undef-addr.ll b/test/CodeGen/ARM/2010-03-04-stm-undef-addr.ll new file mode 100644 index 0000000000..b0b4cb37d1 --- /dev/null +++ b/test/CodeGen/ARM/2010-03-04-stm-undef-addr.ll @@ -0,0 +1,54 @@ +; RUN: llc < %s -march=arm + +define void @"java.lang.String::getChars"([84 x i8]* %method, i32 %base_pc, [788 x i8]* %thread) { + %1 = sub i32 undef, 48 ; [#uses=1] + br i1 undef, label %stack_overflow, label %no_overflow + +stack_overflow: ; preds = %0 + unreachable + +no_overflow: ; preds = %0 + %frame = inttoptr i32 %1 to [17 x i32]* ; <[17 x i32]*> [#uses=4] + %2 = load i32* null ; [#uses=2] + %3 = getelementptr inbounds [17 x i32]* %frame, i32 0, i32 14 ; [#uses=1] + %4 = load i32* %3 ; [#uses=2] + %5 = load [8 x i8]** undef ; <[8 x i8]*> [#uses=2] + br i1 undef, label %bci_13, label %bci_4 + +bci_13: ; preds = %no_overflow + br i1 undef, label %bci_30, label %bci_21 + +bci_30: ; preds = %bci_13 + %6 = icmp sle i32 %2, %4 ; [#uses=1] + br i1 %6, label %bci_46, label %bci_35 + +bci_46: ; preds = %bci_30 + store [84 x i8]* %method, [84 x i8]** undef + br i1 false, label %no_exception, label %exception + +exception: ; preds = %bci_46 + ret void + +no_exception: ; preds = %bci_46 + ret void + +bci_35: ; preds = %bci_30 + %7 = getelementptr inbounds [17 x i32]* %frame, i32 0, i32 15 ; [#uses=1] + store i32 %2, i32* %7 + %8 = getelementptr inbounds [17 x i32]* %frame, i32 0, i32 14 ; [#uses=1] + store i32 %4, i32* %8 + %9 = getelementptr inbounds [17 x i32]* %frame, i32 0, i32 13 ; [#uses=1] + %10 = bitcast i32* %9 to [8 x i8]** ; <[8 x i8]**> [#uses=1] + store [8 x i8]* %5, [8 x i8]** %10 + call void inttoptr (i32 13839116 to void ([788 x i8]*, i32)*)([788 x i8]* %thread, i32 7) + ret void + +bci_21: ; preds = %bci_13 + ret void + +bci_4: ; preds = %no_overflow + store [8 x i8]* %5, [8 x i8]** undef + store i32 undef, i32* undef + call void inttoptr (i32 13839116 to void ([788 x i8]*, i32)*)([788 x i8]* %thread, i32 7) + ret void +} diff --git a/test/CodeGen/ARM/arm-negative-stride.ll b/test/CodeGen/ARM/arm-negative-stride.ll index 72ec8efcc4..52ab8717c1 100644 --- a/test/CodeGen/ARM/arm-negative-stride.ll +++ b/test/CodeGen/ARM/arm-negative-stride.ll @@ -1,7 +1,32 @@ ; RUN: llc < %s -march=arm | FileCheck %s +; This loop is rewritten with an indvar which counts down, which +; frees up a register from holding the trip count. + define void @test(i32* %P, i32 %A, i32 %i) nounwind { entry: +; CHECK: str r1, [{{r.*}}, +{{r.*}}, lsl #2] + icmp eq i32 %i, 0 ; :0 [#uses=1] + br i1 %0, label %return, label %bb + +bb: ; preds = %bb, %entry + %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=2] + %i_addr.09.0 = sub i32 %i, %indvar ; [#uses=1] + %tmp2 = getelementptr i32* %P, i32 %i_addr.09.0 ; [#uses=1] + store i32 %A, i32* %tmp2 + %indvar.next = add i32 %indvar, 1 ; [#uses=2] + icmp eq i32 %indvar.next, %i ; :1 [#uses=1] + br i1 %1, label %return, label %bb + +return: ; preds = %bb, %entry + ret void +} + +; This loop has a non-address use of the count-up indvar, so +; it'll remain. Now the original store uses a negative-stride address. + +define void @test_with_forced_iv(i32* %P, i32 %A, i32 %i) nounwind { +entry: ; CHECK: str r1, [{{r.*}}, -{{r.*}}, lsl #2] icmp eq i32 %i, 0 ; :0 [#uses=1] br i1 %0, label %return, label %bb @@ -11,6 +36,7 @@ bb: ; preds = %bb, %entry %i_addr.09.0 = sub i32 %i, %indvar ; [#uses=1] %tmp2 = getelementptr i32* %P, i32 %i_addr.09.0 ; [#uses=1] store i32 %A, i32* %tmp2 + store i32 %indvar, i32* null %indvar.next = add i32 %indvar, 1 ; [#uses=2] icmp eq i32 %indvar.next, %i ; :1 [#uses=1] br i1 %1, label %return, label %bb diff --git a/test/CodeGen/ARM/armv4.ll b/test/CodeGen/ARM/armv4.ll new file mode 100644 index 0000000000..49b129dabd --- /dev/null +++ b/test/CodeGen/ARM/armv4.ll @@ -0,0 +1,13 @@ +; RUN: llc < %s -mtriple=arm-unknown-eabi | FileCheck %s -check-prefix=THUMB +; RUN: llc < %s -mtriple=arm-unknown-eabi -mcpu=strongarm | FileCheck %s -check-prefix=ARM +; RUN: llc < %s -mtriple=arm-unknown-eabi -mcpu=cortex-a8 | FileCheck %s -check-prefix=THUMB +; RUN: llc < %s -mtriple=arm-unknown-eabi -mattr=+v6 | FileCheck %s -check-prefix=THUMB +; RUN: llc < %s -mtriple=armv4-unknown-eabi | FileCheck %s -check-prefix=ARM +; RUN: llc < %s -mtriple=armv4t-unknown-eabi | FileCheck %s -check-prefix=THUMB + +define arm_aapcscc i32 @test(i32 %a) nounwind readnone { +entry: +; ARM: mov pc +; THUMB: bx + ret i32 %a +} diff --git a/test/CodeGen/ARM/call.ll b/test/CodeGen/ARM/call.ll index 3dd66ae71d..c60b75b574 100644 --- a/test/CodeGen/ARM/call.ll +++ b/test/CodeGen/ARM/call.ll @@ -20,3 +20,17 @@ define void @g.upgrd.1() { %tmp.upgrd.2 = tail call i32 %tmp( ) ; [#uses=0] ret void } + +define i32* @m_231b(i32, i32, i32*, i32*, i32*) nounwind { +; CHECKV4: m_231b +; CHECKV4: bx r{{.*}} +BB0: + %5 = inttoptr i32 %0 to i32* ; [#uses=1] + %t35 = volatile load i32* %5 ; [#uses=1] + %6 = inttoptr i32 %t35 to i32** ; [#uses=1] + %7 = getelementptr i32** %6, i32 86 ; [#uses=1] + %8 = load i32** %7 ; [#uses=1] + %9 = bitcast i32* %8 to i32* (i32, i32*, i32, i32*, i32*, i32*)* ; [#uses=1] + %10 = call i32* %9(i32 %0, i32* null, i32 %1, i32* %2, i32* %3, i32* %4) ; [#uses=1] + ret i32* %10 +} diff --git a/test/CodeGen/ARM/lsr-code-insertion.ll b/test/CodeGen/ARM/lsr-code-insertion.ll index 507ec2c7bd..1bbb96deee 100644 --- a/test/CodeGen/ARM/lsr-code-insertion.ll +++ b/test/CodeGen/ARM/lsr-code-insertion.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -stats |& grep {40.*Number of machine instrs printed} -; RUN: llc < %s -stats |& grep {.*Number of re-materialization} +; RUN: llc < %s -stats |& grep {39.*Number of machine instrs printed} +; RUN: llc < %s -stats |& not grep {.*Number of re-materialization} ; This test really wants to check that the resultant "cond_true" block only ; has a single store in it, and that cond_true55 only has code to materialize ; the constant and do a store. We do *not* want something like this: diff --git a/test/CodeGen/ARM/neon_minmax.ll b/test/CodeGen/ARM/neon_minmax.ll new file mode 100644 index 0000000000..d301c6a4ca --- /dev/null +++ b/test/CodeGen/ARM/neon_minmax.ll @@ -0,0 +1,81 @@ +; RUN: llc < %s -march=arm -mcpu=cortex-a8 | FileCheck %s + +define float @fmin_ole(float %x) nounwind { +;CHECK: fmin_ole: +;CHECK: vmin.f32 + %cond = fcmp ole float 1.0, %x + %min1 = select i1 %cond, float 1.0, float %x + ret float %min1 +} + +define float @fmin_ole_zero(float %x) nounwind { +;CHECK: fmin_ole_zero: +;CHECK-NOT: vmin.f32 + %cond = fcmp ole float 0.0, %x + %min1 = select i1 %cond, float 0.0, float %x + ret float %min1 +} + +define float @fmin_ult(float %x) nounwind { +;CHECK: fmin_ult: +;CHECK: vmin.f32 + %cond = fcmp ult float %x, 1.0 + %min1 = select i1 %cond, float %x, float 1.0 + ret float %min1 +} + +define float @fmax_ogt(float %x) nounwind { +;CHECK: fmax_ogt: +;CHECK: vmax.f32 + %cond = fcmp ogt float 1.0, %x + %max1 = select i1 %cond, float 1.0, float %x + ret float %max1 +} + +define float @fmax_uge(float %x) nounwind { +;CHECK: fmax_uge: +;CHECK: vmax.f32 + %cond = fcmp uge float %x, 1.0 + %max1 = select i1 %cond, float %x, float 1.0 + ret float %max1 +} + +define float @fmax_uge_zero(float %x) nounwind { +;CHECK: fmax_uge_zero: +;CHECK-NOT: vmax.f32 + %cond = fcmp uge float %x, 0.0 + %max1 = select i1 %cond, float %x, float 0.0 + ret float %max1 +} + +define float @fmax_olt_reverse(float %x) nounwind { +;CHECK: fmax_olt_reverse: +;CHECK: vmax.f32 + %cond = fcmp olt float %x, 1.0 + %max1 = select i1 %cond, float 1.0, float %x + ret float %max1 +} + +define float @fmax_ule_reverse(float %x) nounwind { +;CHECK: fmax_ule_reverse: +;CHECK: vmax.f32 + %cond = fcmp ult float 1.0, %x + %max1 = select i1 %cond, float %x, float 1.0 + ret float %max1 +} + +define float @fmin_oge_reverse(float %x) nounwind { +;CHECK: fmin_oge_reverse: +;CHECK: vmin.f32 + %cond = fcmp oge float %x, 1.0 + %min1 = select i1 %cond, float 1.0, float %x + ret float %min1 +} + +define float @fmin_ugt_reverse(float %x) nounwind { +;CHECK: fmin_ugt_reverse: +;CHECK: vmin.f32 + %cond = fcmp ugt float 1.0, %x + %min1 = select i1 %cond, float %x, float 1.0 + ret float %min1 +} diff --git a/test/CodeGen/ARM/remat.ll b/test/CodeGen/ARM/remat.ll index 367f782e0f..92c1cf1821 100644 --- a/test/CodeGen/ARM/remat.ll +++ b/test/CodeGen/ARM/remat.ll @@ -32,16 +32,16 @@ bb.i35: ; preds = %bb142 br label %phi1.exit phi1.exit: ; preds = %bb.i35, %bb142 - %.pn = phi double [ %6, %bb.i35 ], [ 0.000000e+00, %bb142 ] ; [#uses=0] + %.pn = phi double [ %6, %bb.i35 ], [ 0.000000e+00, %bb142 ] ; [#uses=1] %9 = phi double [ %8, %bb.i35 ], [ 0.000000e+00, %bb142 ] ; [#uses=1] - %10 = fmul double undef, %9 ; [#uses=0] + %10 = fmul double %.pn, %9 ; [#uses=1] br i1 %14, label %phi0.exit, label %bb.i bb.i: ; preds = %phi1.exit unreachable phi0.exit: ; preds = %phi1.exit - %11 = fsub double %4, undef ; [#uses=1] + %11 = fsub double %4, %10 ; [#uses=1] %12 = fadd double 0.000000e+00, %11 ; [#uses=1] store double %12, double* undef, align 4 br label %bb142 diff --git a/test/CodeGen/Alpha/add.ll b/test/CodeGen/Alpha/add.ll index 24a74188f8..cd883f64a6 100644 --- a/test/CodeGen/Alpha/add.ll +++ b/test/CodeGen/Alpha/add.ll @@ -4,9 +4,8 @@ ; RUN: grep { addl} %t.s | count 2 ; RUN: grep { addq} %t.s | count 2 ; RUN: grep { subl} %t.s | count 2 -; RUN: grep { subq} %t.s | count 1 +; RUN: grep { subq} %t.s | count 2 ; -; RUN: grep {lda \$0,-100(\$16)} %t.s | count 1 ; RUN: grep {s4addl} %t.s | count 2 ; RUN: grep {s8addl} %t.s | count 2 ; RUN: grep {s4addq} %t.s | count 2 diff --git a/test/CodeGen/Blackfin/promote-logic.ll b/test/CodeGen/Blackfin/promote-logic.ll index 46da56681d..1ac1408290 100644 --- a/test/CodeGen/Blackfin/promote-logic.ll +++ b/test/CodeGen/Blackfin/promote-logic.ll @@ -1,5 +1,4 @@ -; RUN: llc < %s -march=bfin > %t -; XFAIL: * +; RUN: llc < %s -march=bfin ; DAGCombiner::SimplifyBinOpWithSameOpcodeHands can produce an illegal i16 OR ; operation after LegalizeOps. diff --git a/test/CodeGen/CellSPU/bss.ll b/test/CodeGen/CellSPU/bss.ll new file mode 100644 index 0000000000..05a0f50039 --- /dev/null +++ b/test/CodeGen/CellSPU/bss.ll @@ -0,0 +1,5 @@ +; RUN: llc < %s -march=cellspu > %t1.s +; RUN: grep "\.section" %t1.s | grep "\.bss" | count 1 + +@bssVar = global i32 zeroinitializer + diff --git a/test/CodeGen/Generic/2007-05-05-Personality.ll b/test/CodeGen/Generic/2007-05-05-Personality.ll index 27493261d5..c92783e5e4 100644 --- a/test/CodeGen/Generic/2007-05-05-Personality.ll +++ b/test/CodeGen/Generic/2007-05-05-Personality.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=i686-pc-linux-gnu -enable-eh -o - | grep zPLR +; RUN: llc < %s -mtriple=i686-pc-linux-gnu -enable-eh -o - | grep zPL @error = external global i8 ; [#uses=2] diff --git a/test/CodeGen/Generic/GC/argpromotion.ll b/test/CodeGen/Generic/GC/argpromotion.ll index dda376d616..c63ce222b8 100644 --- a/test/CodeGen/Generic/GC/argpromotion.ll +++ b/test/CodeGen/Generic/GC/argpromotion.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -anders-aa -argpromotion +; RUN: opt < %s -argpromotion declare void @llvm.gcroot(i8**, i8*) diff --git a/test/CodeGen/Generic/debug-info.ll b/test/CodeGen/Generic/debug-info.ll deleted file mode 100644 index 20d9f913c1..0000000000 --- a/test/CodeGen/Generic/debug-info.ll +++ /dev/null @@ -1,19 +0,0 @@ -; RUN: llc < %s - - %lldb.compile_unit = type { i32, i16, i16, i8*, i8*, i8*, { }* } -@d.compile_unit7 = external global %lldb.compile_unit ; <%lldb.compile_unit*> [#uses=1] - -declare void @llvm.dbg.stoppoint(i32, i32, %lldb.compile_unit*) - -define void @rb_raise(i32, ...) { -entry: - br i1 false, label %strlen.exit, label %no_exit.i - -no_exit.i: ; preds = %entry - ret void - -strlen.exit: ; preds = %entry - call void @llvm.dbg.stoppoint( i32 4358, i32 0, %lldb.compile_unit* @d.compile_unit7 ) - unreachable -} - diff --git a/test/CodeGen/MBlaze/brind.ll b/test/CodeGen/MBlaze/brind.ll new file mode 100644 index 0000000000..7798e0f56a --- /dev/null +++ b/test/CodeGen/MBlaze/brind.ll @@ -0,0 +1,73 @@ +; Ensure that the select instruction is supported and is lowered to +; some sort of branch instruction. +; +; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s + +declare i32 @printf(i8*, ...) +@MSG = internal constant [13 x i8] c"Message: %d\0A\00" + +@BLKS = private constant [5 x i8*] + [ i8* blockaddress(@brind, %L1), + i8* blockaddress(@brind, %L2), + i8* blockaddress(@brind, %L3), + i8* blockaddress(@brind, %L4), + i8* blockaddress(@brind, %L5) ] + +define i32 @brind(i32 %a, i32 %b) +{ + ; CHECK: brind: +entry: + br label %loop + +loop: + %tmp.0 = phi i32 [ 0, %entry ], [ %tmp.8, %finish ] + %dst.0 = getelementptr [5 x i8*]* @BLKS, i32 0, i32 %tmp.0 + %dst.1 = load i8** %dst.0 + indirectbr i8* %dst.1, [ label %L1, + label %L2, + label %L3, + label %L4, + label %L5 ] + ; CHECK: br {{r[0-9]*}} + +L1: + %tmp.1 = add i32 %a, %b + br label %finish + ; CHECK: br + +L2: + %tmp.2 = sub i32 %a, %b + br label %finish + ; CHECK: br + +L3: + %tmp.3 = mul i32 %a, %b + br label %finish + ; CHECK: br + +L4: + %tmp.4 = sdiv i32 %a, %b + br label %finish + ; CHECK: br + +L5: + %tmp.5 = srem i32 %a, %b + br label %finish + ; CHECK: br + +finish: + %tmp.6 = phi i32 [ %tmp.1, %L1 ], + [ %tmp.2, %L2 ], + [ %tmp.3, %L3 ], + [ %tmp.4, %L4 ], + [ %tmp.5, %L5 ] + + call i32 (i8*,...)* @printf( i8* getelementptr([13 x i8]* @MSG,i32 0,i32 0), + i32 %tmp.6) + + %tmp.7 = add i32 %tmp.0, 1 + %tmp.8 = urem i32 %tmp.7, 5 + + br label %loop + ; CHECK: br +} diff --git a/test/CodeGen/MBlaze/callind.ll b/test/CodeGen/MBlaze/callind.ll new file mode 100644 index 0000000000..bfc8d001fd --- /dev/null +++ b/test/CodeGen/MBlaze/callind.ll @@ -0,0 +1,80 @@ +; Ensure that indirect calls work and that they are lowered to some +; sort of branch and link instruction. +; +; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s + +declare i32 @printf(i8*, ...) +@MSG = internal constant [13 x i8] c"Message: %d\0A\00" + +@FUNS = private constant [5 x i32 (i32,i32)*] + [ i32 (i32,i32)* @doadd, + i32 (i32,i32)* @dosub, + i32 (i32,i32)* @domul, + i32 (i32,i32)* @dodiv, + i32 (i32,i32)* @dorem ] + +define i32 @doadd(i32 %a, i32 %b) +{ + ; CHECK: doadd: + %tmp.0 = add i32 %a, %b + ret i32 %tmp.0 + ; CHECK: rtsd +} + +define i32 @dosub(i32 %a, i32 %b) +{ + ; CHECK: dosub: + %tmp.0 = sub i32 %a, %b + ret i32 %tmp.0 + ; CHECK: rtsd +} + +define i32 @domul(i32 %a, i32 %b) +{ + ; CHECK: domul: + %tmp.0 = mul i32 %a, %b + ret i32 %tmp.0 + ; CHECK: rtsd +} + +define i32 @dodiv(i32 %a, i32 %b) +{ + ; CHECK: dodiv: + %tmp.0 = sdiv i32 %a, %b + ret i32 %tmp.0 + ; CHECK: rtsd +} + +define i32 @dorem(i32 %a, i32 %b) +{ + ; CHECK: dorem: + %tmp.0 = srem i32 %a, %b + ret i32 %tmp.0 + ; CHECK: rtsd +} + +define i32 @callind(i32 %a, i32 %b) +{ + ; CHECK: callind: +entry: + br label %loop + +loop: + %tmp.0 = phi i32 [ 0, %entry ], [ %tmp.3, %loop ] + %dst.0 = getelementptr [5 x i32 (i32,i32)*]* @FUNS, i32 0, i32 %tmp.0 + %dst.1 = load i32 (i32,i32)** %dst.0 + %tmp.1 = call i32 %dst.1(i32 %a, i32 %b) + ; CHECK-NOT: brli + ; CHECK-NOT: brlai + ; CHECK: brl + + call i32 (i8*,...)* @printf( i8* getelementptr([13 x i8]* @MSG,i32 0,i32 0), + i32 %tmp.1) + ; CHECK: brl + + %tmp.2 = add i32 %tmp.0, 1 + %tmp.3 = urem i32 %tmp.2, 5 + + br label %loop + ; CHECK: br +} diff --git a/test/CodeGen/MBlaze/cc.ll b/test/CodeGen/MBlaze/cc.ll new file mode 100644 index 0000000000..aaa918ffc3 --- /dev/null +++ b/test/CodeGen/MBlaze/cc.ll @@ -0,0 +1,315 @@ +; Test some of the calling convention lowering done by the MBlaze backend. +; We test that integer values are passed in the correct registers and +; returned in the correct registers. Additionally, we test that the stack +; is used as appropriate for passing arguments that cannot be placed into +; registers. +; +; RUN: llc < %s -march=mblaze | FileCheck %s + +declare i32 @printf(i8*, ...) +@MSG = internal constant [13 x i8] c"Message: %d\0A\00" + +define void @params0_noret() { + ; CHECK: params0_noret: + ret void + ; CHECK-NOT: {{.* r3, r0, 1}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i8 @params0_8bitret() { + ; CHECK: params0_8bitret: + ret i8 1 + ; CHECK: {{.* r3, r0, 1}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i16 @params0_16bitret() { + ; CHECK: params0_16bitret: + ret i16 1 + ; CHECK: {{.* r3, r0, 1}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params0_32bitret() { + ; CHECK: params0_32bitret: + ret i32 1 + ; CHECK: {{.* r3, r0, 1}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i64 @params0_64bitret() { + ; CHECK: params0_64bitret: + ret i64 1 + ; CHECK: {{.* r3, r0, .*}} + ; CHECK: {{.* r4, r0, 1}} + ; CHECK: rtsd +} + +define i32 @params1_32bitret(i32 %a) { + ; CHECK: params1_32bitret: + ret i32 %a + ; CHECK: {{.* r3, r5, r0}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params2_32bitret(i32 %a, i32 %b) { + ; CHECK: params2_32bitret: + ret i32 %b + ; CHECK: {{.* r3, r6, r0}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params3_32bitret(i32 %a, i32 %b, i32 %c) { + ; CHECK: params3_32bitret: + ret i32 %c + ; CHECK: {{.* r3, r7, r0}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params4_32bitret(i32 %a, i32 %b, i32 %c, i32 %d) { + ; CHECK: params4_32bitret: + ret i32 %d + ; CHECK: {{.* r3, r8, r0}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params5_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) { + ; CHECK: params5_32bitret: + ret i32 %e + ; CHECK: {{.* r3, r9, r0}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params6_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) { + ; CHECK: params6_32bitret: + ret i32 %f + ; CHECK: {{.* r3, r10, r0}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params7_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, + i32 %g) { + ; CHECK: params7_32bitret: + ret i32 %g + ; CHECK: {{lwi? r3, r1, 32}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params8_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, + i32 %g, i32 %h) { + ; CHECK: params8_32bitret: + ret i32 %h + ; CHECK: {{lwi? r3, r1, 36}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params9_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, + i32 %g, i32 %h, i32 %i) { + ; CHECK: params9_32bitret: + ret i32 %i + ; CHECK: {{lwi? r3, r1, 40}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define i32 @params10_32bitret(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, + i32 %g, i32 %h, i32 %i, i32 %j) { + ; CHECK: params10_32bitret: + ret i32 %j + ; CHECK: {{lwi? r3, r1, 44}} + ; CHECK-NOT: {{.* r4, .*, .*}} + ; CHECK: rtsd +} + +define void @testing() { + %MSG.1 = getelementptr [13 x i8]* @MSG, i32 0, i32 0 + + call void @params0_noret() + ; CHECK: brlid + + %tmp.1 = call i8 @params0_8bitret() + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i8 %tmp.1) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.2 = call i16 @params0_16bitret() + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i16 %tmp.2) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.3 = call i32 @params0_32bitret() + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.3) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.4 = call i64 @params0_64bitret() + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i64 %tmp.4) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK: {{.* r7, r4, r0}} + ; CHECK: brlid + + %tmp.5 = call i32 @params1_32bitret(i32 1) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.5) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.6 = call i32 @params2_32bitret(i32 1, i32 2) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.6) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.7 = call i32 @params3_32bitret(i32 1, i32 2, i32 3) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: {{.* r7, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.7) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.8 = call i32 @params4_32bitret(i32 1, i32 2, i32 3, i32 4) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: {{.* r7, .*, .*}} + ; CHECK: {{.* r8, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.8) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.9 = call i32 @params5_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: {{.* r7, .*, .*}} + ; CHECK: {{.* r8, .*, .*}} + ; CHECK: {{.* r9, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.9) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.10 = call i32 @params6_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5, + i32 6) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: {{.* r7, .*, .*}} + ; CHECK: {{.* r8, .*, .*}} + ; CHECK: {{.* r9, .*, .*}} + ; CHECK: {{.* r10, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.10) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.11 = call i32 @params7_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5, + i32 6, i32 7) + ; CHECK: {{swi? .*, r1, 28}} + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: {{.* r7, .*, .*}} + ; CHECK: {{.* r8, .*, .*}} + ; CHECK: {{.* r9, .*, .*}} + ; CHECK: {{.* r10, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.11) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.12 = call i32 @params8_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5, + i32 6, i32 7, i32 8) + ; CHECK: {{swi? .*, r1, 28}} + ; CHECK: {{swi? .*, r1, 32}} + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: {{.* r7, .*, .*}} + ; CHECK: {{.* r8, .*, .*}} + ; CHECK: {{.* r9, .*, .*}} + ; CHECK: {{.* r10, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.12) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.13 = call i32 @params9_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5, + i32 6, i32 7, i32 8, i32 9) + ; CHECK: {{swi? .*, r1, 28}} + ; CHECK: {{swi? .*, r1, 32}} + ; CHECK: {{swi? .*, r1, 36}} + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: {{.* r7, .*, .*}} + ; CHECK: {{.* r8, .*, .*}} + ; CHECK: {{.* r9, .*, .*}} + ; CHECK: {{.* r10, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.13) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + %tmp.14 = call i32 @params10_32bitret(i32 1, i32 2, i32 3, i32 4, i32 5, + i32 6, i32 7, i32 8, i32 9, i32 10) + ; CHECK: {{swi? .*, r1, 28}} + ; CHECK: {{swi? .*, r1, 32}} + ; CHECK: {{swi? .*, r1, 36}} + ; CHECK: {{swi? .*, r1, 40}} + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, .*, .*}} + ; CHECK: {{.* r7, .*, .*}} + ; CHECK: {{.* r8, .*, .*}} + ; CHECK: {{.* r9, .*, .*}} + ; CHECK: {{.* r10, .*, .*}} + ; CHECK: brlid + call i32 (i8*,...)* @printf(i8* %MSG.1, i32 %tmp.14) + ; CHECK: {{.* r5, .*, .*}} + ; CHECK: {{.* r6, r3, r0}} + ; CHECK-NOT: {{.* r7, .*, .*}} + ; CHECK: brlid + + ret void +} diff --git a/test/CodeGen/MBlaze/dg.exp b/test/CodeGen/MBlaze/dg.exp new file mode 100644 index 0000000000..bfd5e47157 --- /dev/null +++ b/test/CodeGen/MBlaze/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if { [llvm_supports_target MBlaze] } { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]] +} diff --git a/test/CodeGen/MBlaze/div.ll b/test/CodeGen/MBlaze/div.ll new file mode 100644 index 0000000000..fae9830619 --- /dev/null +++ b/test/CodeGen/MBlaze/div.ll @@ -0,0 +1,75 @@ +; Ensure that multiplication is lowered to function calls when the multiplier +; unit is not available in the hardware and that function calls are not used +; when the multiplier unit is available in the hardware. +; +; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s +; RUN: llc < %s -march=mblaze -mattr=+div | FileCheck -check-prefix=DIV %s + +define i8 @test_i8(i8 %a, i8 %b) { + ; FUN: test_i8: + ; DIV: test_i8: + + %tmp.1 = udiv i8 %a, %b + ; FUN-NOT: idiv + ; FUN: brlid + ; DIV-NOT: brlid + ; DIV: idivu + + %tmp.2 = sdiv i8 %a, %b + ; FUN-NOT: idiv + ; FUN: brlid + ; DIV-NOT: brlid + ; DIV-NOT: idivu + ; DIV: idiv + + %tmp.3 = add i8 %tmp.1, %tmp.2 + ret i8 %tmp.3 + ; FUN: rtsd + ; DIV: rtsd +} + +define i16 @test_i16(i16 %a, i16 %b) { + ; FUN: test_i16: + ; DIV: test_i16: + + %tmp.1 = udiv i16 %a, %b + ; FUN-NOT: idiv + ; FUN: brlid + ; DIV-NOT: brlid + ; DIV: idivu + + %tmp.2 = sdiv i16 %a, %b + ; FUN-NOT: idiv + ; FUN: brlid + ; DIV-NOT: brlid + ; DIV-NOT: idivu + ; DIV: idiv + + %tmp.3 = add i16 %tmp.1, %tmp.2 + ret i16 %tmp.3 + ; FUN: rtsd + ; DIV: rtsd +} + +define i32 @test_i32(i32 %a, i32 %b) { + ; FUN: test_i32: + ; DIV: test_i32: + + %tmp.1 = udiv i32 %a, %b + ; FUN-NOT: idiv + ; FUN: brlid + ; DIV-NOT: brlid + ; DIV: idivu + + %tmp.2 = sdiv i32 %a, %b + ; FUN-NOT: idiv + ; FUN: brlid + ; DIV-NOT: brlid + ; DIV-NOT: idivu + ; DIV: idiv + + %tmp.3 = add i32 %tmp.1, %tmp.2 + ret i32 %tmp.3 + ; FUN: rtsd + ; DIV: rtsd +} diff --git a/test/CodeGen/MBlaze/fpu.ll b/test/CodeGen/MBlaze/fpu.ll new file mode 100644 index 0000000000..83f4d83124 --- /dev/null +++ b/test/CodeGen/MBlaze/fpu.ll @@ -0,0 +1,66 @@ +; Ensure that floating point operations are lowered to function calls when the +; FPU is not available in the hardware and that function calls are not used +; when the FPU is available in the hardware. +; +; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s +; RUN: llc < %s -march=mblaze -mattr=+fpu | FileCheck -check-prefix=FPU %s + +define float @test_add(float %a, float %b) { + ; FUN: test_add: + ; FPU: test_add: + + %tmp.1 = fadd float %a, %b + ; FUN-NOT: fadd + ; FUN: brlid + ; FPU-NOT: brlid + ; FPU: fadd + + ret float %tmp.1 + ; FUN: rtsd + ; FPU: rtsd +} + +define float @test_sub(float %a, float %b) { + ; FUN: test_sub: + ; FPU: test_sub: + + %tmp.1 = fsub float %a, %b + ; FUN-NOT: frsub + ; FUN: brlid + ; FPU-NOT: brlid + ; FPU: frsub + + ret float %tmp.1 + ; FUN: rtsd + ; FPU: rtsd +} + +define float @test_mul(float %a, float %b) { + ; FUN: test_mul: + ; FPU: test_mul: + + %tmp.1 = fmul float %a, %b + ; FUN-NOT: fmul + ; FUN: brlid + ; FPU-NOT: brlid + ; FPU: fmul + + ret float %tmp.1 + ; FUN: rtsd + ; FPU: rtsd +} + +define float @test_div(float %a, float %b) { + ; FUN: test_div: + ; FPU: test_div: + + %tmp.1 = fdiv float %a, %b + ; FUN-NOT: fdiv + ; FUN: brlid + ; FPU-NOT: brlid + ; FPU: fdiv + + ret float %tmp.1 + ; FUN: rtsd + ; FPU: rtsd +} diff --git a/test/CodeGen/MBlaze/fsl.ll b/test/CodeGen/MBlaze/fsl.ll new file mode 100644 index 0000000000..f9c6205bc1 --- /dev/null +++ b/test/CodeGen/MBlaze/fsl.ll @@ -0,0 +1,323 @@ +; Ensure that the FSL instrinsic instruction generate single FSL instructions +; at the machine level. Additionally, ensure that dynamic values use the +; dynamic version of the instructions and that constant values use the +; constant version of the instructions. +; +; RUN: llc < %s -march=mblaze | FileCheck %s + +declare i32 @llvm.mblaze.fsl.get(i32 %port) +declare i32 @llvm.mblaze.fsl.aget(i32 %port) +declare i32 @llvm.mblaze.fsl.cget(i32 %port) +declare i32 @llvm.mblaze.fsl.caget(i32 %port) +declare i32 @llvm.mblaze.fsl.eget(i32 %port) +declare i32 @llvm.mblaze.fsl.eaget(i32 %port) +declare i32 @llvm.mblaze.fsl.ecget(i32 %port) +declare i32 @llvm.mblaze.fsl.ecaget(i32 %port) +declare i32 @llvm.mblaze.fsl.nget(i32 %port) +declare i32 @llvm.mblaze.fsl.naget(i32 %port) +declare i32 @llvm.mblaze.fsl.ncget(i32 %port) +declare i32 @llvm.mblaze.fsl.ncaget(i32 %port) +declare i32 @llvm.mblaze.fsl.neget(i32 %port) +declare i32 @llvm.mblaze.fsl.neaget(i32 %port) +declare i32 @llvm.mblaze.fsl.necget(i32 %port) +declare i32 @llvm.mblaze.fsl.necaget(i32 %port) +declare i32 @llvm.mblaze.fsl.tget(i32 %port) +declare i32 @llvm.mblaze.fsl.taget(i32 %port) +declare i32 @llvm.mblaze.fsl.tcget(i32 %port) +declare i32 @llvm.mblaze.fsl.tcaget(i32 %port) +declare i32 @llvm.mblaze.fsl.teget(i32 %port) +declare i32 @llvm.mblaze.fsl.teaget(i32 %port) +declare i32 @llvm.mblaze.fsl.tecget(i32 %port) +declare i32 @llvm.mblaze.fsl.tecaget(i32 %port) +declare i32 @llvm.mblaze.fsl.tnget(i32 %port) +declare i32 @llvm.mblaze.fsl.tnaget(i32 %port) +declare i32 @llvm.mblaze.fsl.tncget(i32 %port) +declare i32 @llvm.mblaze.fsl.tncaget(i32 %port) +declare i32 @llvm.mblaze.fsl.tneget(i32 %port) +declare i32 @llvm.mblaze.fsl.tneaget(i32 %port) +declare i32 @llvm.mblaze.fsl.tnecget(i32 %port) +declare i32 @llvm.mblaze.fsl.tnecaget(i32 %port) + +declare void @llvm.mblaze.fsl.put(i32 %value, i32 %port) +declare void @llvm.mblaze.fsl.aput(i32 %value, i32 %port) +declare void @llvm.mblaze.fsl.cput(i32 %value, i32 %port) +declare void @llvm.mblaze.fsl.caput(i32 %value, i32 %port) +declare void @llvm.mblaze.fsl.nput(i32 %value, i32 %port) +declare void @llvm.mblaze.fsl.naput(i32 %value, i32 %port) +declare void @llvm.mblaze.fsl.ncput(i32 %value, i32 %port) +declare void @llvm.mblaze.fsl.ncaput(i32 %value, i32 %port) +declare void @llvm.mblaze.fsl.tput(i32 %port) +declare void @llvm.mblaze.fsl.taput(i32 %port) +declare void @llvm.mblaze.fsl.tcput(i32 %port) +declare void @llvm.mblaze.fsl.tcaput(i32 %port) +declare void @llvm.mblaze.fsl.tnput(i32 %port) +declare void @llvm.mblaze.fsl.tnaput(i32 %port) +declare void @llvm.mblaze.fsl.tncput(i32 %port) +declare void @llvm.mblaze.fsl.tncaput(i32 %port) + +define i32 @fsl_get(i32 %port) +{ + ; CHECK: fsl_get: + %v0 = call i32 @llvm.mblaze.fsl.get(i32 %port) + ; CHECK: getd + %v1 = call i32 @llvm.mblaze.fsl.aget(i32 %port) + ; CHECK-NEXT: agetd + %v2 = call i32 @llvm.mblaze.fsl.cget(i32 %port) + ; CHECK-NEXT: cgetd + %v3 = call i32 @llvm.mblaze.fsl.caget(i32 %port) + ; CHECK-NEXT: cagetd + %v4 = call i32 @llvm.mblaze.fsl.eget(i32 %port) + ; CHECK-NEXT: egetd + %v5 = call i32 @llvm.mblaze.fsl.eaget(i32 %port) + ; CHECK-NEXT: eagetd + %v6 = call i32 @llvm.mblaze.fsl.ecget(i32 %port) + ; CHECK-NEXT: ecgetd + %v7 = call i32 @llvm.mblaze.fsl.ecaget(i32 %port) + ; CHECK-NEXT: ecagetd + %v8 = call i32 @llvm.mblaze.fsl.nget(i32 %port) + ; CHECK-NEXT: ngetd + %v9 = call i32 @llvm.mblaze.fsl.naget(i32 %port) + ; CHECK-NEXT: nagetd + %v10 = call i32 @llvm.mblaze.fsl.ncget(i32 %port) + ; CHECK-NEXT: ncgetd + %v11 = call i32 @llvm.mblaze.fsl.ncaget(i32 %port) + ; CHECK-NEXT: ncagetd + %v12 = call i32 @llvm.mblaze.fsl.neget(i32 %port) + ; CHECK-NEXT: negetd + %v13 = call i32 @llvm.mblaze.fsl.neaget(i32 %port) + ; CHECK-NEXT: neagetd + %v14 = call i32 @llvm.mblaze.fsl.necget(i32 %port) + ; CHECK-NEXT: necgetd + %v15 = call i32 @llvm.mblaze.fsl.necaget(i32 %port) + ; CHECK-NEXT: necagetd + %v16 = call i32 @llvm.mblaze.fsl.tget(i32 %port) + ; CHECK-NEXT: tgetd + %v17 = call i32 @llvm.mblaze.fsl.taget(i32 %port) + ; CHECK-NEXT: tagetd + %v18 = call i32 @llvm.mblaze.fsl.tcget(i32 %port) + ; CHECK-NEXT: tcgetd + %v19 = call i32 @llvm.mblaze.fsl.tcaget(i32 %port) + ; CHECK-NEXT: tcagetd + %v20 = call i32 @llvm.mblaze.fsl.teget(i32 %port) + ; CHECK-NEXT: tegetd + %v21 = call i32 @llvm.mblaze.fsl.teaget(i32 %port) + ; CHECK-NEXT: teagetd + %v22 = call i32 @llvm.mblaze.fsl.tecget(i32 %port) + ; CHECK-NEXT: tecgetd + %v23 = call i32 @llvm.mblaze.fsl.tecaget(i32 %port) + ; CHECK-NEXT: tecagetd + %v24 = call i32 @llvm.mblaze.fsl.tnget(i32 %port) + ; CHECK-NEXT: tngetd + %v25 = call i32 @llvm.mblaze.fsl.tnaget(i32 %port) + ; CHECK-NEXT: tnagetd + %v26 = call i32 @llvm.mblaze.fsl.tncget(i32 %port) + ; CHECK-NEXT: tncgetd + %v27 = call i32 @llvm.mblaze.fsl.tncaget(i32 %port) + ; CHECK-NEXT: tncagetd + %v28 = call i32 @llvm.mblaze.fsl.tneget(i32 %port) + ; CHECK-NEXT: tnegetd + %v29 = call i32 @llvm.mblaze.fsl.tneaget(i32 %port) + ; CHECK-NEXT: tneagetd + %v30 = call i32 @llvm.mblaze.fsl.tnecget(i32 %port) + ; CHECK-NEXT: tnecgetd + %v31 = call i32 @llvm.mblaze.fsl.tnecaget(i32 %port) + ; CHECK-NEXT: tnecagetd + ret i32 1 + ; CHECK: rtsd +} + +define i32 @fslc_get() +{ + ; CHECK: fslc_get: + %v0 = call i32 @llvm.mblaze.fsl.get(i32 1) + ; CHECK: get + %v1 = call i32 @llvm.mblaze.fsl.aget(i32 1) + ; CHECK-NOT: agetd + ; CHECK: aget + %v2 = call i32 @llvm.mblaze.fsl.cget(i32 1) + ; CHECK-NOT: cgetd + ; CHECK: cget + %v3 = call i32 @llvm.mblaze.fsl.caget(i32 1) + ; CHECK-NOT: cagetd + ; CHECK: caget + %v4 = call i32 @llvm.mblaze.fsl.eget(i32 1) + ; CHECK-NOT: egetd + ; CHECK: eget + %v5 = call i32 @llvm.mblaze.fsl.eaget(i32 1) + ; CHECK-NOT: eagetd + ; CHECK: eaget + %v6 = call i32 @llvm.mblaze.fsl.ecget(i32 1) + ; CHECK-NOT: ecgetd + ; CHECK: ecget + %v7 = call i32 @llvm.mblaze.fsl.ecaget(i32 1) + ; CHECK-NOT: ecagetd + ; CHECK: ecaget + %v8 = call i32 @llvm.mblaze.fsl.nget(i32 1) + ; CHECK-NOT: ngetd + ; CHECK: nget + %v9 = call i32 @llvm.mblaze.fsl.naget(i32 1) + ; CHECK-NOT: nagetd + ; CHECK: naget + %v10 = call i32 @llvm.mblaze.fsl.ncget(i32 1) + ; CHECK-NOT: ncgetd + ; CHECK: ncget + %v11 = call i32 @llvm.mblaze.fsl.ncaget(i32 1) + ; CHECK-NOT: ncagetd + ; CHECK: ncaget + %v12 = call i32 @llvm.mblaze.fsl.neget(i32 1) + ; CHECK-NOT: negetd + ; CHECK: neget + %v13 = call i32 @llvm.mblaze.fsl.neaget(i32 1) + ; CHECK-NOT: neagetd + ; CHECK: neaget + %v14 = call i32 @llvm.mblaze.fsl.necget(i32 1) + ; CHECK-NOT: necgetd + ; CHECK: necget + %v15 = call i32 @llvm.mblaze.fsl.necaget(i32 1) + ; CHECK-NOT: necagetd + ; CHECK: necaget + %v16 = call i32 @llvm.mblaze.fsl.tget(i32 1) + ; CHECK-NOT: tgetd + ; CHECK: tget + %v17 = call i32 @llvm.mblaze.fsl.taget(i32 1) + ; CHECK-NOT: tagetd + ; CHECK: taget + %v18 = call i32 @llvm.mblaze.fsl.tcget(i32 1) + ; CHECK-NOT: tcgetd + ; CHECK: tcget + %v19 = call i32 @llvm.mblaze.fsl.tcaget(i32 1) + ; CHECK-NOT: tcagetd + ; CHECK: tcaget + %v20 = call i32 @llvm.mblaze.fsl.teget(i32 1) + ; CHECK-NOT: tegetd + ; CHECK: teget + %v21 = call i32 @llvm.mblaze.fsl.teaget(i32 1) + ; CHECK-NOT: teagetd + ; CHECK: teaget + %v22 = call i32 @llvm.mblaze.fsl.tecget(i32 1) + ; CHECK-NOT: tecgetd + ; CHECK: tecget + %v23 = call i32 @llvm.mblaze.fsl.tecaget(i32 1) + ; CHECK-NOT: tecagetd + ; CHECK: tecaget + %v24 = call i32 @llvm.mblaze.fsl.tnget(i32 1) + ; CHECK-NOT: tngetd + ; CHECK: tnget + %v25 = call i32 @llvm.mblaze.fsl.tnaget(i32 1) + ; CHECK-NOT: tnagetd + ; CHECK: tnaget + %v26 = call i32 @llvm.mblaze.fsl.tncget(i32 1) + ; CHECK-NOT: tncgetd + ; CHECK: tncget + %v27 = call i32 @llvm.mblaze.fsl.tncaget(i32 1) + ; CHECK-NOT: tncagetd + ; CHECK: tncaget + %v28 = call i32 @llvm.mblaze.fsl.tneget(i32 1) + ; CHECK-NOT: tnegetd + ; CHECK: tneget + %v29 = call i32 @llvm.mblaze.fsl.tneaget(i32 1) + ; CHECK-NOT: tneagetd + ; CHECK: tneaget + %v30 = call i32 @llvm.mblaze.fsl.tnecget(i32 1) + ; CHECK-NOT: tnecgetd + ; CHECK: tnecget + %v31 = call i32 @llvm.mblaze.fsl.tnecaget(i32 1) + ; CHECK-NOT: tnecagetd + ; CHECK: tnecaget + ret i32 1 + ; CHECK: rtsd +} + +define void @putfsl(i32 %value, i32 %port) +{ + ; CHECK: putfsl: + call void @llvm.mblaze.fsl.put(i32 %value, i32 %port) + ; CHECK: putd + call void @llvm.mblaze.fsl.aput(i32 %value, i32 %port) + ; CHECK-NEXT: aputd + call void @llvm.mblaze.fsl.cput(i32 %value, i32 %port) + ; CHECK-NEXT: cputd + call void @llvm.mblaze.fsl.caput(i32 %value, i32 %port) + ; CHECK-NEXT: caputd + call void @llvm.mblaze.fsl.nput(i32 %value, i32 %port) + ; CHECK-NEXT: nputd + call void @llvm.mblaze.fsl.naput(i32 %value, i32 %port) + ; CHECK-NEXT: naputd + call void @llvm.mblaze.fsl.ncput(i32 %value, i32 %port) + ; CHECK-NEXT: ncputd + call void @llvm.mblaze.fsl.ncaput(i32 %value, i32 %port) + ; CHECK-NEXT: ncaputd + call void @llvm.mblaze.fsl.tput(i32 %port) + ; CHECK-NEXT: tputd + call void @llvm.mblaze.fsl.taput(i32 %port) + ; CHECK-NEXT: taputd + call void @llvm.mblaze.fsl.tcput(i32 %port) + ; CHECK-NEXT: tcputd + call void @llvm.mblaze.fsl.tcaput(i32 %port) + ; CHECK-NEXT: tcaputd + call void @llvm.mblaze.fsl.tnput(i32 %port) + ; CHECK-NEXT: tnputd + call void @llvm.mblaze.fsl.tnaput(i32 %port) + ; CHECK-NEXT: tnaputd + call void @llvm.mblaze.fsl.tncput(i32 %port) + ; CHECK-NEXT: tncputd + call void @llvm.mblaze.fsl.tncaput(i32 %port) + ; CHECK-NEXT: tncaputd + ret void + ; CHECK: rtsd +} + +define void @putfsl_const(i32 %value) +{ + ; CHECK: putfsl_const: + call void @llvm.mblaze.fsl.put(i32 %value, i32 1) + ; CHECK-NOT: putd + ; CHECK: put + call void @llvm.mblaze.fsl.aput(i32 %value, i32 1) + ; CHECK-NOT: aputd + ; CHECK: aput + call void @llvm.mblaze.fsl.cput(i32 %value, i32 1) + ; CHECK-NOT: cputd + ; CHECK: cput + call void @llvm.mblaze.fsl.caput(i32 %value, i32 1) + ; CHECK-NOT: caputd + ; CHECK: caput + call void @llvm.mblaze.fsl.nput(i32 %value, i32 1) + ; CHECK-NOT: nputd + ; CHECK: nput + call void @llvm.mblaze.fsl.naput(i32 %value, i32 1) + ; CHECK-NOT: naputd + ; CHECK: naput + call void @llvm.mblaze.fsl.ncput(i32 %value, i32 1) + ; CHECK-NOT: ncputd + ; CHECK: ncput + call void @llvm.mblaze.fsl.ncaput(i32 %value, i32 1) + ; CHECK-NOT: ncaputd + ; CHECK: ncaput + call void @llvm.mblaze.fsl.tput(i32 1) + ; CHECK-NOT: tputd + ; CHECK: tput + call void @llvm.mblaze.fsl.taput(i32 1) + ; CHECK-NOT: taputd + ; CHECK: taput + call void @llvm.mblaze.fsl.tcput(i32 1) + ; CHECK-NOT: tcputd + ; CHECK: tcput + call void @llvm.mblaze.fsl.tcaput(i32 1) + ; CHECK-NOT: tcaputd + ; CHECK: tcaput + call void @llvm.mblaze.fsl.tnput(i32 1) + ; CHECK-NOT: tnputd + ; CHECK: tnput + call void @llvm.mblaze.fsl.tnaput(i32 1) + ; CHECK-NOT: tnaputd + ; CHECK: tnaput + call void @llvm.mblaze.fsl.tncput(i32 1) + ; CHECK-NOT: tncputd + ; CHECK: tncput + call void @llvm.mblaze.fsl.tncaput(i32 1) + ; CHECK-NOT: tncaputd + ; CHECK: tncaput + ret void + ; CHECK: rtsd +} diff --git a/test/CodeGen/MBlaze/imm.ll b/test/CodeGen/MBlaze/imm.ll new file mode 100644 index 0000000000..85fad175b7 --- /dev/null +++ b/test/CodeGen/MBlaze/imm.ll @@ -0,0 +1,70 @@ +; Ensure that all immediate values that are 32-bits or less can be loaded +; using a single instruction and that immediate values 64-bits or less can +; be loaded using two instructions. +; +; RUN: llc < %s -march=mblaze | FileCheck %s +; RUN: llc < %s -march=mblaze -mattr=+fpu | FileCheck -check-prefix=FPU %s + +define i8 @retimm_i8() { + ; CHECK: retimm_i8: + ; CHECK: add + ; CHECK-NEXT: rtsd + ; FPU: retimm_i8: + ; FPU: add + ; FPU-NEXT: rtsd + ret i8 123 +} + +define i16 @retimm_i16() { + ; CHECK: retimm_i16: + ; CHECK: add + ; CHECK-NEXT: rtsd + ; FPU: retimm_i16: + ; FPU: add + ; FPU-NEXT: rtsd + ret i16 38212 +} + +define i32 @retimm_i32() { + ; CHECK: retimm_i32: + ; CHECK: add + ; CHECK-NEXT: rtsd + ; FPU: retimm_i32: + ; FPU: add + ; FPU-NEXT: rtsd + ret i32 2938128 +} + +define i64 @retimm_i64() { + ; CHECK: retimm_i64: + ; CHECK: add + ; CHECK-NEXT: add + ; CHECK-NEXT: rtsd + ; FPU: retimm_i64: + ; FPU: add + ; FPU-NEXT: add + ; FPU-NEXT: rtsd + ret i64 94581823 +} + +define float @retimm_float() { + ; CHECK: retimm_float: + ; CHECK: add + ; CHECK-NEXT: rtsd + ; FPU: retimm_float: + ; FPU: or + ; FPU: rtsd + ret float 12.0 +} + +define double @retimm_double() { + ; CHECK: retimm_double: + ; CHECK: add + ; CHECK-NEXT: add + ; CHECK-NEXT: rtsd + ; FPU: retimm_double: + ; FPU: add + ; FPU-NEXT: add + ; FPU-NEXT: rtsd + ret double 598382.39283873 +} diff --git a/test/CodeGen/MBlaze/jumptable.ll b/test/CodeGen/MBlaze/jumptable.ll new file mode 100644 index 0000000000..3f27c12f19 --- /dev/null +++ b/test/CodeGen/MBlaze/jumptable.ll @@ -0,0 +1,79 @@ +; Ensure that jump tables can be handled by the mblaze backend. The +; jump table should be lowered to a "br" instruction using one of the +; available registers. +; +; RUN: llc < %s -march=mblaze | FileCheck %s + +define i32 @jmptable(i32 %arg) +{ + ; CHECK: jmptable: + switch i32 %arg, label %DEFAULT [ i32 0, label %L0 + i32 1, label %L1 + i32 2, label %L2 + i32 3, label %L3 + i32 4, label %L4 + i32 5, label %L5 + i32 6, label %L6 + i32 7, label %L7 + i32 8, label %L8 + i32 9, label %L9 ] + + ; CHECK: lw [[REG:r[0-9]*]] + ; CHECK: br [[REG]] +L0: + %var0 = add i32 %arg, 0 + br label %DONE + +L1: + %var1 = add i32 %arg, 1 + br label %DONE + +L2: + %var2 = add i32 %arg, 2 + br label %DONE + +L3: + %var3 = add i32 %arg, 3 + br label %DONE + +L4: + %var4 = add i32 %arg, 4 + br label %DONE + +L5: + %var5 = add i32 %arg, 5 + br label %DONE + +L6: + %var6 = add i32 %arg, 6 + br label %DONE + +L7: + %var7 = add i32 %arg, 7 + br label %DONE + +L8: + %var8 = add i32 %arg, 8 + br label %DONE + +L9: + %var9 = add i32 %arg, 9 + br label %DONE + +DEFAULT: + unreachable + +DONE: + %rval = phi i32 [ %var0, %L0 ], + [ %var1, %L1 ], + [ %var2, %L2 ], + [ %var3, %L3 ], + [ %var4, %L4 ], + [ %var5, %L5 ], + [ %var6, %L6 ], + [ %var7, %L7 ], + [ %var8, %L8 ], + [ %var9, %L9 ] + ret i32 %rval + ; CHECK: rtsd +} diff --git a/test/CodeGen/MBlaze/loop.ll b/test/CodeGen/MBlaze/loop.ll new file mode 100644 index 0000000000..b473020e66 --- /dev/null +++ b/test/CodeGen/MBlaze/loop.ll @@ -0,0 +1,47 @@ +; Test some complicated looping constructs to ensure that they +; compile successfully and that some sort of branching is used +; in the resulting code. +; +; RUN: llc < %s -march=mblaze -mattr=+mul,+fpu,+barrel | FileCheck %s + +declare i32 @printf(i8*, ...) +@MSG = internal constant [19 x i8] c"Message: %d %d %d\0A\00" + +define i32 @loop(i32 %a, i32 %b) +{ + ; CHECK: loop: +entry: + br label %loop_outer + +loop_outer: + %outer.0 = phi i32 [ 0, %entry ], [ %outer.2, %loop_outer_finish ] + br label %loop_inner + +loop_inner: + %inner.0 = phi i32 [ %a, %loop_outer ], [ %inner.3, %loop_inner_finish ] + %inner.1 = phi i32 [ %b, %loop_outer ], [ %inner.4, %loop_inner_finish ] + %inner.2 = phi i32 [ 0, %loop_outer ], [ %inner.5, %loop_inner_finish ] + %inner.3 = add i32 %inner.0, %inner.1 + %inner.4 = mul i32 %inner.2, 11 + br label %loop_inner_finish + +loop_inner_finish: + %inner.5 = add i32 %inner.2, 1 + ; CHECK: addi {{.*, 1}} + + call i32 (i8*,...)* @printf( i8* getelementptr([19 x i8]* @MSG,i32 0,i32 0), + i32 %inner.0, i32 %inner.1, i32 %inner.2 ) + ; CHECK: brlid + + %inner.6 = icmp eq i32 %inner.5, 100 + ; CHECK: cmp + + br i1 %inner.6, label %loop_inner, label %loop_outer_finish + ; CHECK: {{beq|bne}} + +loop_outer_finish: + %outer.1 = add i32 %outer.0, 1 + %outer.2 = urem i32 %outer.1, 1500 + br label %loop_outer + ; CHECK: br +} diff --git a/test/CodeGen/MBlaze/mul.ll b/test/CodeGen/MBlaze/mul.ll new file mode 100644 index 0000000000..65d3e22a3e --- /dev/null +++ b/test/CodeGen/MBlaze/mul.ll @@ -0,0 +1,51 @@ +; Ensure that multiplication is lowered to function calls when the multiplier +; unit is not available in the hardware and that function calls are not used +; when the multiplier unit is available in the hardware. +; +; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s +; RUN: llc < %s -march=mblaze -mattr=+mul | FileCheck -check-prefix=MUL %s + +define i8 @test_i8(i8 %a, i8 %b) { + ; FUN: test_i8: + ; MUL: test_i8: + + %tmp.1 = mul i8 %a, %b + ; FUN-NOT: mul + ; FUN: brlid + ; MUL-NOT: brlid + ; MUL: mul + + ret i8 %tmp.1 + ; FUN: rtsd + ; MUL: rtsd +} + +define i16 @test_i16(i16 %a, i16 %b) { + ; FUN: test_i16: + ; MUL: test_i16: + + %tmp.1 = mul i16 %a, %b + ; FUN-NOT: mul + ; FUN: brlid + ; MUL-NOT: brlid + ; MUL: mul + + ret i16 %tmp.1 + ; FUN: rtsd + ; MUL: rtsd +} + +define i32 @test_i32(i32 %a, i32 %b) { + ; FUN: test_i32: + ; MUL: test_i32: + + %tmp.1 = mul i32 %a, %b + ; FUN-NOT: mul + ; FUN: brlid + ; MUL-NOT: brlid + ; MUL: mul + + ret i32 %tmp.1 + ; FUN: rtsd + ; MUL: rtsd +} diff --git a/test/CodeGen/MBlaze/mul64.ll b/test/CodeGen/MBlaze/mul64.ll new file mode 100644 index 0000000000..e0ef4138af --- /dev/null +++ b/test/CodeGen/MBlaze/mul64.ll @@ -0,0 +1,23 @@ +; Ensure that multiplication is lowered to function calls when the 64-bit +; multiplier unit is not available in the hardware and that function calls +; are not used when the 64-bit multiplier unit is available in the hardware. +; +; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s +; RUN: llc < %s -march=mblaze -mattr=+mul,+mul64 | \ +; RUN: FileCheck -check-prefix=MUL %s + +define i64 @test_i64(i64 %a, i64 %b) { + ; FUN: test_i64: + ; MUL: test_i64: + + %tmp.1 = mul i64 %a, %b + ; FUN-NOT: mul + ; FUN: brlid + ; MUL-NOT: brlid + ; MUL: mulh + ; MUL: mul + + ret i64 %tmp.1 + ; FUN: rtsd + ; MUL: rtsd +} diff --git a/test/CodeGen/MBlaze/select.ll b/test/CodeGen/MBlaze/select.ll new file mode 100644 index 0000000000..47a88a1e3c --- /dev/null +++ b/test/CodeGen/MBlaze/select.ll @@ -0,0 +1,15 @@ +; Ensure that the select instruction is supported and is lowered to +; some sort of branch instruction. +; +; RUN: llc < %s -march=mblaze | FileCheck %s + +define i32 @testsel(i32 %a, i32 %b) +{ + ; CHECK: testsel: + %tmp.1 = icmp eq i32 %a, %b + ; CHECK: cmp + %tmp.2 = select i1 %tmp.1, i32 %a, i32 %b + ; CHECK: {{bne|beq}} + ret i32 %tmp.2 + ; CHECK: rtsd +} diff --git a/test/CodeGen/MBlaze/shift.ll b/test/CodeGen/MBlaze/shift.ll new file mode 100644 index 0000000000..186115ec19 --- /dev/null +++ b/test/CodeGen/MBlaze/shift.ll @@ -0,0 +1,117 @@ +; Ensure that shifts are lowered to loops when the barrel shifter unit is +; not available in the hardware and that loops are not used when the +; barrel shifter unit is available in the hardware. +; +; RUN: llc < %s -march=mblaze | FileCheck -check-prefix=FUN %s +; RUN: llc < %s -march=mblaze -mattr=+barrel | FileCheck -check-prefix=SHT %s + +define i8 @test_i8(i8 %a, i8 %b) { + ; FUN: test_i8: + ; SHT: test_i8: + + %tmp.1 = shl i8 %a, %b + ; FUN-NOT: bsll + ; FUN: andi + ; FUN: add + ; FUN: bnei + ; SHT-NOT: andi + ; SHT-NOT: bnei + ; SHT: bsll + + ret i8 %tmp.1 + ; FUN: rtsd + ; SHT: rtsd +} + +define i8 @testc_i8(i8 %a, i8 %b) { + ; FUN: testc_i8: + ; SHT: testc_i8: + + %tmp.1 = shl i8 %a, 5 + ; FUN-NOT: bsll + ; FUN: andi + ; FUN: add + ; FUN: bnei + ; SHT-NOT: andi + ; SHT-NOT: add + ; SHT-NOT: bnei + ; SHT: bslli + + ret i8 %tmp.1 + ; FUN: rtsd + ; SHT: rtsd +} + +define i16 @test_i16(i16 %a, i16 %b) { + ; FUN: test_i16: + ; SHT: test_i16: + + %tmp.1 = shl i16 %a, %b + ; FUN-NOT: bsll + ; FUN: andi + ; FUN: add + ; FUN: bnei + ; SHT-NOT: andi + ; SHT-NOT: bnei + ; SHT: bsll + + ret i16 %tmp.1 + ; FUN: rtsd + ; SHT: rtsd +} + +define i16 @testc_i16(i16 %a, i16 %b) { + ; FUN: testc_i16: + ; SHT: testc_i16: + + %tmp.1 = shl i16 %a, 5 + ; FUN-NOT: bsll + ; FUN: andi + ; FUN: add + ; FUN: bnei + ; SHT-NOT: andi + ; SHT-NOT: add + ; SHT-NOT: bnei + ; SHT: bslli + + ret i16 %tmp.1 + ; FUN: rtsd + ; SHT: rtsd +} + +define i32 @test_i32(i32 %a, i32 %b) { + ; FUN: test_i32: + ; SHT: test_i32: + + %tmp.1 = shl i32 %a, %b + ; FUN-NOT: bsll + ; FUN: andi + ; FUN: add + ; FUN: bnei + ; SHT-NOT: andi + ; SHT-NOT: bnei + ; SHT: bsll + + ret i32 %tmp.1 + ; FUN: rtsd + ; SHT: rtsd +} + +define i32 @testc_i32(i32 %a, i32 %b) { + ; FUN: testc_i32: + ; SHT: testc_i32: + + %tmp.1 = shl i32 %a, 5 + ; FUN-NOT: bsll + ; FUN: andi + ; FUN: add + ; FUN: bnei + ; SHT-NOT: andi + ; SHT-NOT: add + ; SHT-NOT: bnei + ; SHT: bslli + + ret i32 %tmp.1 + ; FUN: rtsd + ; SHT: rtsd +} diff --git a/test/CodeGen/MSP430/AddrMode-bis-rx.ll b/test/CodeGen/MSP430/AddrMode-bis-rx.ll index 3340494f6b..4f9a7248bb 100644 --- a/test/CodeGen/MSP430/AddrMode-bis-rx.ll +++ b/test/CodeGen/MSP430/AddrMode-bis-rx.ll @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -march=msp430 | FileCheck %s +; RUN: llc < %s -march=msp430 | FileCheck %s target datalayout = "e-p:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:16:16" target triple = "msp430-generic-generic" @@ -29,7 +29,7 @@ define i8 @am3(i8 %x, i16 %n) nounwind { ret i8 %3 } ; CHECK: am3: -; CHECK: bis.b &bar(r14), r15 +; CHECK: bis.b bar(r14), r15 define i16 @am4(i16 %x) nounwind { %1 = volatile load i16* inttoptr(i16 32 to i16*) @@ -70,5 +70,5 @@ define i8 @am7(i8 %x, i16 %n) nounwind { ret i8 %4 } ; CHECK: am7: -; CHECK: bis.b &duh+2(r14), r15 +; CHECK: bis.b duh+2(r14), r15 diff --git a/test/CodeGen/MSP430/AddrMode-bis-xr.ll b/test/CodeGen/MSP430/AddrMode-bis-xr.ll index ca79fb6d33..17ebd87368 100644 --- a/test/CodeGen/MSP430/AddrMode-bis-xr.ll +++ b/test/CodeGen/MSP430/AddrMode-bis-xr.ll @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -march=msp430 | FileCheck %s +; RUN: llc < %s -march=msp430 | FileCheck %s target datalayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:16" target triple = "msp430-generic-generic" @@ -32,7 +32,7 @@ define void @am3(i16 %i, i8 %x) nounwind { ret void } ; CHECK: am3: -; CHECK: bis.b r14, &bar(r15) +; CHECK: bis.b r14, bar(r15) define void @am4(i16 %x) nounwind { %1 = volatile load i16* inttoptr(i16 32 to i16*) @@ -77,5 +77,5 @@ define void @am7(i16 %n, i8 %x) nounwind { ret void } ; CHECK: am7: -; CHECK: bis.b r14, &duh+2(r15) +; CHECK: bis.b r14, duh+2(r15) diff --git a/test/CodeGen/MSP430/AddrMode-mov-rx.ll b/test/CodeGen/MSP430/AddrMode-mov-rx.ll index 67cbb021c8..6676b88cd1 100644 --- a/test/CodeGen/MSP430/AddrMode-mov-rx.ll +++ b/test/CodeGen/MSP430/AddrMode-mov-rx.ll @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -march=msp430 | FileCheck %s +; RUN: llc < %s -march=msp430 | FileCheck %s target datalayout = "e-p:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:16:16" target triple = "msp430-generic-generic" @@ -26,7 +26,7 @@ define i8 @am3(i16 %n) nounwind { ret i8 %2 } ; CHECK: am3: -; CHECK: mov.b &bar(r15), r15 +; CHECK: mov.b bar(r15), r15 define i16 @am4() nounwind { %1 = volatile load i16* inttoptr(i16 32 to i16*) @@ -63,5 +63,5 @@ define i8 @am7(i16 %n) nounwind { ret i8 %3 } ; CHECK: am7: -; CHECK: mov.b &duh+2(r15), r15 +; CHECK: mov.b duh+2(r15), r15 diff --git a/test/CodeGen/MSP430/AddrMode-mov-xr.ll b/test/CodeGen/MSP430/AddrMode-mov-xr.ll index b8155d3a55..4b327b0578 100644 --- a/test/CodeGen/MSP430/AddrMode-mov-xr.ll +++ b/test/CodeGen/MSP430/AddrMode-mov-xr.ll @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -march=msp430 | FileCheck %s +; RUN: llc < %s -march=msp430 | FileCheck %s target datalayout = "e-p:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:16:16" target triple = "msp430-generic-generic" @@ -26,7 +26,7 @@ define void @am3(i16 %i, i8 %a) nounwind { ret void } ; CHECK: am3: -; CHECK: mov.b r14, &bar(r15) +; CHECK: mov.b r14, bar(r15) define void @am4(i16 %a) nounwind { volatile store i16 %a, i16* inttoptr(i16 32 to i16*) @@ -63,5 +63,5 @@ define void @am7(i16 %n, i8 %a) nounwind { ret void } ; CHECK: am7: -; CHECK: mov.b r14, &duh+2(r15) +; CHECK: mov.b r14, duh+2(r15) diff --git a/test/CodeGen/MSP430/Inst16mm.ll b/test/CodeGen/MSP430/Inst16mm.ll index 510afe3734..2337c2c0f2 100644 --- a/test/CodeGen/MSP430/Inst16mm.ll +++ b/test/CodeGen/MSP430/Inst16mm.ll @@ -1,4 +1,4 @@ -; RUN: llc -march=msp430 < %s | FileCheck %s +; RUN: llc -march=msp430 -combiner-alias-analysis < %s | FileCheck %s target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8" target triple = "msp430-generic-generic" @foo = common global i16 0, align 2 @@ -52,3 +52,18 @@ define void @xor() nounwind { ret void } +define i16 @mov2() nounwind { +entry: + %retval = alloca i16 ; [#uses=3] + %x = alloca i32, align 2 ; [#uses=1] + %y = alloca i32, align 2 ; [#uses=1] + store i16 0, i16* %retval + %tmp = load i32* %y ; [#uses=1] + store i32 %tmp, i32* %x + store i16 0, i16* %retval + %0 = load i16* %retval ; [#uses=1] + ret i16 %0 +; CHECK: mov2: +; CHECK: mov.w 0(r1), 4(r1) +; CHECK: mov.w 2(r1), 6(r1) +} diff --git a/test/CodeGen/MSP430/Inst8rr.ll b/test/CodeGen/MSP430/Inst8rr.ll index 74feaae4eb..0f5fc12b62 100644 --- a/test/CodeGen/MSP430/Inst8rr.ll +++ b/test/CodeGen/MSP430/Inst8rr.ll @@ -10,7 +10,7 @@ define i8 @mov(i8 %a, i8 %b) nounwind { define i8 @add(i8 %a, i8 %b) nounwind { ; CHECK: add: -; CHECK: add.b r14, r15 +; CHECK: add.b r12, r15 %1 = add i8 %a, %b ret i8 %1 } diff --git a/test/CodeGen/MSP430/bit.ll b/test/CodeGen/MSP430/bit.ll index cd664a17bf..03d672bcbe 100644 --- a/test/CodeGen/MSP430/bit.ll +++ b/test/CodeGen/MSP430/bit.ll @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -march=msp430 | FileCheck %s +; RUN: llc < %s -march=msp430 | FileCheck %s target datalayout = "e-p:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:16:32" target triple = "msp430-generic-generic" diff --git a/test/CodeGen/MSP430/setcc.ll b/test/CodeGen/MSP430/setcc.ll index 9db51cce73..c99b17e143 100644 --- a/test/CodeGen/MSP430/setcc.ll +++ b/test/CodeGen/MSP430/setcc.ll @@ -10,9 +10,9 @@ define i16 @sccweqand(i16 %a, i16 %b) nounwind { } ; CHECK: sccweqand: ; CHECK: bit.w r14, r15 -; CHECK-NEXT: mov.w r2, r15 -; CHECK-NEXT: and.w #1, r15 -; CHECK-NEXT: xor.w #1, r15 +; CHECK: mov.w r2, r15 +; CHECK: rra.w r15 +; CHECK: and.w #1, r15 define i16 @sccwneand(i16 %a, i16 %b) nounwind { %t1 = and i16 %a, %b @@ -22,8 +22,8 @@ define i16 @sccwneand(i16 %a, i16 %b) nounwind { } ; CHECK: sccwneand: ; CHECK: bit.w r14, r15 -; CHECK-NEXT: mov.w r2, r15 -; CHECK-NEXT: and.w #1, r15 +; CHECK: mov.w r2, r15 +; CHECK: and.w #1, r15 define i16 @sccwne(i16 %a, i16 %b) nounwind { %t1 = icmp ne i16 %a, %b @@ -32,9 +32,10 @@ define i16 @sccwne(i16 %a, i16 %b) nounwind { } ; CHECK:sccwne: ; CHECK: cmp.w r14, r15 -; CHECK-NEXT: mov.w r2, r15 -; CHECK-NEXT: rra.w r15 -; CHECK-NEXT: and.w #1, r15 +; CHECK: mov.w r2, r15 +; CHECK: rra.w r15 +; CHECK: and.w #1, r15 +; CHECK: xor.w #1, r15 define i16 @sccweq(i16 %a, i16 %b) nounwind { %t1 = icmp eq i16 %a, %b @@ -43,10 +44,9 @@ define i16 @sccweq(i16 %a, i16 %b) nounwind { } ; CHECK:sccweq: ; CHECK: cmp.w r14, r15 -; CHECK-NEXT: mov.w r2, r15 -; CHECK-NEXT: rra.w r15 -; CHECK-NEXT: and.w #1, r15 -; CHECK-NEXT: xor.w #1, r15 +; CHECK: mov.w r2, r15 +; CHECK: rra.w r15 +; CHECK: and.w #1, r15 define i16 @sccwugt(i16 %a, i16 %b) nounwind { %t1 = icmp ugt i16 %a, %b @@ -55,9 +55,9 @@ define i16 @sccwugt(i16 %a, i16 %b) nounwind { } ; CHECK:sccwugt: ; CHECK: cmp.w r15, r14 -; CHECK-NEXT: mov.w r2, r15 -; CHECK-NEXT: and.w #1, r15 -; CHECK-NEXT: xor.w #1, r15 +; CHECK: mov.w r2, r15 +; CHECK: and.w #1, r15 +; CHECK: xor.w #1, r15 define i16 @sccwuge(i16 %a, i16 %b) nounwind { %t1 = icmp uge i16 %a, %b @@ -66,8 +66,8 @@ define i16 @sccwuge(i16 %a, i16 %b) nounwind { } ; CHECK:sccwuge: ; CHECK: cmp.w r14, r15 -; CHECK-NEXT: mov.w r2, r15 -; CHECK-NEXT: and.w #1, r15 +; CHECK: mov.w r2, r15 +; CHECK: and.w #1, r15 define i16 @sccwult(i16 %a, i16 %b) nounwind { %t1 = icmp ult i16 %a, %b @@ -76,9 +76,9 @@ define i16 @sccwult(i16 %a, i16 %b) nounwind { } ; CHECK:sccwult: ; CHECK: cmp.w r14, r15 -; CHECK-NEXT: mov.w r2, r15 -; CHECK-NEXT: and.w #1, r15 -; CHECK-NEXT: xor.w #1, r15 +; CHECK: mov.w r2, r15 +; CHECK: and.w #1, r15 +; CHECK: xor.w #1, r15 define i16 @sccwule(i16 %a, i16 %b) nounwind { %t1 = icmp ule i16 %a, %b @@ -87,8 +87,8 @@ define i16 @sccwule(i16 %a, i16 %b) nounwind { } ; CHECK:sccwule: ; CHECK: cmp.w r15, r14 -; CHECK-NEXT: mov.w r2, r15 -; CHECK-NEXT: and.w #1, r15 +; CHECK: mov.w r2, r15 +; CHECK: and.w #1, r15 define i16 @sccwsgt(i16 %a, i16 %b) nounwind { %t1 = icmp sgt i16 %a, %b diff --git a/test/CodeGen/PIC16/C16-11.ll b/test/CodeGen/PIC16/C16-11.ll index e70092b11c..8a5a0ac11f 100644 --- a/test/CodeGen/PIC16/C16-11.ll +++ b/test/CodeGen/PIC16/C16-11.ll @@ -1,4 +1,7 @@ -;RUN: llc < %s -march=pic16 +; RUN: llc < %s -march=pic16 +; XFAIL: * +; This fails because PIC16 doesn't define a (xor reg, reg) pattern. +; @c612.auto.a.b = internal global i1 false ; [#uses=2] @c612.auto.A.b = internal global i1 false ; [#uses=2] diff --git a/test/CodeGen/PIC16/C16-15.ll b/test/CodeGen/PIC16/C16-15.ll index 2e1dc0c013..5ca2d4a9bd 100644 --- a/test/CodeGen/PIC16/C16-15.ll +++ b/test/CodeGen/PIC16/C16-15.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=pic16 | grep "extern @.lib.unordered.f32" | count 3 +; RUN: llc < %s -march=pic16 | grep "extern" | grep "@.lib.unordered.f32" | count 3 @pc = global i8* inttoptr (i64 160 to i8*), align 1 ; [#uses=2] @aa = common global i16 0, align 1 ; [#uses=0] diff --git a/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll b/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll index d1d28ae15b..be28a9a454 100644 --- a/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll +++ b/test/CodeGen/PowerPC/2007-04-30-InlineAsmEarlyClobber.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s | grep {subfc r3,r5,r4} -; RUN: llc < %s | grep {subfze r4,r2} -; RUN: llc < %s -regalloc=local | grep {subfc r2,r5,r4} +; RUN: llc < %s | grep {subfze r4,r6} +; RUN: llc < %s -regalloc=local | grep {subfc r6,r5,r4} ; RUN: llc < %s -regalloc=local | grep {subfze r3,r3} ; The first argument of subfc must not be the same as any other register. diff --git a/test/CodeGen/PowerPC/2009-08-17-inline-asm-addr-mode-breakage.ll b/test/CodeGen/PowerPC/2009-08-17-inline-asm-addr-mode-breakage.ll index 5d09696933..50a02781fd 100644 --- a/test/CodeGen/PowerPC/2009-08-17-inline-asm-addr-mode-breakage.ll +++ b/test/CodeGen/PowerPC/2009-08-17-inline-asm-addr-mode-breakage.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=ppc32 | FileCheck %s +; RUN: llc < %s -march=ppc32 -mtriple=powerpc-apple-darwin10 -mcpu=g5 | FileCheck %s ; ModuleID = '' target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128" target triple = "powerpc-apple-darwin10.0" @@ -10,8 +10,8 @@ target triple = "powerpc-apple-darwin10.0" define void @foo(i32 %y) nounwind ssp { entry: ; CHECK: foo -; CHECK: add r2 -; CHECK: 0(r2) +; CHECK: add r4 +; CHECK: 0(r4) %y_addr = alloca i32 ; [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] store i32 %y, i32* %y_addr diff --git a/test/CodeGen/PowerPC/2010-02-12-saveCR.ll b/test/CodeGen/PowerPC/2010-02-12-saveCR.ll new file mode 100644 index 0000000000..b73382e6eb --- /dev/null +++ b/test/CodeGen/PowerPC/2010-02-12-saveCR.ll @@ -0,0 +1,30 @@ +; RUN: llc < %s -mtriple=powerpc-apple-darwin | FileCheck %s +; ModuleID = 'hh.c' +target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128-n32" +target triple = "powerpc-apple-darwin9.6" +; This formerly used R0 for both the stack address and CR. + +define void @foo() nounwind { +entry: +;CHECK: mfcr r2 +;CHECK: rlwinm r2, r2, 8, 0, 31 +;CHECK: lis r0, 1 +;CHECK: ori r0, r0, 34540 +;CHECK: stwx r2, r1, r0 + %x = alloca [100000 x i8] ; <[100000 x i8]*> [#uses=1] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + %x1 = bitcast [100000 x i8]* %x to i8* ; [#uses=1] + call void @bar(i8* %x1) nounwind + call void asm sideeffect "", "~{cr2}"() nounwind + br label %return + +return: ; preds = %entry +;CHECK: lis r0, 1 +;CHECK: ori r0, r0, 34540 +;CHECK: lwzx r2, r1, r0 +;CHECK: rlwinm r2, r2, 24, 0, 31 +;CHECK: mtcrf 32, r2 + ret void +} + +declare void @bar(i8*) diff --git a/test/CodeGen/PowerPC/2010-02-26-FoldFloats.ll b/test/CodeGen/PowerPC/2010-02-26-FoldFloats.ll new file mode 100644 index 0000000000..f43f5cae6e --- /dev/null +++ b/test/CodeGen/PowerPC/2010-02-26-FoldFloats.ll @@ -0,0 +1,433 @@ +; RUN: llc < %s -O3 | FileCheck %s +target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128-n32" +target triple = "powerpc-apple-darwin9.6" + +; There should be no stfs spills +; CHECK: main: +; CHECK-NOT: stfs +; CHECK: .section + +@.str66 = external constant [3 x i8], align 4 ; <[3 x i8]*> [#uses=1] +@.str31 = external constant [6 x i8], align 4 ; <[6 x i8]*> [#uses=1] +@.str61 = external constant [21 x i8], align 4 ; <[21 x i8]*> [#uses=1] +@.str101 = external constant [61 x i8], align 4 ; <[61 x i8]*> [#uses=1] +@.str104 = external constant [31 x i8], align 4 ; <[31 x i8]*> [#uses=1] +@.str105 = external constant [45 x i8], align 4 ; <[45 x i8]*> [#uses=1] +@.str112 = external constant [38 x i8], align 4 ; <[38 x i8]*> [#uses=1] +@.str121 = external constant [36 x i8], align 4 ; <[36 x i8]*> [#uses=1] +@.str12293 = external constant [67 x i8], align 4 ; <[67 x i8]*> [#uses=1] +@.str123 = external constant [68 x i8], align 4 ; <[68 x i8]*> [#uses=1] +@.str124 = external constant [52 x i8], align 4 ; <[52 x i8]*> [#uses=1] +@.str125 = external constant [51 x i8], align 4 ; <[51 x i8]*> [#uses=1] + +define i32 @main(i32 %argc, i8** %argv) noreturn nounwind { +entry: + br i1 undef, label %bb4.i1, label %my_fopen.exit + +bb4.i1: ; preds = %entry + unreachable + +my_fopen.exit: ; preds = %entry + br i1 undef, label %bb.i, label %bb1.i + +bb.i: ; preds = %my_fopen.exit + unreachable + +bb1.i: ; preds = %my_fopen.exit + br label %bb134.i + +bb2.i: ; preds = %bb134.i + %0 = icmp eq i32 undef, 0 ; [#uses=1] + br i1 %0, label %bb20.i, label %bb21.i + +bb20.i: ; preds = %bb2.i + br label %bb134.i + +bb21.i: ; preds = %bb2.i + %1 = call i32 @strcmp(i8* undef, i8* getelementptr inbounds ([6 x i8]* @.str31, i32 0, i32 0)) nounwind readonly ; [#uses=0] + br i1 undef, label %bb30.i, label %bb31.i + +bb30.i: ; preds = %bb21.i + br label %bb134.i + +bb31.i: ; preds = %bb21.i + br i1 undef, label %bb41.i, label %bb44.i + +bb41.i: ; preds = %bb31.i + %2 = icmp slt i32 undef, %argc ; [#uses=1] + br i1 %2, label %bb1.i77.i, label %bb2.i78.i + +bb1.i77.i: ; preds = %bb41.i + %3 = load float* undef, align 4 ; [#uses=2] + %4 = fcmp ugt float %3, 0.000000e+00 ; [#uses=1] + br i1 %4, label %bb43.i, label %bb42.i + +bb2.i78.i: ; preds = %bb41.i + unreachable + +bb42.i: ; preds = %bb1.i77.i + unreachable + +bb43.i: ; preds = %bb1.i77.i + br label %bb134.i + +bb44.i: ; preds = %bb31.i + br i1 undef, label %bb45.i, label %bb49.i + +bb45.i: ; preds = %bb44.i + %5 = icmp slt i32 undef, %argc ; [#uses=1] + br i1 %5, label %bb1.i72.i, label %bb2.i73.i + +bb1.i72.i: ; preds = %bb45.i + %6 = load float* undef, align 4 ; [#uses=3] + %7 = fcmp ult float %6, 1.000000e+00 ; [#uses=1] + %or.cond.i = and i1 undef, %7 ; [#uses=1] + br i1 %or.cond.i, label %bb48.i, label %bb47.i + +bb2.i73.i: ; preds = %bb45.i + unreachable + +bb47.i: ; preds = %bb1.i72.i + unreachable + +bb48.i: ; preds = %bb1.i72.i + br label %bb134.i + +bb49.i: ; preds = %bb44.i + br i1 undef, label %bb50.i, label %bb53.i + +bb50.i: ; preds = %bb49.i + br i1 false, label %bb1.i67.i, label %bb2.i68.i + +bb1.i67.i: ; preds = %bb50.i + br i1 false, label %read_float_option.exit69.i, label %bb1.i67.bb2.i68_crit_edge.i + +bb1.i67.bb2.i68_crit_edge.i: ; preds = %bb1.i67.i + br label %bb2.i68.i + +bb2.i68.i: ; preds = %bb1.i67.bb2.i68_crit_edge.i, %bb50.i + unreachable + +read_float_option.exit69.i: ; preds = %bb1.i67.i + br i1 undef, label %bb52.i, label %bb51.i + +bb51.i: ; preds = %read_float_option.exit69.i + unreachable + +bb52.i: ; preds = %read_float_option.exit69.i + br label %bb134.i + +bb53.i: ; preds = %bb49.i + %8 = call i32 @strcmp(i8* undef, i8* getelementptr inbounds ([21 x i8]* @.str61, i32 0, i32 0)) nounwind readonly ; [#uses=0] + br i1 false, label %bb89.i, label %bb92.i + +bb89.i: ; preds = %bb53.i + br i1 undef, label %bb1.i27.i, label %bb2.i28.i + +bb1.i27.i: ; preds = %bb89.i + unreachable + +bb2.i28.i: ; preds = %bb89.i + unreachable + +bb92.i: ; preds = %bb53.i + br i1 undef, label %bb93.i, label %bb96.i + +bb93.i: ; preds = %bb92.i + br i1 undef, label %bb1.i22.i, label %bb2.i23.i + +bb1.i22.i: ; preds = %bb93.i + br i1 undef, label %bb95.i, label %bb94.i + +bb2.i23.i: ; preds = %bb93.i + unreachable + +bb94.i: ; preds = %bb1.i22.i + unreachable + +bb95.i: ; preds = %bb1.i22.i + br label %bb134.i + +bb96.i: ; preds = %bb92.i + br i1 undef, label %bb97.i, label %bb100.i + +bb97.i: ; preds = %bb96.i + %9 = icmp slt i32 undef, %argc ; [#uses=1] + br i1 %9, label %bb1.i17.i, label %bb2.i18.i + +bb1.i17.i: ; preds = %bb97.i + %10 = call i32 (i8*, i8*, ...)* @"\01_sscanf$LDBL128"(i8* undef, i8* getelementptr inbounds ([3 x i8]* @.str66, i32 0, i32 0), float* undef) nounwind ; [#uses=1] + %phitmp.i16.i = icmp eq i32 %10, 1 ; [#uses=1] + br i1 %phitmp.i16.i, label %read_float_option.exit19.i, label %bb1.i17.bb2.i18_crit_edge.i + +bb1.i17.bb2.i18_crit_edge.i: ; preds = %bb1.i17.i + br label %bb2.i18.i + +bb2.i18.i: ; preds = %bb1.i17.bb2.i18_crit_edge.i, %bb97.i + unreachable + +read_float_option.exit19.i: ; preds = %bb1.i17.i + br i1 false, label %bb99.i, label %bb98.i + +bb98.i: ; preds = %read_float_option.exit19.i + unreachable + +bb99.i: ; preds = %read_float_option.exit19.i + br label %bb134.i + +bb100.i: ; preds = %bb96.i + br i1 false, label %bb101.i, label %bb104.i + +bb101.i: ; preds = %bb100.i + br i1 false, label %bb1.i12.i, label %bb2.i13.i + +bb1.i12.i: ; preds = %bb101.i + br i1 undef, label %bb102.i, label %bb103.i + +bb2.i13.i: ; preds = %bb101.i + unreachable + +bb102.i: ; preds = %bb1.i12.i + unreachable + +bb103.i: ; preds = %bb1.i12.i + br label %bb134.i + +bb104.i: ; preds = %bb100.i + unreachable + +bb134.i: ; preds = %bb103.i, %bb99.i, %bb95.i, %bb52.i, %bb48.i, %bb43.i, %bb30.i, %bb20.i, %bb1.i + %annealing_sched.1.0 = phi float [ 1.000000e+01, %bb1.i ], [ %annealing_sched.1.0, %bb20.i ], [ 1.000000e+00, %bb30.i ], [ %annealing_sched.1.0, %bb43.i ], [ %annealing_sched.1.0, %bb48.i ], [ %annealing_sched.1.0, %bb52.i ], [ %annealing_sched.1.0, %bb95.i ], [ %annealing_sched.1.0, %bb99.i ], [ %annealing_sched.1.0, %bb103.i ] ; [#uses=8] + %annealing_sched.2.0 = phi float [ 1.000000e+02, %bb1.i ], [ %annealing_sched.2.0, %bb20.i ], [ %annealing_sched.2.0, %bb30.i ], [ %3, %bb43.i ], [ %annealing_sched.2.0, %bb48.i ], [ %annealing_sched.2.0, %bb52.i ], [ %annealing_sched.2.0, %bb95.i ], [ %annealing_sched.2.0, %bb99.i ], [ %annealing_sched.2.0, %bb103.i ] ; [#uses=8] + %annealing_sched.3.0 = phi float [ 0x3FE99999A0000000, %bb1.i ], [ %annealing_sched.3.0, %bb20.i ], [ %annealing_sched.3.0, %bb30.i ], [ %annealing_sched.3.0, %bb43.i ], [ %6, %bb48.i ], [ %annealing_sched.3.0, %bb52.i ], [ %annealing_sched.3.0, %bb95.i ], [ %annealing_sched.3.0, %bb99.i ], [ %annealing_sched.3.0, %bb103.i ] ; [#uses=8] + %annealing_sched.4.0 = phi float [ 0x3F847AE140000000, %bb1.i ], [ %annealing_sched.4.0, %bb20.i ], [ %annealing_sched.4.0, %bb30.i ], [ %annealing_sched.4.0, %bb43.i ], [ %annealing_sched.4.0, %bb48.i ], [ 0.000000e+00, %bb52.i ], [ %annealing_sched.4.0, %bb95.i ], [ %annealing_sched.4.0, %bb99.i ], [ %annealing_sched.4.0, %bb103.i ] ; [#uses=8] + %router_opts.0.0 = phi float [ 0.000000e+00, %bb1.i ], [ %router_opts.0.0, %bb20.i ], [ 1.000000e+04, %bb30.i ], [ %router_opts.0.0, %bb43.i ], [ %router_opts.0.0, %bb48.i ], [ %router_opts.0.0, %bb52.i ], [ %router_opts.0.0, %bb95.i ], [ %router_opts.0.0, %bb99.i ], [ %router_opts.0.0, %bb103.i ] ; [#uses=8] + %router_opts.1.0 = phi float [ 5.000000e-01, %bb1.i ], [ %router_opts.1.0, %bb20.i ], [ 1.000000e+04, %bb30.i ], [ %router_opts.1.0, %bb43.i ], [ %router_opts.1.0, %bb48.i ], [ %router_opts.1.0, %bb52.i ], [ undef, %bb95.i ], [ %router_opts.1.0, %bb99.i ], [ %router_opts.1.0, %bb103.i ] ; [#uses=7] + %router_opts.2.0 = phi float [ 1.500000e+00, %bb1.i ], [ %router_opts.2.0, %bb20.i ], [ %router_opts.2.0, %bb30.i ], [ %router_opts.2.0, %bb43.i ], [ %router_opts.2.0, %bb48.i ], [ %router_opts.2.0, %bb52.i ], [ %router_opts.2.0, %bb95.i ], [ undef, %bb99.i ], [ %router_opts.2.0, %bb103.i ] ; [#uses=8] + %router_opts.3.0 = phi float [ 0x3FC99999A0000000, %bb1.i ], [ %router_opts.3.0, %bb20.i ], [ %router_opts.3.0, %bb30.i ], [ %router_opts.3.0, %bb43.i ], [ %router_opts.3.0, %bb48.i ], [ %router_opts.3.0, %bb52.i ], [ %router_opts.3.0, %bb95.i ], [ %router_opts.3.0, %bb99.i ], [ 0.000000e+00, %bb103.i ] ; [#uses=8] + %11 = phi float [ 0x3FC99999A0000000, %bb1.i ], [ %11, %bb20.i ], [ %11, %bb30.i ], [ %11, %bb43.i ], [ %11, %bb48.i ], [ %11, %bb52.i ], [ %11, %bb95.i ], [ %11, %bb99.i ], [ 0.000000e+00, %bb103.i ] ; [#uses=8] + %12 = phi float [ 1.500000e+00, %bb1.i ], [ %12, %bb20.i ], [ %12, %bb30.i ], [ %12, %bb43.i ], [ %12, %bb48.i ], [ %12, %bb52.i ], [ %12, %bb95.i ], [ undef, %bb99.i ], [ %12, %bb103.i ] ; [#uses=8] + %13 = phi float [ 5.000000e-01, %bb1.i ], [ %13, %bb20.i ], [ 1.000000e+04, %bb30.i ], [ %13, %bb43.i ], [ %13, %bb48.i ], [ %13, %bb52.i ], [ undef, %bb95.i ], [ %13, %bb99.i ], [ %13, %bb103.i ] ; [#uses=7] + %14 = phi float [ 0.000000e+00, %bb1.i ], [ %14, %bb20.i ], [ 1.000000e+04, %bb30.i ], [ %14, %bb43.i ], [ %14, %bb48.i ], [ %14, %bb52.i ], [ %14, %bb95.i ], [ %14, %bb99.i ], [ %14, %bb103.i ] ; [#uses=8] + %15 = phi float [ 0x3FE99999A0000000, %bb1.i ], [ %15, %bb20.i ], [ %15, %bb30.i ], [ %15, %bb43.i ], [ %6, %bb48.i ], [ %15, %bb52.i ], [ %15, %bb95.i ], [ %15, %bb99.i ], [ %15, %bb103.i ] ; [#uses=8] + %16 = phi float [ 0x3F847AE140000000, %bb1.i ], [ %16, %bb20.i ], [ %16, %bb30.i ], [ %16, %bb43.i ], [ %16, %bb48.i ], [ 0.000000e+00, %bb52.i ], [ %16, %bb95.i ], [ %16, %bb99.i ], [ %16, %bb103.i ] ; [#uses=8] + %17 = phi float [ 1.000000e+01, %bb1.i ], [ %17, %bb20.i ], [ 1.000000e+00, %bb30.i ], [ %17, %bb43.i ], [ %17, %bb48.i ], [ %17, %bb52.i ], [ %17, %bb95.i ], [ %17, %bb99.i ], [ %17, %bb103.i ] ; [#uses=8] + %18 = icmp slt i32 undef, %argc ; [#uses=1] + br i1 %18, label %bb2.i, label %bb135.i + +bb135.i: ; preds = %bb134.i + br i1 undef, label %bb141.i, label %bb142.i + +bb141.i: ; preds = %bb135.i + unreachable + +bb142.i: ; preds = %bb135.i + br i1 undef, label %bb145.i, label %bb144.i + +bb144.i: ; preds = %bb142.i + unreachable + +bb145.i: ; preds = %bb142.i + br i1 undef, label %bb146.i, label %bb147.i + +bb146.i: ; preds = %bb145.i + unreachable + +bb147.i: ; preds = %bb145.i + br i1 undef, label %bb148.i, label %bb155.i + +bb148.i: ; preds = %bb147.i + br label %bb155.i + +bb155.i: ; preds = %bb148.i, %bb147.i + br i1 undef, label %bb156.i, label %bb161.i + +bb156.i: ; preds = %bb155.i + unreachable + +bb161.i: ; preds = %bb155.i + br i1 undef, label %bb162.i, label %bb163.i + +bb162.i: ; preds = %bb161.i + %19 = fpext float %17 to double ; [#uses=1] + %20 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([61 x i8]* @.str101, i32 0, i32 0), double %19) nounwind ; [#uses=0] + unreachable + +bb163.i: ; preds = %bb161.i + %21 = fpext float %16 to double ; [#uses=1] + %22 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([31 x i8]* @.str104, i32 0, i32 0), double %21) nounwind ; [#uses=0] + %23 = fpext float %15 to double ; [#uses=1] + %24 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([45 x i8]* @.str105, i32 0, i32 0), double %23) nounwind ; [#uses=0] + %25 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([38 x i8]* @.str112, i32 0, i32 0), double undef) nounwind ; [#uses=0] + br i1 undef, label %parse_command.exit, label %bb176.i + +bb176.i: ; preds = %bb163.i + br i1 undef, label %bb177.i, label %bb178.i + +bb177.i: ; preds = %bb176.i + unreachable + +bb178.i: ; preds = %bb176.i + %26 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([36 x i8]* @.str121, i32 0, i32 0), double undef) nounwind ; [#uses=0] + %27 = fpext float %14 to double ; [#uses=1] + %28 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([67 x i8]* @.str12293, i32 0, i32 0), double %27) nounwind ; [#uses=0] + %29 = fpext float %13 to double ; [#uses=1] + %30 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([68 x i8]* @.str123, i32 0, i32 0), double %29) nounwind ; [#uses=0] + %31 = fpext float %12 to double ; [#uses=1] + %32 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([52 x i8]* @.str124, i32 0, i32 0), double %31) nounwind ; [#uses=0] + %33 = fpext float %11 to double ; [#uses=1] + %34 = call i32 (i8*, ...)* @"\01_printf$LDBL128"(i8* getelementptr inbounds ([51 x i8]* @.str125, i32 0, i32 0), double %33) nounwind ; [#uses=0] + unreachable + +parse_command.exit: ; preds = %bb163.i + br i1 undef, label %bb4.i152.i, label %my_fopen.exit.i + +bb4.i152.i: ; preds = %parse_command.exit + unreachable + +my_fopen.exit.i: ; preds = %parse_command.exit + br i1 undef, label %bb.i6.i99, label %bb49.preheader.i.i + +bb.i6.i99: ; preds = %my_fopen.exit.i + br i1 undef, label %bb3.i.i100, label %bb1.i8.i + +bb1.i8.i: ; preds = %bb.i6.i99 + unreachable + +bb3.i.i100: ; preds = %bb.i6.i99 + unreachable + +bb49.preheader.i.i: ; preds = %my_fopen.exit.i + br i1 undef, label %bb7.i11.i, label %bb50.i.i + +bb7.i11.i: ; preds = %bb49.preheader.i.i + unreachable + +bb50.i.i: ; preds = %bb49.preheader.i.i + br i1 undef, label %bb.i.i.i20.i, label %my_calloc.exit.i.i.i + +bb.i.i.i20.i: ; preds = %bb50.i.i + unreachable + +my_calloc.exit.i.i.i: ; preds = %bb50.i.i + br i1 undef, label %bb.i.i37.i.i, label %alloc_hash_table.exit.i21.i + +bb.i.i37.i.i: ; preds = %my_calloc.exit.i.i.i + unreachable + +alloc_hash_table.exit.i21.i: ; preds = %my_calloc.exit.i.i.i + br i1 undef, label %bb51.i.i, label %bb3.i23.i.i + +bb51.i.i: ; preds = %alloc_hash_table.exit.i21.i + unreachable + +bb3.i23.i.i: ; preds = %alloc_hash_table.exit.i21.i + br i1 undef, label %bb.i8.i.i, label %bb.nph.i.i + +bb.nph.i.i: ; preds = %bb3.i23.i.i + unreachable + +bb.i8.i.i: ; preds = %bb3.i.i34.i, %bb3.i23.i.i + br i1 undef, label %bb3.i.i34.i, label %bb1.i.i32.i + +bb1.i.i32.i: ; preds = %bb.i8.i.i + unreachable + +bb3.i.i34.i: ; preds = %bb.i8.i.i + br i1 undef, label %free_hash_table.exit.i.i, label %bb.i8.i.i + +free_hash_table.exit.i.i: ; preds = %bb3.i.i34.i + br i1 undef, label %check_netlist.exit.i, label %bb59.i.i + +bb59.i.i: ; preds = %free_hash_table.exit.i.i + unreachable + +check_netlist.exit.i: ; preds = %free_hash_table.exit.i.i + br label %bb.i.i3.i + +bb.i.i3.i: ; preds = %bb3.i.i4.i, %check_netlist.exit.i + br i1 false, label %bb3.i.i4.i, label %bb1.i.i.i122 + +bb1.i.i.i122: ; preds = %bb1.i.i.i122, %bb.i.i3.i + br i1 false, label %bb3.i.i4.i, label %bb1.i.i.i122 + +bb3.i.i4.i: ; preds = %bb1.i.i.i122, %bb.i.i3.i + br i1 undef, label %read_net.exit, label %bb.i.i3.i + +read_net.exit: ; preds = %bb3.i.i4.i + br i1 undef, label %bb.i44, label %bb3.i47 + +bb.i44: ; preds = %read_net.exit + unreachable + +bb3.i47: ; preds = %read_net.exit + br i1 false, label %bb9.i50, label %bb8.i49 + +bb8.i49: ; preds = %bb3.i47 + unreachable + +bb9.i50: ; preds = %bb3.i47 + br i1 undef, label %bb11.i51, label %bb12.i52 + +bb11.i51: ; preds = %bb9.i50 + unreachable + +bb12.i52: ; preds = %bb9.i50 + br i1 undef, label %bb.i.i53, label %my_malloc.exit.i54 + +bb.i.i53: ; preds = %bb12.i52 + unreachable + +my_malloc.exit.i54: ; preds = %bb12.i52 + br i1 undef, label %bb.i2.i55, label %my_malloc.exit3.i56 + +bb.i2.i55: ; preds = %my_malloc.exit.i54 + unreachable + +my_malloc.exit3.i56: ; preds = %my_malloc.exit.i54 + br i1 undef, label %bb.i.i.i57, label %my_malloc.exit.i.i + +bb.i.i.i57: ; preds = %my_malloc.exit3.i56 + unreachable + +my_malloc.exit.i.i: ; preds = %my_malloc.exit3.i56 + br i1 undef, label %bb, label %bb10 + +bb: ; preds = %my_malloc.exit.i.i + unreachable + +bb10: ; preds = %my_malloc.exit.i.i + br i1 false, label %bb12, label %bb11 + +bb11: ; preds = %bb10 + unreachable + +bb12: ; preds = %bb10 + store float %annealing_sched.1.0, float* null, align 4 + store float %annealing_sched.2.0, float* undef, align 8 + store float %annealing_sched.3.0, float* undef, align 4 + store float %annealing_sched.4.0, float* undef, align 8 + store float %router_opts.0.0, float* undef, align 8 + store float %router_opts.1.0, float* undef, align 4 + store float %router_opts.2.0, float* null, align 8 + store float %router_opts.3.0, float* undef, align 4 + br i1 undef, label %place_and_route.exit, label %bb7.i22 + +bb7.i22: ; preds = %bb12 + br i1 false, label %bb8.i23, label %bb9.i26 + +bb8.i23: ; preds = %bb7.i22 + unreachable + +bb9.i26: ; preds = %bb7.i22 + unreachable + +place_and_route.exit: ; preds = %bb12 + unreachable +} + +declare i32 @"\01_printf$LDBL128"(i8*, ...) nounwind + +declare i32 @strcmp(i8* nocapture, i8* nocapture) nounwind readonly + +declare i32 @"\01_sscanf$LDBL128"(i8*, i8*, ...) nounwind diff --git a/test/CodeGen/PowerPC/Frames-alloca.ll b/test/CodeGen/PowerPC/Frames-alloca.ll index aed4fdbb2d..466ae80341 100644 --- a/test/CodeGen/PowerPC/Frames-alloca.ll +++ b/test/CodeGen/PowerPC/Frames-alloca.ll @@ -24,7 +24,7 @@ ; CHECK-PPC64-NOFP: ld r1, 0(r1) ; CHECK-PPC64-NOFP: ld r31, -8(r1) -define i32* @f1(i32 %n) { +define i32* @f1(i32 %n) nounwind { %tmp = alloca i32, i32 %n ; [#uses=1] ret i32* %tmp } diff --git a/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll b/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll index 0f7acacbfa..b10a996867 100644 --- a/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll +++ b/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll @@ -3,14 +3,14 @@ ; RUN: llc < %s -march=ppc64 -mtriple=powerpc-apple-darwin | \ ; RUN: grep {stw r3, 32751} ; RUN: llc < %s -march=ppc64 -mtriple=powerpc-apple-darwin | \ -; RUN: grep {std r2, 9024} +; RUN: grep {std r3, 9024} -define void @test() { +define void @test() nounwind { store i32 0, i32* inttoptr (i64 48725999 to i32*) ret void } -define void @test2() { +define void @test2() nounwind { store i64 0, i64* inttoptr (i64 74560 to i64*) ret void } diff --git a/test/CodeGen/PowerPC/addc.ll b/test/CodeGen/PowerPC/addc.ll index 09a7fbd7a6..8c928ce8bc 100644 --- a/test/CodeGen/PowerPC/addc.ll +++ b/test/CodeGen/PowerPC/addc.ll @@ -1,26 +1,33 @@ ; All of these should be codegen'd without loading immediates -; RUN: llc < %s -march=ppc32 -o %t -; RUN: grep addc %t | count 1 -; RUN: grep adde %t | count 1 -; RUN: grep addze %t | count 1 -; RUN: grep addme %t | count 1 -; RUN: grep addic %t | count 2 +; RUN: llc < %s -mtriple=powerpc-apple-darwin | FileCheck %s -define i64 @add_ll(i64 %a, i64 %b) { +define i64 @add_ll(i64 %a, i64 %b) nounwind { entry: %tmp.2 = add i64 %b, %a ; [#uses=1] ret i64 %tmp.2 +; CHECK: add_ll: +; CHECK: addc r4, r6, r4 +; CHECK: adde r3, r5, r3 +; CHECK: blr } -define i64 @add_l_5(i64 %a) { +define i64 @add_l_5(i64 %a) nounwind { entry: %tmp.1 = add i64 %a, 5 ; [#uses=1] ret i64 %tmp.1 +; CHECK: add_l_5: +; CHECK: addic r4, r4, 5 +; CHECK: addze r3, r3 +; CHECK: blr } -define i64 @add_l_m5(i64 %a) { +define i64 @add_l_m5(i64 %a) nounwind { entry: %tmp.1 = add i64 %a, -5 ; [#uses=1] ret i64 %tmp.1 +; CHECK: add_l_m5: +; CHECK: addic r4, r4, -5 +; CHECK: addme r3, r3 +; CHECK: blr } diff --git a/test/CodeGen/PowerPC/indirectbr.ll b/test/CodeGen/PowerPC/indirectbr.ll index fbc7bd2264..2094e10a58 100644 --- a/test/CodeGen/PowerPC/indirectbr.ll +++ b/test/CodeGen/PowerPC/indirectbr.ll @@ -43,13 +43,13 @@ L2: ; preds = %L3, %bb2 L1: ; preds = %L2, %bb2 %res.3 = phi i32 [ %phitmp, %L2 ], [ 2, %bb2 ] ; [#uses=1] -; PIC: addis r4, r2, ha16(L_BA4__foo_L5-"L1$pb") -; PIC: li r5, lo16(L_BA4__foo_L5-"L1$pb") -; PIC: add r4, r4, r5 -; PIC: stw r4 -; STATIC: li r2, lo16(L_BA4__foo_L5) -; STATIC: addis r2, r2, ha16(L_BA4__foo_L5) -; STATIC: stw r2 +; PIC: addis r5, r4, ha16(L_BA4__foo_L5-"L1$pb") +; PIC: li r6, lo16(L_BA4__foo_L5-"L1$pb") +; PIC: add r5, r5, r6 +; PIC: stw r5 +; STATIC: li r4, lo16(L_BA4__foo_L5) +; STATIC: addis r4, r4, ha16(L_BA4__foo_L5) +; STATIC: stw r4 store i8* blockaddress(@foo, %L5), i8** @nextaddr, align 4 ret i32 %res.3 } diff --git a/test/CodeGen/PowerPC/lsr-postinc-pos.ll b/test/CodeGen/PowerPC/lsr-postinc-pos.ll new file mode 100644 index 0000000000..f441e42da2 --- /dev/null +++ b/test/CodeGen/PowerPC/lsr-postinc-pos.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s -print-lsr-output |& FileCheck %s + +; The icmp is a post-inc use, and the increment is in %bb11, but the +; scevgep needs to be inserted in %bb so that it is dominated by %t. + +; CHECK: %t = load i8** undef +; CHECK: %scevgep = getelementptr i8* %t, i32 %lsr.iv.next +; CHECK: %c1 = icmp ult i8* %scevgep, undef + +target datalayout = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f128:64:128-n32" +target triple = "powerpc-apple-darwin9" + +define void @foo() nounwind { +entry: + br label %bb11 + +bb11: + %i = phi i32 [ 0, %entry ], [ %i.next, %bb ] ; [#uses=3] + %ii = shl i32 %i, 2 ; [#uses=1] + %c0 = icmp eq i32 %i, undef ; [#uses=1] + br i1 %c0, label %bb13, label %bb + +bb: + %t = load i8** undef, align 16 ; [#uses=1] + %p = getelementptr i8* %t, i32 %ii ; [#uses=1] + %c1 = icmp ult i8* %p, undef ; [#uses=1] + %i.next = add i32 %i, 1 ; [#uses=1] + br i1 %c1, label %bb11, label %bb13 + +bb13: + unreachable +} diff --git a/test/CodeGen/PowerPC/mem_update.ll b/test/CodeGen/PowerPC/mem_update.ll index b267719421..17e7e2849c 100644 --- a/test/CodeGen/PowerPC/mem_update.ll +++ b/test/CodeGen/PowerPC/mem_update.ll @@ -3,66 +3,66 @@ ; RUN: llc < %s -march=ppc64 -enable-ppc-preinc | \ ; RUN: not grep addi -@Glob = global i64 4 ; [#uses=2] +@Glob = global i64 4 -define i32* @test0(i32* %X, i32* %dest) { - %Y = getelementptr i32* %X, i32 4 ; [#uses=2] - %A = load i32* %Y ; [#uses=1] +define i32* @test0(i32* %X, i32* %dest) nounwind { + %Y = getelementptr i32* %X, i32 4 + %A = load i32* %Y store i32 %A, i32* %dest ret i32* %Y } -define i32* @test1(i32* %X, i32* %dest) { - %Y = getelementptr i32* %X, i32 4 ; [#uses=2] - %A = load i32* %Y ; [#uses=1] +define i32* @test1(i32* %X, i32* %dest) nounwind { + %Y = getelementptr i32* %X, i32 4 + %A = load i32* %Y store i32 %A, i32* %dest ret i32* %Y } -define i16* @test2(i16* %X, i32* %dest) { - %Y = getelementptr i16* %X, i32 4 ; [#uses=2] - %A = load i16* %Y ; [#uses=1] - %B = sext i16 %A to i32 ; [#uses=1] +define i16* @test2(i16* %X, i32* %dest) nounwind { + %Y = getelementptr i16* %X, i32 4 + %A = load i16* %Y + %B = sext i16 %A to i32 store i32 %B, i32* %dest ret i16* %Y } -define i16* @test3(i16* %X, i32* %dest) { - %Y = getelementptr i16* %X, i32 4 ; [#uses=2] - %A = load i16* %Y ; [#uses=1] - %B = zext i16 %A to i32 ; [#uses=1] +define i16* @test3(i16* %X, i32* %dest) nounwind { + %Y = getelementptr i16* %X, i32 4 + %A = load i16* %Y + %B = zext i16 %A to i32 store i32 %B, i32* %dest ret i16* %Y } -define i16* @test3a(i16* %X, i64* %dest) { - %Y = getelementptr i16* %X, i32 4 ; [#uses=2] - %A = load i16* %Y ; [#uses=1] - %B = sext i16 %A to i64 ; [#uses=1] +define i16* @test3a(i16* %X, i64* %dest) nounwind { + %Y = getelementptr i16* %X, i32 4 + %A = load i16* %Y + %B = sext i16 %A to i64 store i64 %B, i64* %dest ret i16* %Y } -define i64* @test4(i64* %X, i64* %dest) { - %Y = getelementptr i64* %X, i32 4 ; [#uses=2] - %A = load i64* %Y ; [#uses=1] +define i64* @test4(i64* %X, i64* %dest) nounwind { + %Y = getelementptr i64* %X, i32 4 + %A = load i64* %Y store i64 %A, i64* %dest ret i64* %Y } -define i16* @test5(i16* %X) { - %Y = getelementptr i16* %X, i32 4 ; [#uses=2] +define i16* @test5(i16* %X) nounwind { + %Y = getelementptr i16* %X, i32 4 store i16 7, i16* %Y ret i16* %Y } -define i64* @test6(i64* %X, i64 %A) { - %Y = getelementptr i64* %X, i32 4 ; [#uses=2] +define i64* @test6(i64* %X, i64 %A) nounwind { + %Y = getelementptr i64* %X, i32 4 store i64 %A, i64* %Y ret i64* %Y } -define i64* @test7(i64* %X, i64 %A) { +define i64* @test7(i64* %X, i64 %A) nounwind { store i64 %A, i64* @Glob ret i64* @Glob } diff --git a/test/CodeGen/PowerPC/retaddr.ll b/test/CodeGen/PowerPC/retaddr.ll index 9f8647d087..cf16b4c26f 100644 --- a/test/CodeGen/PowerPC/retaddr.ll +++ b/test/CodeGen/PowerPC/retaddr.ll @@ -4,7 +4,7 @@ target triple = "powerpc-apple-darwin8" -define void @foo(i8** %X) { +define void @foo(i8** %X) nounwind { entry: %tmp = tail call i8* @llvm.returnaddress( i32 0 ) ; [#uses=1] store i8* %tmp, i8** %X, align 4 diff --git a/test/CodeGen/Thumb2/2010-02-11-phi-cycle.ll b/test/CodeGen/Thumb2/2010-02-11-phi-cycle.ll new file mode 100644 index 0000000000..363f5719d1 --- /dev/null +++ b/test/CodeGen/Thumb2/2010-02-11-phi-cycle.ll @@ -0,0 +1,76 @@ +; RUN: llc < %s -mtriple=thumbv7-apple-darwin | FileCheck %s +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" + +define arm_apcscc i32 @test(i32 %n) nounwind { +; CHECK: test: +; CHECK-NOT: mov +; CHECK: return +entry: + %0 = icmp eq i32 %n, 1 ; [#uses=1] + br i1 %0, label %return, label %bb.nph + +bb.nph: ; preds = %entry + %tmp = add i32 %n, -1 ; [#uses=1] + br label %bb + +bb: ; preds = %bb.nph, %bb + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb ] ; [#uses=1] + %u.05 = phi i64 [ undef, %bb.nph ], [ %ins, %bb ] ; [#uses=1] + %1 = tail call arm_apcscc i32 @f() nounwind ; [#uses=1] + %tmp4 = zext i32 %1 to i64 ; [#uses=1] + %mask = and i64 %u.05, -4294967296 ; [#uses=1] + %ins = or i64 %tmp4, %mask ; [#uses=2] + tail call arm_apcscc void @g(i64 %ins) nounwind + %indvar.next = add i32 %indvar, 1 ; [#uses=2] + %exitcond = icmp eq i32 %indvar.next, %tmp ; [#uses=1] + br i1 %exitcond, label %return, label %bb + +return: ; preds = %bb, %entry + ret i32 undef +} + +define arm_apcscc i32 @test_dead_cycle(i32 %n) nounwind { +; CHECK: test_dead_cycle: +; CHECK: blx +; CHECK-NOT: mov +; CHECK: blx +entry: + %0 = icmp eq i32 %n, 1 ; [#uses=1] + br i1 %0, label %return, label %bb.nph + +bb.nph: ; preds = %entry + %tmp = add i32 %n, -1 ; [#uses=2] + br label %bb + +bb: ; preds = %bb.nph, %bb2 + %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb2 ] ; [#uses=2] + %u.17 = phi i64 [ undef, %bb.nph ], [ %u.0, %bb2 ] ; [#uses=2] + %tmp9 = sub i32 %tmp, %indvar ; [#uses=1] + %1 = icmp sgt i32 %tmp9, 1 ; [#uses=1] + br i1 %1, label %bb1, label %bb2 + +bb1: ; preds = %bb + %2 = tail call arm_apcscc i32 @f() nounwind ; [#uses=1] + %tmp6 = zext i32 %2 to i64 ; [#uses=1] + %mask = and i64 %u.17, -4294967296 ; [#uses=1] + %ins = or i64 %tmp6, %mask ; [#uses=1] + tail call arm_apcscc void @g(i64 %ins) nounwind + br label %bb2 + +bb2: ; preds = %bb1, %bb +; also check for duplicate induction variables (radar 7645034) +; CHECK: subs r{{.*}}, #1 +; CHECK-NOT: subs r{{.*}}, #1 +; CHECK: pop + %u.0 = phi i64 [ %ins, %bb1 ], [ %u.17, %bb ] ; [#uses=2] + %indvar.next = add i32 %indvar, 1 ; [#uses=2] + %exitcond = icmp eq i32 %indvar.next, %tmp ; [#uses=1] + br i1 %exitcond, label %return, label %bb + +return: ; preds = %bb2, %entry + ret i32 undef +} + +declare arm_apcscc i32 @f() + +declare arm_apcscc void @g(i64) diff --git a/test/CodeGen/Thumb2/2010-02-24-BigStack.ll b/test/CodeGen/Thumb2/2010-02-24-BigStack.ll new file mode 100644 index 0000000000..533546bb19 --- /dev/null +++ b/test/CodeGen/Thumb2/2010-02-24-BigStack.ll @@ -0,0 +1,15 @@ +; RUN: llc < %s -O0 -relocation-model=pic -disable-fp-elim -mcpu=cortex-a8 -mattr=+vfp2 +; This test creates a big stack frame without spilling any callee-saved registers. +; Make sure the whole stack frame is addrerssable wiothout scavenger crashes. +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" +target triple = "thumbv7-apple-darwin3.0.0-iphoneos" + +define arm_apcscc void @FindMin(double* %panelTDEL, i8* %dclOfRow, i32 %numRows, i32 %numCols, double* %retMin_RES_TDEL) { +entry: + %panelTDEL.addr = alloca double*, align 4 ; [#uses=1] + %panelResTDEL = alloca [2560 x double], align 4 ; <[2560 x double]*> [#uses=0] + store double* %panelTDEL, double** %panelTDEL.addr + store double* %retMin_RES_TDEL, double** undef + store i32 0, i32* undef + unreachable +} diff --git a/test/CodeGen/Thumb2/cross-rc-coalescing-2.ll b/test/CodeGen/Thumb2/cross-rc-coalescing-2.ll index 8f6449e8ff..2b20931979 100644 --- a/test/CodeGen/Thumb2/cross-rc-coalescing-2.ll +++ b/test/CodeGen/Thumb2/cross-rc-coalescing-2.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=thumbv7-apple-darwin9 -mcpu=cortex-a8 | grep vmov.f32 | count 7 +; RUN: llc < %s -mtriple=thumbv7-apple-darwin9 -mcpu=cortex-a8 | grep vmov.f32 | count 3 define arm_apcscc void @fht(float* nocapture %fz, i16 signext %n) nounwind { entry: diff --git a/test/CodeGen/Thumb2/ldr-str-imm12.ll b/test/CodeGen/Thumb2/ldr-str-imm12.ll index 47d85b1aa0..f007b5c697 100644 --- a/test/CodeGen/Thumb2/ldr-str-imm12.ll +++ b/test/CodeGen/Thumb2/ldr-str-imm12.ll @@ -52,7 +52,7 @@ bb420: ; preds = %bb20, %bb20 ; CHECK: str r{{[0-7]}}, [sp] ; CHECK: str r{{[0-7]}}, [sp, #+4] ; CHECK: str r{{[0-7]}}, [sp, #+8] -; CHECK: str r{{[0-7]}}, [sp, #+24] +; CHECK: str{{(.w)?}} r{{[0-9]+}}, [sp, #+24] store %union.rec* null, %union.rec** @zz_hold, align 4 store %union.rec* null, %union.rec** @zz_res, align 4 store %union.rec* %x, %union.rec** @zz_hold, align 4 diff --git a/test/CodeGen/Thumb2/lsr-deficiency.ll b/test/CodeGen/Thumb2/lsr-deficiency.ll index 7b1b57a786..ac2cd34e4b 100644 --- a/test/CodeGen/Thumb2/lsr-deficiency.ll +++ b/test/CodeGen/Thumb2/lsr-deficiency.ll @@ -1,25 +1,29 @@ ; RUN: llc < %s -mtriple=thumbv7-apple-darwin10 -relocation-model=pic | FileCheck %s ; rdar://7387640 -; FIXME: We still need to rewrite array reference iv of stride -4 with loop -; count iv of stride -1. +; This now reduces to a single induction variable. + +; TODO: It still gets a GPR shuffle at the end of the loop +; This is because something in instruction selection has decided +; that comparing the pre-incremented value with zero is better +; than comparing the post-incremented value with -4. @G = external global i32 ; [#uses=2] @array = external global i32* ; [#uses=1] define arm_apcscc void @t() nounwind optsize { ; CHECK: t: -; CHECK: mov.w r2, #4000 -; CHECK: movw r3, #1001 +; CHECK: mov.w r2, #1000 entry: %.pre = load i32* @G, align 4 ; [#uses=1] br label %bb bb: ; preds = %bb, %entry ; CHECK: LBB1_1: -; CHECK: subs r3, #1 -; CHECK: cmp r3, #0 -; CHECK: sub.w r2, r2, #4 +; CHECK: cmp r2, #0 +; CHECK: sub.w r9, r2, #1 +; CHECK: mov r2, r9 + %0 = phi i32 [ %.pre, %entry ], [ %3, %bb ] ; [#uses=1] %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=2] %tmp5 = sub i32 1000, %indvar ; [#uses=1] diff --git a/test/CodeGen/Thumb2/thumb2-ifcvt1.ll b/test/CodeGen/Thumb2/thumb2-ifcvt1.ll index 71199abc57..1d267565e0 100644 --- a/test/CodeGen/Thumb2/thumb2-ifcvt1.ll +++ b/test/CodeGen/Thumb2/thumb2-ifcvt1.ll @@ -1,6 +1,6 @@ ; RUN: llc < %s -mtriple=thumbv7-apple-darwin | FileCheck %s -define i32 @t1(i32 %a, i32 %b, i32 %c, i32 %d) { +define i32 @t1(i32 %a, i32 %b, i32 %c, i32 %d) nounwind { ; CHECK: t1: ; CHECK: it ne ; CHECK: cmpne @@ -20,12 +20,12 @@ cond_next: } ; FIXME: Check for # of unconditional branch after adding branch folding post ifcvt. -define i32 @t2(i32 %a, i32 %b) { +define i32 @t2(i32 %a, i32 %b) nounwind { entry: ; CHECK: t2: -; CHECK: ite le -; CHECK: suble +; CHECK: ite gt ; CHECK: subgt +; CHECK: suble %tmp1434 = icmp eq i32 %a, %b ; [#uses=1] br i1 %tmp1434, label %bb17, label %bb.outer @@ -60,14 +60,14 @@ bb17: ; preds = %cond_false, %cond_true, %entry @x = external global i32* ; [#uses=1] -define void @foo(i32 %a) { +define void @foo(i32 %a) nounwind { entry: %tmp = load i32** @x ; [#uses=1] store i32 %a, i32* %tmp ret void } -define void @t3(i32 %a, i32 %b) { +define void @t3(i32 %a, i32 %b) nounwind { entry: ; CHECK: t3: ; CHECK: it lt diff --git a/test/CodeGen/Thumb2/thumb2-spill-q.ll b/test/CodeGen/Thumb2/thumb2-spill-q.ll index 7935163761..ff178b42fb 100644 --- a/test/CodeGen/Thumb2/thumb2-spill-q.ll +++ b/test/CodeGen/Thumb2/thumb2-spill-q.ll @@ -12,8 +12,8 @@ declare <4 x float> @llvm.arm.neon.vld1.v4f32(i8*) nounwind readonly define arm_apcscc void @aaa(%quuz* %this, i8* %block) { ; CHECK: aaa: ; CHECK: bic r4, r4, #15 -; CHECK: vst1.64 {{.*}}[r{{.*}}, :128] -; CHECK: vld1.64 {{.*}}[r{{.*}}, :128] +; CHECK: vst1.64 {{.*}}[{{.*}}, :128] +; CHECK: vld1.64 {{.*}}[{{.*}}, :128] entry: %0 = call <4 x float> @llvm.arm.neon.vld1.v4f32(i8* undef) nounwind ; <<4 x float>> [#uses=1] store float 6.300000e+01, float* undef, align 4 diff --git a/test/CodeGen/Thumb2/thumb2-uxtb.ll b/test/CodeGen/Thumb2/thumb2-uxtb.ll index 4e23f5356c..91598cdc96 100644 --- a/test/CodeGen/Thumb2/thumb2-uxtb.ll +++ b/test/CodeGen/Thumb2/thumb2-uxtb.ll @@ -2,14 +2,14 @@ define i32 @test1(i32 %x) { ; CHECK: test1 -; CHECK: uxtb16.w r0, r0 +; CHECK: uxtb16 r0, r0 %tmp1 = and i32 %x, 16711935 ; [#uses=1] ret i32 %tmp1 } define i32 @test2(i32 %x) { ; CHECK: test2 -; CHECK: uxtb16.w r0, r0, ror #8 +; CHECK: uxtb16 r0, r0, ror #8 %tmp1 = lshr i32 %x, 8 ; [#uses=1] %tmp2 = and i32 %tmp1, 16711935 ; [#uses=1] ret i32 %tmp2 @@ -17,7 +17,7 @@ define i32 @test2(i32 %x) { define i32 @test3(i32 %x) { ; CHECK: test3 -; CHECK: uxtb16.w r0, r0, ror #8 +; CHECK: uxtb16 r0, r0, ror #8 %tmp1 = lshr i32 %x, 8 ; [#uses=1] %tmp2 = and i32 %tmp1, 16711935 ; [#uses=1] ret i32 %tmp2 @@ -25,7 +25,7 @@ define i32 @test3(i32 %x) { define i32 @test4(i32 %x) { ; CHECK: test4 -; CHECK: uxtb16.w r0, r0, ror #8 +; CHECK: uxtb16 r0, r0, ror #8 %tmp1 = lshr i32 %x, 8 ; [#uses=1] %tmp6 = and i32 %tmp1, 16711935 ; [#uses=1] ret i32 %tmp6 @@ -33,7 +33,7 @@ define i32 @test4(i32 %x) { define i32 @test5(i32 %x) { ; CHECK: test5 -; CHECK: uxtb16.w r0, r0, ror #8 +; CHECK: uxtb16 r0, r0, ror #8 %tmp1 = lshr i32 %x, 8 ; [#uses=1] %tmp2 = and i32 %tmp1, 16711935 ; [#uses=1] ret i32 %tmp2 @@ -41,7 +41,7 @@ define i32 @test5(i32 %x) { define i32 @test6(i32 %x) { ; CHECK: test6 -; CHECK: uxtb16.w r0, r0, ror #16 +; CHECK: uxtb16 r0, r0, ror #16 %tmp1 = lshr i32 %x, 16 ; [#uses=1] %tmp2 = and i32 %tmp1, 255 ; [#uses=1] %tmp4 = shl i32 %x, 16 ; [#uses=1] @@ -52,7 +52,7 @@ define i32 @test6(i32 %x) { define i32 @test7(i32 %x) { ; CHECK: test7 -; CHECK: uxtb16.w r0, r0, ror #16 +; CHECK: uxtb16 r0, r0, ror #16 %tmp1 = lshr i32 %x, 16 ; [#uses=1] %tmp2 = and i32 %tmp1, 255 ; [#uses=1] %tmp4 = shl i32 %x, 16 ; [#uses=1] @@ -63,7 +63,7 @@ define i32 @test7(i32 %x) { define i32 @test8(i32 %x) { ; CHECK: test8 -; CHECK: uxtb16.w r0, r0, ror #24 +; CHECK: uxtb16 r0, r0, ror #24 %tmp1 = shl i32 %x, 8 ; [#uses=1] %tmp2 = and i32 %tmp1, 16711680 ; [#uses=1] %tmp5 = lshr i32 %x, 24 ; [#uses=1] @@ -73,7 +73,7 @@ define i32 @test8(i32 %x) { define i32 @test9(i32 %x) { ; CHECK: test9 -; CHECK: uxtb16.w r0, r0, ror #24 +; CHECK: uxtb16 r0, r0, ror #24 %tmp1 = lshr i32 %x, 24 ; [#uses=1] %tmp4 = shl i32 %x, 8 ; [#uses=1] %tmp5 = and i32 %tmp4, 16711680 ; [#uses=1] @@ -86,7 +86,7 @@ define i32 @test10(i32 %p0) { ; CHECK: mov.w r1, #16253176 ; CHECK: and.w r0, r1, r0, lsr #7 ; CHECK: lsrs r1, r0, #5 -; CHECK: uxtb16.w r1, r1 +; CHECK: uxtb16 r1, r1 ; CHECK: orr.w r0, r1, r0 %tmp1 = lshr i32 %p0, 7 ; [#uses=1] diff --git a/test/CodeGen/X86/2005-01-17-CycleInDAG.ll b/test/CodeGen/X86/2005-01-17-CycleInDAG.ll index 32fafc61e8..fe6674da04 100644 --- a/test/CodeGen/X86/2005-01-17-CycleInDAG.ll +++ b/test/CodeGen/X86/2005-01-17-CycleInDAG.ll @@ -7,7 +7,7 @@ @GLOBAL = external global i32 ; [#uses=1] -define i32 @test(i32* %P1, i32* %P2, i32* %P3) { +define i32 @test(i32* %P1, i32* %P2, i32* %P3) nounwind { %L = load i32* @GLOBAL ; [#uses=1] store i32 12, i32* %P2 %Y = load i32* %P3 ; [#uses=1] diff --git a/test/CodeGen/X86/2006-05-11-InstrSched.ll b/test/CodeGen/X86/2006-05-11-InstrSched.ll index bdbe713a29..56d6aa960e 100644 --- a/test/CodeGen/X86/2006-05-11-InstrSched.ll +++ b/test/CodeGen/X86/2006-05-11-InstrSched.ll @@ -1,5 +1,5 @@ ; RUN: llc < %s -march=x86 -mattr=+sse2 -stats -realign-stack=0 |&\ -; RUN: grep {asm-printer} | grep 31 +; RUN: grep {asm-printer} | grep 34 target datalayout = "e-p:32:32" define void @foo(i32* %mc, i32* %bp, i32* %ms, i32* %xmb, i32* %mpp, i32* %tpmm, i32* %ip, i32* %tpim, i32* %dpp, i32* %tpdm, i32* %bpi, i32 %M) nounwind { @@ -40,7 +40,7 @@ cond_true: ; preds = %cond_true, %entry %tmp137.upgrd.7 = bitcast i32* %tmp137 to <2 x i64>* ; <<2 x i64>*> [#uses=1] store <2 x i64> %tmp131, <2 x i64>* %tmp137.upgrd.7 %tmp147 = add nsw i32 %tmp.10, 8 ; [#uses=1] - %tmp.upgrd.8 = icmp slt i32 %tmp147, %M ; [#uses=1] + %tmp.upgrd.8 = icmp ne i32 %tmp147, %M ; [#uses=1] %indvar.next = add i32 %indvar, 1 ; [#uses=1] br i1 %tmp.upgrd.8, label %cond_true, label %return diff --git a/test/CodeGen/X86/2006-10-07-ScalarSSEMiscompile.ll b/test/CodeGen/X86/2006-10-07-ScalarSSEMiscompile.ll index bf9fa5782b..d09d061476 100644 --- a/test/CodeGen/X86/2006-10-07-ScalarSSEMiscompile.ll +++ b/test/CodeGen/X86/2006-10-07-ScalarSSEMiscompile.ll @@ -5,7 +5,7 @@ target datalayout = "e-p:32:32" target triple = "i686-apple-darwin8.7.2" -define <4 x float> @test(<4 x float> %A, <4 x float>* %B) { +define <4 x float> @test(<4 x float> %A, <4 x float>* %B) nounwind { %BV = load <4 x float>* %B ; <<4 x float>> [#uses=1] %tmp28 = tail call <4 x float> @llvm.x86.sse.sub.ss( <4 x float> %A, <4 x float> %BV ) ; <<4 x float>> [#uses=1] ret <4 x float> %tmp28 diff --git a/test/CodeGen/X86/2007-03-15-GEP-Idx-Sink.ll b/test/CodeGen/X86/2007-03-15-GEP-Idx-Sink.ll index 4cac9b4c4a..e1f890192d 100644 --- a/test/CodeGen/X86/2007-03-15-GEP-Idx-Sink.ll +++ b/test/CodeGen/X86/2007-03-15-GEP-Idx-Sink.ll @@ -1,7 +1,7 @@ ; RUN: llc < %s -march=x86 -mtriple=i686-darwin | \ ; RUN: grep push | count 3 -define void @foo(i8** %buf, i32 %size, i32 %col, i8* %p) { +define void @foo(i8** %buf, i32 %size, i32 %col, i8* %p) nounwind { entry: icmp sgt i32 %size, 0 ; :0 [#uses=1] br i1 %0, label %bb.preheader, label %return diff --git a/test/CodeGen/X86/2007-10-05-3AddrConvert.ll b/test/CodeGen/X86/2007-10-05-3AddrConvert.ll index 67323e87ef..2c2706de5d 100644 --- a/test/CodeGen/X86/2007-10-05-3AddrConvert.ll +++ b/test/CodeGen/X86/2007-10-05-3AddrConvert.ll @@ -36,7 +36,9 @@ bb.i6.i: ; preds = %bb.i6.i, %stepsystem.exit.i bb107.i.i: ; preds = %bb107.i.i, %bb.i6.i %q_addr.0.i.i.in = phi %struct.bnode** [ null, %bb107.i.i ], [ %4, %bb.i6.i ] ; <%struct.bnode**> [#uses=1] - %q_addr.0.i.i = load %struct.bnode** %q_addr.0.i.i.in ; <%struct.bnode*> [#uses=0] + %q_addr.0.i.i = load %struct.bnode** %q_addr.0.i.i.in ; <%struct.bnode*> [#uses=1] + %q_addr.1 = getelementptr %struct.anon* %0, i32 0, i32 4, i32 1 + store %struct.bnode* %q_addr.0.i.i, %struct.bnode** %q_addr.1, align 4 br label %bb107.i.i bb47.loopexit.i: ; preds = %bb32.i diff --git a/test/CodeGen/X86/2007-11-30-LoadFolding-Bug.ll b/test/CodeGen/X86/2007-11-30-LoadFolding-Bug.ll index 721d4c945b..8e315f4d80 100644 --- a/test/CodeGen/X86/2007-11-30-LoadFolding-Bug.ll +++ b/test/CodeGen/X86/2007-11-30-LoadFolding-Bug.ll @@ -35,7 +35,7 @@ cond_next36.i: ; preds = %cond_next.i bb.i28.i: ; preds = %bb.i28.i, %cond_next36.i ; CHECK: %bb.i28.i ; CHECK: addl $2 -; CHECK: addl $2 +; CHECK: addl $-2 %j.0.reg2mem.0.i16.i = phi i32 [ 0, %cond_next36.i ], [ %indvar.next39.i, %bb.i28.i ] ; [#uses=2] %din_addr.1.reg2mem.0.i17.i = phi double [ 0.000000e+00, %cond_next36.i ], [ %tmp16.i25.i, %bb.i28.i ] ; [#uses=1] %tmp1.i18.i = fptosi double %din_addr.1.reg2mem.0.i17.i to i32 ; [#uses=2] diff --git a/test/CodeGen/X86/2008-02-22-ReMatBug.ll b/test/CodeGen/X86/2008-02-22-ReMatBug.ll index 8d6bb0df1f..a91ac27f98 100644 --- a/test/CodeGen/X86/2008-02-22-ReMatBug.ll +++ b/test/CodeGen/X86/2008-02-22-ReMatBug.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 -stats |& grep {Number of re-materialization} | grep 3 +; RUN: llc < %s -march=x86 -stats |& grep {Number of re-materialization} | grep 2 ; rdar://5761454 %struct.quad_struct = type { i32, i32, %struct.quad_struct*, %struct.quad_struct*, %struct.quad_struct*, %struct.quad_struct*, %struct.quad_struct* } diff --git a/test/CodeGen/X86/2008-07-11-SpillerBug.ll b/test/CodeGen/X86/2008-07-11-SpillerBug.ll index cd99c0e53c..548b44db6d 100644 --- a/test/CodeGen/X86/2008-07-11-SpillerBug.ll +++ b/test/CodeGen/X86/2008-07-11-SpillerBug.ll @@ -1,9 +1,7 @@ ; RUN: llc < %s -march=x86 -relocation-model=static -disable-fp-elim -post-RA-scheduler=false -asm-verbose=0 | FileCheck %s ; PR2536 - -; CHECK: movw %cx -; CHECK-NEXT: andl $65534, % +; CHECK: andl $65534, % ; CHECK-NEXT: movl % ; CHECK-NEXT: movl $17 diff --git a/test/CodeGen/X86/2008-08-05-SpillerBug.ll b/test/CodeGen/X86/2008-08-05-SpillerBug.ll index 67e14ffae5..4c6493445a 100644 --- a/test/CodeGen/X86/2008-08-05-SpillerBug.ll +++ b/test/CodeGen/X86/2008-08-05-SpillerBug.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin -disable-fp-elim -stats |& grep asm-printer | grep 58 +; RUN: llc < %s -mtriple=i386-apple-darwin -disable-fp-elim -stats |& grep asm-printer | grep 55 ; PR2568 @g_3 = external global i16 ; [#uses=1] diff --git a/test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll b/test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll index 72c7ee93a9..0dca14d064 100644 --- a/test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll +++ b/test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll @@ -3,74 +3,83 @@ ; PR3538 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "i386-apple-darwin9" - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.block.type = type { i32, { }* } - %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8*, i1, i1, i8* } - %llvm.dbg.composite.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }*, { }* } - %llvm.dbg.subprogram.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1 } - %llvm.dbg.subrange.type = type { i32, i64, i64 } - %llvm.dbg.variable.type = type { i32, { }*, i8*, { }*, i32, { }* } -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str = internal constant [4 x i8] c"t.c\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@.str1 = internal constant [2 x i8] c".\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1] -@.str2 = internal constant [6 x i8] c"clang\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), i32 1, i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([2 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str2, i32 0, i32 0), i1 false, i1 false, i8* null }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@.str3 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type { i32 458788, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([4 x i8]* @.str3, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str4 = internal constant [5 x i8] c"test\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.subprogram = internal constant %llvm.dbg.subprogram.type { i32 458798, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to { }*), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([5 x i8]* @.str4, i32 0, i32 0), i8* getelementptr ([5 x i8]* @.str4, i32 0, i32 0), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 3, { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@.str5 = internal constant [2 x i8] c"X\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1] -@llvm.dbg.variable = internal constant %llvm.dbg.variable.type { i32 459009, { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*), i8* getelementptr ([2 x i8]* @.str5, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 3, { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*) }, section "llvm.metadata" ; <%llvm.dbg.variable.type*> [#uses=1] -@llvm.dbg.block = internal constant %llvm.dbg.block.type { i32 458763, { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*) }, section "llvm.metadata" ; <%llvm.dbg.block.type*> [#uses=1] -@llvm.dbg.subrange = internal constant %llvm.dbg.subrange.type { i32 458785, i64 0, i64 0 }, section "llvm.metadata" ; <%llvm.dbg.subrange.type*> [#uses=1] -@llvm.dbg.array = internal constant [1 x { }*] [{ }* bitcast (%llvm.dbg.subrange.type* @llvm.dbg.subrange to { }*)], section "llvm.metadata" ; <[1 x { }*]*> [#uses=1] -@llvm.dbg.composite = internal constant %llvm.dbg.composite.type { i32 458753, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* null, { }* null, i32 0, i64 0, i64 32, i64 0, i32 0, { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*), { }* bitcast ([1 x { }*]* @llvm.dbg.array to { }*) }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@.str6 = internal constant [2 x i8] c"Y\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1] -@llvm.dbg.variable7 = internal constant %llvm.dbg.variable.type { i32 459008, { }* bitcast (%llvm.dbg.block.type* @llvm.dbg.block to { }*), i8* getelementptr ([2 x i8]* @.str6, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 4, { }* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite to { }*) }, section "llvm.metadata" ; <%llvm.dbg.variable.type*> [#uses=1] - -define i32 @test(i32 %X) nounwind { +define signext i8 @foo(i8* %s1) nounwind ssp { entry: - %retval = alloca i32 ; [#uses=1] - %X.addr = alloca i32 ; [#uses=3] - %saved_stack = alloca i8* ; [#uses=2] - call void @llvm.dbg.func.start({ }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*)) - store i32 %X, i32* %X.addr - %0 = bitcast i32* %X.addr to { }* ; <{ }*> [#uses=1] - call void @llvm.dbg.declare({ }* %0, { }* bitcast (%llvm.dbg.variable.type* @llvm.dbg.variable to { }*)) - call void @llvm.dbg.region.start({ }* bitcast (%llvm.dbg.block.type* @llvm.dbg.block to { }*)) - call void @llvm.dbg.stoppoint(i32 4, i32 3, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - %1 = call i8* @llvm.stacksave() ; [#uses=1] - store i8* %1, i8** %saved_stack - %tmp = load i32* %X.addr ; [#uses=1] - %2 = mul i32 4, %tmp ; [#uses=1] - %vla = alloca i8, i32 %2 ; [#uses=1] - %tmp1 = bitcast i8* %vla to i32* ; [#uses=1] - %3 = bitcast i32* %tmp1 to { }* ; <{ }*> [#uses=1] - call void @llvm.dbg.declare({ }* %3, { }* bitcast (%llvm.dbg.variable.type* @llvm.dbg.variable7 to { }*)) - call void @llvm.dbg.stoppoint(i32 5, i32 1, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - call void @llvm.dbg.region.end({ }* bitcast (%llvm.dbg.block.type* @llvm.dbg.block to { }*)) - br label %cleanup + %s1_addr = alloca i8* ; [#uses=2] + %retval = alloca i32 ; [#uses=2] + %saved_stack.1 = alloca i8* ; [#uses=2] + %0 = alloca i32 ; [#uses=2] + %str.0 = alloca [0 x i8]* ; <[0 x i8]**> [#uses=3] + %1 = alloca i64 ; [#uses=2] + %2 = alloca i64 ; [#uses=1] + %3 = alloca i64 ; [#uses=6] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + call void @llvm.dbg.declare(metadata !{i8** %s1_addr}, metadata !0), !dbg !7 + store i8* %s1, i8** %s1_addr + call void @llvm.dbg.declare(metadata !{[0 x i8]** %str.0}, metadata !8), !dbg !7 + %4 = call i8* @llvm.stacksave(), !dbg !7 ; [#uses=1] + store i8* %4, i8** %saved_stack.1, align 8, !dbg !7 + %5 = load i8** %s1_addr, align 8, !dbg !13 ; [#uses=1] + %6 = call i64 @strlen(i8* %5) nounwind readonly, !dbg !13 ; [#uses=1] + %7 = add i64 %6, 1, !dbg !13 ; [#uses=1] + store i64 %7, i64* %3, align 8, !dbg !13 + %8 = load i64* %3, align 8, !dbg !13 ; [#uses=1] + %9 = sub nsw i64 %8, 1, !dbg !13 ; [#uses=0] + %10 = load i64* %3, align 8, !dbg !13 ; [#uses=1] + %11 = mul i64 %10, 8, !dbg !13 ; [#uses=0] + %12 = load i64* %3, align 8, !dbg !13 ; [#uses=1] + store i64 %12, i64* %2, align 8, !dbg !13 + %13 = load i64* %3, align 8, !dbg !13 ; [#uses=1] + %14 = mul i64 %13, 8, !dbg !13 ; [#uses=0] + %15 = load i64* %3, align 8, !dbg !13 ; [#uses=1] + store i64 %15, i64* %1, align 8, !dbg !13 + %16 = load i64* %1, align 8, !dbg !13 ; [#uses=1] + %17 = trunc i64 %16 to i32, !dbg !13 ; [#uses=1] + %18 = alloca i8, i32 %17, !dbg !13 ; [#uses=1] + %19 = bitcast i8* %18 to [0 x i8]*, !dbg !13 ; <[0 x i8]*> [#uses=1] + store [0 x i8]* %19, [0 x i8]** %str.0, align 8, !dbg !13 + %20 = load [0 x i8]** %str.0, align 8, !dbg !15 ; <[0 x i8]*> [#uses=1] + %21 = getelementptr inbounds [0 x i8]* %20, i64 0, i64 0, !dbg !15 ; [#uses=1] + store i8 0, i8* %21, align 1, !dbg !15 + %22 = load [0 x i8]** %str.0, align 8, !dbg !16 ; <[0 x i8]*> [#uses=1] + %23 = getelementptr inbounds [0 x i8]* %22, i64 0, i64 0, !dbg !16 ; [#uses=1] + %24 = load i8* %23, align 1, !dbg !16 ; [#uses=1] + %25 = sext i8 %24 to i32, !dbg !16 ; [#uses=1] + store i32 %25, i32* %0, align 4, !dbg !16 + %26 = load i8** %saved_stack.1, align 8, !dbg !16 ; [#uses=1] + call void @llvm.stackrestore(i8* %26), !dbg !16 + %27 = load i32* %0, align 4, !dbg !16 ; [#uses=1] + store i32 %27, i32* %retval, align 4, !dbg !16 + br label %return, !dbg !16 -cleanup: ; preds = %entry - %tmp2 = load i8** %saved_stack ; [#uses=1] - call void @llvm.stackrestore(i8* %tmp2) - call void @llvm.dbg.region.end({ }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*)) - %4 = load i32* %retval ; [#uses=1] - ret i32 %4 +return: ; preds = %entry + %retval1 = load i32* %retval, !dbg !16 ; [#uses=1] + %retval12 = trunc i32 %retval1 to i8, !dbg !16 ; [#uses=1] + ret i8 %retval12, !dbg !16 } -declare void @llvm.dbg.func.start({ }*) nounwind - -declare void @llvm.dbg.declare({ }*, { }*) nounwind - -declare void @llvm.dbg.region.start({ }*) nounwind - -declare void @llvm.dbg.stoppoint(i32, i32, { }*) nounwind +declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone declare i8* @llvm.stacksave() nounwind +declare i64 @strlen(i8*) nounwind readonly + declare void @llvm.stackrestore(i8*) nounwind -declare void @llvm.dbg.region.end({ }*) nounwind +!0 = metadata !{i32 459009, metadata !1, metadata !"s1", metadata !2, i32 2, metadata !6} ; [ DW_TAG_arg_variable ] +!1 = metadata !{i32 458798, i32 0, metadata !2, metadata !"foo", metadata !"foo", metadata !"foo", metadata !2, i32 2, metadata !3, i1 false, i1 true, i32 0, i32 0, null, i1 false} ; [ DW_TAG_subprogram ] +!2 = metadata !{i32 458769, i32 0, i32 1, metadata !"vla.c", metadata !"/tmp/", metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!3 = metadata !{i32 458773, metadata !2, metadata !"", metadata !2, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !4, i32 0, null} ; [ DW_TAG_subroutine_type ] +!4 = metadata !{metadata !5, metadata !6} +!5 = metadata !{i32 458788, metadata !2, metadata !"char", metadata !2, i32 0, i64 8, i64 8, i64 0, i32 0, i32 6} ; [ DW_TAG_base_type ] +!6 = metadata !{i32 458767, metadata !2, metadata !"", metadata !2, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !5} ; [ DW_TAG_pointer_type ] +!7 = metadata !{i32 2, i32 0, metadata !1, null} +!8 = metadata !{i32 459008, metadata !1, metadata !"str.0", metadata !2, i32 3, metadata !9} ; [ DW_TAG_auto_variable ] +!9 = metadata !{i32 458767, metadata !2, metadata !"", metadata !2, i32 0, i64 64, i64 64, i64 0, i32 64, metadata !10} ; [ DW_TAG_pointer_type ] +!10 = metadata !{i32 458753, metadata !2, metadata !"", metadata !2, i32 0, i64 8, i64 8, i64 0, i32 0, metadata !5, metadata !11, i32 0, null} ; [ DW_TAG_array_type ] +!11 = metadata !{metadata !12} +!12 = metadata !{i32 458785, i64 0, i64 0} ; [ DW_TAG_subrange_type ] +!13 = metadata !{i32 3, i32 0, metadata !14, null} +!14 = metadata !{i32 458763, metadata !1, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!15 = metadata !{i32 4, i32 0, metadata !14, null} +!16 = metadata !{i32 5, i32 0, metadata !14, null} diff --git a/test/CodeGen/X86/2009-07-16-LoadFoldingBug.ll b/test/CodeGen/X86/2009-07-16-LoadFoldingBug.ll deleted file mode 100644 index e21c8923df..0000000000 --- a/test/CodeGen/X86/2009-07-16-LoadFoldingBug.ll +++ /dev/null @@ -1,102 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin10 | FileCheck %s - -; CHECK: _foo: -; CHECK: pavgw LCPI1_4(%rip) - -; rdar://7057804 - -define void @foo(i16* %out8x8, i16* %in8x8, i32 %lastrow) optsize ssp { -entry: - %0 = call <8 x i16> @llvm.x86.sse2.pmulh.w(<8 x i16> , <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=2] - %1 = call <8 x i16> @llvm.x86.sse2.pcmpeq.w(<8 x i16> %0, <8 x i16> ) nounwind readnone ; <<8 x i16>> [#uses=1] - %2 = call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> zeroinitializer, i32 14) nounwind readnone ; <<8 x i16>> [#uses=1] - %3 = call <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16> %2, <8 x i16> zeroinitializer) nounwind readnone ; <<8 x i16>> [#uses=1] - %tmp.i.i10 = add <8 x i16> %0, %3 ; <<8 x i16>> [#uses=1] - %4 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> zeroinitializer, <8 x i16> %1) nounwind readnone ; <<8 x i16>> [#uses=1] - %5 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %tmp.i.i10, <8 x i16> %4) nounwind readnone ; <<8 x i16>> [#uses=3] - %6 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> %5, <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=1] - %7 = call <8 x i16> @llvm.x86.sse2.pmulh.w(<8 x i16> , <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=2] - %8 = call <8 x i16> @llvm.x86.sse2.pcmpeq.w(<8 x i16> %7, <8 x i16> ) nounwind readnone ; <<8 x i16>> [#uses=1] - %9 = call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> zeroinitializer, i32 14) nounwind readnone ; <<8 x i16>> [#uses=1] - %10 = call <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16> %9, <8 x i16> zeroinitializer) nounwind readnone ; <<8 x i16>> [#uses=1] - %tmp.i.i8 = add <8 x i16> %7, %10 ; <<8 x i16>> [#uses=1] - %11 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> undef, <8 x i16> %8) nounwind readnone ; <<8 x i16>> [#uses=1] - %12 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %tmp.i.i8, <8 x i16> %11) nounwind readnone ; <<8 x i16>> [#uses=1] - %13 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> undef, <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=1] - %14 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> %5, <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=1] - %15 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %5, <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=1] - %16 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %6, <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=1] - %17 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %12, <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=1] - %18 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> %13, <8 x i16> %15) nounwind readnone ; <<8 x i16>> [#uses=1] - %19 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> undef, <8 x i16> %14) nounwind readnone ; <<8 x i16>> [#uses=2] - %20 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> undef, <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=4] - %21 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> undef, <8 x i16> %17) nounwind readnone ; <<8 x i16>> [#uses=1] - %22 = bitcast <8 x i16> %21 to <2 x i64> ; <<2 x i64>> [#uses=1] - %23 = call <8 x i16> @llvm.x86.sse2.pmulh.w(<8 x i16> , <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=2] - %24 = call <8 x i16> @llvm.x86.sse2.pcmpeq.w(<8 x i16> %23, <8 x i16> ) nounwind readnone ; <<8 x i16>> [#uses=1] - %25 = call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> zeroinitializer, i32 14) nounwind readnone ; <<8 x i16>> [#uses=1] - %26 = call <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16> %25, <8 x i16> zeroinitializer) nounwind readnone ; <<8 x i16>> [#uses=1] - %tmp.i.i6 = add <8 x i16> %23, %26 ; <<8 x i16>> [#uses=1] - %27 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> undef, <8 x i16> %24) nounwind readnone ; <<8 x i16>> [#uses=1] - %28 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %tmp.i.i6, <8 x i16> %27) nounwind readnone ; <<8 x i16>> [#uses=1] - %29 = call <8 x i16> @llvm.x86.sse2.pmulh.w(<8 x i16> , <8 x i16> undef) nounwind readnone ; <<8 x i16>> [#uses=2] - %30 = call <8 x i16> @llvm.x86.sse2.pcmpeq.w(<8 x i16> %29, <8 x i16> ) nounwind readnone ; <<8 x i16>> [#uses=1] - %31 = call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> zeroinitializer, i32 14) nounwind readnone ; <<8 x i16>> [#uses=1] - %32 = call <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16> %31, <8 x i16> zeroinitializer) nounwind readnone ; <<8 x i16>> [#uses=1] - %tmp.i.i4 = add <8 x i16> %29, %32 ; <<8 x i16>> [#uses=1] - %33 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> undef, <8 x i16> %30) nounwind readnone ; <<8 x i16>> [#uses=1] - %34 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %tmp.i.i4, <8 x i16> %33) nounwind readnone ; <<8 x i16>> [#uses=1] - %35 = call <8 x i16> @llvm.x86.sse2.pmulh.w(<8 x i16> , <8 x i16> %20) nounwind readnone ; <<8 x i16>> [#uses=2] - %tmp.i2.i1 = mul <8 x i16> %20, ; <<8 x i16>> [#uses=1] - %36 = call <8 x i16> @llvm.x86.sse2.pcmpeq.w(<8 x i16> %35, <8 x i16> ) nounwind readnone ; <<8 x i16>> [#uses=1] - %37 = call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %tmp.i2.i1, i32 14) nounwind readnone ; <<8 x i16>> [#uses=1] - %38 = call <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16> %37, <8 x i16> zeroinitializer) nounwind readnone ; <<8 x i16>> [#uses=1] - %tmp.i.i2 = add <8 x i16> %35, %38 ; <<8 x i16>> [#uses=1] - %39 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> %19, <8 x i16> %36) nounwind readnone ; <<8 x i16>> [#uses=1] - %40 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %tmp.i.i2, <8 x i16> %39) nounwind readnone ; <<8 x i16>> [#uses=1] - %41 = call <8 x i16> @llvm.x86.sse2.pmulh.w(<8 x i16> , <8 x i16> %20) nounwind readnone ; <<8 x i16>> [#uses=2] - %tmp.i2.i = mul <8 x i16> %20, ; <<8 x i16>> [#uses=1] - %42 = call <8 x i16> @llvm.x86.sse2.pcmpeq.w(<8 x i16> %41, <8 x i16> ) nounwind readnone ; <<8 x i16>> [#uses=1] - %43 = call <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16> %tmp.i2.i, i32 14) nounwind readnone ; <<8 x i16>> [#uses=1] - %44 = call <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16> %43, <8 x i16> zeroinitializer) nounwind readnone ; <<8 x i16>> [#uses=1] - %tmp.i.i = add <8 x i16> %41, %44 ; <<8 x i16>> [#uses=1] - %45 = call <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16> %19, <8 x i16> %42) nounwind readnone ; <<8 x i16>> [#uses=1] - %46 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %tmp.i.i, <8 x i16> %45) nounwind readnone ; <<8 x i16>> [#uses=1] - %47 = call <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16> %18, <8 x i16> %16) nounwind readnone ; <<8 x i16>> [#uses=1] - %48 = bitcast <8 x i16> %47 to <2 x i64> ; <<2 x i64>> [#uses=1] - %49 = bitcast <8 x i16> %28 to <2 x i64> ; <<2 x i64>> [#uses=1] - %50 = getelementptr i16* %out8x8, i64 8 ; [#uses=1] - %51 = bitcast i16* %50 to <2 x i64>* ; <<2 x i64>*> [#uses=1] - store <2 x i64> %49, <2 x i64>* %51, align 16 - %52 = bitcast <8 x i16> %40 to <2 x i64> ; <<2 x i64>> [#uses=1] - %53 = getelementptr i16* %out8x8, i64 16 ; [#uses=1] - %54 = bitcast i16* %53 to <2 x i64>* ; <<2 x i64>*> [#uses=1] - store <2 x i64> %52, <2 x i64>* %54, align 16 - %55 = getelementptr i16* %out8x8, i64 24 ; [#uses=1] - %56 = bitcast i16* %55 to <2 x i64>* ; <<2 x i64>*> [#uses=1] - store <2 x i64> %48, <2 x i64>* %56, align 16 - %57 = bitcast <8 x i16> %46 to <2 x i64> ; <<2 x i64>> [#uses=1] - %58 = getelementptr i16* %out8x8, i64 40 ; [#uses=1] - %59 = bitcast i16* %58 to <2 x i64>* ; <<2 x i64>*> [#uses=1] - store <2 x i64> %57, <2 x i64>* %59, align 16 - %60 = bitcast <8 x i16> %34 to <2 x i64> ; <<2 x i64>> [#uses=1] - %61 = getelementptr i16* %out8x8, i64 48 ; [#uses=1] - %62 = bitcast i16* %61 to <2 x i64>* ; <<2 x i64>*> [#uses=1] - store <2 x i64> %60, <2 x i64>* %62, align 16 - %63 = getelementptr i16* %out8x8, i64 56 ; [#uses=1] - %64 = bitcast i16* %63 to <2 x i64>* ; <<2 x i64>*> [#uses=1] - store <2 x i64> %22, <2 x i64>* %64, align 16 - ret void -} - -declare <8 x i16> @llvm.x86.sse2.psubs.w(<8 x i16>, <8 x i16>) nounwind readnone - -declare <8 x i16> @llvm.x86.sse2.pmulh.w(<8 x i16>, <8 x i16>) nounwind readnone - -declare <8 x i16> @llvm.x86.sse2.pcmpeq.w(<8 x i16>, <8 x i16>) nounwind readnone - -declare <8 x i16> @llvm.x86.sse2.pavg.w(<8 x i16>, <8 x i16>) nounwind readnone - -declare <8 x i16> @llvm.x86.sse2.padds.w(<8 x i16>, <8 x i16>) nounwind readnone - -declare <8 x i16> @llvm.x86.sse2.psrli.w(<8 x i16>, i32) nounwind readnone diff --git a/test/CodeGen/X86/2009-09-07-CoalescerBug.ll b/test/CodeGen/X86/2009-09-07-CoalescerBug.ll index a5b4a79401..41b4bc0872 100644 --- a/test/CodeGen/X86/2009-09-07-CoalescerBug.ll +++ b/test/CodeGen/X86/2009-09-07-CoalescerBug.ll @@ -8,8 +8,7 @@ define i64 @hammer_time(i64 %modulep, i64 %physfree) nounwind ssp noredzone noimplicitfloat { ; CHECK: hammer_time: ; CHECK: movq $Xrsvd, %rax -; CHECK: movq $Xrsvd, %rsi -; CHECK: movq $Xrsvd, %rdi +; CHECK: movq $Xrsvd, %rcx entry: br i1 undef, label %if.then, label %if.end diff --git a/test/CodeGen/X86/2010-02-11-NonTemporal.ll b/test/CodeGen/X86/2010-02-11-NonTemporal.ll new file mode 100644 index 0000000000..5789a0b984 --- /dev/null +++ b/test/CodeGen/X86/2010-02-11-NonTemporal.ll @@ -0,0 +1,22 @@ +; RUN: llc < %s -march=x86-64 | FileCheck %s +; CHECK: movnt +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +!0 = metadata !{ i32 1 } + +define void @sub_(i32* noalias %n) { +"file movnt.f90, line 2, bb1": + %n1 = alloca i32*, align 8 + %i = alloca i32, align 4 + %"$LCS_0" = alloca i64, align 8 + %"$LCS_S2" = alloca <2 x double>, align 16 + %r9 = load <2 x double>* %"$LCS_S2", align 8 + %r10 = load i64* %"$LCS_0", align 8 + %r11 = inttoptr i64 %r10 to <2 x double>* + store <2 x double> %r9, <2 x double>* %r11, align 16, !nontemporal !0 + br label %"file movnt.f90, line 18, bb5" + +"file movnt.f90, line 18, bb5": + ret void +} diff --git a/test/CodeGen/X86/2010-02-12-CoalescerBug-Impdef.ll b/test/CodeGen/X86/2010-02-12-CoalescerBug-Impdef.ll new file mode 100644 index 0000000000..c5d3d16f81 --- /dev/null +++ b/test/CodeGen/X86/2010-02-12-CoalescerBug-Impdef.ll @@ -0,0 +1,260 @@ +; RUN: llc < %s > %t +; PR6283 + +; Tricky coalescer bug: +; After coalescing %RAX with a virtual register, this instruction was rematted: +; +; %EAX = MOV32rr %reg1070 +; +; This instruction silently defined %RAX, and when rematting removed the +; instruction, the live interval for %RAX was not properly updated. The valno +; referred to a deleted instruction and bad things happened. +; +; The fix is to implicitly define %RAX when coalescing: +; +; %EAX = MOV32rr %reg1070, %RAX +; + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-unknown-linux-gnu" + +module asm "\09.ident\09\22GCC: (GNU) 4.5.0 20100212 (experimental) LLVM: 95975\22" + +%0 = type { %"union gimple_statement_d"* } +%"BITMAP_WORD[]" = type [2 x i64] +%"char[]" = type [4 x i8] +%"enum dom_state[]" = type [2 x i32] +%"int[]" = type [4 x i32] +%"struct VEC_basic_block_base" = type { i32, i32, [1 x %"struct basic_block_def"*] } +%"struct VEC_basic_block_gc" = type { %"struct VEC_basic_block_base" } +%"struct VEC_edge_base" = type { i32, i32, [1 x %"struct edge_def"*] } +%"struct VEC_edge_gc" = type { %"struct VEC_edge_base" } +%"struct VEC_gimple_base" = type { i32, i32, [1 x %"union gimple_statement_d"*] } +%"struct VEC_gimple_gc" = type { %"struct VEC_gimple_base" } +%"struct VEC_iv_cand_p_base" = type { i32, i32, [1 x %"struct iv_cand"*] } +%"struct VEC_iv_cand_p_heap" = type { %"struct VEC_iv_cand_p_base" } +%"struct VEC_iv_use_p_base" = type { i32, i32, [1 x %"struct iv_use"*] } +%"struct VEC_iv_use_p_heap" = type { %"struct VEC_iv_use_p_base" } +%"struct VEC_loop_p_base" = type { i32, i32, [1 x %"struct loop"*] } +%"struct VEC_loop_p_gc" = type { %"struct VEC_loop_p_base" } +%"struct VEC_rtx_base" = type { i32, i32, [1 x %"struct rtx_def"*] } +%"struct VEC_rtx_gc" = type { %"struct VEC_rtx_base" } +%"struct VEC_tree_base" = type { i32, i32, [1 x %"union tree_node"*] } +%"struct VEC_tree_gc" = type { %"struct VEC_tree_base" } +%"struct _obstack_chunk" = type { i8*, %"struct _obstack_chunk"*, %"char[]" } +%"struct basic_block_def" = type { %"struct VEC_edge_gc"*, %"struct VEC_edge_gc"*, i8*, %"struct loop"*, [2 x %"struct et_node"*], %"struct basic_block_def"*, %"struct basic_block_def"*, %"union basic_block_il_dependent", i64, i32, i32, i32, i32, i32 } +%"struct bitmap_element" = type { %"struct bitmap_element"*, %"struct bitmap_element"*, i32, %"BITMAP_WORD[]" } +%"struct bitmap_head_def" = type { %"struct bitmap_element"*, %"struct bitmap_element"*, i32, %"struct bitmap_obstack"* } +%"struct bitmap_obstack" = type { %"struct bitmap_element"*, %"struct bitmap_head_def"*, %"struct obstack" } +%"struct block_symbol" = type { [3 x %"union rtunion"], %"struct object_block"*, i64 } +%"struct comp_cost" = type { i32, i32 } +%"struct control_flow_graph" = type { %"struct basic_block_def"*, %"struct basic_block_def"*, %"struct VEC_basic_block_gc"*, i32, i32, i32, %"struct VEC_basic_block_gc"*, i32, %"enum dom_state[]", %"enum dom_state[]", i32, i32 } +%"struct cost_pair" = type { %"struct iv_cand"*, %"struct comp_cost", %"struct bitmap_head_def"*, %"union tree_node"* } +%"struct def_optype_d" = type { %"struct def_optype_d"*, %"union tree_node"** } +%"struct double_int" = type { i64, i64 } +%"struct edge_def" = type { %"struct basic_block_def"*, %"struct basic_block_def"*, %"union edge_def_insns", i8*, %"union tree_node"*, i32, i32, i32, i32, i64 } +%"struct eh_status" = type opaque +%"struct et_node" = type opaque +%"struct function" = type { %"struct eh_status"*, %"struct control_flow_graph"*, %"struct gimple_seq_d"*, %"struct gimple_df"*, %"struct loops"*, %"struct htab"*, %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, %"struct machine_function"*, %"struct language_function"*, %"struct htab"*, i32, i32, i32, i32, i32, i32, i8*, i8, i8, i8, i8 } +%"struct gimple_bb_info" = type { %"struct gimple_seq_d"*, %"struct gimple_seq_d"* } +%"struct gimple_df" = type { %"struct htab"*, %"struct VEC_gimple_gc"*, %"struct VEC_tree_gc"*, %"union tree_node"*, %"struct pt_solution", %"struct pt_solution", %"struct pointer_map_t"*, %"union tree_node"*, %"struct htab"*, %"struct bitmap_head_def"*, i8, %"struct ssa_operands" } +%"struct gimple_seq_d" = type { %"struct gimple_seq_node_d"*, %"struct gimple_seq_node_d"*, %"struct gimple_seq_d"* } +%"struct gimple_seq_node_d" = type { %"union gimple_statement_d"*, %"struct gimple_seq_node_d"*, %"struct gimple_seq_node_d"* } +%"struct gimple_statement_base" = type { i8, i8, i16, i32, i32, i32, %"struct basic_block_def"*, %"union tree_node"* } +%"struct gimple_statement_phi" = type { %"struct gimple_statement_base", i32, i32, %"union tree_node"*, %"struct phi_arg_d[]" } +%"struct htab" = type { i32 (i8*)*, i32 (i8*, i8*)*, void (i8*)*, i8**, i64, i64, i64, i32, i32, i8* (i64, i64)*, void (i8*)*, i8*, i8* (i8*, i64, i64)*, void (i8*, i8*)*, i32 } +%"struct iv" = type { %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, i8, i8, i32 } +%"struct iv_cand" = type { i32, i8, i32, %"union gimple_statement_d"*, %"union tree_node"*, %"union tree_node"*, %"struct iv"*, i32, i32, %"struct iv_use"*, %"struct bitmap_head_def"* } +%"struct iv_use" = type { i32, i32, %"struct iv"*, %"union gimple_statement_d"*, %"union tree_node"**, %"struct bitmap_head_def"*, i32, %"struct cost_pair"*, %"struct iv_cand"* } +%"struct ivopts_data" = type { %"struct loop"*, %"struct pointer_map_t"*, i32, i32, %"struct version_info"*, %"struct bitmap_head_def"*, %"struct VEC_iv_use_p_heap"*, %"struct VEC_iv_cand_p_heap"*, %"struct bitmap_head_def"*, i32, i8, i8 } +%"struct lang_decl" = type opaque +%"struct language_function" = type opaque +%"struct loop" = type { i32, i32, %"struct basic_block_def"*, %"struct basic_block_def"*, %"struct comp_cost", i32, i32, %"struct VEC_loop_p_gc"*, %"struct loop"*, %"struct loop"*, i8*, %"union tree_node"*, %"struct double_int", %"struct double_int", i8, i8, i32, %"struct nb_iter_bound"*, %"struct loop_exit"*, i8, %"union tree_node"* } +%"struct loop_exit" = type { %"struct edge_def"*, %"struct loop_exit"*, %"struct loop_exit"*, %"struct loop_exit"* } +%"struct loops" = type { i32, %"struct VEC_loop_p_gc"*, %"struct htab"*, %"struct loop"* } +%"struct machine_cfa_state" = type { %"struct rtx_def"*, i64 } +%"struct machine_function" = type { %"struct stack_local_entry"*, i8*, i32, i32, %"int[]", i32, %"struct machine_cfa_state", i32, i8 } +%"struct nb_iter_bound" = type { %"union gimple_statement_d"*, %"struct double_int", i8, %"struct nb_iter_bound"* } +%"struct object_block" = type { %"union section"*, i32, i64, %"struct VEC_rtx_gc"*, %"struct VEC_rtx_gc"* } +%"struct obstack" = type { i64, %"struct _obstack_chunk"*, i8*, i8*, i8*, i64, i32, %"struct _obstack_chunk"* (i8*, i64)*, void (i8*, %"struct _obstack_chunk"*)*, i8*, i8 } +%"struct phi_arg_d" = type { %"struct ssa_use_operand_d", %"union tree_node"*, i32 } +%"struct phi_arg_d[]" = type [1 x %"struct phi_arg_d"] +%"struct pointer_map_t" = type opaque +%"struct pt_solution" = type { i8, %"struct bitmap_head_def"* } +%"struct rtx_def" = type { i16, i8, i8, %"union u" } +%"struct section_common" = type { i32 } +%"struct ssa_operand_memory_d" = type { %"struct ssa_operand_memory_d"*, %"uchar[]" } +%"struct ssa_operands" = type { %"struct ssa_operand_memory_d"*, i32, i32, i8, %"struct def_optype_d"*, %"struct use_optype_d"* } +%"struct ssa_use_operand_d" = type { %"struct ssa_use_operand_d"*, %"struct ssa_use_operand_d"*, %0, %"union tree_node"** } +%"struct stack_local_entry" = type opaque +%"struct tree_base" = type <{ i16, i8, i8, i8, [2 x i8], i8 }> +%"struct tree_common" = type { %"struct tree_base", %"union tree_node"*, %"union tree_node"* } +%"struct tree_decl_common" = type { %"struct tree_decl_minimal", %"union tree_node"*, i8, i8, i8, i8, i8, i32, %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, %"struct lang_decl"* } +%"struct tree_decl_minimal" = type { %"struct tree_common", i32, i32, %"union tree_node"*, %"union tree_node"* } +%"struct tree_decl_non_common" = type { %"struct tree_decl_with_vis", %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, %"union tree_node"* } +%"struct tree_decl_with_rtl" = type { %"struct tree_decl_common", %"struct rtx_def"* } +%"struct tree_decl_with_vis" = type { %"struct tree_decl_with_rtl", %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, i8, i8, i8 } +%"struct tree_function_decl" = type { %"struct tree_decl_non_common", %"struct function"*, %"union tree_node"*, %"union tree_node"*, %"union tree_node"*, i16, i8, i8 } +%"struct unnamed_section" = type { %"struct section_common", void (i8*)*, i8*, %"union section"* } +%"struct use_optype_d" = type { %"struct use_optype_d"*, %"struct ssa_use_operand_d" } +%"struct version_info" = type { %"union tree_node"*, %"struct iv"*, i8, i32, i8 } +%"uchar[]" = type [1 x i8] +%"union basic_block_il_dependent" = type { %"struct gimple_bb_info"* } +%"union edge_def_insns" = type { %"struct gimple_seq_d"* } +%"union gimple_statement_d" = type { %"struct gimple_statement_phi" } +%"union rtunion" = type { i8* } +%"union section" = type { %"struct unnamed_section" } +%"union tree_node" = type { %"struct tree_function_decl" } +%"union u" = type { %"struct block_symbol" } + +declare fastcc %"union tree_node"* @get_computation_at(%"struct loop"*, %"struct iv_use"* nocapture, %"struct iv_cand"* nocapture, %"union gimple_statement_d"*) nounwind + +declare fastcc i32 @computation_cost(%"union tree_node"*, i8 zeroext) nounwind + +define fastcc i64 @get_computation_cost_at(%"struct ivopts_data"* %data, %"struct iv_use"* nocapture %use, %"struct iv_cand"* nocapture %cand, i8 zeroext %address_p, %"struct bitmap_head_def"** %depends_on, %"union gimple_statement_d"* %at, i8* %can_autoinc) nounwind { +entry: + br i1 undef, label %"100", label %"4" + +"4": ; preds = %entry + br i1 undef, label %"6", label %"5" + +"5": ; preds = %"4" + unreachable + +"6": ; preds = %"4" + br i1 undef, label %"8", label %"7" + +"7": ; preds = %"6" + unreachable + +"8": ; preds = %"6" + br i1 undef, label %"100", label %"10" + +"10": ; preds = %"8" + br i1 undef, label %"17", label %"16" + +"16": ; preds = %"10" + unreachable + +"17": ; preds = %"10" + br i1 undef, label %"19", label %"18" + +"18": ; preds = %"17" + unreachable + +"19": ; preds = %"17" + br i1 undef, label %"93", label %"20" + +"20": ; preds = %"19" + br i1 undef, label %"23", label %"21" + +"21": ; preds = %"20" + unreachable + +"23": ; preds = %"20" + br i1 undef, label %"100", label %"25" + +"25": ; preds = %"23" + br i1 undef, label %"100", label %"26" + +"26": ; preds = %"25" + br i1 undef, label %"30", label %"28" + +"28": ; preds = %"26" + unreachable + +"30": ; preds = %"26" + br i1 undef, label %"59", label %"51" + +"51": ; preds = %"30" + br i1 undef, label %"55", label %"52" + +"52": ; preds = %"51" + unreachable + +"55": ; preds = %"51" + %0 = icmp ugt i32 0, undef ; [#uses=1] + br i1 %0, label %"50.i", label %"9.i" + +"9.i": ; preds = %"55" + unreachable + +"50.i": ; preds = %"55" + br i1 undef, label %"55.i", label %"54.i" + +"54.i": ; preds = %"50.i" + br i1 undef, label %"57.i", label %"55.i" + +"55.i": ; preds = %"54.i", %"50.i" + unreachable + +"57.i": ; preds = %"54.i" + br label %"63.i" + +"61.i": ; preds = %"63.i" + br i1 undef, label %"64.i", label %"62.i" + +"62.i": ; preds = %"61.i" + br label %"63.i" + +"63.i": ; preds = %"62.i", %"57.i" + br i1 undef, label %"61.i", label %"64.i" + +"64.i": ; preds = %"63.i", %"61.i" + unreachable + +"59": ; preds = %"30" + br i1 undef, label %"60", label %"82" + +"60": ; preds = %"59" + br i1 undef, label %"61", label %"82" + +"61": ; preds = %"60" + br i1 undef, label %"62", label %"82" + +"62": ; preds = %"61" + br i1 undef, label %"100", label %"63" + +"63": ; preds = %"62" + br i1 undef, label %"65", label %"64" + +"64": ; preds = %"63" + unreachable + +"65": ; preds = %"63" + br i1 undef, label %"66", label %"67" + +"66": ; preds = %"65" + unreachable + +"67": ; preds = %"65" + %1 = load i32* undef, align 4 ; [#uses=0] + br label %"100" + +"82": ; preds = %"61", %"60", %"59" + unreachable + +"93": ; preds = %"19" + %2 = call fastcc %"union tree_node"* @get_computation_at(%"struct loop"* undef, %"struct iv_use"* %use, %"struct iv_cand"* %cand, %"union gimple_statement_d"* %at) nounwind ; <%"union tree_node"*> [#uses=1] + br i1 undef, label %"100", label %"97" + +"97": ; preds = %"93" + br i1 undef, label %"99", label %"98" + +"98": ; preds = %"97" + br label %"99" + +"99": ; preds = %"98", %"97" + %3 = phi %"union tree_node"* [ undef, %"98" ], [ %2, %"97" ] ; <%"union tree_node"*> [#uses=1] + %4 = call fastcc i32 @computation_cost(%"union tree_node"* %3, i8 zeroext undef) nounwind ; [#uses=1] + br label %"100" + +"100": ; preds = %"99", %"93", %"67", %"62", %"25", %"23", %"8", %entry + %memtmp1.1.0 = phi i32 [ 0, %"99" ], [ 10000000, %entry ], [ 10000000, %"8" ], [ 10000000, %"23" ], [ 10000000, %"25" ], [ undef, %"62" ], [ undef, %"67" ], [ 10000000, %"93" ] ; [#uses=1] + %memtmp1.0.0 = phi i32 [ %4, %"99" ], [ 10000000, %entry ], [ 10000000, %"8" ], [ 10000000, %"23" ], [ 10000000, %"25" ], [ undef, %"62" ], [ undef, %"67" ], [ 10000000, %"93" ] ; [#uses=1] + %5 = zext i32 %memtmp1.0.0 to i64 ; [#uses=1] + %6 = zext i32 %memtmp1.1.0 to i64 ; [#uses=1] + %7 = shl i64 %6, 32 ; [#uses=1] + %8 = or i64 %7, %5 ; [#uses=1] + ret i64 %8 +} diff --git a/test/CodeGen/X86/2010-02-15-ImplicitDefBug.ll b/test/CodeGen/X86/2010-02-15-ImplicitDefBug.ll new file mode 100644 index 0000000000..c429172852 --- /dev/null +++ b/test/CodeGen/X86/2010-02-15-ImplicitDefBug.ll @@ -0,0 +1,80 @@ +; RUN: llc < %s > %t +; PR6300 +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-pc-linux-gnu" + +; When the "154" loops back onto itself, it defines a register after using it. +; The first value of the register is implicit-def. + +%"struct location_chain_def" = type { %"struct location_chain_def"*, %"struct rtx_def"*, %"struct rtx_def"*, i32 } +%"struct real_value" = type { i32, [5 x i32] } +%"struct rtx_def" = type { i16, i8, i8, %"union u" } +%"union u" = type { %"struct real_value" } + +define i32 @variable_union(i8** nocapture %slot, i8* nocapture %data) nounwind { +entry: + br i1 undef, label %"4.thread", label %"3" + +"4.thread": ; preds = %entry + unreachable + +"3": ; preds = %entry + br i1 undef, label %"19", label %"20" + +"19": ; preds = %"3" + unreachable + +"20": ; preds = %"3" + br i1 undef, label %"56.preheader", label %dv_onepart_p.exit + +dv_onepart_p.exit: ; preds = %"20" + unreachable + +"56.preheader": ; preds = %"20" + br label %"56" + +"50": ; preds = %"57" + br label %"56" + +"56": ; preds = %"50", %"56.preheader" + br i1 undef, label %"57", label %"58" + +"57": ; preds = %"56" + br i1 undef, label %"50", label %"58" + +"58": ; preds = %"57", %"56" + br i1 undef, label %"62", label %"63" + +"62": ; preds = %"58" + unreachable + +"63": ; preds = %"58" + br i1 undef, label %"67", label %"66" + +"66": ; preds = %"63" + br label %"67" + +"67": ; preds = %"66", %"63" + br label %"68" + +"68": ; preds = %"161", %"67" + br i1 undef, label %"153", label %"161" + +"153": ; preds = %"68" + br i1 undef, label %"160", label %bb.nph46 + +bb.nph46: ; preds = %"153" + br label %"154" + +"154": ; preds = %"154", %bb.nph46 + %0 = phi %"struct location_chain_def"** [ undef, %bb.nph46 ], [ %1, %"154" ] ; <%"struct location_chain_def"**> [#uses=1] + %1 = bitcast i8* undef to %"struct location_chain_def"** ; <%"struct location_chain_def"**> [#uses=1] + store %"struct location_chain_def"* undef, %"struct location_chain_def"** %0, align 4 + br i1 undef, label %"160", label %"154" + +"160": ; preds = %"154", %"153" + br label %"161" + +"161": ; preds = %"160", %"68" + br label %"68" +} diff --git a/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll b/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll new file mode 100644 index 0000000000..eb21dc234a --- /dev/null +++ b/test/CodeGen/X86/2010-02-19-TailCallRetAddrBug.ll @@ -0,0 +1,55 @@ +; RUN: llc -mtriple=i386-apple-darwin -tailcallopt < %s | FileCheck %s +; Check that lowered argumens do not overwrite the return address before it is moved. +; Bug 6225 +; +; If a call is a fastcc tail call and tail call optimization is enabled, the +; caller frame is replaced by the callee frame. This can require that arguments are +; placed on the former return address stack slot. Special care needs to be taken +; taken that the return address is moved / or stored in a register before +; lowering of arguments potentially overwrites the value. +; +; Move return address (76(%esp)) to a temporary register (%ebp) +; CHECK: movl 76(%esp), %ebp +; Overwrite return addresss +; CHECK: movl %ecx, 76(%esp) +; Move return address from temporary register (%ebp) to new stack location (60(%esp)) +; CHECK: movl %ebp, 60(%esp) + +%tupl_p = type [9 x i32]* + +declare fastcc void @l297(i32 %r10, i32 %r9, i32 %r8, i32 %r7, i32 %r6, i32 %r5, i32 %r3, i32 %r2) noreturn nounwind +declare fastcc void @l298(i32 %r10, i32 %r9, i32 %r4) noreturn nounwind + +define fastcc void @l186(%tupl_p %r1) noreturn nounwind { +entry: + %ptr1 = getelementptr %tupl_p %r1, i32 0, i32 0 + %r2 = load i32* %ptr1 + %ptr3 = getelementptr %tupl_p %r1, i32 0, i32 1 + %r3 = load i32* %ptr3 + %ptr5 = getelementptr %tupl_p %r1, i32 0, i32 2 + %r4 = load i32* %ptr5 + %ptr7 = getelementptr %tupl_p %r1, i32 0, i32 3 + %r5 = load i32* %ptr7 + %ptr9 = getelementptr %tupl_p %r1, i32 0, i32 4 + %r6 = load i32* %ptr9 + %ptr11 = getelementptr %tupl_p %r1, i32 0, i32 5 + %r7 = load i32* %ptr11 + %ptr13 = getelementptr %tupl_p %r1, i32 0, i32 6 + %r8 = load i32* %ptr13 + %ptr15 = getelementptr %tupl_p %r1, i32 0, i32 7 + %r9 = load i32* %ptr15 + %ptr17 = getelementptr %tupl_p %r1, i32 0, i32 8 + %r10 = load i32* %ptr17 + %cond = icmp eq i32 %r10, 3 + br i1 %cond, label %true, label %false + +true: + tail call fastcc void @l297(i32 %r10, i32 %r9, i32 %r8, i32 %r7, i32 %r6, i32 %r5, i32 %r3, i32 %r2) noreturn nounwind + ret void + +false: + tail call fastcc void @l298(i32 %r10, i32 %r9, i32 %r4) noreturn nounwind + ret void +} + + diff --git a/test/CodeGen/X86/2010-02-23-DAGCombineBug.ll b/test/CodeGen/X86/2010-02-23-DAGCombineBug.ll new file mode 100644 index 0000000000..6a58e9e551 --- /dev/null +++ b/test/CodeGen/X86/2010-02-23-DAGCombineBug.ll @@ -0,0 +1,18 @@ +; RUN: llc < %s -march=x86 | FileCheck %s + +define i32* @t() nounwind optsize ssp { +entry: +; CHECK: t: +; CHECK: testl %eax, %eax +; CHECK: js + %cmp = icmp slt i32 undef, 0 ; [#uses=1] + %outsearch.0 = select i1 %cmp, i1 false, i1 true ; [#uses=1] + br i1 %outsearch.0, label %if.then27, label %if.else29 + +if.then27: ; preds = %entry + ret i32* undef + +if.else29: ; preds = %entry + unreachable +} + diff --git a/test/CodeGen/X86/2010-02-23-DIV8rDefinesAX.ll b/test/CodeGen/X86/2010-02-23-DIV8rDefinesAX.ll new file mode 100644 index 0000000000..8543c80117 --- /dev/null +++ b/test/CodeGen/X86/2010-02-23-DIV8rDefinesAX.ll @@ -0,0 +1,20 @@ +; RUN: llc < %s +; PR6374 +; +; This test produces a DIV8r instruction and uses %AX instead of %AH and %AL. +; The DIV8r must have the right imp-defs for that to work. +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin10.0.0" + +%struct._i386_state = type { %union.anon } +%union.anon = type { [0 x i8] } + +define void @i386_aam(%struct._i386_state* nocapture %cpustate) nounwind ssp { +entry: + %call = tail call fastcc signext i8 @FETCH() ; [#uses=1] + %rem = urem i8 0, %call ; [#uses=1] + store i8 %rem, i8* undef + ret void +} + +declare fastcc signext i8 @FETCH() nounwind readnone ssp diff --git a/test/CodeGen/X86/2010-02-23-RematImplicitSubreg.ll b/test/CodeGen/X86/2010-02-23-RematImplicitSubreg.ll new file mode 100644 index 0000000000..4a26ba088e --- /dev/null +++ b/test/CodeGen/X86/2010-02-23-RematImplicitSubreg.ll @@ -0,0 +1,49 @@ +; RUN: llc < %s +; PR6372 +; +; This test produces a move instruction with an implicitly defined super-register: +; +; %DL = MOV8rr %reg1038, %RDX +; +; When %DL is rematerialized, we must remember to update live intervals for +; sub-registers %DX and %EDX. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin10.0.0" + +define noalias i8* @foo() nounwind ssp { +entry: + br i1 undef, label %for.end, label %for.body + +for.body: ; preds = %if.end40, %entry + %tmp6 = load i8* undef, align 2 ; [#uses=3] + %conv11 = sext i8 %tmp6 to i64 ; [#uses=1] + %cmp15 = icmp slt i64 %conv11, undef ; [#uses=1] + br i1 %cmp15, label %if.end, label %if.then + +if.then: ; preds = %for.body + %conv18 = sext i8 %tmp6 to i32 ; [#uses=1] + %call = tail call i32 (...)* @invalid(i32 0, i32 0, i32 %conv18) nounwind ; [#uses=0] + br label %if.end + +if.end: ; preds = %if.then, %for.body + %index.0 = phi i8 [ 0, %if.then ], [ %tmp6, %for.body ] ; [#uses=1] + store i8 %index.0, i8* undef + %tmp24 = load i8* undef ; [#uses=2] + br i1 undef, label %if.end40, label %if.then36 + +if.then36: ; preds = %if.end + %conv38 = sext i8 %tmp24 to i32 ; [#uses=1] + %call39 = tail call i32 (...)* @invalid(i32 0, i32 0, i32 %conv38) nounwind ; [#uses=0] + br label %if.end40 + +if.end40: ; preds = %if.then36, %if.end + %index.1 = phi i8 [ 0, %if.then36 ], [ %tmp24, %if.end ] ; [#uses=1] + store i8 %index.1, i8* undef + br i1 false, label %for.body, label %for.end + +for.end: ; preds = %if.end40, %entry + ret i8* undef +} + +declare i32 @invalid(...) diff --git a/test/CodeGen/X86/2010-02-23-SingleDefPhiJoin.ll b/test/CodeGen/X86/2010-02-23-SingleDefPhiJoin.ll new file mode 100644 index 0000000000..aeed401461 --- /dev/null +++ b/test/CodeGen/X86/2010-02-23-SingleDefPhiJoin.ll @@ -0,0 +1,146 @@ +; RUN: llc < %s +; PR6363 +; +; This test case creates a phi join register with a single definition. The other +; predecessor blocks are implicit-def. +; +; If LiveIntervalAnalysis fails to recognize this as a phi join, the coalescer +; will detect an infinity valno loop. +; +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +define i32 @decode(i8* nocapture %input, i32 %offset, i8* nocapture %output) nounwind { +entry: + br i1 undef, label %meshBB86, label %meshBB102 + +bb: ; preds = %meshBB106, %meshBB102 + br i1 false, label %bb9, label %meshBB90 + +bb.nph: ; preds = %meshBB90 + br label %meshBB114 + +bb.nph.fragment: ; preds = %meshBB114 + br label %meshBB118 + +bb1.fragment: ; preds = %meshBB118 + br i1 false, label %bb2, label %bb3 + +bb2: ; preds = %bb1.fragment + br label %meshBB74 + +bb2.fragment15: ; preds = %meshBB74 + br label %meshBB98 + +bb3: ; preds = %bb1.fragment + br i1 undef, label %meshBB, label %meshBB102 + +bb4: ; preds = %meshBB + br label %meshBB118 + +bb4.fragment: ; preds = %meshBB118 + br label %meshBB82 + +bb5: ; preds = %meshBB102, %meshBB82 + br i1 false, label %bb6, label %bb7 + +bb6: ; preds = %bb5 + br label %bb7 + +bb7: ; preds = %meshBB98, %bb6, %bb5 + br label %meshBB114 + +bb7.fragment: ; preds = %meshBB114 + br i1 undef, label %meshBB74, label %bb9 + +bb9: ; preds = %bb7.fragment, %bb + br label %bb1.i23 + +bb1.i23: ; preds = %meshBB110, %bb9 + br i1 undef, label %meshBB106, label %meshBB110 + +skip_to_newline.exit26: ; preds = %meshBB106 + br label %meshBB86 + +skip_to_newline.exit26.fragment: ; preds = %meshBB86 + br i1 false, label %meshBB90, label %meshBB106 + +bb11.fragment: ; preds = %meshBB90, %meshBB86 + br label %meshBB122 + +bb1.i: ; preds = %meshBB122, %meshBB + %ooffset.2.lcssa.phi.SV.phi203 = phi i32 [ 0, %meshBB122 ], [ %ooffset.2.lcssa.phi.SV.phi233, %meshBB ] ; [#uses=1] + br label %meshBB98 + +bb1.i.fragment: ; preds = %meshBB98 + br i1 undef, label %meshBB78, label %meshBB + +skip_to_newline.exit: ; preds = %meshBB78 + br i1 undef, label %bb12, label %meshBB110 + +bb12: ; preds = %skip_to_newline.exit + br label %meshBB94 + +bb12.fragment: ; preds = %meshBB94 + br i1 false, label %bb13, label %meshBB78 + +bb13: ; preds = %bb12.fragment + br label %meshBB82 + +bb13.fragment: ; preds = %meshBB82 + br i1 undef, label %meshBB94, label %meshBB122 + +bb14: ; preds = %meshBB94 + ret i32 %ooffset.2.lcssa.phi.SV.phi250 + +bb15: ; preds = %meshBB122, %meshBB110, %meshBB78 + unreachable + +meshBB: ; preds = %bb1.i.fragment, %bb3 + %ooffset.2.lcssa.phi.SV.phi233 = phi i32 [ undef, %bb3 ], [ %ooffset.2.lcssa.phi.SV.phi209, %bb1.i.fragment ] ; [#uses=1] + br i1 undef, label %bb1.i, label %bb4 + +meshBB74: ; preds = %bb7.fragment, %bb2 + br i1 false, label %meshBB118, label %bb2.fragment15 + +meshBB78: ; preds = %bb12.fragment, %bb1.i.fragment + %ooffset.2.lcssa.phi.SV.phi239 = phi i32 [ %ooffset.2.lcssa.phi.SV.phi209, %bb1.i.fragment ], [ %ooffset.2.lcssa.phi.SV.phi250, %bb12.fragment ] ; [#uses=1] + br i1 false, label %bb15, label %skip_to_newline.exit + +meshBB82: ; preds = %bb13, %bb4.fragment + br i1 false, label %bb5, label %bb13.fragment + +meshBB86: ; preds = %skip_to_newline.exit26, %entry + br i1 undef, label %skip_to_newline.exit26.fragment, label %bb11.fragment + +meshBB90: ; preds = %skip_to_newline.exit26.fragment, %bb + br i1 false, label %bb11.fragment, label %bb.nph + +meshBB94: ; preds = %bb13.fragment, %bb12 + %ooffset.2.lcssa.phi.SV.phi250 = phi i32 [ 0, %bb13.fragment ], [ %ooffset.2.lcssa.phi.SV.phi239, %bb12 ] ; [#uses=2] + br i1 false, label %bb12.fragment, label %bb14 + +meshBB98: ; preds = %bb1.i, %bb2.fragment15 + %ooffset.2.lcssa.phi.SV.phi209 = phi i32 [ undef, %bb2.fragment15 ], [ %ooffset.2.lcssa.phi.SV.phi203, %bb1.i ] ; [#uses=2] + br i1 undef, label %bb1.i.fragment, label %bb7 + +meshBB102: ; preds = %bb3, %entry + br i1 undef, label %bb5, label %bb + +meshBB106: ; preds = %skip_to_newline.exit26.fragment, %bb1.i23 + br i1 undef, label %bb, label %skip_to_newline.exit26 + +meshBB110: ; preds = %skip_to_newline.exit, %bb1.i23 + br i1 false, label %bb15, label %bb1.i23 + +meshBB114: ; preds = %bb7, %bb.nph + %meshStackVariable115.phi = phi i32 [ 19, %bb7 ], [ 8, %bb.nph ] ; [#uses=0] + br i1 undef, label %bb.nph.fragment, label %bb7.fragment + +meshBB118: ; preds = %meshBB74, %bb4, %bb.nph.fragment + %meshCmp121 = icmp eq i32 undef, 10 ; [#uses=1] + br i1 %meshCmp121, label %bb4.fragment, label %bb1.fragment + +meshBB122: ; preds = %bb13.fragment, %bb11.fragment + br i1 false, label %bb1.i, label %bb15 +} diff --git a/test/CodeGen/X86/2010-03-04-Mul8Bug.ll b/test/CodeGen/X86/2010-03-04-Mul8Bug.ll new file mode 100644 index 0000000000..48e75e9572 --- /dev/null +++ b/test/CodeGen/X86/2010-03-04-Mul8Bug.ll @@ -0,0 +1,25 @@ +; RUN: llc < %s +; PR6489 +; +; This test case produces a MUL8 instruction and then tries to read the result +; from the AX register instead of AH/AL. That confuses live interval analysis. +; +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin10.0.0" + +define void @func_56(i64 %p_57, i32*** %p_58) nounwind ssp { +for.end: + %conv49 = trunc i32 undef to i8 ; [#uses=1] + %div.i = udiv i8 %conv49, 5 ; [#uses=1] + %conv51 = zext i8 %div.i to i32 ; [#uses=1] + %call55 = call i32 @qux(i32 undef, i32 -2) nounwind ; [#uses=1] + %rem.i = urem i32 %call55, -1 ; [#uses=1] + %cmp57 = icmp uge i32 %conv51, %rem.i ; [#uses=1] + %conv58 = zext i1 %cmp57 to i32 ; [#uses=1] + %call85 = call i32 @func_35(i32*** undef, i32 undef, i32 %conv58, i32 1247, i32 0) nounwind ; [#uses=0] + ret void +} + +declare i32 @func_35(i32***, i32, i32, i32, i32) + +declare i32 @qux(i32, i32) diff --git a/test/CodeGen/X86/2010-03-05-ConstantFoldCFG.ll b/test/CodeGen/X86/2010-03-05-ConstantFoldCFG.ll new file mode 100644 index 0000000000..5de19662ff --- /dev/null +++ b/test/CodeGen/X86/2010-03-05-ConstantFoldCFG.ll @@ -0,0 +1,42 @@ +; RUN: llc < %s -verify-machineinstrs +; +; When BRCOND is constant-folded to BR, make sure that PHI nodes don't get +; spurious operands when the CFG is trimmed. +; +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin10.2" + +define fastcc void @_ZSt16__introsort_loopIPdl17less_than_functorEvT_S2_T0_T1_(double* %__first, double* %__last, i64 %__depth_limit) nounwind ssp { +entry: + br i1 undef, label %bb1, label %bb2 + +bb1: ; preds = %entry + ret void + +bb2: ; preds = %entry + br label %bb2.outer.i + +bb2.outer.i: ; preds = %bb9.i, %bb2 + br i1 undef, label %bb1.i, label %bb5.preheader.i + +bb1.i: ; preds = %bb1.i, %bb2.outer.i + %indvar5.i = phi i64 [ %tmp, %bb1.i ], [ 0, %bb2.outer.i ] ; [#uses=1] + %tmp = add i64 %indvar5.i, 1 ; [#uses=2] + %scevgep.i = getelementptr double* undef, i64 %tmp ; [#uses=0] + br i1 undef, label %bb1.i, label %bb5.preheader.i + +bb5.preheader.i: ; preds = %bb1.i, %bb2.outer.i + br label %bb5.i + +bb5.i: ; preds = %bb5.i, %bb5.preheader.i + br i1 undef, label %bb5.i, label %bb7.i6 + +bb7.i6: ; preds = %bb5.i + br i1 undef, label %bb9.i, label %_ZSt21__unguarded_partitionIPdd17less_than_functorET_S2_S2_T0_T1_.exit + +bb9.i: ; preds = %bb7.i6 + br label %bb2.outer.i + +_ZSt21__unguarded_partitionIPdd17less_than_functorET_S2_S2_T0_T1_.exit: ; preds = %bb7.i6 + unreachable +} diff --git a/test/CodeGen/X86/2010-03-05-EFLAGS-Redef.ll b/test/CodeGen/X86/2010-03-05-EFLAGS-Redef.ll new file mode 100644 index 0000000000..3cca10e268 --- /dev/null +++ b/test/CodeGen/X86/2010-03-05-EFLAGS-Redef.ll @@ -0,0 +1,49 @@ +; RUN: llc < %s -verify-machineinstrs +; +; This test case is transformed into a single basic block by the machine +; branch folding pass. That makes a complete mess of the %EFLAGS liveness, but +; we don't care about liveness this late anyway. + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin10.2" + +define i32 @main(i32 %argc, i8** nocapture %argv) ssp { +entry: + br i1 undef, label %bb, label %bb2 + +bb: ; preds = %entry + br label %bb2 + +bb2: ; preds = %bb, %entry + br i1 undef, label %bb3, label %bb5 + +bb3: ; preds = %bb2 + br label %bb5 + +bb5: ; preds = %bb3, %bb2 + br i1 undef, label %bb.nph239, label %bb8 + +bb.nph239: ; preds = %bb5 + unreachable + +bb8: ; preds = %bb5 + br i1 undef, label %bb.nph237, label %bb47 + +bb.nph237: ; preds = %bb8 + unreachable + +bb47: ; preds = %bb8 + br i1 undef, label %bb49, label %bb48 + +bb48: ; preds = %bb47 + unreachable + +bb49: ; preds = %bb47 + br i1 undef, label %bb51, label %bb50 + +bb50: ; preds = %bb49 + ret i32 0 + +bb51: ; preds = %bb49 + ret i32 0 +} diff --git a/test/CodeGen/X86/addr-label-difference.ll b/test/CodeGen/X86/addr-label-difference.ll index 547d6b5765..be0908aa1a 100644 --- a/test/CodeGen/X86/addr-label-difference.ll +++ b/test/CodeGen/X86/addr-label-difference.ll @@ -9,14 +9,18 @@ target triple = "i386-apple-darwin10.0" define void @test(i32 %i) nounwind ssp { entry: + call void @test(i32 1) br label %foo -foo: ; preds = %indirectgoto, %indirectgoto, %indirectgoto, %indirectgoto, %indirectgoto +foo: + call void @test(i32 1) br label %bar -bar: ; preds = %foo, %indirectgoto +bar: + call void @test(i32 1) br label %hack -hack: ; preds = %bar, %indirectgoto +hack: + call void @test(i32 1) ret void } diff --git a/test/CodeGen/X86/and-or-fold.ll b/test/CodeGen/X86/and-or-fold.ll index 7733b8a5ba..836b5f1551 100644 --- a/test/CodeGen/X86/and-or-fold.ll +++ b/test/CodeGen/X86/and-or-fold.ll @@ -1,14 +1,26 @@ -; RUN: llc < %s -march=x86 | grep and | count 1 +; RUN: llc < %s -mtriple=i686-apple-darwin | FileCheck -check-prefix=DARWIN %s +; RUN: opt < %s -O2 | llc -mtriple=x86_64-apple-darwin | FileCheck -check-prefix=DARWIN-OPT %s ; The dag combiner should fold together (x&127)|(y&16711680) -> (x|y)&c1 ; in this case. -define i32 @test6(i32 %x, i16 %y) { - %tmp1 = zext i16 %y to i32 ; [#uses=1] - %tmp2 = and i32 %tmp1, 127 ; [#uses=1] - %tmp4 = shl i32 %x, 16 ; [#uses=1] - %tmp5 = and i32 %tmp4, 16711680 ; [#uses=1] - %tmp6 = or i32 %tmp2, %tmp5 ; [#uses=1] - ret i32 %tmp6 +define i32 @test1(i32 %x, i16 %y) { + %tmp1 = zext i16 %y to i32 + %tmp2 = and i32 %tmp1, 127 + %tmp4 = shl i32 %x, 16 + %tmp5 = and i32 %tmp4, 16711680 + %tmp6 = or i32 %tmp2, %tmp5 + ret i32 %tmp6 +; DARWIN: andl $16711807, %eax } +; The optimizer shouldn't fold this into (and (or, C), D) +; if (C & D) == 0 +define i64 @test2(i64 %x) nounwind readnone ssp { +entry: + %tmp1 = and i64 %x, 123127 + %tmp2 = or i64 %tmp1, 3 + ret i64 %tmp2 +; DARWIN-OPT: andq $123124 +; DARWIN-OPT-NEXT: leaq 3 +} diff --git a/test/CodeGen/X86/bswap-inline-asm.ll b/test/CodeGen/X86/bswap-inline-asm.ll index 5bf58fa1d5..2b7019371a 100644 --- a/test/CodeGen/X86/bswap-inline-asm.ll +++ b/test/CodeGen/X86/bswap-inline-asm.ll @@ -1,17 +1,80 @@ ; RUN: llc < %s -march=x86-64 > %t ; RUN: not grep APP %t -; RUN: grep bswapq %t | count 2 -; RUN: grep bswapl %t | count 1 +; RUN: FileCheck %s < %t +; CHECK: foo: +; CHECK: bswapq define i64 @foo(i64 %x) nounwind { %asmtmp = tail call i64 asm "bswap $0", "=r,0,~{dirflag},~{fpsr},~{flags}"(i64 %x) nounwind ret i64 %asmtmp } + +; CHECK: bar: +; CHECK: bswapq define i64 @bar(i64 %x) nounwind { %asmtmp = tail call i64 asm "bswapq ${0:q}", "=r,0,~{dirflag},~{fpsr},~{flags}"(i64 %x) nounwind ret i64 %asmtmp } + +; CHECK: pen: +; CHECK: bswapl define i32 @pen(i32 %x) nounwind { %asmtmp = tail call i32 asm "bswapl ${0:q}", "=r,0,~{dirflag},~{fpsr},~{flags}"(i32 %x) nounwind ret i32 %asmtmp } + +; CHECK: s16: +; CHECK: rolw $8, +define zeroext i16 @s16(i16 zeroext %x) nounwind { + %asmtmp = tail call i16 asm "rorw $$8, ${0:w}", "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i16 %x) nounwind + ret i16 %asmtmp +} + +; CHECK: t16: +; CHECK: rolw $8, +define zeroext i16 @t16(i16 zeroext %x) nounwind { + %asmtmp = tail call i16 asm "rorw $$8, ${0:w}", "=r,0,~{cc},~{dirflag},~{fpsr},~{flags}"(i16 %x) nounwind + ret i16 %asmtmp +} + +; CHECK: u16: +; CHECK: rolw $8, +define zeroext i16 @u16(i16 zeroext %x) nounwind { + %asmtmp = tail call i16 asm "rolw $$8, ${0:w}", "=r,0,~{dirflag},~{fpsr},~{flags},~{cc}"(i16 %x) nounwind + ret i16 %asmtmp +} + +; CHECK: v16: +; CHECK: rolw $8, +define zeroext i16 @v16(i16 zeroext %x) nounwind { + %asmtmp = tail call i16 asm "rolw $$8, ${0:w}", "=r,0,~{cc},~{dirflag},~{fpsr},~{flags}"(i16 %x) nounwind + ret i16 %asmtmp +} + +; CHECK: s32: +; CHECK: bswapl +define i32 @s32(i32 %x) nounwind { + %asmtmp = tail call i32 asm "bswap $0", "=r,0,~{dirflag},~{fpsr},~{flags}"(i32 %x) nounwind + ret i32 %asmtmp +} + +; CHECK: t32: +; CHECK: bswapl +define i32 @t32(i32 %x) nounwind { + %asmtmp = tail call i32 asm "bswap $0", "=r,0,~{dirflag},~{flags},~{fpsr}"(i32 %x) nounwind + ret i32 %asmtmp +} + +; CHECK: s64: +; CHECK: bswapq +define i64 @s64(i64 %x) nounwind { + %asmtmp = tail call i64 asm "bswap ${0:q}", "=r,0,~{dirflag},~{fpsr},~{flags}"(i64 %x) nounwind + ret i64 %asmtmp +} + +; CHECK: t64: +; CHECK: bswapq +define i64 @t64(i64 %x) nounwind { + %asmtmp = tail call i64 asm "bswap ${0:q}", "=r,0,~{fpsr},~{dirflag},~{flags}"(i64 %x) nounwind + ret i64 %asmtmp +} diff --git a/test/CodeGen/X86/code_placement_eh.ll b/test/CodeGen/X86/code_placement_eh.ll new file mode 100644 index 0000000000..172d5910d0 --- /dev/null +++ b/test/CodeGen/X86/code_placement_eh.ll @@ -0,0 +1,45 @@ +; RUN: llc < %s + +; CodePlacementOpt shouldn't try to modify this loop because +; it involves EH edges. + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" +target triple = "i386-apple-darwin10.0" + +define void @foo() { +invcont5: + br label %bb15 + +.noexc3: ; preds = %bb15 + br i1 undef, label %bb18.i5.i, label %bb15 + +.noexc6.i.i: ; preds = %bb18.i5.i + %tmp2021 = invoke float @cosf(float 0.000000e+00) readonly + to label %bb18.i5.i unwind label %lpad.i.i ; [#uses=0] + +bb18.i5.i: ; preds = %.noexc6.i.i, %bb51.i + %tmp2019 = invoke float @sinf(float 0.000000e+00) readonly + to label %.noexc6.i.i unwind label %lpad.i.i ; [#uses=0] + +lpad.i.i: ; preds = %bb18.i5.i, %.noexc6.i.i + %eh_ptr.i.i = call i8* @llvm.eh.exception() ; [#uses=1] + unreachable + +lpad59.i: ; preds = %bb15 + %eh_ptr60.i = call i8* @llvm.eh.exception() ; [#uses=1] + unreachable + +bb15: ; preds = %.noexc3, %invcont5 + invoke fastcc void @_ZN28btHashedOverlappingPairCacheC2Ev() + to label %.noexc3 unwind label %lpad59.i +} + +declare i8* @llvm.eh.exception() nounwind readonly + +declare i32 @llvm.eh.selector(i8*, i8*, ...) nounwind + +declare float @sinf(float) readonly + +declare float @cosf(float) readonly + +declare fastcc void @_ZN28btHashedOverlappingPairCacheC2Ev() align 2 diff --git a/test/CodeGen/X86/crash.ll b/test/CodeGen/X86/crash.ll new file mode 100644 index 0000000000..1e13046f2a --- /dev/null +++ b/test/CodeGen/X86/crash.ll @@ -0,0 +1,20 @@ +; RUN: llc -march=x86 %s -o - +; RUN: llc -march=x86-64 %s -o - + +; PR6497 + +; Chain and flag folding issues. +define i32 @test1() nounwind ssp { +entry: + %tmp5.i = volatile load i32* undef ; [#uses=1] + %conv.i = zext i32 %tmp5.i to i64 ; [#uses=1] + %tmp12.i = volatile load i32* undef ; [#uses=1] + %conv13.i = zext i32 %tmp12.i to i64 ; [#uses=1] + %shl.i = shl i64 %conv13.i, 32 ; [#uses=1] + %or.i = or i64 %shl.i, %conv.i ; [#uses=1] + %add16.i = add i64 %or.i, 256 ; [#uses=1] + %shr.i = lshr i64 %add16.i, 8 ; [#uses=1] + %conv19.i = trunc i64 %shr.i to i32 ; [#uses=1] + volatile store i32 %conv19.i, i32* undef + ret i32 undef +} diff --git a/test/CodeGen/X86/critical-edge-split.ll b/test/CodeGen/X86/critical-edge-split.ll index 4fe554de75..f29cbf323e 100644 --- a/test/CodeGen/X86/critical-edge-split.ll +++ b/test/CodeGen/X86/critical-edge-split.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin -tailcallopt=false -stats -info-output-file - | grep asm-printer | grep 31 +; RUN: llc < %s -mtriple=i386-apple-darwin -stats -info-output-file - | grep asm-printer | grep 29 %CC = type { %Register } %II = type { %"struct.XX::II::$_74" } diff --git a/test/CodeGen/X86/dllexport.ll b/test/CodeGen/X86/dllexport.ll new file mode 100644 index 0000000000..2c699bfb0d --- /dev/null +++ b/test/CodeGen/X86/dllexport.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s | FileCheck %s +; PR2936 + +target triple = "i386-mingw32" + +define dllexport x86_fastcallcc i32 @foo() nounwind { +entry: + ret i32 0 +} + +; CHECK: .section .drectve +; CHECK: -export:@foo@0 \ No newline at end of file diff --git a/test/CodeGen/X86/fastcall-correct-mangling.ll b/test/CodeGen/X86/fastcall-correct-mangling.ll index 2b48f5f371..33b18bb8cc 100644 --- a/test/CodeGen/X86/fastcall-correct-mangling.ll +++ b/test/CodeGen/X86/fastcall-correct-mangling.ll @@ -1,9 +1,9 @@ -; RUN: llc < %s -mtriple=i386-unknown-mingw32 | \ -; RUN: grep {@12} +; RUN: llc < %s -mtriple=i386-unknown-mingw32 | FileCheck %s ; Check that a fastcall function gets correct mangling define x86_fastcallcc void @func(i64 %X, i8 %Y, i8 %G, i16 %Z) { +; CHECK: @func@20: ret void } diff --git a/test/CodeGen/X86/full-lsr.ll b/test/CodeGen/X86/full-lsr.ll index 3bd58b65be..ff9b1b0b6a 100644 --- a/test/CodeGen/X86/full-lsr.ll +++ b/test/CodeGen/X86/full-lsr.ll @@ -1,12 +1,7 @@ ; RUN: llc < %s -march=x86 >%t -; TODO: Enhance full lsr mode to get this: -; RUNX: grep {addl \\\$4,} %t | count 3 -; RUNX: not grep {,%} %t - -; For now, it should find this, which is still pretty good: -; RUN: not grep {addl \\\$4,} %t -; RUN: grep {,%} %t | count 6 +; RUN: grep {addl \\\$4,} %t | count 3 +; RUN: not grep {,%} %t define void @foo(float* nocapture %A, float* nocapture %B, float* nocapture %C, i32 %N) nounwind { entry: diff --git a/test/CodeGen/X86/global-sections.ll b/test/CodeGen/X86/global-sections.ll index 1a7b5777ae..d79c56bc46 100644 --- a/test/CodeGen/X86/global-sections.ll +++ b/test/CodeGen/X86/global-sections.ll @@ -100,7 +100,7 @@ @G8 = constant [4 x i16] [ i16 1, i16 2, i16 3, i16 0 ] -; DARWIN: .section __TEXT,__ustring +; DARWIN: .section __TEXT,__const ; DARWIN: .globl _G8 ; DARWIN: _G8: @@ -110,7 +110,6 @@ @G9 = constant [4 x i32] [ i32 1, i32 2, i32 3, i32 0 ] -; DARWIN: .section __TEXT,__const ; DARWIN: .globl _G9 ; DARWIN: _G9: diff --git a/test/CodeGen/X86/ins_subreg_coalesce-3.ll b/test/CodeGen/X86/ins_subreg_coalesce-3.ll index 627edc51c1..8c1c409766 100644 --- a/test/CodeGen/X86/ins_subreg_coalesce-3.ll +++ b/test/CodeGen/X86/ins_subreg_coalesce-3.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86-64 | grep mov | count 5 +; RUN: llc < %s -march=x86-64 | grep mov | count 3 %struct.COMPOSITE = type { i8, i16, i16 } %struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 } diff --git a/test/CodeGen/X86/iv-users-in-other-loops.ll b/test/CodeGen/X86/iv-users-in-other-loops.ll index c695c29e06..408fb20b8d 100644 --- a/test/CodeGen/X86/iv-users-in-other-loops.ll +++ b/test/CodeGen/X86/iv-users-in-other-loops.ll @@ -1,11 +1,11 @@ ; RUN: llc < %s -march=x86-64 -o %t -; RUN: grep inc %t | count 1 +; RUN: not grep inc %t ; RUN: grep dec %t | count 2 ; RUN: grep addq %t | count 13 ; RUN: not grep addb %t -; RUN: grep leaq %t | count 9 -; RUN: grep leal %t | count 3 -; RUN: grep movq %t | count 5 +; RUN: not grep leaq %t +; RUN: not grep leal %t +; RUN: not grep movq %t ; IV users in each of the loops from other loops shouldn't cause LSR ; to insert new induction variables. Previously it would create a diff --git a/test/CodeGen/X86/licm-symbol.ll b/test/CodeGen/X86/licm-symbol.ll new file mode 100644 index 0000000000..d61bbfccbc --- /dev/null +++ b/test/CodeGen/X86/licm-symbol.ll @@ -0,0 +1,39 @@ +; RUN: llc < %s | FileCheck %s + +; MachineLICM should be able to hoist the sF reference out of the loop. + +; CHECK: pushl %esi +; CHECK: subl $8, %esp +; CHECK: movl $176, %esi +; CHECK: addl L___sF$non_lazy_ptr, %esi +; CHECK: .align 4, 0x90 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32" +target triple = "i386-apple-darwin8" + +%struct.FILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 } +%struct.__sFILEX = type opaque +%struct.__sbuf = type { i8*, i32 } +%struct.gcov_ctr_summary = type { i32, i32, i64, i64, i64 } +%struct.gcov_summary = type { i32, [1 x %struct.gcov_ctr_summary] } + +@__sF = external global [0 x %struct.FILE] ; <[0 x %struct.FILE]*> [#uses=1] + +declare i32 @fprintf(%struct.FILE* nocapture) nounwind + +define void @gcov_exit() nounwind { +entry: + br label %bb151 + +bb151: ; preds = %bb59, %bb56, %bb14 + br i1 undef, label %bb56, label %bb59 + +bb56: ; preds = %bb151 + %t0 = call i32 (%struct.FILE*)* @fprintf(%struct.FILE* getelementptr inbounds ([0 x %struct.FILE]* @__sF, i32 0, i32 2)) nounwind + br label %bb151 + +bb59: ; preds = %bb151 + %t1 = call i32 (%struct.FILE*)* @fprintf(%struct.FILE* getelementptr inbounds ([0 x %struct.FILE]* @__sF, i32 0, i32 2)) nounwind + br label %bb151 +} + diff --git a/test/CodeGen/X86/loop-strength-reduce-2.ll b/test/CodeGen/X86/loop-strength-reduce-2.ll index 30b5114349..b546462b68 100644 --- a/test/CodeGen/X86/loop-strength-reduce-2.ll +++ b/test/CodeGen/X86/loop-strength-reduce-2.ll @@ -1,11 +1,24 @@ -; RUN: llc < %s -march=x86 -relocation-model=pic | \ -; RUN: grep {, 4} | count 1 -; RUN: llc < %s -march=x86 | not grep lea +; RUN: llc < %s -march=x86 -relocation-model=pic | FileCheck %s -check-prefix=PIC +; RUN: llc < %s -march=x86 -relocation-model=static | FileCheck %s -check-prefix=STATIC ; ; Make sure the common loop invariant A is hoisted up to preheader, ; since too many registers are needed to subsume it into the addressing modes. ; It's safe to sink A in when it's not pic. +; PIC: align +; PIC: movl $4, -4([[REG:%e[a-z]+]]) +; PIC: movl $5, ([[REG]]) +; PIC: addl $4, [[REG]] +; PIC: decl {{%e[[a-z]+}} +; PIC: jne + +; STATIC: align +; STATIC: movl $4, -4(%ecx) +; STATIC: movl $5, (%ecx) +; STATIC: addl $4, %ecx +; STATIC: decl %eax +; STATIC: jne + @A = global [16 x [16 x i32]] zeroinitializer, align 32 ; <[16 x [16 x i32]]*> [#uses=2] define void @test(i32 %row, i32 %N.in) nounwind { diff --git a/test/CodeGen/X86/loop-strength-reduce-3.ll b/test/CodeGen/X86/loop-strength-reduce-3.ll index 70c91340c9..b1c9fb9c07 100644 --- a/test/CodeGen/X86/loop-strength-reduce-3.ll +++ b/test/CodeGen/X86/loop-strength-reduce-3.ll @@ -1,8 +1,11 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin -relocation-model=dynamic-no-pic | \ -; RUN: grep {A+} | count 2 -; -; Make sure the common loop invariant A is not hoisted up to preheader, -; since it can be subsumed it into the addressing modes. +; RUN: llc < %s -mtriple=i386-apple-darwin -relocation-model=dynamic-no-pic | FileCheck %s + +; CHECK: align +; CHECK: movl $4, -4(%ecx) +; CHECK: movl $5, (%ecx) +; CHECK: addl $4, %ecx +; CHECK: decl %eax +; CHECK: jne @A = global [16 x [16 x i32]] zeroinitializer, align 32 ; <[16 x [16 x i32]]*> [#uses=2] diff --git a/test/CodeGen/X86/loop-strength-reduce.ll b/test/CodeGen/X86/loop-strength-reduce.ll index 4cb56ca9ed..42c6ac4983 100644 --- a/test/CodeGen/X86/loop-strength-reduce.ll +++ b/test/CodeGen/X86/loop-strength-reduce.ll @@ -1,8 +1,11 @@ -; RUN: llc < %s -march=x86 -relocation-model=static | \ -; RUN: grep {A+} | count 2 -; -; Make sure the common loop invariant A is not hoisted up to preheader, -; since it can be subsumed into the addressing mode in all uses. +; RUN: llc < %s -march=x86 -relocation-model=static | FileCheck %s + +; CHECK: align +; CHECK: movl $4, -4(%ecx) +; CHECK: movl $5, (%ecx) +; CHECK: addl $4, %ecx +; CHECK: decl %eax +; CHECK: jne @A = internal global [16 x [16 x i32]] zeroinitializer, align 32 ; <[16 x [16 x i32]]*> [#uses=2] diff --git a/test/CodeGen/X86/loop-strength-reduce4.ll b/test/CodeGen/X86/loop-strength-reduce4.ll index 07e46eca75..6c0eb8c0df 100644 --- a/test/CodeGen/X86/loop-strength-reduce4.ll +++ b/test/CodeGen/X86/loop-strength-reduce4.ll @@ -1,5 +1,19 @@ -; RUN: llc < %s -march=x86 | grep cmp | grep 64 -; RUN: llc < %s -march=x86 | not grep inc +; RUN: llc < %s -march=x86 -relocation-model=static -mtriple=i686-apple-darwin | FileCheck %s -check-prefix=STATIC +; RUN: llc < %s -march=x86 -relocation-model=pic | FileCheck %s -check-prefix=PIC + +; By starting the IV at -64 instead of 0, a cmp is eliminated, +; as the flags from the add can be used directly. + +; STATIC: movl $-64, %ecx + +; STATIC: movl %eax, _state+76(%ecx) +; STATIC: addl $16, %ecx +; STATIC: jne + +; In PIC mode the symbol can't be folded, so the change-compare-stride +; trick applies. + +; PIC: cmpl $64 @state = external global [0 x i32] ; <[0 x i32]*> [#uses=4] @S = external global [0 x i32] ; <[0 x i32]*> [#uses=4] diff --git a/test/CodeGen/X86/loop-strength-reduce8.ll b/test/CodeGen/X86/loop-strength-reduce8.ll index e14cd8a99e..6b2247d1d6 100644 --- a/test/CodeGen/X86/loop-strength-reduce8.ll +++ b/test/CodeGen/X86/loop-strength-reduce8.ll @@ -1,4 +1,10 @@ -; RUN: llc < %s -mtriple=i386-apple-darwin | grep leal | not grep 16 +; RUN: llc < %s -mtriple=i386-apple-darwin | FileCheck %s + +; CHECK: leal 16(%eax), %edx +; CHECK: align +; CHECK: addl $4, %edx +; CHECK: decl %ecx +; CHECK: jne LBB1_2 %struct.CUMULATIVE_ARGS = type { i32, i32, i32, i32, i32, i32, i32 } %struct.bitmap_element = type { %struct.bitmap_element*, %struct.bitmap_element*, i32, [2 x i64] } diff --git a/test/CodeGen/X86/lsr-overflow.ll b/test/CodeGen/X86/lsr-overflow.ll new file mode 100644 index 0000000000..0b0214c6d9 --- /dev/null +++ b/test/CodeGen/X86/lsr-overflow.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -march=x86-64 | FileCheck %s + +; The comparison uses the pre-inc value, which could lead LSR to +; try to compute -INT64_MIN. + +; CHECK: movabsq $-9223372036854775808, %rax +; CHECK: cmpq %rax, %rbx +; CHECK: sete %al + +declare i64 @bar() + +define i1 @foo() nounwind { +entry: + br label %for.cond.i + +for.cond.i: + %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %for.cond.i ] + %t = call i64 @bar() + %indvar.next = add i64 %indvar, 1 + %s = icmp ne i64 %indvar.next, %t + br i1 %s, label %for.cond.i, label %__ABContainsLabel.exit + +__ABContainsLabel.exit: + %cmp = icmp eq i64 %indvar, 9223372036854775807 + ret i1 %cmp +} diff --git a/test/CodeGen/X86/lsr-reuse-trunc.ll b/test/CodeGen/X86/lsr-reuse-trunc.ll new file mode 100644 index 0000000000..d1d714491f --- /dev/null +++ b/test/CodeGen/X86/lsr-reuse-trunc.ll @@ -0,0 +1,59 @@ +; RUN: llc < %s -march=x86-64 | FileCheck %s + +; Full strength reduction wouldn't reduce register pressure, so LSR should +; stick with indexing here. + +; CHECK: movaps (%rsi,%rax,4), %xmm3 +; CHECK: movaps %xmm3, (%rdi,%rax,4) +; CHECK: addq $4, %rax +; CHECK: cmpl %eax, (%rdx) +; CHECK-NEXT: jg + +define void @vvfloorf(float* nocapture %y, float* nocapture %x, i32* nocapture %n) nounwind { +entry: + %0 = load i32* %n, align 4 + %1 = icmp sgt i32 %0, 0 + br i1 %1, label %bb, label %return + +bb: + %indvar = phi i64 [ %indvar.next, %bb ], [ 0, %entry ] + %tmp = shl i64 %indvar, 2 + %scevgep = getelementptr float* %y, i64 %tmp + %scevgep9 = bitcast float* %scevgep to <4 x float>* + %scevgep10 = getelementptr float* %x, i64 %tmp + %scevgep1011 = bitcast float* %scevgep10 to <4 x float>* + %2 = load <4 x float>* %scevgep1011, align 16 + %3 = bitcast <4 x float> %2 to <4 x i32> + %4 = and <4 x i32> %3, + %5 = bitcast <4 x i32> %4 to <4 x float> + %6 = and <4 x i32> %3, + %7 = tail call <4 x float> @llvm.x86.sse.cmp.ps(<4 x float> %5, <4 x float> , i8 5) nounwind + %tmp.i4 = bitcast <4 x float> %7 to <4 x i32> + %8 = xor <4 x i32> %tmp.i4, + %9 = and <4 x i32> %8, + %10 = or <4 x i32> %9, %6 + %11 = bitcast <4 x i32> %10 to <4 x float> + %12 = fadd <4 x float> %2, %11 + %13 = fsub <4 x float> %12, %11 + %14 = tail call <4 x float> @llvm.x86.sse.cmp.ps(<4 x float> %2, <4 x float> %13, i8 1) nounwind + %15 = bitcast <4 x float> %14 to <4 x i32> + %16 = tail call <4 x float> @llvm.x86.sse2.cvtdq2ps(<4 x i32> %15) nounwind readnone + %17 = fadd <4 x float> %13, %16 + %tmp.i = bitcast <4 x float> %17 to <4 x i32> + %18 = or <4 x i32> %tmp.i, %6 + %19 = bitcast <4 x i32> %18 to <4 x float> + store <4 x float> %19, <4 x float>* %scevgep9, align 16 + %tmp12 = add i64 %tmp, 4 + %tmp13 = trunc i64 %tmp12 to i32 + %20 = load i32* %n, align 4 + %21 = icmp sgt i32 %20, %tmp13 + %indvar.next = add i64 %indvar, 1 + br i1 %21, label %bb, label %return + +return: + ret void +} + +declare <4 x float> @llvm.x86.sse.cmp.ps(<4 x float>, <4 x float>, i8) nounwind readnone + +declare <4 x float> @llvm.x86.sse2.cvtdq2ps(<4 x i32>) nounwind readnone diff --git a/test/CodeGen/X86/lsr-reuse.ll b/test/CodeGen/X86/lsr-reuse.ll new file mode 100644 index 0000000000..2f6fb3fa8b --- /dev/null +++ b/test/CodeGen/X86/lsr-reuse.ll @@ -0,0 +1,442 @@ +; RUN: llc < %s -march=x86-64 -O3 -asm-verbose=false | FileCheck %s +target datalayout = "e-p:64:64:64" +target triple = "x86_64-unknown-unknown" + +; Full strength reduction reduces register pressure from 5 to 4 here. +; Instruction selection should use the FLAGS value from the dec for +; the branch. Scheduling should push the adds upwards. + +; CHECK: full_me_0: +; CHECK: movsd (%rsi), %xmm0 +; CHECK: addq $8, %rsi +; CHECK: mulsd (%rdx), %xmm0 +; CHECK: addq $8, %rdx +; CHECK: movsd %xmm0, (%rdi) +; CHECK: addq $8, %rdi +; CHECK: decq %rcx +; CHECK: jne + +define void @full_me_0(double* nocapture %A, double* nocapture %B, double* nocapture %C, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %Ai = getelementptr inbounds double* %A, i64 %i + %Bi = getelementptr inbounds double* %B, i64 %i + %Ci = getelementptr inbounds double* %C, i64 %i + %t1 = load double* %Bi + %t2 = load double* %Ci + %m = fmul double %t1, %t2 + store double %m, double* %Ai + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %loop + +return: + ret void +} + +; Mostly-full strength reduction means we do full strength reduction on all +; except for the offsets. +; +; Given a choice between constant offsets -2048 and 2048, choose the negative +; value, because at boundary conditions it has a smaller encoding. +; TODO: That's an over-general heuristic. It would be better for the target +; to indicate what the encoding cost would be. Then using a 2048 offset +; would be better on x86-64, since the start value would be 0 instead of +; 2048. + +; CHECK: mostly_full_me_0: +; CHECK: movsd -2048(%rsi), %xmm0 +; CHECK: mulsd -2048(%rdx), %xmm0 +; CHECK: movsd %xmm0, -2048(%rdi) +; CHECK: movsd (%rsi), %xmm0 +; CHECK: addq $8, %rsi +; CHECK: divsd (%rdx), %xmm0 +; CHECK: addq $8, %rdx +; CHECK: movsd %xmm0, (%rdi) +; CHECK: addq $8, %rdi +; CHECK: decq %rcx +; CHECK: jne + +define void @mostly_full_me_0(double* nocapture %A, double* nocapture %B, double* nocapture %C, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %Ai = getelementptr inbounds double* %A, i64 %i + %Bi = getelementptr inbounds double* %B, i64 %i + %Ci = getelementptr inbounds double* %C, i64 %i + %t1 = load double* %Bi + %t2 = load double* %Ci + %m = fmul double %t1, %t2 + store double %m, double* %Ai + %j = add i64 %i, 256 + %Aj = getelementptr inbounds double* %A, i64 %j + %Bj = getelementptr inbounds double* %B, i64 %j + %Cj = getelementptr inbounds double* %C, i64 %j + %t3 = load double* %Bj + %t4 = load double* %Cj + %o = fdiv double %t3, %t4 + store double %o, double* %Aj + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %loop + +return: + ret void +} + +; A minor variation on mostly_full_me_0. +; Prefer to start the indvar at 0. + +; CHECK: mostly_full_me_1: +; CHECK: movsd (%rsi), %xmm0 +; CHECK: mulsd (%rdx), %xmm0 +; CHECK: movsd %xmm0, (%rdi) +; CHECK: movsd -2048(%rsi), %xmm0 +; CHECK: addq $8, %rsi +; CHECK: divsd -2048(%rdx), %xmm0 +; CHECK: addq $8, %rdx +; CHECK: movsd %xmm0, -2048(%rdi) +; CHECK: addq $8, %rdi +; CHECK: decq %rcx +; CHECK: jne + +define void @mostly_full_me_1(double* nocapture %A, double* nocapture %B, double* nocapture %C, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %Ai = getelementptr inbounds double* %A, i64 %i + %Bi = getelementptr inbounds double* %B, i64 %i + %Ci = getelementptr inbounds double* %C, i64 %i + %t1 = load double* %Bi + %t2 = load double* %Ci + %m = fmul double %t1, %t2 + store double %m, double* %Ai + %j = sub i64 %i, 256 + %Aj = getelementptr inbounds double* %A, i64 %j + %Bj = getelementptr inbounds double* %B, i64 %j + %Cj = getelementptr inbounds double* %C, i64 %j + %t3 = load double* %Bj + %t4 = load double* %Cj + %o = fdiv double %t3, %t4 + store double %o, double* %Aj + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %loop + +return: + ret void +} + +; A slightly less minor variation on mostly_full_me_0. + +; CHECK: mostly_full_me_2: +; CHECK: movsd (%rsi), %xmm0 +; CHECK: mulsd (%rdx), %xmm0 +; CHECK: movsd %xmm0, (%rdi) +; CHECK: movsd -4096(%rsi), %xmm0 +; CHECK: addq $8, %rsi +; CHECK: divsd -4096(%rdx), %xmm0 +; CHECK: addq $8, %rdx +; CHECK: movsd %xmm0, -4096(%rdi) +; CHECK: addq $8, %rdi +; CHECK: decq %rcx +; CHECK: jne + +define void @mostly_full_me_2(double* nocapture %A, double* nocapture %B, double* nocapture %C, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %k = add i64 %i, 256 + %Ak = getelementptr inbounds double* %A, i64 %k + %Bk = getelementptr inbounds double* %B, i64 %k + %Ck = getelementptr inbounds double* %C, i64 %k + %t1 = load double* %Bk + %t2 = load double* %Ck + %m = fmul double %t1, %t2 + store double %m, double* %Ak + %j = sub i64 %i, 256 + %Aj = getelementptr inbounds double* %A, i64 %j + %Bj = getelementptr inbounds double* %B, i64 %j + %Cj = getelementptr inbounds double* %C, i64 %j + %t3 = load double* %Bj + %t4 = load double* %Cj + %o = fdiv double %t3, %t4 + store double %o, double* %Aj + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %loop + +return: + ret void +} + +; In this test, the counting IV exit value is used, so full strength reduction +; would not reduce register pressure. IndVarSimplify ought to simplify such +; cases away, but it's useful here to verify that LSR's register pressure +; heuristics are working as expected. + +; CHECK: count_me_0: +; CHECK: movsd (%rsi,%rax,8), %xmm0 +; CHECK: mulsd (%rdx,%rax,8), %xmm0 +; CHECK: movsd %xmm0, (%rdi,%rax,8) +; CHECK: incq %rax +; CHECK: cmpq %rax, %rcx +; CHECK: jne + +define i64 @count_me_0(double* nocapture %A, double* nocapture %B, double* nocapture %C, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %Ai = getelementptr inbounds double* %A, i64 %i + %Bi = getelementptr inbounds double* %B, i64 %i + %Ci = getelementptr inbounds double* %C, i64 %i + %t1 = load double* %Bi + %t2 = load double* %Ci + %m = fmul double %t1, %t2 + store double %m, double* %Ai + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %loop + +return: + %q = phi i64 [ 0, %entry ], [ %i.next, %loop ] + ret i64 %q +} + +; In this test, the trip count value is used, so full strength reduction +; would not reduce register pressure. +; (though it would reduce register pressure inside the loop...) + +; CHECK: count_me_1: +; CHECK: movsd (%rsi,%rax,8), %xmm0 +; CHECK: mulsd (%rdx,%rax,8), %xmm0 +; CHECK: movsd %xmm0, (%rdi,%rax,8) +; CHECK: incq %rax +; CHECK: cmpq %rax, %rcx +; CHECK: jne + +define i64 @count_me_1(double* nocapture %A, double* nocapture %B, double* nocapture %C, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + %Ai = getelementptr inbounds double* %A, i64 %i + %Bi = getelementptr inbounds double* %B, i64 %i + %Ci = getelementptr inbounds double* %C, i64 %i + %t1 = load double* %Bi + %t2 = load double* %Ci + %m = fmul double %t1, %t2 + store double %m, double* %Ai + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %loop + +return: + %q = phi i64 [ 0, %entry ], [ %n, %loop ] + ret i64 %q +} + +; Full strength reduction doesn't save any registers here because the +; loop tripcount is a constant. + +; CHECK: count_me_2: +; CHECK: movl $10, %eax +; CHECK: align +; CHECK: BB7_1: +; CHECK: movsd -40(%rdi,%rax,8), %xmm0 +; CHECK: addsd -40(%rsi,%rax,8), %xmm0 +; CHECK: movsd %xmm0, -40(%rdx,%rax,8) +; CHECK: movsd (%rdi,%rax,8), %xmm0 +; CHECK: subsd (%rsi,%rax,8), %xmm0 +; CHECK: movsd %xmm0, (%rdx,%rax,8) +; CHECK: incq %rax +; CHECK: cmpq $5010, %rax +; CHECK: jne + +define void @count_me_2(double* nocapture %A, double* nocapture %B, double* nocapture %C) nounwind { +entry: + br label %loop + +loop: + %i = phi i64 [ 0, %entry ], [ %i.next, %loop ] + %i5 = add i64 %i, 5 + %Ai = getelementptr double* %A, i64 %i5 + %t2 = load double* %Ai + %Bi = getelementptr double* %B, i64 %i5 + %t4 = load double* %Bi + %t5 = fadd double %t2, %t4 + %Ci = getelementptr double* %C, i64 %i5 + store double %t5, double* %Ci + %i10 = add i64 %i, 10 + %Ai10 = getelementptr double* %A, i64 %i10 + %t9 = load double* %Ai10 + %Bi10 = getelementptr double* %B, i64 %i10 + %t11 = load double* %Bi10 + %t12 = fsub double %t9, %t11 + %Ci10 = getelementptr double* %C, i64 %i10 + store double %t12, double* %Ci10 + %i.next = add i64 %i, 1 + %exitcond = icmp eq i64 %i.next, 5000 + br i1 %exitcond, label %return, label %loop + +return: + ret void +} + +; This should be fully strength-reduced to reduce register pressure. + +; CHECK: full_me_1: +; CHECK: align +; CHECK: BB8_1: +; CHECK: movsd (%rdi), %xmm0 +; CHECK: addsd (%rsi), %xmm0 +; CHECK: movsd %xmm0, (%rdx) +; CHECK: movsd 40(%rdi), %xmm0 +; CHECK: addq $8, %rdi +; CHECK: subsd 40(%rsi), %xmm0 +; CHECK: addq $8, %rsi +; CHECK: movsd %xmm0, 40(%rdx) +; CHECK: addq $8, %rdx +; CHECK: decq %rcx +; CHECK: jne + +define void @full_me_1(double* nocapture %A, double* nocapture %B, double* nocapture %C, i64 %n) nounwind { +entry: + br label %loop + +loop: + %i = phi i64 [ 0, %entry ], [ %i.next, %loop ] + %i5 = add i64 %i, 5 + %Ai = getelementptr double* %A, i64 %i5 + %t2 = load double* %Ai + %Bi = getelementptr double* %B, i64 %i5 + %t4 = load double* %Bi + %t5 = fadd double %t2, %t4 + %Ci = getelementptr double* %C, i64 %i5 + store double %t5, double* %Ci + %i10 = add i64 %i, 10 + %Ai10 = getelementptr double* %A, i64 %i10 + %t9 = load double* %Ai10 + %Bi10 = getelementptr double* %B, i64 %i10 + %t11 = load double* %Bi10 + %t12 = fsub double %t9, %t11 + %Ci10 = getelementptr double* %C, i64 %i10 + store double %t12, double* %Ci10 + %i.next = add i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %loop + +return: + ret void +} + +; This is a variation on full_me_0 in which the 0,+,1 induction variable +; has a non-address use, pinning that value in a register. + +; CHECK: count_me_3: +; CHECK: call +; CHECK: movsd (%r15,%r13,8), %xmm0 +; CHECK: mulsd (%r14,%r13,8), %xmm0 +; CHECK: movsd %xmm0, (%r12,%r13,8) +; CHECK: incq %r13 +; CHECK: cmpq %r13, %rbx +; CHECK: jne + +declare void @use(i64) + +define void @count_me_3(double* nocapture %A, double* nocapture %B, double* nocapture %C, i64 %n) nounwind { +entry: + %t0 = icmp sgt i64 %n, 0 + br i1 %t0, label %loop, label %return + +loop: + %i = phi i64 [ %i.next, %loop ], [ 0, %entry ] + call void @use(i64 %i) + %Ai = getelementptr inbounds double* %A, i64 %i + %Bi = getelementptr inbounds double* %B, i64 %i + %Ci = getelementptr inbounds double* %C, i64 %i + %t1 = load double* %Bi + %t2 = load double* %Ci + %m = fmul double %t1, %t2 + store double %m, double* %Ai + %i.next = add nsw i64 %i, 1 + %exitcond = icmp eq i64 %i.next, %n + br i1 %exitcond, label %return, label %loop + +return: + ret void +} + +; LSR should use only one indvar for the inner loop. +; rdar://7657764 + +; CHECK: asd: +; CHECK: BB10_5: +; CHECK-NEXT: addl (%r{{[^,]*}},%rdi,4), %e +; CHECK-NEXT: incq %rdi +; CHECK-NEXT: cmpq %rdi, %r{{[^,]*}} +; CHECK-NEXT: jg + +%struct.anon = type { i32, [4200 x i32] } + +@bars = common global [123123 x %struct.anon] zeroinitializer, align 32 ; <[123123 x %struct.anon]*> [#uses=2] + +define i32 @asd(i32 %n) nounwind readonly { +entry: + %0 = icmp sgt i32 %n, 0 ; [#uses=1] + br i1 %0, label %bb.nph14, label %bb5 + +bb.nph14: ; preds = %entry + %tmp18 = zext i32 %n to i64 ; [#uses=1] + br label %bb + +bb: ; preds = %bb3, %bb.nph14 + %indvar16 = phi i64 [ 0, %bb.nph14 ], [ %indvar.next17, %bb3 ] ; [#uses=3] + %s.113 = phi i32 [ 0, %bb.nph14 ], [ %s.0.lcssa, %bb3 ] ; [#uses=2] + %scevgep2526 = getelementptr [123123 x %struct.anon]* @bars, i64 0, i64 %indvar16, i32 0 ; [#uses=1] + %1 = load i32* %scevgep2526, align 4 ; [#uses=2] + %2 = icmp sgt i32 %1, 0 ; [#uses=1] + br i1 %2, label %bb.nph, label %bb3 + +bb.nph: ; preds = %bb + %tmp23 = sext i32 %1 to i64 ; [#uses=1] + br label %bb1 + +bb1: ; preds = %bb.nph, %bb1 + %indvar = phi i64 [ 0, %bb.nph ], [ %tmp19, %bb1 ] ; [#uses=2] + %s.07 = phi i32 [ %s.113, %bb.nph ], [ %4, %bb1 ] ; [#uses=1] + %c.08 = getelementptr [123123 x %struct.anon]* @bars, i64 0, i64 %indvar16, i32 1, i64 %indvar ; [#uses=1] + %3 = load i32* %c.08, align 4 ; [#uses=1] + %4 = add nsw i32 %3, %s.07 ; [#uses=2] + %tmp19 = add i64 %indvar, 1 ; [#uses=2] + %5 = icmp sgt i64 %tmp23, %tmp19 ; [#uses=1] + br i1 %5, label %bb1, label %bb3 + +bb3: ; preds = %bb1, %bb + %s.0.lcssa = phi i32 [ %s.113, %bb ], [ %4, %bb1 ] ; [#uses=2] + %indvar.next17 = add i64 %indvar16, 1 ; [#uses=2] + %exitcond = icmp eq i64 %indvar.next17, %tmp18 ; [#uses=1] + br i1 %exitcond, label %bb5, label %bb + +bb5: ; preds = %bb3, %entry + %s.1.lcssa = phi i32 [ 0, %entry ], [ %s.0.lcssa, %bb3 ] ; [#uses=1] + ret i32 %s.1.lcssa +} diff --git a/test/CodeGen/X86/lsr-wrap.ll b/test/CodeGen/X86/lsr-wrap.ll new file mode 100644 index 0000000000..ec8db501ef --- /dev/null +++ b/test/CodeGen/X86/lsr-wrap.ll @@ -0,0 +1,37 @@ +; RUN: llc -march=x86-64 < %s | FileCheck %s + +; LSR would like to use a single IV for both of these, however it's +; not safe due to wraparound. + +; CHECK: addb $-4, %r +; CHECK: decw % + +@g_19 = common global i32 0 ; [#uses=2] + +declare i32 @func_8(i8 zeroext) nounwind + +declare i32 @func_3(i8 signext) nounwind + +define void @func_1() nounwind { +entry: + br label %bb + +bb: ; preds = %bb, %entry + %indvar = phi i16 [ 0, %entry ], [ %indvar.next, %bb ] ; [#uses=2] + %tmp = sub i16 0, %indvar ; [#uses=1] + %tmp27 = trunc i16 %tmp to i8 ; [#uses=1] + %tmp1 = load i32* @g_19, align 4 ; [#uses=2] + %tmp2 = add i32 %tmp1, 1 ; [#uses=1] + store i32 %tmp2, i32* @g_19, align 4 + %tmp3 = trunc i32 %tmp1 to i8 ; [#uses=1] + %tmp4 = tail call i32 @func_8(i8 zeroext %tmp3) nounwind ; [#uses=0] + %tmp5 = shl i8 %tmp27, 2 ; [#uses=1] + %tmp6 = add i8 %tmp5, -112 ; [#uses=1] + %tmp7 = tail call i32 @func_3(i8 signext %tmp6) nounwind ; [#uses=0] + %indvar.next = add i16 %indvar, 1 ; [#uses=2] + %exitcond = icmp eq i16 %indvar.next, -28 ; [#uses=1] + br i1 %exitcond, label %return, label %bb + +return: ; preds = %bb + ret void +} diff --git a/test/CodeGen/X86/masked-iv-safe.ll b/test/CodeGen/X86/masked-iv-safe.ll index bc493bd8f7..0b4d73a683 100644 --- a/test/CodeGen/X86/masked-iv-safe.ll +++ b/test/CodeGen/X86/masked-iv-safe.ll @@ -169,7 +169,7 @@ loop: %indvar.i24 = and i64 %indvar, 16777215 %t3 = getelementptr double* %d, i64 %indvar.i24 %t4 = load double* %t3 - %t5 = fmul double %t4, 2.3 + %t5 = fdiv double %t4, 2.3 store double %t5, double* %t3 %t6 = getelementptr double* %d, i64 %indvar %t7 = load double* %t6 @@ -199,7 +199,7 @@ loop: %indvar.i24 = ashr i64 %s1, 24 %t3 = getelementptr double* %d, i64 %indvar.i24 %t4 = load double* %t3 - %t5 = fmul double %t4, 2.3 + %t5 = fdiv double %t4, 2.3 store double %t5, double* %t3 %t6 = getelementptr double* %d, i64 %indvar %t7 = load double* %t6 @@ -229,7 +229,7 @@ loop: %indvar.i24 = ashr i64 %s1, 24 %t3 = getelementptr double* %d, i64 %indvar.i24 %t4 = load double* %t3 - %t5 = fmul double %t4, 2.3 + %t5 = fdiv double %t4, 2.3 store double %t5, double* %t3 %t6 = getelementptr double* %d, i64 %indvar %t7 = load double* %t6 diff --git a/test/CodeGen/X86/omit-label.ll b/test/CodeGen/X86/omit-label.ll deleted file mode 100644 index 0ec03ebace..0000000000 --- a/test/CodeGen/X86/omit-label.ll +++ /dev/null @@ -1,57 +0,0 @@ -; RUN: llc < %s -asm-verbose=false -mtriple=x86_64-linux-gnu | FileCheck %s -; PR4126 -; PR4732 - -; Don't omit these labels' definitions. - -; CHECK: bux: -; CHECK: LBB1_1: - -define void @bux(i32 %p_53) nounwind optsize { -entry: - %0 = icmp eq i32 %p_53, 0 ; [#uses=1] - %1 = icmp sgt i32 %p_53, 0 ; [#uses=1] - %or.cond = and i1 %0, %1 ; [#uses=1] - br i1 %or.cond, label %bb.i, label %bb3 - -bb.i: ; preds = %entry - %2 = add i32 %p_53, 1 ; [#uses=1] - %3 = icmp slt i32 %2, 0 ; [#uses=0] - br label %bb3 - -bb3: ; preds = %bb.i, %entry - %4 = tail call i32 (...)* @baz(i32 0) nounwind ; [#uses=0] - ret void -} - -declare i32 @baz(...) - -; Don't omit this label in the assembly output. -; CHECK: int321: -; CHECK: LBB2_1 -; CHECK: LBB2_1 -; CHECK: LBB2_1: - -define void @int321(i8 signext %p_103, i32 %uint8p_104) nounwind readnone { -entry: - %tobool = icmp eq i8 %p_103, 0 ; [#uses=1] - %cmp.i = icmp sgt i8 %p_103, 0 ; [#uses=1] - %or.cond = and i1 %tobool, %cmp.i ; [#uses=1] - br i1 %or.cond, label %land.end.i, label %for.cond.preheader - -land.end.i: ; preds = %entry - %conv3.i = sext i8 %p_103 to i32 ; [#uses=1] - %div.i = sdiv i32 1, %conv3.i ; [#uses=1] - %tobool.i = icmp eq i32 %div.i, -2147483647 ; [#uses=0] - br label %for.cond.preheader - -for.cond.preheader: ; preds = %land.end.i, %entry - %cmp = icmp sgt i8 %p_103, 1 ; [#uses=1] - br i1 %cmp, label %for.end.split, label %for.cond - -for.cond: ; preds = %for.cond.preheader, %for.cond - br label %for.cond - -for.end.split: ; preds = %for.cond.preheader - ret void -} diff --git a/test/CodeGen/X86/pr1505b.ll b/test/CodeGen/X86/pr1505b.ll index 12736cda4c..6a08dae51f 100644 --- a/test/CodeGen/X86/pr1505b.ll +++ b/test/CodeGen/X86/pr1505b.ll @@ -1,5 +1,5 @@ -; RUN: llc < %s -mcpu=i486 | grep fstpl | count 4 -; RUN: llc < %s -mcpu=i486 | grep fstps | count 3 +; RUN: llc < %s -mcpu=i486 | grep fstpl | count 5 +; RUN: llc < %s -mcpu=i486 | grep fstps | count 2 ; PR1505 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64" diff --git a/test/CodeGen/X86/pr3495-2.ll b/test/CodeGen/X86/pr3495-2.ll index 71aa5a0488..98c064a07d 100644 --- a/test/CodeGen/X86/pr3495-2.ll +++ b/test/CodeGen/X86/pr3495-2.ll @@ -1,4 +1,8 @@ -; RUN: llc < %s -march=x86 -relocation-model=pic -disable-fp-elim -stats |& grep {Number of reloads omited} +; RUN: llc < %s -march=x86 -relocation-model=pic -disable-fp-elim -stats |& grep {Number of loads added} | grep 1 +; PR3495 +; +; This test may not be testing what it was supposed to test. +; It used to have two spills and four reloads, but not it only has one spill and one reload. target datalayout = "e-p:32:32:32" target triple = "i386-apple-darwin9.6" diff --git a/test/CodeGen/X86/pr3495.ll b/test/CodeGen/X86/pr3495.ll index 1795970d35..e84a84f59b 100644 --- a/test/CodeGen/X86/pr3495.ll +++ b/test/CodeGen/X86/pr3495.ll @@ -1,8 +1,7 @@ ; RUN: llc < %s -march=x86 -stats |& grep {Number of loads added} | grep 2 ; RUN: llc < %s -march=x86 -stats |& grep {Number of register spills} | grep 1 -; RUN: llc < %s -march=x86 -stats |& grep {Number of machine instrs printed} | grep 38 +; RUN: llc < %s -march=x86 -stats |& grep {Number of machine instrs printed} | grep 34 ; PR3495 -; The loop reversal kicks in once here, resulting in one fewer instruction. target triple = "i386-pc-linux-gnu" @x = external global [8 x i32], align 32 ; <[8 x i32]*> [#uses=1] diff --git a/test/CodeGen/X86/pre-split8.ll b/test/CodeGen/X86/pre-split8.ll index ea4b9496b3..0684bd036c 100644 --- a/test/CodeGen/X86/pre-split8.ll +++ b/test/CodeGen/X86/pre-split8.ll @@ -20,7 +20,7 @@ bb: ; preds = %bb9.i, %entry bb9.i: ; preds = %bb %2 = fsub double %.rle4, %0 ; [#uses=0] - %3 = tail call double @asin(double 0.000000e+00) nounwind readonly ; [#uses=0] + %3 = tail call double @asin(double %.rle4) nounwind readonly ; [#uses=0] %4 = fmul double 0.000000e+00, %0 ; [#uses=1] %5 = tail call double @tan(double 0.000000e+00) nounwind readonly ; [#uses=0] %6 = fmul double %4, 0.000000e+00 ; [#uses=1] diff --git a/test/CodeGen/X86/pre-split9.ll b/test/CodeGen/X86/pre-split9.ll index c27d925d43..86dda33533 100644 --- a/test/CodeGen/X86/pre-split9.ll +++ b/test/CodeGen/X86/pre-split9.ll @@ -22,7 +22,7 @@ bb: ; preds = %bb9.i, %entry bb9.i: ; preds = %bb %2 = fsub double %.rle4, %0 ; [#uses=0] - %3 = tail call double @asin(double 0.000000e+00) nounwind readonly ; [#uses=0] + %3 = tail call double @asin(double %.rle4) nounwind readonly ; [#uses=0] %4 = tail call double @sin(double 0.000000e+00) nounwind readonly ; [#uses=1] %5 = fmul double %4, %0 ; [#uses=1] %6 = tail call double @tan(double 0.000000e+00) nounwind readonly ; [#uses=0] diff --git a/test/CodeGen/X86/ptrtoint-constexpr.ll b/test/CodeGen/X86/ptrtoint-constexpr.ll index dd9790568a..d1cb34bec8 100644 --- a/test/CodeGen/X86/ptrtoint-constexpr.ll +++ b/test/CodeGen/X86/ptrtoint-constexpr.ll @@ -9,6 +9,6 @@ ; CHECK: .globl x ; CHECK: x: -; CHECK: .quad 3 +; CHECK: .quad ((0+1)&4294967295)*3 @x = global i64 mul (i64 3, i64 ptrtoint (i2* getelementptr (i2* null, i64 1) to i64)) diff --git a/test/CodeGen/X86/scalar_widen_div.ll b/test/CodeGen/X86/scalar_widen_div.ll index fc67e4417c..77f320f105 100644 --- a/test/CodeGen/X86/scalar_widen_div.ll +++ b/test/CodeGen/X86/scalar_widen_div.ll @@ -152,3 +152,32 @@ define <5 x i64> @test_ulong_rem(<5 x i64> %num, <5 x i64> %rem) { %rem.r = urem <5 x i64> %num, %rem ret <5 x i64> %rem.r } + +define void @test_int_div(<3 x i32>* %dest, <3 x i32>* %old, i32 %n) { +; CHECK: idivl +; CHECK: idivl +; CHECK: idivl +; CHECK-NOT: idivl +; CHECK: ret +entry: + %cmp13 = icmp sgt i32 %n, 0 + br i1 %cmp13, label %bb.nph, label %for.end + +bb.nph: + br label %for.body + +for.body: + %i.014 = phi i32 [ 0, %bb.nph ], [ %inc, %for.body ] + %arrayidx11 = getelementptr <3 x i32>* %dest, i32 %i.014 + %tmp4 = load <3 x i32>* %arrayidx11 ; <<3 x i32>> [#uses=1] + %arrayidx7 = getelementptr inbounds <3 x i32>* %old, i32 %i.014 + %tmp8 = load <3 x i32>* %arrayidx7 ; <<3 x i32>> [#uses=1] + %div = sdiv <3 x i32> %tmp4, %tmp8 + store <3 x i32> %div, <3 x i32>* %arrayidx11 + %inc = add nsw i32 %i.014, 1 + %exitcond = icmp eq i32 %inc, %n + br i1 %exitcond, label %for.end, label %for.body + +for.end: ; preds = %for.body, %entry + ret void +} diff --git a/test/CodeGen/X86/sse-minmax.ll b/test/CodeGen/X86/sse-minmax.ll index 17ffb5e464..19fbed015b 100644 --- a/test/CodeGen/X86/sse-minmax.ll +++ b/test/CodeGen/X86/sse-minmax.ll @@ -1,17 +1,26 @@ ; RUN: llc < %s -march=x86-64 -asm-verbose=false | FileCheck %s +; RUN: llc < %s -march=x86-64 -asm-verbose=false -enable-unsafe-fp-math | FileCheck -check-prefix=UNSAFE %s +; RUN: llc < %s -march=x86-64 -asm-verbose=false -enable-finite-only-fp-math | FileCheck -check-prefix=FINITE %s ; Some of these patterns can be matched as SSE min or max. Some of ; then can be matched provided that the operands are swapped. ; Some of them can't be matched at all and require a comparison ; and a conditional branch. -; The naming convention is {,x_}{o,u}{gt,lt,ge,le}{,_inverse} +; The naming convention is {,x_,y_}{o,u}{gt,lt,ge,le}{,_inverse} ; x_ : use 0.0 instead of %y +; y_ : use -0.0 instead of %y ; _inverse : swap the arms of the select. ; CHECK: ogt: ; CHECK-NEXT: maxsd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: ogt: +; UNSAFE-NEXT: maxsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ogt: +; FINITE-NEXT: maxsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ogt(double %x, double %y) nounwind { %c = fcmp ogt double %x, %y %d = select i1 %c, double %x, double %y @@ -21,6 +30,12 @@ define double @ogt(double %x, double %y) nounwind { ; CHECK: olt: ; CHECK-NEXT: minsd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: olt: +; UNSAFE-NEXT: minsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: olt: +; FINITE-NEXT: minsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @olt(double %x, double %y) nounwind { %c = fcmp olt double %x, %y %d = select i1 %c, double %x, double %y @@ -31,6 +46,14 @@ define double @olt(double %x, double %y) nounwind { ; CHECK-NEXT: minsd %xmm0, %xmm1 ; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: ogt_inverse: +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ogt_inverse: +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ogt_inverse(double %x, double %y) nounwind { %c = fcmp ogt double %x, %y %d = select i1 %c, double %y, double %x @@ -41,6 +64,14 @@ define double @ogt_inverse(double %x, double %y) nounwind { ; CHECK-NEXT: maxsd %xmm0, %xmm1 ; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: olt_inverse: +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: olt_inverse: +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @olt_inverse(double %x, double %y) nounwind { %c = fcmp olt double %x, %y %d = select i1 %c, double %y, double %x @@ -49,6 +80,12 @@ define double @olt_inverse(double %x, double %y) nounwind { ; CHECK: oge: ; CHECK-NEXT: ucomisd %xmm1, %xmm0 +; UNSAFE: oge: +; UNSAFE-NEXT: maxsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: oge: +; FINITE-NEXT: maxsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @oge(double %x, double %y) nounwind { %c = fcmp oge double %x, %y %d = select i1 %c, double %x, double %y @@ -57,6 +94,10 @@ define double @oge(double %x, double %y) nounwind { ; CHECK: ole: ; CHECK-NEXT: ucomisd %xmm0, %xmm1 +; UNSAFE: ole: +; UNSAFE-NEXT: minsd %xmm1, %xmm0 +; FINITE: ole: +; FINITE-NEXT: minsd %xmm1, %xmm0 define double @ole(double %x, double %y) nounwind { %c = fcmp ole double %x, %y %d = select i1 %c, double %x, double %y @@ -65,6 +106,14 @@ define double @ole(double %x, double %y) nounwind { ; CHECK: oge_inverse: ; CHECK-NEXT: ucomisd %xmm1, %xmm0 +; UNSAFE: oge_inverse: +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: oge_inverse: +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @oge_inverse(double %x, double %y) nounwind { %c = fcmp oge double %x, %y %d = select i1 %c, double %y, double %x @@ -73,6 +122,14 @@ define double @oge_inverse(double %x, double %y) nounwind { ; CHECK: ole_inverse: ; CHECK-NEXT: ucomisd %xmm0, %xmm1 +; UNSAFE: ole_inverse: +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ole_inverse: +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ole_inverse(double %x, double %y) nounwind { %c = fcmp ole double %x, %y %d = select i1 %c, double %y, double %x @@ -83,6 +140,14 @@ define double @ole_inverse(double %x, double %y) nounwind { ; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: maxsd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: x_ogt: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: maxsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ogt: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: maxsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ogt(double %x) nounwind { %c = fcmp ogt double %x, 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00 @@ -93,6 +158,14 @@ define double @x_ogt(double %x) nounwind { ; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: minsd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: x_olt: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: minsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_olt: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: minsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_olt(double %x) nounwind { %c = fcmp olt double %x, 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00 @@ -104,6 +177,16 @@ define double @x_olt(double %x) nounwind { ; CHECK-NEXT: minsd %xmm0, %xmm1 ; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: x_ogt_inverse: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ogt_inverse: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ogt_inverse(double %x) nounwind { %c = fcmp ogt double %x, 0.000000e+00 %d = select i1 %c, double 0.000000e+00, double %x @@ -115,6 +198,16 @@ define double @x_ogt_inverse(double %x) nounwind { ; CHECK-NEXT: maxsd %xmm0, %xmm1 ; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: x_olt_inverse: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_olt_inverse: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_olt_inverse(double %x) nounwind { %c = fcmp olt double %x, 0.000000e+00 %d = select i1 %c, double 0.000000e+00, double %x @@ -122,9 +215,15 @@ define double @x_olt_inverse(double %x) nounwind { } ; CHECK: x_oge: -; CHECK-NEXT: pxor %xmm1, %xmm1 -; CHECK-NEXT: maxsd %xmm1, %xmm0 -; CHECK-NEXT: ret +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: x_oge: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: maxsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_oge: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: maxsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_oge(double %x) nounwind { %c = fcmp oge double %x, 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00 @@ -132,9 +231,15 @@ define double @x_oge(double %x) nounwind { } ; CHECK: x_ole: -; CHECK-NEXT: pxor %xmm1, %xmm1 -; CHECK-NEXT: minsd %xmm1, %xmm0 -; CHECK-NEXT: ret +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: x_ole: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: minsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ole: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: minsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ole(double %x) nounwind { %c = fcmp ole double %x, 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00 @@ -142,10 +247,17 @@ define double @x_ole(double %x) nounwind { } ; CHECK: x_oge_inverse: -; CHECK-NEXT: pxor %xmm1, %xmm1 -; CHECK-NEXT: minsd %xmm0, %xmm1 -; CHECK-NEXT: movapd %xmm1, %xmm0 -; CHECK-NEXT: ret +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: x_oge_inverse: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_oge_inverse: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_oge_inverse(double %x) nounwind { %c = fcmp oge double %x, 0.000000e+00 %d = select i1 %c, double 0.000000e+00, double %x @@ -153,10 +265,17 @@ define double @x_oge_inverse(double %x) nounwind { } ; CHECK: x_ole_inverse: -; CHECK-NEXT: pxor %xmm1, %xmm1 -; CHECK-NEXT: maxsd %xmm0, %xmm1 -; CHECK-NEXT: movapd %xmm1, %xmm0 -; CHECK-NEXT: ret +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: x_ole_inverse: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ole_inverse: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ole_inverse(double %x) nounwind { %c = fcmp ole double %x, 0.000000e+00 %d = select i1 %c, double 0.000000e+00, double %x @@ -164,7 +283,13 @@ define double @x_ole_inverse(double %x) nounwind { } ; CHECK: ugt: -; CHECK-NEXT: ucomisd %xmm0, %xmm1 +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: ugt: +; UNSAFE-NEXT: maxsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ugt: +; FINITE-NEXT: maxsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ugt(double %x, double %y) nounwind { %c = fcmp ugt double %x, %y %d = select i1 %c, double %x, double %y @@ -172,7 +297,13 @@ define double @ugt(double %x, double %y) nounwind { } ; CHECK: ult: -; CHECK-NEXT: ucomisd %xmm1, %xmm0 +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: ult: +; UNSAFE-NEXT: minsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ult: +; FINITE-NEXT: minsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ult(double %x, double %y) nounwind { %c = fcmp ult double %x, %y %d = select i1 %c, double %x, double %y @@ -180,7 +311,15 @@ define double @ult(double %x, double %y) nounwind { } ; CHECK: ugt_inverse: -; CHECK-NEXT: ucomisd %xmm0, %xmm1 +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: ugt_inverse: +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ugt_inverse: +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ugt_inverse(double %x, double %y) nounwind { %c = fcmp ugt double %x, %y %d = select i1 %c, double %y, double %x @@ -188,7 +327,15 @@ define double @ugt_inverse(double %x, double %y) nounwind { } ; CHECK: ult_inverse: -; CHECK-NEXT: ucomisd %xmm1, %xmm0 +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: ult_inverse: +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ult_inverse: +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ult_inverse(double %x, double %y) nounwind { %c = fcmp ult double %x, %y %d = select i1 %c, double %y, double %x @@ -196,9 +343,15 @@ define double @ult_inverse(double %x, double %y) nounwind { } ; CHECK: uge: -; CHECK-NEXT: maxsd %xmm0, %xmm1 -; CHECK-NEXT: movapd %xmm1, %xmm0 +; CHECK-NEXT: maxsd %xmm0, %xmm1 +; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: uge: +; UNSAFE-NEXT: maxsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: uge: +; FINITE-NEXT: maxsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @uge(double %x, double %y) nounwind { %c = fcmp uge double %x, %y %d = select i1 %c, double %x, double %y @@ -209,6 +362,12 @@ define double @uge(double %x, double %y) nounwind { ; CHECK-NEXT: minsd %xmm0, %xmm1 ; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: ule: +; UNSAFE-NEXT: minsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ule: +; FINITE-NEXT: minsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ule(double %x, double %y) nounwind { %c = fcmp ule double %x, %y %d = select i1 %c, double %x, double %y @@ -218,6 +377,14 @@ define double @ule(double %x, double %y) nounwind { ; CHECK: uge_inverse: ; CHECK-NEXT: minsd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: uge_inverse: +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: uge_inverse: +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @uge_inverse(double %x, double %y) nounwind { %c = fcmp uge double %x, %y %d = select i1 %c, double %y, double %x @@ -227,6 +394,14 @@ define double @uge_inverse(double %x, double %y) nounwind { ; CHECK: ule_inverse: ; CHECK-NEXT: maxsd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: ule_inverse: +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: ule_inverse: +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @ule_inverse(double %x, double %y) nounwind { %c = fcmp ule double %x, %y %d = select i1 %c, double %y, double %x @@ -234,10 +409,15 @@ define double @ule_inverse(double %x, double %y) nounwind { } ; CHECK: x_ugt: -; CHECK-NEXT: pxor %xmm1, %xmm1 -; CHECK-NEXT: maxsd %xmm0, %xmm1 -; CHECK-NEXT: movapd %xmm1, %xmm0 -; CHECK-NEXT: ret +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: x_ugt: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: maxsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ugt: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: maxsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ugt(double %x) nounwind { %c = fcmp ugt double %x, 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00 @@ -245,10 +425,15 @@ define double @x_ugt(double %x) nounwind { } ; CHECK: x_ult: -; CHECK-NEXT: pxor %xmm1, %xmm1 -; CHECK-NEXT: minsd %xmm0, %xmm1 -; CHECK-NEXT: movapd %xmm1, %xmm0 -; CHECK-NEXT: ret +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: x_ult: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: minsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ult: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: minsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ult(double %x) nounwind { %c = fcmp ult double %x, 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00 @@ -256,9 +441,17 @@ define double @x_ult(double %x) nounwind { } ; CHECK: x_ugt_inverse: -; CHECK-NEXT: pxor %xmm1, %xmm1 -; CHECK-NEXT: minsd %xmm1, %xmm0 -; CHECK-NEXT: ret +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: x_ugt_inverse: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ugt_inverse: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ugt_inverse(double %x) nounwind { %c = fcmp ugt double %x, 0.000000e+00 %d = select i1 %c, double 0.000000e+00, double %x @@ -266,9 +459,17 @@ define double @x_ugt_inverse(double %x) nounwind { } ; CHECK: x_ult_inverse: -; CHECK-NEXT: pxor %xmm1, %xmm1 -; CHECK-NEXT: maxsd %xmm1, %xmm0 -; CHECK-NEXT: ret +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: x_ult_inverse: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ult_inverse: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ult_inverse(double %x) nounwind { %c = fcmp ult double %x, 0.000000e+00 %d = select i1 %c, double 0.000000e+00, double %x @@ -280,6 +481,14 @@ define double @x_ult_inverse(double %x) nounwind { ; CHECK-NEXT: maxsd %xmm0, %xmm1 ; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: x_uge: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: maxsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_uge: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: maxsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_uge(double %x) nounwind { %c = fcmp uge double %x, 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00 @@ -291,6 +500,14 @@ define double @x_uge(double %x) nounwind { ; CHECK-NEXT: minsd %xmm0, %xmm1 ; CHECK-NEXT: movapd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: x_ule: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: minsd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ule: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: minsd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ule(double %x) nounwind { %c = fcmp ule double %x, 0.000000e+00 %d = select i1 %c, double %x, double 0.000000e+00 @@ -301,6 +518,16 @@ define double @x_ule(double %x) nounwind { ; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: minsd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: x_uge_inverse: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_uge_inverse: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_uge_inverse(double %x) nounwind { %c = fcmp uge double %x, 0.000000e+00 %d = select i1 %c, double 0.000000e+00, double %x @@ -311,16 +538,301 @@ define double @x_uge_inverse(double %x) nounwind { ; CHECK-NEXT: pxor %xmm1, %xmm1 ; CHECK-NEXT: maxsd %xmm1, %xmm0 ; CHECK-NEXT: ret +; UNSAFE: x_ule_inverse: +; UNSAFE-NEXT: pxor %xmm1, %xmm1 +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: x_ule_inverse: +; FINITE-NEXT: pxor %xmm1, %xmm1 +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret define double @x_ule_inverse(double %x) nounwind { %c = fcmp ule double %x, 0.000000e+00 %d = select i1 %c, double 0.000000e+00, double %x ret double %d } +; CHECK: y_ogt: +; CHECK-NEXT: maxsd {{[^,]*}}, %xmm0 +; CHECK-NEXT: ret +; UNSAFE: y_ogt: +; UNSAFE-NEXT: maxsd {{[^,]*}}, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ogt: +; FINITE-NEXT: maxsd {{[^,]*}}, %xmm0 +; FINITE-NEXT: ret +define double @y_ogt(double %x) nounwind { + %c = fcmp ogt double %x, -0.000000e+00 + %d = select i1 %c, double %x, double -0.000000e+00 + ret double %d +} + +; CHECK: y_olt: +; CHECK-NEXT: minsd {{[^,]*}}, %xmm0 +; CHECK-NEXT: ret +; UNSAFE: y_olt: +; UNSAFE-NEXT: minsd {{[^,]*}}, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_olt: +; FINITE-NEXT: minsd {{[^,]*}}, %xmm0 +; FINITE-NEXT: ret +define double @y_olt(double %x) nounwind { + %c = fcmp olt double %x, -0.000000e+00 + %d = select i1 %c, double %x, double -0.000000e+00 + ret double %d +} + +; CHECK: y_ogt_inverse: +; CHECK-NEXT: movsd {{[^,]*}}, %xmm1 +; CHECK-NEXT: minsd %xmm0, %xmm1 +; CHECK-NEXT: movapd %xmm1, %xmm0 +; CHECK-NEXT: ret +; UNSAFE: y_ogt_inverse: +; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1 +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ogt_inverse: +; FINITE-NEXT: movsd {{[^,]*}}, %xmm1 +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret +define double @y_ogt_inverse(double %x) nounwind { + %c = fcmp ogt double %x, -0.000000e+00 + %d = select i1 %c, double -0.000000e+00, double %x + ret double %d +} + +; CHECK: y_olt_inverse: +; CHECK-NEXT: movsd {{[^,]*}}, %xmm1 +; CHECK-NEXT: maxsd %xmm0, %xmm1 +; CHECK-NEXT: movapd %xmm1, %xmm0 +; CHECK-NEXT: ret +; UNSAFE: y_olt_inverse: +; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1 +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_olt_inverse: +; FINITE-NEXT: movsd {{[^,]*}}, %xmm1 +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret +define double @y_olt_inverse(double %x) nounwind { + %c = fcmp olt double %x, -0.000000e+00 + %d = select i1 %c, double -0.000000e+00, double %x + ret double %d +} + +; CHECK: y_oge: +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: y_oge: +; UNSAFE-NEXT: maxsd {{[^,]*}}, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_oge: +; FINITE-NEXT: maxsd {{[^,]*}}, %xmm0 +; FINITE-NEXT: ret +define double @y_oge(double %x) nounwind { + %c = fcmp oge double %x, -0.000000e+00 + %d = select i1 %c, double %x, double -0.000000e+00 + ret double %d +} + +; CHECK: y_ole: +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: y_ole: +; UNSAFE-NEXT: minsd {{[^,]*}}, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ole: +; FINITE-NEXT: minsd {{[^,]*}}, %xmm0 +; FINITE-NEXT: ret +define double @y_ole(double %x) nounwind { + %c = fcmp ole double %x, -0.000000e+00 + %d = select i1 %c, double %x, double -0.000000e+00 + ret double %d +} + +; CHECK: y_oge_inverse: +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: y_oge_inverse: +; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1 +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_oge_inverse: +; FINITE-NEXT: movsd {{[^,]*}}, %xmm1 +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret +define double @y_oge_inverse(double %x) nounwind { + %c = fcmp oge double %x, -0.000000e+00 + %d = select i1 %c, double -0.000000e+00, double %x + ret double %d +} + +; CHECK: y_ole_inverse: +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: y_ole_inverse: +; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1 +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ole_inverse: +; FINITE-NEXT: movsd {{[^,]*}}, %xmm1 +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret +define double @y_ole_inverse(double %x) nounwind { + %c = fcmp ole double %x, -0.000000e+00 + %d = select i1 %c, double -0.000000e+00, double %x + ret double %d +} + +; CHECK: y_ugt: +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: y_ugt: +; UNSAFE-NEXT: maxsd {{[^,]*}}, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ugt: +; FINITE-NEXT: maxsd {{[^,]*}}, %xmm0 +; FINITE-NEXT: ret +define double @y_ugt(double %x) nounwind { + %c = fcmp ugt double %x, -0.000000e+00 + %d = select i1 %c, double %x, double -0.000000e+00 + ret double %d +} + +; CHECK: y_ult: +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: y_ult: +; UNSAFE-NEXT: minsd {{[^,]*}}, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ult: +; FINITE-NEXT: minsd {{[^,]*}}, %xmm0 +; FINITE-NEXT: ret +define double @y_ult(double %x) nounwind { + %c = fcmp ult double %x, -0.000000e+00 + %d = select i1 %c, double %x, double -0.000000e+00 + ret double %d +} + +; CHECK: y_ugt_inverse: +; CHECK: ucomisd %xmm0, %xmm1 +; UNSAFE: y_ugt_inverse: +; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1 +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ugt_inverse: +; FINITE-NEXT: movsd {{[^,]*}}, %xmm1 +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret +define double @y_ugt_inverse(double %x) nounwind { + %c = fcmp ugt double %x, -0.000000e+00 + %d = select i1 %c, double -0.000000e+00, double %x + ret double %d +} + +; CHECK: y_ult_inverse: +; CHECK: ucomisd %xmm1, %xmm0 +; UNSAFE: y_ult_inverse: +; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1 +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ult_inverse: +; FINITE-NEXT: movsd {{[^,]*}}, %xmm1 +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret +define double @y_ult_inverse(double %x) nounwind { + %c = fcmp ult double %x, -0.000000e+00 + %d = select i1 %c, double -0.000000e+00, double %x + ret double %d +} + +; CHECK: y_uge: +; CHECK-NEXT: movsd {{[^,]*}}, %xmm1 +; CHECK-NEXT: maxsd %xmm0, %xmm1 +; CHECK-NEXT: movapd %xmm1, %xmm0 +; CHECK-NEXT: ret +; UNSAFE: y_uge: +; UNSAFE-NEXT: maxsd {{[^,]*}}, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_uge: +; FINITE-NEXT: maxsd {{[^,]*}}, %xmm0 +; FINITE-NEXT: ret +define double @y_uge(double %x) nounwind { + %c = fcmp uge double %x, -0.000000e+00 + %d = select i1 %c, double %x, double -0.000000e+00 + ret double %d +} + +; CHECK: y_ule: +; CHECK-NEXT: movsd {{[^,]*}}, %xmm1 +; CHECK-NEXT: minsd %xmm0, %xmm1 +; CHECK-NEXT: movapd %xmm1, %xmm0 +; CHECK-NEXT: ret +; UNSAFE: y_ule: +; UNSAFE-NEXT: minsd {{[^,]*}}, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ule: +; FINITE-NEXT: minsd {{[^,]*}}, %xmm0 +; FINITE-NEXT: ret +define double @y_ule(double %x) nounwind { + %c = fcmp ule double %x, -0.000000e+00 + %d = select i1 %c, double %x, double -0.000000e+00 + ret double %d +} + +; CHECK: y_uge_inverse: +; CHECK-NEXT: minsd {{[^,]*}}, %xmm0 +; CHECK-NEXT: ret +; UNSAFE: y_uge_inverse: +; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1 +; UNSAFE-NEXT: minsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_uge_inverse: +; FINITE-NEXT: movsd {{[^,]*}}, %xmm1 +; FINITE-NEXT: minsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret +define double @y_uge_inverse(double %x) nounwind { + %c = fcmp uge double %x, -0.000000e+00 + %d = select i1 %c, double -0.000000e+00, double %x + ret double %d +} + +; CHECK: y_ule_inverse: +; CHECK-NEXT: maxsd {{[^,]*}}, %xmm0 +; CHECK-NEXT: ret +; UNSAFE: y_ule_inverse: +; UNSAFE-NEXT: movsd {{[^,]*}}, %xmm1 +; UNSAFE-NEXT: maxsd %xmm0, %xmm1 +; UNSAFE-NEXT: movapd %xmm1, %xmm0 +; UNSAFE-NEXT: ret +; FINITE: y_ule_inverse: +; FINITE-NEXT: movsd {{[^,]*}}, %xmm1 +; FINITE-NEXT: maxsd %xmm0, %xmm1 +; FINITE-NEXT: movapd %xmm1, %xmm0 +; FINITE-NEXT: ret +define double @y_ule_inverse(double %x) nounwind { + %c = fcmp ule double %x, -0.000000e+00 + %d = select i1 %c, double -0.000000e+00, double %x + ret double %d +} ; Test a few more misc. cases. ; CHECK: clampTo3k_a: ; CHECK: minsd +; UNSAFE: clampTo3k_a: +; UNSAFE: minsd +; FINITE: clampTo3k_a: +; FINITE: minsd define double @clampTo3k_a(double %x) nounwind readnone { entry: %0 = fcmp ogt double %x, 3.000000e+03 ; [#uses=1] @@ -330,6 +842,10 @@ entry: ; CHECK: clampTo3k_b: ; CHECK: minsd +; UNSAFE: clampTo3k_b: +; UNSAFE: minsd +; FINITE: clampTo3k_b: +; FINITE: minsd define double @clampTo3k_b(double %x) nounwind readnone { entry: %0 = fcmp uge double %x, 3.000000e+03 ; [#uses=1] @@ -339,6 +855,10 @@ entry: ; CHECK: clampTo3k_c: ; CHECK: maxsd +; UNSAFE: clampTo3k_c: +; UNSAFE: maxsd +; FINITE: clampTo3k_c: +; FINITE: maxsd define double @clampTo3k_c(double %x) nounwind readnone { entry: %0 = fcmp olt double %x, 3.000000e+03 ; [#uses=1] @@ -348,6 +868,10 @@ entry: ; CHECK: clampTo3k_d: ; CHECK: maxsd +; UNSAFE: clampTo3k_d: +; UNSAFE: maxsd +; FINITE: clampTo3k_d: +; FINITE: maxsd define double @clampTo3k_d(double %x) nounwind readnone { entry: %0 = fcmp ule double %x, 3.000000e+03 ; [#uses=1] @@ -357,6 +881,10 @@ entry: ; CHECK: clampTo3k_e: ; CHECK: maxsd +; UNSAFE: clampTo3k_e: +; UNSAFE: maxsd +; FINITE: clampTo3k_e: +; FINITE: maxsd define double @clampTo3k_e(double %x) nounwind readnone { entry: %0 = fcmp olt double %x, 3.000000e+03 ; [#uses=1] @@ -366,6 +894,10 @@ entry: ; CHECK: clampTo3k_f: ; CHECK: maxsd +; UNSAFE: clampTo3k_f: +; UNSAFE: maxsd +; FINITE: clampTo3k_f: +; FINITE: maxsd define double @clampTo3k_f(double %x) nounwind readnone { entry: %0 = fcmp ule double %x, 3.000000e+03 ; [#uses=1] @@ -375,6 +907,10 @@ entry: ; CHECK: clampTo3k_g: ; CHECK: minsd +; UNSAFE: clampTo3k_g: +; UNSAFE: minsd +; FINITE: clampTo3k_g: +; FINITE: minsd define double @clampTo3k_g(double %x) nounwind readnone { entry: %0 = fcmp ogt double %x, 3.000000e+03 ; [#uses=1] @@ -384,6 +920,10 @@ entry: ; CHECK: clampTo3k_h: ; CHECK: minsd +; UNSAFE: clampTo3k_h: +; UNSAFE: minsd +; FINITE: clampTo3k_h: +; FINITE: minsd define double @clampTo3k_h(double %x) nounwind readnone { entry: %0 = fcmp uge double %x, 3.000000e+03 ; [#uses=1] diff --git a/test/CodeGen/X86/sse3.ll b/test/CodeGen/X86/sse3.ll index b2af7c947d..921161e4a1 100644 --- a/test/CodeGen/X86/sse3.ll +++ b/test/CodeGen/X86/sse3.ll @@ -144,10 +144,9 @@ define void @t9(<4 x float>* %r, <2 x i32>* %A) nounwind { store <4 x float> %tmp13, <4 x float>* %r ret void ; X64: t9: -; X64: movsd (%rsi), %xmm0 -; X64: movaps (%rdi), %xmm1 -; X64: movlhps %xmm0, %xmm1 -; X64: movaps %xmm1, (%rdi) +; X64: movaps (%rdi), %xmm0 +; X64: movhps (%rsi), %xmm0 +; X64: movaps %xmm0, (%rdi) ; X64: ret } diff --git a/test/CodeGen/X86/stack-align.ll b/test/CodeGen/X86/stack-align.ll index cb65e9b50f..e971ef70db 100644 --- a/test/CodeGen/X86/stack-align.ll +++ b/test/CodeGen/X86/stack-align.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -relocation-model=static -mcpu=yonah | grep {andpd.*4(%esp), %xmm} +; RUN: llc < %s -relocation-model=static -realign-stack=1 -mcpu=yonah | FileCheck %s ; The double argument is at 4(esp) which is 16-byte aligned, allowing us to ; fold the load into the andpd. @@ -12,6 +12,7 @@ entry: %tmp = getelementptr { double, double }* %z, i32 0, i32 0 ; [#uses=1] %tmp1 = load double* %tmp, align 8 ; [#uses=1] %tmp2 = tail call double @fabs( double %tmp1 ) ; [#uses=1] + ; CHECK: andpd{{.*}}4(%esp), %xmm %tmp3 = load double* @G, align 16 ; [#uses=1] %tmp4 = tail call double @fabs( double %tmp3 ) ; [#uses=1] %tmp6 = fadd double %tmp4, %tmp2 ; [#uses=1] @@ -19,4 +20,20 @@ entry: ret void } +define void @test2() alignstack(16) { +entry: + ; CHECK: andl{{.*}}$-16, %esp + ret void +} + +; Use a call to force a spill. +define <2 x double> @test3(<2 x double> %x, <2 x double> %y) alignstack(32) { +entry: + ; CHECK: andl{{.*}}$-32, %esp + call void @test2() + %A = mul <2 x double> %x, %y + ret <2 x double> %A +} + declare double @fabs(double) + diff --git a/test/CodeGen/X86/stack-color-with-reg.ll b/test/CodeGen/X86/stack-color-with-reg.ll index 7d85818d46..42e7a394d8 100644 --- a/test/CodeGen/X86/stack-color-with-reg.ll +++ b/test/CodeGen/X86/stack-color-with-reg.ll @@ -1,5 +1,5 @@ ; RUN: llc < %s -mtriple=x86_64-apple-darwin10 -relocation-model=pic -disable-fp-elim -color-ss-with-regs -stats -info-output-file - > %t -; RUN: grep stackcoloring %t | grep "stack slot refs replaced with reg refs" | grep 14 +; RUN: grep stackcoloring %t | grep "stack slot refs replaced with reg refs" | grep 8 type { [62 x %struct.Bitvec*] } ; type %0 type { i8* } ; type %1 diff --git a/test/CodeGen/X86/stdcall.ll b/test/CodeGen/X86/stdcall.ll new file mode 100644 index 0000000000..70204bcf47 --- /dev/null +++ b/test/CodeGen/X86/stdcall.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s | FileCheck %s +; PR5851 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-mingw32" + +%0 = type { void (...)* } + +@B = global %0 { void (...)* bitcast (void ()* @MyFunc to void (...)*) }, align 4 +; CHECK: _B: +; CHECK: .long _MyFunc@0 + +define internal x86_stdcallcc void @MyFunc() nounwind { +entry: + ret void +} diff --git a/test/CodeGen/X86/store_op_load_fold.ll b/test/CodeGen/X86/store_op_load_fold.ll index 66d0e47c6d..6e47eb397d 100644 --- a/test/CodeGen/X86/store_op_load_fold.ll +++ b/test/CodeGen/X86/store_op_load_fold.ll @@ -4,7 +4,7 @@ @X = internal global i16 0 ; [#uses=2] -define void @foo() { +define void @foo() nounwind { %tmp.0 = load i16* @X ; [#uses=1] %tmp.3 = add i16 %tmp.0, 329 ; [#uses=1] store i16 %tmp.3, i16* @X diff --git a/test/CodeGen/X86/store_op_load_fold2.ll b/test/CodeGen/X86/store_op_load_fold2.ll index 0ccfe470db..46e59e95e5 100644 --- a/test/CodeGen/X86/store_op_load_fold2.ll +++ b/test/CodeGen/X86/store_op_load_fold2.ll @@ -1,21 +1,12 @@ -; RUN: llc < %s -march=x86 -x86-asm-syntax=intel | \ -; RUN: grep {and DWORD PTR} | count 2 +; RUN: llc < %s -march=x86 -x86-asm-syntax=intel | FileCheck %s target datalayout = "e-p:32:32" %struct.Macroblock = type { i32, i32, i32, i32, i32, [8 x i32], %struct.Macroblock*, %struct.Macroblock*, i32, [2 x [4 x [4 x [2 x i32]]]], [16 x i8], [16 x i8], i32, i64, [4 x i32], [4 x i32], i64, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i32, i16, double, i32, i32, i32, i32, i32, i32, i32, i32, i32 } -define internal fastcc i32 @dct_chroma(i32 %uv, i32 %cr_cbp) { -entry: - br i1 true, label %cond_true2732.preheader, label %cond_true129 -cond_true129: ; preds = %entry - ret i32 0 +define internal fastcc i32 @dct_chroma(i32 %uv, i32 %cr_cbp) nounwind { cond_true2732.preheader: ; preds = %entry %tmp2666 = getelementptr %struct.Macroblock* null, i32 0, i32 13 ; [#uses=2] %tmp2674 = trunc i32 0 to i8 ; [#uses=1] - br i1 true, label %cond_true2732.preheader.split.us, label %cond_true2732.preheader.split -cond_true2732.preheader.split.us: ; preds = %cond_true2732.preheader - br i1 true, label %cond_true2732.outer.us.us, label %cond_true2732.outer.us -cond_true2732.outer.us.us: ; preds = %cond_true2732.preheader.split.us %tmp2667.us.us = load i64* %tmp2666 ; [#uses=1] %tmp2670.us.us = load i64* null ; [#uses=1] %shift.upgrd.1 = zext i8 %tmp2674 to i64 ; [#uses=1] @@ -24,11 +15,10 @@ cond_true2732.outer.us.us: ; preds = %cond_true2732.preheader.split %tmp2676.us.us = and i64 %tmp2667.us.us, %tmp2675not.us.us ; [#uses=1] store i64 %tmp2676.us.us, i64* %tmp2666 ret i32 0 -cond_true2732.outer.us: ; preds = %cond_true2732.preheader.split.us - ret i32 0 -cond_true2732.preheader.split: ; preds = %cond_true2732.preheader - ret i32 0 -cond_next2752: ; No predecessors! - ret i32 0 + +; CHECK: and {{E..}}, DWORD PTR [360] +; CHECK: and DWORD PTR [356], {{E..}} +; CHECK: mov DWORD PTR [360], {{E..}} + } diff --git a/test/CodeGen/X86/tailcall2.ll b/test/CodeGen/X86/tailcall2.ll index 80bab619c1..90315fd2f2 100644 --- a/test/CodeGen/X86/tailcall2.ll +++ b/test/CodeGen/X86/tailcall2.ll @@ -195,3 +195,24 @@ bb2: } declare i32 @foo6(i32, i32, %struct.t* byval align 4) + +; rdar://r7717598 +%struct.ns = type { i32, i32 } +%struct.cp = type { float, float } + +define %struct.ns* @t13(%struct.cp* %yy) nounwind ssp { +; 32: t13: +; 32-NOT: jmp +; 32: call +; 32: ret + +; 64: t13: +; 64-NOT: jmp +; 64: call +; 64: ret +entry: + %0 = tail call fastcc %struct.ns* @foo7(%struct.cp* byval align 4 %yy, i8 signext 0) nounwind + ret %struct.ns* %0 +} + +declare fastcc %struct.ns* @foo7(%struct.cp* byval align 4, i8 signext) nounwind ssp diff --git a/test/CodeGen/X86/trunc-to-bool.ll b/test/CodeGen/X86/trunc-to-bool.ll index bfab1aef90..6062084106 100644 --- a/test/CodeGen/X86/trunc-to-bool.ll +++ b/test/CodeGen/X86/trunc-to-bool.ll @@ -3,13 +3,14 @@ ; value and as the operand of a branch. ; RUN: llc < %s -march=x86 | FileCheck %s -define i1 @test1(i32 %X) zeroext { +define i1 @test1(i32 %X) zeroext nounwind { %Y = trunc i32 %X to i1 ret i1 %Y } +; CHECK: test1: ; CHECK: andl $1, %eax -define i1 @test2(i32 %val, i32 %mask) { +define i1 @test2(i32 %val, i32 %mask) nounwind { entry: %shifted = ashr i32 %val, %mask %anded = and i32 %shifted, 1 @@ -20,9 +21,10 @@ ret_true: ret_false: ret i1 false } -; CHECK: testb $1, %al +; CHECK: test2: +; CHECK: btl %eax -define i32 @test3(i8* %ptr) { +define i32 @test3(i8* %ptr) nounwind { %val = load i8* %ptr %tmp = trunc i8 %val to i1 br i1 %tmp, label %cond_true, label %cond_false @@ -31,9 +33,10 @@ cond_true: cond_false: ret i32 42 } -; CHECK: testb $1, %al +; CHECK: test3: +; CHECK: testb $1, (%eax) -define i32 @test4(i8* %ptr) { +define i32 @test4(i8* %ptr) nounwind { %tmp = ptrtoint i8* %ptr to i1 br i1 %tmp, label %cond_true, label %cond_false cond_true: @@ -41,9 +44,10 @@ cond_true: cond_false: ret i32 42 } -; CHECK: testb $1, %al +; CHECK: test4: +; CHECK: testb $1, 4(%esp) -define i32 @test6(double %d) { +define i32 @test5(double %d) nounwind { %tmp = fptosi double %d to i1 br i1 %tmp, label %cond_true, label %cond_false cond_true: @@ -51,4 +55,5 @@ cond_true: cond_false: ret i32 42 } +; CHECK: test5: ; CHECK: testb $1 diff --git a/test/CodeGen/X86/twoaddr-coalesce.ll b/test/CodeGen/X86/twoaddr-coalesce.ll index d0e13f61f2..4c37225ce0 100644 --- a/test/CodeGen/X86/twoaddr-coalesce.ll +++ b/test/CodeGen/X86/twoaddr-coalesce.ll @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 | grep mov | count 5 +; RUN: llc < %s -march=x86 | grep mov | count 4 ; rdar://6523745 @"\01LC" = internal constant [4 x i8] c"%d\0A\00" ; <[4 x i8]*> [#uses=1] diff --git a/test/CodeGen/X86/use-add-flags.ll b/test/CodeGen/X86/use-add-flags.ll index 2dd2a4adac..c2f0c23fe1 100644 --- a/test/CodeGen/X86/use-add-flags.ll +++ b/test/CodeGen/X86/use-add-flags.ll @@ -5,13 +5,13 @@ ; Use the flags on the add. -; CHECK: add_zf: +; CHECK: test1: ; CHECK: addl (%rdi), %esi ; CHECK-NEXT: movl %edx, %eax ; CHECK-NEXT: cmovnsl %ecx, %eax ; CHECK-NEXT: ret -define i32 @add_zf(i32* %x, i32 %y, i32 %a, i32 %b) nounwind { +define i32 @test1(i32* %x, i32 %y, i32 %a, i32 %b) nounwind { %tmp2 = load i32* %x, align 4 ; [#uses=1] %tmp4 = add i32 %tmp2, %y ; [#uses=1] %tmp5 = icmp slt i32 %tmp4, 0 ; [#uses=1] @@ -24,10 +24,10 @@ declare void @foo(i32) ; Don't use the flags result of the and here, since the and has no ; other use. A simple test is better. -; CHECK: bar: +; CHECK: test2: ; CHECK: testb $16, %dil -define void @bar(i32 %x) nounwind { +define void @test2(i32 %x) nounwind { %y = and i32 %x, 16 %t = icmp eq i32 %y, 0 br i1 %t, label %true, label %false @@ -40,11 +40,11 @@ false: ; Do use the flags result of the and here, since the and has another use. -; CHECK: qux: +; CHECK: test3: ; CHECK: andl $16, %edi ; CHECK-NEXT: jne -define void @qux(i32 %x) nounwind { +define void @test3(i32 %x) nounwind { %y = and i32 %x, 16 %t = icmp eq i32 %y, 0 br i1 %t, label %true, label %false diff --git a/test/CodeGen/X86/vec_cast.ll b/test/CodeGen/X86/vec_cast.ll index 1f899b3c20..6f18d13cc9 100644 --- a/test/CodeGen/X86/vec_cast.ll +++ b/test/CodeGen/X86/vec_cast.ll @@ -31,11 +31,10 @@ define <1 x i32> @f(<1 x i16> %a) nounwind { ret <1 x i32> %c } -; TODO: Legalize doesn't yet handle this. -;define <8 x i16> @g(<8 x i32> %a) nounwind { -; %c = trunc <8 x i32> %a to <8 x i16> -; ret <8 x i16> %c -;} +define <8 x i16> @g(<8 x i32> %a) nounwind { + %c = trunc <8 x i32> %a to <8 x i16> + ret <8 x i16> %c +} define <3 x i16> @h(<3 x i32> %a) nounwind { %c = trunc <3 x i32> %a to <3 x i16> @@ -46,3 +45,12 @@ define <1 x i16> @i(<1 x i32> %a) nounwind { %c = trunc <1 x i32> %a to <1 x i16> ret <1 x i16> %c } + +; PR6438 +define void @__OpenCL_math_kernel4_kernel() nounwind { + %tmp12.i = and <4 x i32> zeroinitializer, ; <<4 x i32>> [#uses=1] + %cmp13.i = icmp eq <4 x i32> %tmp12.i, ; <<4 x i1>> [#uses=2] + %cmp.ext14.i = sext <4 x i1> %cmp13.i to <4 x i32> ; <<4 x i32>> [#uses=0] + %tmp2110.i = and <4 x i1> %cmp13.i, zeroinitializer ; <<4 x i1>> [#uses=0] + ret void +} diff --git a/test/CodeGen/X86/vec_insert.ll b/test/CodeGen/X86/vec_insert.ll index a7274a9000..4e5d445ff6 100644 --- a/test/CodeGen/X86/vec_insert.ll +++ b/test/CodeGen/X86/vec_insert.ll @@ -1,7 +1,7 @@ ; RUN: llc < %s -march=x86 -mattr=+sse2,-sse41 | grep movss | count 1 ; RUN: llc < %s -march=x86 -mattr=+sse2,-sse41 | not grep pinsrw -define void @test(<4 x float>* %F, i32 %I) { +define void @test(<4 x float>* %F, i32 %I) nounwind { %tmp = load <4 x float>* %F ; <<4 x float>> [#uses=1] %f = sitofp i32 %I to float ; [#uses=1] %tmp1 = insertelement <4 x float> %tmp, float %f, i32 0 ; <<4 x float>> [#uses=2] @@ -10,7 +10,7 @@ define void @test(<4 x float>* %F, i32 %I) { ret void } -define void @test2(<4 x float>* %F, i32 %I, float %g) { +define void @test2(<4 x float>* %F, i32 %I, float %g) nounwind { %tmp = load <4 x float>* %F ; <<4 x float>> [#uses=1] %f = sitofp i32 %I to float ; [#uses=1] %tmp1 = insertelement <4 x float> %tmp, float %f, i32 2 ; <<4 x float>> [#uses=1] diff --git a/test/CodeGen/X86/vec_shuffle-36.ll b/test/CodeGen/X86/vec_shuffle-36.ll index 8a93a7eeee..1ea37c881e 100644 --- a/test/CodeGen/X86/vec_shuffle-36.ll +++ b/test/CodeGen/X86/vec_shuffle-36.ll @@ -1,9 +1,16 @@ -; RUN: llc < %s -march=x86 -mattr=sse41 -o %t -; RUN: grep pshufb %t | count 1 - +; RUN: llc < %s -march=x86-64 -mattr=sse41 | FileCheck %s define <8 x i16> @shuf6(<8 x i16> %T0, <8 x i16> %T1) nounwind readnone { +; CHECK: pshufb +; CHECK-NOT: pshufb +; CHECK: ret entry: - %tmp9 = shufflevector <8 x i16> %T0, <8 x i16> %T1, <8 x i32> < i32 3, i32 2, i32 0, i32 2, i32 1, i32 5, i32 6 , i32 undef > - ret <8 x i16> %tmp9 + %tmp9 = shufflevector <8 x i16> %T0, <8 x i16> %T1, <8 x i32> < i32 3, i32 2, i32 0, i32 2, i32 1, i32 5, i32 6 , i32 undef > + ret <8 x i16> %tmp9 } + +define <8 x i16> @shuf7(<8 x i16> %t0) { +; CHECK: pshufd + %tmp10 = shufflevector <8 x i16> %t0, <8 x i16> undef, <8 x i32> < i32 undef, i32 2, i32 2, i32 2, i32 2, i32 2, i32 undef, i32 undef > + ret <8 x i16> %tmp10 +} \ No newline at end of file diff --git a/test/CodeGen/X86/vec_ss_load_fold.ll b/test/CodeGen/X86/vec_ss_load_fold.ll index b1613fb3a3..c8b2927b71 100644 --- a/test/CodeGen/X86/vec_ss_load_fold.ll +++ b/test/CodeGen/X86/vec_ss_load_fold.ll @@ -1,6 +1,4 @@ -; RUN: llc < %s -march=x86 -mattr=+sse,+sse2 -o %t -; RUN: grep minss %t | grep CPI | count 2 -; RUN: grep CPI %t | not grep movss +; RUN: llc < %s -march=x86 -mattr=+sse,+sse2,+sse41 | FileCheck %s target datalayout = "e-p:32:32" target triple = "i686-apple-darwin8.7.2" @@ -17,6 +15,10 @@ define i16 @test1(float %f) nounwind { %tmp.upgrd.1 = tail call i32 @llvm.x86.sse.cvttss2si( <4 x float> %tmp59 ) ; [#uses=1] %tmp69 = trunc i32 %tmp.upgrd.1 to i16 ; [#uses=1] ret i16 %tmp69 +; CHECK: test1: +; CHECK: subss LCPI1_ +; CHECK: mulss LCPI1_ +; CHECK: minss LCPI1_ } define i16 @test2(float %f) nounwind { @@ -28,6 +30,10 @@ define i16 @test2(float %f) nounwind { %tmp = tail call i32 @llvm.x86.sse.cvttss2si( <4 x float> %tmp59 ) ; [#uses=1] %tmp69 = trunc i32 %tmp to i16 ; [#uses=1] ret i16 %tmp69 +; CHECK: test2: +; CHECK: addss LCPI2_ +; CHECK: mulss LCPI2_ +; CHECK: minss LCPI2_ } declare <4 x float> @llvm.x86.sse.sub.ss(<4 x float>, <4 x float>) @@ -39,3 +45,28 @@ declare <4 x float> @llvm.x86.sse.min.ss(<4 x float>, <4 x float>) declare <4 x float> @llvm.x86.sse.max.ss(<4 x float>, <4 x float>) declare i32 @llvm.x86.sse.cvttss2si(<4 x float>) + + +declare <4 x float> @llvm.x86.sse41.round.ss(<4 x float>, <4 x float>, i32) +declare <4 x float> @f() + +define <4 x float> @test3(<4 x float> %A, float *%b, i32 %C) nounwind { + %a = load float *%b + %B = insertelement <4 x float> undef, float %a, i32 0 + %X = call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %A, <4 x float> %B, i32 4) + ret <4 x float> %X +; CHECK: test3: +; CHECK: roundss $4, (%eax), %xmm0 +} + +define <4 x float> @test4(<4 x float> %A, float *%b, i32 %C) nounwind { + %a = load float *%b + %B = insertelement <4 x float> undef, float %a, i32 0 + %q = call <4 x float> @f() + %X = call <4 x float> @llvm.x86.sse41.round.ss(<4 x float> %q, <4 x float> %B, i32 4) + ret <4 x float> %X +; CHECK: test4: +; CHECK: movss (%eax), %xmm +; CHECK: call +; CHECK: roundss $4, %xmm{{.*}}, %xmm0 +} diff --git a/test/CodeGen/X86/xor-icmp.ll b/test/CodeGen/X86/xor-icmp.ll index a6bdb13ec6..2d75c5d762 100644 --- a/test/CodeGen/X86/xor-icmp.ll +++ b/test/CodeGen/X86/xor-icmp.ll @@ -1,5 +1,6 @@ ; RUN: llc < %s -march=x86 | FileCheck %s -check-prefix=X32 ; RUN: llc < %s -march=x86-64 | FileCheck %s -check-prefix=X64 +; rdar://7367229 define i32 @t(i32 %a, i32 %b) nounwind ssp { entry: @@ -34,3 +35,33 @@ bb1: ; preds = %entry declare i32 @foo(...) declare i32 @bar(...) + +define i32 @t2(i32 %x, i32 %y) nounwind ssp { +; X32: t2: +; X32: cmpl +; X32: sete +; X32: cmpl +; X32: sete +; X32-NOT: xor +; X32: je + +; X64: t2: +; X64: testl +; X64: sete +; X64: testl +; X64: sete +; X64-NOT: xor +; X64: je +entry: + %0 = icmp eq i32 %x, 0 ; [#uses=1] + %1 = icmp eq i32 %y, 0 ; [#uses=1] + %2 = xor i1 %1, %0 ; [#uses=1] + br i1 %2, label %bb, label %return + +bb: ; preds = %entry + %3 = tail call i32 (...)* @foo() nounwind ; [#uses=0] + ret i32 undef + +return: ; preds = %entry + ret i32 undef +} diff --git a/test/CodeGen/XCore/2010-02-25-LSR-Crash.ll b/test/CodeGen/XCore/2010-02-25-LSR-Crash.ll new file mode 100644 index 0000000000..6ad9a73899 --- /dev/null +++ b/test/CodeGen/XCore/2010-02-25-LSR-Crash.ll @@ -0,0 +1,26 @@ +; RUN: llc < %s -march=xcore +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32" +target triple = "xcore-xmos-elf" + +%0 = type { i32 } +%struct.dwarf_fde = type <{ i32, i32, [0 x i8] }> +%struct.object = type { i8*, i8*, i8*, %union.anon, %0, %struct.object* } +%union.anon = type { %struct.dwarf_fde* } + +define %struct.dwarf_fde* @search_object(%struct.object* %ob, i8* %pc) { +entry: + br i1 undef, label %bb3.i15.i.i, label %bb2 + +bb3.i15.i.i: ; preds = %bb3.i15.i.i, %entry + %indvar.i.i.i = phi i32 [ %indvar.next.i.i.i, %bb3.i15.i.i ], [ 0, %entry ] ; [#uses=2] + %tmp137 = sub i32 0, %indvar.i.i.i ; [#uses=1] + %scevgep13.i.i.i = getelementptr i32* undef, i32 %tmp137 ; [#uses=2] + %scevgep1314.i.i.i = bitcast i32* %scevgep13.i.i.i to %struct.dwarf_fde** ; <%struct.dwarf_fde**> [#uses=1] + %0 = load %struct.dwarf_fde** %scevgep1314.i.i.i, align 4 ; <%struct.dwarf_fde*> [#uses=0] + store i32 undef, i32* %scevgep13.i.i.i + %indvar.next.i.i.i = add i32 %indvar.i.i.i, 1 ; [#uses=1] + br label %bb3.i15.i.i + +bb2: ; preds = %entry + ret %struct.dwarf_fde* undef +} diff --git a/test/CodeGen/XCore/switch.ll b/test/CodeGen/XCore/switch.ll new file mode 100644 index 0000000000..9cc27f2ffa --- /dev/null +++ b/test/CodeGen/XCore/switch.ll @@ -0,0 +1,24 @@ +; RUN: llc -march=xcore < %s | FileCheck %s + +define i32 @switch(i32 %i) { +entry: + switch i32 %i, label %default [ + i32 0, label %bb0 + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 + ] +; CHECK-NOT: shl +; CHECK: bru +; CHECK: .jmptable +bb0: + ret i32 0 +bb1: + ret i32 1 +bb2: + ret i32 2 +bb3: + ret i32 3 +default: + ret i32 4 +} diff --git a/test/CodeGen/XCore/switch_long.ll b/test/CodeGen/XCore/switch_long.ll new file mode 100644 index 0000000000..30c9e3db73 --- /dev/null +++ b/test/CodeGen/XCore/switch_long.ll @@ -0,0 +1,132 @@ +; RUN: llc -march=xcore < %s | FileCheck %s + +define i32 @switch(i32 %i) { +entry: + switch i32 %i, label %default [ + i32 0, label %bb0 + i32 1, label %bb1 + i32 2, label %bb2 + i32 3, label %bb3 + i32 4, label %bb4 + i32 5, label %bb5 + i32 6, label %bb6 + i32 7, label %bb7 + i32 8, label %bb8 + i32 9, label %bb9 + i32 10, label %bb10 + i32 11, label %bb11 + i32 12, label %bb12 + i32 13, label %bb13 + i32 14, label %bb14 + i32 15, label %bb15 + i32 16, label %bb16 + i32 17, label %bb17 + i32 18, label %bb18 + i32 19, label %bb19 + i32 20, label %bb20 + i32 21, label %bb21 + i32 22, label %bb22 + i32 23, label %bb23 + i32 24, label %bb24 + i32 25, label %bb25 + i32 26, label %bb26 + i32 27, label %bb27 + i32 28, label %bb28 + i32 29, label %bb29 + i32 30, label %bb30 + i32 31, label %bb31 + i32 32, label %bb32 + i32 33, label %bb33 + i32 34, label %bb34 + i32 35, label %bb35 + i32 36, label %bb36 + i32 37, label %bb37 + i32 38, label %bb38 + i32 39, label %bb39 + ] +; CHECK: shl +; CHECK: bru +; CHECK: .jmptable +bb0: + ret i32 0 +bb1: + ret i32 1 +bb2: + ret i32 2 +bb3: + ret i32 3 +bb4: + ret i32 4 +bb5: + ret i32 5 +bb6: + ret i32 6 +bb7: + ret i32 7 +bb8: + ret i32 8 +bb9: + ret i32 9 +bb10: + ret i32 0 +bb11: + ret i32 1 +bb12: + ret i32 2 +bb13: + ret i32 3 +bb14: + ret i32 4 +bb15: + ret i32 5 +bb16: + ret i32 6 +bb17: + ret i32 7 +bb18: + ret i32 8 +bb19: + ret i32 9 +bb20: + ret i32 0 +bb21: + ret i32 1 +bb22: + ret i32 2 +bb23: + ret i32 3 +bb24: + ret i32 4 +bb25: + ret i32 5 +bb26: + ret i32 6 +bb27: + ret i32 7 +bb28: + ret i32 8 +bb29: + ret i32 9 +bb30: + ret i32 0 +bb31: + ret i32 1 +bb32: + ret i32 2 +bb33: + ret i32 3 +bb34: + ret i32 4 +bb35: + ret i32 5 +bb36: + ret i32 6 +bb37: + ret i32 7 +bb38: + ret i32 8 +bb39: + ret i32 9 +default: + ret i32 0 +} diff --git a/test/DebugInfo/2009-02-27-licm.ll b/test/DebugInfo/2009-02-27-licm.ll deleted file mode 100644 index b490a28e5d..0000000000 --- a/test/DebugInfo/2009-02-27-licm.ll +++ /dev/null @@ -1,83 +0,0 @@ -;RUN: opt < %s -licm -S | grep {load } | count 4 -; ModuleID = '2009-02-27-licm.bc' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" -target triple = "i386-pc-linux-gnu" - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8*, i1, i1, i8*, i32 } - %llvm.dbg.composite.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }*, { }*, i32 } - %llvm.dbg.subprogram.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1 } -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str = internal constant [12 x i8] c"mt19937ar.c\00", section "llvm.metadata" ; <[12 x i8]*> [#uses=1] -@.str1 = internal constant [58 x i8] c"/developer2/home5/youxiangc/work/project/pr965/test-licm/\00", section "llvm.metadata" ; <[58 x i8]*> [#uses=1] -@.str2 = internal constant [52 x i8] c"4.2.1 (Based on Apple Inc. build 5641) (LLVM build)\00", section "llvm.metadata" ; <[52 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), i32 1, i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([58 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([52 x i8]* @.str2, i32 0, i32 0), i1 true, i1 false, i8* null, i32 0 }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@mti = internal global i32 625 ; [#uses=7] -@.str5 = internal constant [18 x i8] c"long unsigned int\00", section "llvm.metadata" ; <[18 x i8]*> [#uses=1] -@llvm.dbg.basictype6 = internal constant %llvm.dbg.basictype.type { i32 458788, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([18 x i8]* @.str5, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 7 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@llvm.dbg.array = internal constant [2 x { }*] [{ }* null, { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to { }*)], section "llvm.metadata" ; <[2 x { }*]*> [#uses=1] -@llvm.dbg.composite = internal constant %llvm.dbg.composite.type { i32 458773, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 0, i64 0, i64 0, i64 0, i32 0, { }* null, { }* bitcast ([2 x { }*]* @llvm.dbg.array to { }*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str7 = internal constant [13 x i8] c"init_genrand\00", section "llvm.metadata" ; <[13 x i8]*> [#uses=1] -@llvm.dbg.subprogram = internal constant %llvm.dbg.subprogram.type { i32 458798, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to { }*), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([13 x i8]* @.str7, i32 0, i32 0), i8* getelementptr ([13 x i8]* @.str7, i32 0, i32 0), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 13, { }* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite to { }*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@mt = internal global [624 x i32] zeroinitializer, align 32 ; <[624 x i32]*> [#uses=4] - -define void @init_genrand(i32 %s) nounwind { -entry: - tail call void @llvm.dbg.func.start({ }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*)) - tail call void @llvm.dbg.stoppoint(i32 14, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - store i32 %s, i32* getelementptr ([624 x i32]* @mt, i32 0, i32 0), align 32 - tail call void @llvm.dbg.stoppoint(i32 15, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - store i32 1, i32* @mti - tail call void @llvm.dbg.stoppoint(i32 15, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - %0 = load i32* @mti, align 4 ; [#uses=1] - %1 = icmp sgt i32 %0, 623 ; [#uses=1] - br i1 %1, label %return, label %bb.nph - -bb.nph: ; preds = %entry - br label %bb - -bb: ; preds = %bb1, %bb.nph - %storemerge1 = phi i32 [ %16, %bb1 ], [ 1, %bb.nph ] ; [#uses=0] - tail call void @llvm.dbg.stoppoint(i32 16, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - %2 = load i32* @mti, align 4 ; [#uses=3] - %3 = add i32 %2, -1 ; [#uses=1] - %4 = getelementptr [624 x i32]* @mt, i32 0, i32 %3 ; [#uses=1] - %5 = load i32* %4, align 4 ; [#uses=1] - %6 = add i32 %2, -1 ; [#uses=1] - %7 = getelementptr [624 x i32]* @mt, i32 0, i32 %6 ; [#uses=1] - %8 = load i32* %7, align 4 ; [#uses=1] - %9 = lshr i32 %8, 30 ; [#uses=1] - %10 = xor i32 %9, %5 ; [#uses=1] - %11 = mul i32 %10, 1812433253 ; [#uses=1] - %12 = load i32* @mti, align 4 ; [#uses=1] - %13 = add i32 %11, %12 ; [#uses=1] - %14 = getelementptr [624 x i32]* @mt, i32 0, i32 %2 ; [#uses=1] - store i32 %13, i32* %14, align 4 - tail call void @llvm.dbg.stoppoint(i32 15, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - %15 = load i32* @mti, align 4 ; [#uses=1] - %16 = add i32 %15, 1 ; [#uses=2] - br label %bb1 - -bb1: ; preds = %bb - %storemerge = phi i32 [ %16, %bb ] ; [#uses=1] - store i32 %storemerge, i32* @mti - tail call void @llvm.dbg.stoppoint(i32 15, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - %17 = load i32* @mti, align 4 ; [#uses=1] - %18 = icmp sgt i32 %17, 623 ; [#uses=1] - br i1 %18, label %bb1.return_crit_edge, label %bb - -bb1.return_crit_edge: ; preds = %bb1 - br label %return - -return: ; preds = %bb1.return_crit_edge, %entry - tail call void @llvm.dbg.stoppoint(i32 25, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - tail call void @llvm.dbg.region.end({ }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*)) - ret void -} - -declare void @llvm.dbg.func.start({ }*) nounwind - -declare void @llvm.dbg.stoppoint(i32, i32, { }*) nounwind - -declare void @llvm.dbg.region.end({ }*) nounwind diff --git a/test/DebugInfo/2009-03-03-cheapdse.ll b/test/DebugInfo/2009-03-03-cheapdse.ll deleted file mode 100644 index 9f47f16153..0000000000 --- a/test/DebugInfo/2009-03-03-cheapdse.ll +++ /dev/null @@ -1,80 +0,0 @@ -; RUN: opt < %s -instcombine -S | grep store | count 5 -; ModuleID = '' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" -target triple = "i386-apple-darwin9.6" - type { } ; type %0 - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, %0*, i8*, %0*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, %0*, i32, i8*, i8*, i8*, i1, i1, i8*, i32 } - %llvm.dbg.composite.type = type { i32, %0*, i8*, %0*, i32, i64, i64, i64, i32, %0*, %0*, i32 } - %llvm.dbg.derivedtype.type = type { i32, %0*, i8*, %0*, i32, i64, i64, i64, i32, %0* } - %llvm.dbg.subprogram.type = type { i32, %0*, %0*, i8*, i8*, i8*, %0*, i32, %0*, i1, i1 } - %struct.Matrix = type { float*, i32, i32, i32, i32 } -@llvm.dbg.compile_units = internal constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str = internal constant [15 x i8] c"himenobmtxpa.c\00", section "llvm.metadata" ; <[15 x i8]*> [#uses=1] -@.str1 = internal constant [74 x i8] c"/Volumes/MacOS9/gcc/llvm/projects/llvm-test/SingleSource/Benchmarks/Misc/\00", section "llvm.metadata" ; <[74 x i8]*> [#uses=1] -@.str2 = internal constant [52 x i8] c"4.2.1 (Based on Apple Inc. build 5641) (LLVM build)\00", section "llvm.metadata" ; <[52 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to %0*), i32 1, i8* getelementptr ([15 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([74 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([52 x i8]* @.str2, i32 0, i32 0), i1 true, i1 false, i8* null, i32 0 }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@.str3 = internal constant [6 x i8] c"float\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type { i32 458788, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([6 x i8]* @.str3, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 4 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@.str5 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.basictype6 = internal constant %llvm.dbg.basictype.type { i32 458788, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([4 x i8]* @.str5, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@llvm.dbg.subprograms = internal constant %llvm.dbg.anchor.type { i32 458752, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str90 = internal constant [4 x i8] c"Mat\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.derivedtype92 = internal constant %llvm.dbg.derivedtype.type { i32 458767, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@.str93 = internal constant [2 x i8] c"m\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1] -@llvm.dbg.derivedtype94 = internal constant %llvm.dbg.derivedtype.type { i32 458765, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([2 x i8]* @.str93, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 46, i64 32, i64 32, i64 0, i32 0, %0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype92 to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@.str95 = internal constant [6 x i8] c"mnums\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@llvm.dbg.derivedtype96 = internal constant %llvm.dbg.derivedtype.type { i32 458765, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([6 x i8]* @.str95, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 47, i64 32, i64 32, i64 32, i32 0, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@.str97 = internal constant [6 x i8] c"mrows\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@llvm.dbg.derivedtype98 = internal constant %llvm.dbg.derivedtype.type { i32 458765, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([6 x i8]* @.str97, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 48, i64 32, i64 32, i64 64, i32 0, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@.str99 = internal constant [6 x i8] c"mcols\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@llvm.dbg.derivedtype100 = internal constant %llvm.dbg.derivedtype.type { i32 458765, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([6 x i8]* @.str99, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 49, i64 32, i64 32, i64 96, i32 0, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@.str101 = internal constant [6 x i8] c"mdeps\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@llvm.dbg.derivedtype102 = internal constant %llvm.dbg.derivedtype.type { i32 458765, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([6 x i8]* @.str101, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 50, i64 32, i64 32, i64 128, i32 0, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@llvm.dbg.array103 = internal constant [5 x %0*] [%0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype94 to %0*), %0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype96 to %0*), %0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype98 to %0*), %0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype100 to %0*), %0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype102 to %0*)], section "llvm.metadata" ; <[5 x %0*]*> [#uses=1] -@llvm.dbg.composite104 = internal constant %llvm.dbg.composite.type { i32 458771, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([4 x i8]* @.str90, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 45, i64 160, i64 32, i64 0, i32 0, %0* null, %0* bitcast ([5 x %0*]* @llvm.dbg.array103 to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@.str105 = internal constant [7 x i8] c"Matrix\00", section "llvm.metadata" ; <[7 x i8]*> [#uses=1] -@llvm.dbg.derivedtype106 = internal constant %llvm.dbg.derivedtype.type { i32 458774, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([7 x i8]* @.str105, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 54, i64 0, i64 0, i64 0, i32 0, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite104 to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@llvm.dbg.derivedtype107 = internal constant %llvm.dbg.derivedtype.type { i32 458767, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, %0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype106 to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@llvm.dbg.array108 = internal constant [6 x %0*] [%0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*), %0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype107 to %0*), %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*), %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*), %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*), %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*)], section "llvm.metadata" ; <[6 x %0*]*> [#uses=1] -@llvm.dbg.composite109 = internal constant %llvm.dbg.composite.type { i32 458773, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 0, i64 0, i64 0, i32 0, %0* null, %0* bitcast ([6 x %0*]* @llvm.dbg.array108 to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@.str110 = internal constant [7 x i8] c"newMat\00", section "llvm.metadata" ; <[7 x i8]*> [#uses=1] -@llvm.dbg.subprogram111 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([7 x i8]* @.str110, i32 0, i32 0), i8* getelementptr ([7 x i8]* @.str110, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 195, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite109 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 (%struct.Matrix*, i32, i32, i32, i32)* @newMat to i8*)], section "llvm.metadata" ; <[1 x i8*]*> [#uses=0] - -define i32 @newMat(%struct.Matrix* %Mat, i32 %mnums, i32 %mrows, i32 %mcols, i32 %mdeps) nounwind { -entry: - call void @llvm.dbg.func.start(%0* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram111 to %0*)) - call void @llvm.dbg.stoppoint(i32 196, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %0 = getelementptr %struct.Matrix* %Mat, i32 0, i32 1 ; [#uses=1] - store i32 %mnums, i32* %0, align 4 - call void @llvm.dbg.stoppoint(i32 197, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %1 = getelementptr %struct.Matrix* %Mat, i32 0, i32 2 ; [#uses=1] - store i32 %mrows, i32* %1, align 4 - call void @llvm.dbg.stoppoint(i32 198, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %2 = getelementptr %struct.Matrix* %Mat, i32 0, i32 3 ; [#uses=1] - store i32 %mcols, i32* %2, align 4 - call void @llvm.dbg.stoppoint(i32 199, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %3 = getelementptr %struct.Matrix* %Mat, i32 0, i32 4 ; [#uses=1] - store i32 %mdeps, i32* %3, align 4 - call void @llvm.dbg.stoppoint(i32 201, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %4 = mul i32 %mnums, %mrows ; [#uses=1] - %5 = mul i32 %4, %mcols ; [#uses=1] - %6 = mul i32 %5, %mdeps ; [#uses=1] - %7 = malloc float, i32 %6 ; [#uses=2] - %8 = getelementptr %struct.Matrix* %Mat, i32 0, i32 0 ; [#uses=1] - store float* %7, float** %8, align 4 - call void @llvm.dbg.stoppoint(i32 204, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %9 = icmp ne float* %7, null ; [#uses=1] - %10 = zext i1 %9 to i32 ; [#uses=1] - call void @llvm.dbg.stoppoint(i32 204, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - call void @llvm.dbg.region.end(%0* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram111 to %0*)) - ret i32 %10 -} - -declare void @llvm.dbg.func.start(%0*) nounwind readnone - -declare void @llvm.dbg.stoppoint(i32, i32, %0*) nounwind readnone - -declare void @llvm.dbg.region.end(%0*) nounwind readnone diff --git a/test/DebugInfo/2009-03-05-gvn.ll b/test/DebugInfo/2009-03-05-gvn.ll deleted file mode 100644 index f363132c52..0000000000 --- a/test/DebugInfo/2009-03-05-gvn.ll +++ /dev/null @@ -1,125 +0,0 @@ -; RUN: opt < %s -gvn -S | grep {load } | count 1 -; ModuleID = 'db2-before.bc' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" -target triple = "i386-pc-linux-gnu" - type { } ; type %0 - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, %0*, i8*, %0*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, %0*, i32, i8*, i8*, i8*, i1, i1, i8*, i32 } - %llvm.dbg.composite.type = type { i32, %0*, i8*, %0*, i32, i64, i64, i64, i32, %0*, %0*, i32 } - %llvm.dbg.derivedtype.type = type { i32, %0*, i8*, %0*, i32, i64, i64, i64, i32, %0* } - %llvm.dbg.subprogram.type = type { i32, %0*, %0*, i8*, i8*, i8*, %0*, i32, %0*, i1, i1 } -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str = internal constant [12 x i8] c"mt19937ar.c\00", section "llvm.metadata" ; <[12 x i8]*> [#uses=1] -@.str1 = internal constant [34 x i8] c"/developer/home2/zsth/test/debug/\00", section "llvm.metadata" ; <[34 x i8]*> [#uses=1] -@.str2 = internal constant [52 x i8] c"4.2.1 (Based on Apple Inc. build 5641) (LLVM build)\00", section "llvm.metadata" ; <[52 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to %0*), i32 1, i8* getelementptr ([12 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([34 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([52 x i8]* @.str2, i32 0, i32 0), i1 true, i1 false, i8* null, i32 -1 }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@mti = internal global i32 625 ; [#uses=14] -@.str3 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type { i32 458788, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([4 x i8]* @.str3, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@.str5 = internal constant [18 x i8] c"long unsigned int\00", section "llvm.metadata" ; <[18 x i8]*> [#uses=1] -@llvm.dbg.basictype6 = internal constant %llvm.dbg.basictype.type { i32 458788, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([18 x i8]* @.str5, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 7 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@llvm.dbg.array = internal constant [2 x %0*] [%0* null, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*)], section "llvm.metadata" ; <[2 x %0*]*> [#uses=1] -@llvm.dbg.composite = internal constant %llvm.dbg.composite.type { i32 458773, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 0, i64 0, i64 0, i32 0, %0* null, %0* bitcast ([2 x %0*]* @llvm.dbg.array to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str7 = internal constant [13 x i8] c"init_genrand\00", section "llvm.metadata" ; <[13 x i8]*> [#uses=1] -@llvm.dbg.subprogram = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([13 x i8]* @.str7, i32 0, i32 0), i8* getelementptr ([13 x i8]* @.str7, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 58, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@mt = internal global [624 x i32] zeroinitializer, align 32 ; <[624 x i32]*> [#uses=29] -@llvm.dbg.derivedtype = internal constant %llvm.dbg.derivedtype.type { i32 458767, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@llvm.dbg.array9 = internal constant [3 x %0*] [%0* null, %0* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype to %0*), %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to %0*)], section "llvm.metadata" ; <[3 x %0*]*> [#uses=1] -@llvm.dbg.composite10 = internal constant %llvm.dbg.composite.type { i32 458773, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 0, i64 0, i64 0, i32 0, %0* null, %0* bitcast ([3 x %0*]* @llvm.dbg.array9 to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@.str11 = internal constant [14 x i8] c"init_by_array\00", section "llvm.metadata" ; <[14 x i8]*> [#uses=1] -@llvm.dbg.subprogram12 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([14 x i8]* @.str11, i32 0, i32 0), i8* getelementptr ([14 x i8]* @.str11, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 77, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite10 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@llvm.dbg.array23 = internal constant [1 x %0*] [%0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype6 to %0*)], section "llvm.metadata" ; <[1 x %0*]*> [#uses=1] -@llvm.dbg.composite24 = internal constant %llvm.dbg.composite.type { i32 458773, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 0, i64 0, i64 0, i32 0, %0* null, %0* bitcast ([1 x %0*]* @llvm.dbg.array23 to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@.str25 = internal constant [14 x i8] c"genrand_int32\00", section "llvm.metadata" ; <[14 x i8]*> [#uses=1] -@llvm.dbg.subprogram26 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([14 x i8]* @.str25, i32 0, i32 0), i8* getelementptr ([14 x i8]* @.str25, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 103, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite24 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@mag01.1661 = internal constant [2 x i32] [i32 0, i32 -1727483681] ; <[2 x i32]*> [#uses=3] -@.str35 = internal constant [9 x i8] c"long int\00", section "llvm.metadata" ; <[9 x i8]*> [#uses=1] -@llvm.dbg.basictype36 = internal constant %llvm.dbg.basictype.type { i32 458788, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([9 x i8]* @.str35, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@llvm.dbg.array37 = internal constant [1 x %0*] [%0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype36 to %0*)], section "llvm.metadata" ; <[1 x %0*]*> [#uses=1] -@llvm.dbg.composite38 = internal constant %llvm.dbg.composite.type { i32 458773, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 0, i64 0, i64 0, i32 0, %0* null, %0* bitcast ([1 x %0*]* @llvm.dbg.array37 to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@.str39 = internal constant [14 x i8] c"genrand_int31\00", section "llvm.metadata" ; <[14 x i8]*> [#uses=1] -@llvm.dbg.subprogram40 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([14 x i8]* @.str39, i32 0, i32 0), i8* getelementptr ([14 x i8]* @.str39, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 141, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite38 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@.str41 = internal constant [7 x i8] c"double\00", section "llvm.metadata" ; <[7 x i8]*> [#uses=1] -@llvm.dbg.basictype42 = internal constant %llvm.dbg.basictype.type { i32 458788, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([7 x i8]* @.str41, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 64, i64 64, i64 0, i32 0, i32 4 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@llvm.dbg.array43 = internal constant [1 x %0*] [%0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype42 to %0*)], section "llvm.metadata" ; <[1 x %0*]*> [#uses=1] -@llvm.dbg.composite44 = internal constant %llvm.dbg.composite.type { i32 458773, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 0, i64 0, i64 0, i32 0, %0* null, %0* bitcast ([1 x %0*]* @llvm.dbg.array43 to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@.str45 = internal constant [14 x i8] c"genrand_real1\00", section "llvm.metadata" ; <[14 x i8]*> [#uses=1] -@llvm.dbg.subprogram46 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([14 x i8]* @.str45, i32 0, i32 0), i8* getelementptr ([14 x i8]* @.str45, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 147, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite44 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@.str47 = internal constant [14 x i8] c"genrand_real2\00", section "llvm.metadata" ; <[14 x i8]*> [#uses=1] -@llvm.dbg.subprogram48 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([14 x i8]* @.str47, i32 0, i32 0), i8* getelementptr ([14 x i8]* @.str47, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 154, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite44 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@.str49 = internal constant [14 x i8] c"genrand_real3\00", section "llvm.metadata" ; <[14 x i8]*> [#uses=1] -@llvm.dbg.subprogram50 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([14 x i8]* @.str49, i32 0, i32 0), i8* getelementptr ([14 x i8]* @.str49, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 161, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite44 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@.str51 = internal constant [14 x i8] c"genrand_res53\00", section "llvm.metadata" ; <[14 x i8]*> [#uses=1] -@llvm.dbg.subprogram52 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([14 x i8]* @.str51, i32 0, i32 0), i8* getelementptr ([14 x i8]* @.str51, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 168, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite44 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@llvm.dbg.array57 = internal constant [1 x %0*] [%0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to %0*)], section "llvm.metadata" ; <[1 x %0*]*> [#uses=1] -@llvm.dbg.composite58 = internal constant %llvm.dbg.composite.type { i32 458773, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 0, i64 0, i64 0, i32 0, %0* null, %0* bitcast ([1 x %0*]* @llvm.dbg.array57 to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@.str59 = internal constant [5 x i8] c"main\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.subprogram60 = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([5 x i8]* @.str59, i32 0, i32 0), i8* getelementptr ([5 x i8]* @.str59, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 175, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite58 to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@.str69 = internal constant [32 x i8] c"1000 outputs of genrand_int32()\00" ; <[32 x i8]*> [#uses=1] -@.str70 = internal constant [7 x i8] c"%10lu \00" ; <[7 x i8]*> [#uses=1] -@.str71 = internal constant [33 x i8] c"\0A1000 outputs of genrand_real2()\00" ; <[33 x i8]*> [#uses=1] -@.str72 = internal constant [8 x i8] c"%10.8f \00" ; <[8 x i8]*> [#uses=1] - -define void @init_genrand(i32 %s) nounwind { -entry: - tail call void @llvm.dbg.func.start(%0* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to %0*)) - tail call void @llvm.dbg.stoppoint(i32 59, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - store i32 %s, i32* getelementptr ([624 x i32]* @mt, i32 0, i32 0), align 32 - tail call void @llvm.dbg.stoppoint(i32 60, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - store i32 1, i32* @mti - tail call void @llvm.dbg.stoppoint(i32 60, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - br i1 false, label %return, label %bb.nph - -bb.nph: ; preds = %entry - %mti.promoted = load i32* @mti ; [#uses=1] - br label %bb - -bb: ; preds = %bb1, %bb.nph - %indvar = phi i32 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ; [#uses=2] - %mti.tmp.0 = add i32 %indvar, %mti.promoted ; [#uses=5] - tail call void @llvm.dbg.stoppoint(i32 61, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %0 = add i32 %mti.tmp.0, -1 ; [#uses=1] - %1 = getelementptr [624 x i32]* @mt, i32 0, i32 %0 ; [#uses=1] - %2 = load i32* %1, align 4 ; [#uses=1] - %3 = add i32 %mti.tmp.0, -1 ; [#uses=1] - %4 = getelementptr [624 x i32]* @mt, i32 0, i32 %3 ; [#uses=1] - %5 = load i32* %4, align 4 ; [#uses=1] - %6 = lshr i32 %5, 30 ; [#uses=1] - %7 = xor i32 %6, %2 ; [#uses=1] - %8 = mul i32 %7, 1812433253 ; [#uses=1] - %9 = add i32 %8, %mti.tmp.0 ; [#uses=1] - %10 = getelementptr [624 x i32]* @mt, i32 0, i32 %mti.tmp.0 ; [#uses=1] - store i32 %9, i32* %10, align 4 - tail call void @llvm.dbg.stoppoint(i32 60, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %11 = add i32 %mti.tmp.0, 1 ; [#uses=2] - br label %bb1 - -bb1: ; preds = %bb - tail call void @llvm.dbg.stoppoint(i32 60, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %12 = icmp sgt i32 %11, 623 ; [#uses=1] - %indvar.next = add i32 %indvar, 1 ; [#uses=1] - br i1 %12, label %bb1.return_crit_edge, label %bb - -bb1.return_crit_edge: ; preds = %bb1 - store i32 %11, i32* @mti - br label %return - -return: ; preds = %bb1.return_crit_edge, %entry - tail call void @llvm.dbg.stoppoint(i32 70, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - tail call void @llvm.dbg.region.end(%0* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to %0*)) - ret void -} - -declare void @llvm.dbg.func.start(%0*) nounwind - -declare void @llvm.dbg.stoppoint(i32, i32, %0*) nounwind - -declare void @llvm.dbg.region.end(%0*) nounwind - -declare i32 @puts(i8* nocapture) nounwind - -declare i32 @printf(i8* noalias nocapture, ...) nounwind - -declare i32 @putchar(i32) nounwind diff --git a/test/DebugInfo/deaddebuglabel.ll b/test/DebugInfo/deaddebuglabel.ll deleted file mode 100644 index a9af12b385..0000000000 --- a/test/DebugInfo/deaddebuglabel.ll +++ /dev/null @@ -1,62 +0,0 @@ -; RUN: llc %s -o - -O0 | grep "label" | count 8 -; PR2614 -; XFAIL: * - -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-f80:32:32-v64:64:64-v128:128:128-a0:0:64" -target triple = "i686-pc-linux-gnu" - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8* } - %llvm.dbg.compositetype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }*, { }* } - %llvm.dbg.derivedtype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }* } - %llvm.dbg.global_variable.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1, { }* } - %llvm.dbg.subprogram.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1 } - %llvm.dbg.variable.type = type { i32, { }*, i8*, { }*, i32, { }* } -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 52 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=0] -@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str = internal constant [17 x i8] c"deaddebuglabel.d\00", section "llvm.metadata" ; <[17 x i8]*> [#uses=1] -@.str1 = internal constant [50 x i8] c"/home/kamm/eigenes/projekte/llvmdc/llvmdc/mytests\00", section "llvm.metadata" ; <[50 x i8]*> [#uses=1] -@.str2 = internal constant [48 x i8] c"LLVMDC (http://www.dsource.org/projects/llvmdc)\00", section "llvm.metadata" ; <[48 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { - i32 393233, - { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), - i32 2, - i8* getelementptr ([17 x i8]* @.str, i32 0, i32 0), - i8* getelementptr ([50 x i8]* @.str1, i32 0, i32 0), - i8* getelementptr ([48 x i8]* @.str2, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@.str5 = internal constant [20 x i8] c"deaddebuglabel.main\00", section "llvm.metadata" ; <[20 x i8]*> [#uses=1] -@.str6 = internal constant [5 x i8] c"main\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.subprogram7 = internal constant %llvm.dbg.subprogram.type { - i32 393262, - { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to { }*), - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i8* getelementptr ([20 x i8]* @.str5, i32 0, i32 0), - i8* getelementptr ([20 x i8]* @.str5, i32 0, i32 0), - i8* getelementptr ([5 x i8]* @.str6, i32 0, i32 0), - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i32 3, - { }* null, - i1 false, - i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] - -declare void @llvm.dbg.func.start({ }*) nounwind - -declare void @llvm.dbg.stoppoint(i32, i32, { }*) nounwind - -declare void @llvm.dbg.region.end({ }*) nounwind - -define fastcc i32 @main() { -entry.main: - call void @llvm.dbg.func.start( { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram7 to { }*) ) - br i1 true, label %reachable, label %unreachable - -reachable: ; preds = %entry.main - call void @llvm.dbg.region.end( { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram7 to { }*) ) - ret i32 1 - -unreachable: ; preds = %entry.main - call void @llvm.dbg.stoppoint( i32 7, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - call void @llvm.dbg.region.end( { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram7 to { }*) ) - ret i32 0 -} diff --git a/test/DebugInfo/funccall.ll b/test/DebugInfo/funccall.ll deleted file mode 100644 index e44b0298ce..0000000000 --- a/test/DebugInfo/funccall.ll +++ /dev/null @@ -1,147 +0,0 @@ -;; RUN: llc < %s - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8* } - %llvm.dbg.global_variable.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1, { }* } - %llvm.dbg.subprogram.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1 } - %llvm.dbg.variable.type = type { i32, { }*, i8*, { }*, i32, { }* } -@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 52 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@llvm.dbg.subprogram = internal constant %llvm.dbg.subprogram.type { - i32 393262, - { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to { }*), - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i8* getelementptr ([4 x i8]* @str, i32 0, i32 0), - i8* getelementptr ([4 x i8]* @str, i32 0, i32 0), - i8* null, - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i32 4, - { }* null, - i1 false, - i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@str = internal constant [4 x i8] c"foo\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { - i32 393233, - { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), - i32 1, - i8* getelementptr ([11 x i8]* @str1, i32 0, i32 0), - i8* getelementptr ([50 x i8]* @str2, i32 0, i32 0), - i8* getelementptr ([45 x i8]* @str3, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@str1 = internal constant [11 x i8] c"funccall.c\00", section "llvm.metadata" ; <[11 x i8]*> [#uses=1] -@str2 = internal constant [50 x i8] c"/Volumes/Big2/llvm/llvm/test/Regression/Debugger/\00", section "llvm.metadata" ; <[50 x i8]*> [#uses=1] -@str3 = internal constant [45 x i8] c"4.0.1 LLVM (Apple Computer, Inc. build 5421)\00", section "llvm.metadata" ; <[45 x i8]*> [#uses=1] -@llvm.dbg.variable = internal constant %llvm.dbg.variable.type { - i32 393472, - { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*), - i8* getelementptr ([2 x i8]* @str4, i32 0, i32 0), - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i32 5, - { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*) }, section "llvm.metadata" ; <%llvm.dbg.variable.type*> [#uses=1] -@str4 = internal constant [2 x i8] c"t\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1] -@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type { - i32 393252, - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i8* getelementptr ([4 x i8]* @str15, i32 0, i32 0), - { }* null, - i32 0, - i64 32, - i64 32, - i64 0, - i32 0, - i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@str15 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.subprogram2 = internal constant %llvm.dbg.subprogram.type { - i32 393262, - { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to { }*), - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i8* getelementptr ([5 x i8]* @str6, i32 0, i32 0), - i8* getelementptr ([5 x i8]* @str6, i32 0, i32 0), - i8* null, - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i32 8, - { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*), - i1 false, - i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@str6 = internal constant [5 x i8] c"main\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.variable3 = internal constant %llvm.dbg.variable.type { - i32 393474, - { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram2 to { }*), - i8* getelementptr ([7 x i8]* @str7, i32 0, i32 0), - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i32 8, - { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*) }, section "llvm.metadata" ; <%llvm.dbg.variable.type*> [#uses=1] -@str7 = internal constant [7 x i8] c"retval\00", section "llvm.metadata" ; <[7 x i8]*> [#uses=1] -@llvm.dbg.global_variable = internal constant %llvm.dbg.global_variable.type { - i32 393268, - { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.global_variables to { }*), - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i8* getelementptr ([2 x i8]* @str4, i32 0, i32 0), - i8* getelementptr ([2 x i8]* @str4, i32 0, i32 0), - i8* null, - { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), - i32 2, - { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*), - i1 true, - i1 true, - { }* bitcast (i32* @q to { }*) }, section "llvm.metadata" ; <%llvm.dbg.global_variable.type*> [#uses=0] -@str4.upgrd.1 = internal constant [2 x i8] c"q\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=0] -@q = internal global i32 0 ; [#uses=7] - -declare void @llvm.dbg.func.start({ }*) - -declare void @llvm.dbg.stoppoint(i32, i32, { }*) - -declare void @llvm.dbg.declare({ }*, { }*) - -declare void @llvm.dbg.region.start({ }*) - -declare void @llvm.dbg.region.end({ }*) - -define void @foo() { -entry: - %t = alloca i32, align 4 ; [#uses=3] - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - call void @llvm.dbg.func.start( { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*) ) - call void @llvm.dbg.stoppoint( i32 4, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - %t.upgrd.2 = bitcast i32* %t to { }* ; <{ }*> [#uses=1] - call void @llvm.dbg.declare( { }* %t.upgrd.2, { }* bitcast (%llvm.dbg.variable.type* @llvm.dbg.variable to { }*) ) - call void @llvm.dbg.stoppoint( i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - %tmp = load i32* @q ; [#uses=1] - store i32 %tmp, i32* %t - call void @llvm.dbg.stoppoint( i32 6, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - %tmp1 = load i32* %t ; [#uses=1] - %tmp2 = add i32 %tmp1, 1 ; [#uses=1] - store i32 %tmp2, i32* @q - call void @llvm.dbg.stoppoint( i32 7, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - call void @llvm.dbg.region.end( { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*) ) - ret void -} - -define i32 @main() { -entry: - %retval = alloca i32, align 4 ; [#uses=3] - %tmp = alloca i32, align 4 ; [#uses=2] - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - call void @llvm.dbg.func.start( { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram2 to { }*) ) - call void @llvm.dbg.stoppoint( i32 8, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - %retval.upgrd.3 = bitcast i32* %retval to { }* ; <{ }*> [#uses=1] - call void @llvm.dbg.declare( { }* %retval.upgrd.3, { }* bitcast (%llvm.dbg.variable.type* @llvm.dbg.variable3 to { }*) ) - call void @llvm.dbg.stoppoint( i32 9, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - store i32 0, i32* @q - call void @llvm.dbg.stoppoint( i32 10, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - call void (...)* bitcast (void ()* @foo to void (...)*)( ) - call void @llvm.dbg.stoppoint( i32 11, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - %tmp.upgrd.4 = load i32* @q ; [#uses=1] - %tmp1 = sub i32 %tmp.upgrd.4, 1 ; [#uses=1] - store i32 %tmp1, i32* @q - call void @llvm.dbg.stoppoint( i32 13, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - %tmp2 = load i32* @q ; [#uses=1] - store i32 %tmp2, i32* %tmp - %tmp3 = load i32* %tmp ; [#uses=1] - store i32 %tmp3, i32* %retval - %retval.upgrd.5 = load i32* %retval ; [#uses=1] - call void @llvm.dbg.stoppoint( i32 14, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*) ) - call void @llvm.dbg.region.end( { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram2 to { }*) ) - ret i32 %retval.upgrd.5 -} diff --git a/test/DebugInfo/globalGetElementPtr.ll b/test/DebugInfo/globalGetElementPtr.ll deleted file mode 100644 index 155deb7225..0000000000 --- a/test/DebugInfo/globalGetElementPtr.ll +++ /dev/null @@ -1,264 +0,0 @@ -; RUN: llc < %s -; ModuleID = 'foo.c' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" -target triple = "i686-apple-darwin8" - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, %struct.anon*, i8*, %struct.anon*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, %struct.anon*, i32, i8*, i8*, i8* } - %llvm.dbg.compositetype.type = type { i32, %struct.anon*, i8*, %struct.anon*, i32, i64, i64, i64, i32, %struct.anon*, %struct.anon* } - %llvm.dbg.derivedtype.type = type { i32, %struct.anon*, i8*, %struct.anon*, i32, i64, i64, i64, i32, %struct.anon* } - %llvm.dbg.global_variable.type = type { i32, %struct.anon*, %struct.anon*, i8*, i8*, i8*, %struct.anon*, i32, %struct.anon*, i1, i1, %struct.anon* } - %llvm.dbg.subprogram.type = type { i32, %struct.anon*, %struct.anon*, i8*, i8*, i8*, %struct.anon*, i32, %struct.anon*, i1, i1 } - %llvm.dbg.subrange.type = type { i32, i64, i64 } - %llvm.dbg.variable.type = type { i32, %struct.anon*, i8*, %struct.anon*, i32, %struct.anon* } - %struct.S271 = type { [0 x %struct.anon], %struct.anon } - %struct.anon = type { } -@llvm.dbg.subprogram = internal constant %llvm.dbg.subprogram.type { - i32 393262, - %struct.anon* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %struct.anon*), - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* getelementptr ([4 x i8]* @.str3, i32 0, i32 0), - i8* getelementptr ([4 x i8]* @.str3, i32 0, i32 0), - i8* null, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 2, - %struct.anon* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype to %struct.anon*), - i1 false, - i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { - i32 393233, - %struct.anon* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to %struct.anon*), - i32 1, - i8* getelementptr ([6 x i8]* @.str, i32 0, i32 0), - i8* getelementptr ([23 x i8]* @.str1, i32 0, i32 0), - i8* getelementptr ([52 x i8]* @.str2, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str = internal constant [6 x i8] c"foo.c\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@.str1 = internal constant [23 x i8] c"/Volumes/MacOS9/tests/\00", section "llvm.metadata" ; <[23 x i8]*> [#uses=1] -@.str2 = internal constant [52 x i8] c"4.2.1 (Based on Apple Inc. build 5546) (LLVM build)\00", section "llvm.metadata" ; <[52 x i8]*> [#uses=1] -@.str3 = internal constant [4 x i8] c"var\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.derivedtype = internal constant %llvm.dbg.derivedtype.type { - i32 393231, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* null, - %struct.anon* null, - i32 0, - i64 32, - i64 32, - i64 0, - i32 0, - %struct.anon* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type { - i32 393252, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* getelementptr ([5 x i8]* @.str4, i32 0, i32 0), - %struct.anon* null, - i32 0, - i64 8, - i64 8, - i64 0, - i32 0, - i32 6 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@.str4 = internal constant [5 x i8] c"char\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.variable = internal constant %llvm.dbg.variable.type { - i32 393474, - %struct.anon* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to %struct.anon*), - i8* getelementptr ([7 x i8]* @.str5, i32 0, i32 0), - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 2, - %struct.anon* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.variable.type*> [#uses=1] -@.str5 = internal constant [7 x i8] c"retval\00", section "llvm.metadata" ; <[7 x i8]*> [#uses=1] -@a271 = weak global [0 x %struct.S271] zeroinitializer ; <[0 x %struct.S271]*> [#uses=3] -@llvm.dbg.subprogram6 = internal constant %llvm.dbg.subprogram.type { - i32 393262, - %struct.anon* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %struct.anon*), - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* getelementptr ([5 x i8]* @.str7, i32 0, i32 0), - i8* getelementptr ([5 x i8]* @.str7, i32 0, i32 0), - i8* null, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 3, - %struct.anon* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype8 to %struct.anon*), - i1 false, - i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@.str7 = internal constant [5 x i8] c"main\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.basictype8 = internal constant %llvm.dbg.basictype.type { - i32 393252, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* getelementptr ([4 x i8]* @.str9, i32 0, i32 0), - %struct.anon* null, - i32 0, - i64 32, - i64 32, - i64 0, - i32 0, - i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@.str9 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.variable10 = internal constant %llvm.dbg.variable.type { - i32 393474, - %struct.anon* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram6 to %struct.anon*), - i8* getelementptr ([7 x i8]* @.str5, i32 0, i32 0), - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 3, - %struct.anon* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype8 to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.variable.type*> [#uses=1] -@llvm.dbg.global_variable = internal constant %llvm.dbg.global_variable.type { - i32 393268, - %struct.anon* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.global_variables to %struct.anon*), - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* getelementptr ([5 x i8]* @.str11, i32 0, i32 0), - i8* getelementptr ([5 x i8]* @.str11, i32 0, i32 0), - i8* null, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 1, - %struct.anon* bitcast (%llvm.dbg.compositetype.type* @llvm.dbg.compositetype to %struct.anon*), - i1 false, - i1 true, - %struct.anon* getelementptr ([0 x %struct.S271]* @a271, i32 0, i32 0, i32 0, i32 0) }, section "llvm.metadata" ; <%llvm.dbg.global_variable.type*> [#uses=0] -@llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type { i32 393216, i32 52 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str11 = internal constant [5 x i8] c"a271\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.compositetype = internal constant %llvm.dbg.compositetype.type { - i32 393217, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* null, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 0, - i64 0, - i64 8, - i64 0, - i32 0, - %struct.anon* bitcast (%llvm.dbg.compositetype.type* @llvm.dbg.compositetype12 to %struct.anon*), - %struct.anon* bitcast ([1 x %struct.anon*]* @llvm.dbg.array25 to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.compositetype.type*> [#uses=1] -@llvm.dbg.compositetype12 = internal constant %llvm.dbg.compositetype.type { - i32 393235, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* getelementptr ([5 x i8]* @.str13, i32 0, i32 0), - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 1, - i64 0, - i64 8, - i64 0, - i32 0, - %struct.anon* null, - %struct.anon* bitcast ([2 x %struct.anon*]* @llvm.dbg.array23 to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.compositetype.type*> [#uses=1] -@.str13 = internal constant [5 x i8] c"S271\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.derivedtype14 = internal constant %llvm.dbg.derivedtype.type { - i32 393229, - %struct.anon* null, - i8* getelementptr ([2 x i8]* @.str15, i32 0, i32 0), - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 1, - i64 0, - i64 8, - i64 0, - i32 0, - %struct.anon* bitcast (%llvm.dbg.compositetype.type* @llvm.dbg.compositetype16 to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@.str15 = internal constant [2 x i8] c"a\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1] -@llvm.dbg.compositetype16 = internal constant %llvm.dbg.compositetype.type { - i32 393217, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* null, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 0, - i64 0, - i64 8, - i64 0, - i32 0, - %struct.anon* bitcast (%llvm.dbg.compositetype.type* @llvm.dbg.compositetype17 to %struct.anon*), - %struct.anon* bitcast ([1 x %struct.anon*]* @llvm.dbg.array18 to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.compositetype.type*> [#uses=1] -@llvm.dbg.compositetype17 = internal constant %llvm.dbg.compositetype.type { - i32 393235, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* null, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 1, - i64 0, - i64 8, - i64 0, - i32 0, - %struct.anon* null, - %struct.anon* bitcast ([0 x %struct.anon*]* @llvm.dbg.array to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.compositetype.type*> [#uses=1] -@llvm.dbg.array = internal constant [0 x %struct.anon*] zeroinitializer, section "llvm.metadata" ; <[0 x %struct.anon*]*> [#uses=1] -@llvm.dbg.subrange = internal constant %llvm.dbg.subrange.type { - i32 393249, - i64 0, - i64 4 }, section "llvm.metadata" ; <%llvm.dbg.subrange.type*> [#uses=1] -@llvm.dbg.array18 = internal constant [1 x %struct.anon*] [ %struct.anon* bitcast (%llvm.dbg.subrange.type* @llvm.dbg.subrange to %struct.anon*) ], section "llvm.metadata" ; <[1 x %struct.anon*]*> [#uses=1] -@llvm.dbg.derivedtype19 = internal constant %llvm.dbg.derivedtype.type { - i32 393229, - %struct.anon* null, - i8* getelementptr ([2 x i8]* @.str20, i32 0, i32 0), - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 1, - i64 0, - i64 8, - i64 0, - i32 0, - %struct.anon* bitcast (%llvm.dbg.compositetype.type* @llvm.dbg.compositetype21 to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@.str20 = internal constant [2 x i8] c"b\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1] -@llvm.dbg.compositetype21 = internal constant %llvm.dbg.compositetype.type { - i32 393235, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i8* null, - %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*), - i32 1, - i64 0, - i64 8, - i64 0, - i32 0, - %struct.anon* null, - %struct.anon* bitcast ([0 x %struct.anon*]* @llvm.dbg.array22 to %struct.anon*) }, section "llvm.metadata" ; <%llvm.dbg.compositetype.type*> [#uses=1] -@llvm.dbg.array22 = internal constant [0 x %struct.anon*] zeroinitializer, section "llvm.metadata" ; <[0 x %struct.anon*]*> [#uses=1] -@llvm.dbg.array23 = internal constant [2 x %struct.anon*] [ %struct.anon* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype14 to %struct.anon*), %struct.anon* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype19 to %struct.anon*) ], section "llvm.metadata" ; <[2 x %struct.anon*]*> [#uses=1] -@llvm.dbg.subrange24 = internal constant %llvm.dbg.subrange.type { - i32 393249, - i64 0, - i64 4 }, section "llvm.metadata" ; <%llvm.dbg.subrange.type*> [#uses=1] -@llvm.dbg.array25 = internal constant [1 x %struct.anon*] [ %struct.anon* bitcast (%llvm.dbg.subrange.type* @llvm.dbg.subrange24 to %struct.anon*) ], section "llvm.metadata" ; <[1 x %struct.anon*]*> [#uses=1] - -define i8* @var() { -entry: - %retval = alloca i8* ; [#uses=3] - %tmp = alloca i8* ; [#uses=2] - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - call void @llvm.dbg.func.start( %struct.anon* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to %struct.anon*) ) - call void @llvm.dbg.stoppoint( i32 2, i32 0, %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*) ) - %retval1 = bitcast i8** %retval to %struct.anon* ; <%struct.anon*> [#uses=1] - call void @llvm.dbg.declare( %struct.anon* %retval1, %struct.anon* bitcast (%llvm.dbg.variable.type* @llvm.dbg.variable to %struct.anon*) ) - bitcast %struct.S271* getelementptr ([0 x %struct.S271]* @a271, i32 0, i32 0) to i8* ; :0 [#uses=0] - store i8* bitcast ([0 x %struct.S271]* @a271 to i8*), i8** %tmp, align 4 - %tmp2 = load i8** %tmp, align 4 ; [#uses=1] - store i8* %tmp2, i8** %retval, align 4 - br label %return - -return: ; preds = %entry - %retval3 = load i8** %retval ; [#uses=1] - call void @llvm.dbg.stoppoint( i32 2, i32 0, %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*) ) - call void @llvm.dbg.region.end( %struct.anon* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to %struct.anon*) ) - ret i8* %retval3 -} - -declare void @llvm.dbg.func.start(%struct.anon*) nounwind - -declare void @llvm.dbg.stoppoint(i32, i32, %struct.anon*) nounwind - -declare void @llvm.dbg.declare(%struct.anon*, %struct.anon*) nounwind - -declare void @llvm.dbg.region.end(%struct.anon*) nounwind - -define i32 @main() { -entry: - %retval = alloca i32 ; [#uses=2] - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - call void @llvm.dbg.func.start( %struct.anon* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram6 to %struct.anon*) ) - call void @llvm.dbg.stoppoint( i32 3, i32 0, %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*) ) - %retval1 = bitcast i32* %retval to %struct.anon* ; <%struct.anon*> [#uses=1] - call void @llvm.dbg.declare( %struct.anon* %retval1, %struct.anon* bitcast (%llvm.dbg.variable.type* @llvm.dbg.variable10 to %struct.anon*) ) - br label %return - -return: ; preds = %entry - %retval2 = load i32* %retval ; [#uses=1] - call void @llvm.dbg.stoppoint( i32 3, i32 0, %struct.anon* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %struct.anon*) ) - call void @llvm.dbg.region.end( %struct.anon* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram6 to %struct.anon*) ) - ret i32 %retval2 -} diff --git a/test/DebugInfo/inheritance.ll b/test/DebugInfo/inheritance.ll new file mode 100644 index 0000000000..a689cb2281 --- /dev/null +++ b/test/DebugInfo/inheritance.ll @@ -0,0 +1,151 @@ +; RUN: llc %s -o /dev/null +; PR 2613. + +%struct.__class_type_info_pseudo = type { %struct.__type_info_pseudo } +%struct.__type_info_pseudo = type { i8*, i8* } +%struct.test1 = type { i32 (...)** } + +@_ZTV5test1 = weak_odr constant [4 x i32 (...)*] [i32 (...)* null, i32 (...)* bitcast (%struct.__class_type_info_pseudo* @_ZTI5test1 to i32 (...)*), i32 (...)* bitcast (void (%struct.test1*)* @_ZN5test1D1Ev to i32 (...)*), i32 (...)* bitcast (void (%struct.test1*)* @_ZN5test1D0Ev to i32 (...)*)], align 32 ; <[4 x i32 (...)*]*> [#uses=1] +@_ZTI5test1 = weak_odr constant %struct.__class_type_info_pseudo { %struct.__type_info_pseudo { i8* inttoptr (i64 add (i64 ptrtoint ([0 x i32 (...)*]* @_ZTVN10__cxxabiv117__class_type_infoE to i64), i64 16) to i8*), i8* getelementptr inbounds ([7 x i8]* @_ZTS5test1, i64 0, i64 0) } }, align 16 ; <%struct.__class_type_info_pseudo*> [#uses=1] +@_ZTVN10__cxxabiv117__class_type_infoE = external constant [0 x i32 (...)*] ; <[0 x i32 (...)*]*> [#uses=1] +@_ZTS5test1 = weak_odr constant [7 x i8] c"5test1\00" ; <[7 x i8]*> [#uses=2] + +define i32 @main() nounwind ssp { +entry: + %retval = alloca i32 ; [#uses=2] + %0 = alloca i32 ; [#uses=2] + %tst = alloca %struct.test1 ; <%struct.test1*> [#uses=1] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + call void @llvm.dbg.declare(metadata !{%struct.test1* %tst}, metadata !0), !dbg !21 + call void @_ZN5test1C1Ev(%struct.test1* %tst) nounwind, !dbg !22 + store i32 0, i32* %0, align 4, !dbg !23 + %1 = load i32* %0, align 4, !dbg !23 ; [#uses=1] + store i32 %1, i32* %retval, align 4, !dbg !23 + br label %return, !dbg !23 + +return: ; preds = %entry + %retval1 = load i32* %retval, !dbg !23 ; [#uses=1] + ret i32 %retval1, !dbg !23 +} + +define linkonce_odr void @_ZN5test1C1Ev(%struct.test1* %this) nounwind ssp align 2 { +entry: + %this_addr = alloca %struct.test1* ; <%struct.test1**> [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + call void @llvm.dbg.declare(metadata !{%struct.test1** %this_addr}, metadata !24), !dbg !28 + store %struct.test1* %this, %struct.test1** %this_addr + %0 = load %struct.test1** %this_addr, align 8, !dbg !28 ; <%struct.test1*> [#uses=1] + %1 = getelementptr inbounds %struct.test1* %0, i32 0, i32 0, !dbg !28 ; [#uses=1] + store i32 (...)** getelementptr inbounds ([4 x i32 (...)*]* @_ZTV5test1, i64 0, i64 2), i32 (...)*** %1, align 8, !dbg !28 + br label %return, !dbg !28 + +return: ; preds = %entry + ret void, !dbg !29 +} + +declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone + +define linkonce_odr void @_ZN5test1D1Ev(%struct.test1* %this) nounwind ssp align 2 { +entry: + %this_addr = alloca %struct.test1* ; <%struct.test1**> [#uses=3] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + call void @llvm.dbg.declare(metadata !{%struct.test1** %this_addr}, metadata !32), !dbg !34 + store %struct.test1* %this, %struct.test1** %this_addr + %0 = load %struct.test1** %this_addr, align 8, !dbg !35 ; <%struct.test1*> [#uses=1] + %1 = getelementptr inbounds %struct.test1* %0, i32 0, i32 0, !dbg !35 ; [#uses=1] + store i32 (...)** getelementptr inbounds ([4 x i32 (...)*]* @_ZTV5test1, i64 0, i64 2), i32 (...)*** %1, align 8, !dbg !35 + br label %bb, !dbg !37 + +bb: ; preds = %entry + %2 = trunc i32 0 to i8, !dbg !37 ; [#uses=1] + %toBool = icmp ne i8 %2, 0, !dbg !37 ; [#uses=1] + br i1 %toBool, label %bb1, label %bb2, !dbg !37 + +bb1: ; preds = %bb + %3 = load %struct.test1** %this_addr, align 8, !dbg !37 ; <%struct.test1*> [#uses=1] + %4 = bitcast %struct.test1* %3 to i8*, !dbg !37 ; [#uses=1] + call void @_ZdlPv(i8* %4) nounwind, !dbg !37 + br label %bb2, !dbg !37 + +bb2: ; preds = %bb1, %bb + br label %return, !dbg !37 + +return: ; preds = %bb2 + ret void, !dbg !37 +} + +define linkonce_odr void @_ZN5test1D0Ev(%struct.test1* %this) nounwind ssp align 2 { +entry: + %this_addr = alloca %struct.test1* ; <%struct.test1**> [#uses=3] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + call void @llvm.dbg.declare(metadata !{%struct.test1** %this_addr}, metadata !38), !dbg !40 + store %struct.test1* %this, %struct.test1** %this_addr + %0 = load %struct.test1** %this_addr, align 8, !dbg !41 ; <%struct.test1*> [#uses=1] + %1 = getelementptr inbounds %struct.test1* %0, i32 0, i32 0, !dbg !41 ; [#uses=1] + store i32 (...)** getelementptr inbounds ([4 x i32 (...)*]* @_ZTV5test1, i64 0, i64 2), i32 (...)*** %1, align 8, !dbg !41 + br label %bb, !dbg !43 + +bb: ; preds = %entry + %2 = trunc i32 1 to i8, !dbg !43 ; [#uses=1] + %toBool = icmp ne i8 %2, 0, !dbg !43 ; [#uses=1] + br i1 %toBool, label %bb1, label %bb2, !dbg !43 + +bb1: ; preds = %bb + %3 = load %struct.test1** %this_addr, align 8, !dbg !43 ; <%struct.test1*> [#uses=1] + %4 = bitcast %struct.test1* %3 to i8*, !dbg !43 ; [#uses=1] + call void @_ZdlPv(i8* %4) nounwind, !dbg !43 + br label %bb2, !dbg !43 + +bb2: ; preds = %bb1, %bb + br label %return, !dbg !43 + +return: ; preds = %bb2 + ret void, !dbg !43 +} + +declare void @_ZdlPv(i8*) nounwind + +!0 = metadata !{i32 459008, metadata !1, metadata !"tst", metadata !4, i32 13, metadata !8} ; [ DW_TAG_auto_variable ] +!1 = metadata !{i32 458763, metadata !2, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!2 = metadata !{i32 458763, metadata !3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!3 = metadata !{i32 458798, i32 0, metadata !4, metadata !"main", metadata !"main", metadata !"main", metadata !4, i32 11, metadata !5, i1 false, i1 true, i32 0, i32 0, null, i1 false} ; [ DW_TAG_subprogram ] +!4 = metadata !{i32 458769, i32 0, i32 4, metadata !"inheritance.cpp", metadata !"/tmp/", metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!5 = metadata !{i32 458773, metadata !4, metadata !"", metadata !4, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !6, i32 0, null} ; [ DW_TAG_subroutine_type ] +!6 = metadata !{metadata !7} +!7 = metadata !{i32 458788, metadata !4, metadata !"int", metadata !4, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] +!8 = metadata !{i32 458771, metadata !4, metadata !"test1", metadata !4, i32 1, i64 64, i64 64, i64 0, i32 0, null, metadata !9, i32 0, metadata !8} ; [ DW_TAG_structure_type ] +!9 = metadata !{metadata !10, metadata !14, metadata !18} +!10 = metadata !{i32 458765, metadata !8, metadata !"_vptr$test1", metadata !4, i32 1, i64 64, i64 64, i64 0, i32 0, metadata !11} ; [ DW_TAG_member ] +!11 = metadata !{i32 458767, metadata !4, metadata !"", metadata !4, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !12} ; [ DW_TAG_pointer_type ] +!12 = metadata !{i32 458767, metadata !4, metadata !"__vtbl_ptr_type", metadata !13, i32 0, i64 0, i64 0, i64 0, i32 0, metadata !5} ; [ DW_TAG_pointer_type ] +!13 = metadata !{i32 458769, i32 0, i32 4, metadata !"", metadata !"/tmp/", metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 false, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!14 = metadata !{i32 458798, i32 0, metadata !8, metadata !"test1", metadata !"test1", metadata !"", metadata !4, i32 1, metadata !15, i1 false, i1 false, i32 0, i32 0, null, i1 true} ; [ DW_TAG_subprogram ] +!15 = metadata !{i32 458773, metadata !4, metadata !"", metadata !4, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !16, i32 0, null} ; [ DW_TAG_subroutine_type ] +!16 = metadata !{null, metadata !17} +!17 = metadata !{i32 458767, metadata !4, metadata !"", metadata !4, i32 0, i64 64, i64 64, i64 0, i32 64, metadata !8} ; [ DW_TAG_pointer_type ] +!18 = metadata !{i32 458798, i32 0, metadata !8, metadata !"~test1", metadata !"~test1", metadata !"", metadata !4, i32 4, metadata !19, i1 false, i1 false, i32 1, i32 0, metadata !8, i1 false} ; [ DW_TAG_subprogram ] +!19 = metadata !{i32 458773, metadata !4, metadata !"", metadata !4, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !20, i32 0, null} ; [ DW_TAG_subroutine_type ] +!20 = metadata !{null, metadata !17, metadata !7} +!21 = metadata !{i32 11, i32 0, metadata !1, null} +!22 = metadata !{i32 13, i32 0, metadata !1, null} +!23 = metadata !{i32 14, i32 0, metadata !1, null} +!24 = metadata !{i32 459009, metadata !25, metadata !"this", metadata !4, i32 13, metadata !26} ; [ DW_TAG_arg_variable ] +!25 = metadata !{i32 458798, i32 0, metadata !4, metadata !"test1", metadata !"test1", metadata !"_ZN5test1C1Ev", metadata !4, i32 1, metadata !15, i1 false, i1 true, i32 0, i32 0, null, i1 false} ; [ DW_TAG_subprogram ] +!26 = metadata !{i32 458790, metadata !4, metadata !"", metadata !4, i32 0, i64 64, i64 64, i64 0, i32 64, metadata !27} ; [ DW_TAG_const_type ] +!27 = metadata !{i32 458767, metadata !4, metadata !"", metadata !4, i32 0, i64 64, i64 64, i64 0, i32 0, metadata !8} ; [ DW_TAG_pointer_type ] +!28 = metadata !{i32 1, i32 0, metadata !25, null} +!29 = metadata !{i32 1, i32 0, metadata !30, null} +!30 = metadata !{i32 458763, metadata !31, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!31 = metadata !{i32 458763, metadata !25, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!32 = metadata !{i32 459009, metadata !33, metadata !"this", metadata !4, i32 4, metadata !26} ; [ DW_TAG_arg_variable ] +!33 = metadata !{i32 458798, i32 0, metadata !8, metadata !"~test1", metadata !"~test1", metadata !"_ZN5test1D1Ev", metadata !4, i32 4, metadata !15, i1 false, i1 true, i32 1, i32 0, metadata !8, i1 false} ; [ DW_TAG_subprogram ] +!34 = metadata !{i32 4, i32 0, metadata !33, null} +!35 = metadata !{i32 5, i32 0, metadata !36, null} +!36 = metadata !{i32 458763, metadata !33, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!37 = metadata !{i32 6, i32 0, metadata !36, null} +!38 = metadata !{i32 459009, metadata !39, metadata !"this", metadata !4, i32 4, metadata !26} ; [ DW_TAG_arg_variable ] +!39 = metadata !{i32 458798, i32 0, metadata !8, metadata !"~test1", metadata !"~test1", metadata !"_ZN5test1D0Ev", metadata !4, i32 4, metadata !15, i1 false, i1 true, i32 1, i32 1, metadata !8, i1 false} ; [ DW_TAG_subprogram ] +!40 = metadata !{i32 4, i32 0, metadata !39, null} +!41 = metadata !{i32 5, i32 0, metadata !42, null} +!42 = metadata !{i32 458763, metadata !39, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!43 = metadata !{i32 6, i32 0, metadata !42, null} diff --git a/test/ExecutionEngine/2010-01-15-UndefValue.ll b/test/ExecutionEngine/2010-01-15-UndefValue.ll index 7d646ebdeb..33ca63a020 100644 --- a/test/ExecutionEngine/2010-01-15-UndefValue.ll +++ b/test/ExecutionEngine/2010-01-15-UndefValue.ll @@ -3,7 +3,7 @@ define i32 @main() { %a = add i32 0, undef - %b = add float 0.0, undef - %c = add double 0.0, undef + %b = fadd float 0.0, undef + %c = fadd double 0.0, undef ret i32 0 } diff --git a/test/Feature/alignment.ll b/test/Feature/alignment.ll index 409efebe84..ef35a1344a 100644 --- a/test/Feature/alignment.ll +++ b/test/Feature/alignment.ll @@ -19,3 +19,7 @@ define i32* @test2() { ret i32* %X } +define void @test3() alignstack(16) { + ret void +} + diff --git a/test/Feature/unions.ll b/test/Feature/unions.ll new file mode 100644 index 0000000000..9d6c36bb3c --- /dev/null +++ b/test/Feature/unions.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | llvm-dis > %t1.ll +; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll +; RUN: diff %t1.ll %t2.ll + +%union.anon = type union { i8, i32, float } + +@union1 = constant union { i32, i8 } { i32 4 } +@union2 = constant union { i32, i8 } insertvalue(union { i32, i8 } undef, i32 4, 0) + +define void @"Unions" () { + ret void +} diff --git a/test/FrontendC++/2010-02-08-NamespaceVar.cpp b/test/FrontendC++/2010-02-08-NamespaceVar.cpp deleted file mode 100644 index cd8247aeaa..0000000000 --- a/test/FrontendC++/2010-02-08-NamespaceVar.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// RUN: %llvmgxx -S %s -o - | grep cX - -namespace C { - int c = 1; - namespace { - int cX = 6; - void marker2() { - cX; - } - } -} - -int main() { - C::marker2(); - return 0; -} diff --git a/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp b/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp new file mode 100644 index 0000000000..4c8e0e5509 --- /dev/null +++ b/test/FrontendC++/2010-02-17-DbgArtificialArg.cpp @@ -0,0 +1,14 @@ +// RUN: %llvmgcc -g -S %s -o - | grep DW_TAG_pointer_type | grep "i32 458767, metadata .., metadata ..., metadata .., i32 ., i64 .., i64 .., i64 0, i32 64, metadata ..." +// Here, second to last argument "i32 64" indicates that artificial type is set. +// Test to artificial attribute attahed to "this" pointer type. +// Radar 7655792 and 7655002 + +class A { +public: + int fn1(int i) const { return i + 2; }; +}; + +int foo() { + A a; + return a.fn1(1); +} diff --git a/test/FrontendC/2003-12-14-ExternInlineSupport.c b/test/FrontendC/2003-12-14-ExternInlineSupport.c index 510d1f800f..fb92ec773c 100644 --- a/test/FrontendC/2003-12-14-ExternInlineSupport.c +++ b/test/FrontendC/2003-12-14-ExternInlineSupport.c @@ -1,3 +1,3 @@ -// RUN: %llvmgcc -Os -xc %s -c -o - | llvm-dis | not grep dead_function +// RUN: %llvmgcc -xc %s -c -o - | llvm-dis | not grep dead_function extern __inline__ void dead_function() {} diff --git a/test/FrontendC/2007-02-16-WritableStrings.c b/test/FrontendC/2007-02-16-WritableStrings.c index 811e3301f8..0f281ce7c5 100644 --- a/test/FrontendC/2007-02-16-WritableStrings.c +++ b/test/FrontendC/2007-02-16-WritableStrings.c @@ -1,7 +1,7 @@ // Test the -fwritable-strings option. // RUN: %llvmgcc -O3 -S -o - -emit-llvm -fwritable-strings %s | \ -// RUN: grep {private global} +// RUN: grep {internal global} // RUN: %llvmgcc -O3 -S -o - -emit-llvm %s | grep {private constant} char *X = "foo"; diff --git a/test/FrontendC/2007-09-17-WeakRef.c b/test/FrontendC/2007-09-17-WeakRef.c index 3cdd47e4e0..6c420ea38a 100644 --- a/test/FrontendC/2007-09-17-WeakRef.c +++ b/test/FrontendC/2007-09-17-WeakRef.c @@ -1,6 +1,6 @@ // RUN: %llvmgcc -O1 -S %s -o - | grep icmp // PR1678 -// XFAIL: llvmgcc4.0.1 + extern void B (void); static __typeof(B) A __attribute__ ((__weakref__("B"))); int active (void) diff --git a/test/FrontendC/2010-02-10-PointerName.c b/test/FrontendC/2010-02-10-PointerName.c new file mode 100644 index 0000000000..7880fa8345 --- /dev/null +++ b/test/FrontendC/2010-02-10-PointerName.c @@ -0,0 +1,7 @@ +// RUN: %llvmgcc %s -S -g -o - | grep DW_TAG_pointer_type | grep -v char + +char i = 1; +void foo() { + char *cp = &i; +} + diff --git a/test/FrontendC/2010-02-15-DbgStaticVar.c b/test/FrontendC/2010-02-15-DbgStaticVar.c new file mode 100644 index 0000000000..7827d96ce6 --- /dev/null +++ b/test/FrontendC/2010-02-15-DbgStaticVar.c @@ -0,0 +1,13 @@ +// RUN: %llvmgcc -g -S %s -o - | grep "metadata ..b., metadata ..b., metadata ...," +// Test to check intentionally empty linkage name for a static variable. +// Radar 7651244. +static int foo(int a) +{ + static int b = 1; + return b+a; +} + +int main() { + int j = foo(1); + return 0; +} diff --git a/test/FrontendC/2010-02-16-DbgVarScope.c b/test/FrontendC/2010-02-16-DbgVarScope.c new file mode 100644 index 0000000000..1d912d0f5e --- /dev/null +++ b/test/FrontendC/2010-02-16-DbgVarScope.c @@ -0,0 +1,30 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | \ +// RUN: llc --disable-fp-elim -o %t.s -O0 -relocation-model=pic +// RUN: %compile_c %t.s -o %t.o +// RUN: %link %t.o -o %t.exe +// RUN: echo {break 24\nrun\np loc\n} > %t.in +// RN: gdb -q -batch -n -x %t.in %t.exe | tee %t.out | \ +// RN: grep {$1 = 1} + +int g1 = 1; +int g2 = 2; + +int __attribute__((always_inline)) bar() { + return g2 - g1; +} +void foobar() {} + +void foo(int s) { + unsigned loc = 0; + if (s) { + loc = 1; + foobar(); + } else { + loc = bar(); + foobar(); + } +} + +int main() { + foo(0); +} diff --git a/test/FrontendC/2010-02-18-Dbg-VectorType.c b/test/FrontendC/2010-02-18-Dbg-VectorType.c new file mode 100644 index 0000000000..d34031f09a --- /dev/null +++ b/test/FrontendC/2010-02-18-Dbg-VectorType.c @@ -0,0 +1,9 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | grep DW_TAG_typedef | grep float4 +typedef float float4 __attribute__((vector_size(16))); + +int main(){ + volatile float4 x = (float4) { 0.0f, 1.0f, 2.0f, 3.0f }; + x += x; + return 0; +} + diff --git a/test/FrontendC/2010-03-5-LexicalScope.c b/test/FrontendC/2010-03-5-LexicalScope.c new file mode 100644 index 0000000000..93a841a8f2 --- /dev/null +++ b/test/FrontendC/2010-03-5-LexicalScope.c @@ -0,0 +1,10 @@ +// RUN: %llvmgcc -S -O0 -g %s -o - | grep DW_TAG_lexical_block | count 3 +int foo(int i) { + if (i) { + int j = 2; + } + else { + int j = 3; + } + return i; +} diff --git a/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m b/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m new file mode 100644 index 0000000000..13e16312cf --- /dev/null +++ b/test/FrontendObjC/2010-02-11-fwritable-stringsBug.m @@ -0,0 +1,17 @@ +// RUN: %llvmgcc -x objective-c -fwritable-strings -S %s -o - | FileCheck %s +// CHECK: @.str = private constant +// CHECK: @.str1 = internal global + +// rdar://7634471 + +@class NSString; + +@interface A +- (void)foo:(NSString*)msg; +- (void)bar:(const char*)msg; +@end + +void func(A *a) { + [a foo:@"Hello world!"]; + [a bar:"Goodbye world!"]; +} diff --git a/test/FrontendObjC/2010-02-23-DbgInheritance.m b/test/FrontendObjC/2010-02-23-DbgInheritance.m new file mode 100644 index 0000000000..7e1cf67b47 --- /dev/null +++ b/test/FrontendObjC/2010-02-23-DbgInheritance.m @@ -0,0 +1,9 @@ +// RUN: %llvmgcc %s -S -g -o - | grep -v DW_TAG_member +// Interface P should not be a member of interface I in debug info. +@interface P +@end + +@interface I : P +@end + +void fn(I *iptr) {} diff --git a/test/LLVMC/AppendCmdHook.td b/test/LLVMC/AppendCmdHook.td index 4a9d39121a..539a93f834 100644 --- a/test/LLVMC/AppendCmdHook.td +++ b/test/LLVMC/AppendCmdHook.td @@ -13,14 +13,14 @@ def OptList : OptionList<[ ]>; def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy_lang"), (out_language "dummy_lang"), (actions (case - // CHECK: push_back("-arg1") - // CHECK: push_back("-arg2") + // CHECK: , "-arg1")); + // CHECK: , "-arg2")); (switch_on "dummy1"), (append_cmd "-arg1 -arg2"), - // CHECK: push_back("-arg3") + // CHECK: , "-arg3")); // CHECK: hooks::MyHook() (switch_on "dummy2"), (append_cmd "-arg3 $CALL(MyHook)"))) ]>; diff --git a/test/LLVMC/EnvParentheses.td b/test/LLVMC/EnvParentheses.td index 77aab95c5f..c563171335 100644 --- a/test/LLVMC/EnvParentheses.td +++ b/test/LLVMC/EnvParentheses.td @@ -1,13 +1,13 @@ // Check the fix for PR4157. // http://llvm.org/bugs/show_bug.cgi?id=4157 // RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t -// RUN: not grep {)));} %t +// RUN: not grep {FOO")));} %t // RUN: %compile_cxx -fexceptions -x c++ %t include "llvm/CompilerDriver/Common.td" def dummy_tool : Tool<[ -(cmd_line "gcc -o $OUTFILE $INFILE $ENV(FOO)/bar"), +(command "gcc $ENV(FOO)/bar"), (in_language "dummy"), (out_language "dummy") ]>; diff --git a/test/LLVMC/ExternOptions.td b/test/LLVMC/ExternOptions.td index a05f2ca15b..77cb4bf652 100644 --- a/test/LLVMC/ExternOptions.td +++ b/test/LLVMC/ExternOptions.td @@ -13,7 +13,7 @@ def OptList : OptionList<[(switch_option "Wall", (extern)), (prefix_list_option "L", (extern))]>; def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy"), (out_language "dummy"), (actions (case diff --git a/test/LLVMC/ForwardAs.td b/test/LLVMC/ForwardAs.td index ce6fbb06ef..7c3bd1798a 100644 --- a/test/LLVMC/ForwardAs.td +++ b/test/LLVMC/ForwardAs.td @@ -9,11 +9,11 @@ include "llvm/CompilerDriver/Common.td" def OptList : OptionList<[(parameter_option "dummy", (extern))]>; def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy"), (out_language "dummy"), (actions (case - // CHECK: vec.push_back("unique_name") + // CHECK: "unique_name")); (not_empty "dummy"), (forward_as "dummy", "unique_name"))) ]>; diff --git a/test/LLVMC/ForwardTransformedValue.td b/test/LLVMC/ForwardTransformedValue.td index e26345362c..2caef6cd53 100644 --- a/test/LLVMC/ForwardTransformedValue.td +++ b/test/LLVMC/ForwardTransformedValue.td @@ -13,7 +13,7 @@ def OptList : OptionList<[(parameter_option "a", (extern)), // CHECK: std::string HookB def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy"), (out_language "dummy"), (actions (case diff --git a/test/LLVMC/ForwardValue.td b/test/LLVMC/ForwardValue.td index 31e395e6d0..463235c611 100644 --- a/test/LLVMC/ForwardValue.td +++ b/test/LLVMC/ForwardValue.td @@ -10,13 +10,13 @@ def OptList : OptionList<[(parameter_option "a", (extern)), (prefix_list_option "b", (extern))]>; def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy"), (out_language "dummy"), (actions (case - // CHECK: vec.push_back(AutoGeneratedParameter_a) + // CHECK: , AutoGeneratedParameter_a)); (not_empty "a"), (forward_value "a"), - // CHECK: std::copy(AutoGeneratedList_b.begin() + // CHECK: B = AutoGeneratedList_b.begin() (not_empty "b"), (forward_value "b"))) ]>; diff --git a/test/LLVMC/HookWithArguments.td b/test/LLVMC/HookWithArguments.td index ba0bbe10d3..312fa9cceb 100644 --- a/test/LLVMC/HookWithArguments.td +++ b/test/LLVMC/HookWithArguments.td @@ -6,12 +6,12 @@ include "llvm/CompilerDriver/Common.td" // CHECK: Hook(const char* Arg0, const char* Arg1, const char* Arg2); +// CHECK: "/path" // CHECK: std::getenv("VARIABLE") // CHECK: "/2path" -// CHECK: "/path" def dummy_tool : Tool<[ -(cmd_line "$CALL(Hook, 'Arg1', 'Arg2', 'Arg3 Arg3Cont')/path arg1 $ENV(VARIABLE)/2path arg2 $INFILE"), +(command "$CALL(Hook, 'Arg1', 'Arg2', 'Arg3 Arg3Cont')/path arg1 $ENV(VARIABLE)/2path arg2"), (in_language "dummy"), (out_language "dummy") ]>; diff --git a/test/LLVMC/HookWithInFile.td b/test/LLVMC/HookWithInFile.td index e15e43cdf0..f58e3f4288 100644 --- a/test/LLVMC/HookWithInFile.td +++ b/test/LLVMC/HookWithInFile.td @@ -7,7 +7,7 @@ include "llvm/CompilerDriver/Common.td" def dummy_tool : Tool<[ // CHECK: Hook(inFile.c_str()) -(cmd_line "$CALL(Hook, '$INFILE')/path $INFILE"), +(command "$CALL(Hook, '$INFILE')/path"), (in_language "dummy"), (out_language "dummy") ]>; diff --git a/test/LLVMC/Init.td b/test/LLVMC/Init.td index 355d83ff95..ff9a0d8d90 100644 --- a/test/LLVMC/Init.td +++ b/test/LLVMC/Init.td @@ -13,7 +13,7 @@ def OptList : OptionList<[ ]>; def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy_lang"), (out_language "dummy_lang"), (actions (case diff --git a/test/LLVMC/MultiValuedOption.td b/test/LLVMC/MultiValuedOption.td index 8cb1878270..b52af57ade 100644 --- a/test/LLVMC/MultiValuedOption.td +++ b/test/LLVMC/MultiValuedOption.td @@ -12,7 +12,7 @@ def OptList : OptionList<[ (parameter_list_option "baz", (multi_val 2), (extern))]>; def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy"), (out_language "dummy"), (actions (case diff --git a/test/LLVMC/MultiplePluginPriorities.td b/test/LLVMC/MultiplePluginPriorities.td index f1086418f1..2fe06450ee 100644 --- a/test/LLVMC/MultiplePluginPriorities.td +++ b/test/LLVMC/MultiplePluginPriorities.td @@ -4,6 +4,10 @@ // Disable for Darwin PPC: // XFAIL: powerpc-apple-darwin +// Generally XFAIL'ed for now, this is (sometimes?) failing on x86_64-apple-darwin10. +// RUN: false +// XFAIL: * + include "llvm/CompilerDriver/Common.td" def Graph : CompilationGraph<[]>; diff --git a/test/LLVMC/NoActions.td b/test/LLVMC/NoActions.td index 9c2d45a810..015bfdd097 100644 --- a/test/LLVMC/NoActions.td +++ b/test/LLVMC/NoActions.td @@ -7,7 +7,7 @@ include "llvm/CompilerDriver/Common.td" // CHECK: class dummy_tool : public Tool { def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy"), (out_language "dummy") ]>; diff --git a/test/LLVMC/OneOrMore.td b/test/LLVMC/OneOrMore.td index ddf7cd1143..42ec693fbb 100644 --- a/test/LLVMC/OneOrMore.td +++ b/test/LLVMC/OneOrMore.td @@ -13,7 +13,7 @@ def OptList : OptionList<[ (parameter_list_option "baz", (optional))]>; def dummy_tool : Tool<[ -(cmd_line "dummy_cmd $INFILE"), +(command "dummy_cmd"), (in_language "dummy"), (out_language "dummy"), (actions (case diff --git a/test/LLVMC/OptionPreprocessor.td b/test/LLVMC/OptionPreprocessor.td index 8d748eee53..8a314818a0 100644 --- a/test/LLVMC/OptionPreprocessor.td +++ b/test/LLVMC/OptionPreprocessor.td @@ -52,7 +52,7 @@ def dummy : Tool< [(in_language "dummy"), (out_language "dummy"), (output_suffix "d"), - (cmd_line "dummy $INFILE -o $OUTFILE"), + (command "dummy"), (actions (case (switch_on "foo"), (error), (switch_on "bar"), (error), (switch_on "baz"), (error), diff --git a/test/MC/AsmParser/X86/x86_32-bit_cat.s b/test/MC/AsmParser/X86/x86_32-bit_cat.s index f610b13c68..f0c7804d97 100644 --- a/test/MC/AsmParser/X86/x86_32-bit_cat.s +++ b/test/MC/AsmParser/X86/x86_32-bit_cat.s @@ -1,7 +1,7 @@ // This is the current set of tests that can pass though llvm-mc as it were a // logical cat(1) and then reassemble to the same instruction. All of these // will not yet encode correctly. The subset that will encode correctly are in -// the file x86_32-bit.s . +// the file x86_32-encoding.s (and other tests that encode are in x86_32-bit.s). // RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s @@ -1103,6 +1103,48 @@ // CHECK: rcrb $127, 305419896 rcrb $0x7f,0x12345678 +// CHECK: shll $0, 3735928559(%ebx,%ecx,8) + sall $0,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shll $0, 69 + sall $0,0x45 + +// CHECK: shll $0, 32493 + sall $0,0x7eed + +// CHECK: shll $0, 3133065982 + sall $0,0xbabecafe + +// CHECK: shll $0, 305419896 + sall $0,0x12345678 + +// CHECK: shlb $127, 3735928559(%ebx,%ecx,8) + salb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shlb $127, 69 + salb $0x7f,0x45 + +// CHECK: shlb $127, 32493 + salb $0x7f,0x7eed + +// CHECK: shlb $127, 3133065982 + salb $0x7f,0xbabecafe + +// CHECK: shlb $127, 305419896 + salb $0x7f,0x12345678 + +// CHECK: shll 3735928559(%ebx,%ecx,8) + sall 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shlw 32493 + salw 0x7eed + +// CHECK: shll 3133065982 + sall 0xbabecafe + +// CHECK: shll 305419896 + sall 0x12345678 + // CHECK: shll $0, 3735928559(%ebx,%ecx,8) shll $0,0xdeadbeef(%ebx,%ecx,8) @@ -1826,6 +1868,9 @@ // CHECK: verw 305419896 verw 0x12345678 +// CHECK: fld %st(2) + fld %st(2) + // CHECK: fldl 3735928559(%ebx,%ecx,8) fldl 0xdeadbeef(%ebx,%ecx,8) @@ -1835,6 +1880,9 @@ // CHECK: fldl 305419896 fldl 0x12345678 +// CHECK: fld %st(2) + fld %st(2) + // CHECK: fildl 3735928559(%ebx,%ecx,8) fildl 0xdeadbeef(%ebx,%ecx,8) @@ -1880,6 +1928,9 @@ // CHECK: fbld 305419896 fbld 0x12345678 +// CHECK: fst %st(2) + fst %st(2) + // CHECK: fstl 3735928559(%ebx,%ecx,8) fstl 0xdeadbeef(%ebx,%ecx,8) @@ -1889,6 +1940,9 @@ // CHECK: fstl 305419896 fstl 0x12345678 +// CHECK: fst %st(2) + fst %st(2) + // CHECK: fistl 3735928559(%ebx,%ecx,8) fistl 0xdeadbeef(%ebx,%ecx,8) @@ -1898,6 +1952,9 @@ // CHECK: fistl 305419896 fistl 0x12345678 +// CHECK: fstp %st(2) + fstp %st(2) + // CHECK: fstpl 3735928559(%ebx,%ecx,8) fstpl 0xdeadbeef(%ebx,%ecx,8) @@ -1907,6 +1964,9 @@ // CHECK: fstpl 305419896 fstpl 0x12345678 +// CHECK: fstp %st(2) + fstp %st(2) + // CHECK: fistpl 3735928559(%ebx,%ecx,8) fistpl 0xdeadbeef(%ebx,%ecx,8) @@ -1952,6 +2012,12 @@ // CHECK: fbstp 305419896 fbstp 0x12345678 +// CHECK: fxch %st(2) + fxch %st(2) + +// CHECK: fcom %st(2) + fcom %st(2) + // CHECK: fcoml 3735928559(%ebx,%ecx,8) fcoml 0xdeadbeef(%ebx,%ecx,8) @@ -1961,6 +2027,9 @@ // CHECK: fcoml 305419896 fcoml 0x12345678 +// CHECK: fcom %st(2) + fcom %st(2) + // CHECK: ficoml 3735928559(%ebx,%ecx,8) ficoml 0xdeadbeef(%ebx,%ecx,8) @@ -1970,6 +2039,9 @@ // CHECK: ficoml 305419896 ficoml 0x12345678 +// CHECK: fcomp %st(2) + fcomp %st(2) + // CHECK: fcompl 3735928559(%ebx,%ecx,8) fcompl 0xdeadbeef(%ebx,%ecx,8) @@ -1979,6 +2051,9 @@ // CHECK: fcompl 305419896 fcompl 0x12345678 +// CHECK: fcomp %st(2) + fcomp %st(2) + // CHECK: ficompl 3735928559(%ebx,%ecx,8) ficompl 0xdeadbeef(%ebx,%ecx,8) @@ -1991,6 +2066,12 @@ // CHECK: fcompp fcompp +// CHECK: fucom %st(2) + fucom %st(2) + +// CHECK: fucomp %st(2) + fucomp %st(2) + // CHECK: fucompp fucompp @@ -2021,6 +2102,9 @@ // CHECK: fldz fldz +// CHECK: fadd %st(2) + fadd %st(2) + // CHECK: faddl 3735928559(%ebx,%ecx,8) faddl 0xdeadbeef(%ebx,%ecx,8) @@ -2039,6 +2123,12 @@ // CHECK: fiaddl 305419896 fiaddl 0x12345678 +// CHECK: faddp %st(2) + faddp %st(2) + +// CHECK: fsub %st(2) + fsub %st(2) + // CHECK: fsubl 3735928559(%ebx,%ecx,8) fsubl 0xdeadbeef(%ebx,%ecx,8) @@ -2057,6 +2147,12 @@ // CHECK: fisubl 305419896 fisubl 0x12345678 +// CHECK: fsubp %st(2) + fsubp %st(2) + +// CHECK: fsubr %st(2) + fsubr %st(2) + // CHECK: fsubrl 3735928559(%ebx,%ecx,8) fsubrl 0xdeadbeef(%ebx,%ecx,8) @@ -2075,6 +2171,12 @@ // CHECK: fisubrl 305419896 fisubrl 0x12345678 +// CHECK: fsubrp %st(2) + fsubrp %st(2) + +// CHECK: fmul %st(2) + fmul %st(2) + // CHECK: fmull 3735928559(%ebx,%ecx,8) fmull 0xdeadbeef(%ebx,%ecx,8) @@ -2093,6 +2195,12 @@ // CHECK: fimull 305419896 fimull 0x12345678 +// CHECK: fmulp %st(2) + fmulp %st(2) + +// CHECK: fdiv %st(2) + fdiv %st(2) + // CHECK: fdivl 3735928559(%ebx,%ecx,8) fdivl 0xdeadbeef(%ebx,%ecx,8) @@ -2111,6 +2219,12 @@ // CHECK: fidivl 305419896 fidivl 0x12345678 +// CHECK: fdivp %st(2) + fdivp %st(2) + +// CHECK: fdivr %st(2) + fdivr %st(2) + // CHECK: fdivrl 3735928559(%ebx,%ecx,8) fdivrl 0xdeadbeef(%ebx,%ecx,8) @@ -2129,6 +2243,9 @@ // CHECK: fidivrl 305419896 fidivrl 0x12345678 +// CHECK: fdivrp %st(2) + fdivrp %st(2) + // CHECK: f2xm1 f2xm1 @@ -2228,6 +2345,9 @@ // CHECK: frstor 32493 frstor 0x7eed +// CHECK: ffree %st(2) + ffree %st(2) + // CHECK: fnop fnop @@ -2297,6 +2417,42 @@ // CHECK: ud2 ud2 +// CHECK: fcmovb %st(2), %st(0) + fcmovb %st(2),%st + +// CHECK: fcmove %st(2), %st(0) + fcmove %st(2),%st + +// CHECK: fcmovbe %st(2), %st(0) + fcmovbe %st(2),%st + +// CHECK: fcmovu %st(2), %st(0) + fcmovu %st(2),%st + +// CHECK: fcmovnb %st(2), %st(0) + fcmovnb %st(2),%st + +// CHECK: fcmovne %st(2), %st(0) + fcmovne %st(2),%st + +// CHECK: fcmovnbe %st(2), %st(0) + fcmovnbe %st(2),%st + +// CHECK: fcmovnu %st(2), %st(0) + fcmovnu %st(2),%st + +// CHECK: fcomi %st(2), %st(0) + fcomi %st(2),%st + +// CHECK: fucomi %st(2), %st(0) + fucomi %st(2),%st + +// CHECK: fcomip %st(2), %st(0) + fcomip %st(2),%st + +// CHECK: fucomip %st(2), %st(0) + fucomip %st(2),%st + // CHECK: movnti %ecx, 3735928559(%ebx,%ecx,8) movnti %ecx,0xdeadbeef(%ebx,%ecx,8) diff --git a/test/MC/AsmParser/X86/x86_32-encoding.s b/test/MC/AsmParser/X86/x86_32-encoding.s index e029ded0d1..e325bdd169 100644 --- a/test/MC/AsmParser/X86/x86_32-encoding.s +++ b/test/MC/AsmParser/X86/x86_32-encoding.s @@ -1,13 +1,9861 @@ -// RUN: llvm-mc -triple i386-unknown-unknown %s -show-encoding | FileCheck %s +// RUN: llvm-mc -triple i386-unknown-unknown --show-encoding %s | FileCheck %s -fisttpl 3735928559(%ebx,%ecx,8) -# CHECK: encoding: [0xdb,0x8c,0xcb,0xef,0xbe,0xad,0xde] +// CHECK: movb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc6,0x84,0xcb,0xef,0xbe,0xad,0xde,0x7f] + movb $0x7f,0xdeadbeef(%ebx,%ecx,8) -sbbb $0xfe,0xdeadbeef(%ebx,%ecx,8) -# CHECK: encoding: [0x80,0x9c,0xcb,0xef,0xbe,0xad,0xde,0xfe] +// CHECK: movb $127, 69 +// CHECK: encoding: [0xc6,0x05,0x45,0x00,0x00,0x00,0x7f] + movb $0x7f,0x45 -psllw 69, %mm3 -# CHECK: encoding: [0x0f,0xf1,0x1d,0x45,0x00,0x00,0x00] +// CHECK: movb $127, 32493 +// CHECK: encoding: [0xc6,0x05,0xed,0x7e,0x00,0x00,0x7f] + movb $0x7f,0x7eed -movntdqa 0xdeadbeef(%ebx,%ecx,8),%xmm5 -# CHECK: encoding: [0x66,0x0f,0x38,0x2a,0xac,0xcb,0xef,0xbe,0xad,0xde] +// CHECK: movb $127, 3133065982 +// CHECK: encoding: [0xc6,0x05,0xfe,0xca,0xbe,0xba,0x7f] + movb $0x7f,0xbabecafe + +// CHECK: movb $127, 305419896 +// CHECK: encoding: [0xc6,0x05,0x78,0x56,0x34,0x12,0x7f] + movb $0x7f,0x12345678 + +// CHECK: movw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0xc7,0x84,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + movw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movw $31438, 69 +// CHECK: encoding: [0x66,0xc7,0x05,0x45,0x00,0x00,0x00,0xce,0x7a] + movw $0x7ace,0x45 + +// CHECK: movw $31438, 32493 +// CHECK: encoding: [0x66,0xc7,0x05,0xed,0x7e,0x00,0x00,0xce,0x7a] + movw $0x7ace,0x7eed + +// CHECK: movw $31438, 3133065982 +// CHECK: encoding: [0x66,0xc7,0x05,0xfe,0xca,0xbe,0xba,0xce,0x7a] + movw $0x7ace,0xbabecafe + +// CHECK: movw $31438, 305419896 +// CHECK: encoding: [0x66,0xc7,0x05,0x78,0x56,0x34,0x12,0xce,0x7a] + movw $0x7ace,0x12345678 + +// CHECK: movl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc7,0x84,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + movl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movl $2063514302, 69 +// CHECK: encoding: [0xc7,0x05,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + movl $0x7afebabe,0x45 + +// CHECK: movl $2063514302, 32493 +// CHECK: encoding: [0xc7,0x05,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + movl $0x7afebabe,0x7eed + +// CHECK: movl $2063514302, 3133065982 +// CHECK: encoding: [0xc7,0x05,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + movl $0x7afebabe,0xbabecafe + +// CHECK: movl $2063514302, 305419896 +// CHECK: encoding: [0xc7,0x05,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + movl $0x7afebabe,0x12345678 + +// CHECK: movl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc7,0x84,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + movl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movl $324478056, 69 +// CHECK: encoding: [0xc7,0x05,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + movl $0x13572468,0x45 + +// CHECK: movl $324478056, 32493 +// CHECK: encoding: [0xc7,0x05,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + movl $0x13572468,0x7eed + +// CHECK: movl $324478056, 3133065982 +// CHECK: encoding: [0xc7,0x05,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + movl $0x13572468,0xbabecafe + +// CHECK: movl $324478056, 305419896 +// CHECK: encoding: [0xc7,0x05,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + movl $0x13572468,0x12345678 + +// CHECK: movsbl 3735928559(%ebx,%ecx,8), %ecx +// CHECK: encoding: [0x0f,0xbe,0x8c,0xcb,0xef,0xbe,0xad,0xde] + movsbl 0xdeadbeef(%ebx,%ecx,8),%ecx + +// CHECK: movsbl 69, %ecx +// CHECK: encoding: [0x0f,0xbe,0x0d,0x45,0x00,0x00,0x00] + movsbl 0x45,%ecx + +// CHECK: movsbl 32493, %ecx +// CHECK: encoding: [0x0f,0xbe,0x0d,0xed,0x7e,0x00,0x00] + movsbl 0x7eed,%ecx + +// CHECK: movsbl 3133065982, %ecx +// CHECK: encoding: [0x0f,0xbe,0x0d,0xfe,0xca,0xbe,0xba] + movsbl 0xbabecafe,%ecx + +// CHECK: movsbl 305419896, %ecx +// CHECK: encoding: [0x0f,0xbe,0x0d,0x78,0x56,0x34,0x12] + movsbl 0x12345678,%ecx + +// CHECK: movsbw 3735928559(%ebx,%ecx,8), %bx +// CHECK: encoding: [0x66,0x0f,0xbe,0x9c,0xcb,0xef,0xbe,0xad,0xde] + movsbw 0xdeadbeef(%ebx,%ecx,8),%bx + +// CHECK: movsbw 69, %bx +// CHECK: encoding: [0x66,0x0f,0xbe,0x1d,0x45,0x00,0x00,0x00] + movsbw 0x45,%bx + +// CHECK: movsbw 32493, %bx +// CHECK: encoding: [0x66,0x0f,0xbe,0x1d,0xed,0x7e,0x00,0x00] + movsbw 0x7eed,%bx + +// CHECK: movsbw 3133065982, %bx +// CHECK: encoding: [0x66,0x0f,0xbe,0x1d,0xfe,0xca,0xbe,0xba] + movsbw 0xbabecafe,%bx + +// CHECK: movsbw 305419896, %bx +// CHECK: encoding: [0x66,0x0f,0xbe,0x1d,0x78,0x56,0x34,0x12] + movsbw 0x12345678,%bx + +// CHECK: movswl 3735928559(%ebx,%ecx,8), %ecx +// CHECK: encoding: [0x0f,0xbf,0x8c,0xcb,0xef,0xbe,0xad,0xde] + movswl 0xdeadbeef(%ebx,%ecx,8),%ecx + +// CHECK: movswl 69, %ecx +// CHECK: encoding: [0x0f,0xbf,0x0d,0x45,0x00,0x00,0x00] + movswl 0x45,%ecx + +// CHECK: movswl 32493, %ecx +// CHECK: encoding: [0x0f,0xbf,0x0d,0xed,0x7e,0x00,0x00] + movswl 0x7eed,%ecx + +// CHECK: movswl 3133065982, %ecx +// CHECK: encoding: [0x0f,0xbf,0x0d,0xfe,0xca,0xbe,0xba] + movswl 0xbabecafe,%ecx + +// CHECK: movswl 305419896, %ecx +// CHECK: encoding: [0x0f,0xbf,0x0d,0x78,0x56,0x34,0x12] + movswl 0x12345678,%ecx + +// CHECK: movzbl 3735928559(%ebx,%ecx,8), %ecx +// CHECK: encoding: [0x0f,0xb6,0x8c,0xcb,0xef,0xbe,0xad,0xde] + movzbl 0xdeadbeef(%ebx,%ecx,8),%ecx + +// CHECK: movzbl 69, %ecx +// CHECK: encoding: [0x0f,0xb6,0x0d,0x45,0x00,0x00,0x00] + movzbl 0x45,%ecx + +// CHECK: movzbl 32493, %ecx +// CHECK: encoding: [0x0f,0xb6,0x0d,0xed,0x7e,0x00,0x00] + movzbl 0x7eed,%ecx + +// CHECK: movzbl 3133065982, %ecx +// CHECK: encoding: [0x0f,0xb6,0x0d,0xfe,0xca,0xbe,0xba] + movzbl 0xbabecafe,%ecx + +// CHECK: movzbl 305419896, %ecx +// CHECK: encoding: [0x0f,0xb6,0x0d,0x78,0x56,0x34,0x12] + movzbl 0x12345678,%ecx + +// CHECK: movzbw 3735928559(%ebx,%ecx,8), %bx +// CHECK: encoding: [0x66,0x0f,0xb6,0x9c,0xcb,0xef,0xbe,0xad,0xde] + movzbw 0xdeadbeef(%ebx,%ecx,8),%bx + +// CHECK: movzbw 69, %bx +// CHECK: encoding: [0x66,0x0f,0xb6,0x1d,0x45,0x00,0x00,0x00] + movzbw 0x45,%bx + +// CHECK: movzbw 32493, %bx +// CHECK: encoding: [0x66,0x0f,0xb6,0x1d,0xed,0x7e,0x00,0x00] + movzbw 0x7eed,%bx + +// CHECK: movzbw 3133065982, %bx +// CHECK: encoding: [0x66,0x0f,0xb6,0x1d,0xfe,0xca,0xbe,0xba] + movzbw 0xbabecafe,%bx + +// CHECK: movzbw 305419896, %bx +// CHECK: encoding: [0x66,0x0f,0xb6,0x1d,0x78,0x56,0x34,0x12] + movzbw 0x12345678,%bx + +// CHECK: movzwl 3735928559(%ebx,%ecx,8), %ecx +// CHECK: encoding: [0x0f,0xb7,0x8c,0xcb,0xef,0xbe,0xad,0xde] + movzwl 0xdeadbeef(%ebx,%ecx,8),%ecx + +// CHECK: movzwl 69, %ecx +// CHECK: encoding: [0x0f,0xb7,0x0d,0x45,0x00,0x00,0x00] + movzwl 0x45,%ecx + +// CHECK: movzwl 32493, %ecx +// CHECK: encoding: [0x0f,0xb7,0x0d,0xed,0x7e,0x00,0x00] + movzwl 0x7eed,%ecx + +// CHECK: movzwl 3133065982, %ecx +// CHECK: encoding: [0x0f,0xb7,0x0d,0xfe,0xca,0xbe,0xba] + movzwl 0xbabecafe,%ecx + +// CHECK: movzwl 305419896, %ecx +// CHECK: encoding: [0x0f,0xb7,0x0d,0x78,0x56,0x34,0x12] + movzwl 0x12345678,%ecx + +// CHECK: pushl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xff,0xb4,0xcb,0xef,0xbe,0xad,0xde] + pushl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: pushw 32493 +// CHECK: encoding: [0x66,0xff,0x35,0xed,0x7e,0x00,0x00] + pushw 0x7eed + +// CHECK: pushl 3133065982 +// CHECK: encoding: [0xff,0x35,0xfe,0xca,0xbe,0xba] + pushl 0xbabecafe + +// CHECK: pushl 305419896 +// CHECK: encoding: [0xff,0x35,0x78,0x56,0x34,0x12] + pushl 0x12345678 + +// CHECK: popl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x8f,0x84,0xcb,0xef,0xbe,0xad,0xde] + popl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: popw 32493 +// CHECK: encoding: [0x66,0x8f,0x05,0xed,0x7e,0x00,0x00] + popw 0x7eed + +// CHECK: popl 3133065982 +// CHECK: encoding: [0x8f,0x05,0xfe,0xca,0xbe,0xba] + popl 0xbabecafe + +// CHECK: popl 305419896 +// CHECK: encoding: [0x8f,0x05,0x78,0x56,0x34,0x12] + popl 0x12345678 + +// CHECK: clc +// CHECK: encoding: [0xf8] + clc + +// CHECK: cld +// CHECK: encoding: [0xfc] + cld + +// CHECK: cli +// CHECK: encoding: [0xfa] + cli + +// CHECK: clts +// CHECK: encoding: [0x0f,0x06] + clts + +// CHECK: cmc +// CHECK: encoding: [0xf5] + cmc + +// CHECK: lahf +// CHECK: encoding: [0x9f] + lahf + +// CHECK: sahf +// CHECK: encoding: [0x9e] + sahf + +// CHECK: stc +// CHECK: encoding: [0xf9] + stc + +// CHECK: std +// CHECK: encoding: [0xfd] + std + +// CHECK: sti +// CHECK: encoding: [0xfb] + sti + +// CHECK: addb $254, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0x84,0xcb,0xef,0xbe,0xad,0xde,0xfe] + addb $0xfe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: addb $254, 69 +// CHECK: encoding: [0x80,0x05,0x45,0x00,0x00,0x00,0xfe] + addb $0xfe,0x45 + +// CHECK: addb $254, 32493 +// CHECK: encoding: [0x80,0x05,0xed,0x7e,0x00,0x00,0xfe] + addb $0xfe,0x7eed + +// CHECK: addb $254, 3133065982 +// CHECK: encoding: [0x80,0x05,0xfe,0xca,0xbe,0xba,0xfe] + addb $0xfe,0xbabecafe + +// CHECK: addb $254, 305419896 +// CHECK: encoding: [0x80,0x05,0x78,0x56,0x34,0x12,0xfe] + addb $0xfe,0x12345678 + +// CHECK: addb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0x84,0xcb,0xef,0xbe,0xad,0xde,0x7f] + addb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: addb $127, 69 +// CHECK: encoding: [0x80,0x05,0x45,0x00,0x00,0x00,0x7f] + addb $0x7f,0x45 + +// CHECK: addb $127, 32493 +// CHECK: encoding: [0x80,0x05,0xed,0x7e,0x00,0x00,0x7f] + addb $0x7f,0x7eed + +// CHECK: addb $127, 3133065982 +// CHECK: encoding: [0x80,0x05,0xfe,0xca,0xbe,0xba,0x7f] + addb $0x7f,0xbabecafe + +// CHECK: addb $127, 305419896 +// CHECK: encoding: [0x80,0x05,0x78,0x56,0x34,0x12,0x7f] + addb $0x7f,0x12345678 + +// CHECK: addw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x81,0x84,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + addw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: addw $31438, 69 +// CHECK: encoding: [0x66,0x81,0x05,0x45,0x00,0x00,0x00,0xce,0x7a] + addw $0x7ace,0x45 + +// CHECK: addw $31438, 32493 +// CHECK: encoding: [0x66,0x81,0x05,0xed,0x7e,0x00,0x00,0xce,0x7a] + addw $0x7ace,0x7eed + +// CHECK: addw $31438, 3133065982 +// CHECK: encoding: [0x66,0x81,0x05,0xfe,0xca,0xbe,0xba,0xce,0x7a] + addw $0x7ace,0xbabecafe + +// CHECK: addw $31438, 305419896 +// CHECK: encoding: [0x66,0x81,0x05,0x78,0x56,0x34,0x12,0xce,0x7a] + addw $0x7ace,0x12345678 + +// CHECK: addl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0x84,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + addl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: addl $2063514302, 69 +// CHECK: encoding: [0x81,0x05,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + addl $0x7afebabe,0x45 + +// CHECK: addl $2063514302, 32493 +// CHECK: encoding: [0x81,0x05,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + addl $0x7afebabe,0x7eed + +// CHECK: addl $2063514302, 3133065982 +// CHECK: encoding: [0x81,0x05,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + addl $0x7afebabe,0xbabecafe + +// CHECK: addl $2063514302, 305419896 +// CHECK: encoding: [0x81,0x05,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + addl $0x7afebabe,0x12345678 + +// CHECK: addl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0x84,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + addl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: addl $324478056, 69 +// CHECK: encoding: [0x81,0x05,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + addl $0x13572468,0x45 + +// CHECK: addl $324478056, 32493 +// CHECK: encoding: [0x81,0x05,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + addl $0x13572468,0x7eed + +// CHECK: addl $324478056, 3133065982 +// CHECK: encoding: [0x81,0x05,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + addl $0x13572468,0xbabecafe + +// CHECK: addl $324478056, 305419896 +// CHECK: encoding: [0x81,0x05,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + addl $0x13572468,0x12345678 + +// CHECK: incl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xff,0x84,0xcb,0xef,0xbe,0xad,0xde] + incl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: incw 32493 +// CHECK: encoding: [0x66,0xff,0x05,0xed,0x7e,0x00,0x00] + incw 0x7eed + +// CHECK: incl 3133065982 +// CHECK: encoding: [0xff,0x05,0xfe,0xca,0xbe,0xba] + incl 0xbabecafe + +// CHECK: incl 305419896 +// CHECK: encoding: [0xff,0x05,0x78,0x56,0x34,0x12] + incl 0x12345678 + +// CHECK: subb $254, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0xac,0xcb,0xef,0xbe,0xad,0xde,0xfe] + subb $0xfe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: subb $254, 69 +// CHECK: encoding: [0x80,0x2d,0x45,0x00,0x00,0x00,0xfe] + subb $0xfe,0x45 + +// CHECK: subb $254, 32493 +// CHECK: encoding: [0x80,0x2d,0xed,0x7e,0x00,0x00,0xfe] + subb $0xfe,0x7eed + +// CHECK: subb $254, 3133065982 +// CHECK: encoding: [0x80,0x2d,0xfe,0xca,0xbe,0xba,0xfe] + subb $0xfe,0xbabecafe + +// CHECK: subb $254, 305419896 +// CHECK: encoding: [0x80,0x2d,0x78,0x56,0x34,0x12,0xfe] + subb $0xfe,0x12345678 + +// CHECK: subb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0xac,0xcb,0xef,0xbe,0xad,0xde,0x7f] + subb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: subb $127, 69 +// CHECK: encoding: [0x80,0x2d,0x45,0x00,0x00,0x00,0x7f] + subb $0x7f,0x45 + +// CHECK: subb $127, 32493 +// CHECK: encoding: [0x80,0x2d,0xed,0x7e,0x00,0x00,0x7f] + subb $0x7f,0x7eed + +// CHECK: subb $127, 3133065982 +// CHECK: encoding: [0x80,0x2d,0xfe,0xca,0xbe,0xba,0x7f] + subb $0x7f,0xbabecafe + +// CHECK: subb $127, 305419896 +// CHECK: encoding: [0x80,0x2d,0x78,0x56,0x34,0x12,0x7f] + subb $0x7f,0x12345678 + +// CHECK: subw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x81,0xac,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + subw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: subw $31438, 69 +// CHECK: encoding: [0x66,0x81,0x2d,0x45,0x00,0x00,0x00,0xce,0x7a] + subw $0x7ace,0x45 + +// CHECK: subw $31438, 32493 +// CHECK: encoding: [0x66,0x81,0x2d,0xed,0x7e,0x00,0x00,0xce,0x7a] + subw $0x7ace,0x7eed + +// CHECK: subw $31438, 3133065982 +// CHECK: encoding: [0x66,0x81,0x2d,0xfe,0xca,0xbe,0xba,0xce,0x7a] + subw $0x7ace,0xbabecafe + +// CHECK: subw $31438, 305419896 +// CHECK: encoding: [0x66,0x81,0x2d,0x78,0x56,0x34,0x12,0xce,0x7a] + subw $0x7ace,0x12345678 + +// CHECK: subl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0xac,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + subl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: subl $2063514302, 69 +// CHECK: encoding: [0x81,0x2d,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + subl $0x7afebabe,0x45 + +// CHECK: subl $2063514302, 32493 +// CHECK: encoding: [0x81,0x2d,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + subl $0x7afebabe,0x7eed + +// CHECK: subl $2063514302, 3133065982 +// CHECK: encoding: [0x81,0x2d,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + subl $0x7afebabe,0xbabecafe + +// CHECK: subl $2063514302, 305419896 +// CHECK: encoding: [0x81,0x2d,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + subl $0x7afebabe,0x12345678 + +// CHECK: subl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0xac,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + subl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: subl $324478056, 69 +// CHECK: encoding: [0x81,0x2d,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + subl $0x13572468,0x45 + +// CHECK: subl $324478056, 32493 +// CHECK: encoding: [0x81,0x2d,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + subl $0x13572468,0x7eed + +// CHECK: subl $324478056, 3133065982 +// CHECK: encoding: [0x81,0x2d,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + subl $0x13572468,0xbabecafe + +// CHECK: subl $324478056, 305419896 +// CHECK: encoding: [0x81,0x2d,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + subl $0x13572468,0x12345678 + +// CHECK: decl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xff,0x8c,0xcb,0xef,0xbe,0xad,0xde] + decl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: decw 32493 +// CHECK: encoding: [0x66,0xff,0x0d,0xed,0x7e,0x00,0x00] + decw 0x7eed + +// CHECK: decl 3133065982 +// CHECK: encoding: [0xff,0x0d,0xfe,0xca,0xbe,0xba] + decl 0xbabecafe + +// CHECK: decl 305419896 +// CHECK: encoding: [0xff,0x0d,0x78,0x56,0x34,0x12] + decl 0x12345678 + +// CHECK: sbbb $254, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0x9c,0xcb,0xef,0xbe,0xad,0xde,0xfe] + sbbb $0xfe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sbbb $254, 69 +// CHECK: encoding: [0x80,0x1d,0x45,0x00,0x00,0x00,0xfe] + sbbb $0xfe,0x45 + +// CHECK: sbbb $254, 32493 +// CHECK: encoding: [0x80,0x1d,0xed,0x7e,0x00,0x00,0xfe] + sbbb $0xfe,0x7eed + +// CHECK: sbbb $254, 3133065982 +// CHECK: encoding: [0x80,0x1d,0xfe,0xca,0xbe,0xba,0xfe] + sbbb $0xfe,0xbabecafe + +// CHECK: sbbb $254, 305419896 +// CHECK: encoding: [0x80,0x1d,0x78,0x56,0x34,0x12,0xfe] + sbbb $0xfe,0x12345678 + +// CHECK: sbbb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0x9c,0xcb,0xef,0xbe,0xad,0xde,0x7f] + sbbb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sbbb $127, 69 +// CHECK: encoding: [0x80,0x1d,0x45,0x00,0x00,0x00,0x7f] + sbbb $0x7f,0x45 + +// CHECK: sbbb $127, 32493 +// CHECK: encoding: [0x80,0x1d,0xed,0x7e,0x00,0x00,0x7f] + sbbb $0x7f,0x7eed + +// CHECK: sbbb $127, 3133065982 +// CHECK: encoding: [0x80,0x1d,0xfe,0xca,0xbe,0xba,0x7f] + sbbb $0x7f,0xbabecafe + +// CHECK: sbbb $127, 305419896 +// CHECK: encoding: [0x80,0x1d,0x78,0x56,0x34,0x12,0x7f] + sbbb $0x7f,0x12345678 + +// CHECK: sbbw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x81,0x9c,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + sbbw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sbbw $31438, 69 +// CHECK: encoding: [0x66,0x81,0x1d,0x45,0x00,0x00,0x00,0xce,0x7a] + sbbw $0x7ace,0x45 + +// CHECK: sbbw $31438, 32493 +// CHECK: encoding: [0x66,0x81,0x1d,0xed,0x7e,0x00,0x00,0xce,0x7a] + sbbw $0x7ace,0x7eed + +// CHECK: sbbw $31438, 3133065982 +// CHECK: encoding: [0x66,0x81,0x1d,0xfe,0xca,0xbe,0xba,0xce,0x7a] + sbbw $0x7ace,0xbabecafe + +// CHECK: sbbw $31438, 305419896 +// CHECK: encoding: [0x66,0x81,0x1d,0x78,0x56,0x34,0x12,0xce,0x7a] + sbbw $0x7ace,0x12345678 + +// CHECK: sbbl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0x9c,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + sbbl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sbbl $2063514302, 69 +// CHECK: encoding: [0x81,0x1d,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + sbbl $0x7afebabe,0x45 + +// CHECK: sbbl $2063514302, 32493 +// CHECK: encoding: [0x81,0x1d,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + sbbl $0x7afebabe,0x7eed + +// CHECK: sbbl $2063514302, 3133065982 +// CHECK: encoding: [0x81,0x1d,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + sbbl $0x7afebabe,0xbabecafe + +// CHECK: sbbl $2063514302, 305419896 +// CHECK: encoding: [0x81,0x1d,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + sbbl $0x7afebabe,0x12345678 + +// CHECK: sbbl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0x9c,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + sbbl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sbbl $324478056, 69 +// CHECK: encoding: [0x81,0x1d,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + sbbl $0x13572468,0x45 + +// CHECK: sbbl $324478056, 32493 +// CHECK: encoding: [0x81,0x1d,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + sbbl $0x13572468,0x7eed + +// CHECK: sbbl $324478056, 3133065982 +// CHECK: encoding: [0x81,0x1d,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + sbbl $0x13572468,0xbabecafe + +// CHECK: sbbl $324478056, 305419896 +// CHECK: encoding: [0x81,0x1d,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + sbbl $0x13572468,0x12345678 + +// CHECK: cmpb $254, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0xbc,0xcb,0xef,0xbe,0xad,0xde,0xfe] + cmpb $0xfe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: cmpb $254, 69 +// CHECK: encoding: [0x80,0x3d,0x45,0x00,0x00,0x00,0xfe] + cmpb $0xfe,0x45 + +// CHECK: cmpb $254, 32493 +// CHECK: encoding: [0x80,0x3d,0xed,0x7e,0x00,0x00,0xfe] + cmpb $0xfe,0x7eed + +// CHECK: cmpb $254, 3133065982 +// CHECK: encoding: [0x80,0x3d,0xfe,0xca,0xbe,0xba,0xfe] + cmpb $0xfe,0xbabecafe + +// CHECK: cmpb $254, 305419896 +// CHECK: encoding: [0x80,0x3d,0x78,0x56,0x34,0x12,0xfe] + cmpb $0xfe,0x12345678 + +// CHECK: cmpb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0xbc,0xcb,0xef,0xbe,0xad,0xde,0x7f] + cmpb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: cmpb $127, 69 +// CHECK: encoding: [0x80,0x3d,0x45,0x00,0x00,0x00,0x7f] + cmpb $0x7f,0x45 + +// CHECK: cmpb $127, 32493 +// CHECK: encoding: [0x80,0x3d,0xed,0x7e,0x00,0x00,0x7f] + cmpb $0x7f,0x7eed + +// CHECK: cmpb $127, 3133065982 +// CHECK: encoding: [0x80,0x3d,0xfe,0xca,0xbe,0xba,0x7f] + cmpb $0x7f,0xbabecafe + +// CHECK: cmpb $127, 305419896 +// CHECK: encoding: [0x80,0x3d,0x78,0x56,0x34,0x12,0x7f] + cmpb $0x7f,0x12345678 + +// CHECK: cmpw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x81,0xbc,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + cmpw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: cmpw $31438, 69 +// CHECK: encoding: [0x66,0x81,0x3d,0x45,0x00,0x00,0x00,0xce,0x7a] + cmpw $0x7ace,0x45 + +// CHECK: cmpw $31438, 32493 +// CHECK: encoding: [0x66,0x81,0x3d,0xed,0x7e,0x00,0x00,0xce,0x7a] + cmpw $0x7ace,0x7eed + +// CHECK: cmpw $31438, 3133065982 +// CHECK: encoding: [0x66,0x81,0x3d,0xfe,0xca,0xbe,0xba,0xce,0x7a] + cmpw $0x7ace,0xbabecafe + +// CHECK: cmpw $31438, 305419896 +// CHECK: encoding: [0x66,0x81,0x3d,0x78,0x56,0x34,0x12,0xce,0x7a] + cmpw $0x7ace,0x12345678 + +// CHECK: cmpl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0xbc,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + cmpl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: cmpl $2063514302, 69 +// CHECK: encoding: [0x81,0x3d,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + cmpl $0x7afebabe,0x45 + +// CHECK: cmpl $2063514302, 32493 +// CHECK: encoding: [0x81,0x3d,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + cmpl $0x7afebabe,0x7eed + +// CHECK: cmpl $2063514302, 3133065982 +// CHECK: encoding: [0x81,0x3d,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + cmpl $0x7afebabe,0xbabecafe + +// CHECK: cmpl $2063514302, 305419896 +// CHECK: encoding: [0x81,0x3d,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + cmpl $0x7afebabe,0x12345678 + +// CHECK: cmpl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0xbc,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + cmpl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: cmpl $324478056, 69 +// CHECK: encoding: [0x81,0x3d,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + cmpl $0x13572468,0x45 + +// CHECK: cmpl $324478056, 32493 +// CHECK: encoding: [0x81,0x3d,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + cmpl $0x13572468,0x7eed + +// CHECK: cmpl $324478056, 3133065982 +// CHECK: encoding: [0x81,0x3d,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + cmpl $0x13572468,0xbabecafe + +// CHECK: cmpl $324478056, 305419896 +// CHECK: encoding: [0x81,0x3d,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + cmpl $0x13572468,0x12345678 + +// CHECK: testb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf6,0x84,0xcb,0xef,0xbe,0xad,0xde,0x7f] + testb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: testb $127, 69 +// CHECK: encoding: [0xf6,0x05,0x45,0x00,0x00,0x00,0x7f] + testb $0x7f,0x45 + +// CHECK: testb $127, 32493 +// CHECK: encoding: [0xf6,0x05,0xed,0x7e,0x00,0x00,0x7f] + testb $0x7f,0x7eed + +// CHECK: testb $127, 3133065982 +// CHECK: encoding: [0xf6,0x05,0xfe,0xca,0xbe,0xba,0x7f] + testb $0x7f,0xbabecafe + +// CHECK: testb $127, 305419896 +// CHECK: encoding: [0xf6,0x05,0x78,0x56,0x34,0x12,0x7f] + testb $0x7f,0x12345678 + +// CHECK: testw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0xf7,0x84,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + testw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: testw $31438, 69 +// CHECK: encoding: [0x66,0xf7,0x05,0x45,0x00,0x00,0x00,0xce,0x7a] + testw $0x7ace,0x45 + +// CHECK: testw $31438, 32493 +// CHECK: encoding: [0x66,0xf7,0x05,0xed,0x7e,0x00,0x00,0xce,0x7a] + testw $0x7ace,0x7eed + +// CHECK: testw $31438, 3133065982 +// CHECK: encoding: [0x66,0xf7,0x05,0xfe,0xca,0xbe,0xba,0xce,0x7a] + testw $0x7ace,0xbabecafe + +// CHECK: testw $31438, 305419896 +// CHECK: encoding: [0x66,0xf7,0x05,0x78,0x56,0x34,0x12,0xce,0x7a] + testw $0x7ace,0x12345678 + +// CHECK: testl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf7,0x84,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + testl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: testl $2063514302, 69 +// CHECK: encoding: [0xf7,0x05,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + testl $0x7afebabe,0x45 + +// CHECK: testl $2063514302, 32493 +// CHECK: encoding: [0xf7,0x05,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + testl $0x7afebabe,0x7eed + +// CHECK: testl $2063514302, 3133065982 +// CHECK: encoding: [0xf7,0x05,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + testl $0x7afebabe,0xbabecafe + +// CHECK: testl $2063514302, 305419896 +// CHECK: encoding: [0xf7,0x05,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + testl $0x7afebabe,0x12345678 + +// CHECK: testl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf7,0x84,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + testl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: testl $324478056, 69 +// CHECK: encoding: [0xf7,0x05,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + testl $0x13572468,0x45 + +// CHECK: testl $324478056, 32493 +// CHECK: encoding: [0xf7,0x05,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + testl $0x13572468,0x7eed + +// CHECK: testl $324478056, 3133065982 +// CHECK: encoding: [0xf7,0x05,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + testl $0x13572468,0xbabecafe + +// CHECK: testl $324478056, 305419896 +// CHECK: encoding: [0xf7,0x05,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + testl $0x13572468,0x12345678 + +// CHECK: andb $254, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0xa4,0xcb,0xef,0xbe,0xad,0xde,0xfe] + andb $0xfe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: andb $254, 69 +// CHECK: encoding: [0x80,0x25,0x45,0x00,0x00,0x00,0xfe] + andb $0xfe,0x45 + +// CHECK: andb $254, 32493 +// CHECK: encoding: [0x80,0x25,0xed,0x7e,0x00,0x00,0xfe] + andb $0xfe,0x7eed + +// CHECK: andb $254, 3133065982 +// CHECK: encoding: [0x80,0x25,0xfe,0xca,0xbe,0xba,0xfe] + andb $0xfe,0xbabecafe + +// CHECK: andb $254, 305419896 +// CHECK: encoding: [0x80,0x25,0x78,0x56,0x34,0x12,0xfe] + andb $0xfe,0x12345678 + +// CHECK: andb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0xa4,0xcb,0xef,0xbe,0xad,0xde,0x7f] + andb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: andb $127, 69 +// CHECK: encoding: [0x80,0x25,0x45,0x00,0x00,0x00,0x7f] + andb $0x7f,0x45 + +// CHECK: andb $127, 32493 +// CHECK: encoding: [0x80,0x25,0xed,0x7e,0x00,0x00,0x7f] + andb $0x7f,0x7eed + +// CHECK: andb $127, 3133065982 +// CHECK: encoding: [0x80,0x25,0xfe,0xca,0xbe,0xba,0x7f] + andb $0x7f,0xbabecafe + +// CHECK: andb $127, 305419896 +// CHECK: encoding: [0x80,0x25,0x78,0x56,0x34,0x12,0x7f] + andb $0x7f,0x12345678 + +// CHECK: andw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x81,0xa4,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + andw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: andw $31438, 69 +// CHECK: encoding: [0x66,0x81,0x25,0x45,0x00,0x00,0x00,0xce,0x7a] + andw $0x7ace,0x45 + +// CHECK: andw $31438, 32493 +// CHECK: encoding: [0x66,0x81,0x25,0xed,0x7e,0x00,0x00,0xce,0x7a] + andw $0x7ace,0x7eed + +// CHECK: andw $31438, 3133065982 +// CHECK: encoding: [0x66,0x81,0x25,0xfe,0xca,0xbe,0xba,0xce,0x7a] + andw $0x7ace,0xbabecafe + +// CHECK: andw $31438, 305419896 +// CHECK: encoding: [0x66,0x81,0x25,0x78,0x56,0x34,0x12,0xce,0x7a] + andw $0x7ace,0x12345678 + +// CHECK: andl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0xa4,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + andl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: andl $2063514302, 69 +// CHECK: encoding: [0x81,0x25,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + andl $0x7afebabe,0x45 + +// CHECK: andl $2063514302, 32493 +// CHECK: encoding: [0x81,0x25,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + andl $0x7afebabe,0x7eed + +// CHECK: andl $2063514302, 3133065982 +// CHECK: encoding: [0x81,0x25,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + andl $0x7afebabe,0xbabecafe + +// CHECK: andl $2063514302, 305419896 +// CHECK: encoding: [0x81,0x25,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + andl $0x7afebabe,0x12345678 + +// CHECK: andl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0xa4,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + andl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: andl $324478056, 69 +// CHECK: encoding: [0x81,0x25,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + andl $0x13572468,0x45 + +// CHECK: andl $324478056, 32493 +// CHECK: encoding: [0x81,0x25,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + andl $0x13572468,0x7eed + +// CHECK: andl $324478056, 3133065982 +// CHECK: encoding: [0x81,0x25,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + andl $0x13572468,0xbabecafe + +// CHECK: andl $324478056, 305419896 +// CHECK: encoding: [0x81,0x25,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + andl $0x13572468,0x12345678 + +// CHECK: orb $254, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0x8c,0xcb,0xef,0xbe,0xad,0xde,0xfe] + orb $0xfe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: orb $254, 69 +// CHECK: encoding: [0x80,0x0d,0x45,0x00,0x00,0x00,0xfe] + orb $0xfe,0x45 + +// CHECK: orb $254, 32493 +// CHECK: encoding: [0x80,0x0d,0xed,0x7e,0x00,0x00,0xfe] + orb $0xfe,0x7eed + +// CHECK: orb $254, 3133065982 +// CHECK: encoding: [0x80,0x0d,0xfe,0xca,0xbe,0xba,0xfe] + orb $0xfe,0xbabecafe + +// CHECK: orb $254, 305419896 +// CHECK: encoding: [0x80,0x0d,0x78,0x56,0x34,0x12,0xfe] + orb $0xfe,0x12345678 + +// CHECK: orb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0x8c,0xcb,0xef,0xbe,0xad,0xde,0x7f] + orb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: orb $127, 69 +// CHECK: encoding: [0x80,0x0d,0x45,0x00,0x00,0x00,0x7f] + orb $0x7f,0x45 + +// CHECK: orb $127, 32493 +// CHECK: encoding: [0x80,0x0d,0xed,0x7e,0x00,0x00,0x7f] + orb $0x7f,0x7eed + +// CHECK: orb $127, 3133065982 +// CHECK: encoding: [0x80,0x0d,0xfe,0xca,0xbe,0xba,0x7f] + orb $0x7f,0xbabecafe + +// CHECK: orb $127, 305419896 +// CHECK: encoding: [0x80,0x0d,0x78,0x56,0x34,0x12,0x7f] + orb $0x7f,0x12345678 + +// CHECK: orw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x81,0x8c,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + orw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: orw $31438, 69 +// CHECK: encoding: [0x66,0x81,0x0d,0x45,0x00,0x00,0x00,0xce,0x7a] + orw $0x7ace,0x45 + +// CHECK: orw $31438, 32493 +// CHECK: encoding: [0x66,0x81,0x0d,0xed,0x7e,0x00,0x00,0xce,0x7a] + orw $0x7ace,0x7eed + +// CHECK: orw $31438, 3133065982 +// CHECK: encoding: [0x66,0x81,0x0d,0xfe,0xca,0xbe,0xba,0xce,0x7a] + orw $0x7ace,0xbabecafe + +// CHECK: orw $31438, 305419896 +// CHECK: encoding: [0x66,0x81,0x0d,0x78,0x56,0x34,0x12,0xce,0x7a] + orw $0x7ace,0x12345678 + +// CHECK: orl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0x8c,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + orl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: orl $2063514302, 69 +// CHECK: encoding: [0x81,0x0d,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + orl $0x7afebabe,0x45 + +// CHECK: orl $2063514302, 32493 +// CHECK: encoding: [0x81,0x0d,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + orl $0x7afebabe,0x7eed + +// CHECK: orl $2063514302, 3133065982 +// CHECK: encoding: [0x81,0x0d,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + orl $0x7afebabe,0xbabecafe + +// CHECK: orl $2063514302, 305419896 +// CHECK: encoding: [0x81,0x0d,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + orl $0x7afebabe,0x12345678 + +// CHECK: orl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0x8c,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + orl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: orl $324478056, 69 +// CHECK: encoding: [0x81,0x0d,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + orl $0x13572468,0x45 + +// CHECK: orl $324478056, 32493 +// CHECK: encoding: [0x81,0x0d,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + orl $0x13572468,0x7eed + +// CHECK: orl $324478056, 3133065982 +// CHECK: encoding: [0x81,0x0d,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + orl $0x13572468,0xbabecafe + +// CHECK: orl $324478056, 305419896 +// CHECK: encoding: [0x81,0x0d,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + orl $0x13572468,0x12345678 + +// CHECK: xorb $254, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0xb4,0xcb,0xef,0xbe,0xad,0xde,0xfe] + xorb $0xfe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: xorb $254, 69 +// CHECK: encoding: [0x80,0x35,0x45,0x00,0x00,0x00,0xfe] + xorb $0xfe,0x45 + +// CHECK: xorb $254, 32493 +// CHECK: encoding: [0x80,0x35,0xed,0x7e,0x00,0x00,0xfe] + xorb $0xfe,0x7eed + +// CHECK: xorb $254, 3133065982 +// CHECK: encoding: [0x80,0x35,0xfe,0xca,0xbe,0xba,0xfe] + xorb $0xfe,0xbabecafe + +// CHECK: xorb $254, 305419896 +// CHECK: encoding: [0x80,0x35,0x78,0x56,0x34,0x12,0xfe] + xorb $0xfe,0x12345678 + +// CHECK: xorb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0xb4,0xcb,0xef,0xbe,0xad,0xde,0x7f] + xorb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: xorb $127, 69 +// CHECK: encoding: [0x80,0x35,0x45,0x00,0x00,0x00,0x7f] + xorb $0x7f,0x45 + +// CHECK: xorb $127, 32493 +// CHECK: encoding: [0x80,0x35,0xed,0x7e,0x00,0x00,0x7f] + xorb $0x7f,0x7eed + +// CHECK: xorb $127, 3133065982 +// CHECK: encoding: [0x80,0x35,0xfe,0xca,0xbe,0xba,0x7f] + xorb $0x7f,0xbabecafe + +// CHECK: xorb $127, 305419896 +// CHECK: encoding: [0x80,0x35,0x78,0x56,0x34,0x12,0x7f] + xorb $0x7f,0x12345678 + +// CHECK: xorw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x81,0xb4,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + xorw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: xorw $31438, 69 +// CHECK: encoding: [0x66,0x81,0x35,0x45,0x00,0x00,0x00,0xce,0x7a] + xorw $0x7ace,0x45 + +// CHECK: xorw $31438, 32493 +// CHECK: encoding: [0x66,0x81,0x35,0xed,0x7e,0x00,0x00,0xce,0x7a] + xorw $0x7ace,0x7eed + +// CHECK: xorw $31438, 3133065982 +// CHECK: encoding: [0x66,0x81,0x35,0xfe,0xca,0xbe,0xba,0xce,0x7a] + xorw $0x7ace,0xbabecafe + +// CHECK: xorw $31438, 305419896 +// CHECK: encoding: [0x66,0x81,0x35,0x78,0x56,0x34,0x12,0xce,0x7a] + xorw $0x7ace,0x12345678 + +// CHECK: xorl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0xb4,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + xorl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: xorl $2063514302, 69 +// CHECK: encoding: [0x81,0x35,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + xorl $0x7afebabe,0x45 + +// CHECK: xorl $2063514302, 32493 +// CHECK: encoding: [0x81,0x35,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + xorl $0x7afebabe,0x7eed + +// CHECK: xorl $2063514302, 3133065982 +// CHECK: encoding: [0x81,0x35,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + xorl $0x7afebabe,0xbabecafe + +// CHECK: xorl $2063514302, 305419896 +// CHECK: encoding: [0x81,0x35,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + xorl $0x7afebabe,0x12345678 + +// CHECK: xorl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0xb4,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + xorl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: xorl $324478056, 69 +// CHECK: encoding: [0x81,0x35,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + xorl $0x13572468,0x45 + +// CHECK: xorl $324478056, 32493 +// CHECK: encoding: [0x81,0x35,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + xorl $0x13572468,0x7eed + +// CHECK: xorl $324478056, 3133065982 +// CHECK: encoding: [0x81,0x35,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + xorl $0x13572468,0xbabecafe + +// CHECK: xorl $324478056, 305419896 +// CHECK: encoding: [0x81,0x35,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + xorl $0x13572468,0x12345678 + +// CHECK: adcb $254, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0x94,0xcb,0xef,0xbe,0xad,0xde,0xfe] + adcb $0xfe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: adcb $254, 69 +// CHECK: encoding: [0x80,0x15,0x45,0x00,0x00,0x00,0xfe] + adcb $0xfe,0x45 + +// CHECK: adcb $254, 32493 +// CHECK: encoding: [0x80,0x15,0xed,0x7e,0x00,0x00,0xfe] + adcb $0xfe,0x7eed + +// CHECK: adcb $254, 3133065982 +// CHECK: encoding: [0x80,0x15,0xfe,0xca,0xbe,0xba,0xfe] + adcb $0xfe,0xbabecafe + +// CHECK: adcb $254, 305419896 +// CHECK: encoding: [0x80,0x15,0x78,0x56,0x34,0x12,0xfe] + adcb $0xfe,0x12345678 + +// CHECK: adcb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x80,0x94,0xcb,0xef,0xbe,0xad,0xde,0x7f] + adcb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: adcb $127, 69 +// CHECK: encoding: [0x80,0x15,0x45,0x00,0x00,0x00,0x7f] + adcb $0x7f,0x45 + +// CHECK: adcb $127, 32493 +// CHECK: encoding: [0x80,0x15,0xed,0x7e,0x00,0x00,0x7f] + adcb $0x7f,0x7eed + +// CHECK: adcb $127, 3133065982 +// CHECK: encoding: [0x80,0x15,0xfe,0xca,0xbe,0xba,0x7f] + adcb $0x7f,0xbabecafe + +// CHECK: adcb $127, 305419896 +// CHECK: encoding: [0x80,0x15,0x78,0x56,0x34,0x12,0x7f] + adcb $0x7f,0x12345678 + +// CHECK: adcw $31438, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x81,0x94,0xcb,0xef,0xbe,0xad,0xde,0xce,0x7a] + adcw $0x7ace,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: adcw $31438, 69 +// CHECK: encoding: [0x66,0x81,0x15,0x45,0x00,0x00,0x00,0xce,0x7a] + adcw $0x7ace,0x45 + +// CHECK: adcw $31438, 32493 +// CHECK: encoding: [0x66,0x81,0x15,0xed,0x7e,0x00,0x00,0xce,0x7a] + adcw $0x7ace,0x7eed + +// CHECK: adcw $31438, 3133065982 +// CHECK: encoding: [0x66,0x81,0x15,0xfe,0xca,0xbe,0xba,0xce,0x7a] + adcw $0x7ace,0xbabecafe + +// CHECK: adcw $31438, 305419896 +// CHECK: encoding: [0x66,0x81,0x15,0x78,0x56,0x34,0x12,0xce,0x7a] + adcw $0x7ace,0x12345678 + +// CHECK: adcl $2063514302, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0x94,0xcb,0xef,0xbe,0xad,0xde,0xbe,0xba,0xfe,0x7a] + adcl $0x7afebabe,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: adcl $2063514302, 69 +// CHECK: encoding: [0x81,0x15,0x45,0x00,0x00,0x00,0xbe,0xba,0xfe,0x7a] + adcl $0x7afebabe,0x45 + +// CHECK: adcl $2063514302, 32493 +// CHECK: encoding: [0x81,0x15,0xed,0x7e,0x00,0x00,0xbe,0xba,0xfe,0x7a] + adcl $0x7afebabe,0x7eed + +// CHECK: adcl $2063514302, 3133065982 +// CHECK: encoding: [0x81,0x15,0xfe,0xca,0xbe,0xba,0xbe,0xba,0xfe,0x7a] + adcl $0x7afebabe,0xbabecafe + +// CHECK: adcl $2063514302, 305419896 +// CHECK: encoding: [0x81,0x15,0x78,0x56,0x34,0x12,0xbe,0xba,0xfe,0x7a] + adcl $0x7afebabe,0x12345678 + +// CHECK: adcl $324478056, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x81,0x94,0xcb,0xef,0xbe,0xad,0xde,0x68,0x24,0x57,0x13] + adcl $0x13572468,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: adcl $324478056, 69 +// CHECK: encoding: [0x81,0x15,0x45,0x00,0x00,0x00,0x68,0x24,0x57,0x13] + adcl $0x13572468,0x45 + +// CHECK: adcl $324478056, 32493 +// CHECK: encoding: [0x81,0x15,0xed,0x7e,0x00,0x00,0x68,0x24,0x57,0x13] + adcl $0x13572468,0x7eed + +// CHECK: adcl $324478056, 3133065982 +// CHECK: encoding: [0x81,0x15,0xfe,0xca,0xbe,0xba,0x68,0x24,0x57,0x13] + adcl $0x13572468,0xbabecafe + +// CHECK: adcl $324478056, 305419896 +// CHECK: encoding: [0x81,0x15,0x78,0x56,0x34,0x12,0x68,0x24,0x57,0x13] + adcl $0x13572468,0x12345678 + +// CHECK: negl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf7,0x9c,0xcb,0xef,0xbe,0xad,0xde] + negl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: negw 32493 +// CHECK: encoding: [0x66,0xf7,0x1d,0xed,0x7e,0x00,0x00] + negw 0x7eed + +// CHECK: negl 3133065982 +// CHECK: encoding: [0xf7,0x1d,0xfe,0xca,0xbe,0xba] + negl 0xbabecafe + +// CHECK: negl 305419896 +// CHECK: encoding: [0xf7,0x1d,0x78,0x56,0x34,0x12] + negl 0x12345678 + +// CHECK: notl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf7,0x94,0xcb,0xef,0xbe,0xad,0xde] + notl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: notw 32493 +// CHECK: encoding: [0x66,0xf7,0x15,0xed,0x7e,0x00,0x00] + notw 0x7eed + +// CHECK: notl 3133065982 +// CHECK: encoding: [0xf7,0x15,0xfe,0xca,0xbe,0xba] + notl 0xbabecafe + +// CHECK: notl 305419896 +// CHECK: encoding: [0xf7,0x15,0x78,0x56,0x34,0x12] + notl 0x12345678 + +// CHECK: cbtw +// CHECK: encoding: [0x66,0x98] + cbtw + +// CHECK: cwtl +// CHECK: encoding: [0x98] + cwtl + +// CHECK: cwtd +// CHECK: encoding: [0x66,0x99] + cwtd + +// CHECK: cltd +// CHECK: encoding: [0x99] + cltd + +// CHECK: mull 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf7,0xa4,0xcb,0xef,0xbe,0xad,0xde] + mull 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: mulw 32493 +// CHECK: encoding: [0x66,0xf7,0x25,0xed,0x7e,0x00,0x00] + mulw 0x7eed + +// CHECK: mull 3133065982 +// CHECK: encoding: [0xf7,0x25,0xfe,0xca,0xbe,0xba] + mull 0xbabecafe + +// CHECK: mull 305419896 +// CHECK: encoding: [0xf7,0x25,0x78,0x56,0x34,0x12] + mull 0x12345678 + +// CHECK: imull 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf7,0xac,0xcb,0xef,0xbe,0xad,0xde] + imull 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: imulw 32493 +// CHECK: encoding: [0x66,0xf7,0x2d,0xed,0x7e,0x00,0x00] + imulw 0x7eed + +// CHECK: imull 3133065982 +// CHECK: encoding: [0xf7,0x2d,0xfe,0xca,0xbe,0xba] + imull 0xbabecafe + +// CHECK: imull 305419896 +// CHECK: encoding: [0xf7,0x2d,0x78,0x56,0x34,0x12] + imull 0x12345678 + +// CHECK: divl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf7,0xb4,0xcb,0xef,0xbe,0xad,0xde] + divl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: divw 32493 +// CHECK: encoding: [0x66,0xf7,0x35,0xed,0x7e,0x00,0x00] + divw 0x7eed + +// CHECK: divl 3133065982 +// CHECK: encoding: [0xf7,0x35,0xfe,0xca,0xbe,0xba] + divl 0xbabecafe + +// CHECK: divl 305419896 +// CHECK: encoding: [0xf7,0x35,0x78,0x56,0x34,0x12] + divl 0x12345678 + +// CHECK: idivl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf7,0xbc,0xcb,0xef,0xbe,0xad,0xde] + idivl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: idivw 32493 +// CHECK: encoding: [0x66,0xf7,0x3d,0xed,0x7e,0x00,0x00] + idivw 0x7eed + +// CHECK: idivl 3133065982 +// CHECK: encoding: [0xf7,0x3d,0xfe,0xca,0xbe,0xba] + idivl 0xbabecafe + +// CHECK: idivl 305419896 +// CHECK: encoding: [0xf7,0x3d,0x78,0x56,0x34,0x12] + idivl 0x12345678 + +// CHECK: roll $0, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc1,0x84,0xcb,0xef,0xbe,0xad,0xde,0x00] + roll $0,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: roll $0, 69 +// CHECK: encoding: [0xc1,0x05,0x45,0x00,0x00,0x00,0x00] + roll $0,0x45 + +// CHECK: roll $0, 32493 +// CHECK: encoding: [0xc1,0x05,0xed,0x7e,0x00,0x00,0x00] + roll $0,0x7eed + +// CHECK: roll $0, 3133065982 +// CHECK: encoding: [0xc1,0x05,0xfe,0xca,0xbe,0xba,0x00] + roll $0,0xbabecafe + +// CHECK: roll $0, 305419896 +// CHECK: encoding: [0xc1,0x05,0x78,0x56,0x34,0x12,0x00] + roll $0,0x12345678 + +// CHECK: rolb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc0,0x84,0xcb,0xef,0xbe,0xad,0xde,0x7f] + rolb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: rolb $127, 69 +// CHECK: encoding: [0xc0,0x05,0x45,0x00,0x00,0x00,0x7f] + rolb $0x7f,0x45 + +// CHECK: rolb $127, 32493 +// CHECK: encoding: [0xc0,0x05,0xed,0x7e,0x00,0x00,0x7f] + rolb $0x7f,0x7eed + +// CHECK: rolb $127, 3133065982 +// CHECK: encoding: [0xc0,0x05,0xfe,0xca,0xbe,0xba,0x7f] + rolb $0x7f,0xbabecafe + +// CHECK: rolb $127, 305419896 +// CHECK: encoding: [0xc0,0x05,0x78,0x56,0x34,0x12,0x7f] + rolb $0x7f,0x12345678 + +// CHECK: roll 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xd1,0x84,0xcb,0xef,0xbe,0xad,0xde] + roll 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: rolw 32493 +// CHECK: encoding: [0x66,0xd1,0x05,0xed,0x7e,0x00,0x00] + rolw 0x7eed + +// CHECK: roll 3133065982 +// CHECK: encoding: [0xd1,0x05,0xfe,0xca,0xbe,0xba] + roll 0xbabecafe + +// CHECK: roll 305419896 +// CHECK: encoding: [0xd1,0x05,0x78,0x56,0x34,0x12] + roll 0x12345678 + +// CHECK: rorl $0, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc1,0x8c,0xcb,0xef,0xbe,0xad,0xde,0x00] + rorl $0,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: rorl $0, 69 +// CHECK: encoding: [0xc1,0x0d,0x45,0x00,0x00,0x00,0x00] + rorl $0,0x45 + +// CHECK: rorl $0, 32493 +// CHECK: encoding: [0xc1,0x0d,0xed,0x7e,0x00,0x00,0x00] + rorl $0,0x7eed + +// CHECK: rorl $0, 3133065982 +// CHECK: encoding: [0xc1,0x0d,0xfe,0xca,0xbe,0xba,0x00] + rorl $0,0xbabecafe + +// CHECK: rorl $0, 305419896 +// CHECK: encoding: [0xc1,0x0d,0x78,0x56,0x34,0x12,0x00] + rorl $0,0x12345678 + +// CHECK: rorb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc0,0x8c,0xcb,0xef,0xbe,0xad,0xde,0x7f] + rorb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: rorb $127, 69 +// CHECK: encoding: [0xc0,0x0d,0x45,0x00,0x00,0x00,0x7f] + rorb $0x7f,0x45 + +// CHECK: rorb $127, 32493 +// CHECK: encoding: [0xc0,0x0d,0xed,0x7e,0x00,0x00,0x7f] + rorb $0x7f,0x7eed + +// CHECK: rorb $127, 3133065982 +// CHECK: encoding: [0xc0,0x0d,0xfe,0xca,0xbe,0xba,0x7f] + rorb $0x7f,0xbabecafe + +// CHECK: rorb $127, 305419896 +// CHECK: encoding: [0xc0,0x0d,0x78,0x56,0x34,0x12,0x7f] + rorb $0x7f,0x12345678 + +// CHECK: rorl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xd1,0x8c,0xcb,0xef,0xbe,0xad,0xde] + rorl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: rorw 32493 +// CHECK: encoding: [0x66,0xd1,0x0d,0xed,0x7e,0x00,0x00] + rorw 0x7eed + +// CHECK: rorl 3133065982 +// CHECK: encoding: [0xd1,0x0d,0xfe,0xca,0xbe,0xba] + rorl 0xbabecafe + +// CHECK: rorl 305419896 +// CHECK: encoding: [0xd1,0x0d,0x78,0x56,0x34,0x12] + rorl 0x12345678 + +// CHECK: shll $0, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc1,0xa4,0xcb,0xef,0xbe,0xad,0xde,0x00] + sall $0,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shll $0, 69 +// CHECK: encoding: [0xc1,0x25,0x45,0x00,0x00,0x00,0x00] + sall $0,0x45 + +// CHECK: shll $0, 32493 +// CHECK: encoding: [0xc1,0x25,0xed,0x7e,0x00,0x00,0x00] + sall $0,0x7eed + +// CHECK: shll $0, 3133065982 +// CHECK: encoding: [0xc1,0x25,0xfe,0xca,0xbe,0xba,0x00] + sall $0,0xbabecafe + +// CHECK: shll $0, 305419896 +// CHECK: encoding: [0xc1,0x25,0x78,0x56,0x34,0x12,0x00] + sall $0,0x12345678 + +// CHECK: shlb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc0,0xa4,0xcb,0xef,0xbe,0xad,0xde,0x7f] + salb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shlb $127, 69 +// CHECK: encoding: [0xc0,0x25,0x45,0x00,0x00,0x00,0x7f] + salb $0x7f,0x45 + +// CHECK: shlb $127, 32493 +// CHECK: encoding: [0xc0,0x25,0xed,0x7e,0x00,0x00,0x7f] + salb $0x7f,0x7eed + +// CHECK: shlb $127, 3133065982 +// CHECK: encoding: [0xc0,0x25,0xfe,0xca,0xbe,0xba,0x7f] + salb $0x7f,0xbabecafe + +// CHECK: shlb $127, 305419896 +// CHECK: encoding: [0xc0,0x25,0x78,0x56,0x34,0x12,0x7f] + salb $0x7f,0x12345678 + +// CHECK: shll 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xd1,0xa4,0xcb,0xef,0xbe,0xad,0xde] + sall 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shlw 32493 +// CHECK: encoding: [0x66,0xd1,0x25,0xed,0x7e,0x00,0x00] + salw 0x7eed + +// CHECK: shll 3133065982 +// CHECK: encoding: [0xd1,0x25,0xfe,0xca,0xbe,0xba] + sall 0xbabecafe + +// CHECK: shll 305419896 +// CHECK: encoding: [0xd1,0x25,0x78,0x56,0x34,0x12] + sall 0x12345678 + +// CHECK: shll $0, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc1,0xa4,0xcb,0xef,0xbe,0xad,0xde,0x00] + shll $0,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shll $0, 69 +// CHECK: encoding: [0xc1,0x25,0x45,0x00,0x00,0x00,0x00] + shll $0,0x45 + +// CHECK: shll $0, 32493 +// CHECK: encoding: [0xc1,0x25,0xed,0x7e,0x00,0x00,0x00] + shll $0,0x7eed + +// CHECK: shll $0, 3133065982 +// CHECK: encoding: [0xc1,0x25,0xfe,0xca,0xbe,0xba,0x00] + shll $0,0xbabecafe + +// CHECK: shll $0, 305419896 +// CHECK: encoding: [0xc1,0x25,0x78,0x56,0x34,0x12,0x00] + shll $0,0x12345678 + +// CHECK: shlb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc0,0xa4,0xcb,0xef,0xbe,0xad,0xde,0x7f] + shlb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shlb $127, 69 +// CHECK: encoding: [0xc0,0x25,0x45,0x00,0x00,0x00,0x7f] + shlb $0x7f,0x45 + +// CHECK: shlb $127, 32493 +// CHECK: encoding: [0xc0,0x25,0xed,0x7e,0x00,0x00,0x7f] + shlb $0x7f,0x7eed + +// CHECK: shlb $127, 3133065982 +// CHECK: encoding: [0xc0,0x25,0xfe,0xca,0xbe,0xba,0x7f] + shlb $0x7f,0xbabecafe + +// CHECK: shlb $127, 305419896 +// CHECK: encoding: [0xc0,0x25,0x78,0x56,0x34,0x12,0x7f] + shlb $0x7f,0x12345678 + +// CHECK: shll 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xd1,0xa4,0xcb,0xef,0xbe,0xad,0xde] + shll 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shlw 32493 +// CHECK: encoding: [0x66,0xd1,0x25,0xed,0x7e,0x00,0x00] + shlw 0x7eed + +// CHECK: shll 3133065982 +// CHECK: encoding: [0xd1,0x25,0xfe,0xca,0xbe,0xba] + shll 0xbabecafe + +// CHECK: shll 305419896 +// CHECK: encoding: [0xd1,0x25,0x78,0x56,0x34,0x12] + shll 0x12345678 + +// CHECK: shrl $0, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc1,0xac,0xcb,0xef,0xbe,0xad,0xde,0x00] + shrl $0,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shrl $0, 69 +// CHECK: encoding: [0xc1,0x2d,0x45,0x00,0x00,0x00,0x00] + shrl $0,0x45 + +// CHECK: shrl $0, 32493 +// CHECK: encoding: [0xc1,0x2d,0xed,0x7e,0x00,0x00,0x00] + shrl $0,0x7eed + +// CHECK: shrl $0, 3133065982 +// CHECK: encoding: [0xc1,0x2d,0xfe,0xca,0xbe,0xba,0x00] + shrl $0,0xbabecafe + +// CHECK: shrl $0, 305419896 +// CHECK: encoding: [0xc1,0x2d,0x78,0x56,0x34,0x12,0x00] + shrl $0,0x12345678 + +// CHECK: shrb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc0,0xac,0xcb,0xef,0xbe,0xad,0xde,0x7f] + shrb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shrb $127, 69 +// CHECK: encoding: [0xc0,0x2d,0x45,0x00,0x00,0x00,0x7f] + shrb $0x7f,0x45 + +// CHECK: shrb $127, 32493 +// CHECK: encoding: [0xc0,0x2d,0xed,0x7e,0x00,0x00,0x7f] + shrb $0x7f,0x7eed + +// CHECK: shrb $127, 3133065982 +// CHECK: encoding: [0xc0,0x2d,0xfe,0xca,0xbe,0xba,0x7f] + shrb $0x7f,0xbabecafe + +// CHECK: shrb $127, 305419896 +// CHECK: encoding: [0xc0,0x2d,0x78,0x56,0x34,0x12,0x7f] + shrb $0x7f,0x12345678 + +// CHECK: shrl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xd1,0xac,0xcb,0xef,0xbe,0xad,0xde] + shrl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: shrw 32493 +// CHECK: encoding: [0x66,0xd1,0x2d,0xed,0x7e,0x00,0x00] + shrw 0x7eed + +// CHECK: shrl 3133065982 +// CHECK: encoding: [0xd1,0x2d,0xfe,0xca,0xbe,0xba] + shrl 0xbabecafe + +// CHECK: shrl 305419896 +// CHECK: encoding: [0xd1,0x2d,0x78,0x56,0x34,0x12] + shrl 0x12345678 + +// CHECK: sarl $0, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc1,0xbc,0xcb,0xef,0xbe,0xad,0xde,0x00] + sarl $0,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sarl $0, 69 +// CHECK: encoding: [0xc1,0x3d,0x45,0x00,0x00,0x00,0x00] + sarl $0,0x45 + +// CHECK: sarl $0, 32493 +// CHECK: encoding: [0xc1,0x3d,0xed,0x7e,0x00,0x00,0x00] + sarl $0,0x7eed + +// CHECK: sarl $0, 3133065982 +// CHECK: encoding: [0xc1,0x3d,0xfe,0xca,0xbe,0xba,0x00] + sarl $0,0xbabecafe + +// CHECK: sarl $0, 305419896 +// CHECK: encoding: [0xc1,0x3d,0x78,0x56,0x34,0x12,0x00] + sarl $0,0x12345678 + +// CHECK: sarb $127, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xc0,0xbc,0xcb,0xef,0xbe,0xad,0xde,0x7f] + sarb $0x7f,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sarb $127, 69 +// CHECK: encoding: [0xc0,0x3d,0x45,0x00,0x00,0x00,0x7f] + sarb $0x7f,0x45 + +// CHECK: sarb $127, 32493 +// CHECK: encoding: [0xc0,0x3d,0xed,0x7e,0x00,0x00,0x7f] + sarb $0x7f,0x7eed + +// CHECK: sarb $127, 3133065982 +// CHECK: encoding: [0xc0,0x3d,0xfe,0xca,0xbe,0xba,0x7f] + sarb $0x7f,0xbabecafe + +// CHECK: sarb $127, 305419896 +// CHECK: encoding: [0xc0,0x3d,0x78,0x56,0x34,0x12,0x7f] + sarb $0x7f,0x12345678 + +// CHECK: sarl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xd1,0xbc,0xcb,0xef,0xbe,0xad,0xde] + sarl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sarw 32493 +// CHECK: encoding: [0x66,0xd1,0x3d,0xed,0x7e,0x00,0x00] + sarw 0x7eed + +// CHECK: sarl 3133065982 +// CHECK: encoding: [0xd1,0x3d,0xfe,0xca,0xbe,0xba] + sarl 0xbabecafe + +// CHECK: sarl 305419896 +// CHECK: encoding: [0xd1,0x3d,0x78,0x56,0x34,0x12] + sarl 0x12345678 + +// CHECK: call *%ecx +// CHECK: encoding: [0xff,0xd1] + call *%ecx + +// CHECK: call *3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xff,0x94,0xcb,0xef,0xbe,0xad,0xde] + call *0xdeadbeef(%ebx,%ecx,8) + +// CHECK: call *3135175374 +// CHECK: encoding: [0xff,0x15,0xce,0xfa,0xde,0xba] + call *0xbadeface + +// CHECK: call *3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xff,0x94,0xcb,0xef,0xbe,0xad,0xde] + call *0xdeadbeef(%ebx,%ecx,8) + +// CHECK: call *3135175374 +// CHECK: encoding: [0xff,0x15,0xce,0xfa,0xde,0xba] + call *0xbadeface + +// CHECK: lcallw *32493 +// CHECK: encoding: [0x66,0xff,0x1d,0xed,0x7e,0x00,0x00] + lcallw *0x7eed + +// CHECK: jmp *3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xff,0xa4,0xcb,0xef,0xbe,0xad,0xde] + jmp *0xdeadbeef(%ebx,%ecx,8) + +// CHECK: jmp *3135175374 +// CHECK: encoding: [0xff,0x25,0xce,0xfa,0xde,0xba] + jmp *0xbadeface + +// CHECK: jmp *3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xff,0xa4,0xcb,0xef,0xbe,0xad,0xde] + jmp *0xdeadbeef(%ebx,%ecx,8) + +// CHECK: jmp *3135175374 +// CHECK: encoding: [0xff,0x25,0xce,0xfa,0xde,0xba] + jmp *0xbadeface + +// CHECK: ljmpl *3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xff,0xac,0xcb,0xef,0xbe,0xad,0xde] + ljmpl *0xdeadbeef(%ebx,%ecx,8) + +// CHECK: ljmpw *32493 +// CHECK: encoding: [0x66,0xff,0x2d,0xed,0x7e,0x00,0x00] + ljmpw *0x7eed + +// CHECK: ljmpl *3133065982 +// CHECK: encoding: [0xff,0x2d,0xfe,0xca,0xbe,0xba] + ljmpl *0xbabecafe + +// CHECK: ljmpl *305419896 +// CHECK: encoding: [0xff,0x2d,0x78,0x56,0x34,0x12] + ljmpl *0x12345678 + +// CHECK: ret +// CHECK: encoding: [0xc3] + ret + +// CHECK: lret +// CHECK: encoding: [0xcb] + lret + +// CHECK: leave +// CHECK: encoding: [0xc9] + leave + +// CHECK: seto %bl +// CHECK: encoding: [0x0f,0x90,0xc3] + seto %bl + +// CHECK: seto 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x90,0x84,0xcb,0xef,0xbe,0xad,0xde] + seto 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: seto 32493 +// CHECK: encoding: [0x0f,0x90,0x05,0xed,0x7e,0x00,0x00] + seto 0x7eed + +// CHECK: seto 3133065982 +// CHECK: encoding: [0x0f,0x90,0x05,0xfe,0xca,0xbe,0xba] + seto 0xbabecafe + +// CHECK: seto 305419896 +// CHECK: encoding: [0x0f,0x90,0x05,0x78,0x56,0x34,0x12] + seto 0x12345678 + +// CHECK: setno %bl +// CHECK: encoding: [0x0f,0x91,0xc3] + setno %bl + +// CHECK: setno 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x91,0x84,0xcb,0xef,0xbe,0xad,0xde] + setno 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setno 32493 +// CHECK: encoding: [0x0f,0x91,0x05,0xed,0x7e,0x00,0x00] + setno 0x7eed + +// CHECK: setno 3133065982 +// CHECK: encoding: [0x0f,0x91,0x05,0xfe,0xca,0xbe,0xba] + setno 0xbabecafe + +// CHECK: setno 305419896 +// CHECK: encoding: [0x0f,0x91,0x05,0x78,0x56,0x34,0x12] + setno 0x12345678 + +// CHECK: setb %bl +// CHECK: encoding: [0x0f,0x92,0xc3] + setb %bl + +// CHECK: setb 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x92,0x84,0xcb,0xef,0xbe,0xad,0xde] + setb 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setb 32493 +// CHECK: encoding: [0x0f,0x92,0x05,0xed,0x7e,0x00,0x00] + setb 0x7eed + +// CHECK: setb 3133065982 +// CHECK: encoding: [0x0f,0x92,0x05,0xfe,0xca,0xbe,0xba] + setb 0xbabecafe + +// CHECK: setb 305419896 +// CHECK: encoding: [0x0f,0x92,0x05,0x78,0x56,0x34,0x12] + setb 0x12345678 + +// CHECK: setae %bl +// CHECK: encoding: [0x0f,0x93,0xc3] + setae %bl + +// CHECK: setae 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x93,0x84,0xcb,0xef,0xbe,0xad,0xde] + setae 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setae 32493 +// CHECK: encoding: [0x0f,0x93,0x05,0xed,0x7e,0x00,0x00] + setae 0x7eed + +// CHECK: setae 3133065982 +// CHECK: encoding: [0x0f,0x93,0x05,0xfe,0xca,0xbe,0xba] + setae 0xbabecafe + +// CHECK: setae 305419896 +// CHECK: encoding: [0x0f,0x93,0x05,0x78,0x56,0x34,0x12] + setae 0x12345678 + +// CHECK: sete %bl +// CHECK: encoding: [0x0f,0x94,0xc3] + sete %bl + +// CHECK: sete 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x94,0x84,0xcb,0xef,0xbe,0xad,0xde] + sete 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sete 32493 +// CHECK: encoding: [0x0f,0x94,0x05,0xed,0x7e,0x00,0x00] + sete 0x7eed + +// CHECK: sete 3133065982 +// CHECK: encoding: [0x0f,0x94,0x05,0xfe,0xca,0xbe,0xba] + sete 0xbabecafe + +// CHECK: sete 305419896 +// CHECK: encoding: [0x0f,0x94,0x05,0x78,0x56,0x34,0x12] + sete 0x12345678 + +// CHECK: setne %bl +// CHECK: encoding: [0x0f,0x95,0xc3] + setne %bl + +// CHECK: setne 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x95,0x84,0xcb,0xef,0xbe,0xad,0xde] + setne 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setne 32493 +// CHECK: encoding: [0x0f,0x95,0x05,0xed,0x7e,0x00,0x00] + setne 0x7eed + +// CHECK: setne 3133065982 +// CHECK: encoding: [0x0f,0x95,0x05,0xfe,0xca,0xbe,0xba] + setne 0xbabecafe + +// CHECK: setne 305419896 +// CHECK: encoding: [0x0f,0x95,0x05,0x78,0x56,0x34,0x12] + setne 0x12345678 + +// CHECK: setbe %bl +// CHECK: encoding: [0x0f,0x96,0xc3] + setbe %bl + +// CHECK: setbe 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x96,0x84,0xcb,0xef,0xbe,0xad,0xde] + setbe 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setbe 32493 +// CHECK: encoding: [0x0f,0x96,0x05,0xed,0x7e,0x00,0x00] + setbe 0x7eed + +// CHECK: setbe 3133065982 +// CHECK: encoding: [0x0f,0x96,0x05,0xfe,0xca,0xbe,0xba] + setbe 0xbabecafe + +// CHECK: setbe 305419896 +// CHECK: encoding: [0x0f,0x96,0x05,0x78,0x56,0x34,0x12] + setbe 0x12345678 + +// CHECK: seta %bl +// CHECK: encoding: [0x0f,0x97,0xc3] + seta %bl + +// CHECK: seta 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x97,0x84,0xcb,0xef,0xbe,0xad,0xde] + seta 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: seta 32493 +// CHECK: encoding: [0x0f,0x97,0x05,0xed,0x7e,0x00,0x00] + seta 0x7eed + +// CHECK: seta 3133065982 +// CHECK: encoding: [0x0f,0x97,0x05,0xfe,0xca,0xbe,0xba] + seta 0xbabecafe + +// CHECK: seta 305419896 +// CHECK: encoding: [0x0f,0x97,0x05,0x78,0x56,0x34,0x12] + seta 0x12345678 + +// CHECK: sets %bl +// CHECK: encoding: [0x0f,0x98,0xc3] + sets %bl + +// CHECK: sets 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x98,0x84,0xcb,0xef,0xbe,0xad,0xde] + sets 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: sets 32493 +// CHECK: encoding: [0x0f,0x98,0x05,0xed,0x7e,0x00,0x00] + sets 0x7eed + +// CHECK: sets 3133065982 +// CHECK: encoding: [0x0f,0x98,0x05,0xfe,0xca,0xbe,0xba] + sets 0xbabecafe + +// CHECK: sets 305419896 +// CHECK: encoding: [0x0f,0x98,0x05,0x78,0x56,0x34,0x12] + sets 0x12345678 + +// CHECK: setns %bl +// CHECK: encoding: [0x0f,0x99,0xc3] + setns %bl + +// CHECK: setns 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x99,0x84,0xcb,0xef,0xbe,0xad,0xde] + setns 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setns 32493 +// CHECK: encoding: [0x0f,0x99,0x05,0xed,0x7e,0x00,0x00] + setns 0x7eed + +// CHECK: setns 3133065982 +// CHECK: encoding: [0x0f,0x99,0x05,0xfe,0xca,0xbe,0xba] + setns 0xbabecafe + +// CHECK: setns 305419896 +// CHECK: encoding: [0x0f,0x99,0x05,0x78,0x56,0x34,0x12] + setns 0x12345678 + +// CHECK: setp %bl +// CHECK: encoding: [0x0f,0x9a,0xc3] + setp %bl + +// CHECK: setp 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x9a,0x84,0xcb,0xef,0xbe,0xad,0xde] + setp 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setp 32493 +// CHECK: encoding: [0x0f,0x9a,0x05,0xed,0x7e,0x00,0x00] + setp 0x7eed + +// CHECK: setp 3133065982 +// CHECK: encoding: [0x0f,0x9a,0x05,0xfe,0xca,0xbe,0xba] + setp 0xbabecafe + +// CHECK: setp 305419896 +// CHECK: encoding: [0x0f,0x9a,0x05,0x78,0x56,0x34,0x12] + setp 0x12345678 + +// CHECK: setnp %bl +// CHECK: encoding: [0x0f,0x9b,0xc3] + setnp %bl + +// CHECK: setnp 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x9b,0x84,0xcb,0xef,0xbe,0xad,0xde] + setnp 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setnp 32493 +// CHECK: encoding: [0x0f,0x9b,0x05,0xed,0x7e,0x00,0x00] + setnp 0x7eed + +// CHECK: setnp 3133065982 +// CHECK: encoding: [0x0f,0x9b,0x05,0xfe,0xca,0xbe,0xba] + setnp 0xbabecafe + +// CHECK: setnp 305419896 +// CHECK: encoding: [0x0f,0x9b,0x05,0x78,0x56,0x34,0x12] + setnp 0x12345678 + +// CHECK: setl %bl +// CHECK: encoding: [0x0f,0x9c,0xc3] + setl %bl + +// CHECK: setl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x9c,0x84,0xcb,0xef,0xbe,0xad,0xde] + setl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setl 32493 +// CHECK: encoding: [0x0f,0x9c,0x05,0xed,0x7e,0x00,0x00] + setl 0x7eed + +// CHECK: setl 3133065982 +// CHECK: encoding: [0x0f,0x9c,0x05,0xfe,0xca,0xbe,0xba] + setl 0xbabecafe + +// CHECK: setl 305419896 +// CHECK: encoding: [0x0f,0x9c,0x05,0x78,0x56,0x34,0x12] + setl 0x12345678 + +// CHECK: setge %bl +// CHECK: encoding: [0x0f,0x9d,0xc3] + setge %bl + +// CHECK: setge 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x9d,0x84,0xcb,0xef,0xbe,0xad,0xde] + setge 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setge 32493 +// CHECK: encoding: [0x0f,0x9d,0x05,0xed,0x7e,0x00,0x00] + setge 0x7eed + +// CHECK: setge 3133065982 +// CHECK: encoding: [0x0f,0x9d,0x05,0xfe,0xca,0xbe,0xba] + setge 0xbabecafe + +// CHECK: setge 305419896 +// CHECK: encoding: [0x0f,0x9d,0x05,0x78,0x56,0x34,0x12] + setge 0x12345678 + +// CHECK: setle %bl +// CHECK: encoding: [0x0f,0x9e,0xc3] + setle %bl + +// CHECK: setle 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x9e,0x84,0xcb,0xef,0xbe,0xad,0xde] + setle 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setle 32493 +// CHECK: encoding: [0x0f,0x9e,0x05,0xed,0x7e,0x00,0x00] + setle 0x7eed + +// CHECK: setle 3133065982 +// CHECK: encoding: [0x0f,0x9e,0x05,0xfe,0xca,0xbe,0xba] + setle 0xbabecafe + +// CHECK: setle 305419896 +// CHECK: encoding: [0x0f,0x9e,0x05,0x78,0x56,0x34,0x12] + setle 0x12345678 + +// CHECK: setg %bl +// CHECK: encoding: [0x0f,0x9f,0xc3] + setg %bl + +// CHECK: setg 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x9f,0x84,0xcb,0xef,0xbe,0xad,0xde] + setg 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: setg 32493 +// CHECK: encoding: [0x0f,0x9f,0x05,0xed,0x7e,0x00,0x00] + setg 0x7eed + +// CHECK: setg 3133065982 +// CHECK: encoding: [0x0f,0x9f,0x05,0xfe,0xca,0xbe,0xba] + setg 0xbabecafe + +// CHECK: setg 305419896 +// CHECK: encoding: [0x0f,0x9f,0x05,0x78,0x56,0x34,0x12] + setg 0x12345678 + +// CHECK: rsm +// CHECK: encoding: [0x0f,0xaa] + rsm + +// CHECK: hlt +// CHECK: encoding: [0xf4] + hlt + +// CHECK: nopl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x1f,0x84,0xcb,0xef,0xbe,0xad,0xde] + nopl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: nopw 32493 +// CHECK: encoding: [0x66,0x0f,0x1f,0x05,0xed,0x7e,0x00,0x00] + nopw 0x7eed + +// CHECK: nopl 3133065982 +// CHECK: encoding: [0x0f,0x1f,0x05,0xfe,0xca,0xbe,0xba] + nopl 0xbabecafe + +// CHECK: nopl 305419896 +// CHECK: encoding: [0x0f,0x1f,0x05,0x78,0x56,0x34,0x12] + nopl 0x12345678 + +// CHECK: nop +// CHECK: encoding: [0x90] + nop + +// CHECK: lldtw 32493 +// CHECK: encoding: [0x0f,0x00,0x15,0xed,0x7e,0x00,0x00] + lldtw 0x7eed + +// CHECK: lmsww 32493 +// CHECK: encoding: [0x0f,0x01,0x35,0xed,0x7e,0x00,0x00] + lmsww 0x7eed + +// CHECK: ltrw 32493 +// CHECK: encoding: [0x0f,0x00,0x1d,0xed,0x7e,0x00,0x00] + ltrw 0x7eed + +// CHECK: sldtw 32493 +// CHECK: encoding: [0x0f,0x00,0x05,0xed,0x7e,0x00,0x00] + sldtw 0x7eed + +// CHECK: smsww 32493 +// CHECK: encoding: [0x0f,0x01,0x25,0xed,0x7e,0x00,0x00] + smsww 0x7eed + +// CHECK: strw 32493 +// CHECK: encoding: [0x0f,0x00,0x0d,0xed,0x7e,0x00,0x00] + strw 0x7eed + +// CHECK: verr %bx +// CHECK: encoding: [0x0f,0x00,0xe3] + verr %bx + +// CHECK: verr 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x00,0xa4,0xcb,0xef,0xbe,0xad,0xde] + verr 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: verr 3133065982 +// CHECK: encoding: [0x0f,0x00,0x25,0xfe,0xca,0xbe,0xba] + verr 0xbabecafe + +// CHECK: verr 305419896 +// CHECK: encoding: [0x0f,0x00,0x25,0x78,0x56,0x34,0x12] + verr 0x12345678 + +// CHECK: verw %bx +// CHECK: encoding: [0x0f,0x00,0xeb] + verw %bx + +// CHECK: verw 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x00,0xac,0xcb,0xef,0xbe,0xad,0xde] + verw 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: verw 3133065982 +// CHECK: encoding: [0x0f,0x00,0x2d,0xfe,0xca,0xbe,0xba] + verw 0xbabecafe + +// CHECK: verw 305419896 +// CHECK: encoding: [0x0f,0x00,0x2d,0x78,0x56,0x34,0x12] + verw 0x12345678 + +// CHECK: fld %st(2) +// CHECK: encoding: [0xd9,0xc2] + fld %st(2) + +// CHECK: fldl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdd,0x84,0xcb,0xef,0xbe,0xad,0xde] + fldl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fldl 3133065982 +// CHECK: encoding: [0xdd,0x05,0xfe,0xca,0xbe,0xba] + fldl 0xbabecafe + +// CHECK: fldl 305419896 +// CHECK: encoding: [0xdd,0x05,0x78,0x56,0x34,0x12] + fldl 0x12345678 + +// CHECK: fld %st(2) +// CHECK: encoding: [0xd9,0xc2] + fld %st(2) + +// CHECK: fildl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdb,0x84,0xcb,0xef,0xbe,0xad,0xde] + fildl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fildl 3133065982 +// CHECK: encoding: [0xdb,0x05,0xfe,0xca,0xbe,0xba] + fildl 0xbabecafe + +// CHECK: fildl 305419896 +// CHECK: encoding: [0xdb,0x05,0x78,0x56,0x34,0x12] + fildl 0x12345678 + +// CHECK: fildll 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdf,0xac,0xcb,0xef,0xbe,0xad,0xde] + fildll 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fildll 32493 +// CHECK: encoding: [0xdf,0x2d,0xed,0x7e,0x00,0x00] + fildll 0x7eed + +// CHECK: fildll 3133065982 +// CHECK: encoding: [0xdf,0x2d,0xfe,0xca,0xbe,0xba] + fildll 0xbabecafe + +// CHECK: fildll 305419896 +// CHECK: encoding: [0xdf,0x2d,0x78,0x56,0x34,0x12] + fildll 0x12345678 + +// CHECK: fldt 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdb,0xac,0xcb,0xef,0xbe,0xad,0xde] + fldt 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fldt 32493 +// CHECK: encoding: [0xdb,0x2d,0xed,0x7e,0x00,0x00] + fldt 0x7eed + +// CHECK: fldt 3133065982 +// CHECK: encoding: [0xdb,0x2d,0xfe,0xca,0xbe,0xba] + fldt 0xbabecafe + +// CHECK: fldt 305419896 +// CHECK: encoding: [0xdb,0x2d,0x78,0x56,0x34,0x12] + fldt 0x12345678 + +// CHECK: fbld 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdf,0xa4,0xcb,0xef,0xbe,0xad,0xde] + fbld 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fbld 32493 +// CHECK: encoding: [0xdf,0x25,0xed,0x7e,0x00,0x00] + fbld 0x7eed + +// CHECK: fbld 3133065982 +// CHECK: encoding: [0xdf,0x25,0xfe,0xca,0xbe,0xba] + fbld 0xbabecafe + +// CHECK: fbld 305419896 +// CHECK: encoding: [0xdf,0x25,0x78,0x56,0x34,0x12] + fbld 0x12345678 + +// CHECK: fst %st(2) +// CHECK: encoding: [0xdd,0xd2] + fst %st(2) + +// CHECK: fstl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdd,0x94,0xcb,0xef,0xbe,0xad,0xde] + fstl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fstl 3133065982 +// CHECK: encoding: [0xdd,0x15,0xfe,0xca,0xbe,0xba] + fstl 0xbabecafe + +// CHECK: fstl 305419896 +// CHECK: encoding: [0xdd,0x15,0x78,0x56,0x34,0x12] + fstl 0x12345678 + +// CHECK: fst %st(2) +// CHECK: encoding: [0xdd,0xd2] + fst %st(2) + +// CHECK: fistl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdb,0x94,0xcb,0xef,0xbe,0xad,0xde] + fistl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fistl 3133065982 +// CHECK: encoding: [0xdb,0x15,0xfe,0xca,0xbe,0xba] + fistl 0xbabecafe + +// CHECK: fistl 305419896 +// CHECK: encoding: [0xdb,0x15,0x78,0x56,0x34,0x12] + fistl 0x12345678 + +// CHECK: fstp %st(2) +// CHECK: encoding: [0xdd,0xda] + fstp %st(2) + +// CHECK: fstpl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdd,0x9c,0xcb,0xef,0xbe,0xad,0xde] + fstpl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fstpl 3133065982 +// CHECK: encoding: [0xdd,0x1d,0xfe,0xca,0xbe,0xba] + fstpl 0xbabecafe + +// CHECK: fstpl 305419896 +// CHECK: encoding: [0xdd,0x1d,0x78,0x56,0x34,0x12] + fstpl 0x12345678 + +// CHECK: fstp %st(2) +// CHECK: encoding: [0xdd,0xda] + fstp %st(2) + +// CHECK: fistpl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdb,0x9c,0xcb,0xef,0xbe,0xad,0xde] + fistpl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fistpl 3133065982 +// CHECK: encoding: [0xdb,0x1d,0xfe,0xca,0xbe,0xba] + fistpl 0xbabecafe + +// CHECK: fistpl 305419896 +// CHECK: encoding: [0xdb,0x1d,0x78,0x56,0x34,0x12] + fistpl 0x12345678 + +// CHECK: fistpll 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdf,0xbc,0xcb,0xef,0xbe,0xad,0xde] + fistpll 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fistpll 32493 +// CHECK: encoding: [0xdf,0x3d,0xed,0x7e,0x00,0x00] + fistpll 0x7eed + +// CHECK: fistpll 3133065982 +// CHECK: encoding: [0xdf,0x3d,0xfe,0xca,0xbe,0xba] + fistpll 0xbabecafe + +// CHECK: fistpll 305419896 +// CHECK: encoding: [0xdf,0x3d,0x78,0x56,0x34,0x12] + fistpll 0x12345678 + +// CHECK: fstpt 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdb,0xbc,0xcb,0xef,0xbe,0xad,0xde] + fstpt 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fstpt 32493 +// CHECK: encoding: [0xdb,0x3d,0xed,0x7e,0x00,0x00] + fstpt 0x7eed + +// CHECK: fstpt 3133065982 +// CHECK: encoding: [0xdb,0x3d,0xfe,0xca,0xbe,0xba] + fstpt 0xbabecafe + +// CHECK: fstpt 305419896 +// CHECK: encoding: [0xdb,0x3d,0x78,0x56,0x34,0x12] + fstpt 0x12345678 + +// CHECK: fbstp 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdf,0xb4,0xcb,0xef,0xbe,0xad,0xde] + fbstp 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fbstp 32493 +// CHECK: encoding: [0xdf,0x35,0xed,0x7e,0x00,0x00] + fbstp 0x7eed + +// CHECK: fbstp 3133065982 +// CHECK: encoding: [0xdf,0x35,0xfe,0xca,0xbe,0xba] + fbstp 0xbabecafe + +// CHECK: fbstp 305419896 +// CHECK: encoding: [0xdf,0x35,0x78,0x56,0x34,0x12] + fbstp 0x12345678 + +// CHECK: fxch %st(2) +// CHECK: encoding: [0xd9,0xca] + fxch %st(2) + +// CHECK: fcom %st(2) +// CHECK: encoding: [0xd8,0xd2] + fcom %st(2) + +// CHECK: fcom %st(2) +// CHECK: encoding: [0xd8,0xd2] + fcom %st(2) + +// CHECK: ficoml 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xda,0x94,0xcb,0xef,0xbe,0xad,0xde] + ficoml 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: ficoml 3133065982 +// CHECK: encoding: [0xda,0x15,0xfe,0xca,0xbe,0xba] + ficoml 0xbabecafe + +// CHECK: ficoml 305419896 +// CHECK: encoding: [0xda,0x15,0x78,0x56,0x34,0x12] + ficoml 0x12345678 + +// CHECK: fcomp %st(2) +// CHECK: encoding: [0xd8,0xda] + fcomp %st(2) + +// CHECK: fcomp %st(2) +// CHECK: encoding: [0xd8,0xda] + fcomp %st(2) + +// CHECK: ficompl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xda,0x9c,0xcb,0xef,0xbe,0xad,0xde] + ficompl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: ficompl 3133065982 +// CHECK: encoding: [0xda,0x1d,0xfe,0xca,0xbe,0xba] + ficompl 0xbabecafe + +// CHECK: ficompl 305419896 +// CHECK: encoding: [0xda,0x1d,0x78,0x56,0x34,0x12] + ficompl 0x12345678 + +// CHECK: fcompp +// CHECK: encoding: [0xde,0xd9] + fcompp + +// CHECK: fucom %st(2) +// CHECK: encoding: [0xdd,0xe2] + fucom %st(2) + +// CHECK: fucomp %st(2) +// CHECK: encoding: [0xdd,0xea] + fucomp %st(2) + +// CHECK: fucompp +// CHECK: encoding: [0xda,0xe9] + fucompp + +// CHECK: ftst +// CHECK: encoding: [0xd9,0xe4] + ftst + +// CHECK: fxam +// CHECK: encoding: [0xd9,0xe5] + fxam + +// CHECK: fld1 +// CHECK: encoding: [0xd9,0xe8] + fld1 + +// CHECK: fldl2t +// CHECK: encoding: [0xd9,0xe9] + fldl2t + +// CHECK: fldl2e +// CHECK: encoding: [0xd9,0xea] + fldl2e + +// CHECK: fldpi +// CHECK: encoding: [0xd9,0xeb] + fldpi + +// CHECK: fldlg2 +// CHECK: encoding: [0xd9,0xec] + fldlg2 + +// CHECK: fldln2 +// CHECK: encoding: [0xd9,0xed] + fldln2 + +// CHECK: fldz +// CHECK: encoding: [0xd9,0xee] + fldz + +// CHECK: fadd %st(2) +// CHECK: encoding: [0xd8,0xc2] + fadd %st(2) + +// CHECK: faddl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdc,0x84,0xcb,0xef,0xbe,0xad,0xde] + faddl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: faddl 3133065982 +// CHECK: encoding: [0xdc,0x05,0xfe,0xca,0xbe,0xba] + faddl 0xbabecafe + +// CHECK: faddl 305419896 +// CHECK: encoding: [0xdc,0x05,0x78,0x56,0x34,0x12] + faddl 0x12345678 + +// CHECK: fiaddl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xda,0x84,0xcb,0xef,0xbe,0xad,0xde] + fiaddl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fiaddl 3133065982 +// CHECK: encoding: [0xda,0x05,0xfe,0xca,0xbe,0xba] + fiaddl 0xbabecafe + +// CHECK: fiaddl 305419896 +// CHECK: encoding: [0xda,0x05,0x78,0x56,0x34,0x12] + fiaddl 0x12345678 + +// CHECK: faddp %st(2) +// CHECK: encoding: [0xde,0xc2] + faddp %st(2) + +// CHECK: fsub %st(2) +// CHECK: encoding: [0xd8,0xe2] + fsub %st(2) + +// CHECK: fsubl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdc,0xa4,0xcb,0xef,0xbe,0xad,0xde] + fsubl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fsubl 3133065982 +// CHECK: encoding: [0xdc,0x25,0xfe,0xca,0xbe,0xba] + fsubl 0xbabecafe + +// CHECK: fsubl 305419896 +// CHECK: encoding: [0xdc,0x25,0x78,0x56,0x34,0x12] + fsubl 0x12345678 + +// CHECK: fisubl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xda,0xa4,0xcb,0xef,0xbe,0xad,0xde] + fisubl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fisubl 3133065982 +// CHECK: encoding: [0xda,0x25,0xfe,0xca,0xbe,0xba] + fisubl 0xbabecafe + +// CHECK: fisubl 305419896 +// CHECK: encoding: [0xda,0x25,0x78,0x56,0x34,0x12] + fisubl 0x12345678 + +// CHECK: fsubp %st(2) +// CHECK: encoding: [0xde,0xe2] + fsubp %st(2) + +// CHECK: fsubr %st(2) +// CHECK: encoding: [0xd8,0xea] + fsubr %st(2) + +// CHECK: fsubrl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdc,0xac,0xcb,0xef,0xbe,0xad,0xde] + fsubrl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fsubrl 3133065982 +// CHECK: encoding: [0xdc,0x2d,0xfe,0xca,0xbe,0xba] + fsubrl 0xbabecafe + +// CHECK: fsubrl 305419896 +// CHECK: encoding: [0xdc,0x2d,0x78,0x56,0x34,0x12] + fsubrl 0x12345678 + +// CHECK: fisubrl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xda,0xac,0xcb,0xef,0xbe,0xad,0xde] + fisubrl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fisubrl 3133065982 +// CHECK: encoding: [0xda,0x2d,0xfe,0xca,0xbe,0xba] + fisubrl 0xbabecafe + +// CHECK: fisubrl 305419896 +// CHECK: encoding: [0xda,0x2d,0x78,0x56,0x34,0x12] + fisubrl 0x12345678 + +// CHECK: fsubrp %st(2) +// CHECK: encoding: [0xde,0xea] + fsubrp %st(2) + +// CHECK: fmul %st(2) +// CHECK: encoding: [0xd8,0xca] + fmul %st(2) + +// CHECK: fmull 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdc,0x8c,0xcb,0xef,0xbe,0xad,0xde] + fmull 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fmull 3133065982 +// CHECK: encoding: [0xdc,0x0d,0xfe,0xca,0xbe,0xba] + fmull 0xbabecafe + +// CHECK: fmull 305419896 +// CHECK: encoding: [0xdc,0x0d,0x78,0x56,0x34,0x12] + fmull 0x12345678 + +// CHECK: fimull 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xda,0x8c,0xcb,0xef,0xbe,0xad,0xde] + fimull 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fimull 3133065982 +// CHECK: encoding: [0xda,0x0d,0xfe,0xca,0xbe,0xba] + fimull 0xbabecafe + +// CHECK: fimull 305419896 +// CHECK: encoding: [0xda,0x0d,0x78,0x56,0x34,0x12] + fimull 0x12345678 + +// CHECK: fmulp %st(2) +// CHECK: encoding: [0xde,0xca] + fmulp %st(2) + +// CHECK: fdiv %st(2) +// CHECK: encoding: [0xd8,0xf2] + fdiv %st(2) + +// CHECK: fdivl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdc,0xb4,0xcb,0xef,0xbe,0xad,0xde] + fdivl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fdivl 3133065982 +// CHECK: encoding: [0xdc,0x35,0xfe,0xca,0xbe,0xba] + fdivl 0xbabecafe + +// CHECK: fdivl 305419896 +// CHECK: encoding: [0xdc,0x35,0x78,0x56,0x34,0x12] + fdivl 0x12345678 + +// CHECK: fidivl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xda,0xb4,0xcb,0xef,0xbe,0xad,0xde] + fidivl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fidivl 3133065982 +// CHECK: encoding: [0xda,0x35,0xfe,0xca,0xbe,0xba] + fidivl 0xbabecafe + +// CHECK: fidivl 305419896 +// CHECK: encoding: [0xda,0x35,0x78,0x56,0x34,0x12] + fidivl 0x12345678 + +// CHECK: fdivp %st(2) +// CHECK: encoding: [0xde,0xf2] + fdivp %st(2) + +// CHECK: fdivr %st(2) +// CHECK: encoding: [0xd8,0xfa] + fdivr %st(2) + +// CHECK: fdivrl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdc,0xbc,0xcb,0xef,0xbe,0xad,0xde] + fdivrl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fdivrl 3133065982 +// CHECK: encoding: [0xdc,0x3d,0xfe,0xca,0xbe,0xba] + fdivrl 0xbabecafe + +// CHECK: fdivrl 305419896 +// CHECK: encoding: [0xdc,0x3d,0x78,0x56,0x34,0x12] + fdivrl 0x12345678 + +// CHECK: fidivrl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xda,0xbc,0xcb,0xef,0xbe,0xad,0xde] + fidivrl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fidivrl 3133065982 +// CHECK: encoding: [0xda,0x3d,0xfe,0xca,0xbe,0xba] + fidivrl 0xbabecafe + +// CHECK: fidivrl 305419896 +// CHECK: encoding: [0xda,0x3d,0x78,0x56,0x34,0x12] + fidivrl 0x12345678 + +// CHECK: fdivrp %st(2) +// CHECK: encoding: [0xde,0xfa] + fdivrp %st(2) + +// CHECK: f2xm1 +// CHECK: encoding: [0xd9,0xf0] + f2xm1 + +// CHECK: fyl2x +// CHECK: encoding: [0xd9,0xf1] + fyl2x + +// CHECK: fptan +// CHECK: encoding: [0xd9,0xf2] + fptan + +// CHECK: fpatan +// CHECK: encoding: [0xd9,0xf3] + fpatan + +// CHECK: fxtract +// CHECK: encoding: [0xd9,0xf4] + fxtract + +// CHECK: fprem1 +// CHECK: encoding: [0xd9,0xf5] + fprem1 + +// CHECK: fdecstp +// CHECK: encoding: [0xd9,0xf6] + fdecstp + +// CHECK: fincstp +// CHECK: encoding: [0xd9,0xf7] + fincstp + +// CHECK: fprem +// CHECK: encoding: [0xd9,0xf8] + fprem + +// CHECK: fyl2xp1 +// CHECK: encoding: [0xd9,0xf9] + fyl2xp1 + +// CHECK: fsqrt +// CHECK: encoding: [0xd9,0xfa] + fsqrt + +// CHECK: fsincos +// CHECK: encoding: [0xd9,0xfb] + fsincos + +// CHECK: frndint +// CHECK: encoding: [0xd9,0xfc] + frndint + +// CHECK: fscale +// CHECK: encoding: [0xd9,0xfd] + fscale + +// CHECK: fsin +// CHECK: encoding: [0xd9,0xfe] + fsin + +// CHECK: fcos +// CHECK: encoding: [0xd9,0xff] + fcos + +// CHECK: fchs +// CHECK: encoding: [0xd9,0xe0] + fchs + +// CHECK: fabs +// CHECK: encoding: [0xd9,0xe1] + fabs + +// CHECK: fninit +// CHECK: encoding: [0xdb,0xe3] + fninit + +// CHECK: fldcw 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xd9,0xac,0xcb,0xef,0xbe,0xad,0xde] + fldcw 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fldcw 3133065982 +// CHECK: encoding: [0xd9,0x2d,0xfe,0xca,0xbe,0xba] + fldcw 0xbabecafe + +// CHECK: fldcw 305419896 +// CHECK: encoding: [0xd9,0x2d,0x78,0x56,0x34,0x12] + fldcw 0x12345678 + +// CHECK: fnstcw 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xd9,0xbc,0xcb,0xef,0xbe,0xad,0xde] + fnstcw 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fnstcw 3133065982 +// CHECK: encoding: [0xd9,0x3d,0xfe,0xca,0xbe,0xba] + fnstcw 0xbabecafe + +// CHECK: fnstcw 305419896 +// CHECK: encoding: [0xd9,0x3d,0x78,0x56,0x34,0x12] + fnstcw 0x12345678 + +// CHECK: fnstsw 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdd,0xbc,0xcb,0xef,0xbe,0xad,0xde] + fnstsw 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fnstsw 3133065982 +// CHECK: encoding: [0xdd,0x3d,0xfe,0xca,0xbe,0xba] + fnstsw 0xbabecafe + +// CHECK: fnstsw 305419896 +// CHECK: encoding: [0xdd,0x3d,0x78,0x56,0x34,0x12] + fnstsw 0x12345678 + +// CHECK: fnclex +// CHECK: encoding: [0xdb,0xe2] + fnclex + +// CHECK: fnstenv 32493 +// CHECK: encoding: [0xd9,0x35,0xed,0x7e,0x00,0x00] + fnstenv 0x7eed + +// CHECK: fldenv 32493 +// CHECK: encoding: [0xd9,0x25,0xed,0x7e,0x00,0x00] + fldenv 0x7eed + +// CHECK: fnsave 32493 +// CHECK: encoding: [0xdd,0x35,0xed,0x7e,0x00,0x00] + fnsave 0x7eed + +// CHECK: frstor 32493 +// CHECK: encoding: [0xdd,0x25,0xed,0x7e,0x00,0x00] + frstor 0x7eed + +// CHECK: ffree %st(2) +// CHECK: encoding: [0xdd,0xc2] + ffree %st(2) + +// CHECK: fnop +// CHECK: encoding: [0xd9,0xd0] + fnop + +// CHECK: invd +// CHECK: encoding: [0x0f,0x08] + invd + +// CHECK: wbinvd +// CHECK: encoding: [0x0f,0x09] + wbinvd + +// CHECK: cpuid +// CHECK: encoding: [0x0f,0xa2] + cpuid + +// CHECK: wrmsr +// CHECK: encoding: [0x0f,0x30] + wrmsr + +// CHECK: rdtsc +// CHECK: encoding: [0x0f,0x31] + rdtsc + +// CHECK: rdmsr +// CHECK: encoding: [0x0f,0x32] + rdmsr + +// CHECK: cmpxchg8b 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xc7,0x8c,0xcb,0xef,0xbe,0xad,0xde] + cmpxchg8b 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: cmpxchg8b 32493 +// CHECK: encoding: [0x0f,0xc7,0x0d,0xed,0x7e,0x00,0x00] + cmpxchg8b 0x7eed + +// CHECK: cmpxchg8b 3133065982 +// CHECK: encoding: [0x0f,0xc7,0x0d,0xfe,0xca,0xbe,0xba] + cmpxchg8b 0xbabecafe + +// CHECK: cmpxchg8b 305419896 +// CHECK: encoding: [0x0f,0xc7,0x0d,0x78,0x56,0x34,0x12] + cmpxchg8b 0x12345678 + +// CHECK: sysenter +// CHECK: encoding: [0x0f,0x34] + sysenter + +// CHECK: sysexit +// CHECK: encoding: [0x0f,0x35] + sysexit + +// CHECK: fxsave 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xae,0x84,0xcb,0xef,0xbe,0xad,0xde] + fxsave 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fxsave 32493 +// CHECK: encoding: [0x0f,0xae,0x05,0xed,0x7e,0x00,0x00] + fxsave 0x7eed + +// CHECK: fxsave 3133065982 +// CHECK: encoding: [0x0f,0xae,0x05,0xfe,0xca,0xbe,0xba] + fxsave 0xbabecafe + +// CHECK: fxsave 305419896 +// CHECK: encoding: [0x0f,0xae,0x05,0x78,0x56,0x34,0x12] + fxsave 0x12345678 + +// CHECK: fxrstor 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xae,0x8c,0xcb,0xef,0xbe,0xad,0xde] + fxrstor 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fxrstor 32493 +// CHECK: encoding: [0x0f,0xae,0x0d,0xed,0x7e,0x00,0x00] + fxrstor 0x7eed + +// CHECK: fxrstor 3133065982 +// CHECK: encoding: [0x0f,0xae,0x0d,0xfe,0xca,0xbe,0xba] + fxrstor 0xbabecafe + +// CHECK: fxrstor 305419896 +// CHECK: encoding: [0x0f,0xae,0x0d,0x78,0x56,0x34,0x12] + fxrstor 0x12345678 + +// CHECK: rdpmc +// CHECK: encoding: [0x0f,0x33] + rdpmc + +// CHECK: ud2 +// CHECK: encoding: [0x0f,0x0b] + ud2 + +// CHECK: fcmovb %st(2), %st(0) +// CHECK: encoding: [0xda,0xc2] + fcmovb %st(2),%st + +// CHECK: fcmove %st(2), %st(0) +// CHECK: encoding: [0xda,0xca] + fcmove %st(2),%st + +// CHECK: fcmovbe %st(2), %st(0) +// CHECK: encoding: [0xda,0xd2] + fcmovbe %st(2),%st + +// CHECK: fcmovu %st(2), %st(0) +// CHECK: encoding: [0xda,0xda] + fcmovu %st(2),%st + +// CHECK: fcmovnb %st(2), %st(0) +// CHECK: encoding: [0xdb,0xc2] + fcmovnb %st(2),%st + +// CHECK: fcmovne %st(2), %st(0) +// CHECK: encoding: [0xdb,0xca] + fcmovne %st(2),%st + +// CHECK: fcmovnbe %st(2), %st(0) +// CHECK: encoding: [0xdb,0xd2] + fcmovnbe %st(2),%st + +// CHECK: fcmovnu %st(2), %st(0) +// CHECK: encoding: [0xdb,0xda] + fcmovnu %st(2),%st + +// CHECK: fcomi %st(2), %st(0) +// CHECK: encoding: [0xdb,0xf2] + fcomi %st(2),%st + +// CHECK: fucomi %st(2), %st(0) +// CHECK: encoding: [0xdb,0xea] + fucomi %st(2),%st + +// CHECK: fcomip %st(2), %st(0) +// CHECK: encoding: [0xdf,0xf2] + fcomip %st(2),%st + +// CHECK: fucomip %st(2), %st(0) +// CHECK: encoding: [0xdf,0xea] + fucomip %st(2),%st + +// CHECK: movnti %ecx, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xc3,0x8c,0xcb,0xef,0xbe,0xad,0xde] + movnti %ecx,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movnti %ecx, 69 +// CHECK: encoding: [0x0f,0xc3,0x0d,0x45,0x00,0x00,0x00] + movnti %ecx,0x45 + +// CHECK: movnti %ecx, 32493 +// CHECK: encoding: [0x0f,0xc3,0x0d,0xed,0x7e,0x00,0x00] + movnti %ecx,0x7eed + +// CHECK: movnti %ecx, 3133065982 +// CHECK: encoding: [0x0f,0xc3,0x0d,0xfe,0xca,0xbe,0xba] + movnti %ecx,0xbabecafe + +// CHECK: movnti %ecx, 305419896 +// CHECK: encoding: [0x0f,0xc3,0x0d,0x78,0x56,0x34,0x12] + movnti %ecx,0x12345678 + +// CHECK: clflush 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xae,0xbc,0xcb,0xef,0xbe,0xad,0xde] + clflush 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: clflush 32493 +// CHECK: encoding: [0x0f,0xae,0x3d,0xed,0x7e,0x00,0x00] + clflush 0x7eed + +// CHECK: clflush 3133065982 +// CHECK: encoding: [0x0f,0xae,0x3d,0xfe,0xca,0xbe,0xba] + clflush 0xbabecafe + +// CHECK: clflush 305419896 +// CHECK: encoding: [0x0f,0xae,0x3d,0x78,0x56,0x34,0x12] + clflush 0x12345678 + +// CHECK: emms +// CHECK: encoding: [0x0f,0x77] + emms + +// CHECK: movd %ecx, %mm3 +// CHECK: encoding: [0x0f,0x6e,0xd9] + movd %ecx,%mm3 + +// CHECK: movd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x6e,0x9c,0xcb,0xef,0xbe,0xad,0xde] + movd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: movd 69, %mm3 +// CHECK: encoding: [0x0f,0x6e,0x1d,0x45,0x00,0x00,0x00] + movd 0x45,%mm3 + +// CHECK: movd 32493, %mm3 +// CHECK: encoding: [0x0f,0x6e,0x1d,0xed,0x7e,0x00,0x00] + movd 0x7eed,%mm3 + +// CHECK: movd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x6e,0x1d,0xfe,0xca,0xbe,0xba] + movd 0xbabecafe,%mm3 + +// CHECK: movd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x6e,0x1d,0x78,0x56,0x34,0x12] + movd 0x12345678,%mm3 + +// CHECK: movd %mm3, %ecx +// CHECK: encoding: [0x0f,0x7e,0xd9] + movd %mm3,%ecx + +// CHECK: movd %mm3, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x7e,0x9c,0xcb,0xef,0xbe,0xad,0xde] + movd %mm3,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movd %mm3, 69 +// CHECK: encoding: [0x0f,0x7e,0x1d,0x45,0x00,0x00,0x00] + movd %mm3,0x45 + +// CHECK: movd %mm3, 32493 +// CHECK: encoding: [0x0f,0x7e,0x1d,0xed,0x7e,0x00,0x00] + movd %mm3,0x7eed + +// CHECK: movd %mm3, 3133065982 +// CHECK: encoding: [0x0f,0x7e,0x1d,0xfe,0xca,0xbe,0xba] + movd %mm3,0xbabecafe + +// CHECK: movd %mm3, 305419896 +// CHECK: encoding: [0x0f,0x7e,0x1d,0x78,0x56,0x34,0x12] + movd %mm3,0x12345678 + +// CHECK: movd %ecx, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6e,0xe9] + movd %ecx,%xmm5 + +// CHECK: movd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6e,0xac,0xcb,0xef,0xbe,0xad,0xde] + movd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6e,0x2d,0x45,0x00,0x00,0x00] + movd 0x45,%xmm5 + +// CHECK: movd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6e,0x2d,0xed,0x7e,0x00,0x00] + movd 0x7eed,%xmm5 + +// CHECK: movd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6e,0x2d,0xfe,0xca,0xbe,0xba] + movd 0xbabecafe,%xmm5 + +// CHECK: movd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6e,0x2d,0x78,0x56,0x34,0x12] + movd 0x12345678,%xmm5 + +// CHECK: movd %xmm5, %ecx +// CHECK: encoding: [0x66,0x0f,0x7e,0xe9] + movd %xmm5,%ecx + +// CHECK: movd %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0x7e,0xac,0xcb,0xef,0xbe,0xad,0xde] + movd %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movd %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0x7e,0x2d,0x45,0x00,0x00,0x00] + movd %xmm5,0x45 + +// CHECK: movd %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0x7e,0x2d,0xed,0x7e,0x00,0x00] + movd %xmm5,0x7eed + +// CHECK: movd %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0x7e,0x2d,0xfe,0xca,0xbe,0xba] + movd %xmm5,0xbabecafe + +// CHECK: movd %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0x7e,0x2d,0x78,0x56,0x34,0x12] + movd %xmm5,0x12345678 + +// CHECK: movq 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x6f,0x9c,0xcb,0xef,0xbe,0xad,0xde] + movq 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: movq 69, %mm3 +// CHECK: encoding: [0x0f,0x6f,0x1d,0x45,0x00,0x00,0x00] + movq 0x45,%mm3 + +// CHECK: movq 32493, %mm3 +// CHECK: encoding: [0x0f,0x6f,0x1d,0xed,0x7e,0x00,0x00] + movq 0x7eed,%mm3 + +// CHECK: movq 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x6f,0x1d,0xfe,0xca,0xbe,0xba] + movq 0xbabecafe,%mm3 + +// CHECK: movq 305419896, %mm3 +// CHECK: encoding: [0x0f,0x6f,0x1d,0x78,0x56,0x34,0x12] + movq 0x12345678,%mm3 + +// CHECK: movq %mm3, %mm3 +// CHECK: encoding: [0x0f,0x6f,0xdb] + movq %mm3,%mm3 + +// CHECK: movq %mm3, %mm3 +// CHECK: encoding: [0x0f,0x6f,0xdb] + movq %mm3,%mm3 + +// CHECK: movq %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x7e,0xed] + movq %xmm5,%xmm5 + +// CHECK: movq %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0xd6,0xac,0xcb,0xef,0xbe,0xad,0xde] + movq %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movq %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0xd6,0x2d,0x45,0x00,0x00,0x00] + movq %xmm5,0x45 + +// CHECK: movq %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0xd6,0x2d,0xed,0x7e,0x00,0x00] + movq %xmm5,0x7eed + +// CHECK: movq %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0xd6,0x2d,0xfe,0xca,0xbe,0xba] + movq %xmm5,0xbabecafe + +// CHECK: movq %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0xd6,0x2d,0x78,0x56,0x34,0x12] + movq %xmm5,0x12345678 + +// CHECK: movq %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x7e,0xed] + movq %xmm5,%xmm5 + +// CHECK: packssdw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x6b,0x9c,0xcb,0xef,0xbe,0xad,0xde] + packssdw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: packssdw 69, %mm3 +// CHECK: encoding: [0x0f,0x6b,0x1d,0x45,0x00,0x00,0x00] + packssdw 0x45,%mm3 + +// CHECK: packssdw 32493, %mm3 +// CHECK: encoding: [0x0f,0x6b,0x1d,0xed,0x7e,0x00,0x00] + packssdw 0x7eed,%mm3 + +// CHECK: packssdw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x6b,0x1d,0xfe,0xca,0xbe,0xba] + packssdw 0xbabecafe,%mm3 + +// CHECK: packssdw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x6b,0x1d,0x78,0x56,0x34,0x12] + packssdw 0x12345678,%mm3 + +// CHECK: packssdw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x6b,0xdb] + packssdw %mm3,%mm3 + +// CHECK: packssdw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6b,0xac,0xcb,0xef,0xbe,0xad,0xde] + packssdw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: packssdw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6b,0x2d,0x45,0x00,0x00,0x00] + packssdw 0x45,%xmm5 + +// CHECK: packssdw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6b,0x2d,0xed,0x7e,0x00,0x00] + packssdw 0x7eed,%xmm5 + +// CHECK: packssdw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6b,0x2d,0xfe,0xca,0xbe,0xba] + packssdw 0xbabecafe,%xmm5 + +// CHECK: packssdw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6b,0x2d,0x78,0x56,0x34,0x12] + packssdw 0x12345678,%xmm5 + +// CHECK: packssdw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6b,0xed] + packssdw %xmm5,%xmm5 + +// CHECK: packsswb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x63,0x9c,0xcb,0xef,0xbe,0xad,0xde] + packsswb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: packsswb 69, %mm3 +// CHECK: encoding: [0x0f,0x63,0x1d,0x45,0x00,0x00,0x00] + packsswb 0x45,%mm3 + +// CHECK: packsswb 32493, %mm3 +// CHECK: encoding: [0x0f,0x63,0x1d,0xed,0x7e,0x00,0x00] + packsswb 0x7eed,%mm3 + +// CHECK: packsswb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x63,0x1d,0xfe,0xca,0xbe,0xba] + packsswb 0xbabecafe,%mm3 + +// CHECK: packsswb 305419896, %mm3 +// CHECK: encoding: [0x0f,0x63,0x1d,0x78,0x56,0x34,0x12] + packsswb 0x12345678,%mm3 + +// CHECK: packsswb %mm3, %mm3 +// CHECK: encoding: [0x0f,0x63,0xdb] + packsswb %mm3,%mm3 + +// CHECK: packsswb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x63,0xac,0xcb,0xef,0xbe,0xad,0xde] + packsswb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: packsswb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x63,0x2d,0x45,0x00,0x00,0x00] + packsswb 0x45,%xmm5 + +// CHECK: packsswb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x63,0x2d,0xed,0x7e,0x00,0x00] + packsswb 0x7eed,%xmm5 + +// CHECK: packsswb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x63,0x2d,0xfe,0xca,0xbe,0xba] + packsswb 0xbabecafe,%xmm5 + +// CHECK: packsswb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x63,0x2d,0x78,0x56,0x34,0x12] + packsswb 0x12345678,%xmm5 + +// CHECK: packsswb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x63,0xed] + packsswb %xmm5,%xmm5 + +// CHECK: packuswb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x67,0x9c,0xcb,0xef,0xbe,0xad,0xde] + packuswb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: packuswb 69, %mm3 +// CHECK: encoding: [0x0f,0x67,0x1d,0x45,0x00,0x00,0x00] + packuswb 0x45,%mm3 + +// CHECK: packuswb 32493, %mm3 +// CHECK: encoding: [0x0f,0x67,0x1d,0xed,0x7e,0x00,0x00] + packuswb 0x7eed,%mm3 + +// CHECK: packuswb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x67,0x1d,0xfe,0xca,0xbe,0xba] + packuswb 0xbabecafe,%mm3 + +// CHECK: packuswb 305419896, %mm3 +// CHECK: encoding: [0x0f,0x67,0x1d,0x78,0x56,0x34,0x12] + packuswb 0x12345678,%mm3 + +// CHECK: packuswb %mm3, %mm3 +// CHECK: encoding: [0x0f,0x67,0xdb] + packuswb %mm3,%mm3 + +// CHECK: packuswb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x67,0xac,0xcb,0xef,0xbe,0xad,0xde] + packuswb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: packuswb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x67,0x2d,0x45,0x00,0x00,0x00] + packuswb 0x45,%xmm5 + +// CHECK: packuswb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x67,0x2d,0xed,0x7e,0x00,0x00] + packuswb 0x7eed,%xmm5 + +// CHECK: packuswb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x67,0x2d,0xfe,0xca,0xbe,0xba] + packuswb 0xbabecafe,%xmm5 + +// CHECK: packuswb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x67,0x2d,0x78,0x56,0x34,0x12] + packuswb 0x12345678,%xmm5 + +// CHECK: packuswb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x67,0xed] + packuswb %xmm5,%xmm5 + +// CHECK: paddb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xfc,0x9c,0xcb,0xef,0xbe,0xad,0xde] + paddb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: paddb 69, %mm3 +// CHECK: encoding: [0x0f,0xfc,0x1d,0x45,0x00,0x00,0x00] + paddb 0x45,%mm3 + +// CHECK: paddb 32493, %mm3 +// CHECK: encoding: [0x0f,0xfc,0x1d,0xed,0x7e,0x00,0x00] + paddb 0x7eed,%mm3 + +// CHECK: paddb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xfc,0x1d,0xfe,0xca,0xbe,0xba] + paddb 0xbabecafe,%mm3 + +// CHECK: paddb 305419896, %mm3 +// CHECK: encoding: [0x0f,0xfc,0x1d,0x78,0x56,0x34,0x12] + paddb 0x12345678,%mm3 + +// CHECK: paddb %mm3, %mm3 +// CHECK: encoding: [0x0f,0xfc,0xdb] + paddb %mm3,%mm3 + +// CHECK: paddb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfc,0xac,0xcb,0xef,0xbe,0xad,0xde] + paddb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: paddb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfc,0x2d,0x45,0x00,0x00,0x00] + paddb 0x45,%xmm5 + +// CHECK: paddb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfc,0x2d,0xed,0x7e,0x00,0x00] + paddb 0x7eed,%xmm5 + +// CHECK: paddb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfc,0x2d,0xfe,0xca,0xbe,0xba] + paddb 0xbabecafe,%xmm5 + +// CHECK: paddb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfc,0x2d,0x78,0x56,0x34,0x12] + paddb 0x12345678,%xmm5 + +// CHECK: paddb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfc,0xed] + paddb %xmm5,%xmm5 + +// CHECK: paddw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xfd,0x9c,0xcb,0xef,0xbe,0xad,0xde] + paddw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: paddw 69, %mm3 +// CHECK: encoding: [0x0f,0xfd,0x1d,0x45,0x00,0x00,0x00] + paddw 0x45,%mm3 + +// CHECK: paddw 32493, %mm3 +// CHECK: encoding: [0x0f,0xfd,0x1d,0xed,0x7e,0x00,0x00] + paddw 0x7eed,%mm3 + +// CHECK: paddw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xfd,0x1d,0xfe,0xca,0xbe,0xba] + paddw 0xbabecafe,%mm3 + +// CHECK: paddw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xfd,0x1d,0x78,0x56,0x34,0x12] + paddw 0x12345678,%mm3 + +// CHECK: paddw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xfd,0xdb] + paddw %mm3,%mm3 + +// CHECK: paddw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfd,0xac,0xcb,0xef,0xbe,0xad,0xde] + paddw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: paddw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfd,0x2d,0x45,0x00,0x00,0x00] + paddw 0x45,%xmm5 + +// CHECK: paddw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfd,0x2d,0xed,0x7e,0x00,0x00] + paddw 0x7eed,%xmm5 + +// CHECK: paddw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfd,0x2d,0xfe,0xca,0xbe,0xba] + paddw 0xbabecafe,%xmm5 + +// CHECK: paddw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfd,0x2d,0x78,0x56,0x34,0x12] + paddw 0x12345678,%xmm5 + +// CHECK: paddw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfd,0xed] + paddw %xmm5,%xmm5 + +// CHECK: paddd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xfe,0x9c,0xcb,0xef,0xbe,0xad,0xde] + paddd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: paddd 69, %mm3 +// CHECK: encoding: [0x0f,0xfe,0x1d,0x45,0x00,0x00,0x00] + paddd 0x45,%mm3 + +// CHECK: paddd 32493, %mm3 +// CHECK: encoding: [0x0f,0xfe,0x1d,0xed,0x7e,0x00,0x00] + paddd 0x7eed,%mm3 + +// CHECK: paddd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xfe,0x1d,0xfe,0xca,0xbe,0xba] + paddd 0xbabecafe,%mm3 + +// CHECK: paddd 305419896, %mm3 +// CHECK: encoding: [0x0f,0xfe,0x1d,0x78,0x56,0x34,0x12] + paddd 0x12345678,%mm3 + +// CHECK: paddd %mm3, %mm3 +// CHECK: encoding: [0x0f,0xfe,0xdb] + paddd %mm3,%mm3 + +// CHECK: paddd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfe,0xac,0xcb,0xef,0xbe,0xad,0xde] + paddd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: paddd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfe,0x2d,0x45,0x00,0x00,0x00] + paddd 0x45,%xmm5 + +// CHECK: paddd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfe,0x2d,0xed,0x7e,0x00,0x00] + paddd 0x7eed,%xmm5 + +// CHECK: paddd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfe,0x2d,0xfe,0xca,0xbe,0xba] + paddd 0xbabecafe,%xmm5 + +// CHECK: paddd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfe,0x2d,0x78,0x56,0x34,0x12] + paddd 0x12345678,%xmm5 + +// CHECK: paddd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfe,0xed] + paddd %xmm5,%xmm5 + +// CHECK: paddq 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xd4,0x9c,0xcb,0xef,0xbe,0xad,0xde] + paddq 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: paddq 69, %mm3 +// CHECK: encoding: [0x0f,0xd4,0x1d,0x45,0x00,0x00,0x00] + paddq 0x45,%mm3 + +// CHECK: paddq 32493, %mm3 +// CHECK: encoding: [0x0f,0xd4,0x1d,0xed,0x7e,0x00,0x00] + paddq 0x7eed,%mm3 + +// CHECK: paddq 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xd4,0x1d,0xfe,0xca,0xbe,0xba] + paddq 0xbabecafe,%mm3 + +// CHECK: paddq 305419896, %mm3 +// CHECK: encoding: [0x0f,0xd4,0x1d,0x78,0x56,0x34,0x12] + paddq 0x12345678,%mm3 + +// CHECK: paddq %mm3, %mm3 +// CHECK: encoding: [0x0f,0xd4,0xdb] + paddq %mm3,%mm3 + +// CHECK: paddq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd4,0xac,0xcb,0xef,0xbe,0xad,0xde] + paddq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: paddq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd4,0x2d,0x45,0x00,0x00,0x00] + paddq 0x45,%xmm5 + +// CHECK: paddq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd4,0x2d,0xed,0x7e,0x00,0x00] + paddq 0x7eed,%xmm5 + +// CHECK: paddq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd4,0x2d,0xfe,0xca,0xbe,0xba] + paddq 0xbabecafe,%xmm5 + +// CHECK: paddq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd4,0x2d,0x78,0x56,0x34,0x12] + paddq 0x12345678,%xmm5 + +// CHECK: paddq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd4,0xed] + paddq %xmm5,%xmm5 + +// CHECK: paddsb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xec,0x9c,0xcb,0xef,0xbe,0xad,0xde] + paddsb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: paddsb 69, %mm3 +// CHECK: encoding: [0x0f,0xec,0x1d,0x45,0x00,0x00,0x00] + paddsb 0x45,%mm3 + +// CHECK: paddsb 32493, %mm3 +// CHECK: encoding: [0x0f,0xec,0x1d,0xed,0x7e,0x00,0x00] + paddsb 0x7eed,%mm3 + +// CHECK: paddsb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xec,0x1d,0xfe,0xca,0xbe,0xba] + paddsb 0xbabecafe,%mm3 + +// CHECK: paddsb 305419896, %mm3 +// CHECK: encoding: [0x0f,0xec,0x1d,0x78,0x56,0x34,0x12] + paddsb 0x12345678,%mm3 + +// CHECK: paddsb %mm3, %mm3 +// CHECK: encoding: [0x0f,0xec,0xdb] + paddsb %mm3,%mm3 + +// CHECK: paddsb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xec,0xac,0xcb,0xef,0xbe,0xad,0xde] + paddsb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: paddsb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xec,0x2d,0x45,0x00,0x00,0x00] + paddsb 0x45,%xmm5 + +// CHECK: paddsb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xec,0x2d,0xed,0x7e,0x00,0x00] + paddsb 0x7eed,%xmm5 + +// CHECK: paddsb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xec,0x2d,0xfe,0xca,0xbe,0xba] + paddsb 0xbabecafe,%xmm5 + +// CHECK: paddsb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xec,0x2d,0x78,0x56,0x34,0x12] + paddsb 0x12345678,%xmm5 + +// CHECK: paddsb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xec,0xed] + paddsb %xmm5,%xmm5 + +// CHECK: paddsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xed,0x9c,0xcb,0xef,0xbe,0xad,0xde] + paddsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: paddsw 69, %mm3 +// CHECK: encoding: [0x0f,0xed,0x1d,0x45,0x00,0x00,0x00] + paddsw 0x45,%mm3 + +// CHECK: paddsw 32493, %mm3 +// CHECK: encoding: [0x0f,0xed,0x1d,0xed,0x7e,0x00,0x00] + paddsw 0x7eed,%mm3 + +// CHECK: paddsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xed,0x1d,0xfe,0xca,0xbe,0xba] + paddsw 0xbabecafe,%mm3 + +// CHECK: paddsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xed,0x1d,0x78,0x56,0x34,0x12] + paddsw 0x12345678,%mm3 + +// CHECK: paddsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xed,0xdb] + paddsw %mm3,%mm3 + +// CHECK: paddsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xed,0xac,0xcb,0xef,0xbe,0xad,0xde] + paddsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: paddsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xed,0x2d,0x45,0x00,0x00,0x00] + paddsw 0x45,%xmm5 + +// CHECK: paddsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xed,0x2d,0xed,0x7e,0x00,0x00] + paddsw 0x7eed,%xmm5 + +// CHECK: paddsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xed,0x2d,0xfe,0xca,0xbe,0xba] + paddsw 0xbabecafe,%xmm5 + +// CHECK: paddsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xed,0x2d,0x78,0x56,0x34,0x12] + paddsw 0x12345678,%xmm5 + +// CHECK: paddsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xed,0xed] + paddsw %xmm5,%xmm5 + +// CHECK: paddusb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xdc,0x9c,0xcb,0xef,0xbe,0xad,0xde] + paddusb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: paddusb 69, %mm3 +// CHECK: encoding: [0x0f,0xdc,0x1d,0x45,0x00,0x00,0x00] + paddusb 0x45,%mm3 + +// CHECK: paddusb 32493, %mm3 +// CHECK: encoding: [0x0f,0xdc,0x1d,0xed,0x7e,0x00,0x00] + paddusb 0x7eed,%mm3 + +// CHECK: paddusb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xdc,0x1d,0xfe,0xca,0xbe,0xba] + paddusb 0xbabecafe,%mm3 + +// CHECK: paddusb 305419896, %mm3 +// CHECK: encoding: [0x0f,0xdc,0x1d,0x78,0x56,0x34,0x12] + paddusb 0x12345678,%mm3 + +// CHECK: paddusb %mm3, %mm3 +// CHECK: encoding: [0x0f,0xdc,0xdb] + paddusb %mm3,%mm3 + +// CHECK: paddusb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdc,0xac,0xcb,0xef,0xbe,0xad,0xde] + paddusb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: paddusb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdc,0x2d,0x45,0x00,0x00,0x00] + paddusb 0x45,%xmm5 + +// CHECK: paddusb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdc,0x2d,0xed,0x7e,0x00,0x00] + paddusb 0x7eed,%xmm5 + +// CHECK: paddusb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdc,0x2d,0xfe,0xca,0xbe,0xba] + paddusb 0xbabecafe,%xmm5 + +// CHECK: paddusb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdc,0x2d,0x78,0x56,0x34,0x12] + paddusb 0x12345678,%xmm5 + +// CHECK: paddusb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdc,0xed] + paddusb %xmm5,%xmm5 + +// CHECK: paddusw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xdd,0x9c,0xcb,0xef,0xbe,0xad,0xde] + paddusw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: paddusw 69, %mm3 +// CHECK: encoding: [0x0f,0xdd,0x1d,0x45,0x00,0x00,0x00] + paddusw 0x45,%mm3 + +// CHECK: paddusw 32493, %mm3 +// CHECK: encoding: [0x0f,0xdd,0x1d,0xed,0x7e,0x00,0x00] + paddusw 0x7eed,%mm3 + +// CHECK: paddusw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xdd,0x1d,0xfe,0xca,0xbe,0xba] + paddusw 0xbabecafe,%mm3 + +// CHECK: paddusw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xdd,0x1d,0x78,0x56,0x34,0x12] + paddusw 0x12345678,%mm3 + +// CHECK: paddusw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xdd,0xdb] + paddusw %mm3,%mm3 + +// CHECK: paddusw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdd,0xac,0xcb,0xef,0xbe,0xad,0xde] + paddusw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: paddusw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdd,0x2d,0x45,0x00,0x00,0x00] + paddusw 0x45,%xmm5 + +// CHECK: paddusw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdd,0x2d,0xed,0x7e,0x00,0x00] + paddusw 0x7eed,%xmm5 + +// CHECK: paddusw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdd,0x2d,0xfe,0xca,0xbe,0xba] + paddusw 0xbabecafe,%xmm5 + +// CHECK: paddusw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdd,0x2d,0x78,0x56,0x34,0x12] + paddusw 0x12345678,%xmm5 + +// CHECK: paddusw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdd,0xed] + paddusw %xmm5,%xmm5 + +// CHECK: pand 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xdb,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pand 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pand 69, %mm3 +// CHECK: encoding: [0x0f,0xdb,0x1d,0x45,0x00,0x00,0x00] + pand 0x45,%mm3 + +// CHECK: pand 32493, %mm3 +// CHECK: encoding: [0x0f,0xdb,0x1d,0xed,0x7e,0x00,0x00] + pand 0x7eed,%mm3 + +// CHECK: pand 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xdb,0x1d,0xfe,0xca,0xbe,0xba] + pand 0xbabecafe,%mm3 + +// CHECK: pand 305419896, %mm3 +// CHECK: encoding: [0x0f,0xdb,0x1d,0x78,0x56,0x34,0x12] + pand 0x12345678,%mm3 + +// CHECK: pand %mm3, %mm3 +// CHECK: encoding: [0x0f,0xdb,0xdb] + pand %mm3,%mm3 + +// CHECK: pand 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdb,0xac,0xcb,0xef,0xbe,0xad,0xde] + pand 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pand 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdb,0x2d,0x45,0x00,0x00,0x00] + pand 0x45,%xmm5 + +// CHECK: pand 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdb,0x2d,0xed,0x7e,0x00,0x00] + pand 0x7eed,%xmm5 + +// CHECK: pand 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdb,0x2d,0xfe,0xca,0xbe,0xba] + pand 0xbabecafe,%xmm5 + +// CHECK: pand 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdb,0x2d,0x78,0x56,0x34,0x12] + pand 0x12345678,%xmm5 + +// CHECK: pand %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdb,0xed] + pand %xmm5,%xmm5 + +// CHECK: pandn 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xdf,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pandn 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pandn 69, %mm3 +// CHECK: encoding: [0x0f,0xdf,0x1d,0x45,0x00,0x00,0x00] + pandn 0x45,%mm3 + +// CHECK: pandn 32493, %mm3 +// CHECK: encoding: [0x0f,0xdf,0x1d,0xed,0x7e,0x00,0x00] + pandn 0x7eed,%mm3 + +// CHECK: pandn 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xdf,0x1d,0xfe,0xca,0xbe,0xba] + pandn 0xbabecafe,%mm3 + +// CHECK: pandn 305419896, %mm3 +// CHECK: encoding: [0x0f,0xdf,0x1d,0x78,0x56,0x34,0x12] + pandn 0x12345678,%mm3 + +// CHECK: pandn %mm3, %mm3 +// CHECK: encoding: [0x0f,0xdf,0xdb] + pandn %mm3,%mm3 + +// CHECK: pandn 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdf,0xac,0xcb,0xef,0xbe,0xad,0xde] + pandn 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pandn 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdf,0x2d,0x45,0x00,0x00,0x00] + pandn 0x45,%xmm5 + +// CHECK: pandn 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdf,0x2d,0xed,0x7e,0x00,0x00] + pandn 0x7eed,%xmm5 + +// CHECK: pandn 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdf,0x2d,0xfe,0xca,0xbe,0xba] + pandn 0xbabecafe,%xmm5 + +// CHECK: pandn 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdf,0x2d,0x78,0x56,0x34,0x12] + pandn 0x12345678,%xmm5 + +// CHECK: pandn %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xdf,0xed] + pandn %xmm5,%xmm5 + +// CHECK: pcmpeqb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x74,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pcmpeqb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pcmpeqb 69, %mm3 +// CHECK: encoding: [0x0f,0x74,0x1d,0x45,0x00,0x00,0x00] + pcmpeqb 0x45,%mm3 + +// CHECK: pcmpeqb 32493, %mm3 +// CHECK: encoding: [0x0f,0x74,0x1d,0xed,0x7e,0x00,0x00] + pcmpeqb 0x7eed,%mm3 + +// CHECK: pcmpeqb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x74,0x1d,0xfe,0xca,0xbe,0xba] + pcmpeqb 0xbabecafe,%mm3 + +// CHECK: pcmpeqb 305419896, %mm3 +// CHECK: encoding: [0x0f,0x74,0x1d,0x78,0x56,0x34,0x12] + pcmpeqb 0x12345678,%mm3 + +// CHECK: pcmpeqb %mm3, %mm3 +// CHECK: encoding: [0x0f,0x74,0xdb] + pcmpeqb %mm3,%mm3 + +// CHECK: pcmpeqb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x74,0xac,0xcb,0xef,0xbe,0xad,0xde] + pcmpeqb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pcmpeqb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x74,0x2d,0x45,0x00,0x00,0x00] + pcmpeqb 0x45,%xmm5 + +// CHECK: pcmpeqb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x74,0x2d,0xed,0x7e,0x00,0x00] + pcmpeqb 0x7eed,%xmm5 + +// CHECK: pcmpeqb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x74,0x2d,0xfe,0xca,0xbe,0xba] + pcmpeqb 0xbabecafe,%xmm5 + +// CHECK: pcmpeqb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x74,0x2d,0x78,0x56,0x34,0x12] + pcmpeqb 0x12345678,%xmm5 + +// CHECK: pcmpeqb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x74,0xed] + pcmpeqb %xmm5,%xmm5 + +// CHECK: pcmpeqw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x75,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pcmpeqw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pcmpeqw 69, %mm3 +// CHECK: encoding: [0x0f,0x75,0x1d,0x45,0x00,0x00,0x00] + pcmpeqw 0x45,%mm3 + +// CHECK: pcmpeqw 32493, %mm3 +// CHECK: encoding: [0x0f,0x75,0x1d,0xed,0x7e,0x00,0x00] + pcmpeqw 0x7eed,%mm3 + +// CHECK: pcmpeqw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x75,0x1d,0xfe,0xca,0xbe,0xba] + pcmpeqw 0xbabecafe,%mm3 + +// CHECK: pcmpeqw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x75,0x1d,0x78,0x56,0x34,0x12] + pcmpeqw 0x12345678,%mm3 + +// CHECK: pcmpeqw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x75,0xdb] + pcmpeqw %mm3,%mm3 + +// CHECK: pcmpeqw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x75,0xac,0xcb,0xef,0xbe,0xad,0xde] + pcmpeqw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pcmpeqw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x75,0x2d,0x45,0x00,0x00,0x00] + pcmpeqw 0x45,%xmm5 + +// CHECK: pcmpeqw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x75,0x2d,0xed,0x7e,0x00,0x00] + pcmpeqw 0x7eed,%xmm5 + +// CHECK: pcmpeqw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x75,0x2d,0xfe,0xca,0xbe,0xba] + pcmpeqw 0xbabecafe,%xmm5 + +// CHECK: pcmpeqw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x75,0x2d,0x78,0x56,0x34,0x12] + pcmpeqw 0x12345678,%xmm5 + +// CHECK: pcmpeqw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x75,0xed] + pcmpeqw %xmm5,%xmm5 + +// CHECK: pcmpeqd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x76,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pcmpeqd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pcmpeqd 69, %mm3 +// CHECK: encoding: [0x0f,0x76,0x1d,0x45,0x00,0x00,0x00] + pcmpeqd 0x45,%mm3 + +// CHECK: pcmpeqd 32493, %mm3 +// CHECK: encoding: [0x0f,0x76,0x1d,0xed,0x7e,0x00,0x00] + pcmpeqd 0x7eed,%mm3 + +// CHECK: pcmpeqd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x76,0x1d,0xfe,0xca,0xbe,0xba] + pcmpeqd 0xbabecafe,%mm3 + +// CHECK: pcmpeqd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x76,0x1d,0x78,0x56,0x34,0x12] + pcmpeqd 0x12345678,%mm3 + +// CHECK: pcmpeqd %mm3, %mm3 +// CHECK: encoding: [0x0f,0x76,0xdb] + pcmpeqd %mm3,%mm3 + +// CHECK: pcmpeqd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x76,0xac,0xcb,0xef,0xbe,0xad,0xde] + pcmpeqd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pcmpeqd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x76,0x2d,0x45,0x00,0x00,0x00] + pcmpeqd 0x45,%xmm5 + +// CHECK: pcmpeqd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x76,0x2d,0xed,0x7e,0x00,0x00] + pcmpeqd 0x7eed,%xmm5 + +// CHECK: pcmpeqd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x76,0x2d,0xfe,0xca,0xbe,0xba] + pcmpeqd 0xbabecafe,%xmm5 + +// CHECK: pcmpeqd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x76,0x2d,0x78,0x56,0x34,0x12] + pcmpeqd 0x12345678,%xmm5 + +// CHECK: pcmpeqd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x76,0xed] + pcmpeqd %xmm5,%xmm5 + +// CHECK: pcmpgtb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x64,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pcmpgtb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pcmpgtb 69, %mm3 +// CHECK: encoding: [0x0f,0x64,0x1d,0x45,0x00,0x00,0x00] + pcmpgtb 0x45,%mm3 + +// CHECK: pcmpgtb 32493, %mm3 +// CHECK: encoding: [0x0f,0x64,0x1d,0xed,0x7e,0x00,0x00] + pcmpgtb 0x7eed,%mm3 + +// CHECK: pcmpgtb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x64,0x1d,0xfe,0xca,0xbe,0xba] + pcmpgtb 0xbabecafe,%mm3 + +// CHECK: pcmpgtb 305419896, %mm3 +// CHECK: encoding: [0x0f,0x64,0x1d,0x78,0x56,0x34,0x12] + pcmpgtb 0x12345678,%mm3 + +// CHECK: pcmpgtb %mm3, %mm3 +// CHECK: encoding: [0x0f,0x64,0xdb] + pcmpgtb %mm3,%mm3 + +// CHECK: pcmpgtb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x64,0xac,0xcb,0xef,0xbe,0xad,0xde] + pcmpgtb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pcmpgtb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x64,0x2d,0x45,0x00,0x00,0x00] + pcmpgtb 0x45,%xmm5 + +// CHECK: pcmpgtb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x64,0x2d,0xed,0x7e,0x00,0x00] + pcmpgtb 0x7eed,%xmm5 + +// CHECK: pcmpgtb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x64,0x2d,0xfe,0xca,0xbe,0xba] + pcmpgtb 0xbabecafe,%xmm5 + +// CHECK: pcmpgtb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x64,0x2d,0x78,0x56,0x34,0x12] + pcmpgtb 0x12345678,%xmm5 + +// CHECK: pcmpgtb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x64,0xed] + pcmpgtb %xmm5,%xmm5 + +// CHECK: pcmpgtw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x65,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pcmpgtw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pcmpgtw 69, %mm3 +// CHECK: encoding: [0x0f,0x65,0x1d,0x45,0x00,0x00,0x00] + pcmpgtw 0x45,%mm3 + +// CHECK: pcmpgtw 32493, %mm3 +// CHECK: encoding: [0x0f,0x65,0x1d,0xed,0x7e,0x00,0x00] + pcmpgtw 0x7eed,%mm3 + +// CHECK: pcmpgtw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x65,0x1d,0xfe,0xca,0xbe,0xba] + pcmpgtw 0xbabecafe,%mm3 + +// CHECK: pcmpgtw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x65,0x1d,0x78,0x56,0x34,0x12] + pcmpgtw 0x12345678,%mm3 + +// CHECK: pcmpgtw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x65,0xdb] + pcmpgtw %mm3,%mm3 + +// CHECK: pcmpgtw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x65,0xac,0xcb,0xef,0xbe,0xad,0xde] + pcmpgtw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pcmpgtw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x65,0x2d,0x45,0x00,0x00,0x00] + pcmpgtw 0x45,%xmm5 + +// CHECK: pcmpgtw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x65,0x2d,0xed,0x7e,0x00,0x00] + pcmpgtw 0x7eed,%xmm5 + +// CHECK: pcmpgtw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x65,0x2d,0xfe,0xca,0xbe,0xba] + pcmpgtw 0xbabecafe,%xmm5 + +// CHECK: pcmpgtw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x65,0x2d,0x78,0x56,0x34,0x12] + pcmpgtw 0x12345678,%xmm5 + +// CHECK: pcmpgtw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x65,0xed] + pcmpgtw %xmm5,%xmm5 + +// CHECK: pcmpgtd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x66,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pcmpgtd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pcmpgtd 69, %mm3 +// CHECK: encoding: [0x0f,0x66,0x1d,0x45,0x00,0x00,0x00] + pcmpgtd 0x45,%mm3 + +// CHECK: pcmpgtd 32493, %mm3 +// CHECK: encoding: [0x0f,0x66,0x1d,0xed,0x7e,0x00,0x00] + pcmpgtd 0x7eed,%mm3 + +// CHECK: pcmpgtd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x66,0x1d,0xfe,0xca,0xbe,0xba] + pcmpgtd 0xbabecafe,%mm3 + +// CHECK: pcmpgtd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x66,0x1d,0x78,0x56,0x34,0x12] + pcmpgtd 0x12345678,%mm3 + +// CHECK: pcmpgtd %mm3, %mm3 +// CHECK: encoding: [0x0f,0x66,0xdb] + pcmpgtd %mm3,%mm3 + +// CHECK: pcmpgtd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x66,0xac,0xcb,0xef,0xbe,0xad,0xde] + pcmpgtd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pcmpgtd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x66,0x2d,0x45,0x00,0x00,0x00] + pcmpgtd 0x45,%xmm5 + +// CHECK: pcmpgtd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x66,0x2d,0xed,0x7e,0x00,0x00] + pcmpgtd 0x7eed,%xmm5 + +// CHECK: pcmpgtd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x66,0x2d,0xfe,0xca,0xbe,0xba] + pcmpgtd 0xbabecafe,%xmm5 + +// CHECK: pcmpgtd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x66,0x2d,0x78,0x56,0x34,0x12] + pcmpgtd 0x12345678,%xmm5 + +// CHECK: pcmpgtd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x66,0xed] + pcmpgtd %xmm5,%xmm5 + +// CHECK: pmaddwd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xf5,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmaddwd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmaddwd 69, %mm3 +// CHECK: encoding: [0x0f,0xf5,0x1d,0x45,0x00,0x00,0x00] + pmaddwd 0x45,%mm3 + +// CHECK: pmaddwd 32493, %mm3 +// CHECK: encoding: [0x0f,0xf5,0x1d,0xed,0x7e,0x00,0x00] + pmaddwd 0x7eed,%mm3 + +// CHECK: pmaddwd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xf5,0x1d,0xfe,0xca,0xbe,0xba] + pmaddwd 0xbabecafe,%mm3 + +// CHECK: pmaddwd 305419896, %mm3 +// CHECK: encoding: [0x0f,0xf5,0x1d,0x78,0x56,0x34,0x12] + pmaddwd 0x12345678,%mm3 + +// CHECK: pmaddwd %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf5,0xdb] + pmaddwd %mm3,%mm3 + +// CHECK: pmaddwd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf5,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmaddwd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmaddwd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf5,0x2d,0x45,0x00,0x00,0x00] + pmaddwd 0x45,%xmm5 + +// CHECK: pmaddwd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf5,0x2d,0xed,0x7e,0x00,0x00] + pmaddwd 0x7eed,%xmm5 + +// CHECK: pmaddwd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf5,0x2d,0xfe,0xca,0xbe,0xba] + pmaddwd 0xbabecafe,%xmm5 + +// CHECK: pmaddwd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf5,0x2d,0x78,0x56,0x34,0x12] + pmaddwd 0x12345678,%xmm5 + +// CHECK: pmaddwd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf5,0xed] + pmaddwd %xmm5,%xmm5 + +// CHECK: pmulhw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xe5,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmulhw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmulhw 69, %mm3 +// CHECK: encoding: [0x0f,0xe5,0x1d,0x45,0x00,0x00,0x00] + pmulhw 0x45,%mm3 + +// CHECK: pmulhw 32493, %mm3 +// CHECK: encoding: [0x0f,0xe5,0x1d,0xed,0x7e,0x00,0x00] + pmulhw 0x7eed,%mm3 + +// CHECK: pmulhw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xe5,0x1d,0xfe,0xca,0xbe,0xba] + pmulhw 0xbabecafe,%mm3 + +// CHECK: pmulhw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xe5,0x1d,0x78,0x56,0x34,0x12] + pmulhw 0x12345678,%mm3 + +// CHECK: pmulhw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xe5,0xdb] + pmulhw %mm3,%mm3 + +// CHECK: pmulhw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe5,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmulhw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmulhw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe5,0x2d,0x45,0x00,0x00,0x00] + pmulhw 0x45,%xmm5 + +// CHECK: pmulhw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe5,0x2d,0xed,0x7e,0x00,0x00] + pmulhw 0x7eed,%xmm5 + +// CHECK: pmulhw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe5,0x2d,0xfe,0xca,0xbe,0xba] + pmulhw 0xbabecafe,%xmm5 + +// CHECK: pmulhw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe5,0x2d,0x78,0x56,0x34,0x12] + pmulhw 0x12345678,%xmm5 + +// CHECK: pmulhw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe5,0xed] + pmulhw %xmm5,%xmm5 + +// CHECK: pmullw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xd5,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmullw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmullw 69, %mm3 +// CHECK: encoding: [0x0f,0xd5,0x1d,0x45,0x00,0x00,0x00] + pmullw 0x45,%mm3 + +// CHECK: pmullw 32493, %mm3 +// CHECK: encoding: [0x0f,0xd5,0x1d,0xed,0x7e,0x00,0x00] + pmullw 0x7eed,%mm3 + +// CHECK: pmullw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xd5,0x1d,0xfe,0xca,0xbe,0xba] + pmullw 0xbabecafe,%mm3 + +// CHECK: pmullw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xd5,0x1d,0x78,0x56,0x34,0x12] + pmullw 0x12345678,%mm3 + +// CHECK: pmullw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xd5,0xdb] + pmullw %mm3,%mm3 + +// CHECK: pmullw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd5,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmullw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmullw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd5,0x2d,0x45,0x00,0x00,0x00] + pmullw 0x45,%xmm5 + +// CHECK: pmullw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd5,0x2d,0xed,0x7e,0x00,0x00] + pmullw 0x7eed,%xmm5 + +// CHECK: pmullw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd5,0x2d,0xfe,0xca,0xbe,0xba] + pmullw 0xbabecafe,%xmm5 + +// CHECK: pmullw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd5,0x2d,0x78,0x56,0x34,0x12] + pmullw 0x12345678,%xmm5 + +// CHECK: pmullw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd5,0xed] + pmullw %xmm5,%xmm5 + +// CHECK: por 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xeb,0x9c,0xcb,0xef,0xbe,0xad,0xde] + por 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: por 69, %mm3 +// CHECK: encoding: [0x0f,0xeb,0x1d,0x45,0x00,0x00,0x00] + por 0x45,%mm3 + +// CHECK: por 32493, %mm3 +// CHECK: encoding: [0x0f,0xeb,0x1d,0xed,0x7e,0x00,0x00] + por 0x7eed,%mm3 + +// CHECK: por 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xeb,0x1d,0xfe,0xca,0xbe,0xba] + por 0xbabecafe,%mm3 + +// CHECK: por 305419896, %mm3 +// CHECK: encoding: [0x0f,0xeb,0x1d,0x78,0x56,0x34,0x12] + por 0x12345678,%mm3 + +// CHECK: por %mm3, %mm3 +// CHECK: encoding: [0x0f,0xeb,0xdb] + por %mm3,%mm3 + +// CHECK: por 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xeb,0xac,0xcb,0xef,0xbe,0xad,0xde] + por 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: por 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xeb,0x2d,0x45,0x00,0x00,0x00] + por 0x45,%xmm5 + +// CHECK: por 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xeb,0x2d,0xed,0x7e,0x00,0x00] + por 0x7eed,%xmm5 + +// CHECK: por 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xeb,0x2d,0xfe,0xca,0xbe,0xba] + por 0xbabecafe,%xmm5 + +// CHECK: por 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xeb,0x2d,0x78,0x56,0x34,0x12] + por 0x12345678,%xmm5 + +// CHECK: por %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xeb,0xed] + por %xmm5,%xmm5 + +// CHECK: psllw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xf1,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psllw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psllw 69, %mm3 +// CHECK: encoding: [0x0f,0xf1,0x1d,0x45,0x00,0x00,0x00] + psllw 0x45,%mm3 + +// CHECK: psllw 32493, %mm3 +// CHECK: encoding: [0x0f,0xf1,0x1d,0xed,0x7e,0x00,0x00] + psllw 0x7eed,%mm3 + +// CHECK: psllw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xf1,0x1d,0xfe,0xca,0xbe,0xba] + psllw 0xbabecafe,%mm3 + +// CHECK: psllw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xf1,0x1d,0x78,0x56,0x34,0x12] + psllw 0x12345678,%mm3 + +// CHECK: psllw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf1,0xdb] + psllw %mm3,%mm3 + +// CHECK: psllw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf1,0xac,0xcb,0xef,0xbe,0xad,0xde] + psllw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psllw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf1,0x2d,0x45,0x00,0x00,0x00] + psllw 0x45,%xmm5 + +// CHECK: psllw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf1,0x2d,0xed,0x7e,0x00,0x00] + psllw 0x7eed,%xmm5 + +// CHECK: psllw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf1,0x2d,0xfe,0xca,0xbe,0xba] + psllw 0xbabecafe,%xmm5 + +// CHECK: psllw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf1,0x2d,0x78,0x56,0x34,0x12] + psllw 0x12345678,%xmm5 + +// CHECK: psllw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf1,0xed] + psllw %xmm5,%xmm5 + +// CHECK: psllw $127, %mm3 +// CHECK: encoding: [0x0f,0x71,0xf3,0x7f] + psllw $0x7f,%mm3 + +// CHECK: psllw $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x71,0xf5,0x7f] + psllw $0x7f,%xmm5 + +// CHECK: pslld 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xf2,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pslld 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pslld 69, %mm3 +// CHECK: encoding: [0x0f,0xf2,0x1d,0x45,0x00,0x00,0x00] + pslld 0x45,%mm3 + +// CHECK: pslld 32493, %mm3 +// CHECK: encoding: [0x0f,0xf2,0x1d,0xed,0x7e,0x00,0x00] + pslld 0x7eed,%mm3 + +// CHECK: pslld 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xf2,0x1d,0xfe,0xca,0xbe,0xba] + pslld 0xbabecafe,%mm3 + +// CHECK: pslld 305419896, %mm3 +// CHECK: encoding: [0x0f,0xf2,0x1d,0x78,0x56,0x34,0x12] + pslld 0x12345678,%mm3 + +// CHECK: pslld %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf2,0xdb] + pslld %mm3,%mm3 + +// CHECK: pslld 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf2,0xac,0xcb,0xef,0xbe,0xad,0xde] + pslld 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pslld 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf2,0x2d,0x45,0x00,0x00,0x00] + pslld 0x45,%xmm5 + +// CHECK: pslld 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf2,0x2d,0xed,0x7e,0x00,0x00] + pslld 0x7eed,%xmm5 + +// CHECK: pslld 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf2,0x2d,0xfe,0xca,0xbe,0xba] + pslld 0xbabecafe,%xmm5 + +// CHECK: pslld 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf2,0x2d,0x78,0x56,0x34,0x12] + pslld 0x12345678,%xmm5 + +// CHECK: pslld %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf2,0xed] + pslld %xmm5,%xmm5 + +// CHECK: pslld $127, %mm3 +// CHECK: encoding: [0x0f,0x72,0xf3,0x7f] + pslld $0x7f,%mm3 + +// CHECK: pslld $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x72,0xf5,0x7f] + pslld $0x7f,%xmm5 + +// CHECK: psllq 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xf3,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psllq 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psllq 69, %mm3 +// CHECK: encoding: [0x0f,0xf3,0x1d,0x45,0x00,0x00,0x00] + psllq 0x45,%mm3 + +// CHECK: psllq 32493, %mm3 +// CHECK: encoding: [0x0f,0xf3,0x1d,0xed,0x7e,0x00,0x00] + psllq 0x7eed,%mm3 + +// CHECK: psllq 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xf3,0x1d,0xfe,0xca,0xbe,0xba] + psllq 0xbabecafe,%mm3 + +// CHECK: psllq 305419896, %mm3 +// CHECK: encoding: [0x0f,0xf3,0x1d,0x78,0x56,0x34,0x12] + psllq 0x12345678,%mm3 + +// CHECK: psllq %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf3,0xdb] + psllq %mm3,%mm3 + +// CHECK: psllq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf3,0xac,0xcb,0xef,0xbe,0xad,0xde] + psllq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psllq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf3,0x2d,0x45,0x00,0x00,0x00] + psllq 0x45,%xmm5 + +// CHECK: psllq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf3,0x2d,0xed,0x7e,0x00,0x00] + psllq 0x7eed,%xmm5 + +// CHECK: psllq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf3,0x2d,0xfe,0xca,0xbe,0xba] + psllq 0xbabecafe,%xmm5 + +// CHECK: psllq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf3,0x2d,0x78,0x56,0x34,0x12] + psllq 0x12345678,%xmm5 + +// CHECK: psllq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf3,0xed] + psllq %xmm5,%xmm5 + +// CHECK: psllq $127, %mm3 +// CHECK: encoding: [0x0f,0x73,0xf3,0x7f] + psllq $0x7f,%mm3 + +// CHECK: psllq $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x73,0xf5,0x7f] + psllq $0x7f,%xmm5 + +// CHECK: psraw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xe1,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psraw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psraw 69, %mm3 +// CHECK: encoding: [0x0f,0xe1,0x1d,0x45,0x00,0x00,0x00] + psraw 0x45,%mm3 + +// CHECK: psraw 32493, %mm3 +// CHECK: encoding: [0x0f,0xe1,0x1d,0xed,0x7e,0x00,0x00] + psraw 0x7eed,%mm3 + +// CHECK: psraw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xe1,0x1d,0xfe,0xca,0xbe,0xba] + psraw 0xbabecafe,%mm3 + +// CHECK: psraw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xe1,0x1d,0x78,0x56,0x34,0x12] + psraw 0x12345678,%mm3 + +// CHECK: psraw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xe1,0xdb] + psraw %mm3,%mm3 + +// CHECK: psraw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe1,0xac,0xcb,0xef,0xbe,0xad,0xde] + psraw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psraw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe1,0x2d,0x45,0x00,0x00,0x00] + psraw 0x45,%xmm5 + +// CHECK: psraw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe1,0x2d,0xed,0x7e,0x00,0x00] + psraw 0x7eed,%xmm5 + +// CHECK: psraw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe1,0x2d,0xfe,0xca,0xbe,0xba] + psraw 0xbabecafe,%xmm5 + +// CHECK: psraw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe1,0x2d,0x78,0x56,0x34,0x12] + psraw 0x12345678,%xmm5 + +// CHECK: psraw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe1,0xed] + psraw %xmm5,%xmm5 + +// CHECK: psraw $127, %mm3 +// CHECK: encoding: [0x0f,0x71,0xe3,0x7f] + psraw $0x7f,%mm3 + +// CHECK: psraw $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x71,0xe5,0x7f] + psraw $0x7f,%xmm5 + +// CHECK: psrad 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xe2,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psrad 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psrad 69, %mm3 +// CHECK: encoding: [0x0f,0xe2,0x1d,0x45,0x00,0x00,0x00] + psrad 0x45,%mm3 + +// CHECK: psrad 32493, %mm3 +// CHECK: encoding: [0x0f,0xe2,0x1d,0xed,0x7e,0x00,0x00] + psrad 0x7eed,%mm3 + +// CHECK: psrad 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xe2,0x1d,0xfe,0xca,0xbe,0xba] + psrad 0xbabecafe,%mm3 + +// CHECK: psrad 305419896, %mm3 +// CHECK: encoding: [0x0f,0xe2,0x1d,0x78,0x56,0x34,0x12] + psrad 0x12345678,%mm3 + +// CHECK: psrad %mm3, %mm3 +// CHECK: encoding: [0x0f,0xe2,0xdb] + psrad %mm3,%mm3 + +// CHECK: psrad 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe2,0xac,0xcb,0xef,0xbe,0xad,0xde] + psrad 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psrad 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe2,0x2d,0x45,0x00,0x00,0x00] + psrad 0x45,%xmm5 + +// CHECK: psrad 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe2,0x2d,0xed,0x7e,0x00,0x00] + psrad 0x7eed,%xmm5 + +// CHECK: psrad 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe2,0x2d,0xfe,0xca,0xbe,0xba] + psrad 0xbabecafe,%xmm5 + +// CHECK: psrad 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe2,0x2d,0x78,0x56,0x34,0x12] + psrad 0x12345678,%xmm5 + +// CHECK: psrad %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe2,0xed] + psrad %xmm5,%xmm5 + +// CHECK: psrad $127, %mm3 +// CHECK: encoding: [0x0f,0x72,0xe3,0x7f] + psrad $0x7f,%mm3 + +// CHECK: psrad $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x72,0xe5,0x7f] + psrad $0x7f,%xmm5 + +// CHECK: psrlw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xd1,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psrlw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psrlw 69, %mm3 +// CHECK: encoding: [0x0f,0xd1,0x1d,0x45,0x00,0x00,0x00] + psrlw 0x45,%mm3 + +// CHECK: psrlw 32493, %mm3 +// CHECK: encoding: [0x0f,0xd1,0x1d,0xed,0x7e,0x00,0x00] + psrlw 0x7eed,%mm3 + +// CHECK: psrlw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xd1,0x1d,0xfe,0xca,0xbe,0xba] + psrlw 0xbabecafe,%mm3 + +// CHECK: psrlw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xd1,0x1d,0x78,0x56,0x34,0x12] + psrlw 0x12345678,%mm3 + +// CHECK: psrlw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xd1,0xdb] + psrlw %mm3,%mm3 + +// CHECK: psrlw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd1,0xac,0xcb,0xef,0xbe,0xad,0xde] + psrlw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psrlw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd1,0x2d,0x45,0x00,0x00,0x00] + psrlw 0x45,%xmm5 + +// CHECK: psrlw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd1,0x2d,0xed,0x7e,0x00,0x00] + psrlw 0x7eed,%xmm5 + +// CHECK: psrlw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd1,0x2d,0xfe,0xca,0xbe,0xba] + psrlw 0xbabecafe,%xmm5 + +// CHECK: psrlw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd1,0x2d,0x78,0x56,0x34,0x12] + psrlw 0x12345678,%xmm5 + +// CHECK: psrlw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd1,0xed] + psrlw %xmm5,%xmm5 + +// CHECK: psrlw $127, %mm3 +// CHECK: encoding: [0x0f,0x71,0xd3,0x7f] + psrlw $0x7f,%mm3 + +// CHECK: psrlw $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x71,0xd5,0x7f] + psrlw $0x7f,%xmm5 + +// CHECK: psrld 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xd2,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psrld 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psrld 69, %mm3 +// CHECK: encoding: [0x0f,0xd2,0x1d,0x45,0x00,0x00,0x00] + psrld 0x45,%mm3 + +// CHECK: psrld 32493, %mm3 +// CHECK: encoding: [0x0f,0xd2,0x1d,0xed,0x7e,0x00,0x00] + psrld 0x7eed,%mm3 + +// CHECK: psrld 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xd2,0x1d,0xfe,0xca,0xbe,0xba] + psrld 0xbabecafe,%mm3 + +// CHECK: psrld 305419896, %mm3 +// CHECK: encoding: [0x0f,0xd2,0x1d,0x78,0x56,0x34,0x12] + psrld 0x12345678,%mm3 + +// CHECK: psrld %mm3, %mm3 +// CHECK: encoding: [0x0f,0xd2,0xdb] + psrld %mm3,%mm3 + +// CHECK: psrld 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd2,0xac,0xcb,0xef,0xbe,0xad,0xde] + psrld 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psrld 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd2,0x2d,0x45,0x00,0x00,0x00] + psrld 0x45,%xmm5 + +// CHECK: psrld 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd2,0x2d,0xed,0x7e,0x00,0x00] + psrld 0x7eed,%xmm5 + +// CHECK: psrld 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd2,0x2d,0xfe,0xca,0xbe,0xba] + psrld 0xbabecafe,%xmm5 + +// CHECK: psrld 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd2,0x2d,0x78,0x56,0x34,0x12] + psrld 0x12345678,%xmm5 + +// CHECK: psrld %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd2,0xed] + psrld %xmm5,%xmm5 + +// CHECK: psrld $127, %mm3 +// CHECK: encoding: [0x0f,0x72,0xd3,0x7f] + psrld $0x7f,%mm3 + +// CHECK: psrld $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x72,0xd5,0x7f] + psrld $0x7f,%xmm5 + +// CHECK: psrlq 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xd3,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psrlq 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psrlq 69, %mm3 +// CHECK: encoding: [0x0f,0xd3,0x1d,0x45,0x00,0x00,0x00] + psrlq 0x45,%mm3 + +// CHECK: psrlq 32493, %mm3 +// CHECK: encoding: [0x0f,0xd3,0x1d,0xed,0x7e,0x00,0x00] + psrlq 0x7eed,%mm3 + +// CHECK: psrlq 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xd3,0x1d,0xfe,0xca,0xbe,0xba] + psrlq 0xbabecafe,%mm3 + +// CHECK: psrlq 305419896, %mm3 +// CHECK: encoding: [0x0f,0xd3,0x1d,0x78,0x56,0x34,0x12] + psrlq 0x12345678,%mm3 + +// CHECK: psrlq %mm3, %mm3 +// CHECK: encoding: [0x0f,0xd3,0xdb] + psrlq %mm3,%mm3 + +// CHECK: psrlq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd3,0xac,0xcb,0xef,0xbe,0xad,0xde] + psrlq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psrlq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd3,0x2d,0x45,0x00,0x00,0x00] + psrlq 0x45,%xmm5 + +// CHECK: psrlq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd3,0x2d,0xed,0x7e,0x00,0x00] + psrlq 0x7eed,%xmm5 + +// CHECK: psrlq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd3,0x2d,0xfe,0xca,0xbe,0xba] + psrlq 0xbabecafe,%xmm5 + +// CHECK: psrlq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd3,0x2d,0x78,0x56,0x34,0x12] + psrlq 0x12345678,%xmm5 + +// CHECK: psrlq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd3,0xed] + psrlq %xmm5,%xmm5 + +// CHECK: psrlq $127, %mm3 +// CHECK: encoding: [0x0f,0x73,0xd3,0x7f] + psrlq $0x7f,%mm3 + +// CHECK: psrlq $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x73,0xd5,0x7f] + psrlq $0x7f,%xmm5 + +// CHECK: psubb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xf8,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psubb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psubb 69, %mm3 +// CHECK: encoding: [0x0f,0xf8,0x1d,0x45,0x00,0x00,0x00] + psubb 0x45,%mm3 + +// CHECK: psubb 32493, %mm3 +// CHECK: encoding: [0x0f,0xf8,0x1d,0xed,0x7e,0x00,0x00] + psubb 0x7eed,%mm3 + +// CHECK: psubb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xf8,0x1d,0xfe,0xca,0xbe,0xba] + psubb 0xbabecafe,%mm3 + +// CHECK: psubb 305419896, %mm3 +// CHECK: encoding: [0x0f,0xf8,0x1d,0x78,0x56,0x34,0x12] + psubb 0x12345678,%mm3 + +// CHECK: psubb %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf8,0xdb] + psubb %mm3,%mm3 + +// CHECK: psubb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf8,0xac,0xcb,0xef,0xbe,0xad,0xde] + psubb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psubb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf8,0x2d,0x45,0x00,0x00,0x00] + psubb 0x45,%xmm5 + +// CHECK: psubb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf8,0x2d,0xed,0x7e,0x00,0x00] + psubb 0x7eed,%xmm5 + +// CHECK: psubb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf8,0x2d,0xfe,0xca,0xbe,0xba] + psubb 0xbabecafe,%xmm5 + +// CHECK: psubb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf8,0x2d,0x78,0x56,0x34,0x12] + psubb 0x12345678,%xmm5 + +// CHECK: psubb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf8,0xed] + psubb %xmm5,%xmm5 + +// CHECK: psubw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xf9,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psubw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psubw 69, %mm3 +// CHECK: encoding: [0x0f,0xf9,0x1d,0x45,0x00,0x00,0x00] + psubw 0x45,%mm3 + +// CHECK: psubw 32493, %mm3 +// CHECK: encoding: [0x0f,0xf9,0x1d,0xed,0x7e,0x00,0x00] + psubw 0x7eed,%mm3 + +// CHECK: psubw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xf9,0x1d,0xfe,0xca,0xbe,0xba] + psubw 0xbabecafe,%mm3 + +// CHECK: psubw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xf9,0x1d,0x78,0x56,0x34,0x12] + psubw 0x12345678,%mm3 + +// CHECK: psubw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf9,0xdb] + psubw %mm3,%mm3 + +// CHECK: psubw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf9,0xac,0xcb,0xef,0xbe,0xad,0xde] + psubw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psubw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf9,0x2d,0x45,0x00,0x00,0x00] + psubw 0x45,%xmm5 + +// CHECK: psubw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf9,0x2d,0xed,0x7e,0x00,0x00] + psubw 0x7eed,%xmm5 + +// CHECK: psubw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf9,0x2d,0xfe,0xca,0xbe,0xba] + psubw 0xbabecafe,%xmm5 + +// CHECK: psubw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf9,0x2d,0x78,0x56,0x34,0x12] + psubw 0x12345678,%xmm5 + +// CHECK: psubw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf9,0xed] + psubw %xmm5,%xmm5 + +// CHECK: psubd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xfa,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psubd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psubd 69, %mm3 +// CHECK: encoding: [0x0f,0xfa,0x1d,0x45,0x00,0x00,0x00] + psubd 0x45,%mm3 + +// CHECK: psubd 32493, %mm3 +// CHECK: encoding: [0x0f,0xfa,0x1d,0xed,0x7e,0x00,0x00] + psubd 0x7eed,%mm3 + +// CHECK: psubd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xfa,0x1d,0xfe,0xca,0xbe,0xba] + psubd 0xbabecafe,%mm3 + +// CHECK: psubd 305419896, %mm3 +// CHECK: encoding: [0x0f,0xfa,0x1d,0x78,0x56,0x34,0x12] + psubd 0x12345678,%mm3 + +// CHECK: psubd %mm3, %mm3 +// CHECK: encoding: [0x0f,0xfa,0xdb] + psubd %mm3,%mm3 + +// CHECK: psubd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfa,0xac,0xcb,0xef,0xbe,0xad,0xde] + psubd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psubd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfa,0x2d,0x45,0x00,0x00,0x00] + psubd 0x45,%xmm5 + +// CHECK: psubd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfa,0x2d,0xed,0x7e,0x00,0x00] + psubd 0x7eed,%xmm5 + +// CHECK: psubd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfa,0x2d,0xfe,0xca,0xbe,0xba] + psubd 0xbabecafe,%xmm5 + +// CHECK: psubd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfa,0x2d,0x78,0x56,0x34,0x12] + psubd 0x12345678,%xmm5 + +// CHECK: psubd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfa,0xed] + psubd %xmm5,%xmm5 + +// CHECK: psubq 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xfb,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psubq 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psubq 69, %mm3 +// CHECK: encoding: [0x0f,0xfb,0x1d,0x45,0x00,0x00,0x00] + psubq 0x45,%mm3 + +// CHECK: psubq 32493, %mm3 +// CHECK: encoding: [0x0f,0xfb,0x1d,0xed,0x7e,0x00,0x00] + psubq 0x7eed,%mm3 + +// CHECK: psubq 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xfb,0x1d,0xfe,0xca,0xbe,0xba] + psubq 0xbabecafe,%mm3 + +// CHECK: psubq 305419896, %mm3 +// CHECK: encoding: [0x0f,0xfb,0x1d,0x78,0x56,0x34,0x12] + psubq 0x12345678,%mm3 + +// CHECK: psubq %mm3, %mm3 +// CHECK: encoding: [0x0f,0xfb,0xdb] + psubq %mm3,%mm3 + +// CHECK: psubq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfb,0xac,0xcb,0xef,0xbe,0xad,0xde] + psubq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psubq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfb,0x2d,0x45,0x00,0x00,0x00] + psubq 0x45,%xmm5 + +// CHECK: psubq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfb,0x2d,0xed,0x7e,0x00,0x00] + psubq 0x7eed,%xmm5 + +// CHECK: psubq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfb,0x2d,0xfe,0xca,0xbe,0xba] + psubq 0xbabecafe,%xmm5 + +// CHECK: psubq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfb,0x2d,0x78,0x56,0x34,0x12] + psubq 0x12345678,%xmm5 + +// CHECK: psubq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xfb,0xed] + psubq %xmm5,%xmm5 + +// CHECK: psubsb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xe8,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psubsb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psubsb 69, %mm3 +// CHECK: encoding: [0x0f,0xe8,0x1d,0x45,0x00,0x00,0x00] + psubsb 0x45,%mm3 + +// CHECK: psubsb 32493, %mm3 +// CHECK: encoding: [0x0f,0xe8,0x1d,0xed,0x7e,0x00,0x00] + psubsb 0x7eed,%mm3 + +// CHECK: psubsb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xe8,0x1d,0xfe,0xca,0xbe,0xba] + psubsb 0xbabecafe,%mm3 + +// CHECK: psubsb 305419896, %mm3 +// CHECK: encoding: [0x0f,0xe8,0x1d,0x78,0x56,0x34,0x12] + psubsb 0x12345678,%mm3 + +// CHECK: psubsb %mm3, %mm3 +// CHECK: encoding: [0x0f,0xe8,0xdb] + psubsb %mm3,%mm3 + +// CHECK: psubsb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe8,0xac,0xcb,0xef,0xbe,0xad,0xde] + psubsb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psubsb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe8,0x2d,0x45,0x00,0x00,0x00] + psubsb 0x45,%xmm5 + +// CHECK: psubsb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe8,0x2d,0xed,0x7e,0x00,0x00] + psubsb 0x7eed,%xmm5 + +// CHECK: psubsb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe8,0x2d,0xfe,0xca,0xbe,0xba] + psubsb 0xbabecafe,%xmm5 + +// CHECK: psubsb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe8,0x2d,0x78,0x56,0x34,0x12] + psubsb 0x12345678,%xmm5 + +// CHECK: psubsb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe8,0xed] + psubsb %xmm5,%xmm5 + +// CHECK: psubsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xe9,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psubsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psubsw 69, %mm3 +// CHECK: encoding: [0x0f,0xe9,0x1d,0x45,0x00,0x00,0x00] + psubsw 0x45,%mm3 + +// CHECK: psubsw 32493, %mm3 +// CHECK: encoding: [0x0f,0xe9,0x1d,0xed,0x7e,0x00,0x00] + psubsw 0x7eed,%mm3 + +// CHECK: psubsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xe9,0x1d,0xfe,0xca,0xbe,0xba] + psubsw 0xbabecafe,%mm3 + +// CHECK: psubsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xe9,0x1d,0x78,0x56,0x34,0x12] + psubsw 0x12345678,%mm3 + +// CHECK: psubsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xe9,0xdb] + psubsw %mm3,%mm3 + +// CHECK: psubsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe9,0xac,0xcb,0xef,0xbe,0xad,0xde] + psubsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psubsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe9,0x2d,0x45,0x00,0x00,0x00] + psubsw 0x45,%xmm5 + +// CHECK: psubsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe9,0x2d,0xed,0x7e,0x00,0x00] + psubsw 0x7eed,%xmm5 + +// CHECK: psubsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe9,0x2d,0xfe,0xca,0xbe,0xba] + psubsw 0xbabecafe,%xmm5 + +// CHECK: psubsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe9,0x2d,0x78,0x56,0x34,0x12] + psubsw 0x12345678,%xmm5 + +// CHECK: psubsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe9,0xed] + psubsw %xmm5,%xmm5 + +// CHECK: psubusb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xd8,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psubusb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psubusb 69, %mm3 +// CHECK: encoding: [0x0f,0xd8,0x1d,0x45,0x00,0x00,0x00] + psubusb 0x45,%mm3 + +// CHECK: psubusb 32493, %mm3 +// CHECK: encoding: [0x0f,0xd8,0x1d,0xed,0x7e,0x00,0x00] + psubusb 0x7eed,%mm3 + +// CHECK: psubusb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xd8,0x1d,0xfe,0xca,0xbe,0xba] + psubusb 0xbabecafe,%mm3 + +// CHECK: psubusb 305419896, %mm3 +// CHECK: encoding: [0x0f,0xd8,0x1d,0x78,0x56,0x34,0x12] + psubusb 0x12345678,%mm3 + +// CHECK: psubusb %mm3, %mm3 +// CHECK: encoding: [0x0f,0xd8,0xdb] + psubusb %mm3,%mm3 + +// CHECK: psubusb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd8,0xac,0xcb,0xef,0xbe,0xad,0xde] + psubusb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psubusb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd8,0x2d,0x45,0x00,0x00,0x00] + psubusb 0x45,%xmm5 + +// CHECK: psubusb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd8,0x2d,0xed,0x7e,0x00,0x00] + psubusb 0x7eed,%xmm5 + +// CHECK: psubusb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd8,0x2d,0xfe,0xca,0xbe,0xba] + psubusb 0xbabecafe,%xmm5 + +// CHECK: psubusb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd8,0x2d,0x78,0x56,0x34,0x12] + psubusb 0x12345678,%xmm5 + +// CHECK: psubusb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd8,0xed] + psubusb %xmm5,%xmm5 + +// CHECK: psubusw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xd9,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psubusw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psubusw 69, %mm3 +// CHECK: encoding: [0x0f,0xd9,0x1d,0x45,0x00,0x00,0x00] + psubusw 0x45,%mm3 + +// CHECK: psubusw 32493, %mm3 +// CHECK: encoding: [0x0f,0xd9,0x1d,0xed,0x7e,0x00,0x00] + psubusw 0x7eed,%mm3 + +// CHECK: psubusw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xd9,0x1d,0xfe,0xca,0xbe,0xba] + psubusw 0xbabecafe,%mm3 + +// CHECK: psubusw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xd9,0x1d,0x78,0x56,0x34,0x12] + psubusw 0x12345678,%mm3 + +// CHECK: psubusw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xd9,0xdb] + psubusw %mm3,%mm3 + +// CHECK: psubusw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd9,0xac,0xcb,0xef,0xbe,0xad,0xde] + psubusw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psubusw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd9,0x2d,0x45,0x00,0x00,0x00] + psubusw 0x45,%xmm5 + +// CHECK: psubusw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd9,0x2d,0xed,0x7e,0x00,0x00] + psubusw 0x7eed,%xmm5 + +// CHECK: psubusw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd9,0x2d,0xfe,0xca,0xbe,0xba] + psubusw 0xbabecafe,%xmm5 + +// CHECK: psubusw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd9,0x2d,0x78,0x56,0x34,0x12] + psubusw 0x12345678,%xmm5 + +// CHECK: psubusw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd9,0xed] + psubusw %xmm5,%xmm5 + +// CHECK: punpckhbw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x68,0x9c,0xcb,0xef,0xbe,0xad,0xde] + punpckhbw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: punpckhbw 69, %mm3 +// CHECK: encoding: [0x0f,0x68,0x1d,0x45,0x00,0x00,0x00] + punpckhbw 0x45,%mm3 + +// CHECK: punpckhbw 32493, %mm3 +// CHECK: encoding: [0x0f,0x68,0x1d,0xed,0x7e,0x00,0x00] + punpckhbw 0x7eed,%mm3 + +// CHECK: punpckhbw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x68,0x1d,0xfe,0xca,0xbe,0xba] + punpckhbw 0xbabecafe,%mm3 + +// CHECK: punpckhbw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x68,0x1d,0x78,0x56,0x34,0x12] + punpckhbw 0x12345678,%mm3 + +// CHECK: punpckhbw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x68,0xdb] + punpckhbw %mm3,%mm3 + +// CHECK: punpckhbw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x68,0xac,0xcb,0xef,0xbe,0xad,0xde] + punpckhbw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: punpckhbw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x68,0x2d,0x45,0x00,0x00,0x00] + punpckhbw 0x45,%xmm5 + +// CHECK: punpckhbw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x68,0x2d,0xed,0x7e,0x00,0x00] + punpckhbw 0x7eed,%xmm5 + +// CHECK: punpckhbw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x68,0x2d,0xfe,0xca,0xbe,0xba] + punpckhbw 0xbabecafe,%xmm5 + +// CHECK: punpckhbw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x68,0x2d,0x78,0x56,0x34,0x12] + punpckhbw 0x12345678,%xmm5 + +// CHECK: punpckhbw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x68,0xed] + punpckhbw %xmm5,%xmm5 + +// CHECK: punpckhwd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x69,0x9c,0xcb,0xef,0xbe,0xad,0xde] + punpckhwd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: punpckhwd 69, %mm3 +// CHECK: encoding: [0x0f,0x69,0x1d,0x45,0x00,0x00,0x00] + punpckhwd 0x45,%mm3 + +// CHECK: punpckhwd 32493, %mm3 +// CHECK: encoding: [0x0f,0x69,0x1d,0xed,0x7e,0x00,0x00] + punpckhwd 0x7eed,%mm3 + +// CHECK: punpckhwd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x69,0x1d,0xfe,0xca,0xbe,0xba] + punpckhwd 0xbabecafe,%mm3 + +// CHECK: punpckhwd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x69,0x1d,0x78,0x56,0x34,0x12] + punpckhwd 0x12345678,%mm3 + +// CHECK: punpckhwd %mm3, %mm3 +// CHECK: encoding: [0x0f,0x69,0xdb] + punpckhwd %mm3,%mm3 + +// CHECK: punpckhwd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x69,0xac,0xcb,0xef,0xbe,0xad,0xde] + punpckhwd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: punpckhwd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x69,0x2d,0x45,0x00,0x00,0x00] + punpckhwd 0x45,%xmm5 + +// CHECK: punpckhwd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x69,0x2d,0xed,0x7e,0x00,0x00] + punpckhwd 0x7eed,%xmm5 + +// CHECK: punpckhwd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x69,0x2d,0xfe,0xca,0xbe,0xba] + punpckhwd 0xbabecafe,%xmm5 + +// CHECK: punpckhwd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x69,0x2d,0x78,0x56,0x34,0x12] + punpckhwd 0x12345678,%xmm5 + +// CHECK: punpckhwd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x69,0xed] + punpckhwd %xmm5,%xmm5 + +// CHECK: punpckhdq 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x6a,0x9c,0xcb,0xef,0xbe,0xad,0xde] + punpckhdq 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: punpckhdq 69, %mm3 +// CHECK: encoding: [0x0f,0x6a,0x1d,0x45,0x00,0x00,0x00] + punpckhdq 0x45,%mm3 + +// CHECK: punpckhdq 32493, %mm3 +// CHECK: encoding: [0x0f,0x6a,0x1d,0xed,0x7e,0x00,0x00] + punpckhdq 0x7eed,%mm3 + +// CHECK: punpckhdq 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x6a,0x1d,0xfe,0xca,0xbe,0xba] + punpckhdq 0xbabecafe,%mm3 + +// CHECK: punpckhdq 305419896, %mm3 +// CHECK: encoding: [0x0f,0x6a,0x1d,0x78,0x56,0x34,0x12] + punpckhdq 0x12345678,%mm3 + +// CHECK: punpckhdq %mm3, %mm3 +// CHECK: encoding: [0x0f,0x6a,0xdb] + punpckhdq %mm3,%mm3 + +// CHECK: punpckhdq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6a,0xac,0xcb,0xef,0xbe,0xad,0xde] + punpckhdq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: punpckhdq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6a,0x2d,0x45,0x00,0x00,0x00] + punpckhdq 0x45,%xmm5 + +// CHECK: punpckhdq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6a,0x2d,0xed,0x7e,0x00,0x00] + punpckhdq 0x7eed,%xmm5 + +// CHECK: punpckhdq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6a,0x2d,0xfe,0xca,0xbe,0xba] + punpckhdq 0xbabecafe,%xmm5 + +// CHECK: punpckhdq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6a,0x2d,0x78,0x56,0x34,0x12] + punpckhdq 0x12345678,%xmm5 + +// CHECK: punpckhdq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6a,0xed] + punpckhdq %xmm5,%xmm5 + +// CHECK: punpcklbw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x60,0x9c,0xcb,0xef,0xbe,0xad,0xde] + punpcklbw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: punpcklbw 69, %mm3 +// CHECK: encoding: [0x0f,0x60,0x1d,0x45,0x00,0x00,0x00] + punpcklbw 0x45,%mm3 + +// CHECK: punpcklbw 32493, %mm3 +// CHECK: encoding: [0x0f,0x60,0x1d,0xed,0x7e,0x00,0x00] + punpcklbw 0x7eed,%mm3 + +// CHECK: punpcklbw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x60,0x1d,0xfe,0xca,0xbe,0xba] + punpcklbw 0xbabecafe,%mm3 + +// CHECK: punpcklbw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x60,0x1d,0x78,0x56,0x34,0x12] + punpcklbw 0x12345678,%mm3 + +// CHECK: punpcklbw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x60,0xdb] + punpcklbw %mm3,%mm3 + +// CHECK: punpcklbw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x60,0xac,0xcb,0xef,0xbe,0xad,0xde] + punpcklbw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: punpcklbw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x60,0x2d,0x45,0x00,0x00,0x00] + punpcklbw 0x45,%xmm5 + +// CHECK: punpcklbw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x60,0x2d,0xed,0x7e,0x00,0x00] + punpcklbw 0x7eed,%xmm5 + +// CHECK: punpcklbw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x60,0x2d,0xfe,0xca,0xbe,0xba] + punpcklbw 0xbabecafe,%xmm5 + +// CHECK: punpcklbw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x60,0x2d,0x78,0x56,0x34,0x12] + punpcklbw 0x12345678,%xmm5 + +// CHECK: punpcklbw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x60,0xed] + punpcklbw %xmm5,%xmm5 + +// CHECK: punpcklwd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x61,0x9c,0xcb,0xef,0xbe,0xad,0xde] + punpcklwd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: punpcklwd 69, %mm3 +// CHECK: encoding: [0x0f,0x61,0x1d,0x45,0x00,0x00,0x00] + punpcklwd 0x45,%mm3 + +// CHECK: punpcklwd 32493, %mm3 +// CHECK: encoding: [0x0f,0x61,0x1d,0xed,0x7e,0x00,0x00] + punpcklwd 0x7eed,%mm3 + +// CHECK: punpcklwd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x61,0x1d,0xfe,0xca,0xbe,0xba] + punpcklwd 0xbabecafe,%mm3 + +// CHECK: punpcklwd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x61,0x1d,0x78,0x56,0x34,0x12] + punpcklwd 0x12345678,%mm3 + +// CHECK: punpcklwd %mm3, %mm3 +// CHECK: encoding: [0x0f,0x61,0xdb] + punpcklwd %mm3,%mm3 + +// CHECK: punpcklwd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x61,0xac,0xcb,0xef,0xbe,0xad,0xde] + punpcklwd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: punpcklwd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x61,0x2d,0x45,0x00,0x00,0x00] + punpcklwd 0x45,%xmm5 + +// CHECK: punpcklwd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x61,0x2d,0xed,0x7e,0x00,0x00] + punpcklwd 0x7eed,%xmm5 + +// CHECK: punpcklwd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x61,0x2d,0xfe,0xca,0xbe,0xba] + punpcklwd 0xbabecafe,%xmm5 + +// CHECK: punpcklwd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x61,0x2d,0x78,0x56,0x34,0x12] + punpcklwd 0x12345678,%xmm5 + +// CHECK: punpcklwd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x61,0xed] + punpcklwd %xmm5,%xmm5 + +// CHECK: punpckldq 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x62,0x9c,0xcb,0xef,0xbe,0xad,0xde] + punpckldq 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: punpckldq 69, %mm3 +// CHECK: encoding: [0x0f,0x62,0x1d,0x45,0x00,0x00,0x00] + punpckldq 0x45,%mm3 + +// CHECK: punpckldq 32493, %mm3 +// CHECK: encoding: [0x0f,0x62,0x1d,0xed,0x7e,0x00,0x00] + punpckldq 0x7eed,%mm3 + +// CHECK: punpckldq 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x62,0x1d,0xfe,0xca,0xbe,0xba] + punpckldq 0xbabecafe,%mm3 + +// CHECK: punpckldq 305419896, %mm3 +// CHECK: encoding: [0x0f,0x62,0x1d,0x78,0x56,0x34,0x12] + punpckldq 0x12345678,%mm3 + +// CHECK: punpckldq %mm3, %mm3 +// CHECK: encoding: [0x0f,0x62,0xdb] + punpckldq %mm3,%mm3 + +// CHECK: punpckldq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x62,0xac,0xcb,0xef,0xbe,0xad,0xde] + punpckldq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: punpckldq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x62,0x2d,0x45,0x00,0x00,0x00] + punpckldq 0x45,%xmm5 + +// CHECK: punpckldq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x62,0x2d,0xed,0x7e,0x00,0x00] + punpckldq 0x7eed,%xmm5 + +// CHECK: punpckldq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x62,0x2d,0xfe,0xca,0xbe,0xba] + punpckldq 0xbabecafe,%xmm5 + +// CHECK: punpckldq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x62,0x2d,0x78,0x56,0x34,0x12] + punpckldq 0x12345678,%xmm5 + +// CHECK: punpckldq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x62,0xed] + punpckldq %xmm5,%xmm5 + +// CHECK: pxor 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xef,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pxor 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pxor 69, %mm3 +// CHECK: encoding: [0x0f,0xef,0x1d,0x45,0x00,0x00,0x00] + pxor 0x45,%mm3 + +// CHECK: pxor 32493, %mm3 +// CHECK: encoding: [0x0f,0xef,0x1d,0xed,0x7e,0x00,0x00] + pxor 0x7eed,%mm3 + +// CHECK: pxor 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xef,0x1d,0xfe,0xca,0xbe,0xba] + pxor 0xbabecafe,%mm3 + +// CHECK: pxor 305419896, %mm3 +// CHECK: encoding: [0x0f,0xef,0x1d,0x78,0x56,0x34,0x12] + pxor 0x12345678,%mm3 + +// CHECK: pxor %mm3, %mm3 +// CHECK: encoding: [0x0f,0xef,0xdb] + pxor %mm3,%mm3 + +// CHECK: pxor 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xef,0xac,0xcb,0xef,0xbe,0xad,0xde] + pxor 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pxor 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xef,0x2d,0x45,0x00,0x00,0x00] + pxor 0x45,%xmm5 + +// CHECK: pxor 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xef,0x2d,0xed,0x7e,0x00,0x00] + pxor 0x7eed,%xmm5 + +// CHECK: pxor 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xef,0x2d,0xfe,0xca,0xbe,0xba] + pxor 0xbabecafe,%xmm5 + +// CHECK: pxor 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xef,0x2d,0x78,0x56,0x34,0x12] + pxor 0x12345678,%xmm5 + +// CHECK: pxor %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xef,0xed] + pxor %xmm5,%xmm5 + +// CHECK: addps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x58,0xac,0xcb,0xef,0xbe,0xad,0xde] + addps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: addps 69, %xmm5 +// CHECK: encoding: [0x0f,0x58,0x2d,0x45,0x00,0x00,0x00] + addps 0x45,%xmm5 + +// CHECK: addps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x58,0x2d,0xed,0x7e,0x00,0x00] + addps 0x7eed,%xmm5 + +// CHECK: addps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x58,0x2d,0xfe,0xca,0xbe,0xba] + addps 0xbabecafe,%xmm5 + +// CHECK: addps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x58,0x2d,0x78,0x56,0x34,0x12] + addps 0x12345678,%xmm5 + +// CHECK: addps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x58,0xed] + addps %xmm5,%xmm5 + +// CHECK: addss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x58,0xac,0xcb,0xef,0xbe,0xad,0xde] + addss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: addss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x58,0x2d,0x45,0x00,0x00,0x00] + addss 0x45,%xmm5 + +// CHECK: addss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x58,0x2d,0xed,0x7e,0x00,0x00] + addss 0x7eed,%xmm5 + +// CHECK: addss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x58,0x2d,0xfe,0xca,0xbe,0xba] + addss 0xbabecafe,%xmm5 + +// CHECK: addss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x58,0x2d,0x78,0x56,0x34,0x12] + addss 0x12345678,%xmm5 + +// CHECK: addss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x58,0xed] + addss %xmm5,%xmm5 + +// CHECK: andnps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x55,0xac,0xcb,0xef,0xbe,0xad,0xde] + andnps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: andnps 69, %xmm5 +// CHECK: encoding: [0x0f,0x55,0x2d,0x45,0x00,0x00,0x00] + andnps 0x45,%xmm5 + +// CHECK: andnps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x55,0x2d,0xed,0x7e,0x00,0x00] + andnps 0x7eed,%xmm5 + +// CHECK: andnps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x55,0x2d,0xfe,0xca,0xbe,0xba] + andnps 0xbabecafe,%xmm5 + +// CHECK: andnps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x55,0x2d,0x78,0x56,0x34,0x12] + andnps 0x12345678,%xmm5 + +// CHECK: andnps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x55,0xed] + andnps %xmm5,%xmm5 + +// CHECK: andps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x54,0xac,0xcb,0xef,0xbe,0xad,0xde] + andps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: andps 69, %xmm5 +// CHECK: encoding: [0x0f,0x54,0x2d,0x45,0x00,0x00,0x00] + andps 0x45,%xmm5 + +// CHECK: andps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x54,0x2d,0xed,0x7e,0x00,0x00] + andps 0x7eed,%xmm5 + +// CHECK: andps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x54,0x2d,0xfe,0xca,0xbe,0xba] + andps 0xbabecafe,%xmm5 + +// CHECK: andps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x54,0x2d,0x78,0x56,0x34,0x12] + andps 0x12345678,%xmm5 + +// CHECK: andps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x54,0xed] + andps %xmm5,%xmm5 + +// CHECK: comiss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x2f,0xac,0xcb,0xef,0xbe,0xad,0xde] + comiss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: comiss 69, %xmm5 +// CHECK: encoding: [0x0f,0x2f,0x2d,0x45,0x00,0x00,0x00] + comiss 0x45,%xmm5 + +// CHECK: comiss 32493, %xmm5 +// CHECK: encoding: [0x0f,0x2f,0x2d,0xed,0x7e,0x00,0x00] + comiss 0x7eed,%xmm5 + +// CHECK: comiss 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x2f,0x2d,0xfe,0xca,0xbe,0xba] + comiss 0xbabecafe,%xmm5 + +// CHECK: comiss 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x2f,0x2d,0x78,0x56,0x34,0x12] + comiss 0x12345678,%xmm5 + +// CHECK: comiss %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x2f,0xed] + comiss %xmm5,%xmm5 + +// CHECK: cvtpi2ps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x2a,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtpi2ps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtpi2ps 69, %xmm5 +// CHECK: encoding: [0x0f,0x2a,0x2d,0x45,0x00,0x00,0x00] + cvtpi2ps 0x45,%xmm5 + +// CHECK: cvtpi2ps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x2a,0x2d,0xed,0x7e,0x00,0x00] + cvtpi2ps 0x7eed,%xmm5 + +// CHECK: cvtpi2ps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x2a,0x2d,0xfe,0xca,0xbe,0xba] + cvtpi2ps 0xbabecafe,%xmm5 + +// CHECK: cvtpi2ps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x2a,0x2d,0x78,0x56,0x34,0x12] + cvtpi2ps 0x12345678,%xmm5 + +// CHECK: cvtpi2ps %mm3, %xmm5 +// CHECK: encoding: [0x0f,0x2a,0xeb] + cvtpi2ps %mm3,%xmm5 + +// CHECK: cvtps2pi 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x2d,0x9c,0xcb,0xef,0xbe,0xad,0xde] + cvtps2pi 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: cvtps2pi 69, %mm3 +// CHECK: encoding: [0x0f,0x2d,0x1d,0x45,0x00,0x00,0x00] + cvtps2pi 0x45,%mm3 + +// CHECK: cvtps2pi 32493, %mm3 +// CHECK: encoding: [0x0f,0x2d,0x1d,0xed,0x7e,0x00,0x00] + cvtps2pi 0x7eed,%mm3 + +// CHECK: cvtps2pi 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x2d,0x1d,0xfe,0xca,0xbe,0xba] + cvtps2pi 0xbabecafe,%mm3 + +// CHECK: cvtps2pi 305419896, %mm3 +// CHECK: encoding: [0x0f,0x2d,0x1d,0x78,0x56,0x34,0x12] + cvtps2pi 0x12345678,%mm3 + +// CHECK: cvtps2pi %xmm5, %mm3 +// CHECK: encoding: [0x0f,0x2d,0xdd] + cvtps2pi %xmm5,%mm3 + +// CHECK: cvtsi2ss %ecx, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x2a,0xe9] + cvtsi2ss %ecx,%xmm5 + +// CHECK: cvtsi2ss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x2a,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtsi2ss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtsi2ss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x2a,0x2d,0x45,0x00,0x00,0x00] + cvtsi2ss 0x45,%xmm5 + +// CHECK: cvtsi2ss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x2a,0x2d,0xed,0x7e,0x00,0x00] + cvtsi2ss 0x7eed,%xmm5 + +// CHECK: cvtsi2ss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x2a,0x2d,0xfe,0xca,0xbe,0xba] + cvtsi2ss 0xbabecafe,%xmm5 + +// CHECK: cvtsi2ss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x2a,0x2d,0x78,0x56,0x34,0x12] + cvtsi2ss 0x12345678,%xmm5 + +// CHECK: cvttps2pi 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x2c,0x9c,0xcb,0xef,0xbe,0xad,0xde] + cvttps2pi 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: cvttps2pi 69, %mm3 +// CHECK: encoding: [0x0f,0x2c,0x1d,0x45,0x00,0x00,0x00] + cvttps2pi 0x45,%mm3 + +// CHECK: cvttps2pi 32493, %mm3 +// CHECK: encoding: [0x0f,0x2c,0x1d,0xed,0x7e,0x00,0x00] + cvttps2pi 0x7eed,%mm3 + +// CHECK: cvttps2pi 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x2c,0x1d,0xfe,0xca,0xbe,0xba] + cvttps2pi 0xbabecafe,%mm3 + +// CHECK: cvttps2pi 305419896, %mm3 +// CHECK: encoding: [0x0f,0x2c,0x1d,0x78,0x56,0x34,0x12] + cvttps2pi 0x12345678,%mm3 + +// CHECK: cvttps2pi %xmm5, %mm3 +// CHECK: encoding: [0x0f,0x2c,0xdd] + cvttps2pi %xmm5,%mm3 + +// CHECK: cvttss2si 3735928559(%ebx,%ecx,8), %ecx +// CHECK: encoding: [0xf3,0x0f,0x2c,0x8c,0xcb,0xef,0xbe,0xad,0xde] + cvttss2si 0xdeadbeef(%ebx,%ecx,8),%ecx + +// CHECK: cvttss2si 69, %ecx +// CHECK: encoding: [0xf3,0x0f,0x2c,0x0d,0x45,0x00,0x00,0x00] + cvttss2si 0x45,%ecx + +// CHECK: cvttss2si 32493, %ecx +// CHECK: encoding: [0xf3,0x0f,0x2c,0x0d,0xed,0x7e,0x00,0x00] + cvttss2si 0x7eed,%ecx + +// CHECK: cvttss2si 3133065982, %ecx +// CHECK: encoding: [0xf3,0x0f,0x2c,0x0d,0xfe,0xca,0xbe,0xba] + cvttss2si 0xbabecafe,%ecx + +// CHECK: cvttss2si 305419896, %ecx +// CHECK: encoding: [0xf3,0x0f,0x2c,0x0d,0x78,0x56,0x34,0x12] + cvttss2si 0x12345678,%ecx + +// CHECK: cvttss2si %xmm5, %ecx +// CHECK: encoding: [0xf3,0x0f,0x2c,0xcd] + cvttss2si %xmm5,%ecx + +// CHECK: divps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x5e,0xac,0xcb,0xef,0xbe,0xad,0xde] + divps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: divps 69, %xmm5 +// CHECK: encoding: [0x0f,0x5e,0x2d,0x45,0x00,0x00,0x00] + divps 0x45,%xmm5 + +// CHECK: divps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x5e,0x2d,0xed,0x7e,0x00,0x00] + divps 0x7eed,%xmm5 + +// CHECK: divps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x5e,0x2d,0xfe,0xca,0xbe,0xba] + divps 0xbabecafe,%xmm5 + +// CHECK: divps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x5e,0x2d,0x78,0x56,0x34,0x12] + divps 0x12345678,%xmm5 + +// CHECK: divps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x5e,0xed] + divps %xmm5,%xmm5 + +// CHECK: divss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5e,0xac,0xcb,0xef,0xbe,0xad,0xde] + divss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: divss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5e,0x2d,0x45,0x00,0x00,0x00] + divss 0x45,%xmm5 + +// CHECK: divss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5e,0x2d,0xed,0x7e,0x00,0x00] + divss 0x7eed,%xmm5 + +// CHECK: divss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5e,0x2d,0xfe,0xca,0xbe,0xba] + divss 0xbabecafe,%xmm5 + +// CHECK: divss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5e,0x2d,0x78,0x56,0x34,0x12] + divss 0x12345678,%xmm5 + +// CHECK: divss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5e,0xed] + divss %xmm5,%xmm5 + +// CHECK: ldmxcsr 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xae,0x94,0xcb,0xef,0xbe,0xad,0xde] + ldmxcsr 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: ldmxcsr 32493 +// CHECK: encoding: [0x0f,0xae,0x15,0xed,0x7e,0x00,0x00] + ldmxcsr 0x7eed + +// CHECK: ldmxcsr 3133065982 +// CHECK: encoding: [0x0f,0xae,0x15,0xfe,0xca,0xbe,0xba] + ldmxcsr 0xbabecafe + +// CHECK: ldmxcsr 305419896 +// CHECK: encoding: [0x0f,0xae,0x15,0x78,0x56,0x34,0x12] + ldmxcsr 0x12345678 + +// CHECK: maskmovq %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf7,0xdb] + maskmovq %mm3,%mm3 + +// CHECK: maxps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x5f,0xac,0xcb,0xef,0xbe,0xad,0xde] + maxps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: maxps 69, %xmm5 +// CHECK: encoding: [0x0f,0x5f,0x2d,0x45,0x00,0x00,0x00] + maxps 0x45,%xmm5 + +// CHECK: maxps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x5f,0x2d,0xed,0x7e,0x00,0x00] + maxps 0x7eed,%xmm5 + +// CHECK: maxps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x5f,0x2d,0xfe,0xca,0xbe,0xba] + maxps 0xbabecafe,%xmm5 + +// CHECK: maxps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x5f,0x2d,0x78,0x56,0x34,0x12] + maxps 0x12345678,%xmm5 + +// CHECK: maxps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x5f,0xed] + maxps %xmm5,%xmm5 + +// CHECK: maxss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5f,0xac,0xcb,0xef,0xbe,0xad,0xde] + maxss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: maxss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5f,0x2d,0x45,0x00,0x00,0x00] + maxss 0x45,%xmm5 + +// CHECK: maxss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5f,0x2d,0xed,0x7e,0x00,0x00] + maxss 0x7eed,%xmm5 + +// CHECK: maxss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5f,0x2d,0xfe,0xca,0xbe,0xba] + maxss 0xbabecafe,%xmm5 + +// CHECK: maxss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5f,0x2d,0x78,0x56,0x34,0x12] + maxss 0x12345678,%xmm5 + +// CHECK: maxss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5f,0xed] + maxss %xmm5,%xmm5 + +// CHECK: minps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x5d,0xac,0xcb,0xef,0xbe,0xad,0xde] + minps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: minps 69, %xmm5 +// CHECK: encoding: [0x0f,0x5d,0x2d,0x45,0x00,0x00,0x00] + minps 0x45,%xmm5 + +// CHECK: minps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x5d,0x2d,0xed,0x7e,0x00,0x00] + minps 0x7eed,%xmm5 + +// CHECK: minps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x5d,0x2d,0xfe,0xca,0xbe,0xba] + minps 0xbabecafe,%xmm5 + +// CHECK: minps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x5d,0x2d,0x78,0x56,0x34,0x12] + minps 0x12345678,%xmm5 + +// CHECK: minps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x5d,0xed] + minps %xmm5,%xmm5 + +// CHECK: minss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5d,0xac,0xcb,0xef,0xbe,0xad,0xde] + minss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: minss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5d,0x2d,0x45,0x00,0x00,0x00] + minss 0x45,%xmm5 + +// CHECK: minss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5d,0x2d,0xed,0x7e,0x00,0x00] + minss 0x7eed,%xmm5 + +// CHECK: minss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5d,0x2d,0xfe,0xca,0xbe,0xba] + minss 0xbabecafe,%xmm5 + +// CHECK: minss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5d,0x2d,0x78,0x56,0x34,0x12] + minss 0x12345678,%xmm5 + +// CHECK: minss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5d,0xed] + minss %xmm5,%xmm5 + +// CHECK: movaps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x28,0xac,0xcb,0xef,0xbe,0xad,0xde] + movaps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movaps 69, %xmm5 +// CHECK: encoding: [0x0f,0x28,0x2d,0x45,0x00,0x00,0x00] + movaps 0x45,%xmm5 + +// CHECK: movaps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x28,0x2d,0xed,0x7e,0x00,0x00] + movaps 0x7eed,%xmm5 + +// CHECK: movaps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x28,0x2d,0xfe,0xca,0xbe,0xba] + movaps 0xbabecafe,%xmm5 + +// CHECK: movaps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x28,0x2d,0x78,0x56,0x34,0x12] + movaps 0x12345678,%xmm5 + +// CHECK: movaps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x28,0xed] + movaps %xmm5,%xmm5 + +// CHECK: movaps %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x29,0xac,0xcb,0xef,0xbe,0xad,0xde] + movaps %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movaps %xmm5, 69 +// CHECK: encoding: [0x0f,0x29,0x2d,0x45,0x00,0x00,0x00] + movaps %xmm5,0x45 + +// CHECK: movaps %xmm5, 32493 +// CHECK: encoding: [0x0f,0x29,0x2d,0xed,0x7e,0x00,0x00] + movaps %xmm5,0x7eed + +// CHECK: movaps %xmm5, 3133065982 +// CHECK: encoding: [0x0f,0x29,0x2d,0xfe,0xca,0xbe,0xba] + movaps %xmm5,0xbabecafe + +// CHECK: movaps %xmm5, 305419896 +// CHECK: encoding: [0x0f,0x29,0x2d,0x78,0x56,0x34,0x12] + movaps %xmm5,0x12345678 + +// CHECK: movaps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x28,0xed] + movaps %xmm5,%xmm5 + +// CHECK: movhlps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x12,0xed] + movhlps %xmm5,%xmm5 + +// CHECK: movhps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x16,0xac,0xcb,0xef,0xbe,0xad,0xde] + movhps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movhps 69, %xmm5 +// CHECK: encoding: [0x0f,0x16,0x2d,0x45,0x00,0x00,0x00] + movhps 0x45,%xmm5 + +// CHECK: movhps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x16,0x2d,0xed,0x7e,0x00,0x00] + movhps 0x7eed,%xmm5 + +// CHECK: movhps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x16,0x2d,0xfe,0xca,0xbe,0xba] + movhps 0xbabecafe,%xmm5 + +// CHECK: movhps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x16,0x2d,0x78,0x56,0x34,0x12] + movhps 0x12345678,%xmm5 + +// CHECK: movhps %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x17,0xac,0xcb,0xef,0xbe,0xad,0xde] + movhps %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movhps %xmm5, 69 +// CHECK: encoding: [0x0f,0x17,0x2d,0x45,0x00,0x00,0x00] + movhps %xmm5,0x45 + +// CHECK: movhps %xmm5, 32493 +// CHECK: encoding: [0x0f,0x17,0x2d,0xed,0x7e,0x00,0x00] + movhps %xmm5,0x7eed + +// CHECK: movhps %xmm5, 3133065982 +// CHECK: encoding: [0x0f,0x17,0x2d,0xfe,0xca,0xbe,0xba] + movhps %xmm5,0xbabecafe + +// CHECK: movhps %xmm5, 305419896 +// CHECK: encoding: [0x0f,0x17,0x2d,0x78,0x56,0x34,0x12] + movhps %xmm5,0x12345678 + +// CHECK: movlhps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x16,0xed] + movlhps %xmm5,%xmm5 + +// CHECK: movlps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x12,0xac,0xcb,0xef,0xbe,0xad,0xde] + movlps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movlps 69, %xmm5 +// CHECK: encoding: [0x0f,0x12,0x2d,0x45,0x00,0x00,0x00] + movlps 0x45,%xmm5 + +// CHECK: movlps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x12,0x2d,0xed,0x7e,0x00,0x00] + movlps 0x7eed,%xmm5 + +// CHECK: movlps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x12,0x2d,0xfe,0xca,0xbe,0xba] + movlps 0xbabecafe,%xmm5 + +// CHECK: movlps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x12,0x2d,0x78,0x56,0x34,0x12] + movlps 0x12345678,%xmm5 + +// CHECK: movlps %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x13,0xac,0xcb,0xef,0xbe,0xad,0xde] + movlps %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movlps %xmm5, 69 +// CHECK: encoding: [0x0f,0x13,0x2d,0x45,0x00,0x00,0x00] + movlps %xmm5,0x45 + +// CHECK: movlps %xmm5, 32493 +// CHECK: encoding: [0x0f,0x13,0x2d,0xed,0x7e,0x00,0x00] + movlps %xmm5,0x7eed + +// CHECK: movlps %xmm5, 3133065982 +// CHECK: encoding: [0x0f,0x13,0x2d,0xfe,0xca,0xbe,0xba] + movlps %xmm5,0xbabecafe + +// CHECK: movlps %xmm5, 305419896 +// CHECK: encoding: [0x0f,0x13,0x2d,0x78,0x56,0x34,0x12] + movlps %xmm5,0x12345678 + +// CHECK: movmskps %xmm5, %ecx +// CHECK: encoding: [0x0f,0x50,0xcd] + movmskps %xmm5,%ecx + +// CHECK: movntps %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x2b,0xac,0xcb,0xef,0xbe,0xad,0xde] + movntps %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movntps %xmm5, 69 +// CHECK: encoding: [0x0f,0x2b,0x2d,0x45,0x00,0x00,0x00] + movntps %xmm5,0x45 + +// CHECK: movntps %xmm5, 32493 +// CHECK: encoding: [0x0f,0x2b,0x2d,0xed,0x7e,0x00,0x00] + movntps %xmm5,0x7eed + +// CHECK: movntps %xmm5, 3133065982 +// CHECK: encoding: [0x0f,0x2b,0x2d,0xfe,0xca,0xbe,0xba] + movntps %xmm5,0xbabecafe + +// CHECK: movntps %xmm5, 305419896 +// CHECK: encoding: [0x0f,0x2b,0x2d,0x78,0x56,0x34,0x12] + movntps %xmm5,0x12345678 + +// CHECK: movntq %mm3, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xe7,0x9c,0xcb,0xef,0xbe,0xad,0xde] + movntq %mm3,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movntq %mm3, 69 +// CHECK: encoding: [0x0f,0xe7,0x1d,0x45,0x00,0x00,0x00] + movntq %mm3,0x45 + +// CHECK: movntq %mm3, 32493 +// CHECK: encoding: [0x0f,0xe7,0x1d,0xed,0x7e,0x00,0x00] + movntq %mm3,0x7eed + +// CHECK: movntq %mm3, 3133065982 +// CHECK: encoding: [0x0f,0xe7,0x1d,0xfe,0xca,0xbe,0xba] + movntq %mm3,0xbabecafe + +// CHECK: movntq %mm3, 305419896 +// CHECK: encoding: [0x0f,0xe7,0x1d,0x78,0x56,0x34,0x12] + movntq %mm3,0x12345678 + +// CHECK: movntdq %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0xe7,0xac,0xcb,0xef,0xbe,0xad,0xde] + movntdq %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movntdq %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0xe7,0x2d,0x45,0x00,0x00,0x00] + movntdq %xmm5,0x45 + +// CHECK: movntdq %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0xe7,0x2d,0xed,0x7e,0x00,0x00] + movntdq %xmm5,0x7eed + +// CHECK: movntdq %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0xe7,0x2d,0xfe,0xca,0xbe,0xba] + movntdq %xmm5,0xbabecafe + +// CHECK: movntdq %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0xe7,0x2d,0x78,0x56,0x34,0x12] + movntdq %xmm5,0x12345678 + +// CHECK: movss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x10,0xac,0xcb,0xef,0xbe,0xad,0xde] + movss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x10,0x2d,0x45,0x00,0x00,0x00] + movss 0x45,%xmm5 + +// CHECK: movss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x10,0x2d,0xed,0x7e,0x00,0x00] + movss 0x7eed,%xmm5 + +// CHECK: movss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x10,0x2d,0xfe,0xca,0xbe,0xba] + movss 0xbabecafe,%xmm5 + +// CHECK: movss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x10,0x2d,0x78,0x56,0x34,0x12] + movss 0x12345678,%xmm5 + +// CHECK: movss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x10,0xed] + movss %xmm5,%xmm5 + +// CHECK: movss %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf3,0x0f,0x11,0xac,0xcb,0xef,0xbe,0xad,0xde] + movss %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movss %xmm5, 69 +// CHECK: encoding: [0xf3,0x0f,0x11,0x2d,0x45,0x00,0x00,0x00] + movss %xmm5,0x45 + +// CHECK: movss %xmm5, 32493 +// CHECK: encoding: [0xf3,0x0f,0x11,0x2d,0xed,0x7e,0x00,0x00] + movss %xmm5,0x7eed + +// CHECK: movss %xmm5, 3133065982 +// CHECK: encoding: [0xf3,0x0f,0x11,0x2d,0xfe,0xca,0xbe,0xba] + movss %xmm5,0xbabecafe + +// CHECK: movss %xmm5, 305419896 +// CHECK: encoding: [0xf3,0x0f,0x11,0x2d,0x78,0x56,0x34,0x12] + movss %xmm5,0x12345678 + +// CHECK: movss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x10,0xed] + movss %xmm5,%xmm5 + +// CHECK: movups 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x10,0xac,0xcb,0xef,0xbe,0xad,0xde] + movups 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movups 69, %xmm5 +// CHECK: encoding: [0x0f,0x10,0x2d,0x45,0x00,0x00,0x00] + movups 0x45,%xmm5 + +// CHECK: movups 32493, %xmm5 +// CHECK: encoding: [0x0f,0x10,0x2d,0xed,0x7e,0x00,0x00] + movups 0x7eed,%xmm5 + +// CHECK: movups 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x10,0x2d,0xfe,0xca,0xbe,0xba] + movups 0xbabecafe,%xmm5 + +// CHECK: movups 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x10,0x2d,0x78,0x56,0x34,0x12] + movups 0x12345678,%xmm5 + +// CHECK: movups %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x10,0xed] + movups %xmm5,%xmm5 + +// CHECK: movups %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x11,0xac,0xcb,0xef,0xbe,0xad,0xde] + movups %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movups %xmm5, 69 +// CHECK: encoding: [0x0f,0x11,0x2d,0x45,0x00,0x00,0x00] + movups %xmm5,0x45 + +// CHECK: movups %xmm5, 32493 +// CHECK: encoding: [0x0f,0x11,0x2d,0xed,0x7e,0x00,0x00] + movups %xmm5,0x7eed + +// CHECK: movups %xmm5, 3133065982 +// CHECK: encoding: [0x0f,0x11,0x2d,0xfe,0xca,0xbe,0xba] + movups %xmm5,0xbabecafe + +// CHECK: movups %xmm5, 305419896 +// CHECK: encoding: [0x0f,0x11,0x2d,0x78,0x56,0x34,0x12] + movups %xmm5,0x12345678 + +// CHECK: movups %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x10,0xed] + movups %xmm5,%xmm5 + +// CHECK: mulps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x59,0xac,0xcb,0xef,0xbe,0xad,0xde] + mulps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: mulps 69, %xmm5 +// CHECK: encoding: [0x0f,0x59,0x2d,0x45,0x00,0x00,0x00] + mulps 0x45,%xmm5 + +// CHECK: mulps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x59,0x2d,0xed,0x7e,0x00,0x00] + mulps 0x7eed,%xmm5 + +// CHECK: mulps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x59,0x2d,0xfe,0xca,0xbe,0xba] + mulps 0xbabecafe,%xmm5 + +// CHECK: mulps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x59,0x2d,0x78,0x56,0x34,0x12] + mulps 0x12345678,%xmm5 + +// CHECK: mulps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x59,0xed] + mulps %xmm5,%xmm5 + +// CHECK: mulss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x59,0xac,0xcb,0xef,0xbe,0xad,0xde] + mulss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: mulss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x59,0x2d,0x45,0x00,0x00,0x00] + mulss 0x45,%xmm5 + +// CHECK: mulss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x59,0x2d,0xed,0x7e,0x00,0x00] + mulss 0x7eed,%xmm5 + +// CHECK: mulss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x59,0x2d,0xfe,0xca,0xbe,0xba] + mulss 0xbabecafe,%xmm5 + +// CHECK: mulss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x59,0x2d,0x78,0x56,0x34,0x12] + mulss 0x12345678,%xmm5 + +// CHECK: mulss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x59,0xed] + mulss %xmm5,%xmm5 + +// CHECK: orps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x56,0xac,0xcb,0xef,0xbe,0xad,0xde] + orps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: orps 69, %xmm5 +// CHECK: encoding: [0x0f,0x56,0x2d,0x45,0x00,0x00,0x00] + orps 0x45,%xmm5 + +// CHECK: orps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x56,0x2d,0xed,0x7e,0x00,0x00] + orps 0x7eed,%xmm5 + +// CHECK: orps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x56,0x2d,0xfe,0xca,0xbe,0xba] + orps 0xbabecafe,%xmm5 + +// CHECK: orps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x56,0x2d,0x78,0x56,0x34,0x12] + orps 0x12345678,%xmm5 + +// CHECK: orps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x56,0xed] + orps %xmm5,%xmm5 + +// CHECK: pavgb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xe0,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pavgb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pavgb 69, %mm3 +// CHECK: encoding: [0x0f,0xe0,0x1d,0x45,0x00,0x00,0x00] + pavgb 0x45,%mm3 + +// CHECK: pavgb 32493, %mm3 +// CHECK: encoding: [0x0f,0xe0,0x1d,0xed,0x7e,0x00,0x00] + pavgb 0x7eed,%mm3 + +// CHECK: pavgb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xe0,0x1d,0xfe,0xca,0xbe,0xba] + pavgb 0xbabecafe,%mm3 + +// CHECK: pavgb 305419896, %mm3 +// CHECK: encoding: [0x0f,0xe0,0x1d,0x78,0x56,0x34,0x12] + pavgb 0x12345678,%mm3 + +// CHECK: pavgb %mm3, %mm3 +// CHECK: encoding: [0x0f,0xe0,0xdb] + pavgb %mm3,%mm3 + +// CHECK: pavgb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe0,0xac,0xcb,0xef,0xbe,0xad,0xde] + pavgb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pavgb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe0,0x2d,0x45,0x00,0x00,0x00] + pavgb 0x45,%xmm5 + +// CHECK: pavgb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe0,0x2d,0xed,0x7e,0x00,0x00] + pavgb 0x7eed,%xmm5 + +// CHECK: pavgb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe0,0x2d,0xfe,0xca,0xbe,0xba] + pavgb 0xbabecafe,%xmm5 + +// CHECK: pavgb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe0,0x2d,0x78,0x56,0x34,0x12] + pavgb 0x12345678,%xmm5 + +// CHECK: pavgb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe0,0xed] + pavgb %xmm5,%xmm5 + +// CHECK: pavgw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xe3,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pavgw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pavgw 69, %mm3 +// CHECK: encoding: [0x0f,0xe3,0x1d,0x45,0x00,0x00,0x00] + pavgw 0x45,%mm3 + +// CHECK: pavgw 32493, %mm3 +// CHECK: encoding: [0x0f,0xe3,0x1d,0xed,0x7e,0x00,0x00] + pavgw 0x7eed,%mm3 + +// CHECK: pavgw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xe3,0x1d,0xfe,0xca,0xbe,0xba] + pavgw 0xbabecafe,%mm3 + +// CHECK: pavgw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xe3,0x1d,0x78,0x56,0x34,0x12] + pavgw 0x12345678,%mm3 + +// CHECK: pavgw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xe3,0xdb] + pavgw %mm3,%mm3 + +// CHECK: pavgw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe3,0xac,0xcb,0xef,0xbe,0xad,0xde] + pavgw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pavgw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe3,0x2d,0x45,0x00,0x00,0x00] + pavgw 0x45,%xmm5 + +// CHECK: pavgw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe3,0x2d,0xed,0x7e,0x00,0x00] + pavgw 0x7eed,%xmm5 + +// CHECK: pavgw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe3,0x2d,0xfe,0xca,0xbe,0xba] + pavgw 0xbabecafe,%xmm5 + +// CHECK: pavgw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe3,0x2d,0x78,0x56,0x34,0x12] + pavgw 0x12345678,%xmm5 + +// CHECK: pavgw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe3,0xed] + pavgw %xmm5,%xmm5 + +// CHECK: pmaxsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xee,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmaxsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmaxsw 69, %mm3 +// CHECK: encoding: [0x0f,0xee,0x1d,0x45,0x00,0x00,0x00] + pmaxsw 0x45,%mm3 + +// CHECK: pmaxsw 32493, %mm3 +// CHECK: encoding: [0x0f,0xee,0x1d,0xed,0x7e,0x00,0x00] + pmaxsw 0x7eed,%mm3 + +// CHECK: pmaxsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xee,0x1d,0xfe,0xca,0xbe,0xba] + pmaxsw 0xbabecafe,%mm3 + +// CHECK: pmaxsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xee,0x1d,0x78,0x56,0x34,0x12] + pmaxsw 0x12345678,%mm3 + +// CHECK: pmaxsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xee,0xdb] + pmaxsw %mm3,%mm3 + +// CHECK: pmaxsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xee,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmaxsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmaxsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xee,0x2d,0x45,0x00,0x00,0x00] + pmaxsw 0x45,%xmm5 + +// CHECK: pmaxsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xee,0x2d,0xed,0x7e,0x00,0x00] + pmaxsw 0x7eed,%xmm5 + +// CHECK: pmaxsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xee,0x2d,0xfe,0xca,0xbe,0xba] + pmaxsw 0xbabecafe,%xmm5 + +// CHECK: pmaxsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xee,0x2d,0x78,0x56,0x34,0x12] + pmaxsw 0x12345678,%xmm5 + +// CHECK: pmaxsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xee,0xed] + pmaxsw %xmm5,%xmm5 + +// CHECK: pmaxub 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xde,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmaxub 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmaxub 69, %mm3 +// CHECK: encoding: [0x0f,0xde,0x1d,0x45,0x00,0x00,0x00] + pmaxub 0x45,%mm3 + +// CHECK: pmaxub 32493, %mm3 +// CHECK: encoding: [0x0f,0xde,0x1d,0xed,0x7e,0x00,0x00] + pmaxub 0x7eed,%mm3 + +// CHECK: pmaxub 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xde,0x1d,0xfe,0xca,0xbe,0xba] + pmaxub 0xbabecafe,%mm3 + +// CHECK: pmaxub 305419896, %mm3 +// CHECK: encoding: [0x0f,0xde,0x1d,0x78,0x56,0x34,0x12] + pmaxub 0x12345678,%mm3 + +// CHECK: pmaxub %mm3, %mm3 +// CHECK: encoding: [0x0f,0xde,0xdb] + pmaxub %mm3,%mm3 + +// CHECK: pmaxub 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xde,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmaxub 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmaxub 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xde,0x2d,0x45,0x00,0x00,0x00] + pmaxub 0x45,%xmm5 + +// CHECK: pmaxub 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xde,0x2d,0xed,0x7e,0x00,0x00] + pmaxub 0x7eed,%xmm5 + +// CHECK: pmaxub 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xde,0x2d,0xfe,0xca,0xbe,0xba] + pmaxub 0xbabecafe,%xmm5 + +// CHECK: pmaxub 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xde,0x2d,0x78,0x56,0x34,0x12] + pmaxub 0x12345678,%xmm5 + +// CHECK: pmaxub %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xde,0xed] + pmaxub %xmm5,%xmm5 + +// CHECK: pminsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xea,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pminsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pminsw 69, %mm3 +// CHECK: encoding: [0x0f,0xea,0x1d,0x45,0x00,0x00,0x00] + pminsw 0x45,%mm3 + +// CHECK: pminsw 32493, %mm3 +// CHECK: encoding: [0x0f,0xea,0x1d,0xed,0x7e,0x00,0x00] + pminsw 0x7eed,%mm3 + +// CHECK: pminsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xea,0x1d,0xfe,0xca,0xbe,0xba] + pminsw 0xbabecafe,%mm3 + +// CHECK: pminsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xea,0x1d,0x78,0x56,0x34,0x12] + pminsw 0x12345678,%mm3 + +// CHECK: pminsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xea,0xdb] + pminsw %mm3,%mm3 + +// CHECK: pminsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xea,0xac,0xcb,0xef,0xbe,0xad,0xde] + pminsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pminsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xea,0x2d,0x45,0x00,0x00,0x00] + pminsw 0x45,%xmm5 + +// CHECK: pminsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xea,0x2d,0xed,0x7e,0x00,0x00] + pminsw 0x7eed,%xmm5 + +// CHECK: pminsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xea,0x2d,0xfe,0xca,0xbe,0xba] + pminsw 0xbabecafe,%xmm5 + +// CHECK: pminsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xea,0x2d,0x78,0x56,0x34,0x12] + pminsw 0x12345678,%xmm5 + +// CHECK: pminsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xea,0xed] + pminsw %xmm5,%xmm5 + +// CHECK: pminub 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xda,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pminub 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pminub 69, %mm3 +// CHECK: encoding: [0x0f,0xda,0x1d,0x45,0x00,0x00,0x00] + pminub 0x45,%mm3 + +// CHECK: pminub 32493, %mm3 +// CHECK: encoding: [0x0f,0xda,0x1d,0xed,0x7e,0x00,0x00] + pminub 0x7eed,%mm3 + +// CHECK: pminub 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xda,0x1d,0xfe,0xca,0xbe,0xba] + pminub 0xbabecafe,%mm3 + +// CHECK: pminub 305419896, %mm3 +// CHECK: encoding: [0x0f,0xda,0x1d,0x78,0x56,0x34,0x12] + pminub 0x12345678,%mm3 + +// CHECK: pminub %mm3, %mm3 +// CHECK: encoding: [0x0f,0xda,0xdb] + pminub %mm3,%mm3 + +// CHECK: pminub 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xda,0xac,0xcb,0xef,0xbe,0xad,0xde] + pminub 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pminub 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xda,0x2d,0x45,0x00,0x00,0x00] + pminub 0x45,%xmm5 + +// CHECK: pminub 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xda,0x2d,0xed,0x7e,0x00,0x00] + pminub 0x7eed,%xmm5 + +// CHECK: pminub 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xda,0x2d,0xfe,0xca,0xbe,0xba] + pminub 0xbabecafe,%xmm5 + +// CHECK: pminub 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xda,0x2d,0x78,0x56,0x34,0x12] + pminub 0x12345678,%xmm5 + +// CHECK: pminub %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xda,0xed] + pminub %xmm5,%xmm5 + +// CHECK: pmovmskb %mm3, %ecx +// CHECK: encoding: [0x0f,0xd7,0xcb] + pmovmskb %mm3,%ecx + +// CHECK: pmovmskb %xmm5, %ecx +// CHECK: encoding: [0x66,0x0f,0xd7,0xcd] + pmovmskb %xmm5,%ecx + +// CHECK: pmulhuw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xe4,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmulhuw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmulhuw 69, %mm3 +// CHECK: encoding: [0x0f,0xe4,0x1d,0x45,0x00,0x00,0x00] + pmulhuw 0x45,%mm3 + +// CHECK: pmulhuw 32493, %mm3 +// CHECK: encoding: [0x0f,0xe4,0x1d,0xed,0x7e,0x00,0x00] + pmulhuw 0x7eed,%mm3 + +// CHECK: pmulhuw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xe4,0x1d,0xfe,0xca,0xbe,0xba] + pmulhuw 0xbabecafe,%mm3 + +// CHECK: pmulhuw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xe4,0x1d,0x78,0x56,0x34,0x12] + pmulhuw 0x12345678,%mm3 + +// CHECK: pmulhuw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xe4,0xdb] + pmulhuw %mm3,%mm3 + +// CHECK: pmulhuw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe4,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmulhuw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmulhuw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe4,0x2d,0x45,0x00,0x00,0x00] + pmulhuw 0x45,%xmm5 + +// CHECK: pmulhuw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe4,0x2d,0xed,0x7e,0x00,0x00] + pmulhuw 0x7eed,%xmm5 + +// CHECK: pmulhuw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe4,0x2d,0xfe,0xca,0xbe,0xba] + pmulhuw 0xbabecafe,%xmm5 + +// CHECK: pmulhuw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe4,0x2d,0x78,0x56,0x34,0x12] + pmulhuw 0x12345678,%xmm5 + +// CHECK: pmulhuw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xe4,0xed] + pmulhuw %xmm5,%xmm5 + +// CHECK: prefetchnta 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x18,0x84,0xcb,0xef,0xbe,0xad,0xde] + prefetchnta 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: prefetchnta 32493 +// CHECK: encoding: [0x0f,0x18,0x05,0xed,0x7e,0x00,0x00] + prefetchnta 0x7eed + +// CHECK: prefetchnta 3133065982 +// CHECK: encoding: [0x0f,0x18,0x05,0xfe,0xca,0xbe,0xba] + prefetchnta 0xbabecafe + +// CHECK: prefetchnta 305419896 +// CHECK: encoding: [0x0f,0x18,0x05,0x78,0x56,0x34,0x12] + prefetchnta 0x12345678 + +// CHECK: prefetcht0 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x18,0x8c,0xcb,0xef,0xbe,0xad,0xde] + prefetcht0 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: prefetcht0 32493 +// CHECK: encoding: [0x0f,0x18,0x0d,0xed,0x7e,0x00,0x00] + prefetcht0 0x7eed + +// CHECK: prefetcht0 3133065982 +// CHECK: encoding: [0x0f,0x18,0x0d,0xfe,0xca,0xbe,0xba] + prefetcht0 0xbabecafe + +// CHECK: prefetcht0 305419896 +// CHECK: encoding: [0x0f,0x18,0x0d,0x78,0x56,0x34,0x12] + prefetcht0 0x12345678 + +// CHECK: prefetcht1 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x18,0x94,0xcb,0xef,0xbe,0xad,0xde] + prefetcht1 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: prefetcht1 32493 +// CHECK: encoding: [0x0f,0x18,0x15,0xed,0x7e,0x00,0x00] + prefetcht1 0x7eed + +// CHECK: prefetcht1 3133065982 +// CHECK: encoding: [0x0f,0x18,0x15,0xfe,0xca,0xbe,0xba] + prefetcht1 0xbabecafe + +// CHECK: prefetcht1 305419896 +// CHECK: encoding: [0x0f,0x18,0x15,0x78,0x56,0x34,0x12] + prefetcht1 0x12345678 + +// CHECK: prefetcht2 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0x18,0x9c,0xcb,0xef,0xbe,0xad,0xde] + prefetcht2 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: prefetcht2 32493 +// CHECK: encoding: [0x0f,0x18,0x1d,0xed,0x7e,0x00,0x00] + prefetcht2 0x7eed + +// CHECK: prefetcht2 3133065982 +// CHECK: encoding: [0x0f,0x18,0x1d,0xfe,0xca,0xbe,0xba] + prefetcht2 0xbabecafe + +// CHECK: prefetcht2 305419896 +// CHECK: encoding: [0x0f,0x18,0x1d,0x78,0x56,0x34,0x12] + prefetcht2 0x12345678 + +// CHECK: psadbw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xf6,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psadbw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psadbw 69, %mm3 +// CHECK: encoding: [0x0f,0xf6,0x1d,0x45,0x00,0x00,0x00] + psadbw 0x45,%mm3 + +// CHECK: psadbw 32493, %mm3 +// CHECK: encoding: [0x0f,0xf6,0x1d,0xed,0x7e,0x00,0x00] + psadbw 0x7eed,%mm3 + +// CHECK: psadbw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xf6,0x1d,0xfe,0xca,0xbe,0xba] + psadbw 0xbabecafe,%mm3 + +// CHECK: psadbw 305419896, %mm3 +// CHECK: encoding: [0x0f,0xf6,0x1d,0x78,0x56,0x34,0x12] + psadbw 0x12345678,%mm3 + +// CHECK: psadbw %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf6,0xdb] + psadbw %mm3,%mm3 + +// CHECK: psadbw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf6,0xac,0xcb,0xef,0xbe,0xad,0xde] + psadbw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psadbw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf6,0x2d,0x45,0x00,0x00,0x00] + psadbw 0x45,%xmm5 + +// CHECK: psadbw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf6,0x2d,0xed,0x7e,0x00,0x00] + psadbw 0x7eed,%xmm5 + +// CHECK: psadbw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf6,0x2d,0xfe,0xca,0xbe,0xba] + psadbw 0xbabecafe,%xmm5 + +// CHECK: psadbw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf6,0x2d,0x78,0x56,0x34,0x12] + psadbw 0x12345678,%xmm5 + +// CHECK: psadbw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf6,0xed] + psadbw %xmm5,%xmm5 + +// CHECK: rcpps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x53,0xac,0xcb,0xef,0xbe,0xad,0xde] + rcpps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: rcpps 69, %xmm5 +// CHECK: encoding: [0x0f,0x53,0x2d,0x45,0x00,0x00,0x00] + rcpps 0x45,%xmm5 + +// CHECK: rcpps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x53,0x2d,0xed,0x7e,0x00,0x00] + rcpps 0x7eed,%xmm5 + +// CHECK: rcpps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x53,0x2d,0xfe,0xca,0xbe,0xba] + rcpps 0xbabecafe,%xmm5 + +// CHECK: rcpps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x53,0x2d,0x78,0x56,0x34,0x12] + rcpps 0x12345678,%xmm5 + +// CHECK: rcpps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x53,0xed] + rcpps %xmm5,%xmm5 + +// CHECK: rcpss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x53,0xac,0xcb,0xef,0xbe,0xad,0xde] + rcpss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: rcpss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x53,0x2d,0x45,0x00,0x00,0x00] + rcpss 0x45,%xmm5 + +// CHECK: rcpss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x53,0x2d,0xed,0x7e,0x00,0x00] + rcpss 0x7eed,%xmm5 + +// CHECK: rcpss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x53,0x2d,0xfe,0xca,0xbe,0xba] + rcpss 0xbabecafe,%xmm5 + +// CHECK: rcpss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x53,0x2d,0x78,0x56,0x34,0x12] + rcpss 0x12345678,%xmm5 + +// CHECK: rcpss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x53,0xed] + rcpss %xmm5,%xmm5 + +// CHECK: rsqrtps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x52,0xac,0xcb,0xef,0xbe,0xad,0xde] + rsqrtps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: rsqrtps 69, %xmm5 +// CHECK: encoding: [0x0f,0x52,0x2d,0x45,0x00,0x00,0x00] + rsqrtps 0x45,%xmm5 + +// CHECK: rsqrtps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x52,0x2d,0xed,0x7e,0x00,0x00] + rsqrtps 0x7eed,%xmm5 + +// CHECK: rsqrtps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x52,0x2d,0xfe,0xca,0xbe,0xba] + rsqrtps 0xbabecafe,%xmm5 + +// CHECK: rsqrtps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x52,0x2d,0x78,0x56,0x34,0x12] + rsqrtps 0x12345678,%xmm5 + +// CHECK: rsqrtps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x52,0xed] + rsqrtps %xmm5,%xmm5 + +// CHECK: rsqrtss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x52,0xac,0xcb,0xef,0xbe,0xad,0xde] + rsqrtss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: rsqrtss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x52,0x2d,0x45,0x00,0x00,0x00] + rsqrtss 0x45,%xmm5 + +// CHECK: rsqrtss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x52,0x2d,0xed,0x7e,0x00,0x00] + rsqrtss 0x7eed,%xmm5 + +// CHECK: rsqrtss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x52,0x2d,0xfe,0xca,0xbe,0xba] + rsqrtss 0xbabecafe,%xmm5 + +// CHECK: rsqrtss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x52,0x2d,0x78,0x56,0x34,0x12] + rsqrtss 0x12345678,%xmm5 + +// CHECK: rsqrtss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x52,0xed] + rsqrtss %xmm5,%xmm5 + +// CHECK: sqrtps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x51,0xac,0xcb,0xef,0xbe,0xad,0xde] + sqrtps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: sqrtps 69, %xmm5 +// CHECK: encoding: [0x0f,0x51,0x2d,0x45,0x00,0x00,0x00] + sqrtps 0x45,%xmm5 + +// CHECK: sqrtps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x51,0x2d,0xed,0x7e,0x00,0x00] + sqrtps 0x7eed,%xmm5 + +// CHECK: sqrtps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x51,0x2d,0xfe,0xca,0xbe,0xba] + sqrtps 0xbabecafe,%xmm5 + +// CHECK: sqrtps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x51,0x2d,0x78,0x56,0x34,0x12] + sqrtps 0x12345678,%xmm5 + +// CHECK: sqrtps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x51,0xed] + sqrtps %xmm5,%xmm5 + +// CHECK: sqrtss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x51,0xac,0xcb,0xef,0xbe,0xad,0xde] + sqrtss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: sqrtss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x51,0x2d,0x45,0x00,0x00,0x00] + sqrtss 0x45,%xmm5 + +// CHECK: sqrtss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x51,0x2d,0xed,0x7e,0x00,0x00] + sqrtss 0x7eed,%xmm5 + +// CHECK: sqrtss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x51,0x2d,0xfe,0xca,0xbe,0xba] + sqrtss 0xbabecafe,%xmm5 + +// CHECK: sqrtss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x51,0x2d,0x78,0x56,0x34,0x12] + sqrtss 0x12345678,%xmm5 + +// CHECK: sqrtss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x51,0xed] + sqrtss %xmm5,%xmm5 + +// CHECK: stmxcsr 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xae,0x9c,0xcb,0xef,0xbe,0xad,0xde] + stmxcsr 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: stmxcsr 32493 +// CHECK: encoding: [0x0f,0xae,0x1d,0xed,0x7e,0x00,0x00] + stmxcsr 0x7eed + +// CHECK: stmxcsr 3133065982 +// CHECK: encoding: [0x0f,0xae,0x1d,0xfe,0xca,0xbe,0xba] + stmxcsr 0xbabecafe + +// CHECK: stmxcsr 305419896 +// CHECK: encoding: [0x0f,0xae,0x1d,0x78,0x56,0x34,0x12] + stmxcsr 0x12345678 + +// CHECK: subps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x5c,0xac,0xcb,0xef,0xbe,0xad,0xde] + subps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: subps 69, %xmm5 +// CHECK: encoding: [0x0f,0x5c,0x2d,0x45,0x00,0x00,0x00] + subps 0x45,%xmm5 + +// CHECK: subps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x5c,0x2d,0xed,0x7e,0x00,0x00] + subps 0x7eed,%xmm5 + +// CHECK: subps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x5c,0x2d,0xfe,0xca,0xbe,0xba] + subps 0xbabecafe,%xmm5 + +// CHECK: subps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x5c,0x2d,0x78,0x56,0x34,0x12] + subps 0x12345678,%xmm5 + +// CHECK: subps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x5c,0xed] + subps %xmm5,%xmm5 + +// CHECK: subss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5c,0xac,0xcb,0xef,0xbe,0xad,0xde] + subss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: subss 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5c,0x2d,0x45,0x00,0x00,0x00] + subss 0x45,%xmm5 + +// CHECK: subss 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5c,0x2d,0xed,0x7e,0x00,0x00] + subss 0x7eed,%xmm5 + +// CHECK: subss 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5c,0x2d,0xfe,0xca,0xbe,0xba] + subss 0xbabecafe,%xmm5 + +// CHECK: subss 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5c,0x2d,0x78,0x56,0x34,0x12] + subss 0x12345678,%xmm5 + +// CHECK: subss %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5c,0xed] + subss %xmm5,%xmm5 + +// CHECK: ucomiss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x2e,0xac,0xcb,0xef,0xbe,0xad,0xde] + ucomiss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: ucomiss 69, %xmm5 +// CHECK: encoding: [0x0f,0x2e,0x2d,0x45,0x00,0x00,0x00] + ucomiss 0x45,%xmm5 + +// CHECK: ucomiss 32493, %xmm5 +// CHECK: encoding: [0x0f,0x2e,0x2d,0xed,0x7e,0x00,0x00] + ucomiss 0x7eed,%xmm5 + +// CHECK: ucomiss 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x2e,0x2d,0xfe,0xca,0xbe,0xba] + ucomiss 0xbabecafe,%xmm5 + +// CHECK: ucomiss 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x2e,0x2d,0x78,0x56,0x34,0x12] + ucomiss 0x12345678,%xmm5 + +// CHECK: ucomiss %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x2e,0xed] + ucomiss %xmm5,%xmm5 + +// CHECK: unpckhps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x15,0xac,0xcb,0xef,0xbe,0xad,0xde] + unpckhps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: unpckhps 69, %xmm5 +// CHECK: encoding: [0x0f,0x15,0x2d,0x45,0x00,0x00,0x00] + unpckhps 0x45,%xmm5 + +// CHECK: unpckhps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x15,0x2d,0xed,0x7e,0x00,0x00] + unpckhps 0x7eed,%xmm5 + +// CHECK: unpckhps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x15,0x2d,0xfe,0xca,0xbe,0xba] + unpckhps 0xbabecafe,%xmm5 + +// CHECK: unpckhps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x15,0x2d,0x78,0x56,0x34,0x12] + unpckhps 0x12345678,%xmm5 + +// CHECK: unpckhps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x15,0xed] + unpckhps %xmm5,%xmm5 + +// CHECK: unpcklps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x14,0xac,0xcb,0xef,0xbe,0xad,0xde] + unpcklps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: unpcklps 69, %xmm5 +// CHECK: encoding: [0x0f,0x14,0x2d,0x45,0x00,0x00,0x00] + unpcklps 0x45,%xmm5 + +// CHECK: unpcklps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x14,0x2d,0xed,0x7e,0x00,0x00] + unpcklps 0x7eed,%xmm5 + +// CHECK: unpcklps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x14,0x2d,0xfe,0xca,0xbe,0xba] + unpcklps 0xbabecafe,%xmm5 + +// CHECK: unpcklps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x14,0x2d,0x78,0x56,0x34,0x12] + unpcklps 0x12345678,%xmm5 + +// CHECK: unpcklps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x14,0xed] + unpcklps %xmm5,%xmm5 + +// CHECK: xorps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x57,0xac,0xcb,0xef,0xbe,0xad,0xde] + xorps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: xorps 69, %xmm5 +// CHECK: encoding: [0x0f,0x57,0x2d,0x45,0x00,0x00,0x00] + xorps 0x45,%xmm5 + +// CHECK: xorps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x57,0x2d,0xed,0x7e,0x00,0x00] + xorps 0x7eed,%xmm5 + +// CHECK: xorps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x57,0x2d,0xfe,0xca,0xbe,0xba] + xorps 0xbabecafe,%xmm5 + +// CHECK: xorps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x57,0x2d,0x78,0x56,0x34,0x12] + xorps 0x12345678,%xmm5 + +// CHECK: xorps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x57,0xed] + xorps %xmm5,%xmm5 + +// CHECK: addpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x58,0xac,0xcb,0xef,0xbe,0xad,0xde] + addpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: addpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x58,0x2d,0x45,0x00,0x00,0x00] + addpd 0x45,%xmm5 + +// CHECK: addpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x58,0x2d,0xed,0x7e,0x00,0x00] + addpd 0x7eed,%xmm5 + +// CHECK: addpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x58,0x2d,0xfe,0xca,0xbe,0xba] + addpd 0xbabecafe,%xmm5 + +// CHECK: addpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x58,0x2d,0x78,0x56,0x34,0x12] + addpd 0x12345678,%xmm5 + +// CHECK: addpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x58,0xed] + addpd %xmm5,%xmm5 + +// CHECK: addsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x58,0xac,0xcb,0xef,0xbe,0xad,0xde] + addsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: addsd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x58,0x2d,0x45,0x00,0x00,0x00] + addsd 0x45,%xmm5 + +// CHECK: addsd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x58,0x2d,0xed,0x7e,0x00,0x00] + addsd 0x7eed,%xmm5 + +// CHECK: addsd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x58,0x2d,0xfe,0xca,0xbe,0xba] + addsd 0xbabecafe,%xmm5 + +// CHECK: addsd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x58,0x2d,0x78,0x56,0x34,0x12] + addsd 0x12345678,%xmm5 + +// CHECK: addsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x58,0xed] + addsd %xmm5,%xmm5 + +// CHECK: andnpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x55,0xac,0xcb,0xef,0xbe,0xad,0xde] + andnpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: andnpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x55,0x2d,0x45,0x00,0x00,0x00] + andnpd 0x45,%xmm5 + +// CHECK: andnpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x55,0x2d,0xed,0x7e,0x00,0x00] + andnpd 0x7eed,%xmm5 + +// CHECK: andnpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x55,0x2d,0xfe,0xca,0xbe,0xba] + andnpd 0xbabecafe,%xmm5 + +// CHECK: andnpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x55,0x2d,0x78,0x56,0x34,0x12] + andnpd 0x12345678,%xmm5 + +// CHECK: andnpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x55,0xed] + andnpd %xmm5,%xmm5 + +// CHECK: andpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x54,0xac,0xcb,0xef,0xbe,0xad,0xde] + andpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: andpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x54,0x2d,0x45,0x00,0x00,0x00] + andpd 0x45,%xmm5 + +// CHECK: andpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x54,0x2d,0xed,0x7e,0x00,0x00] + andpd 0x7eed,%xmm5 + +// CHECK: andpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x54,0x2d,0xfe,0xca,0xbe,0xba] + andpd 0xbabecafe,%xmm5 + +// CHECK: andpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x54,0x2d,0x78,0x56,0x34,0x12] + andpd 0x12345678,%xmm5 + +// CHECK: andpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x54,0xed] + andpd %xmm5,%xmm5 + +// CHECK: comisd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2f,0xac,0xcb,0xef,0xbe,0xad,0xde] + comisd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: comisd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2f,0x2d,0x45,0x00,0x00,0x00] + comisd 0x45,%xmm5 + +// CHECK: comisd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2f,0x2d,0xed,0x7e,0x00,0x00] + comisd 0x7eed,%xmm5 + +// CHECK: comisd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2f,0x2d,0xfe,0xca,0xbe,0xba] + comisd 0xbabecafe,%xmm5 + +// CHECK: comisd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2f,0x2d,0x78,0x56,0x34,0x12] + comisd 0x12345678,%xmm5 + +// CHECK: comisd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2f,0xed] + comisd %xmm5,%xmm5 + +// CHECK: cvtpi2pd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2a,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtpi2pd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtpi2pd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2a,0x2d,0x45,0x00,0x00,0x00] + cvtpi2pd 0x45,%xmm5 + +// CHECK: cvtpi2pd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2a,0x2d,0xed,0x7e,0x00,0x00] + cvtpi2pd 0x7eed,%xmm5 + +// CHECK: cvtpi2pd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2a,0x2d,0xfe,0xca,0xbe,0xba] + cvtpi2pd 0xbabecafe,%xmm5 + +// CHECK: cvtpi2pd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2a,0x2d,0x78,0x56,0x34,0x12] + cvtpi2pd 0x12345678,%xmm5 + +// CHECK: cvtpi2pd %mm3, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2a,0xeb] + cvtpi2pd %mm3,%xmm5 + +// CHECK: cvtsi2sd %ecx, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x2a,0xe9] + cvtsi2sd %ecx,%xmm5 + +// CHECK: cvtsi2sd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x2a,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtsi2sd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtsi2sd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x2a,0x2d,0x45,0x00,0x00,0x00] + cvtsi2sd 0x45,%xmm5 + +// CHECK: cvtsi2sd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x2a,0x2d,0xed,0x7e,0x00,0x00] + cvtsi2sd 0x7eed,%xmm5 + +// CHECK: cvtsi2sd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x2a,0x2d,0xfe,0xca,0xbe,0xba] + cvtsi2sd 0xbabecafe,%xmm5 + +// CHECK: cvtsi2sd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x2a,0x2d,0x78,0x56,0x34,0x12] + cvtsi2sd 0x12345678,%xmm5 + +// CHECK: divpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5e,0xac,0xcb,0xef,0xbe,0xad,0xde] + divpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: divpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5e,0x2d,0x45,0x00,0x00,0x00] + divpd 0x45,%xmm5 + +// CHECK: divpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5e,0x2d,0xed,0x7e,0x00,0x00] + divpd 0x7eed,%xmm5 + +// CHECK: divpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5e,0x2d,0xfe,0xca,0xbe,0xba] + divpd 0xbabecafe,%xmm5 + +// CHECK: divpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5e,0x2d,0x78,0x56,0x34,0x12] + divpd 0x12345678,%xmm5 + +// CHECK: divpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5e,0xed] + divpd %xmm5,%xmm5 + +// CHECK: divsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5e,0xac,0xcb,0xef,0xbe,0xad,0xde] + divsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: divsd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5e,0x2d,0x45,0x00,0x00,0x00] + divsd 0x45,%xmm5 + +// CHECK: divsd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5e,0x2d,0xed,0x7e,0x00,0x00] + divsd 0x7eed,%xmm5 + +// CHECK: divsd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5e,0x2d,0xfe,0xca,0xbe,0xba] + divsd 0xbabecafe,%xmm5 + +// CHECK: divsd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5e,0x2d,0x78,0x56,0x34,0x12] + divsd 0x12345678,%xmm5 + +// CHECK: divsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5e,0xed] + divsd %xmm5,%xmm5 + +// CHECK: maxpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5f,0xac,0xcb,0xef,0xbe,0xad,0xde] + maxpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: maxpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5f,0x2d,0x45,0x00,0x00,0x00] + maxpd 0x45,%xmm5 + +// CHECK: maxpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5f,0x2d,0xed,0x7e,0x00,0x00] + maxpd 0x7eed,%xmm5 + +// CHECK: maxpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5f,0x2d,0xfe,0xca,0xbe,0xba] + maxpd 0xbabecafe,%xmm5 + +// CHECK: maxpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5f,0x2d,0x78,0x56,0x34,0x12] + maxpd 0x12345678,%xmm5 + +// CHECK: maxpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5f,0xed] + maxpd %xmm5,%xmm5 + +// CHECK: maxsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5f,0xac,0xcb,0xef,0xbe,0xad,0xde] + maxsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: maxsd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5f,0x2d,0x45,0x00,0x00,0x00] + maxsd 0x45,%xmm5 + +// CHECK: maxsd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5f,0x2d,0xed,0x7e,0x00,0x00] + maxsd 0x7eed,%xmm5 + +// CHECK: maxsd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5f,0x2d,0xfe,0xca,0xbe,0xba] + maxsd 0xbabecafe,%xmm5 + +// CHECK: maxsd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5f,0x2d,0x78,0x56,0x34,0x12] + maxsd 0x12345678,%xmm5 + +// CHECK: maxsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5f,0xed] + maxsd %xmm5,%xmm5 + +// CHECK: minpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5d,0xac,0xcb,0xef,0xbe,0xad,0xde] + minpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: minpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5d,0x2d,0x45,0x00,0x00,0x00] + minpd 0x45,%xmm5 + +// CHECK: minpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5d,0x2d,0xed,0x7e,0x00,0x00] + minpd 0x7eed,%xmm5 + +// CHECK: minpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5d,0x2d,0xfe,0xca,0xbe,0xba] + minpd 0xbabecafe,%xmm5 + +// CHECK: minpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5d,0x2d,0x78,0x56,0x34,0x12] + minpd 0x12345678,%xmm5 + +// CHECK: minpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5d,0xed] + minpd %xmm5,%xmm5 + +// CHECK: minsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5d,0xac,0xcb,0xef,0xbe,0xad,0xde] + minsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: minsd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5d,0x2d,0x45,0x00,0x00,0x00] + minsd 0x45,%xmm5 + +// CHECK: minsd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5d,0x2d,0xed,0x7e,0x00,0x00] + minsd 0x7eed,%xmm5 + +// CHECK: minsd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5d,0x2d,0xfe,0xca,0xbe,0xba] + minsd 0xbabecafe,%xmm5 + +// CHECK: minsd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5d,0x2d,0x78,0x56,0x34,0x12] + minsd 0x12345678,%xmm5 + +// CHECK: minsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5d,0xed] + minsd %xmm5,%xmm5 + +// CHECK: movapd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x28,0xac,0xcb,0xef,0xbe,0xad,0xde] + movapd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movapd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x28,0x2d,0x45,0x00,0x00,0x00] + movapd 0x45,%xmm5 + +// CHECK: movapd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x28,0x2d,0xed,0x7e,0x00,0x00] + movapd 0x7eed,%xmm5 + +// CHECK: movapd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x28,0x2d,0xfe,0xca,0xbe,0xba] + movapd 0xbabecafe,%xmm5 + +// CHECK: movapd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x28,0x2d,0x78,0x56,0x34,0x12] + movapd 0x12345678,%xmm5 + +// CHECK: movapd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x28,0xed] + movapd %xmm5,%xmm5 + +// CHECK: movapd %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0x29,0xac,0xcb,0xef,0xbe,0xad,0xde] + movapd %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movapd %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0x29,0x2d,0x45,0x00,0x00,0x00] + movapd %xmm5,0x45 + +// CHECK: movapd %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0x29,0x2d,0xed,0x7e,0x00,0x00] + movapd %xmm5,0x7eed + +// CHECK: movapd %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0x29,0x2d,0xfe,0xca,0xbe,0xba] + movapd %xmm5,0xbabecafe + +// CHECK: movapd %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0x29,0x2d,0x78,0x56,0x34,0x12] + movapd %xmm5,0x12345678 + +// CHECK: movapd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x28,0xed] + movapd %xmm5,%xmm5 + +// CHECK: movhpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x16,0xac,0xcb,0xef,0xbe,0xad,0xde] + movhpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movhpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x16,0x2d,0x45,0x00,0x00,0x00] + movhpd 0x45,%xmm5 + +// CHECK: movhpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x16,0x2d,0xed,0x7e,0x00,0x00] + movhpd 0x7eed,%xmm5 + +// CHECK: movhpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x16,0x2d,0xfe,0xca,0xbe,0xba] + movhpd 0xbabecafe,%xmm5 + +// CHECK: movhpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x16,0x2d,0x78,0x56,0x34,0x12] + movhpd 0x12345678,%xmm5 + +// CHECK: movhpd %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0x17,0xac,0xcb,0xef,0xbe,0xad,0xde] + movhpd %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movhpd %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0x17,0x2d,0x45,0x00,0x00,0x00] + movhpd %xmm5,0x45 + +// CHECK: movhpd %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0x17,0x2d,0xed,0x7e,0x00,0x00] + movhpd %xmm5,0x7eed + +// CHECK: movhpd %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0x17,0x2d,0xfe,0xca,0xbe,0xba] + movhpd %xmm5,0xbabecafe + +// CHECK: movhpd %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0x17,0x2d,0x78,0x56,0x34,0x12] + movhpd %xmm5,0x12345678 + +// CHECK: movlpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x12,0xac,0xcb,0xef,0xbe,0xad,0xde] + movlpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movlpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x12,0x2d,0x45,0x00,0x00,0x00] + movlpd 0x45,%xmm5 + +// CHECK: movlpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x12,0x2d,0xed,0x7e,0x00,0x00] + movlpd 0x7eed,%xmm5 + +// CHECK: movlpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x12,0x2d,0xfe,0xca,0xbe,0xba] + movlpd 0xbabecafe,%xmm5 + +// CHECK: movlpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x12,0x2d,0x78,0x56,0x34,0x12] + movlpd 0x12345678,%xmm5 + +// CHECK: movlpd %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0x13,0xac,0xcb,0xef,0xbe,0xad,0xde] + movlpd %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movlpd %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0x13,0x2d,0x45,0x00,0x00,0x00] + movlpd %xmm5,0x45 + +// CHECK: movlpd %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0x13,0x2d,0xed,0x7e,0x00,0x00] + movlpd %xmm5,0x7eed + +// CHECK: movlpd %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0x13,0x2d,0xfe,0xca,0xbe,0xba] + movlpd %xmm5,0xbabecafe + +// CHECK: movlpd %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0x13,0x2d,0x78,0x56,0x34,0x12] + movlpd %xmm5,0x12345678 + +// CHECK: movmskpd %xmm5, %ecx +// CHECK: encoding: [0x66,0x0f,0x50,0xcd] + movmskpd %xmm5,%ecx + +// CHECK: movntpd %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0x2b,0xac,0xcb,0xef,0xbe,0xad,0xde] + movntpd %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movntpd %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0x2b,0x2d,0x45,0x00,0x00,0x00] + movntpd %xmm5,0x45 + +// CHECK: movntpd %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0x2b,0x2d,0xed,0x7e,0x00,0x00] + movntpd %xmm5,0x7eed + +// CHECK: movntpd %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0x2b,0x2d,0xfe,0xca,0xbe,0xba] + movntpd %xmm5,0xbabecafe + +// CHECK: movntpd %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0x2b,0x2d,0x78,0x56,0x34,0x12] + movntpd %xmm5,0x12345678 + +// CHECK: movsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x10,0xac,0xcb,0xef,0xbe,0xad,0xde] + movsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movsd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x10,0x2d,0x45,0x00,0x00,0x00] + movsd 0x45,%xmm5 + +// CHECK: movsd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x10,0x2d,0xed,0x7e,0x00,0x00] + movsd 0x7eed,%xmm5 + +// CHECK: movsd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x10,0x2d,0xfe,0xca,0xbe,0xba] + movsd 0xbabecafe,%xmm5 + +// CHECK: movsd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x10,0x2d,0x78,0x56,0x34,0x12] + movsd 0x12345678,%xmm5 + +// CHECK: movsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x10,0xed] + movsd %xmm5,%xmm5 + +// CHECK: movsd %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf2,0x0f,0x11,0xac,0xcb,0xef,0xbe,0xad,0xde] + movsd %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movsd %xmm5, 69 +// CHECK: encoding: [0xf2,0x0f,0x11,0x2d,0x45,0x00,0x00,0x00] + movsd %xmm5,0x45 + +// CHECK: movsd %xmm5, 32493 +// CHECK: encoding: [0xf2,0x0f,0x11,0x2d,0xed,0x7e,0x00,0x00] + movsd %xmm5,0x7eed + +// CHECK: movsd %xmm5, 3133065982 +// CHECK: encoding: [0xf2,0x0f,0x11,0x2d,0xfe,0xca,0xbe,0xba] + movsd %xmm5,0xbabecafe + +// CHECK: movsd %xmm5, 305419896 +// CHECK: encoding: [0xf2,0x0f,0x11,0x2d,0x78,0x56,0x34,0x12] + movsd %xmm5,0x12345678 + +// CHECK: movsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x10,0xed] + movsd %xmm5,%xmm5 + +// CHECK: movupd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x10,0xac,0xcb,0xef,0xbe,0xad,0xde] + movupd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movupd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x10,0x2d,0x45,0x00,0x00,0x00] + movupd 0x45,%xmm5 + +// CHECK: movupd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x10,0x2d,0xed,0x7e,0x00,0x00] + movupd 0x7eed,%xmm5 + +// CHECK: movupd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x10,0x2d,0xfe,0xca,0xbe,0xba] + movupd 0xbabecafe,%xmm5 + +// CHECK: movupd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x10,0x2d,0x78,0x56,0x34,0x12] + movupd 0x12345678,%xmm5 + +// CHECK: movupd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x10,0xed] + movupd %xmm5,%xmm5 + +// CHECK: movupd %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0x11,0xac,0xcb,0xef,0xbe,0xad,0xde] + movupd %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movupd %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0x11,0x2d,0x45,0x00,0x00,0x00] + movupd %xmm5,0x45 + +// CHECK: movupd %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0x11,0x2d,0xed,0x7e,0x00,0x00] + movupd %xmm5,0x7eed + +// CHECK: movupd %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0x11,0x2d,0xfe,0xca,0xbe,0xba] + movupd %xmm5,0xbabecafe + +// CHECK: movupd %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0x11,0x2d,0x78,0x56,0x34,0x12] + movupd %xmm5,0x12345678 + +// CHECK: movupd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x10,0xed] + movupd %xmm5,%xmm5 + +// CHECK: mulpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x59,0xac,0xcb,0xef,0xbe,0xad,0xde] + mulpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: mulpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x59,0x2d,0x45,0x00,0x00,0x00] + mulpd 0x45,%xmm5 + +// CHECK: mulpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x59,0x2d,0xed,0x7e,0x00,0x00] + mulpd 0x7eed,%xmm5 + +// CHECK: mulpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x59,0x2d,0xfe,0xca,0xbe,0xba] + mulpd 0xbabecafe,%xmm5 + +// CHECK: mulpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x59,0x2d,0x78,0x56,0x34,0x12] + mulpd 0x12345678,%xmm5 + +// CHECK: mulpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x59,0xed] + mulpd %xmm5,%xmm5 + +// CHECK: mulsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x59,0xac,0xcb,0xef,0xbe,0xad,0xde] + mulsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: mulsd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x59,0x2d,0x45,0x00,0x00,0x00] + mulsd 0x45,%xmm5 + +// CHECK: mulsd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x59,0x2d,0xed,0x7e,0x00,0x00] + mulsd 0x7eed,%xmm5 + +// CHECK: mulsd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x59,0x2d,0xfe,0xca,0xbe,0xba] + mulsd 0xbabecafe,%xmm5 + +// CHECK: mulsd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x59,0x2d,0x78,0x56,0x34,0x12] + mulsd 0x12345678,%xmm5 + +// CHECK: mulsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x59,0xed] + mulsd %xmm5,%xmm5 + +// CHECK: orpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x56,0xac,0xcb,0xef,0xbe,0xad,0xde] + orpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: orpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x56,0x2d,0x45,0x00,0x00,0x00] + orpd 0x45,%xmm5 + +// CHECK: orpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x56,0x2d,0xed,0x7e,0x00,0x00] + orpd 0x7eed,%xmm5 + +// CHECK: orpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x56,0x2d,0xfe,0xca,0xbe,0xba] + orpd 0xbabecafe,%xmm5 + +// CHECK: orpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x56,0x2d,0x78,0x56,0x34,0x12] + orpd 0x12345678,%xmm5 + +// CHECK: orpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x56,0xed] + orpd %xmm5,%xmm5 + +// CHECK: sqrtpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x51,0xac,0xcb,0xef,0xbe,0xad,0xde] + sqrtpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: sqrtpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x51,0x2d,0x45,0x00,0x00,0x00] + sqrtpd 0x45,%xmm5 + +// CHECK: sqrtpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x51,0x2d,0xed,0x7e,0x00,0x00] + sqrtpd 0x7eed,%xmm5 + +// CHECK: sqrtpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x51,0x2d,0xfe,0xca,0xbe,0xba] + sqrtpd 0xbabecafe,%xmm5 + +// CHECK: sqrtpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x51,0x2d,0x78,0x56,0x34,0x12] + sqrtpd 0x12345678,%xmm5 + +// CHECK: sqrtpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x51,0xed] + sqrtpd %xmm5,%xmm5 + +// CHECK: sqrtsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x51,0xac,0xcb,0xef,0xbe,0xad,0xde] + sqrtsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: sqrtsd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x51,0x2d,0x45,0x00,0x00,0x00] + sqrtsd 0x45,%xmm5 + +// CHECK: sqrtsd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x51,0x2d,0xed,0x7e,0x00,0x00] + sqrtsd 0x7eed,%xmm5 + +// CHECK: sqrtsd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x51,0x2d,0xfe,0xca,0xbe,0xba] + sqrtsd 0xbabecafe,%xmm5 + +// CHECK: sqrtsd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x51,0x2d,0x78,0x56,0x34,0x12] + sqrtsd 0x12345678,%xmm5 + +// CHECK: sqrtsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x51,0xed] + sqrtsd %xmm5,%xmm5 + +// CHECK: subpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5c,0xac,0xcb,0xef,0xbe,0xad,0xde] + subpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: subpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5c,0x2d,0x45,0x00,0x00,0x00] + subpd 0x45,%xmm5 + +// CHECK: subpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5c,0x2d,0xed,0x7e,0x00,0x00] + subpd 0x7eed,%xmm5 + +// CHECK: subpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5c,0x2d,0xfe,0xca,0xbe,0xba] + subpd 0xbabecafe,%xmm5 + +// CHECK: subpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5c,0x2d,0x78,0x56,0x34,0x12] + subpd 0x12345678,%xmm5 + +// CHECK: subpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5c,0xed] + subpd %xmm5,%xmm5 + +// CHECK: subsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5c,0xac,0xcb,0xef,0xbe,0xad,0xde] + subsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: subsd 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5c,0x2d,0x45,0x00,0x00,0x00] + subsd 0x45,%xmm5 + +// CHECK: subsd 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5c,0x2d,0xed,0x7e,0x00,0x00] + subsd 0x7eed,%xmm5 + +// CHECK: subsd 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5c,0x2d,0xfe,0xca,0xbe,0xba] + subsd 0xbabecafe,%xmm5 + +// CHECK: subsd 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5c,0x2d,0x78,0x56,0x34,0x12] + subsd 0x12345678,%xmm5 + +// CHECK: subsd %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5c,0xed] + subsd %xmm5,%xmm5 + +// CHECK: ucomisd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2e,0xac,0xcb,0xef,0xbe,0xad,0xde] + ucomisd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: ucomisd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2e,0x2d,0x45,0x00,0x00,0x00] + ucomisd 0x45,%xmm5 + +// CHECK: ucomisd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2e,0x2d,0xed,0x7e,0x00,0x00] + ucomisd 0x7eed,%xmm5 + +// CHECK: ucomisd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2e,0x2d,0xfe,0xca,0xbe,0xba] + ucomisd 0xbabecafe,%xmm5 + +// CHECK: ucomisd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2e,0x2d,0x78,0x56,0x34,0x12] + ucomisd 0x12345678,%xmm5 + +// CHECK: ucomisd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x2e,0xed] + ucomisd %xmm5,%xmm5 + +// CHECK: unpckhpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x15,0xac,0xcb,0xef,0xbe,0xad,0xde] + unpckhpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: unpckhpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x15,0x2d,0x45,0x00,0x00,0x00] + unpckhpd 0x45,%xmm5 + +// CHECK: unpckhpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x15,0x2d,0xed,0x7e,0x00,0x00] + unpckhpd 0x7eed,%xmm5 + +// CHECK: unpckhpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x15,0x2d,0xfe,0xca,0xbe,0xba] + unpckhpd 0xbabecafe,%xmm5 + +// CHECK: unpckhpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x15,0x2d,0x78,0x56,0x34,0x12] + unpckhpd 0x12345678,%xmm5 + +// CHECK: unpckhpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x15,0xed] + unpckhpd %xmm5,%xmm5 + +// CHECK: unpcklpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x14,0xac,0xcb,0xef,0xbe,0xad,0xde] + unpcklpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: unpcklpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x14,0x2d,0x45,0x00,0x00,0x00] + unpcklpd 0x45,%xmm5 + +// CHECK: unpcklpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x14,0x2d,0xed,0x7e,0x00,0x00] + unpcklpd 0x7eed,%xmm5 + +// CHECK: unpcklpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x14,0x2d,0xfe,0xca,0xbe,0xba] + unpcklpd 0xbabecafe,%xmm5 + +// CHECK: unpcklpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x14,0x2d,0x78,0x56,0x34,0x12] + unpcklpd 0x12345678,%xmm5 + +// CHECK: unpcklpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x14,0xed] + unpcklpd %xmm5,%xmm5 + +// CHECK: xorpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x57,0xac,0xcb,0xef,0xbe,0xad,0xde] + xorpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: xorpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x57,0x2d,0x45,0x00,0x00,0x00] + xorpd 0x45,%xmm5 + +// CHECK: xorpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x57,0x2d,0xed,0x7e,0x00,0x00] + xorpd 0x7eed,%xmm5 + +// CHECK: xorpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x57,0x2d,0xfe,0xca,0xbe,0xba] + xorpd 0xbabecafe,%xmm5 + +// CHECK: xorpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x57,0x2d,0x78,0x56,0x34,0x12] + xorpd 0x12345678,%xmm5 + +// CHECK: xorpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x57,0xed] + xorpd %xmm5,%xmm5 + +// CHECK: cvtdq2pd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0xe6,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtdq2pd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtdq2pd 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0xe6,0x2d,0x45,0x00,0x00,0x00] + cvtdq2pd 0x45,%xmm5 + +// CHECK: cvtdq2pd 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0xe6,0x2d,0xed,0x7e,0x00,0x00] + cvtdq2pd 0x7eed,%xmm5 + +// CHECK: cvtdq2pd 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0xe6,0x2d,0xfe,0xca,0xbe,0xba] + cvtdq2pd 0xbabecafe,%xmm5 + +// CHECK: cvtdq2pd 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0xe6,0x2d,0x78,0x56,0x34,0x12] + cvtdq2pd 0x12345678,%xmm5 + +// CHECK: cvtdq2pd %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0xe6,0xed] + cvtdq2pd %xmm5,%xmm5 + +// CHECK: cvtpd2dq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xe6,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtpd2dq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtpd2dq 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xe6,0x2d,0x45,0x00,0x00,0x00] + cvtpd2dq 0x45,%xmm5 + +// CHECK: cvtpd2dq 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xe6,0x2d,0xed,0x7e,0x00,0x00] + cvtpd2dq 0x7eed,%xmm5 + +// CHECK: cvtpd2dq 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xe6,0x2d,0xfe,0xca,0xbe,0xba] + cvtpd2dq 0xbabecafe,%xmm5 + +// CHECK: cvtpd2dq 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xe6,0x2d,0x78,0x56,0x34,0x12] + cvtpd2dq 0x12345678,%xmm5 + +// CHECK: cvtpd2dq %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xe6,0xed] + cvtpd2dq %xmm5,%xmm5 + +// CHECK: cvtdq2ps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x5b,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtdq2ps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtdq2ps 69, %xmm5 +// CHECK: encoding: [0x0f,0x5b,0x2d,0x45,0x00,0x00,0x00] + cvtdq2ps 0x45,%xmm5 + +// CHECK: cvtdq2ps 32493, %xmm5 +// CHECK: encoding: [0x0f,0x5b,0x2d,0xed,0x7e,0x00,0x00] + cvtdq2ps 0x7eed,%xmm5 + +// CHECK: cvtdq2ps 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x5b,0x2d,0xfe,0xca,0xbe,0xba] + cvtdq2ps 0xbabecafe,%xmm5 + +// CHECK: cvtdq2ps 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x5b,0x2d,0x78,0x56,0x34,0x12] + cvtdq2ps 0x12345678,%xmm5 + +// CHECK: cvtdq2ps %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x5b,0xed] + cvtdq2ps %xmm5,%xmm5 + +// CHECK: cvtpd2pi 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x66,0x0f,0x2d,0x9c,0xcb,0xef,0xbe,0xad,0xde] + cvtpd2pi 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: cvtpd2pi 69, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2d,0x1d,0x45,0x00,0x00,0x00] + cvtpd2pi 0x45,%mm3 + +// CHECK: cvtpd2pi 32493, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2d,0x1d,0xed,0x7e,0x00,0x00] + cvtpd2pi 0x7eed,%mm3 + +// CHECK: cvtpd2pi 3133065982, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2d,0x1d,0xfe,0xca,0xbe,0xba] + cvtpd2pi 0xbabecafe,%mm3 + +// CHECK: cvtpd2pi 305419896, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2d,0x1d,0x78,0x56,0x34,0x12] + cvtpd2pi 0x12345678,%mm3 + +// CHECK: cvtpd2pi %xmm5, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2d,0xdd] + cvtpd2pi %xmm5,%mm3 + +// CHECK: cvtpd2ps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5a,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtpd2ps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtpd2ps 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5a,0x2d,0x45,0x00,0x00,0x00] + cvtpd2ps 0x45,%xmm5 + +// CHECK: cvtpd2ps 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5a,0x2d,0xed,0x7e,0x00,0x00] + cvtpd2ps 0x7eed,%xmm5 + +// CHECK: cvtpd2ps 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5a,0x2d,0xfe,0xca,0xbe,0xba] + cvtpd2ps 0xbabecafe,%xmm5 + +// CHECK: cvtpd2ps 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5a,0x2d,0x78,0x56,0x34,0x12] + cvtpd2ps 0x12345678,%xmm5 + +// CHECK: cvtpd2ps %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5a,0xed] + cvtpd2ps %xmm5,%xmm5 + +// CHECK: cvtps2pd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x0f,0x5a,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtps2pd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtps2pd 69, %xmm5 +// CHECK: encoding: [0x0f,0x5a,0x2d,0x45,0x00,0x00,0x00] + cvtps2pd 0x45,%xmm5 + +// CHECK: cvtps2pd 32493, %xmm5 +// CHECK: encoding: [0x0f,0x5a,0x2d,0xed,0x7e,0x00,0x00] + cvtps2pd 0x7eed,%xmm5 + +// CHECK: cvtps2pd 3133065982, %xmm5 +// CHECK: encoding: [0x0f,0x5a,0x2d,0xfe,0xca,0xbe,0xba] + cvtps2pd 0xbabecafe,%xmm5 + +// CHECK: cvtps2pd 305419896, %xmm5 +// CHECK: encoding: [0x0f,0x5a,0x2d,0x78,0x56,0x34,0x12] + cvtps2pd 0x12345678,%xmm5 + +// CHECK: cvtps2pd %xmm5, %xmm5 +// CHECK: encoding: [0x0f,0x5a,0xed] + cvtps2pd %xmm5,%xmm5 + +// CHECK: cvtps2dq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5b,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtps2dq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtps2dq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5b,0x2d,0x45,0x00,0x00,0x00] + cvtps2dq 0x45,%xmm5 + +// CHECK: cvtps2dq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5b,0x2d,0xed,0x7e,0x00,0x00] + cvtps2dq 0x7eed,%xmm5 + +// CHECK: cvtps2dq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5b,0x2d,0xfe,0xca,0xbe,0xba] + cvtps2dq 0xbabecafe,%xmm5 + +// CHECK: cvtps2dq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5b,0x2d,0x78,0x56,0x34,0x12] + cvtps2dq 0x12345678,%xmm5 + +// CHECK: cvtps2dq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x5b,0xed] + cvtps2dq %xmm5,%xmm5 + +// CHECK: cvtsd2ss 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5a,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtsd2ss 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtsd2ss 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5a,0x2d,0x45,0x00,0x00,0x00] + cvtsd2ss 0x45,%xmm5 + +// CHECK: cvtsd2ss 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5a,0x2d,0xed,0x7e,0x00,0x00] + cvtsd2ss 0x7eed,%xmm5 + +// CHECK: cvtsd2ss 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5a,0x2d,0xfe,0xca,0xbe,0xba] + cvtsd2ss 0xbabecafe,%xmm5 + +// CHECK: cvtsd2ss 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5a,0x2d,0x78,0x56,0x34,0x12] + cvtsd2ss 0x12345678,%xmm5 + +// CHECK: cvtsd2ss %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x5a,0xed] + cvtsd2ss %xmm5,%xmm5 + +// CHECK: cvtss2sd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5a,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvtss2sd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvtss2sd 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5a,0x2d,0x45,0x00,0x00,0x00] + cvtss2sd 0x45,%xmm5 + +// CHECK: cvtss2sd 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5a,0x2d,0xed,0x7e,0x00,0x00] + cvtss2sd 0x7eed,%xmm5 + +// CHECK: cvtss2sd 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5a,0x2d,0xfe,0xca,0xbe,0xba] + cvtss2sd 0xbabecafe,%xmm5 + +// CHECK: cvtss2sd 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5a,0x2d,0x78,0x56,0x34,0x12] + cvtss2sd 0x12345678,%xmm5 + +// CHECK: cvtss2sd %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5a,0xed] + cvtss2sd %xmm5,%xmm5 + +// CHECK: cvttpd2pi 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x66,0x0f,0x2c,0x9c,0xcb,0xef,0xbe,0xad,0xde] + cvttpd2pi 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: cvttpd2pi 69, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2c,0x1d,0x45,0x00,0x00,0x00] + cvttpd2pi 0x45,%mm3 + +// CHECK: cvttpd2pi 32493, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2c,0x1d,0xed,0x7e,0x00,0x00] + cvttpd2pi 0x7eed,%mm3 + +// CHECK: cvttpd2pi 3133065982, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2c,0x1d,0xfe,0xca,0xbe,0xba] + cvttpd2pi 0xbabecafe,%mm3 + +// CHECK: cvttpd2pi 305419896, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2c,0x1d,0x78,0x56,0x34,0x12] + cvttpd2pi 0x12345678,%mm3 + +// CHECK: cvttpd2pi %xmm5, %mm3 +// CHECK: encoding: [0x66,0x0f,0x2c,0xdd] + cvttpd2pi %xmm5,%mm3 + +// CHECK: cvttsd2si 3735928559(%ebx,%ecx,8), %ecx +// CHECK: encoding: [0xf2,0x0f,0x2c,0x8c,0xcb,0xef,0xbe,0xad,0xde] + cvttsd2si 0xdeadbeef(%ebx,%ecx,8),%ecx + +// CHECK: cvttsd2si 69, %ecx +// CHECK: encoding: [0xf2,0x0f,0x2c,0x0d,0x45,0x00,0x00,0x00] + cvttsd2si 0x45,%ecx + +// CHECK: cvttsd2si 32493, %ecx +// CHECK: encoding: [0xf2,0x0f,0x2c,0x0d,0xed,0x7e,0x00,0x00] + cvttsd2si 0x7eed,%ecx + +// CHECK: cvttsd2si 3133065982, %ecx +// CHECK: encoding: [0xf2,0x0f,0x2c,0x0d,0xfe,0xca,0xbe,0xba] + cvttsd2si 0xbabecafe,%ecx + +// CHECK: cvttsd2si 305419896, %ecx +// CHECK: encoding: [0xf2,0x0f,0x2c,0x0d,0x78,0x56,0x34,0x12] + cvttsd2si 0x12345678,%ecx + +// CHECK: cvttsd2si %xmm5, %ecx +// CHECK: encoding: [0xf2,0x0f,0x2c,0xcd] + cvttsd2si %xmm5,%ecx + +// CHECK: cvttps2dq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5b,0xac,0xcb,0xef,0xbe,0xad,0xde] + cvttps2dq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: cvttps2dq 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5b,0x2d,0x45,0x00,0x00,0x00] + cvttps2dq 0x45,%xmm5 + +// CHECK: cvttps2dq 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5b,0x2d,0xed,0x7e,0x00,0x00] + cvttps2dq 0x7eed,%xmm5 + +// CHECK: cvttps2dq 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5b,0x2d,0xfe,0xca,0xbe,0xba] + cvttps2dq 0xbabecafe,%xmm5 + +// CHECK: cvttps2dq 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5b,0x2d,0x78,0x56,0x34,0x12] + cvttps2dq 0x12345678,%xmm5 + +// CHECK: cvttps2dq %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x5b,0xed] + cvttps2dq %xmm5,%xmm5 + +// CHECK: maskmovdqu %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf7,0xed] + maskmovdqu %xmm5,%xmm5 + +// CHECK: movdqa 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6f,0xac,0xcb,0xef,0xbe,0xad,0xde] + movdqa 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movdqa 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6f,0x2d,0x45,0x00,0x00,0x00] + movdqa 0x45,%xmm5 + +// CHECK: movdqa 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6f,0x2d,0xed,0x7e,0x00,0x00] + movdqa 0x7eed,%xmm5 + +// CHECK: movdqa 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6f,0x2d,0xfe,0xca,0xbe,0xba] + movdqa 0xbabecafe,%xmm5 + +// CHECK: movdqa 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6f,0x2d,0x78,0x56,0x34,0x12] + movdqa 0x12345678,%xmm5 + +// CHECK: movdqa %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6f,0xed] + movdqa %xmm5,%xmm5 + +// CHECK: movdqa %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0x7f,0xac,0xcb,0xef,0xbe,0xad,0xde] + movdqa %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movdqa %xmm5, 69 +// CHECK: encoding: [0x66,0x0f,0x7f,0x2d,0x45,0x00,0x00,0x00] + movdqa %xmm5,0x45 + +// CHECK: movdqa %xmm5, 32493 +// CHECK: encoding: [0x66,0x0f,0x7f,0x2d,0xed,0x7e,0x00,0x00] + movdqa %xmm5,0x7eed + +// CHECK: movdqa %xmm5, 3133065982 +// CHECK: encoding: [0x66,0x0f,0x7f,0x2d,0xfe,0xca,0xbe,0xba] + movdqa %xmm5,0xbabecafe + +// CHECK: movdqa %xmm5, 305419896 +// CHECK: encoding: [0x66,0x0f,0x7f,0x2d,0x78,0x56,0x34,0x12] + movdqa %xmm5,0x12345678 + +// CHECK: movdqa %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6f,0xed] + movdqa %xmm5,%xmm5 + +// CHECK: movdqu 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x6f,0xac,0xcb,0xef,0xbe,0xad,0xde] + movdqu 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movdqu 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x6f,0x2d,0x45,0x00,0x00,0x00] + movdqu 0x45,%xmm5 + +// CHECK: movdqu 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x6f,0x2d,0xed,0x7e,0x00,0x00] + movdqu 0x7eed,%xmm5 + +// CHECK: movdqu 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x6f,0x2d,0xfe,0xca,0xbe,0xba] + movdqu 0xbabecafe,%xmm5 + +// CHECK: movdqu 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x6f,0x2d,0x78,0x56,0x34,0x12] + movdqu 0x12345678,%xmm5 + +// CHECK: movdqu %xmm5, 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xf3,0x0f,0x7f,0xac,0xcb,0xef,0xbe,0xad,0xde] + movdqu %xmm5,0xdeadbeef(%ebx,%ecx,8) + +// CHECK: movdqu %xmm5, 69 +// CHECK: encoding: [0xf3,0x0f,0x7f,0x2d,0x45,0x00,0x00,0x00] + movdqu %xmm5,0x45 + +// CHECK: movdqu %xmm5, 32493 +// CHECK: encoding: [0xf3,0x0f,0x7f,0x2d,0xed,0x7e,0x00,0x00] + movdqu %xmm5,0x7eed + +// CHECK: movdqu %xmm5, 3133065982 +// CHECK: encoding: [0xf3,0x0f,0x7f,0x2d,0xfe,0xca,0xbe,0xba] + movdqu %xmm5,0xbabecafe + +// CHECK: movdqu %xmm5, 305419896 +// CHECK: encoding: [0xf3,0x0f,0x7f,0x2d,0x78,0x56,0x34,0x12] + movdqu %xmm5,0x12345678 + +// CHECK: movdq2q %xmm5, %mm3 +// CHECK: encoding: [0xf2,0x0f,0xd6,0xdd] + movdq2q %xmm5,%mm3 + +// CHECK: movq2dq %mm3, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0xd6,0xeb] + movq2dq %mm3,%xmm5 + +// CHECK: pmuludq 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0xf4,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmuludq 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmuludq 69, %mm3 +// CHECK: encoding: [0x0f,0xf4,0x1d,0x45,0x00,0x00,0x00] + pmuludq 0x45,%mm3 + +// CHECK: pmuludq 32493, %mm3 +// CHECK: encoding: [0x0f,0xf4,0x1d,0xed,0x7e,0x00,0x00] + pmuludq 0x7eed,%mm3 + +// CHECK: pmuludq 3133065982, %mm3 +// CHECK: encoding: [0x0f,0xf4,0x1d,0xfe,0xca,0xbe,0xba] + pmuludq 0xbabecafe,%mm3 + +// CHECK: pmuludq 305419896, %mm3 +// CHECK: encoding: [0x0f,0xf4,0x1d,0x78,0x56,0x34,0x12] + pmuludq 0x12345678,%mm3 + +// CHECK: pmuludq %mm3, %mm3 +// CHECK: encoding: [0x0f,0xf4,0xdb] + pmuludq %mm3,%mm3 + +// CHECK: pmuludq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf4,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmuludq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmuludq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf4,0x2d,0x45,0x00,0x00,0x00] + pmuludq 0x45,%xmm5 + +// CHECK: pmuludq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf4,0x2d,0xed,0x7e,0x00,0x00] + pmuludq 0x7eed,%xmm5 + +// CHECK: pmuludq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf4,0x2d,0xfe,0xca,0xbe,0xba] + pmuludq 0xbabecafe,%xmm5 + +// CHECK: pmuludq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf4,0x2d,0x78,0x56,0x34,0x12] + pmuludq 0x12345678,%xmm5 + +// CHECK: pmuludq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xf4,0xed] + pmuludq %xmm5,%xmm5 + +// CHECK: pslldq $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x73,0xfd,0x7f] + pslldq $0x7f,%xmm5 + +// CHECK: psrldq $127, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x73,0xdd,0x7f] + psrldq $0x7f,%xmm5 + +// CHECK: punpckhqdq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6d,0xac,0xcb,0xef,0xbe,0xad,0xde] + punpckhqdq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: punpckhqdq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6d,0x2d,0x45,0x00,0x00,0x00] + punpckhqdq 0x45,%xmm5 + +// CHECK: punpckhqdq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6d,0x2d,0xed,0x7e,0x00,0x00] + punpckhqdq 0x7eed,%xmm5 + +// CHECK: punpckhqdq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6d,0x2d,0xfe,0xca,0xbe,0xba] + punpckhqdq 0xbabecafe,%xmm5 + +// CHECK: punpckhqdq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6d,0x2d,0x78,0x56,0x34,0x12] + punpckhqdq 0x12345678,%xmm5 + +// CHECK: punpckhqdq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6d,0xed] + punpckhqdq %xmm5,%xmm5 + +// CHECK: punpcklqdq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6c,0xac,0xcb,0xef,0xbe,0xad,0xde] + punpcklqdq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: punpcklqdq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6c,0x2d,0x45,0x00,0x00,0x00] + punpcklqdq 0x45,%xmm5 + +// CHECK: punpcklqdq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6c,0x2d,0xed,0x7e,0x00,0x00] + punpcklqdq 0x7eed,%xmm5 + +// CHECK: punpcklqdq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6c,0x2d,0xfe,0xca,0xbe,0xba] + punpcklqdq 0xbabecafe,%xmm5 + +// CHECK: punpcklqdq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6c,0x2d,0x78,0x56,0x34,0x12] + punpcklqdq 0x12345678,%xmm5 + +// CHECK: punpcklqdq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x6c,0xed] + punpcklqdq %xmm5,%xmm5 + +// CHECK: addsubpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd0,0xac,0xcb,0xef,0xbe,0xad,0xde] + addsubpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: addsubpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd0,0x2d,0x45,0x00,0x00,0x00] + addsubpd 0x45,%xmm5 + +// CHECK: addsubpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd0,0x2d,0xed,0x7e,0x00,0x00] + addsubpd 0x7eed,%xmm5 + +// CHECK: addsubpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd0,0x2d,0xfe,0xca,0xbe,0xba] + addsubpd 0xbabecafe,%xmm5 + +// CHECK: addsubpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd0,0x2d,0x78,0x56,0x34,0x12] + addsubpd 0x12345678,%xmm5 + +// CHECK: addsubpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0xd0,0xed] + addsubpd %xmm5,%xmm5 + +// CHECK: addsubps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xd0,0xac,0xcb,0xef,0xbe,0xad,0xde] + addsubps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: addsubps 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xd0,0x2d,0x45,0x00,0x00,0x00] + addsubps 0x45,%xmm5 + +// CHECK: addsubps 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xd0,0x2d,0xed,0x7e,0x00,0x00] + addsubps 0x7eed,%xmm5 + +// CHECK: addsubps 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xd0,0x2d,0xfe,0xca,0xbe,0xba] + addsubps 0xbabecafe,%xmm5 + +// CHECK: addsubps 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xd0,0x2d,0x78,0x56,0x34,0x12] + addsubps 0x12345678,%xmm5 + +// CHECK: addsubps %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xd0,0xed] + addsubps %xmm5,%xmm5 + +// CHECK: fisttpl 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0xdb,0x8c,0xcb,0xef,0xbe,0xad,0xde] + fisttpl 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: fisttpl 3133065982 +// CHECK: encoding: [0xdb,0x0d,0xfe,0xca,0xbe,0xba] + fisttpl 0xbabecafe + +// CHECK: fisttpl 305419896 +// CHECK: encoding: [0xdb,0x0d,0x78,0x56,0x34,0x12] + fisttpl 0x12345678 + +// CHECK: haddpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7c,0xac,0xcb,0xef,0xbe,0xad,0xde] + haddpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: haddpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7c,0x2d,0x45,0x00,0x00,0x00] + haddpd 0x45,%xmm5 + +// CHECK: haddpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7c,0x2d,0xed,0x7e,0x00,0x00] + haddpd 0x7eed,%xmm5 + +// CHECK: haddpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7c,0x2d,0xfe,0xca,0xbe,0xba] + haddpd 0xbabecafe,%xmm5 + +// CHECK: haddpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7c,0x2d,0x78,0x56,0x34,0x12] + haddpd 0x12345678,%xmm5 + +// CHECK: haddpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7c,0xed] + haddpd %xmm5,%xmm5 + +// CHECK: haddps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7c,0xac,0xcb,0xef,0xbe,0xad,0xde] + haddps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: haddps 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7c,0x2d,0x45,0x00,0x00,0x00] + haddps 0x45,%xmm5 + +// CHECK: haddps 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7c,0x2d,0xed,0x7e,0x00,0x00] + haddps 0x7eed,%xmm5 + +// CHECK: haddps 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7c,0x2d,0xfe,0xca,0xbe,0xba] + haddps 0xbabecafe,%xmm5 + +// CHECK: haddps 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7c,0x2d,0x78,0x56,0x34,0x12] + haddps 0x12345678,%xmm5 + +// CHECK: haddps %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7c,0xed] + haddps %xmm5,%xmm5 + +// CHECK: hsubpd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7d,0xac,0xcb,0xef,0xbe,0xad,0xde] + hsubpd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: hsubpd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7d,0x2d,0x45,0x00,0x00,0x00] + hsubpd 0x45,%xmm5 + +// CHECK: hsubpd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7d,0x2d,0xed,0x7e,0x00,0x00] + hsubpd 0x7eed,%xmm5 + +// CHECK: hsubpd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7d,0x2d,0xfe,0xca,0xbe,0xba] + hsubpd 0xbabecafe,%xmm5 + +// CHECK: hsubpd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7d,0x2d,0x78,0x56,0x34,0x12] + hsubpd 0x12345678,%xmm5 + +// CHECK: hsubpd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x7d,0xed] + hsubpd %xmm5,%xmm5 + +// CHECK: hsubps 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7d,0xac,0xcb,0xef,0xbe,0xad,0xde] + hsubps 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: hsubps 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7d,0x2d,0x45,0x00,0x00,0x00] + hsubps 0x45,%xmm5 + +// CHECK: hsubps 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7d,0x2d,0xed,0x7e,0x00,0x00] + hsubps 0x7eed,%xmm5 + +// CHECK: hsubps 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7d,0x2d,0xfe,0xca,0xbe,0xba] + hsubps 0xbabecafe,%xmm5 + +// CHECK: hsubps 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7d,0x2d,0x78,0x56,0x34,0x12] + hsubps 0x12345678,%xmm5 + +// CHECK: hsubps %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x7d,0xed] + hsubps %xmm5,%xmm5 + +// CHECK: lddqu 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xf0,0xac,0xcb,0xef,0xbe,0xad,0xde] + lddqu 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: lddqu 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xf0,0x2d,0x45,0x00,0x00,0x00] + lddqu 0x45,%xmm5 + +// CHECK: lddqu 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xf0,0x2d,0xed,0x7e,0x00,0x00] + lddqu 0x7eed,%xmm5 + +// CHECK: lddqu 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xf0,0x2d,0xfe,0xca,0xbe,0xba] + lddqu 0xbabecafe,%xmm5 + +// CHECK: lddqu 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0xf0,0x2d,0x78,0x56,0x34,0x12] + lddqu 0x12345678,%xmm5 + +// CHECK: movddup 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x12,0xac,0xcb,0xef,0xbe,0xad,0xde] + movddup 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movddup 69, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x12,0x2d,0x45,0x00,0x00,0x00] + movddup 0x45,%xmm5 + +// CHECK: movddup 32493, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x12,0x2d,0xed,0x7e,0x00,0x00] + movddup 0x7eed,%xmm5 + +// CHECK: movddup 3133065982, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x12,0x2d,0xfe,0xca,0xbe,0xba] + movddup 0xbabecafe,%xmm5 + +// CHECK: movddup 305419896, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x12,0x2d,0x78,0x56,0x34,0x12] + movddup 0x12345678,%xmm5 + +// CHECK: movddup %xmm5, %xmm5 +// CHECK: encoding: [0xf2,0x0f,0x12,0xed] + movddup %xmm5,%xmm5 + +// CHECK: movshdup 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x16,0xac,0xcb,0xef,0xbe,0xad,0xde] + movshdup 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movshdup 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x16,0x2d,0x45,0x00,0x00,0x00] + movshdup 0x45,%xmm5 + +// CHECK: movshdup 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x16,0x2d,0xed,0x7e,0x00,0x00] + movshdup 0x7eed,%xmm5 + +// CHECK: movshdup 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x16,0x2d,0xfe,0xca,0xbe,0xba] + movshdup 0xbabecafe,%xmm5 + +// CHECK: movshdup 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x16,0x2d,0x78,0x56,0x34,0x12] + movshdup 0x12345678,%xmm5 + +// CHECK: movshdup %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x16,0xed] + movshdup %xmm5,%xmm5 + +// CHECK: movsldup 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x12,0xac,0xcb,0xef,0xbe,0xad,0xde] + movsldup 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movsldup 69, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x12,0x2d,0x45,0x00,0x00,0x00] + movsldup 0x45,%xmm5 + +// CHECK: movsldup 32493, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x12,0x2d,0xed,0x7e,0x00,0x00] + movsldup 0x7eed,%xmm5 + +// CHECK: movsldup 3133065982, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x12,0x2d,0xfe,0xca,0xbe,0xba] + movsldup 0xbabecafe,%xmm5 + +// CHECK: movsldup 305419896, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x12,0x2d,0x78,0x56,0x34,0x12] + movsldup 0x12345678,%xmm5 + +// CHECK: movsldup %xmm5, %xmm5 +// CHECK: encoding: [0xf3,0x0f,0x12,0xed] + movsldup %xmm5,%xmm5 + +// CHECK: vmclear 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x66,0x0f,0xc7,0xb4,0xcb,0xef,0xbe,0xad,0xde] + vmclear 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: vmclear 32493 +// CHECK: encoding: [0x66,0x0f,0xc7,0x35,0xed,0x7e,0x00,0x00] + vmclear 0x7eed + +// CHECK: vmclear 3133065982 +// CHECK: encoding: [0x66,0x0f,0xc7,0x35,0xfe,0xca,0xbe,0xba] + vmclear 0xbabecafe + +// CHECK: vmclear 305419896 +// CHECK: encoding: [0x66,0x0f,0xc7,0x35,0x78,0x56,0x34,0x12] + vmclear 0x12345678 + +// CHECK: vmptrld 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xc7,0xb4,0xcb,0xef,0xbe,0xad,0xde] + vmptrld 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: vmptrld 32493 +// CHECK: encoding: [0x0f,0xc7,0x35,0xed,0x7e,0x00,0x00] + vmptrld 0x7eed + +// CHECK: vmptrld 3133065982 +// CHECK: encoding: [0x0f,0xc7,0x35,0xfe,0xca,0xbe,0xba] + vmptrld 0xbabecafe + +// CHECK: vmptrld 305419896 +// CHECK: encoding: [0x0f,0xc7,0x35,0x78,0x56,0x34,0x12] + vmptrld 0x12345678 + +// CHECK: vmptrst 3735928559(%ebx,%ecx,8) +// CHECK: encoding: [0x0f,0xc7,0xbc,0xcb,0xef,0xbe,0xad,0xde] + vmptrst 0xdeadbeef(%ebx,%ecx,8) + +// CHECK: vmptrst 32493 +// CHECK: encoding: [0x0f,0xc7,0x3d,0xed,0x7e,0x00,0x00] + vmptrst 0x7eed + +// CHECK: vmptrst 3133065982 +// CHECK: encoding: [0x0f,0xc7,0x3d,0xfe,0xca,0xbe,0xba] + vmptrst 0xbabecafe + +// CHECK: vmptrst 305419896 +// CHECK: encoding: [0x0f,0xc7,0x3d,0x78,0x56,0x34,0x12] + vmptrst 0x12345678 + +// CHECK: phaddw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x01,0x9c,0xcb,0xef,0xbe,0xad,0xde] + phaddw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: phaddw 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x01,0x1d,0x45,0x00,0x00,0x00] + phaddw 0x45,%mm3 + +// CHECK: phaddw 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x01,0x1d,0xed,0x7e,0x00,0x00] + phaddw 0x7eed,%mm3 + +// CHECK: phaddw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x01,0x1d,0xfe,0xca,0xbe,0xba] + phaddw 0xbabecafe,%mm3 + +// CHECK: phaddw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x01,0x1d,0x78,0x56,0x34,0x12] + phaddw 0x12345678,%mm3 + +// CHECK: phaddw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x01,0xdb] + phaddw %mm3,%mm3 + +// CHECK: phaddw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x01,0xac,0xcb,0xef,0xbe,0xad,0xde] + phaddw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: phaddw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x01,0x2d,0x45,0x00,0x00,0x00] + phaddw 0x45,%xmm5 + +// CHECK: phaddw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x01,0x2d,0xed,0x7e,0x00,0x00] + phaddw 0x7eed,%xmm5 + +// CHECK: phaddw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x01,0x2d,0xfe,0xca,0xbe,0xba] + phaddw 0xbabecafe,%xmm5 + +// CHECK: phaddw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x01,0x2d,0x78,0x56,0x34,0x12] + phaddw 0x12345678,%xmm5 + +// CHECK: phaddw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x01,0xed] + phaddw %xmm5,%xmm5 + +// CHECK: phaddd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x02,0x9c,0xcb,0xef,0xbe,0xad,0xde] + phaddd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: phaddd 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x02,0x1d,0x45,0x00,0x00,0x00] + phaddd 0x45,%mm3 + +// CHECK: phaddd 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x02,0x1d,0xed,0x7e,0x00,0x00] + phaddd 0x7eed,%mm3 + +// CHECK: phaddd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x02,0x1d,0xfe,0xca,0xbe,0xba] + phaddd 0xbabecafe,%mm3 + +// CHECK: phaddd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x02,0x1d,0x78,0x56,0x34,0x12] + phaddd 0x12345678,%mm3 + +// CHECK: phaddd %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x02,0xdb] + phaddd %mm3,%mm3 + +// CHECK: phaddd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x02,0xac,0xcb,0xef,0xbe,0xad,0xde] + phaddd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: phaddd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x02,0x2d,0x45,0x00,0x00,0x00] + phaddd 0x45,%xmm5 + +// CHECK: phaddd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x02,0x2d,0xed,0x7e,0x00,0x00] + phaddd 0x7eed,%xmm5 + +// CHECK: phaddd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x02,0x2d,0xfe,0xca,0xbe,0xba] + phaddd 0xbabecafe,%xmm5 + +// CHECK: phaddd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x02,0x2d,0x78,0x56,0x34,0x12] + phaddd 0x12345678,%xmm5 + +// CHECK: phaddd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x02,0xed] + phaddd %xmm5,%xmm5 + +// CHECK: phaddsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x03,0x9c,0xcb,0xef,0xbe,0xad,0xde] + phaddsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: phaddsw 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x03,0x1d,0x45,0x00,0x00,0x00] + phaddsw 0x45,%mm3 + +// CHECK: phaddsw 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x03,0x1d,0xed,0x7e,0x00,0x00] + phaddsw 0x7eed,%mm3 + +// CHECK: phaddsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x03,0x1d,0xfe,0xca,0xbe,0xba] + phaddsw 0xbabecafe,%mm3 + +// CHECK: phaddsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x03,0x1d,0x78,0x56,0x34,0x12] + phaddsw 0x12345678,%mm3 + +// CHECK: phaddsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x03,0xdb] + phaddsw %mm3,%mm3 + +// CHECK: phaddsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x03,0xac,0xcb,0xef,0xbe,0xad,0xde] + phaddsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: phaddsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x03,0x2d,0x45,0x00,0x00,0x00] + phaddsw 0x45,%xmm5 + +// CHECK: phaddsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x03,0x2d,0xed,0x7e,0x00,0x00] + phaddsw 0x7eed,%xmm5 + +// CHECK: phaddsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x03,0x2d,0xfe,0xca,0xbe,0xba] + phaddsw 0xbabecafe,%xmm5 + +// CHECK: phaddsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x03,0x2d,0x78,0x56,0x34,0x12] + phaddsw 0x12345678,%xmm5 + +// CHECK: phaddsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x03,0xed] + phaddsw %xmm5,%xmm5 + +// CHECK: phsubw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x05,0x9c,0xcb,0xef,0xbe,0xad,0xde] + phsubw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: phsubw 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x05,0x1d,0x45,0x00,0x00,0x00] + phsubw 0x45,%mm3 + +// CHECK: phsubw 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x05,0x1d,0xed,0x7e,0x00,0x00] + phsubw 0x7eed,%mm3 + +// CHECK: phsubw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x05,0x1d,0xfe,0xca,0xbe,0xba] + phsubw 0xbabecafe,%mm3 + +// CHECK: phsubw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x05,0x1d,0x78,0x56,0x34,0x12] + phsubw 0x12345678,%mm3 + +// CHECK: phsubw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x05,0xdb] + phsubw %mm3,%mm3 + +// CHECK: phsubw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x05,0xac,0xcb,0xef,0xbe,0xad,0xde] + phsubw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: phsubw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x05,0x2d,0x45,0x00,0x00,0x00] + phsubw 0x45,%xmm5 + +// CHECK: phsubw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x05,0x2d,0xed,0x7e,0x00,0x00] + phsubw 0x7eed,%xmm5 + +// CHECK: phsubw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x05,0x2d,0xfe,0xca,0xbe,0xba] + phsubw 0xbabecafe,%xmm5 + +// CHECK: phsubw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x05,0x2d,0x78,0x56,0x34,0x12] + phsubw 0x12345678,%xmm5 + +// CHECK: phsubw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x05,0xed] + phsubw %xmm5,%xmm5 + +// CHECK: phsubd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x06,0x9c,0xcb,0xef,0xbe,0xad,0xde] + phsubd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: phsubd 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x06,0x1d,0x45,0x00,0x00,0x00] + phsubd 0x45,%mm3 + +// CHECK: phsubd 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x06,0x1d,0xed,0x7e,0x00,0x00] + phsubd 0x7eed,%mm3 + +// CHECK: phsubd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x06,0x1d,0xfe,0xca,0xbe,0xba] + phsubd 0xbabecafe,%mm3 + +// CHECK: phsubd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x06,0x1d,0x78,0x56,0x34,0x12] + phsubd 0x12345678,%mm3 + +// CHECK: phsubd %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x06,0xdb] + phsubd %mm3,%mm3 + +// CHECK: phsubd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x06,0xac,0xcb,0xef,0xbe,0xad,0xde] + phsubd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: phsubd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x06,0x2d,0x45,0x00,0x00,0x00] + phsubd 0x45,%xmm5 + +// CHECK: phsubd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x06,0x2d,0xed,0x7e,0x00,0x00] + phsubd 0x7eed,%xmm5 + +// CHECK: phsubd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x06,0x2d,0xfe,0xca,0xbe,0xba] + phsubd 0xbabecafe,%xmm5 + +// CHECK: phsubd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x06,0x2d,0x78,0x56,0x34,0x12] + phsubd 0x12345678,%xmm5 + +// CHECK: phsubd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x06,0xed] + phsubd %xmm5,%xmm5 + +// CHECK: phsubsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x07,0x9c,0xcb,0xef,0xbe,0xad,0xde] + phsubsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: phsubsw 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x07,0x1d,0x45,0x00,0x00,0x00] + phsubsw 0x45,%mm3 + +// CHECK: phsubsw 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x07,0x1d,0xed,0x7e,0x00,0x00] + phsubsw 0x7eed,%mm3 + +// CHECK: phsubsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x07,0x1d,0xfe,0xca,0xbe,0xba] + phsubsw 0xbabecafe,%mm3 + +// CHECK: phsubsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x07,0x1d,0x78,0x56,0x34,0x12] + phsubsw 0x12345678,%mm3 + +// CHECK: phsubsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x07,0xdb] + phsubsw %mm3,%mm3 + +// CHECK: phsubsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x07,0xac,0xcb,0xef,0xbe,0xad,0xde] + phsubsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: phsubsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x07,0x2d,0x45,0x00,0x00,0x00] + phsubsw 0x45,%xmm5 + +// CHECK: phsubsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x07,0x2d,0xed,0x7e,0x00,0x00] + phsubsw 0x7eed,%xmm5 + +// CHECK: phsubsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x07,0x2d,0xfe,0xca,0xbe,0xba] + phsubsw 0xbabecafe,%xmm5 + +// CHECK: phsubsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x07,0x2d,0x78,0x56,0x34,0x12] + phsubsw 0x12345678,%xmm5 + +// CHECK: phsubsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x07,0xed] + phsubsw %xmm5,%xmm5 + +// CHECK: pmaddubsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x04,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmaddubsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmaddubsw 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x04,0x1d,0x45,0x00,0x00,0x00] + pmaddubsw 0x45,%mm3 + +// CHECK: pmaddubsw 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x04,0x1d,0xed,0x7e,0x00,0x00] + pmaddubsw 0x7eed,%mm3 + +// CHECK: pmaddubsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x04,0x1d,0xfe,0xca,0xbe,0xba] + pmaddubsw 0xbabecafe,%mm3 + +// CHECK: pmaddubsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x04,0x1d,0x78,0x56,0x34,0x12] + pmaddubsw 0x12345678,%mm3 + +// CHECK: pmaddubsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x04,0xdb] + pmaddubsw %mm3,%mm3 + +// CHECK: pmaddubsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x04,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmaddubsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmaddubsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x04,0x2d,0x45,0x00,0x00,0x00] + pmaddubsw 0x45,%xmm5 + +// CHECK: pmaddubsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x04,0x2d,0xed,0x7e,0x00,0x00] + pmaddubsw 0x7eed,%xmm5 + +// CHECK: pmaddubsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x04,0x2d,0xfe,0xca,0xbe,0xba] + pmaddubsw 0xbabecafe,%xmm5 + +// CHECK: pmaddubsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x04,0x2d,0x78,0x56,0x34,0x12] + pmaddubsw 0x12345678,%xmm5 + +// CHECK: pmaddubsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x04,0xed] + pmaddubsw %xmm5,%xmm5 + +// CHECK: pmulhrsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x0b,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pmulhrsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pmulhrsw 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0b,0x1d,0x45,0x00,0x00,0x00] + pmulhrsw 0x45,%mm3 + +// CHECK: pmulhrsw 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0b,0x1d,0xed,0x7e,0x00,0x00] + pmulhrsw 0x7eed,%mm3 + +// CHECK: pmulhrsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0b,0x1d,0xfe,0xca,0xbe,0xba] + pmulhrsw 0xbabecafe,%mm3 + +// CHECK: pmulhrsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0b,0x1d,0x78,0x56,0x34,0x12] + pmulhrsw 0x12345678,%mm3 + +// CHECK: pmulhrsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0b,0xdb] + pmulhrsw %mm3,%mm3 + +// CHECK: pmulhrsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0b,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmulhrsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmulhrsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0b,0x2d,0x45,0x00,0x00,0x00] + pmulhrsw 0x45,%xmm5 + +// CHECK: pmulhrsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0b,0x2d,0xed,0x7e,0x00,0x00] + pmulhrsw 0x7eed,%xmm5 + +// CHECK: pmulhrsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0b,0x2d,0xfe,0xca,0xbe,0xba] + pmulhrsw 0xbabecafe,%xmm5 + +// CHECK: pmulhrsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0b,0x2d,0x78,0x56,0x34,0x12] + pmulhrsw 0x12345678,%xmm5 + +// CHECK: pmulhrsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0b,0xed] + pmulhrsw %xmm5,%xmm5 + +// CHECK: pshufb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x00,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pshufb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pshufb 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x00,0x1d,0x45,0x00,0x00,0x00] + pshufb 0x45,%mm3 + +// CHECK: pshufb 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x00,0x1d,0xed,0x7e,0x00,0x00] + pshufb 0x7eed,%mm3 + +// CHECK: pshufb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x00,0x1d,0xfe,0xca,0xbe,0xba] + pshufb 0xbabecafe,%mm3 + +// CHECK: pshufb 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x00,0x1d,0x78,0x56,0x34,0x12] + pshufb 0x12345678,%mm3 + +// CHECK: pshufb %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x00,0xdb] + pshufb %mm3,%mm3 + +// CHECK: pshufb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x00,0xac,0xcb,0xef,0xbe,0xad,0xde] + pshufb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pshufb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x00,0x2d,0x45,0x00,0x00,0x00] + pshufb 0x45,%xmm5 + +// CHECK: pshufb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x00,0x2d,0xed,0x7e,0x00,0x00] + pshufb 0x7eed,%xmm5 + +// CHECK: pshufb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x00,0x2d,0xfe,0xca,0xbe,0xba] + pshufb 0xbabecafe,%xmm5 + +// CHECK: pshufb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x00,0x2d,0x78,0x56,0x34,0x12] + pshufb 0x12345678,%xmm5 + +// CHECK: pshufb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x00,0xed] + pshufb %xmm5,%xmm5 + +// CHECK: psignb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x08,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psignb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psignb 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x08,0x1d,0x45,0x00,0x00,0x00] + psignb 0x45,%mm3 + +// CHECK: psignb 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x08,0x1d,0xed,0x7e,0x00,0x00] + psignb 0x7eed,%mm3 + +// CHECK: psignb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x08,0x1d,0xfe,0xca,0xbe,0xba] + psignb 0xbabecafe,%mm3 + +// CHECK: psignb 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x08,0x1d,0x78,0x56,0x34,0x12] + psignb 0x12345678,%mm3 + +// CHECK: psignb %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x08,0xdb] + psignb %mm3,%mm3 + +// CHECK: psignb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x08,0xac,0xcb,0xef,0xbe,0xad,0xde] + psignb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psignb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x08,0x2d,0x45,0x00,0x00,0x00] + psignb 0x45,%xmm5 + +// CHECK: psignb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x08,0x2d,0xed,0x7e,0x00,0x00] + psignb 0x7eed,%xmm5 + +// CHECK: psignb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x08,0x2d,0xfe,0xca,0xbe,0xba] + psignb 0xbabecafe,%xmm5 + +// CHECK: psignb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x08,0x2d,0x78,0x56,0x34,0x12] + psignb 0x12345678,%xmm5 + +// CHECK: psignb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x08,0xed] + psignb %xmm5,%xmm5 + +// CHECK: psignw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x09,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psignw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psignw 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x09,0x1d,0x45,0x00,0x00,0x00] + psignw 0x45,%mm3 + +// CHECK: psignw 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x09,0x1d,0xed,0x7e,0x00,0x00] + psignw 0x7eed,%mm3 + +// CHECK: psignw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x09,0x1d,0xfe,0xca,0xbe,0xba] + psignw 0xbabecafe,%mm3 + +// CHECK: psignw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x09,0x1d,0x78,0x56,0x34,0x12] + psignw 0x12345678,%mm3 + +// CHECK: psignw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x09,0xdb] + psignw %mm3,%mm3 + +// CHECK: psignw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x09,0xac,0xcb,0xef,0xbe,0xad,0xde] + psignw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psignw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x09,0x2d,0x45,0x00,0x00,0x00] + psignw 0x45,%xmm5 + +// CHECK: psignw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x09,0x2d,0xed,0x7e,0x00,0x00] + psignw 0x7eed,%xmm5 + +// CHECK: psignw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x09,0x2d,0xfe,0xca,0xbe,0xba] + psignw 0xbabecafe,%xmm5 + +// CHECK: psignw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x09,0x2d,0x78,0x56,0x34,0x12] + psignw 0x12345678,%xmm5 + +// CHECK: psignw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x09,0xed] + psignw %xmm5,%xmm5 + +// CHECK: psignd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x0a,0x9c,0xcb,0xef,0xbe,0xad,0xde] + psignd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: psignd 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0a,0x1d,0x45,0x00,0x00,0x00] + psignd 0x45,%mm3 + +// CHECK: psignd 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0a,0x1d,0xed,0x7e,0x00,0x00] + psignd 0x7eed,%mm3 + +// CHECK: psignd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0a,0x1d,0xfe,0xca,0xbe,0xba] + psignd 0xbabecafe,%mm3 + +// CHECK: psignd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0a,0x1d,0x78,0x56,0x34,0x12] + psignd 0x12345678,%mm3 + +// CHECK: psignd %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x0a,0xdb] + psignd %mm3,%mm3 + +// CHECK: psignd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0a,0xac,0xcb,0xef,0xbe,0xad,0xde] + psignd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: psignd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0a,0x2d,0x45,0x00,0x00,0x00] + psignd 0x45,%xmm5 + +// CHECK: psignd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0a,0x2d,0xed,0x7e,0x00,0x00] + psignd 0x7eed,%xmm5 + +// CHECK: psignd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0a,0x2d,0xfe,0xca,0xbe,0xba] + psignd 0xbabecafe,%xmm5 + +// CHECK: psignd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0a,0x2d,0x78,0x56,0x34,0x12] + psignd 0x12345678,%xmm5 + +// CHECK: psignd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x0a,0xed] + psignd %xmm5,%xmm5 + +// CHECK: pabsb 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x1c,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pabsb 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pabsb 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1c,0x1d,0x45,0x00,0x00,0x00] + pabsb 0x45,%mm3 + +// CHECK: pabsb 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1c,0x1d,0xed,0x7e,0x00,0x00] + pabsb 0x7eed,%mm3 + +// CHECK: pabsb 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1c,0x1d,0xfe,0xca,0xbe,0xba] + pabsb 0xbabecafe,%mm3 + +// CHECK: pabsb 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1c,0x1d,0x78,0x56,0x34,0x12] + pabsb 0x12345678,%mm3 + +// CHECK: pabsb %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1c,0xdb] + pabsb %mm3,%mm3 + +// CHECK: pabsb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1c,0xac,0xcb,0xef,0xbe,0xad,0xde] + pabsb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pabsb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1c,0x2d,0x45,0x00,0x00,0x00] + pabsb 0x45,%xmm5 + +// CHECK: pabsb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1c,0x2d,0xed,0x7e,0x00,0x00] + pabsb 0x7eed,%xmm5 + +// CHECK: pabsb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1c,0x2d,0xfe,0xca,0xbe,0xba] + pabsb 0xbabecafe,%xmm5 + +// CHECK: pabsb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1c,0x2d,0x78,0x56,0x34,0x12] + pabsb 0x12345678,%xmm5 + +// CHECK: pabsb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1c,0xed] + pabsb %xmm5,%xmm5 + +// CHECK: pabsw 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x1d,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pabsw 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pabsw 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1d,0x1d,0x45,0x00,0x00,0x00] + pabsw 0x45,%mm3 + +// CHECK: pabsw 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1d,0x1d,0xed,0x7e,0x00,0x00] + pabsw 0x7eed,%mm3 + +// CHECK: pabsw 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1d,0x1d,0xfe,0xca,0xbe,0xba] + pabsw 0xbabecafe,%mm3 + +// CHECK: pabsw 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1d,0x1d,0x78,0x56,0x34,0x12] + pabsw 0x12345678,%mm3 + +// CHECK: pabsw %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1d,0xdb] + pabsw %mm3,%mm3 + +// CHECK: pabsw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1d,0xac,0xcb,0xef,0xbe,0xad,0xde] + pabsw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pabsw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1d,0x2d,0x45,0x00,0x00,0x00] + pabsw 0x45,%xmm5 + +// CHECK: pabsw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1d,0x2d,0xed,0x7e,0x00,0x00] + pabsw 0x7eed,%xmm5 + +// CHECK: pabsw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1d,0x2d,0xfe,0xca,0xbe,0xba] + pabsw 0xbabecafe,%xmm5 + +// CHECK: pabsw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1d,0x2d,0x78,0x56,0x34,0x12] + pabsw 0x12345678,%xmm5 + +// CHECK: pabsw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1d,0xed] + pabsw %xmm5,%xmm5 + +// CHECK: pabsd 3735928559(%ebx,%ecx,8), %mm3 +// CHECK: encoding: [0x0f,0x38,0x1e,0x9c,0xcb,0xef,0xbe,0xad,0xde] + pabsd 0xdeadbeef(%ebx,%ecx,8),%mm3 + +// CHECK: pabsd 69, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1e,0x1d,0x45,0x00,0x00,0x00] + pabsd 0x45,%mm3 + +// CHECK: pabsd 32493, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1e,0x1d,0xed,0x7e,0x00,0x00] + pabsd 0x7eed,%mm3 + +// CHECK: pabsd 3133065982, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1e,0x1d,0xfe,0xca,0xbe,0xba] + pabsd 0xbabecafe,%mm3 + +// CHECK: pabsd 305419896, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1e,0x1d,0x78,0x56,0x34,0x12] + pabsd 0x12345678,%mm3 + +// CHECK: pabsd %mm3, %mm3 +// CHECK: encoding: [0x0f,0x38,0x1e,0xdb] + pabsd %mm3,%mm3 + +// CHECK: pabsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1e,0xac,0xcb,0xef,0xbe,0xad,0xde] + pabsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pabsd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1e,0x2d,0x45,0x00,0x00,0x00] + pabsd 0x45,%xmm5 + +// CHECK: pabsd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1e,0x2d,0xed,0x7e,0x00,0x00] + pabsd 0x7eed,%xmm5 + +// CHECK: pabsd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1e,0x2d,0xfe,0xca,0xbe,0xba] + pabsd 0xbabecafe,%xmm5 + +// CHECK: pabsd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1e,0x2d,0x78,0x56,0x34,0x12] + pabsd 0x12345678,%xmm5 + +// CHECK: pabsd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x1e,0xed] + pabsd %xmm5,%xmm5 + +// CHECK: femms +// CHECK: encoding: [0x0f,0x0e] + femms + +// CHECK: movntdqa 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2a,0xac,0xcb,0xef,0xbe,0xad,0xde] + movntdqa 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: movntdqa 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2a,0x2d,0x45,0x00,0x00,0x00] + movntdqa 0x45,%xmm5 + +// CHECK: movntdqa 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2a,0x2d,0xed,0x7e,0x00,0x00] + movntdqa 0x7eed,%xmm5 + +// CHECK: movntdqa 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2a,0x2d,0xfe,0xca,0xbe,0xba] + movntdqa 0xbabecafe,%xmm5 + +// CHECK: movntdqa 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2a,0x2d,0x78,0x56,0x34,0x12] + movntdqa 0x12345678,%xmm5 + +// CHECK: packusdw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2b,0xac,0xcb,0xef,0xbe,0xad,0xde] + packusdw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: packusdw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2b,0x2d,0x45,0x00,0x00,0x00] + packusdw 0x45,%xmm5 + +// CHECK: packusdw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2b,0x2d,0xed,0x7e,0x00,0x00] + packusdw 0x7eed,%xmm5 + +// CHECK: packusdw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2b,0x2d,0xfe,0xca,0xbe,0xba] + packusdw 0xbabecafe,%xmm5 + +// CHECK: packusdw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2b,0x2d,0x78,0x56,0x34,0x12] + packusdw 0x12345678,%xmm5 + +// CHECK: packusdw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x2b,0xed] + packusdw %xmm5,%xmm5 + +// CHECK: pcmpeqq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x29,0xac,0xcb,0xef,0xbe,0xad,0xde] + pcmpeqq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pcmpeqq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x29,0x2d,0x45,0x00,0x00,0x00] + pcmpeqq 0x45,%xmm5 + +// CHECK: pcmpeqq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x29,0x2d,0xed,0x7e,0x00,0x00] + pcmpeqq 0x7eed,%xmm5 + +// CHECK: pcmpeqq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x29,0x2d,0xfe,0xca,0xbe,0xba] + pcmpeqq 0xbabecafe,%xmm5 + +// CHECK: pcmpeqq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x29,0x2d,0x78,0x56,0x34,0x12] + pcmpeqq 0x12345678,%xmm5 + +// CHECK: pcmpeqq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x29,0xed] + pcmpeqq %xmm5,%xmm5 + +// CHECK: phminposuw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x41,0xac,0xcb,0xef,0xbe,0xad,0xde] + phminposuw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: phminposuw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x41,0x2d,0x45,0x00,0x00,0x00] + phminposuw 0x45,%xmm5 + +// CHECK: phminposuw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x41,0x2d,0xed,0x7e,0x00,0x00] + phminposuw 0x7eed,%xmm5 + +// CHECK: phminposuw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x41,0x2d,0xfe,0xca,0xbe,0xba] + phminposuw 0xbabecafe,%xmm5 + +// CHECK: phminposuw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x41,0x2d,0x78,0x56,0x34,0x12] + phminposuw 0x12345678,%xmm5 + +// CHECK: phminposuw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x41,0xed] + phminposuw %xmm5,%xmm5 + +// CHECK: pmaxsb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3c,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmaxsb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmaxsb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3c,0x2d,0x45,0x00,0x00,0x00] + pmaxsb 0x45,%xmm5 + +// CHECK: pmaxsb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3c,0x2d,0xed,0x7e,0x00,0x00] + pmaxsb 0x7eed,%xmm5 + +// CHECK: pmaxsb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3c,0x2d,0xfe,0xca,0xbe,0xba] + pmaxsb 0xbabecafe,%xmm5 + +// CHECK: pmaxsb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3c,0x2d,0x78,0x56,0x34,0x12] + pmaxsb 0x12345678,%xmm5 + +// CHECK: pmaxsb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3c,0xed] + pmaxsb %xmm5,%xmm5 + +// CHECK: pmaxsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3d,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmaxsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmaxsd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3d,0x2d,0x45,0x00,0x00,0x00] + pmaxsd 0x45,%xmm5 + +// CHECK: pmaxsd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3d,0x2d,0xed,0x7e,0x00,0x00] + pmaxsd 0x7eed,%xmm5 + +// CHECK: pmaxsd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3d,0x2d,0xfe,0xca,0xbe,0xba] + pmaxsd 0xbabecafe,%xmm5 + +// CHECK: pmaxsd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3d,0x2d,0x78,0x56,0x34,0x12] + pmaxsd 0x12345678,%xmm5 + +// CHECK: pmaxsd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3d,0xed] + pmaxsd %xmm5,%xmm5 + +// CHECK: pmaxud 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3f,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmaxud 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmaxud 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3f,0x2d,0x45,0x00,0x00,0x00] + pmaxud 0x45,%xmm5 + +// CHECK: pmaxud 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3f,0x2d,0xed,0x7e,0x00,0x00] + pmaxud 0x7eed,%xmm5 + +// CHECK: pmaxud 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3f,0x2d,0xfe,0xca,0xbe,0xba] + pmaxud 0xbabecafe,%xmm5 + +// CHECK: pmaxud 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3f,0x2d,0x78,0x56,0x34,0x12] + pmaxud 0x12345678,%xmm5 + +// CHECK: pmaxud %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3f,0xed] + pmaxud %xmm5,%xmm5 + +// CHECK: pmaxuw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3e,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmaxuw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmaxuw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3e,0x2d,0x45,0x00,0x00,0x00] + pmaxuw 0x45,%xmm5 + +// CHECK: pmaxuw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3e,0x2d,0xed,0x7e,0x00,0x00] + pmaxuw 0x7eed,%xmm5 + +// CHECK: pmaxuw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3e,0x2d,0xfe,0xca,0xbe,0xba] + pmaxuw 0xbabecafe,%xmm5 + +// CHECK: pmaxuw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3e,0x2d,0x78,0x56,0x34,0x12] + pmaxuw 0x12345678,%xmm5 + +// CHECK: pmaxuw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3e,0xed] + pmaxuw %xmm5,%xmm5 + +// CHECK: pminsb 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x38,0xac,0xcb,0xef,0xbe,0xad,0xde] + pminsb 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pminsb 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x38,0x2d,0x45,0x00,0x00,0x00] + pminsb 0x45,%xmm5 + +// CHECK: pminsb 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x38,0x2d,0xed,0x7e,0x00,0x00] + pminsb 0x7eed,%xmm5 + +// CHECK: pminsb 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x38,0x2d,0xfe,0xca,0xbe,0xba] + pminsb 0xbabecafe,%xmm5 + +// CHECK: pminsb 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x38,0x2d,0x78,0x56,0x34,0x12] + pminsb 0x12345678,%xmm5 + +// CHECK: pminsb %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x38,0xed] + pminsb %xmm5,%xmm5 + +// CHECK: pminsd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x39,0xac,0xcb,0xef,0xbe,0xad,0xde] + pminsd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pminsd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x39,0x2d,0x45,0x00,0x00,0x00] + pminsd 0x45,%xmm5 + +// CHECK: pminsd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x39,0x2d,0xed,0x7e,0x00,0x00] + pminsd 0x7eed,%xmm5 + +// CHECK: pminsd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x39,0x2d,0xfe,0xca,0xbe,0xba] + pminsd 0xbabecafe,%xmm5 + +// CHECK: pminsd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x39,0x2d,0x78,0x56,0x34,0x12] + pminsd 0x12345678,%xmm5 + +// CHECK: pminsd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x39,0xed] + pminsd %xmm5,%xmm5 + +// CHECK: pminud 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3b,0xac,0xcb,0xef,0xbe,0xad,0xde] + pminud 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pminud 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3b,0x2d,0x45,0x00,0x00,0x00] + pminud 0x45,%xmm5 + +// CHECK: pminud 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3b,0x2d,0xed,0x7e,0x00,0x00] + pminud 0x7eed,%xmm5 + +// CHECK: pminud 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3b,0x2d,0xfe,0xca,0xbe,0xba] + pminud 0xbabecafe,%xmm5 + +// CHECK: pminud 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3b,0x2d,0x78,0x56,0x34,0x12] + pminud 0x12345678,%xmm5 + +// CHECK: pminud %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3b,0xed] + pminud %xmm5,%xmm5 + +// CHECK: pminuw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3a,0xac,0xcb,0xef,0xbe,0xad,0xde] + pminuw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pminuw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3a,0x2d,0x45,0x00,0x00,0x00] + pminuw 0x45,%xmm5 + +// CHECK: pminuw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3a,0x2d,0xed,0x7e,0x00,0x00] + pminuw 0x7eed,%xmm5 + +// CHECK: pminuw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3a,0x2d,0xfe,0xca,0xbe,0xba] + pminuw 0xbabecafe,%xmm5 + +// CHECK: pminuw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3a,0x2d,0x78,0x56,0x34,0x12] + pminuw 0x12345678,%xmm5 + +// CHECK: pminuw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x3a,0xed] + pminuw %xmm5,%xmm5 + +// CHECK: pmovsxbw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x20,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovsxbw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovsxbw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x20,0x2d,0x45,0x00,0x00,0x00] + pmovsxbw 0x45,%xmm5 + +// CHECK: pmovsxbw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x20,0x2d,0xed,0x7e,0x00,0x00] + pmovsxbw 0x7eed,%xmm5 + +// CHECK: pmovsxbw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x20,0x2d,0xfe,0xca,0xbe,0xba] + pmovsxbw 0xbabecafe,%xmm5 + +// CHECK: pmovsxbw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x20,0x2d,0x78,0x56,0x34,0x12] + pmovsxbw 0x12345678,%xmm5 + +// CHECK: pmovsxbw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x20,0xed] + pmovsxbw %xmm5,%xmm5 + +// CHECK: pmovsxbd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x21,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovsxbd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovsxbd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x21,0x2d,0x45,0x00,0x00,0x00] + pmovsxbd 0x45,%xmm5 + +// CHECK: pmovsxbd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x21,0x2d,0xed,0x7e,0x00,0x00] + pmovsxbd 0x7eed,%xmm5 + +// CHECK: pmovsxbd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x21,0x2d,0xfe,0xca,0xbe,0xba] + pmovsxbd 0xbabecafe,%xmm5 + +// CHECK: pmovsxbd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x21,0x2d,0x78,0x56,0x34,0x12] + pmovsxbd 0x12345678,%xmm5 + +// CHECK: pmovsxbd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x21,0xed] + pmovsxbd %xmm5,%xmm5 + +// CHECK: pmovsxbq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x22,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovsxbq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovsxbq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x22,0x2d,0x45,0x00,0x00,0x00] + pmovsxbq 0x45,%xmm5 + +// CHECK: pmovsxbq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x22,0x2d,0xed,0x7e,0x00,0x00] + pmovsxbq 0x7eed,%xmm5 + +// CHECK: pmovsxbq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x22,0x2d,0xfe,0xca,0xbe,0xba] + pmovsxbq 0xbabecafe,%xmm5 + +// CHECK: pmovsxbq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x22,0x2d,0x78,0x56,0x34,0x12] + pmovsxbq 0x12345678,%xmm5 + +// CHECK: pmovsxbq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x22,0xed] + pmovsxbq %xmm5,%xmm5 + +// CHECK: pmovsxwd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x23,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovsxwd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovsxwd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x23,0x2d,0x45,0x00,0x00,0x00] + pmovsxwd 0x45,%xmm5 + +// CHECK: pmovsxwd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x23,0x2d,0xed,0x7e,0x00,0x00] + pmovsxwd 0x7eed,%xmm5 + +// CHECK: pmovsxwd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x23,0x2d,0xfe,0xca,0xbe,0xba] + pmovsxwd 0xbabecafe,%xmm5 + +// CHECK: pmovsxwd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x23,0x2d,0x78,0x56,0x34,0x12] + pmovsxwd 0x12345678,%xmm5 + +// CHECK: pmovsxwd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x23,0xed] + pmovsxwd %xmm5,%xmm5 + +// CHECK: pmovsxwq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x24,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovsxwq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovsxwq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x24,0x2d,0x45,0x00,0x00,0x00] + pmovsxwq 0x45,%xmm5 + +// CHECK: pmovsxwq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x24,0x2d,0xed,0x7e,0x00,0x00] + pmovsxwq 0x7eed,%xmm5 + +// CHECK: pmovsxwq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x24,0x2d,0xfe,0xca,0xbe,0xba] + pmovsxwq 0xbabecafe,%xmm5 + +// CHECK: pmovsxwq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x24,0x2d,0x78,0x56,0x34,0x12] + pmovsxwq 0x12345678,%xmm5 + +// CHECK: pmovsxwq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x24,0xed] + pmovsxwq %xmm5,%xmm5 + +// CHECK: pmovsxdq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x25,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovsxdq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovsxdq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x25,0x2d,0x45,0x00,0x00,0x00] + pmovsxdq 0x45,%xmm5 + +// CHECK: pmovsxdq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x25,0x2d,0xed,0x7e,0x00,0x00] + pmovsxdq 0x7eed,%xmm5 + +// CHECK: pmovsxdq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x25,0x2d,0xfe,0xca,0xbe,0xba] + pmovsxdq 0xbabecafe,%xmm5 + +// CHECK: pmovsxdq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x25,0x2d,0x78,0x56,0x34,0x12] + pmovsxdq 0x12345678,%xmm5 + +// CHECK: pmovsxdq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x25,0xed] + pmovsxdq %xmm5,%xmm5 + +// CHECK: pmovzxbw 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x30,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovzxbw 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovzxbw 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x30,0x2d,0x45,0x00,0x00,0x00] + pmovzxbw 0x45,%xmm5 + +// CHECK: pmovzxbw 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x30,0x2d,0xed,0x7e,0x00,0x00] + pmovzxbw 0x7eed,%xmm5 + +// CHECK: pmovzxbw 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x30,0x2d,0xfe,0xca,0xbe,0xba] + pmovzxbw 0xbabecafe,%xmm5 + +// CHECK: pmovzxbw 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x30,0x2d,0x78,0x56,0x34,0x12] + pmovzxbw 0x12345678,%xmm5 + +// CHECK: pmovzxbw %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x30,0xed] + pmovzxbw %xmm5,%xmm5 + +// CHECK: pmovzxbd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x31,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovzxbd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovzxbd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x31,0x2d,0x45,0x00,0x00,0x00] + pmovzxbd 0x45,%xmm5 + +// CHECK: pmovzxbd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x31,0x2d,0xed,0x7e,0x00,0x00] + pmovzxbd 0x7eed,%xmm5 + +// CHECK: pmovzxbd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x31,0x2d,0xfe,0xca,0xbe,0xba] + pmovzxbd 0xbabecafe,%xmm5 + +// CHECK: pmovzxbd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x31,0x2d,0x78,0x56,0x34,0x12] + pmovzxbd 0x12345678,%xmm5 + +// CHECK: pmovzxbd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x31,0xed] + pmovzxbd %xmm5,%xmm5 + +// CHECK: pmovzxbq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x32,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovzxbq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovzxbq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x32,0x2d,0x45,0x00,0x00,0x00] + pmovzxbq 0x45,%xmm5 + +// CHECK: pmovzxbq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x32,0x2d,0xed,0x7e,0x00,0x00] + pmovzxbq 0x7eed,%xmm5 + +// CHECK: pmovzxbq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x32,0x2d,0xfe,0xca,0xbe,0xba] + pmovzxbq 0xbabecafe,%xmm5 + +// CHECK: pmovzxbq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x32,0x2d,0x78,0x56,0x34,0x12] + pmovzxbq 0x12345678,%xmm5 + +// CHECK: pmovzxbq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x32,0xed] + pmovzxbq %xmm5,%xmm5 + +// CHECK: pmovzxwd 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x33,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovzxwd 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovzxwd 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x33,0x2d,0x45,0x00,0x00,0x00] + pmovzxwd 0x45,%xmm5 + +// CHECK: pmovzxwd 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x33,0x2d,0xed,0x7e,0x00,0x00] + pmovzxwd 0x7eed,%xmm5 + +// CHECK: pmovzxwd 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x33,0x2d,0xfe,0xca,0xbe,0xba] + pmovzxwd 0xbabecafe,%xmm5 + +// CHECK: pmovzxwd 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x33,0x2d,0x78,0x56,0x34,0x12] + pmovzxwd 0x12345678,%xmm5 + +// CHECK: pmovzxwd %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x33,0xed] + pmovzxwd %xmm5,%xmm5 + +// CHECK: pmovzxwq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x34,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovzxwq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovzxwq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x34,0x2d,0x45,0x00,0x00,0x00] + pmovzxwq 0x45,%xmm5 + +// CHECK: pmovzxwq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x34,0x2d,0xed,0x7e,0x00,0x00] + pmovzxwq 0x7eed,%xmm5 + +// CHECK: pmovzxwq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x34,0x2d,0xfe,0xca,0xbe,0xba] + pmovzxwq 0xbabecafe,%xmm5 + +// CHECK: pmovzxwq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x34,0x2d,0x78,0x56,0x34,0x12] + pmovzxwq 0x12345678,%xmm5 + +// CHECK: pmovzxwq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x34,0xed] + pmovzxwq %xmm5,%xmm5 + +// CHECK: pmovzxdq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x35,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmovzxdq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmovzxdq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x35,0x2d,0x45,0x00,0x00,0x00] + pmovzxdq 0x45,%xmm5 + +// CHECK: pmovzxdq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x35,0x2d,0xed,0x7e,0x00,0x00] + pmovzxdq 0x7eed,%xmm5 + +// CHECK: pmovzxdq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x35,0x2d,0xfe,0xca,0xbe,0xba] + pmovzxdq 0xbabecafe,%xmm5 + +// CHECK: pmovzxdq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x35,0x2d,0x78,0x56,0x34,0x12] + pmovzxdq 0x12345678,%xmm5 + +// CHECK: pmovzxdq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x35,0xed] + pmovzxdq %xmm5,%xmm5 + +// CHECK: pmuldq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x28,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmuldq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmuldq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x28,0x2d,0x45,0x00,0x00,0x00] + pmuldq 0x45,%xmm5 + +// CHECK: pmuldq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x28,0x2d,0xed,0x7e,0x00,0x00] + pmuldq 0x7eed,%xmm5 + +// CHECK: pmuldq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x28,0x2d,0xfe,0xca,0xbe,0xba] + pmuldq 0xbabecafe,%xmm5 + +// CHECK: pmuldq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x28,0x2d,0x78,0x56,0x34,0x12] + pmuldq 0x12345678,%xmm5 + +// CHECK: pmuldq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x28,0xed] + pmuldq %xmm5,%xmm5 + +// CHECK: pmulld 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x40,0xac,0xcb,0xef,0xbe,0xad,0xde] + pmulld 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pmulld 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x40,0x2d,0x45,0x00,0x00,0x00] + pmulld 0x45,%xmm5 + +// CHECK: pmulld 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x40,0x2d,0xed,0x7e,0x00,0x00] + pmulld 0x7eed,%xmm5 + +// CHECK: pmulld 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x40,0x2d,0xfe,0xca,0xbe,0xba] + pmulld 0xbabecafe,%xmm5 + +// CHECK: pmulld 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x40,0x2d,0x78,0x56,0x34,0x12] + pmulld 0x12345678,%xmm5 + +// CHECK: pmulld %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x40,0xed] + pmulld %xmm5,%xmm5 + +// CHECK: ptest 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x17,0xac,0xcb,0xef,0xbe,0xad,0xde] + ptest 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: ptest 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x17,0x2d,0x45,0x00,0x00,0x00] + ptest 0x45,%xmm5 + +// CHECK: ptest 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x17,0x2d,0xed,0x7e,0x00,0x00] + ptest 0x7eed,%xmm5 + +// CHECK: ptest 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x17,0x2d,0xfe,0xca,0xbe,0xba] + ptest 0xbabecafe,%xmm5 + +// CHECK: ptest 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x17,0x2d,0x78,0x56,0x34,0x12] + ptest 0x12345678,%xmm5 + +// CHECK: ptest %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x17,0xed] + ptest %xmm5,%xmm5 + +// CHECK: pcmpgtq 3735928559(%ebx,%ecx,8), %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x37,0xac,0xcb,0xef,0xbe,0xad,0xde] + pcmpgtq 0xdeadbeef(%ebx,%ecx,8),%xmm5 + +// CHECK: pcmpgtq 69, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x37,0x2d,0x45,0x00,0x00,0x00] + pcmpgtq 0x45,%xmm5 + +// CHECK: pcmpgtq 32493, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x37,0x2d,0xed,0x7e,0x00,0x00] + pcmpgtq 0x7eed,%xmm5 + +// CHECK: pcmpgtq 3133065982, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x37,0x2d,0xfe,0xca,0xbe,0xba] + pcmpgtq 0xbabecafe,%xmm5 + +// CHECK: pcmpgtq 305419896, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x37,0x2d,0x78,0x56,0x34,0x12] + pcmpgtq 0x12345678,%xmm5 + +// CHECK: pcmpgtq %xmm5, %xmm5 +// CHECK: encoding: [0x66,0x0f,0x38,0x37,0xed] + pcmpgtq %xmm5,%xmm5 diff --git a/test/MC/AsmParser/X86/x86_32-new-encoder.s b/test/MC/AsmParser/X86/x86_32-new-encoder.s new file mode 100644 index 0000000000..6fd0cbb916 --- /dev/null +++ b/test/MC/AsmParser/X86/x86_32-new-encoder.s @@ -0,0 +1,41 @@ +// RUN: llvm-mc -triple i386-unknown-unknown --show-encoding %s | FileCheck %s + + lfence +// CHECK: lfence +// CHECK: encoding: [0x0f,0xae,0xe8] + mfence +// CHECK: mfence +// CHECK: encoding: [0x0f,0xae,0xf0] + monitor +// CHECK: monitor +// CHECK: encoding: [0x0f,0x01,0xc8] + mwait +// CHECK: mwait +// CHECK: encoding: [0x0f,0x01,0xc9] + + vmcall +// CHECK: vmcall +// CHECK: encoding: [0x0f,0x01,0xc1] + vmlaunch +// CHECK: vmlaunch +// CHECK: encoding: [0x0f,0x01,0xc2] + vmresume +// CHECK: vmresume +// CHECK: encoding: [0x0f,0x01,0xc3] + vmxoff +// CHECK: vmxoff +// CHECK: encoding: [0x0f,0x01,0xc4] + swapgs +// CHECK: swapgs +// CHECK: encoding: [0x0f,0x01,0xf8] + +rdtscp +// CHECK: rdtscp +// CHECK: encoding: [0x0f,0x01,0xf9] + + +// CHECK: movl %eax, 16(%ebp) # encoding: [0x89,0x45,0x10] + movl %eax, 16(%ebp) +// CHECK: movl %eax, -16(%ebp) # encoding: [0x89,0x45,0xf0] + movl %eax, -16(%ebp) + diff --git a/test/MC/AsmParser/X86/x86_64-new-encoder.s b/test/MC/AsmParser/X86/x86_64-new-encoder.s new file mode 100644 index 0000000000..56ec0b3899 --- /dev/null +++ b/test/MC/AsmParser/X86/x86_64-new-encoder.s @@ -0,0 +1,26 @@ +// RUN: llvm-mc -triple x86_64-unknown-unknown --show-encoding %s | FileCheck %s + +movl foo(%rip), %eax +// CHECK: movl foo(%rip), %eax +// CHECK: encoding: [0x8b,0x05,A,A,A,A] +// CHECK: fixup A - offset: 2, value: foo-4, kind: reloc_riprel_4byte + +movb $12, foo(%rip) +// CHECK: movb $12, foo(%rip) +// CHECK: encoding: [0xc6,0x05,A,A,A,A,0x0c] +// CHECK: fixup A - offset: 2, value: foo-5, kind: reloc_riprel_4byte + +movw $12, foo(%rip) +// CHECK: movw $12, foo(%rip) +// CHECK: encoding: [0x66,0xc7,0x05,A,A,A,A,0x0c,0x00] +// CHECK: fixup A - offset: 3, value: foo-6, kind: reloc_riprel_4byte + +movl $12, foo(%rip) +// CHECK: movl $12, foo(%rip) +// CHECK: encoding: [0xc7,0x05,A,A,A,A,0x0c,0x00,0x00,0x00] +// CHECK: fixup A - offset: 2, value: foo-8, kind: reloc_riprel_4byte + +movq $12, foo(%rip) +// CHECK: movq $12, foo(%rip) +// CHECK: encoding: [0x48,0xc7,0x05,A,A,A,A,0x0c,0x00,0x00,0x00] +// CHECK: fixup A - offset: 3, value: foo-8, kind: reloc_riprel_4byte diff --git a/test/MC/AsmParser/X86/x86_instructions.s b/test/MC/AsmParser/X86/x86_instructions.s index a74dcd24ea..b558c2eb5f 100644 --- a/test/MC/AsmParser/X86/x86_instructions.s +++ b/test/MC/AsmParser/X86/x86_instructions.s @@ -109,31 +109,31 @@ repne;scasb // CHECK: lock -// CHECK: cmpxchgb %al, 0(%ebx) +// CHECK: cmpxchgb %al, (%ebx) lock;cmpxchgb %al, 0(%ebx) // CHECK: cs -// CHECK: movb 0(%eax), %al +// CHECK: movb (%eax), %al cs;movb 0(%eax), %al // CHECK: ss -// CHECK: movb 0(%eax), %al +// CHECK: movb (%eax), %al ss;movb 0(%eax), %al // CHECK: ds -// CHECK: movb 0(%eax), %al +// CHECK: movb (%eax), %al ds;movb 0(%eax), %al // CHECK: es -// CHECK: movb 0(%eax), %al +// CHECK: movb (%eax), %al es;movb 0(%eax), %al // CHECK: fs -// CHECK: movb 0(%eax), %al +// CHECK: movb (%eax), %al fs;movb 0(%eax), %al // CHECK: gs -// CHECK: movb 0(%eax), %al +// CHECK: movb (%eax), %al gs;movb 0(%eax), %al // CHECK: fadd %st(0) diff --git a/test/MC/AsmParser/X86/x86_operands.s b/test/MC/AsmParser/X86/x86_operands.s index 433c9bf772..edddd1fc44 100644 --- a/test/MC/AsmParser/X86/x86_operands.s +++ b/test/MC/AsmParser/X86/x86_operands.s @@ -5,28 +5,28 @@ # Immediates # CHECK: addl $1, %eax addl $1, %eax -# CHECK: addl $1+2, %eax +# CHECK: addl $3, %eax addl $(1+2), %eax # CHECK: addl $a, %eax addl $a, %eax -# CHECK: addl $1+2, %eax +# CHECK: addl $3, %eax addl $1 + 2, %eax # Disambiguation - # FIXME: Add back when we can match this. - #addl $1, 4+4 - # FIXME: Add back when we can match this. - #addl $1, (4+4) -# CHECK: addl $1, 4+4(%eax) +# CHECK: addl $1, 8 + addl $1, 4+4 +# CHECK: addl $1, 8 + addl $1, (4+4) +# CHECK: addl $1, 8(%eax) addl $1, 4+4(%eax) -# CHECK: addl $1, 4+4(%eax) +# CHECK: addl $1, 8(%eax) addl $1, (4+4)(%eax) # CHECK: addl $1, 8(%eax) addl $1, 8(%eax) -# CHECK: addl $1, 0(%eax) +# CHECK: addl $1, (%eax) addl $1, (%eax) -# CHECK: addl $1, 4+4(,%eax) +# CHECK: addl $1, 8(,%eax) addl $1, (4+4)(,%eax) # Indirect Memory Operands diff --git a/test/MC/AsmParser/conditional_asm.s b/test/MC/AsmParser/conditional_asm.s index b8a514fb4f..f619ef9bb4 100644 --- a/test/MC/AsmParser/conditional_asm.s +++ b/test/MC/AsmParser/conditional_asm.s @@ -1,6 +1,6 @@ # RUN: llvm-mc -triple i386-unknown-unknown %s -I %p | FileCheck %s -# CHECK: .byte 1+1 +# CHECK: .byte 2 .if 1+2 .if 1-1 .byte 1 diff --git a/test/MC/Disassembler/simple-tests.txt b/test/MC/Disassembler/simple-tests.txt index 1e3249f826..11c077d892 100644 --- a/test/MC/Disassembler/simple-tests.txt +++ b/test/MC/Disassembler/simple-tests.txt @@ -13,3 +13,32 @@ # CHECK: callq -1234 0xe8 0x2e 0xfb 0xff 0xff +# CHECK: lfence +0x0f 0xae 0xe8 + +# CHECK: mfence +0x0f 0xae 0xf0 + +# CHECK: monitor +0x0f 0x01 0xc8 + +# CHECK: mwait +0x0f 0x01 0xc9 + +# CHECK: vmcall +0x0f 0x01 0xc1 + +# CHECK: vmlaunch +0x0f 0x01 0xc2 + +# CHECK: vmresume +0x0f 0x01 0xc3 + +# CHECK: vmxoff +0x0f 0x01 0xc4 + +# CHECK: swapgs +0x0f 0x01 0xf8 + +# CHECK: rdtscp +0x0f 0x01 0xf9 \ No newline at end of file diff --git a/test/MC/MachO/Darwin/optimal_nop.s b/test/MC/MachO/Darwin/optimal_nop.s new file mode 100644 index 0000000000..29cb0738e1 --- /dev/null +++ b/test/MC/MachO/Darwin/optimal_nop.s @@ -0,0 +1,156 @@ +// Validate that we can assemble this file exactly like the platform +// assembler. +// +// RUN: llvm-mc -filetype=obj -triple i386-apple-darwin10 -o %t.mc.o %s +// RUN: as -arch i386 -o %t.as.o %s +// RUN: diff %t.mc.o %t.as.o + +# 1 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + # nop + # 0x90 + .align 1, 0x90 + ret +# 2 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + # xchg %ax,%ax + # 0x66, 0x90 + .align 2, 0x90 + ret +# 3 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + # nopl (%[re]ax) + # 0x0f, 0x1f, 0x00 + .align 2, 0x90 + ret +# 4 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + ret + ret + # nopl 0(%[re]ax) + # 0x0f, 0x1f, 0x40, 0x00 + .align 3, 0x90 + ret +# 5 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + ret + # nopl 0(%[re]ax,%[re]ax,1) + # 0x0f, 0x1f, 0x44, 0x00, 0x00 + .align 3, 0x90 + ret +# 6 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + # nopw 0(%[re]ax,%[re]ax,1) + # 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 + .align 3, 0x90 + ret +# 7 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + # nopl 0L(%[re]ax) + # 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 + .align 3, 0x90 + ret +# 8 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + ret + ret + ret + ret + ret + ret + # nopl 0L(%[re]ax,%[re]ax,1) + # 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 + .align 3, 0x90 + ret +# 9 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + ret + ret + ret + ret + ret + # nopw 0L(%[re]ax,%[re]ax,1) + # 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 + .align 4, 0x90 + ret +# 10 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + ret + ret + ret + ret + ret + # nopw %cs:0L(%[re]ax,%[re]ax,1) + # 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 + .align 4, 0x90 + ret +# 11 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + ret + ret + ret + # nopw %cs:0L(%[re]ax,%[re]ax,1) + # 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 + .align 4, 0x90 + ret +# 12 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + ret + ret + # nopw 0(%[re]ax,%[re]ax,1) + # nopw 0(%[re]ax,%[re]ax,1) + # 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, + # 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 + .align 4, 0x90 + ret +# 13 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + ret + # nopw 0(%[re]ax,%[re]ax,1) + # nopl 0L(%[re]ax) + # 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, + # 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 + .align 4, 0x90 + ret +# 14 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + ret + # nopl 0L(%[re]ax) + # nopl 0L(%[re]ax) + # 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, + # 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 + .align 4, 0x90 + ret +# 15 byte nop test + .align 4, 0 # start with 16 byte alignment filled with zeros + ret + # nopl 0L(%[re]ax) + # nopl 0L(%[re]ax,%[re]ax,1) + # 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, + # 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 + .align 4, 0x90 + ret diff --git a/test/Makefile b/test/Makefile index e7776f8459..3750fdb2f1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -155,7 +155,6 @@ site.exp: FORCE @echo 'set target_triplet "$(TARGET_TRIPLE)"' >> site.tmp @echo 'set TARGETS_TO_BUILD "$(TARGETS_TO_BUILD)"' >> site.tmp @echo 'set llvmgcc_langs "$(LLVMGCC_LANGS)"' >> site.tmp - @echo 'set llvmgcc_version "$(LLVMGCC_VERSION)"' >> site.tmp @echo 'set llvmtoolsdir "$(ToolDir)"' >>site.tmp @echo 'set llvmlibsdir "$(LibDir)"' >>site.tmp @echo 'set llvm_bindings "$(BINDINGS_TO_BUILD)"' >> site.tmp @@ -170,7 +169,6 @@ site.exp: FORCE @echo 'set link "' $(CXX) $(CPP.Flags) $(CXX.Flags) $(TargetCommonOpts) $(CompileCommonOpts) $(LD.Flags) '"' >>site.tmp @echo 'set llvmgcc "$(LLVMGCC) $(TargetCommonOpts) $(EXTRA_OPTIONS)"' >> site.tmp @echo 'set llvmgxx "$(LLVMGCC) $(TargetCommonOpts) $(EXTRA_OPTIONS)"' >> site.tmp - @echo 'set llvmgccmajvers "$(LLVMGCC_MAJVERS)"' >> site.tmp @echo 'set bugpoint_topts $(BUGPOINT_TOPTS)' >> site.tmp @echo 'set shlibext "$(SHLIBEXT)"' >> site.tmp @echo 'set ocamlopt "$(OCAMLOPT) -cc \"$(CXX_FOR_OCAMLOPT)\" -I $(LibDir)/ocaml"' >> site.tmp @@ -200,4 +198,6 @@ Unit/lit.site.cfg: $(PROJ_OBJ_DIR)/Unit/.dir FORCE -e "s#@LLVM_TOOLS_DIR@#$(ToolDir)#g" \ -e "s#@LLVMGCCDIR@#$(LLVMGCCDIR)#g" \ -e "s#@LLVM_BUILD_MODE@#$(BuildMode)#g" \ + -e "s#@ENABLE_SHARED@#$(ENABLE_SHARED)#g" \ + -e "s#@SHLIBPATH_VAR@#$(SHLIBPATH_VAR)#g" \ $(PROJ_SRC_DIR)/Unit/lit.site.cfg.in > $@ diff --git a/test/Makefile.tests b/test/Makefile.tests index 90e9f2c705..aeb5871e7c 100644 --- a/test/Makefile.tests +++ b/test/Makefile.tests @@ -49,15 +49,15 @@ clean:: # Compile from X.c to Output/X.ll Output/%.ll: %.c $(LCC1) Output/.dir $(INCLUDES) - -$(LLVMGCCWITHPATH) $(CPPFLAGS) $(LCCFLAGS) -S $< -o $@ + -$(LLVMCC) $(CPPFLAGS) $(LCCFLAGS) -S $< -o $@ # Compile from X.cpp to Output/X.ll Output/%.ll: %.cpp $(LCC1XX) Output/.dir $(INCLUDES) - -$(LLVMGXXWITHPATH) $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@ + -$(LLVMCXX) $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@ # Compile from X.cc to Output/X.ll Output/%.ll: %.cc $(LCC1XX) Output/.dir $(INCLUDES) - -$(LLVMGXXWITHPATH) $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@ + -$(LLVMCXX) $(CPPFLAGS) $(LCXXFLAGS) -S $< -o $@ # LLVM Assemble from Output/X.ll to Output/X.bc. Output/X.ll must have come # from GCC output, so use GCCAS. diff --git a/test/Other/2008-03-19-PassManager.ll b/test/Other/2008-03-19-PassManager.ll deleted file mode 100644 index e2082228e3..0000000000 --- a/test/Other/2008-03-19-PassManager.ll +++ /dev/null @@ -1,58 +0,0 @@ -; PR 2034 -; RUN: opt < %s -anders-aa -instcombine -gvn -disable-output - %struct.FULL = type { i32, i32, [1000 x float*] } - -define i32 @sgesl(%struct.FULL* %a, i32* %ipvt, float* %b, i32 %job) { -entry: - %a_addr = alloca %struct.FULL* ; <%struct.FULL**> [#uses=1] - %ipvt_addr = alloca i32* ; [#uses=1] - %b_addr = alloca float* ; [#uses=1] - %job_addr = alloca i32 ; [#uses=1] - %akk = alloca float* ; [#uses=2] - %k = alloca i32 ; [#uses=1] - %l = alloca i32 ; [#uses=1] - %n = alloca i32 ; [#uses=1] - %nm1 = alloca i32 ; [#uses=1] - %tmp5 = load i32* %job_addr, align 4 ; [#uses=1] - %tmp6 = icmp eq i32 %tmp5, 0 ; [#uses=1] - %tmp67 = zext i1 %tmp6 to i8 ; [#uses=1] - %toBool = icmp ne i8 %tmp67, 0 ; [#uses=1] - br i1 %toBool, label %cond_true, label %cond_next137 - -cond_true: ; preds = %entry - %tmp732 = load i32* %nm1, align 4 ; [#uses=1] - %tmp743 = icmp slt i32 0, %tmp732 ; [#uses=1] - %tmp74754 = zext i1 %tmp743 to i8 ; [#uses=1] - %toBool765 = icmp ne i8 %tmp74754, 0 ; [#uses=1] - br i1 %toBool765, label %bb, label %bb77 - -bb: ; preds = %cond_true - %tmp9 = load %struct.FULL** %a_addr, align 4 ; <%struct.FULL*> [#uses=1] - %tmp10 = getelementptr %struct.FULL* %tmp9, i32 0, i32 2 ; <[1000 x float*]*> [#uses=1] - %tmp11 = getelementptr [1000 x float*]* %tmp10, i32 0, i32 0 ; [#uses=1] - %tmp12 = load float** %tmp11, align 4 ; [#uses=1] - %tmp13 = load i32* %k, align 4 ; [#uses=1] - %tmp14 = getelementptr float* %tmp12, i32 %tmp13 ; [#uses=1] - store float* %tmp14, float** %akk, align 4 - %tmp17 = load float** %b_addr, align 4 ; [#uses=0] - %tmp18 = load i32* %l, align 4 ; [#uses=0] - ret i32 0 - -bb77: ; preds = %cond_true - ret i32 0 - -cond_next137: ; preds = %entry - %tmp18922 = load i32* %n, align 4 ; [#uses=1] - %tmp19023 = icmp slt i32 0, %tmp18922 ; [#uses=1] - %tmp19019124 = zext i1 %tmp19023 to i8 ; [#uses=1] - %toBool19225 = icmp ne i8 %tmp19019124, 0 ; [#uses=1] - br i1 %toBool19225, label %bb138, label %bb193 - -bb138: ; preds = %cond_next137 - store float* null, float** %akk, align 4 - ret i32 0 - -bb193: ; preds = %cond_next137 - %tmp196 = load i32** %ipvt_addr, align 4 ; [#uses=0] - ret i32 0 -} diff --git a/test/Other/constant-fold-gep.ll b/test/Other/constant-fold-gep.ll index 2888b3d2b0..5358e1f523 100644 --- a/test/Other/constant-fold-gep.ll +++ b/test/Other/constant-fold-gep.ll @@ -69,6 +69,8 @@ ; PLAIN: @g = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) ; PLAIN: @h = constant i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) ; PLAIN: @i = constant i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) +; PLAIN: @j = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; PLAIN: @k = constant i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64) ; OPT: @a = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) ; OPT: @b = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) ; OPT: @c = constant i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2) @@ -78,6 +80,8 @@ ; OPT: @g = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) ; OPT: @h = constant i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) ; OPT: @i = constant i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) +; OPT: @j = constant i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; OPT: @k = constant i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64) ; TO: @a = constant i64 18480 ; TO: @b = constant i64 8 ; TO: @c = constant i64 16 @@ -87,6 +91,8 @@ ; TO: @g = constant i64 8 ; TO: @h = constant i64 8 ; TO: @i = constant i64 8 +; TO: @j = constant i64 8 +; TO: @k = constant i64 8 @a = constant i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) @b = constant i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}* null, i64 0, i32 1) to i64) @@ -97,6 +103,8 @@ @g = constant i64 ptrtoint ({double, double}* getelementptr ({i1, {double, double}}* null, i64 0, i32 1) to i64) @h = constant i64 ptrtoint (double** getelementptr (double** null, i64 1) to i64) @i = constant i64 ptrtoint (double** getelementptr ({i1, double*}* null, i64 0, i32 1) to i64) +@j = constant i64 ptrtoint (union {double, double}* getelementptr ({i1, union {double, double}}* null, i64 0, i32 1) to i64) +@k = constant i64 ptrtoint (union {double, double}* getelementptr (union {double, double}* null, i64 1) to i64) ; The target-dependent folder should cast GEP indices to integer-sized pointers. @@ -244,15 +252,23 @@ define i1* @hoo1() nounwind { ; PLAIN: ret i64 %t ; PLAIN: } ; PLAIN: define i64 @fg() nounwind { -; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64 ; PLAIN: ret i64 %t ; PLAIN: } ; PLAIN: define i64 @fh() nounwind { -; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) +; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) to i64 ; PLAIN: ret i64 %t ; PLAIN: } ; PLAIN: define i64 @fi() nounwind { -; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) +; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fj() nounwind { +; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64 +; PLAIN: ret i64 %t +; PLAIN: } +; PLAIN: define i64 @fk() nounwind { +; PLAIN: %t = bitcast i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64) to i64 ; PLAIN: ret i64 %t ; PLAIN: } ; OPT: define i64 @fa() nounwind { @@ -282,6 +298,12 @@ define i1* @hoo1() nounwind { ; OPT: define i64 @fi() nounwind { ; OPT: ret i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) ; OPT: } +; OPT: define i64 @fj() nounwind { +; OPT: ret i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; OPT: } +; OPT: define i64 @fk() nounwind { +; OPT: ret i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64) +; OPT: } ; TO: define i64 @fa() nounwind { ; TO: ret i64 18480 ; TO: } @@ -309,6 +331,12 @@ define i1* @hoo1() nounwind { ; TO: define i64 @fi() nounwind { ; TO: ret i64 8 ; TO: } +; TO: define i64 @fj() nounwind { +; TO: ret i64 8 +; TO: } +; TO: define i64 @fk() nounwind { +; TO: ret i64 8 +; TO: } ; SCEV: Classifying expressions for: @fa ; SCEV: %t = bitcast i64 mul (i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64), i64 2310) to i64 ; SCEV: --> (2310 * sizeof(double)) @@ -328,14 +356,20 @@ define i1* @hoo1() nounwind { ; SCEV: %t = bitcast i64 1 to i64 ; SCEV: --> 1 ; SCEV: Classifying expressions for: @fg -; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) +; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64 ; SCEV: --> alignof(double) ; SCEV: Classifying expressions for: @fh -; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) +; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr (i1** null, i32 1) to i64) to i64 ; SCEV: --> sizeof(i1*) ; SCEV: Classifying expressions for: @fi -; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) +; SCEV: %t = bitcast i64 ptrtoint (i1** getelementptr (%2* null, i64 0, i32 1) to i64) to i64 ; SCEV: --> alignof(i1*) +; SCEV: Classifying expressions for: @fj +; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (%0* null, i64 0, i32 1) to i64) to i64 +; SCEV: --> alignof(double) +; SCEV: Classifying expressions for: @fk +; SCEV: %t = bitcast i64 ptrtoint (double* getelementptr (double* null, i32 1) to i64) to i64 +; SCEV: --> sizeof(double) define i64 @fa() nounwind { %t = bitcast i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) to i64 @@ -373,6 +407,14 @@ define i64 @fi() nounwind { %t = bitcast i64 ptrtoint (double** getelementptr ({i1, double*}* null, i64 0, i32 1) to i64) to i64 ret i64 %t } +define i64 @fj() nounwind { + %t = bitcast i64 ptrtoint (union {double, double}* getelementptr ({i1, union {double, double}}* null, i64 0, i32 1) to i64) to i64 + ret i64 %t +} +define i64 @fk() nounwind { + %t = bitcast i64 ptrtoint (union {double, double}* getelementptr (union {double, double}* null, i64 1) to i64) to i64 + ret i64 %t +} ; PLAIN: define i64* @fM() nounwind { ; PLAIN: %t = bitcast i64* getelementptr (i64* null, i32 1) to i64* diff --git a/test/Transforms/ConstantMerge/2006-03-07-DontMergeDiffSections.ll b/test/Transforms/ConstantMerge/2006-03-07-DontMergeDiffSections.ll deleted file mode 100644 index cea18a05ef..0000000000 --- a/test/Transforms/ConstantMerge/2006-03-07-DontMergeDiffSections.ll +++ /dev/null @@ -1,16 +0,0 @@ -; RUN: opt < %s -constmerge -S | grep foo -; RUN: opt < %s -constmerge -S | grep bar - -; Don't merge constants in different sections. - -@G1 = internal constant i32 1, section "foo" ; [#uses=1] -@G2 = internal constant i32 1, section "bar" ; [#uses=1] -@G3 = internal constant i32 1, section "bar" ; [#uses=1] - -define void @test(i32** %P1, i32** %P2, i32** %P3) { - store i32* @G1, i32** %P1 - store i32* @G2, i32** %P2 - store i32* @G3, i32** %P3 - ret void -} - diff --git a/test/Transforms/ConstantMerge/dont-merge.ll b/test/Transforms/ConstantMerge/dont-merge.ll new file mode 100644 index 0000000000..877cf8dc67 --- /dev/null +++ b/test/Transforms/ConstantMerge/dont-merge.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -constmerge -S | FileCheck %s + +; Don't merge constants with specified sections. + +@T1G1 = internal constant i32 1, section "foo" +@T1G2 = internal constant i32 1, section "bar" +@T1G3 = internal constant i32 1, section "bar" + +; CHECK: @T1G1 +; CHECK: @T1G2 +; CHECK: @T1G3 + +define void @test1(i32** %P1, i32** %P2, i32** %P3) { + store i32* @T1G1, i32** %P1 + store i32* @T1G2, i32** %P2 + store i32* @T1G3, i32** %P3 + ret void +} + +@T2a = internal constant i32 224 +@T2b = internal addrspace(30) constant i32 224 + +; CHECK: @T2a +; CHECK: @T2b + +define void @test2(i32** %P1, i32 addrspace(30)** %P2) { + store i32* @T2a, i32** %P1 + store i32 addrspace(30)* @T2b, i32 addrspace(30)** %P2 + ret void +} diff --git a/test/Transforms/DeadStoreElimination/crash.ll b/test/Transforms/DeadStoreElimination/crash.ll index f89f8f5185..6d8ba71b20 100644 --- a/test/Transforms/DeadStoreElimination/crash.ll +++ b/test/Transforms/DeadStoreElimination/crash.ll @@ -41,3 +41,17 @@ bb14: ; preds = %bb4 } declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind + + +; rdar://7635088 +define i32 @test3() { +entry: + ret i32 0 + +dead: + %P2 = getelementptr i32 *%P2, i32 52 + %Q2 = getelementptr i32 *%Q2, i32 52 + store i32 4, i32* %P2 + store i32 4, i32* %Q2 + br label %dead +} \ No newline at end of file diff --git a/test/Transforms/GVN/2008-02-13-NewPHI.ll b/test/Transforms/GVN/2008-02-13-NewPHI.ll index 54998db0ac..80b519d14e 100644 --- a/test/Transforms/GVN/2008-02-13-NewPHI.ll +++ b/test/Transforms/GVN/2008-02-13-NewPHI.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -anders-aa -gvn +; RUN: opt < %s -gvn ; PR2032 define i32 @sscal(i32 %n, double %sa1, float* %sx, i32 %incx) { diff --git a/test/Transforms/GVN/2009-03-05-dbg.ll b/test/Transforms/GVN/2009-03-05-dbg.ll deleted file mode 100644 index cad3312995..0000000000 --- a/test/Transforms/GVN/2009-03-05-dbg.ll +++ /dev/null @@ -1,66 +0,0 @@ -; RUN: opt < %s -gvn -disable-output - %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8*, i1, i1, i8*, i32 } -@llvm.dbg.compile_unit298 = external constant %llvm.dbg.compile_unit.type ; <%llvm.dbg.compile_unit.type*> [#uses=1] - -declare void @llvm.dbg.stoppoint(i32, i32, { }*) nounwind - -define i8* @__deregister_frame_info_bases(i8* %begin) { -entry: - br i1 false, label %bb17, label %bb - -bb: ; preds = %entry - br i1 false, label %bb17, label %bb6.preheader - -bb6.preheader: ; preds = %bb - br label %bb6 - -bb3: ; preds = %bb6 - br i1 false, label %bb4, label %bb6 - -bb4: ; preds = %bb3 - br label %out - -bb6: ; preds = %bb3, %bb6.preheader - br i1 false, label %bb14.loopexit, label %bb3 - -bb8: ; preds = %bb14 - br i1 false, label %bb9, label %bb11 - -bb9: ; preds = %bb8 - br i1 false, label %bb10, label %bb13 - -bb10: ; preds = %bb9 - br label %out - -bb11: ; preds = %bb8 - br i1 false, label %bb12, label %bb13 - -bb12: ; preds = %bb11 - br label %out - -bb13: ; preds = %bb11, %bb9 - br label %bb14 - -bb14.loopexit: ; preds = %bb6 - br label %bb14 - -bb14: ; preds = %bb14.loopexit, %bb13 - br i1 false, label %bb15.loopexit, label %bb8 - -out: ; preds = %bb12, %bb10, %bb4 - tail call void @llvm.dbg.stoppoint(i32 217, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit298 to { }*)) - br i1 false, label %bb15, label %bb16 - -bb15.loopexit: ; preds = %bb14 - br label %bb15 - -bb15: ; preds = %bb15.loopexit, %out - tail call void @llvm.dbg.stoppoint(i32 217, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit298 to { }*)) - unreachable - -bb16: ; preds = %out - ret i8* null - -bb17: ; preds = %bb, %entry - ret i8* null -} diff --git a/test/Transforms/GVN/crash.ll b/test/Transforms/GVN/crash.ll index 9167b6ec68..4a3aa1c55a 100644 --- a/test/Transforms/GVN/crash.ll +++ b/test/Transforms/GVN/crash.ll @@ -5,7 +5,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin10.0" -define i32* @peel_to_type(i8* %name, i32 %namelen, i32* %o, i32 %expected_type) nounwind ssp { +define i32* @test1(i8* %name, i32 %namelen, i32* %o, i32 %expected_type) nounwind ssp { entry: br i1 undef, label %if.end13, label %while.body.preheader @@ -69,7 +69,7 @@ declare i32* @parse_object(i8*) @attribute_tables = external global [4 x %struct.attribute_spec*] ; <[4 x %struct.attribute_spec*]*> [#uses=2] -define void @decl_attributes() nounwind { +define void @test2() nounwind { entry: br label %bb69.i @@ -99,7 +99,7 @@ bb66.i: ; Unreachable @g = external global i64, align 8 -define i32* @foo() { +define i32* @test3() { do.end17.i: %tmp18.i = load i7** undef %tmp1 = bitcast i7* %tmp18.i to i8* @@ -135,3 +135,19 @@ do.body57.i: declare i32 @foo2() + + +define i32 @test4() { +entry: + ret i32 0 + +dead: + %P2 = getelementptr i32 *%P2, i32 52 + %Q2 = getelementptr i32 *%Q2, i32 52 + store i32 4, i32* %P2 + %A = load i32* %Q2 + br i1 true, label %dead, label %dead2 + +dead2: + ret i32 %A +} diff --git a/test/Transforms/GVN/pre-load.ll b/test/Transforms/GVN/pre-load.ll index 7047d4eba4..d40a467bf6 100644 --- a/test/Transforms/GVN/pre-load.ll +++ b/test/Transforms/GVN/pre-load.ll @@ -362,3 +362,30 @@ bb: return: ret void } + +; Test critical edge splitting. +define i32 @test11(i32* %p, i1 %C, i32 %N) { +; CHECK: @test11 +block1: + br i1 %C, label %block2, label %block3 + +block2: + %cond = icmp sgt i32 %N, 1 + br i1 %cond, label %block4, label %block5 +; CHECK: load i32* %p +; CHECK-NEXT: br label %block4 + +block3: + store i32 0, i32* %p + br label %block4 + +block4: + %PRE = load i32* %p + br label %block5 + +block5: + %ret = phi i32 [ 0, %block2 ], [ %PRE, %block4 ] + ret i32 %ret +; CHECK: block4: +; CHECK-NEXT: phi i32 +} diff --git a/test/Transforms/GlobalOpt/2009-03-03-dbg.ll b/test/Transforms/GlobalOpt/2009-03-03-dbg.ll deleted file mode 100644 index 070f89f492..0000000000 --- a/test/Transforms/GlobalOpt/2009-03-03-dbg.ll +++ /dev/null @@ -1,54 +0,0 @@ -; RUN: opt < %s -globalopt -S | not grep global_variable42 -; XFAIL: * - - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8*, i1, i1, i8*, i32 } - %llvm.dbg.composite.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }*, { }*, i32 } - %llvm.dbg.derivedtype.type = type { i32, { }*, i8*, { }*, i32, i64, i64, i64, i32, { }* } - %llvm.dbg.global_variable.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1, { }* } - %llvm.dbg.subprogram.type = type { i32, { }*, { }*, i8*, i8*, i8*, { }*, i32, { }*, i1, i1 } - %llvm.dbg.subrange.type = type { i32, i64, i64 } - %llvm.dbg.variable.type = type { i32, { }*, i8*, { }*, i32, { }* } -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str = internal constant [4 x i8] c"a.c\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@.str1 = internal constant [5 x i8] c"/tmp\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@.str2 = internal constant [57 x i8] c"4.2.1 (Based on Apple Inc. build 5636) (LLVM build 2099)\00", section "llvm.metadata" ; <[57 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), i32 1, i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([5 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([57 x i8]* @.str2, i32 0, i32 0), i1 true, i1 false, i8* null, i32 0 }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@.str3 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type { i32 458788, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([4 x i8]* @.str3, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@llvm.dbg.array = internal constant [1 x { }*] [ { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*) ], section "llvm.metadata" ; <[1 x { }*]*> [#uses=1] -@llvm.dbg.composite = internal constant %llvm.dbg.composite.type { i32 458773, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 0, i64 0, i64 0, i64 0, i32 0, { }* null, { }* bitcast ([1 x { }*]* @llvm.dbg.array to { }*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str4 = internal constant [5 x i8] c"main\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.subprogram = internal constant %llvm.dbg.subprogram.type { i32 458798, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to { }*), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([5 x i8]* @.str4, i32 0, i32 0), i8* getelementptr ([5 x i8]* @.str4, i32 0, i32 0), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 3, { }* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite to { }*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@llvm.dbg.derivedtype = internal constant %llvm.dbg.derivedtype.type { i32 458767, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 0, i64 32, i64 32, i64 0, i32 0, { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*) }, section "llvm.metadata" ; <%llvm.dbg.derivedtype.type*> [#uses=1] -@.str5 = internal constant [6 x i8] c"i_ptr\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@llvm.dbg.variable = internal constant %llvm.dbg.variable.type { i32 459008, { }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*), i8* getelementptr ([6 x i8]* @.str5, i32 0, i32 0), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 5, { }* bitcast (%llvm.dbg.derivedtype.type* @llvm.dbg.derivedtype to { }*) }, section "llvm.metadata" ; <%llvm.dbg.variable.type*> [#uses=0] -@sillyArray.1433 = internal global [8 x i32] [ i32 2, i32 3, i32 5, i32 7, i32 11, i32 13, i32 17, i32 19 ] ; <[8 x i32]*> [#uses=1] -@llvm.dbg.subrange = internal constant %llvm.dbg.subrange.type { i32 458785, i64 0, i64 7 }, section "llvm.metadata" ; <%llvm.dbg.subrange.type*> [#uses=1] -@llvm.dbg.array6 = internal constant [1 x { }*] [ { }* bitcast (%llvm.dbg.subrange.type* @llvm.dbg.subrange to { }*) ], section "llvm.metadata" ; <[1 x { }*]*> [#uses=1] -@llvm.dbg.composite7 = internal constant %llvm.dbg.composite.type { i32 458753, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 0, i64 256, i64 32, i64 0, i32 0, { }* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to { }*), { }* bitcast ([1 x { }*]* @llvm.dbg.array6 to { }*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 52 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str8 = internal constant [16 x i8] c"sillyArray.1433\00", section "llvm.metadata" ; <[16 x i8]*> [#uses=1] -@.str9 = internal constant [11 x i8] c"sillyArray\00", section "llvm.metadata" ; <[11 x i8]*> [#uses=1] -@llvm.dbg.global_variable42 = internal constant %llvm.dbg.global_variable.type { i32 458804, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.global_variables to { }*), { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i8* getelementptr ([16 x i8]* @.str8, i32 0, i32 0), i8* getelementptr ([11 x i8]* @.str9, i32 0, i32 0), i8* null, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*), i32 4, { }* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite7 to { }*), i1 true, i1 true, { }* bitcast ([8 x i32]* @sillyArray.1433 to { }*) }, section "llvm.metadata" ; <%llvm.dbg.global_variable.type*> [#uses=0] - -define i32 @main() nounwind { -entry: - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - call void @llvm.dbg.func.start({ }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*)) - call void @llvm.dbg.stoppoint(i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - call void @llvm.dbg.stoppoint(i32 6, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - call void @llvm.dbg.stoppoint(i32 6, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - call void @llvm.dbg.region.end({ }* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to { }*)) - ret i32 0 -} - -declare void @llvm.dbg.func.start({ }*) nounwind - -declare void @llvm.dbg.declare({ }*, { }*) nounwind - -declare void @llvm.dbg.stoppoint(i32, i32, { }*) nounwind - -declare void @llvm.dbg.region.end({ }*) nounwind diff --git a/test/Transforms/GlobalOpt/2009-03-05-dbg.ll b/test/Transforms/GlobalOpt/2009-03-05-dbg.ll index a5f9ed39ca..3154856574 100644 --- a/test/Transforms/GlobalOpt/2009-03-05-dbg.ll +++ b/test/Transforms/GlobalOpt/2009-03-05-dbg.ll @@ -1,67 +1,76 @@ ; RUN: opt < %s -globalopt -stats -disable-output |& grep "1 globalopt - Number of global vars shrunk to booleans" -; XFAIL: * - type { } ; type %0 - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.basictype.type = type { i32, %0*, i8*, %0*, i32, i64, i64, i64, i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, %0*, i32, i8*, i8*, i8*, i1, i1, i8*, i32 } - %llvm.dbg.composite.type = type { i32, %0*, i8*, %0*, i32, i64, i64, i64, i32, %0*, %0*, i32 } - %llvm.dbg.global_variable.type = type { i32, %0*, %0*, i8*, i8*, i8*, %0*, i32, %0*, i1, i1, %0* } - %llvm.dbg.subprogram.type = type { i32, %0*, %0*, i8*, i8*, i8*, %0*, i32, %0*, i1, i1 } - %llvm.dbg.variable.type = type { i32, %0*, i8*, %0*, i32, %0* } -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str = internal constant [5 x i8] c"gs.c\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@.str1 = internal constant [6 x i8] c"/tmp/\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@.str2 = internal constant [55 x i8] c"4.2.1 (Based on Apple Inc. build 5641) (LLVM build 00)\00", section "llvm.metadata" ; <[55 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to %0*), i32 1, i8* getelementptr ([5 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([55 x i8]* @.str2, i32 0, i32 0), i1 true, i1 false, i8* null, i32 0 }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] -@.str3 = internal constant [4 x i8] c"int\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.basictype = internal constant %llvm.dbg.basictype.type { i32 458788, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([4 x i8]* @.str3, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 32, i64 32, i64 0, i32 0, i32 5 }, section "llvm.metadata" ; <%llvm.dbg.basictype.type*> [#uses=1] -@llvm.dbg.array = internal constant [2 x %0*] [%0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to %0*), %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to %0*)], section "llvm.metadata" ; <[2 x %0*]*> [#uses=1] -@llvm.dbg.composite = internal constant %llvm.dbg.composite.type { i32 458773, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 0, i64 0, i64 0, i64 0, i32 0, %0* null, %0* bitcast ([2 x %0*]* @llvm.dbg.array to %0*), i32 0 }, section "llvm.metadata" ; <%llvm.dbg.composite.type*> [#uses=1] -@llvm.dbg.subprograms = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 46 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str4 = internal constant [4 x i8] c"foo\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@llvm.dbg.subprogram = internal constant %llvm.dbg.subprogram.type { i32 458798, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.subprograms to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([4 x i8]* @.str4, i32 0, i32 0), i8* getelementptr ([4 x i8]* @.str4, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 4, %0* bitcast (%llvm.dbg.composite.type* @llvm.dbg.composite to %0*), i1 false, i1 true }, section "llvm.metadata" ; <%llvm.dbg.subprogram.type*> [#uses=1] -@.str5 = internal constant [2 x i8] c"i\00", section "llvm.metadata" ; <[2 x i8]*> [#uses=1] -@llvm.dbg.variable = internal constant %llvm.dbg.variable.type { i32 459009, %0* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to %0*), i8* getelementptr ([2 x i8]* @.str5, i32 0, i32 0), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 4, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to %0*) }, section "llvm.metadata" ; <%llvm.dbg.variable.type*> [#uses=1] -@Stop = internal global i32 0 ; [#uses=4] -@llvm.dbg.global_variables = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 52 }, section "llvm.metadata" ; <%llvm.dbg.anchor.type*> [#uses=1] -@.str6 = internal constant [5 x i8] c"Stop\00", section "llvm.metadata" ; <[5 x i8]*> [#uses=1] -@llvm.dbg.global_variable = internal constant %llvm.dbg.global_variable.type { i32 458804, %0* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.global_variables to %0*), %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i8* getelementptr ([5 x i8]* @.str6, i32 0, i32 0), i8* getelementptr ([5 x i8]* @.str6, i32 0, i32 0), i8* null, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*), i32 2, %0* bitcast (%llvm.dbg.basictype.type* @llvm.dbg.basictype to %0*), i1 true, i1 true, %0* bitcast (i32* @Stop to %0*) }, section "llvm.metadata" ; <%llvm.dbg.global_variable.type*> [#uses=0] +@Stop = internal global i32 0 ; [#uses=3] -define i32 @foo(i32 %i) nounwind { +define i32 @foo(i32 %i) nounwind ssp { entry: - %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - call void @llvm.dbg.func.start(%0* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to %0*)) - call void @llvm.dbg.stoppoint(i32 5, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %0 = load i32* @Stop, align 4 ; [#uses=1] - %1 = icmp eq i32 %0, 1 ; [#uses=1] - br i1 %1, label %bb, label %bb1 + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + call void @llvm.dbg.value(metadata !{i32 %i}, i64 0, metadata !3) + %0 = icmp eq i32 %i, 1, !dbg !7 ; [#uses=1] + br i1 %0, label %bb, label %bb1, !dbg !7 -bb: ; preds = %entry - call void @llvm.dbg.stoppoint(i32 6, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - store i32 0, i32* @Stop, align 4 - call void @llvm.dbg.stoppoint(i32 7, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - %2 = mul i32 %i, 42 ; [#uses=1] - br label %bb2 +bb: ; preds = %entry + store i32 0, i32* @Stop, align 4, !dbg !9 + %1 = mul nsw i32 %i, 42, !dbg !10 ; [#uses=1] + call void @llvm.dbg.value(metadata !{i32 %1}, i64 0, metadata !3), !dbg !10 + br label %bb2, !dbg !10 -bb1: ; preds = %entry - call void @llvm.dbg.stoppoint(i32 9, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - store i32 1, i32* @Stop, align 4 - call void @llvm.dbg.stoppoint(i32 10, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - br label %bb2 +bb1: ; preds = %entry + store i32 1, i32* @Stop, align 4, !dbg !11 + br label %bb2, !dbg !11 -bb2: ; preds = %bb1, %bb - %.0 = phi i32 [ %i, %bb1 ], [ %2, %bb ] ; [#uses=1] - call void @llvm.dbg.stoppoint(i32 10, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - call void @llvm.dbg.stoppoint(i32 10, i32 0, %0* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to %0*)) - call void @llvm.dbg.region.end(%0* bitcast (%llvm.dbg.subprogram.type* @llvm.dbg.subprogram to %0*)) - ret i32 %.0 +bb2: ; preds = %bb1, %bb + %i_addr.0 = phi i32 [ %1, %bb ], [ %i, %bb1 ] ; [#uses=1] + br label %return, !dbg !12 + +return: ; preds = %bb2 + ret i32 %i_addr.0, !dbg !12 } -declare void @llvm.dbg.func.start(%0*) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone + +define i32 @bar() nounwind ssp { +entry: + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + %0 = load i32* @Stop, align 4, !dbg !13 ; [#uses=1] + %1 = icmp eq i32 %0, 1, !dbg !13 ; [#uses=1] + br i1 %1, label %bb, label %bb1, !dbg !13 + +bb: ; preds = %entry + br label %bb2, !dbg !18 + +bb1: ; preds = %entry + br label %bb2, !dbg !19 + +bb2: ; preds = %bb1, %bb + %.0 = phi i32 [ 0, %bb ], [ 1, %bb1 ] ; [#uses=1] + br label %return, !dbg !19 + +return: ; preds = %bb2 + ret i32 %.0, !dbg !19 +} -declare void @llvm.dbg.declare(%0*, %0*) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone -declare void @llvm.dbg.stoppoint(i32, i32, %0*) nounwind readnone +!llvm.dbg.gv = !{!0} -declare void @llvm.dbg.region.end(%0*) nounwind readnone +!0 = metadata !{i32 458804, i32 0, metadata !1, metadata !"Stop", metadata !"Stop", metadata !"", metadata !1, i32 2, metadata !2, i1 true, i1 true, i32* @Stop} ; [ DW_TAG_variable ] +!1 = metadata !{i32 458769, i32 0, i32 1, metadata !"g.c", metadata !"/tmp", metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build)", i1 true, i1 false, metadata !"", i32 0} ; [ DW_TAG_compile_unit ] +!2 = metadata !{i32 458788, metadata !1, metadata !"int", metadata !1, i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] +!3 = metadata !{i32 459009, metadata !4, metadata !"i", metadata !1, i32 4, metadata !2} ; [ DW_TAG_arg_variable ] +!4 = metadata !{i32 458798, i32 0, metadata !1, metadata !"foo", metadata !"foo", metadata !"foo", metadata !1, i32 4, metadata !5, i1 false, i1 true, i32 0, i32 0, null, i1 false} ; [ DW_TAG_subprogram ] +!5 = metadata !{i32 458773, metadata !1, metadata !"", metadata !1, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !6, i32 0, null} ; [ DW_TAG_subroutine_type ] +!6 = metadata !{metadata !2, metadata !2} +!7 = metadata !{i32 5, i32 0, metadata !8, null} +!8 = metadata !{i32 458763, metadata !4, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!9 = metadata !{i32 6, i32 0, metadata !8, null} +!10 = metadata !{i32 7, i32 0, metadata !8, null} +!11 = metadata !{i32 9, i32 0, metadata !8, null} +!12 = metadata !{i32 11, i32 0, metadata !8, null} +!13 = metadata !{i32 14, i32 0, metadata !14, null} +!14 = metadata !{i32 458763, metadata !15, i32 0, i32 0} ; [ DW_TAG_lexical_block ] +!15 = metadata !{i32 458798, i32 0, metadata !1, metadata !"bar", metadata !"bar", metadata !"bar", metadata !1, i32 13, metadata !16, i1 false, i1 true, i32 0, i32 0, null, i1 false} ; [ DW_TAG_subprogram ] +!16 = metadata !{i32 458773, metadata !1, metadata !"", metadata !1, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !17, i32 0, null} ; [ DW_TAG_subroutine_type ] +!17 = metadata !{metadata !2} +!18 = metadata !{i32 15, i32 0, metadata !14, null} +!19 = metadata !{i32 16, i32 0, metadata !14, null} diff --git a/test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll b/test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll new file mode 100644 index 0000000000..27352fa290 --- /dev/null +++ b/test/Transforms/GlobalOpt/2010-02-25-MallocPromote.ll @@ -0,0 +1,18 @@ +; PR6422 +; RUN: opt -globalopt -S %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +@fixLRBT = internal global i32* null ; [#uses=2] + +declare noalias i8* @malloc(i32) + +define i32 @parser() nounwind { +bb918: + %malloccall.i10 = call i8* @malloc(i32 16) nounwind ; [#uses=1] + %0 = bitcast i8* %malloccall.i10 to i32* ; [#uses=1] + store i32* %0, i32** @fixLRBT, align 8 + %1 = load i32** @fixLRBT, align 8 ; [#uses=0] + %A = load i32* %1 + ret i32 %A +} diff --git a/test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll b/test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll new file mode 100644 index 0000000000..6f1996a867 --- /dev/null +++ b/test/Transforms/GlobalOpt/2010-02-26-MallocSROA.ll @@ -0,0 +1,27 @@ +; RUN: opt -globalopt -S %s +; PR6435 +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.xyz = type { double, i32 } + +@Y = internal global %struct.xyz* null ; <%struct.xyz**> [#uses=2] +@numf2s = external global i32 ; [#uses=1] + +define fastcc void @init_net() nounwind { +entry: + %0 = load i32* @numf2s, align 4 ; [#uses=1] + %mallocsize2 = shl i32 %0, 4 ; [#uses=1] + %malloccall3 = tail call i8* @malloc(i32 %mallocsize2) nounwind ; [#uses=1] + %1 = bitcast i8* %malloccall3 to %struct.xyz* ; <%struct.xyz*> [#uses=1] + store %struct.xyz* %1, %struct.xyz** @Y, align 8 + ret void +} + +define fastcc void @load_train(i8* %trainfile, i32 %mode, i32 %objects) nounwind { +entry: + %0 = load %struct.xyz** @Y, align 8 ; <%struct.xyz*> [#uses=0] + ret void +} + +declare noalias i8* @malloc(i32) diff --git a/test/Transforms/GlobalOpt/ctor-list-opt-dbg.ll b/test/Transforms/GlobalOpt/ctor-list-opt-dbg.ll deleted file mode 100644 index f794e9f96b..0000000000 --- a/test/Transforms/GlobalOpt/ctor-list-opt-dbg.ll +++ /dev/null @@ -1,98 +0,0 @@ -; RUN: opt < %s -globalopt -S | not grep CTOR -@llvm.global_ctors = appending global [10 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @CTOR1 }, { i32, void ()* } { i32 65535, void ()* @CTOR1 }, { i32, void ()* } { i32 65535, void ()* @CTOR2 }, { i32, void ()* } { i32 65535, void ()* @CTOR3 }, { i32, void ()* } { i32 65535, void ()* @CTOR4 }, { i32, void ()* } { i32 65535, void ()* @CTOR5 }, { i32, void ()* } { i32 65535, void ()* @CTOR6 }, { i32, void ()* } { i32 65535, void ()* @CTOR7 }, { i32, void ()* } { i32 65535, void ()* @CTOR8 }, { i32, void ()* } { i32 2147483647, void ()* null } ] ; <[10 x { i32, void ()* }]*> [#uses=0] -@G = global i32 0 ; [#uses=1] -@G2 = global i32 0 ; [#uses=1] -@G3 = global i32 -123 ; [#uses=2] -@X = global { i32, [2 x i32] } { i32 0, [2 x i32] [ i32 17, i32 21 ] } ; <{ i32, [2 x i32] }*> [#uses=2] -@Y = global i32 -1 ; [#uses=2] -@Z = global i32 123 ; [#uses=1] -@D = global double 0.000000e+00 ; [#uses=1] -@CTORGV = internal global i1 false ; [#uses=2] - - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8*, i1, i1, i8* } - -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" - -@.str = internal constant [4 x i8] c"a.c\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@.str1 = internal constant [6 x i8] c"/tmp/\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@.str2 = internal constant [55 x i8] c"4.2.1 (Based on Apple Inc. build 5636) (LLVM build 00)\00", section "llvm.metadata" ; <[55 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), i32 1, i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([55 x i8]* @.str2, i32 0, i32 0), i1 true, i1 false, i8* null }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] - -declare void @llvm.dbg.stoppoint(i32, i32, { }*) nounwind - -define internal void @CTOR1() { - ret void -} - -define internal void @CTOR2() { - %A = add i32 1, 23 ; [#uses=1] - call void @llvm.dbg.stoppoint(i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - store i32 %A, i32* @G - store i1 true, i1* @CTORGV - ret void -} - -define internal void @CTOR3() { - %X = or i1 true, false ; [#uses=1] - br label %Cont - -Cont: ; preds = %0 - br i1 %X, label %S, label %T - -S: ; preds = %Cont - store i32 24, i32* @G2 - ret void - -T: ; preds = %Cont - ret void -} - -define internal void @CTOR4() { - %X = load i32* @G3 ; [#uses=1] - %Y = add i32 %X, 123 ; [#uses=1] - store i32 %Y, i32* @G3 - ret void -} - -define internal void @CTOR5() { - %X.2p = getelementptr inbounds { i32, [2 x i32] }* @X, i32 0, i32 1, i32 0 ; [#uses=2] - %X.2 = load i32* %X.2p ; [#uses=1] - %X.1p = getelementptr inbounds { i32, [2 x i32] }* @X, i32 0, i32 0 ; [#uses=1] - store i32 %X.2, i32* %X.1p - store i32 42, i32* %X.2p - ret void -} - -define internal void @CTOR6() { - %A = alloca i32 ; [#uses=2] - %y = load i32* @Y ; [#uses=1] - store i32 %y, i32* %A - %Av = load i32* %A ; [#uses=1] - %Av1 = add i32 %Av, 1 ; [#uses=1] - store i32 %Av1, i32* @Y - ret void -} - -define internal void @CTOR7() { - call void @setto( i32* @Z, i32 0 ) - ret void -} - -define void @setto(i32* %P, i32 %V) { - store i32 %V, i32* %P - ret void -} - -declare double @cos(double) - -define internal void @CTOR8() { - %X = call double @cos( double 1.000000e+00 ) ; [#uses=1] - store double %X, double* @D - ret void -} - -define i1 @accessor() { - %V = load i1* @CTORGV ; [#uses=1] - ret i1 %V -} diff --git a/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll b/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll index 36d50065d3..ecd5086f73 100644 --- a/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll +++ b/test/Transforms/IndVarSimplify/2003-09-12-MultiplePred.ll @@ -7,7 +7,7 @@ define i32 @test() { LoopHead: ; preds = %LoopHead, %0, %0 %A = phi i32 [ 7, %0 ], [ 7, %0 ], [ %B, %LoopHead ] ; [#uses=1] %B = add i32 %A, 1 ; [#uses=2] - br i1 false, label %LoopHead, label %Out + br i1 true, label %LoopHead, label %Out Out: ; preds = %LoopHead ret i32 %B diff --git a/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll b/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll index 70ea11ebf0..7536331475 100644 --- a/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll +++ b/test/Transforms/IndVarSimplify/2003-12-10-RemoveInstrCrash.ll @@ -10,7 +10,7 @@ no_exit: ; preds = %no_exit, %entry %k.0.pn = phi i32 [ %inc.4, %no_exit ], [ 1, %entry ] ; [#uses=1] %inc.3 = add i32 %j.0.pn, 1 ; [#uses=1] %inc.4 = add i32 %k.0.pn, 1 ; [#uses=1] - br i1 false, label %no_exit, label %loopexit + br i1 undef, label %no_exit, label %loopexit loopexit: ; preds = %no_exit, %entry ret void diff --git a/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll b/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll index 5aa2d90a42..662828c749 100644 --- a/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll +++ b/test/Transforms/IndVarSimplify/2003-12-15-Crash.ll @@ -8,7 +8,7 @@ cond_continue.3: ; preds = %entry loopexit.14: ; preds = %entry %tmp.738 = sub i32 0, 0 ; [#uses=1] - br i1 false, label %no_exit.15.preheader, label %loopexit.15 + br i1 undef, label %no_exit.15.preheader, label %loopexit.15 no_exit.15.preheader: ; preds = %loopexit.14 br label %no_exit.15 @@ -16,7 +16,7 @@ no_exit.15.preheader: ; preds = %loopexit.14 no_exit.15: ; preds = %no_exit.15, %no_exit.15.preheader %highC.0 = phi i32 [ %tmp.738, %no_exit.15.preheader ], [ %dec.0, %no_exit.15 ] ; [#uses=1] %dec.0 = add i32 %highC.0, -1 ; [#uses=1] - br i1 false, label %no_exit.15, label %loopexit.15 + br i1 undef, label %no_exit.15, label %loopexit.15 loopexit.15: ; preds = %no_exit.15, %loopexit.14 ret void diff --git a/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll b/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll index f9a3fe6233..7202c7ae9d 100644 --- a/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll +++ b/test/Transforms/IndVarSimplify/2005-11-18-Crash.ll @@ -9,7 +9,7 @@ entry: no_exit.0: ; preds = %no_exit.0, %entry %p.0.0 = phi i32* [ getelementptr ([29 x [29 x [2 x i32]]]* @fixtab, i32 0, i32 0, i32 0, i32 0), %entry ], [ %inc.0, %no_exit.0 ] ; [#uses=1] %inc.0 = getelementptr i32* %p.0.0, i32 1 ; [#uses=1] - br i1 false, label %no_exit.0, label %no_exit.1 + br i1 undef, label %no_exit.0, label %no_exit.1 no_exit.1: ; preds = %no_exit.0 ret void diff --git a/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll b/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll index 79ac1f072d..80c9ebf2f0 100644 --- a/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll +++ b/test/Transforms/IndVarSimplify/2006-12-10-BitCast.ll @@ -20,7 +20,7 @@ cond_next182.i: ; preds = %cond_next182.i, %cond_true52 %tmp194.i53 = bitcast i32 %decay.i.0 to float ; [#uses=1] %tmp195.i = fsub float %tmp194.i53, 8.000000e+00 ; [#uses=1] %tmp195.i.upgrd.1 = bitcast float %tmp195.i to i32 ; [#uses=1] - br i1 false, label %cond_next182.i, label %bb418.i.preheader + br i1 undef, label %cond_next182.i, label %bb418.i.preheader bb418.i.preheader: ; preds = %cond_next182.i ret void diff --git a/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll b/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll index 9ad86913e2..d73eee812b 100644 --- a/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll +++ b/test/Transforms/IndVarSimplify/2009-05-24-useafterfree.ll @@ -12,7 +12,7 @@ bb.nph1.preheader: ; preds = %4 br label %bb.nph1 bb.nph1: ; preds = %.outer, %bb.nph1.preheader - br i1 false, label %bb.nph3.preheader, label %.outer + br i1 undef, label %bb.nph3.preheader, label %.outer bb.nph3.preheader: ; preds = %bb.nph1 br label %bb.nph3 @@ -31,7 +31,7 @@ bb.nph3: ; preds = %bb.nph3, %bb.nph3.preheader br label %.outer .outer: ; preds = %.outer.loopexit, %bb.nph1 - br i1 false, label %bb.nph1, label %.outer._crit_edge.loopexit + br i1 undef, label %bb.nph1, label %.outer._crit_edge.loopexit .outer._crit_edge.loopexit: ; preds = %.outer br label %.outer._crit_edge diff --git a/test/Transforms/IndVarSimplify/addrec-gep.ll b/test/Transforms/IndVarSimplify/addrec-gep.ll index 9e4273491e..345f666c3b 100644 --- a/test/Transforms/IndVarSimplify/addrec-gep.ll +++ b/test/Transforms/IndVarSimplify/addrec-gep.ll @@ -25,7 +25,7 @@ bb1: ; preds = %bb2, %bb.nph %j.01 = phi i64 [ %tmp9, %bb2 ], [ 0, %bb.nph ] ; [#uses=3] %tmp3 = add i64 %j.01, %tmp1 ; [#uses=1] %tmp4 = add i64 %j.01, %tmp2 ; [#uses=1] - %z0 = add i64 %tmp4, 5203 + %z0 = add i64 %tmp3, 5203 %tmp5 = getelementptr double* %p, i64 %z0 ; [#uses=1] %tmp6 = load double* %tmp5, align 8 ; [#uses=1] %tmp7 = fdiv double %tmp6, 2.100000e+00 ; [#uses=1] diff --git a/test/Transforms/IndVarSimplify/avoid-i0.ll b/test/Transforms/IndVarSimplify/avoid-i0.ll index d110a8a7ba..59661fa2e8 100644 --- a/test/Transforms/IndVarSimplify/avoid-i0.ll +++ b/test/Transforms/IndVarSimplify/avoid-i0.ll @@ -10,13 +10,13 @@ entry: bb: ; preds = %bb6, %entry %p_71_addr.0 = phi i8 [ %p_71, %entry ], [ %0, %bb6 ] ; [#uses=0] - br i1 false, label %bb4, label %bb1 + br i1 undef, label %bb4, label %bb1 bb1: ; preds = %bb ret i32 0 bb4: ; preds = %bb4, %bb - br i1 false, label %bb6, label %bb4 + br i1 undef, label %bb6, label %bb4 bb6: ; preds = %bb4 %0 = and i8 0, 0 ; [#uses=1] diff --git a/test/Transforms/IndVarSimplify/max-pointer.ll b/test/Transforms/IndVarSimplify/max-pointer.ll index 71bc720d5e..f18f968f59 100644 --- a/test/Transforms/IndVarSimplify/max-pointer.ll +++ b/test/Transforms/IndVarSimplify/max-pointer.ll @@ -16,7 +16,7 @@ bb2: ; preds = %bb2, %entry %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; [#uses=1] %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; [#uses=2] %2 = icmp ult i8* %1, %inLastBytePtr ; [#uses=0] - br i1 false, label %bb2, label %return + br i1 undef, label %bb2, label %return return: ; preds = %bb2 ret void @@ -32,7 +32,7 @@ bb2: ; preds = %bb2, %entry %str2Ptr_addr.1 = phi i8* [ %str2Ptr_addr.0, %entry ], [ %1, %bb2 ] ; [#uses=1] %1 = getelementptr i8* %str2Ptr_addr.1, i64 1 ; [#uses=2] %2 = icmp slt i8* %1, %inLastBytePtr ; [#uses=0] - br i1 false, label %bb2, label %return + br i1 undef, label %bb2, label %return return: ; preds = %bb2 ret void diff --git a/test/Transforms/InstCombine/2006-12-08-ICmp-Combining.ll b/test/Transforms/InstCombine/2006-12-08-ICmp-Combining.ll deleted file mode 100644 index 80ee3e2a29..0000000000 --- a/test/Transforms/InstCombine/2006-12-08-ICmp-Combining.ll +++ /dev/null @@ -1,18 +0,0 @@ -; RUN: opt < %s -instcombine -S | \ -; RUN: grep {%bothcond =} - -define i1 @Doit_bb(i32 %i.0) { -bb: - %tmp = icmp sgt i32 %i.0, 0 ; [#uses=1] - %tmp.not = xor i1 %tmp, true ; [#uses=1] - %tmp2 = icmp sgt i32 %i.0, 8 ; [#uses=1] - %bothcond = or i1 %tmp.not, %tmp2 ; [#uses=1] - br i1 %bothcond, label %exitTrue, label %exitFalse - -exitTrue: ; preds = %bb - ret i1 true - -exitFalse: ; preds = %bb - ret i1 false -} - diff --git a/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll b/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll index 79a2f1fd8e..142134791e 100644 --- a/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll +++ b/test/Transforms/InstCombine/2009-01-19-fmod-constant-float-specials.ll @@ -1,5 +1,4 @@ -; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF8000000000000 | count 7 -; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF00000FFFFFFFF | count 5 +; RUN: opt < %s -simplifycfg -instcombine -S | grep 0x7FF8000000000000 | count 12 ; RUN: opt < %s -simplifycfg -instcombine -S | grep {0\\.0} | count 3 ; RUN: opt < %s -simplifycfg -instcombine -S | grep {3\\.5} | count 1 ; diff --git a/test/Transforms/InstCombine/2010-03-03-ExtElim.ll b/test/Transforms/InstCombine/2010-03-03-ExtElim.ll new file mode 100644 index 0000000000..2df12d670a --- /dev/null +++ b/test/Transforms/InstCombine/2010-03-03-ExtElim.ll @@ -0,0 +1,18 @@ +; RUN: opt -instcombine -S %s | FileCheck %s +; PR6486 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i386-unknown-linux-gnu" + +@g_92 = common global [2 x i32*] zeroinitializer, align 4 ; <[2 x i32*]*> [#uses=1] +@g_177 = constant i32** bitcast (i8* getelementptr (i8* bitcast ([2 x i32*]* @g_92 to i8*), i64 4) to i32**), align 4 ; [#uses=1] + +define i1 @test() nounwind { +; CHECK: @test + %tmp = load i32*** @g_177 ; [#uses=1] + %cmp = icmp ne i32** null, %tmp ; [#uses=1] + %conv = zext i1 %cmp to i32 ; [#uses=1] + %cmp1 = icmp sle i32 0, %conv ; [#uses=1] + ret i1 %cmp1 +; CHECK: ret i1 true +} diff --git a/test/Transforms/InstCombine/JavaCompare.ll b/test/Transforms/InstCombine/JavaCompare.ll index 7d0edb84d1..46b6c19f9a 100644 --- a/test/Transforms/InstCombine/JavaCompare.ll +++ b/test/Transforms/InstCombine/JavaCompare.ll @@ -1,7 +1,7 @@ ; This is the sequence of stuff that the Java front-end expands for a single ; <= comparison. Check to make sure we turn it into a <= (only) -; RUN: opt < %s -instcombine -S | grep {%c3 = icmp sle i32 %A, %B} +; RUN: opt < %s -instcombine -S | grep {icmp sle i32 %A, %B} define i1 @le(i32 %A, i32 %B) { %c1 = icmp sgt i32 %A, %B ; [#uses=1] diff --git a/test/Transforms/InstCombine/and2.ll b/test/Transforms/InstCombine/and2.ll index 0af9bfaff3..a5a6574e9f 100644 --- a/test/Transforms/InstCombine/and2.ll +++ b/test/Transforms/InstCombine/and2.ll @@ -1,5 +1,4 @@ -; RUN: opt < %s -instcombine -S | not grep and - +; RUN: opt < %s -instcombine -S | FileCheck %s ; PR1738 define i1 @test1(double %X, double %Y) { @@ -7,6 +6,5 @@ define i1 @test1(double %X, double %Y) { %tmp13 = fcmp ord double %Y, 0.000000e+00 %bothcond = and i1 %tmp13, %tmp9 ret i1 %bothcond +; CHECK: fcmp ord double %Y, %X } - - diff --git a/test/Transforms/InstCombine/bswap-fold.ll b/test/Transforms/InstCombine/bswap-fold.ll index 034c70e400..a6b30c053e 100644 --- a/test/Transforms/InstCombine/bswap-fold.ll +++ b/test/Transforms/InstCombine/bswap-fold.ll @@ -67,3 +67,9 @@ define i16 @test8(i64 %A) { %D = tail call i16 @llvm.bswap.i16(i16 %C) nounwind ret i16 %D } + +; Misc: Fold bswap(undef) to undef. +define i64 @foo() { + %a = call i64 @llvm.bswap.i64(i64 undef) + ret i64 %a +} diff --git a/test/Transforms/InstCombine/constant-fold-ptr-casts.ll b/test/Transforms/InstCombine/constant-fold-ptr-casts.ll deleted file mode 100644 index 9b6c6c3f58..0000000000 --- a/test/Transforms/InstCombine/constant-fold-ptr-casts.ll +++ /dev/null @@ -1,18 +0,0 @@ -; RUN: opt < %s -instcombine -S | grep {ret i32 2143034560} - -; Instcombine should be able to completely fold this code. - -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" -target triple = "i686-apple-darwin8" - -@bar = constant [3 x i64] [i64 9220983451228067448, i64 9220983451228067449, i64 9220983450959631991], align 8 - -define i32 @foo() nounwind { -entry: - %tmp87.2 = load i64* inttoptr (i32 add (i32 16, i32 ptrtoint ([3 x i64]* @bar to i32)) to i64*), align 8 - %t0 = bitcast i64 %tmp87.2 to double - %tmp9192.2 = fptrunc double %t0 to float - %t1 = bitcast float %tmp9192.2 to i32 - ret i32 %t1 -} - diff --git a/test/Transforms/InstCombine/crash.ll b/test/Transforms/InstCombine/crash.ll index 2faa5392d4..854bfc81de 100644 --- a/test/Transforms/InstCombine/crash.ll +++ b/test/Transforms/InstCombine/crash.ll @@ -237,3 +237,18 @@ entry: %or = or i32 %and42, %and47 ret i32 %or } + +; PR6503 +define void @test12(i32* %A) nounwind { +entry: + %tmp1 = load i32* %A + %cmp = icmp ugt i32 1, %tmp1 ; [#uses=1] + %conv = zext i1 %cmp to i32 ; [#uses=1] + %tmp2 = load i32* %A + %cmp3 = icmp ne i32 %tmp2, 0 ; [#uses=1] + %conv4 = zext i1 %cmp3 to i32 ; [#uses=1] + %or = or i32 %conv, %conv4 ; [#uses=1] + %cmp5 = icmp ugt i32 undef, %or ; [#uses=1] + %conv6 = zext i1 %cmp5 to i32 ; [#uses=0] + ret void +} diff --git a/test/Transforms/InstCombine/fcmp-select.ll b/test/Transforms/InstCombine/fcmp-select.ll new file mode 100644 index 0000000000..e04ab3e892 --- /dev/null +++ b/test/Transforms/InstCombine/fcmp-select.ll @@ -0,0 +1,53 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; x != y ? x : y -> x if it's the right kind of != and at least +; one of x and y is not negative zero. + +; CHECK: f0 +; CHECK: ret double %x +define double @f0(double %x) nounwind readnone { +entry: + %cmp = fcmp une double %x, -1.0 + %cond = select i1 %cmp, double %x, double -1.0 + ret double %cond +} +; CHECK: f1 +; CHECK: ret double -1.000000e+00 +define double @f1(double %x) nounwind readnone { +entry: + %cmp = fcmp une double %x, -1.0 + %cond = select i1 %cmp, double -1.0, double %x + ret double %cond +} +; CHECK: f2 +; CHECK: ret double %cond +define double @f2(double %x, double %y) nounwind readnone { +entry: + %cmp = fcmp une double %x, %y + %cond = select i1 %cmp, double %x, double %y + ret double %cond +} +; CHECK: f3 +; CHECK: ret double %cond +define double @f3(double %x, double %y) nounwind readnone { +entry: + %cmp = fcmp une double %x, %y + %cond = select i1 %cmp, double %y, double %x + ret double %cond +} +; CHECK: f4 +; CHECK: ret double %cond +define double @f4(double %x) nounwind readnone { +entry: + %cmp = fcmp one double %x, -1.0 + %cond = select i1 %cmp, double %x, double -1.0 + ret double %cond +} +; CHECK: f5 +; CHECK: ret double %cond +define double @f5(double %x) nounwind readnone { +entry: + %cmp = fcmp one double %x, -1.0 + %cond = select i1 %cmp, double -1.0, double %x + ret double %cond +} diff --git a/test/Transforms/InstCombine/fcmp-special.ll b/test/Transforms/InstCombine/fcmp-special.ll new file mode 100644 index 0000000000..a39021e08d --- /dev/null +++ b/test/Transforms/InstCombine/fcmp-special.ll @@ -0,0 +1,155 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; Infinity + +; CHECK: inf0 +; CHECK: ret i1 false +define i1 @inf0(double %arg) nounwind readnone { + %tmp = fcmp ogt double %arg, 0x7FF0000000000000 + ret i1 %tmp +} + +; CHECK: inf1 +; CHECK: ret i1 true +define i1 @inf1(double %arg) nounwind readnone { + %tmp = fcmp ule double %arg, 0x7FF0000000000000 + ret i1 %tmp +} + +; Negative infinity + +; CHECK: ninf0 +; CHECK: ret i1 false +define i1 @ninf0(double %arg) nounwind readnone { + %tmp = fcmp olt double %arg, 0xFFF0000000000000 + ret i1 %tmp +} + +; CHECK: ninf1 +; CHECK: ret i1 true +define i1 @ninf1(double %arg) nounwind readnone { + %tmp = fcmp uge double %arg, 0xFFF0000000000000 + ret i1 %tmp +} + +; NaNs + +; CHECK: nan0 +; CHECK: ret i1 false +define i1 @nan0(double %arg) nounwind readnone { + %tmp = fcmp ord double %arg, 0x7FF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nan1 +; CHECK: ret i1 false +define i1 @nan1(double %arg) nounwind readnone { + %tmp = fcmp oeq double %arg, 0x7FF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nan2 +; CHECK: ret i1 false +define i1 @nan2(double %arg) nounwind readnone { + %tmp = fcmp olt double %arg, 0x7FF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nan3 +; CHECK: ret i1 true +define i1 @nan3(double %arg) nounwind readnone { + %tmp = fcmp uno double %arg, 0x7FF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nan4 +; CHECK: ret i1 true +define i1 @nan4(double %arg) nounwind readnone { + %tmp = fcmp une double %arg, 0x7FF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nan5 +; CHECK: ret i1 true +define i1 @nan5(double %arg) nounwind readnone { + %tmp = fcmp ult double %arg, 0x7FF00000FFFFFFFF + ret i1 %tmp +} + +; Negative NaN. + +; CHECK: nnan0 +; CHECK: ret i1 false +define i1 @nnan0(double %arg) nounwind readnone { + %tmp = fcmp ord double %arg, 0xFFF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nnan1 +; CHECK: ret i1 false +define i1 @nnan1(double %arg) nounwind readnone { + %tmp = fcmp oeq double %arg, 0xFFF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nnan2 +; CHECK: ret i1 false +define i1 @nnan2(double %arg) nounwind readnone { + %tmp = fcmp olt double %arg, 0xFFF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nnan3 +; CHECK: ret i1 true +define i1 @nnan3(double %arg) nounwind readnone { + %tmp = fcmp uno double %arg, 0xFFF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nnan4 +; CHECK: ret i1 true +define i1 @nnan4(double %arg) nounwind readnone { + %tmp = fcmp une double %arg, 0xFFF00000FFFFFFFF + ret i1 %tmp +} + +; CHECK: nnan5 +; CHECK: ret i1 true +define i1 @nnan5(double %arg) nounwind readnone { + %tmp = fcmp ult double %arg, 0xFFF00000FFFFFFFF + ret i1 %tmp +} + +; Negative zero. + +; CHECK: nzero0 +; CHECK: ret i1 true +define i1 @nzero0() { + %tmp = fcmp oeq double 0.0, -0.0 + ret i1 %tmp +} + +; CHECK: nzero1 +; CHECK: ret i1 false +define i1 @nzero1() { + %tmp = fcmp ogt double 0.0, -0.0 + ret i1 %tmp +} + +; Misc. + +; CHECK: misc0 +; CHECK: %tmp = fcmp ord double %arg, 0.000000e+00 +; CHECK: ret i1 %tmp +define i1 @misc0(double %arg) { + %tmp = fcmp oeq double %arg, %arg + ret i1 %tmp +} + +; CHECK: misc1 +; CHECK: ret i1 false +define i1 @misc1(double %arg) { + %tmp = fcmp one double %arg, %arg + ret i1 %tmp +} + diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index c2234a10e5..29997bf8c4 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -48,7 +48,7 @@ entry: %V = icmp eq <2 x i64> %x, undef ret <2 x i1> %V ; CHECK: @test5 -; CHECK: ret <2 x i1> undef +; CHECK: ret <2 x i1> } define i32 @test6(i32 %a, i32 %b) { @@ -121,3 +121,13 @@ define i1 @test12(i1 %A) { ; CHECK-NEXT: %B = select i1 ; CHECK-NEXT: ret i1 %B } + +; PR6481 +define i1 @test13(i8 %X) nounwind readnone { +entry: + %cmp = icmp slt i8 undef, %X + ret i1 %cmp +; CHECK: @test13 +; CHECK: ret i1 false +} + diff --git a/test/Transforms/InstCombine/load-cmp.ll b/test/Transforms/InstCombine/load-cmp.ll index fe5df92843..5cafb7787e 100644 --- a/test/Transforms/InstCombine/load-cmp.ll +++ b/test/Transforms/InstCombine/load-cmp.ll @@ -89,8 +89,8 @@ define i1 @test8(i32 %X) { ret i1 %S ; CHECK: @test8 ; CHECK-NEXT: add i32 %X, -8 -; CHECK-NEXT: %S = icmp ult i32 {{.*}}, 2 -; CHECK-NEXT: ret i1 %S +; CHECK-NEXT: icmp ult i32 {{.*}}, 2 +; CHECK-NEXT: ret i1 } @GA = internal constant [4 x { i32, i32 } ] [ @@ -107,6 +107,6 @@ define i1 @test9(i32 %X) { ret i1 %R ; CHECK: @test9 ; CHECK-NEXT: add i32 %X, -1 -; CHECK-NEXT: %R = icmp ult i32 {{.*}}, 2 -; CHECK-NEXT: ret i1 %R +; CHECK-NEXT: icmp ult i32 {{.*}}, 2 +; CHECK-NEXT: ret i1 } diff --git a/test/Transforms/InstCombine/memset_chk.ll b/test/Transforms/InstCombine/memset_chk.ll new file mode 100644 index 0000000000..5a4e6d9e84 --- /dev/null +++ b/test/Transforms/InstCombine/memset_chk.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +; rdar://7719085 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + +%struct.data = type { [100 x i32], [100 x i32], [1024 x i8] } + +define i32 @t() nounwind ssp { +; CHECK: @t +; CHECK: @llvm.memset.i64 +entry: + %0 = alloca %struct.data, align 8 ; <%struct.data*> [#uses=1] + %1 = bitcast %struct.data* %0 to i8* ; [#uses=1] + %2 = call i8* @__memset_chk(i8* %1, i32 0, i64 1824, i64 1824) nounwind ; [#uses=0] + ret i32 0 +} + +declare i8* @__memset_chk(i8*, i32, i64, i64) nounwind diff --git a/test/Transforms/InstCombine/multi-use-or.ll b/test/Transforms/InstCombine/multi-use-or.ll index 9bbef2383b..8c6a0e0bbc 100644 --- a/test/Transforms/InstCombine/multi-use-or.ll +++ b/test/Transforms/InstCombine/multi-use-or.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -instcombine -S | grep {add double .sx, .sy} +; RUN: opt < %s -instcombine -S | grep {fadd double .sx, .sy} ; The 'or' has multiple uses, make sure that this doesn't prevent instcombine ; from propagating the extends to the truncs. diff --git a/test/Transforms/InstCombine/objsize.ll b/test/Transforms/InstCombine/objsize.ll index 69e09f61f7..57dc2fd054 100644 --- a/test/Transforms/InstCombine/objsize.ll +++ b/test/Transforms/InstCombine/objsize.ll @@ -23,18 +23,17 @@ entry: br i1 %cmp, label %cond.true, label %cond.false cond.true: - %1 = load i8** %retval; - ret i8* %1; + %1 = load i8** %retval + ret i8* %1 cond.false: - %2 = load i8** %retval; - ret i8* %2; + %2 = load i8** %retval + ret i8* %2 } -; FIXME: Should be ret i32 0 define i32 @f() nounwind { ; CHECK: @f -; CHECK-NEXT: llvm.objectsize.i32 +; CHECK-NEXT: ret i32 0 %1 = call i32 @llvm.objectsize.i32(i8* getelementptr ([60 x i8]* @a, i32 1, i32 0), i1 false) ret i32 %1 } @@ -49,4 +48,78 @@ define i1 @baz() nounwind { ret i1 %2 } -declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly \ No newline at end of file +define void @test1(i8* %q, i32 %x) nounwind noinline { +; CHECK: @test1 +; CHECK: objectsize.i32 +entry: + %0 = call i32 @llvm.objectsize.i32(i8* getelementptr inbounds ([0 x i8]* @window, i32 0, i32 10), i1 false) ; [#uses=1] + %1 = icmp eq i32 %0, -1 ; [#uses=1] + br i1 %1, label %"47", label %"46" + +"46": ; preds = %entry + unreachable + +"47": ; preds = %entry + unreachable +} + +@.str5 = private constant [9 x i32] [i32 97, i32 98, i32 99, i32 100, i32 0, i32 + 101, i32 102, i32 103, i32 0], align 4 +define i32 @test2() nounwind { +; CHECK: @test2 +; CHECK-NEXT: ret i32 34 + %1 = call i32 @llvm.objectsize.i32(i8* getelementptr (i8* bitcast ([9 x i32]* @.str5 to i8*), i32 2), i1 false) + ret i32 %1 +} + +; rdar://7674946 +@array = internal global [480 x float] zeroinitializer ; <[480 x float]*> [#uses=1] + +declare i8* @__memcpy_chk(i8*, i8*, i32, i32) nounwind + +declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly + +declare i8* @__inline_memcpy_chk(i8*, i8*, i32) nounwind inlinehint + +define void @test3() nounwind { +; CHECK: @test3 +entry: + br i1 undef, label %bb11, label %bb12 + +bb11: + %0 = getelementptr inbounds float* getelementptr inbounds ([480 x float]* @array, i32 0, i32 128), i32 -127 ; [#uses=1] + %1 = bitcast float* %0 to i8* ; [#uses=1] + %2 = call i32 @llvm.objectsize.i32(i8* %1, i1 false) ; [#uses=1] + %3 = call i8* @__memcpy_chk(i8* undef, i8* undef, i32 512, i32 %2) nounwind ; [#uses=0] +; CHECK: unreachable + unreachable + +bb12: + %4 = getelementptr inbounds float* getelementptr inbounds ([480 x float]* @array, i32 0, i32 128), i32 -127 ; [#uses=1] + %5 = bitcast float* %4 to i8* ; [#uses=1] + %6 = call i8* @__inline_memcpy_chk(i8* %5, i8* undef, i32 512) nounwind inlinehint ; [#uses=0] +; CHECK: @__inline_memcpy_chk + unreachable +} + +; rdar://7718857 + +%struct.data = type { [100 x i32], [100 x i32], [1024 x i8] } + +define i32 @test4() nounwind ssp { +; CHECK: @test4 +entry: + %0 = alloca %struct.data, align 8 + %1 = bitcast %struct.data* %0 to i8* + %2 = call i64 @llvm.objectsize.i64(i8* %1, i1 false) nounwind +; CHECK-NOT: @llvm.objectsize +; CHECK: @llvm.memset.i64(i8* %1, i8 0, i64 1824, i32 8) + %3 = call i8* @__memset_chk(i8* %1, i32 0, i64 1824, i64 %2) nounwind + ret i32 0 +} + +declare i8* @__memset_chk(i8*, i32, i64, i64) nounwind + +declare i32 @llvm.objectsize.i32(i8*, i1) nounwind readonly + +declare i64 @llvm.objectsize.i64(i8*, i1) nounwind readonly diff --git a/test/Transforms/InstCombine/or.ll b/test/Transforms/InstCombine/or.ll index 189be1050f..c3526b77f6 100644 --- a/test/Transforms/InstCombine/or.ll +++ b/test/Transforms/InstCombine/or.ll @@ -126,8 +126,8 @@ define i1 @test14(i32 %A, i32 %B) { %D = or i1 %C1, %C2 ret i1 %D ; CHECK: @test14 -; CHECK: %D = icmp ne i32 %A, %B -; CHECK: ret i1 %D +; CHECK: icmp ne i32 %A, %B +; CHECK: ret i1 } define i1 @test15(i32 %A, i32 %B) { @@ -137,8 +137,8 @@ define i1 @test15(i32 %A, i32 %B) { %D = or i1 %C1, %C2 ret i1 %D ; CHECK: @test15 -; CHECK: %D = icmp ule i32 %A, %B -; CHECK: ret i1 %D +; CHECK: icmp ule i32 %A, %B +; CHECK: ret i1 } define i32 @test16(i32 %A) { @@ -171,8 +171,8 @@ define i1 @test18(i32 %A) { ret i1 %D ; CHECK: @test18 ; CHECK: add i32 -; CHECK: %D = icmp ugt -; CHECK: ret i1 %D +; CHECK: icmp ugt +; CHECK: ret i1 } define i1 @test19(i32 %A) { @@ -183,8 +183,8 @@ define i1 @test19(i32 %A) { ret i1 %D ; CHECK: @test19 ; CHECK: add i32 -; CHECK: %D = icmp ult -; CHECK: ret i1 %D +; CHECK: icmp ult +; CHECK: ret i1 } define i32 @test20(i32 %x) { @@ -236,8 +236,8 @@ define i1 @test24(double %X, double %Y) { ret i1 %bothcond ; CHECK: @test24 -; CHECK: %bothcond = fcmp uno double %Y, %X ; [#uses=1] -; CHECK: ret i1 %bothcond +; CHECK: = fcmp uno double %Y, %X +; CHECK: ret i1 } ; PR3266 & PR5276 diff --git a/test/Transforms/InstCombine/phi.ll b/test/Transforms/InstCombine/phi.ll index f0343e44c2..fc321e9682 100644 --- a/test/Transforms/InstCombine/phi.ll +++ b/test/Transforms/InstCombine/phi.ll @@ -362,3 +362,43 @@ end: ; CHECK-NEXT: ret i64 } +; PR6512 - Shouldn't merge loads from different addr spaces. +define i32 @test16(i32 addrspace(1)* %pointer1, i32 %flag, i32* %pointer2) +nounwind { +entry: + %retval = alloca i32, align 4 ; [#uses=2] + %pointer1.addr = alloca i32 addrspace(1)*, align 4 ; + %flag.addr = alloca i32, align 4 ; [#uses=2] + %pointer2.addr = alloca i32*, align 4 ; [#uses=2] + %res = alloca i32, align 4 ; [#uses=4] + store i32 addrspace(1)* %pointer1, i32 addrspace(1)** %pointer1.addr + store i32 %flag, i32* %flag.addr + store i32* %pointer2, i32** %pointer2.addr + store i32 10, i32* %res + %tmp = load i32* %flag.addr ; [#uses=1] + %tobool = icmp ne i32 %tmp, 0 ; [#uses=1] + br i1 %tobool, label %if.then, label %if.else + +return: ; preds = %if.end + %tmp7 = load i32* %retval ; [#uses=1] + ret i32 %tmp7 + +if.end: ; preds = %if.else, %if.then + %tmp6 = load i32* %res ; [#uses=1] + store i32 %tmp6, i32* %retval + br label %return + +if.then: ; preds = %entry + %tmp1 = load i32 addrspace(1)** %pointer1.addr ; + %arrayidx = getelementptr i32 addrspace(1)* %tmp1, i32 0 ; [#uses=1] + %tmp2 = load i32 addrspace(1)* %arrayidx ; [#uses=1] + store i32 %tmp2, i32* %res + br label %if.end + +if.else: ; preds = %entry + %tmp3 = load i32** %pointer2.addr ; [#uses=1] + %arrayidx4 = getelementptr i32* %tmp3, i32 0 ; [#uses=1] + %tmp5 = load i32* %arrayidx4 ; [#uses=1] + store i32 %tmp5, i32* %res + br label %if.end +} diff --git a/test/Transforms/InstCombine/ptr-int-cast.ll b/test/Transforms/InstCombine/ptr-int-cast.ll index c7ae689048..ad11e430d9 100644 --- a/test/Transforms/InstCombine/ptr-int-cast.ll +++ b/test/Transforms/InstCombine/ptr-int-cast.ll @@ -1,17 +1,29 @@ -; RUN: opt < %s -instcombine -S > %t +; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" define i1 @test1(i32 *%x) nounwind { entry: -; RUN: grep {ptrtoint i32\\* %x to i64} %t +; CHECK: test1 +; CHECK: ptrtoint i32* %x to i64 %tmp = ptrtoint i32* %x to i1 ret i1 %tmp } define i32* @test2(i128 %x) nounwind { entry: -; RUN: grep {inttoptr i64 %.mp1 to i32\\*} %t +; CHECK: test2 +; CHECK: inttoptr i64 %tmp1 to i32* %tmp = inttoptr i128 %x to i32* ret i32* %tmp } +; PR3574 +; CHECK: f0 +; CHECK: %tmp = zext i32 %a0 to i64 +; CHECK: ret i64 %tmp +define i64 @f0(i32 %a0) nounwind { + %t0 = inttoptr i32 %a0 to i8* + %t1 = ptrtoint i8* %t0 to i64 + ret i64 %t1 +} + diff --git a/test/Transforms/InstCombine/strcpy_chk.ll b/test/Transforms/InstCombine/strcpy_chk.ll new file mode 100644 index 0000000000..a20a13c78b --- /dev/null +++ b/test/Transforms/InstCombine/strcpy_chk.ll @@ -0,0 +1,12 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s +@a = common global [60 x i8] zeroinitializer, align 1 ; <[60 x i8]*> [#uses=1] +@.str = private constant [8 x i8] c"abcdefg\00" ; <[8 x i8]*> [#uses=1] + +define i8* @foo() nounwind { +; CHECK: @foo +; CHECK-NEXT: call i8* @strcpy + %call = call i8* @__strcpy_chk(i8* getelementptr inbounds ([60 x i8]* @a, i32 0, i32 0), i8* getelementptr inbounds ([8 x i8]* @.str, i32 0, i32 0), i32 60) ; [#uses=1] + ret i8* %call +} + +declare i8* @__strcpy_chk(i8*, i8*, i32) nounwind diff --git a/test/Transforms/InstCombine/vec_narrow.ll b/test/Transforms/InstCombine/vec_narrow.ll index daf7bcf297..c05c802188 100644 --- a/test/Transforms/InstCombine/vec_narrow.ll +++ b/test/Transforms/InstCombine/vec_narrow.ll @@ -1,5 +1,5 @@ ; RUN: opt < %s -instcombine -S | \ -; RUN: grep {add float} +; RUN: grep {fadd float} %V = type <4 x float> diff --git a/test/Transforms/InstCombine/vector-casts.ll b/test/Transforms/InstCombine/vector-casts.ll index 470d485475..24bd04dcb2 100644 --- a/test/Transforms/InstCombine/vector-casts.ll +++ b/test/Transforms/InstCombine/vector-casts.ll @@ -51,6 +51,22 @@ entry: } +; rdar://7434900 +define <2 x i64> @test5(<4 x float> %a, <4 x float> %b) nounwind readnone { +entry: + %cmp = fcmp ult <4 x float> %a, zeroinitializer + %sext = sext <4 x i1> %cmp to <4 x i32> + %cmp4 = fcmp ult <4 x float> %b, zeroinitializer + %sext5 = sext <4 x i1> %cmp4 to <4 x i32> + %and = and <4 x i32> %sext, %sext5 + %conv = bitcast <4 x i32> %and to <2 x i64> + ret <2 x i64> %conv + +; CHECK: @test5 +; CHECK: sext <4 x i1> %cmp to <4 x i32> +; CHECK: sext <4 x i1> %cmp4 to <4 x i32> +} + define void @convert(<2 x i32>* %dst.addr, <2 x i64> %src) nounwind { entry: diff --git a/test/Transforms/InstCombine/xor2.ll b/test/Transforms/InstCombine/xor2.ll index de3d65dd8c..67f05efa23 100644 --- a/test/Transforms/InstCombine/xor2.ll +++ b/test/Transforms/InstCombine/xor2.ll @@ -22,8 +22,8 @@ define i1 @test1(i32 %A) { ; PR1014 define i32 @test2(i32 %tmp1) { ; CHECK: @test2 -; CHECK-NEXT: or i32 %tmp1, 8 -; CHECK-NEXT: and i32 +; CHECK-NEXT: and i32 %tmp1, 32 +; CHECK-NEXT: or i32 %ovm, 8 ; CHECK-NEXT: ret i32 %ovm = and i32 %tmp1, 32 %ov3 = add i32 %ovm, 145 @@ -33,8 +33,8 @@ define i32 @test2(i32 %tmp1) { define i32 @test3(i32 %tmp1) { ; CHECK: @test3 -; CHECK-NEXT: or i32 %tmp1, 8 -; CHECK-NEXT: and i32 +; CHECK-NEXT: and i32 %tmp1, 32 +; CHECK-NEXT: or i32 %tmp, 8 ; CHECK-NEXT: ret i32 %ovm = or i32 %tmp1, 145 %ov31 = and i32 %ovm, 177 diff --git a/test/Transforms/JumpThreading/crash.ll b/test/Transforms/JumpThreading/crash.ll index cf292df0f7..c65fd1014b 100644 --- a/test/Transforms/JumpThreading/crash.ll +++ b/test/Transforms/JumpThreading/crash.ll @@ -313,3 +313,14 @@ for.cond: ; preds = %for.body, %lor.end for.body: ; preds = %for.cond br label %for.cond } + + +; PR6305 +define void @test11() nounwind { +entry: + br label %A + +A: ; preds = %entry + call void undef(i64 ptrtoint (i8* blockaddress(@test11, %A) to i64)) nounwind + unreachable +} diff --git a/test/Transforms/JumpThreading/or-undef.ll b/test/Transforms/JumpThreading/or-undef.ll new file mode 100644 index 0000000000..6e359925b6 --- /dev/null +++ b/test/Transforms/JumpThreading/or-undef.ll @@ -0,0 +1,69 @@ +; RUN: opt -jump-threading -S %s | FileCheck %s +; rdar://7620633 + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" +target triple = "x86_64-apple-darwin11.0" + +define void @test1(i8* %args, i32 %from_tty) nounwind optsize ssp { +entry: + %tmp = call i8* @f3(void (i8*)* null, i8* null) nounwind ; [#uses=1] + %tmp1 = icmp eq i8* %args, null ; [#uses=1] + br i1 %tmp1, label %bb2, label %bb + +; CHECK: entry: +; CHECK-NEXT: %tmp = call i8* @f3 +; CHECK-NEXT: %tmp1 = icmp eq i8* %args, null +; CHECK-NEXT: br i1 %tmp1, label %bb7, label %bb + +bb: ; preds = %entry + %tmp2 = call noalias i8** @buildargv(i8* %args) nounwind ; [#uses=4] + %tmp3 = icmp eq i8** %tmp2, null ; [#uses=1] + br i1 %tmp3, label %bb2, label %bb1 + +bb1: ; preds = %bb + call void @f2(i8** %tmp2) nounwind + br label %bb2 + +bb2: ; preds = %bb1, %bb, %entry + %argv.0 = phi i8** [ %tmp2, %bb1 ], [ %tmp2, %bb ], [ undef, %entry ] ; [#uses=4] + %tmp5 = icmp eq i8* %args, null ; [#uses=1] + %tmp6 = icmp eq i8** %argv.0, null ; [#uses=1] + %tmp7 = or i1 %tmp5, %tmp6 ; [#uses=1] + br i1 %tmp7, label %bb7, label %bb5 + +bb5: ; preds = %bb2 + %tmp8 = load i8** %argv.0, align 8 ; [#uses=1] + %tmp9 = icmp eq i8* %tmp8, null ; [#uses=1] + br i1 %tmp9, label %bb7, label %bb6 + +bb6: ; preds = %bb5 + %tmp10 = load i8** %argv.0, align 8 ; [#uses=1] + %tmp11 = load i8* %tmp10, align 1 ; [#uses=1] + %tmp12 = icmp eq i8 %tmp11, 0 ; [#uses=1] + br i1 %tmp12, label %bb7, label %bb8 + +bb7: ; preds = %bb6, %bb5, %bb2 + call void @f1() nounwind optsize ssp + br label %bb9 + +bb8: ; preds = %bb6 + %tmp13 = load i8** %argv.0, align 8 ; [#uses=1] + %tmp14 = call i64 @f5(i8* %tmp13) nounwind ; [#uses=0] + br label %bb9 + +bb9: ; preds = %bb8, %bb7 + call void @f4(i8* %tmp) nounwind + ret void +} + +declare noalias i8** @buildargv(i8*) + +declare void @f2(i8**) + +declare void @f4(i8*) + +declare i8* @f3(void (i8*)*, i8*) + +declare void @f1() + +declare i64 @f5(i8*) diff --git a/test/Transforms/LoopDeletion/simplify-then-delete.ll b/test/Transforms/LoopDeletion/simplify-then-delete.ll new file mode 100644 index 0000000000..5a21672a59 --- /dev/null +++ b/test/Transforms/LoopDeletion/simplify-then-delete.ll @@ -0,0 +1,65 @@ +; RUN: opt < %s -S -indvars -loop-deletion -simplifycfg | FileCheck %s +; PR5794 + +; Indvars and loop deletion should be able to eliminate all looping +; in this testcase. + +; CHECK: define i32 @pmat(i32 %m, i32 %n, double* %y) nounwind { +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 0 +; CHECK-NEXT: } + +target datalayout = "e-p:64:64:64" + +define i32 @pmat(i32 %m, i32 %n, double* %y) nounwind { +entry: + %cmp4 = icmp sgt i32 %m, 0 + br i1 %cmp4, label %bb.n10, label %w.e12 + +w.c: + %cmp = icmp slt i32 %inc11, %m + br i1 %cmp, label %w.c2.p, label %w.c.w.e12c + +w.c.w.e12c: + br label %w.c.w.e12c.s + +w.c.w.e12c.s: + br label %w.e12 + +bb.n10: + %cmp51 = icmp sgt i32 %n, 0 + br i1 %cmp51, label %bb.n10.w.c.w.e12c.sc, label %bb.n10.bb.n10.sc + +bb.n10.bb.n10.sc: + br label %bb.n10.s + +bb.n10.w.c.w.e12c.sc: + br label %w.c.w.e12c.s + +bb.n10.s: + br label %w.c2.p + +w.c2.p: + %i.05 = phi i32 [ 0, %bb.n10.s ], [ %inc11, %w.c ] + br i1 false, label %bb.n, label %w.e + +w.c2: + br i1 undef, label %w.b6, label %w.c2.w.ec + +w.c2.w.ec: + br label %w.e + +bb.n: + br label %w.b6 + +w.b6: + br label %w.c2 + +w.e: + %i.08 = phi i32 [ undef, %w.c2.w.ec ], [ %i.05, %w.c2.p ] + %inc11 = add nsw i32 %i.08, 1 + br label %w.c + +w.e12: + ret i32 0 +} diff --git a/test/Transforms/LoopIndexSplit/SplitValue-2007-08-24-dbg.ll b/test/Transforms/LoopIndexSplit/SplitValue-2007-08-24-dbg.ll deleted file mode 100644 index 4ab95fcb38..0000000000 --- a/test/Transforms/LoopIndexSplit/SplitValue-2007-08-24-dbg.ll +++ /dev/null @@ -1,71 +0,0 @@ -; Split loop. Save last value. Split value is off by one in this example. -; RUN: opt < %s -loop-index-split -disable-output -stats |& \ -; RUN: grep "loop-index-split" | count 1 - - %llvm.dbg.anchor.type = type { i32, i32 } - %llvm.dbg.compile_unit.type = type { i32, { }*, i32, i8*, i8*, i8*, i1, i1, i8* } - -@llvm.dbg.compile_units = linkonce constant %llvm.dbg.anchor.type { i32 458752, i32 17 }, section "llvm.metadata" - -@.str = internal constant [4 x i8] c"a.c\00", section "llvm.metadata" ; <[4 x i8]*> [#uses=1] -@.str1 = internal constant [6 x i8] c"/tmp/\00", section "llvm.metadata" ; <[6 x i8]*> [#uses=1] -@.str2 = internal constant [55 x i8] c"4.2.1 (Based on Apple Inc. build 5636) (LLVM build 00)\00", section "llvm.metadata" ; <[55 x i8]*> [#uses=1] -@llvm.dbg.compile_unit = internal constant %llvm.dbg.compile_unit.type { i32 458769, { }* bitcast (%llvm.dbg.anchor.type* @llvm.dbg.compile_units to { }*), i32 1, i8* getelementptr ([4 x i8]* @.str, i32 0, i32 0), i8* getelementptr ([6 x i8]* @.str1, i32 0, i32 0), i8* getelementptr ([55 x i8]* @.str2, i32 0, i32 0), i1 true, i1 false, i8* null }, section "llvm.metadata" ; <%llvm.dbg.compile_unit.type*> [#uses=1] - -declare void @llvm.dbg.stoppoint(i32, i32, { }*) nounwind - - -@k = external global i32 ; [#uses=2] - -define void @foobar(i32 %a, i32 %b) { -entry: - br label %bb - -bb: ; preds = %cond_next16, %entry - %i.01.0 = phi i32 [ 0, %entry ], [ %tmp18, %cond_next16 ] ; [#uses=5] - %tsum.18.0 = phi i32 [ 42, %entry ], [ %tsum.013.1, %cond_next16 ] ; [#uses=3] - %tmp1 = icmp sgt i32 %i.01.0, 50 ; [#uses=1] -call void @llvm.dbg.stoppoint(i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - br i1 %tmp1, label %cond_true, label %cond_false - -cond_true: ; preds = %bb - %tmp4 = tail call i32 @foo( i32 %i.01.0 ) ; [#uses=1] - %tmp6 = add i32 %tmp4, %tsum.18.0 ; [#uses=2] - %tmp914 = load i32* @k, align 4 ; [#uses=1] - %tmp1015 = icmp eq i32 %tmp914, 0 ; [#uses=1] -call void @llvm.dbg.stoppoint(i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - br i1 %tmp1015, label %cond_next16, label %cond_true13 - -cond_false: ; preds = %bb - %tmp8 = tail call i32 @bar( i32 %i.01.0 ) ; [#uses=0] - %tmp9 = load i32* @k, align 4 ; [#uses=1] - %tmp10 = icmp eq i32 %tmp9, 0 ; [#uses=1] -call void @llvm.dbg.stoppoint(i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - br i1 %tmp10, label %cond_next16, label %cond_true13 - -cond_true13: ; preds = %cond_false, %cond_true - %tsum.013.0 = phi i32 [ %tmp6, %cond_true ], [ %tsum.18.0, %cond_false ] ; [#uses=1] - %tmp15 = tail call i32 @bar( i32 %i.01.0 ) ; [#uses=0] -call void @llvm.dbg.stoppoint(i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - br label %cond_next16 - -cond_next16: ; preds = %cond_false, %cond_true, %cond_true13 - %tsum.013.1 = phi i32 [ %tsum.013.0, %cond_true13 ], [ %tmp6, %cond_true ], [ %tsum.18.0, %cond_false ] ; [#uses=2] - %tmp18 = add i32 %i.01.0, 1 ; [#uses=3] - %tmp21 = icmp slt i32 %tmp18, 100 ; [#uses=1] -call void @llvm.dbg.stoppoint(i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - br i1 %tmp21, label %bb, label %bb24 - -bb24: ; preds = %cond_next16 - %tmp18.lcssa = phi i32 [ %tmp18, %cond_next16 ] ; [#uses=1] - %tsum.013.1.lcssa = phi i32 [ %tsum.013.1, %cond_next16 ] ; [#uses=1] - %tmp27 = tail call i32 @t( i32 %tmp18.lcssa, i32 %tsum.013.1.lcssa ) ; [#uses=0] -call void @llvm.dbg.stoppoint(i32 5, i32 0, { }* bitcast (%llvm.dbg.compile_unit.type* @llvm.dbg.compile_unit to { }*)) - ret void -} - -declare i32 @foo(i32) - -declare i32 @bar(i32) - -declare i32 @t(i32, i32) diff --git a/test/Transforms/LoopStrengthReduce/2008-08-06-CmpStride.ll b/test/Transforms/LoopStrengthReduce/2008-08-06-CmpStride.ll index 7c7a21c013..99cb8569b3 100644 --- a/test/Transforms/LoopStrengthReduce/2008-08-06-CmpStride.ll +++ b/test/Transforms/LoopStrengthReduce/2008-08-06-CmpStride.ll @@ -1,5 +1,4 @@ -; RUN: opt < %s -loop-reduce -S | grep ugt -; PR2535 +; RUN: llc -march=x86-64 < %s -o - | grep {cmpl \\$\[1\], %} @.str = internal constant [4 x i8] c"%d\0A\00" @@ -16,7 +15,7 @@ forbody: %add166 = or i32 %mul15, 1 ; [#uses=1] * call i32 (i8*, ...)* @printf( i8* noalias getelementptr ([4 x i8]* @.str, i32 0, i32 0), i32 %add166 ) nounwind %inc = add i32 %i.0, 1 ; [#uses=3] - %cmp = icmp ult i32 %inc, 1027 ; [#uses=1] + %cmp = icmp ne i32 %inc, 1027 ; [#uses=1] br i1 %cmp, label %forbody, label %afterfor afterfor: ; preds = %forcond diff --git a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll index 36941ad6d3..1f7f6ecafa 100644 --- a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll +++ b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-0.ll @@ -1,10 +1,15 @@ -; RUN: llc %s -o - --x86-asm-syntax=att | grep {cmpl \$4} +; RUN: llc < %s -o - | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" target triple = "x86_64-apple-darwin9" -; This is like change-compare-stride-trickiness-1.ll except the comparison -; happens before the relevant use, so the comparison stride can't be -; easily changed. +; The comparison happens before the relevant use, but it can still be rewritten +; to compare with zero. + +; CHECK: foo: +; CHECK: align +; CHECK: incl %eax +; CHECK-NEXT: decl %ecx +; CHECK-NEXT: jne define void @foo() nounwind { entry: diff --git a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll index ea8a259ecd..cb638092ea 100644 --- a/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll +++ b/test/Transforms/LoopStrengthReduce/change-compare-stride-trickiness-1.ll @@ -1,10 +1,12 @@ -; RUN: llc %s -o - --x86-asm-syntax=att | grep {cmp. \$8} +; RUN: llc %s -o - --x86-asm-syntax=att | grep {cmp. \$10} target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" target triple = "x86_64-apple-darwin9" ; The comparison happens after the relevant use, so the stride can easily ; be changed. The comparison can be done in a narrower mode than the ; induction variable. +; TODO: By making the first store post-increment as well, the loop setup +; could be made simpler. define void @foo() nounwind { entry: diff --git a/test/Transforms/LoopStrengthReduce/count-to-zero.ll b/test/Transforms/LoopStrengthReduce/count-to-zero.ll index 8cc3b5c103..feb79f8a0c 100644 --- a/test/Transforms/LoopStrengthReduce/count-to-zero.ll +++ b/test/Transforms/LoopStrengthReduce/count-to-zero.ll @@ -19,7 +19,7 @@ bb3: ; preds = %bb1 %tmp4 = add i32 %c_addr.1, -1 ; [#uses=1] %c_addr.1.be = select i1 %tmp2, i32 %tmp3, i32 %tmp4 ; [#uses=1] %indvar.next = add i32 %indvar, 1 ; [#uses=1] -; CHECK: sub i32 %lsr.iv, 1 +; CHECK: add i32 %lsr.iv, -1 br label %bb6 bb6: ; preds = %bb3, %entry diff --git a/test/Transforms/LoopStrengthReduce/invariant_value_first.ll b/test/Transforms/LoopStrengthReduce/invariant_value_first.ll index f86638b0a8..4094e9c7e4 100644 --- a/test/Transforms/LoopStrengthReduce/invariant_value_first.ll +++ b/test/Transforms/LoopStrengthReduce/invariant_value_first.ll @@ -1,5 +1,5 @@ ; Check that the index of 'P[outer]' is pulled out of the loop. -; RUN: opt < %s -loop-reduce -S | \ +; RUN: opt < %s -loop-reduce -S -default-data-layout="e-p:32:32:32" | \ ; RUN: not grep {getelementptr.*%outer.*%INDVAR} declare i1 @pred() diff --git a/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll b/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll index 37acf0f61d..e2aed78c32 100644 --- a/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll +++ b/test/Transforms/LoopStrengthReduce/invariant_value_first_arg.ll @@ -1,5 +1,5 @@ ; Check that the index of 'P[outer]' is pulled out of the loop. -; RUN: opt < %s -loop-reduce -S | \ +; RUN: opt < %s -loop-reduce -S -default-data-layout="e-p:32:32:32" | \ ; RUN: not grep {getelementptr.*%outer.*%INDVAR} declare i1 @pred() diff --git a/test/Transforms/LoopStrengthReduce/nonlinear-postinc.ll b/test/Transforms/LoopStrengthReduce/nonlinear-postinc.ll new file mode 100644 index 0000000000..1e63770553 --- /dev/null +++ b/test/Transforms/LoopStrengthReduce/nonlinear-postinc.ll @@ -0,0 +1,44 @@ +; RUN: opt < %s -loop-reduce +; PR6453 + +target datalayout = "e-p:64:64:64" + +define void @_ZNK15PolynomialSpaceILi3EE13compute_indexEjRA3_j() nounwind { +entry: + br label %bb6 + +bb6: + %t4 = phi i32 [ 0, %entry ], [ %t3, %bb5 ] + %t16 = sub i32 undef, %t4 + %t25 = sub i32 undef, %t4 + %t26 = add i32 undef, %t25 + br label %bb4 + +bb4: + %t2 = phi i32 [ %t1, %bb3 ], [ 0, %bb6 ] + %t17 = mul i32 %t2, %t16 + %t18 = zext i32 %t2 to i33 + %t19 = add i32 %t2, -1 + %t20 = zext i32 %t19 to i33 + %t21 = mul i33 %t18, %t20 + %t22 = lshr i33 %t21, 1 + %t23 = trunc i33 %t22 to i32 + %t24 = sub i32 %t17, %t23 + %t27 = add i32 %t24, %t26 + br i1 false, label %bb1, label %bb5 + +bb1: + %t = icmp ugt i32 %t27, undef + br i1 %t, label %bb2, label %bb3 + +bb3: + %t1 = add i32 %t2, 1 + br label %bb4 + +bb5: + %t3 = add i32 %t4, 1 + br label %bb6 + +bb2: + ret void +} diff --git a/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll b/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll index a032cc9735..410d88f672 100644 --- a/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll +++ b/test/Transforms/LoopStrengthReduce/ops_after_indvar.ll @@ -1,7 +1,7 @@ ; Check that this test makes INDVAR and related stuff dead, because P[indvar] ; gets reduced, making INDVAR dead. -; RUN: opt < %s -loop-reduce -S | not grep INDVAR +; RUN: opt < %s -loop-reduce -S -default-data-layout="e-p:32:32:32" | not grep INDVAR declare i1 @pred() diff --git a/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll b/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll index c91f5cd4ca..8959c17740 100644 --- a/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll +++ b/test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -analyze -iv-users | grep {Stride i64 {3,+,2}<%loop>:} +; RUN: opt < %s -analyze -iv-users | grep {\{1,+,3,+,2\}<%loop> (post-inc)} ; The value of %r is dependent on a polynomial iteration expression. diff --git a/test/Transforms/LoopStrengthReduce/remove_indvar.ll b/test/Transforms/LoopStrengthReduce/remove_indvar.ll index 53f4b9d5b9..bb395324d4 100644 --- a/test/Transforms/LoopStrengthReduce/remove_indvar.ll +++ b/test/Transforms/LoopStrengthReduce/remove_indvar.ll @@ -7,10 +7,12 @@ define void @test(i32* %P) { ;