aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEd Schouten <ed@FreeBSD.org>2009-06-22 08:08:12 +0000
committerEd Schouten <ed@FreeBSD.org>2009-06-22 08:08:12 +0000
commitb2f21fb044b6b5c52cff6227f9f79ca4ed42b18f (patch)
tree86c1bc482baa6c81fc70b8d715153bfa93377186
parent600c6fa13de5c407dc36dbb0ab73807868741ae0 (diff)
downloadsrc-b2f21fb044b6b5c52cff6227f9f79ca4ed42b18f.tar.gz
src-b2f21fb044b6b5c52cff6227f9f79ca4ed42b18f.zip
Update LLVM sources to r73879.vendor/llvm/llvm-r73879
Notes
Notes: svn path=/vendor/llvm/dist/; revision=194612 svn path=/vendor/llvm/llvm-r73879/; revision=194614; tag=vendor/llvm/llvm-r73879
-rw-r--r--CMakeLists.txt29
-rw-r--r--Makefile2
-rw-r--r--Makefile.rules80
-rw-r--r--autoconf/configure.ac36
-rwxr-xr-xcmake/config-ix.cmake44
-rwxr-xr-xconfigure201
-rw-r--r--docs/CodeGenerator.html4
-rw-r--r--docs/CommandLine.html19
-rw-r--r--docs/CompilerDriver.html121
-rw-r--r--docs/CompilerDriverTutorial.html21
-rw-r--r--docs/DeveloperPolicy.html4
-rw-r--r--docs/LangRef.html24
-rw-r--r--docs/MakefileGuide.html20
-rw-r--r--docs/ProgrammersManual.html138
-rw-r--r--docs/WritingAnLLVMPass.html4
-rw-r--r--examples/BrainF/BrainFDriver.cpp3
-rw-r--r--examples/HowToUseJIT/HowToUseJIT.cpp4
-rw-r--r--examples/Kaleidoscope/toy.cpp3
-rw-r--r--examples/ParallelJIT/ParallelJIT.cpp6
-rw-r--r--include/llvm/ADT/PostOrderIterator.h7
-rw-r--r--include/llvm/ADT/Triple.h1
-rw-r--r--include/llvm/Analysis/IVUsers.h23
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h110
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpressions.h67
-rw-r--r--include/llvm/CallingConv.h13
-rw-r--r--include/llvm/CodeGen/FastISel.h1
-rw-r--r--include/llvm/CodeGen/LiveInterval.h148
-rw-r--r--include/llvm/CodeGen/MachineFunction.h2
-rw-r--r--include/llvm/CodeGen/MachineInstr.h4
-rw-r--r--include/llvm/CodeGen/MachineOperand.h18
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h29
-rw-r--r--include/llvm/CodeGen/RuntimeLibcalls.h4
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h2
-rw-r--r--include/llvm/Config/AsmPrinters.def.in29
-rw-r--r--include/llvm/Config/Targets.def.in28
-rw-r--r--include/llvm/Config/config.h.cmake3
-rw-r--r--include/llvm/Config/config.h.in6
-rw-r--r--include/llvm/Constants.h34
-rw-r--r--include/llvm/DerivedTypes.h4
-rw-r--r--include/llvm/MC/MCInst.h125
-rw-r--r--include/llvm/Support/CommandLine.h4
-rw-r--r--include/llvm/Support/DebugLoc.h (renamed from include/llvm/CodeGen/DebugLoc.h)12
-rw-r--r--include/llvm/Support/IRBuilder.h8
-rw-r--r--include/llvm/Support/ManagedStatic.h16
-rw-r--r--include/llvm/Support/SourceMgr.h (renamed from utils/TableGen/TGSourceMgr.h)68
-rw-r--r--include/llvm/System/Atomic.h2
-rw-r--r--include/llvm/System/Mutex.h80
-rw-r--r--include/llvm/System/Path.h5
-rw-r--r--include/llvm/System/RWMutex.h175
-rw-r--r--include/llvm/System/Threading.h45
-rw-r--r--include/llvm/Target/DarwinTargetAsmInfo.h2
-rw-r--r--include/llvm/Target/Target.td1
-rw-r--r--include/llvm/Target/TargetAsmInfo.h26
-rw-r--r--include/llvm/Target/TargetLowering.h2
-rw-r--r--include/llvm/Target/TargetMachine.h8
-rw-r--r--include/llvm/Target/TargetRegisterInfo.h30
-rw-r--r--include/llvm/Target/TargetSelect.h65
-rw-r--r--include/llvm/Transforms/Scalar.h8
-rw-r--r--include/llvm/Transforms/Utils/Local.h10
-rw-r--r--include/llvm/Type.h36
-rw-r--r--lib/Analysis/ConstantFolding.cpp4
-rw-r--r--lib/Analysis/DebugInfo.cpp2
-rw-r--r--lib/Analysis/IVUsers.cpp47
-rw-r--r--lib/Analysis/ScalarEvolution.cpp811
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp20
-rw-r--r--lib/Analysis/ValueTracking.cpp35
-rw-r--r--lib/AsmParser/LLLexer.cpp4
-rw-r--r--lib/AsmParser/LLParser.cpp16
-rw-r--r--lib/AsmParser/LLToken.h4
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp11
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp29
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp22
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfPrinter.cpp4
-rw-r--r--lib/CodeGen/IfConversion.cpp13
-rw-r--r--lib/CodeGen/LazyLiveness.cpp19
-rw-r--r--lib/CodeGen/LiveInterval.cpp60
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp65
-rw-r--r--lib/CodeGen/LiveVariables.cpp13
-rw-r--r--lib/CodeGen/MachineRegisterInfo.cpp2
-rw-r--r--lib/CodeGen/PreAllocSplitting.cpp42
-rw-r--r--lib/CodeGen/RegAllocLinearScan.cpp57
-rw-r--r--lib/CodeGen/RegAllocPBQP.cpp5
-rw-r--r--lib/CodeGen/SelectionDAG/FastISel.cpp3
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp47
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp7
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp8
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp18
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.cpp160
-rw-r--r--lib/CodeGen/SimpleRegisterCoalescing.h8
-rw-r--r--lib/CodeGen/Spiller.cpp156
-rw-r--r--lib/CodeGen/Spiller.h11
-rw-r--r--lib/CodeGen/StrongPHIElimination.cpp11
-rw-r--r--lib/CodeGen/VirtRegMap.cpp16
-rw-r--r--lib/CodeGen/VirtRegMap.h8
-rw-r--r--lib/ExecutionEngine/ExecutionEngineBindings.cpp2
-rw-r--r--lib/Support/CMakeLists.txt1
-rw-r--r--lib/Support/ManagedStatic.cpp24
-rw-r--r--lib/Support/SourceMgr.cpp (renamed from utils/TableGen/TGSourceMgr.cpp)52
-rw-r--r--lib/Support/Triple.cpp5
-rw-r--r--lib/System/Atomic.cpp28
-rw-r--r--lib/System/CMakeLists.txt2
-rw-r--r--lib/System/Mutex.cpp20
-rw-r--r--lib/System/RWMutex.cpp175
-rw-r--r--lib/System/Threading.cpp63
-rw-r--r--lib/System/Unix/Mutex.inc10
-rw-r--r--lib/System/Unix/Path.inc8
-rw-r--r--lib/System/Unix/RWMutex.inc43
-rw-r--r--lib/System/Unix/Unix.h9
-rw-r--r--lib/System/Win32/Mutex.inc10
-rw-r--r--lib/System/Win32/Path.inc18
-rw-r--r--lib/System/Win32/RWMutex.inc58
-rw-r--r--lib/Target/ARM/ARM.td94
-rw-r--r--lib/Target/ARM/ARMCallingConv.td27
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp4
-rw-r--r--lib/Target/ARM/ARMISelDAGToDAG.cpp40
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp62
-rw-r--r--lib/Target/ARM/ARMISelLowering.h1
-rw-r--r--lib/Target/ARM/ARMInstrInfo.cpp8
-rw-r--r--lib/Target/ARM/ARMInstrInfo.td32
-rw-r--r--lib/Target/ARM/ARMInstrThumb.td5
-rw-r--r--lib/Target/ARM/ARMInstrThumb2.td196
-rw-r--r--lib/Target/ARM/ARMLoadStoreOptimizer.cpp300
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.cpp344
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.h37
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.td4
-rw-r--r--lib/Target/ARM/ARMSchedule.td35
-rw-r--r--lib/Target/ARM/ARMScheduleV6.td22
-rw-r--r--lib/Target/ARM/ARMSubtarget.cpp5
-rw-r--r--lib/Target/ARM/ARMSubtarget.h16
-rw-r--r--lib/Target/ARM/ARMTargetAsmInfo.cpp91
-rw-r--r--lib/Target/ARM/ARMTargetAsmInfo.h3
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp13
-rw-r--r--lib/Target/ARM/ARMTargetMachine.h18
-rw-r--r--lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp44
-rw-r--r--lib/Target/Alpha/AlphaISelLowering.cpp2
-rw-r--r--lib/Target/Alpha/AlphaTargetMachine.cpp34
-rw-r--r--lib/Target/Alpha/AlphaTargetMachine.h20
-rw-r--r--lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp14
-rw-r--r--lib/Target/CBackend/CBackend.cpp16
-rw-r--r--lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp23
-rw-r--r--lib/Target/CellSPU/SPUISelLowering.cpp19
-rw-r--r--lib/Target/CellSPU/SPUTargetAsmInfo.cpp3
-rw-r--r--lib/Target/CellSPU/SPUTargetMachine.cpp21
-rw-r--r--lib/Target/CellSPU/SPUTargetMachine.h18
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp5
-rw-r--r--lib/Target/DarwinTargetAsmInfo.cpp47
-rw-r--r--lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp15
-rw-r--r--lib/Target/IA64/IA64ISelLowering.cpp4
-rw-r--r--lib/Target/IA64/IA64TargetMachine.cpp23
-rw-r--r--lib/Target/IA64/IA64TargetMachine.h18
-rw-r--r--lib/Target/MSIL/MSILWriter.cpp5
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.cpp5
-rw-r--r--lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp14
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp2
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp14
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h15
-rw-r--r--lib/Target/PIC16/PIC16AsmPrinter.cpp39
-rw-r--r--lib/Target/PIC16/PIC16AsmPrinter.h2
-rw-r--r--lib/Target/PIC16/PIC16DebugInfo.cpp446
-rw-r--r--lib/Target/PIC16/PIC16DebugInfo.h53
-rw-r--r--lib/Target/PIC16/PIC16ISelLowering.cpp66
-rw-r--r--lib/Target/PIC16/PIC16TargetMachine.cpp5
-rw-r--r--lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp28
-rw-r--r--lib/Target/PowerPC/PPCTargetAsmInfo.cpp46
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.cpp5
-rw-r--r--lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp18
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.cpp21
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.h12
-rw-r--r--lib/Target/TargetAsmInfo.cpp13
-rw-r--r--lib/Target/X86/AsmPrinter/CMakeLists.txt1
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp320
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.h58
-rw-r--r--lib/Target/X86/AsmPrinter/X86ATTInstPrinter.cpp143
-rw-r--r--lib/Target/X86/AsmPrinter/X86AsmPrinter.cpp14
-rw-r--r--lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.cpp57
-rw-r--r--lib/Target/X86/AsmPrinter/X86IntelAsmPrinter.h3
-rw-r--r--lib/Target/X86/README.txt45
-rw-r--r--lib/Target/X86/X86FloatingPoint.cpp9
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp28
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp15
-rw-r--r--lib/Target/X86/X86Instr64bit.td33
-rw-r--r--lib/Target/X86/X86InstrInfo.td113
-rw-r--r--lib/Target/X86/X86InstrSSE.td6
-rw-r--r--lib/Target/X86/X86RegisterInfo.cpp27
-rw-r--r--lib/Target/X86/X86Subtarget.h2
-rw-r--r--lib/Target/X86/X86TargetAsmInfo.cpp62
-rw-r--r--lib/Target/X86/X86TargetMachine.cpp5
-rw-r--r--lib/Target/XCore/XCoreAsmPrinter.cpp6
-rw-r--r--lib/Target/XCore/XCoreTargetAsmInfo.cpp3
-rw-r--r--lib/Target/XCore/XCoreTargetMachine.cpp5
-rw-r--r--lib/Transforms/IPO/CMakeLists.txt1
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp5
-rw-r--r--lib/Transforms/IPO/PartialInlining.cpp5
-rw-r--r--lib/Transforms/IPO/RaiseAllocations.cpp4
-rw-r--r--lib/Transforms/Instrumentation/RSProfiling.cpp12
-rw-r--r--lib/Transforms/Scalar/CodeGenPrepare.cpp4
-rw-r--r--lib/Transforms/Scalar/GVN.cpp29
-rw-r--r--lib/Transforms/Scalar/IndVarSimplify.cpp13
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp394
-rw-r--r--lib/Transforms/Scalar/JumpThreading.cpp94
-rw-r--r--lib/Transforms/Scalar/LoopIndexSplit.cpp4
-rw-r--r--lib/Transforms/Scalar/LoopStrengthReduce.cpp151
-rw-r--r--lib/Transforms/Scalar/ScalarReplAggregates.cpp6
-rw-r--r--lib/Transforms/Scalar/SimplifyLibCalls.cpp93
-rw-r--r--lib/Transforms/Scalar/TailRecursionElimination.cpp16
-rw-r--r--lib/Transforms/Utils/Local.cpp45
-rw-r--r--lib/Transforms/Utils/LowerAllocations.cpp2
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp29
-rw-r--r--lib/VMCore/AsmWriter.cpp13
-rw-r--r--lib/VMCore/ConstantFold.cpp48
-rw-r--r--lib/VMCore/Constants.cpp330
-rw-r--r--lib/VMCore/Function.cpp8
-rw-r--r--lib/VMCore/Instructions.cpp87
-rw-r--r--lib/VMCore/LeakDetector.cpp60
-rw-r--r--lib/VMCore/Mangler.cpp9
-rw-r--r--lib/VMCore/Pass.cpp22
-rw-r--r--lib/VMCore/PassManager.cpp8
-rw-r--r--lib/VMCore/Type.cpp268
-rw-r--r--lib/VMCore/TypeSymbolTable.cpp29
-rw-r--r--lib/VMCore/Value.cpp16
-rw-r--r--lib/VMCore/Verifier.cpp20
-rw-r--r--test/Analysis/ScalarEvolution/2007-07-15-NegativeStride.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2007-08-06-Unsigned.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2007-09-27-LargeStepping.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2007-11-18-OrInstruction.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-02-11-ReversedCondition.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-02-12-SMAXTripCount.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-02-15-UMax.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-05-25-NegativeStepToZero.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect1.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-07-12-UnneededSelect2.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-07-19-InfiniteLoop.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-07-19-WrappingIV.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-11-02-QuadraticCrash.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-11-15-CubicOOM.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-11-18-LessThanOrEqual.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-11-18-Stride1.ll7
-rw-r--r--test/Analysis/ScalarEvolution/2008-11-18-Stride2.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-12-08-FiniteSGE.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-12-11-SMaxOverflow.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-12-14-StrideAndSigned.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2008-12-15-DontUseSDiv.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2009-01-02-SignedNegativeStride.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2009-04-22-TruncCast.ll2
-rw-r--r--test/Analysis/ScalarEvolution/2009-05-09-PointerEdgeCount.ll2
-rw-r--r--test/Analysis/ScalarEvolution/SolveQuadraticEquation.ll2
-rw-r--r--test/Analysis/ScalarEvolution/avoid-smax-0.ll2
-rw-r--r--test/Analysis/ScalarEvolution/do-loop.ll2
-rw-r--r--test/Analysis/ScalarEvolution/smax.ll4
-rw-r--r--test/Analysis/ScalarEvolution/trip-count.ll2
-rw-r--r--test/Analysis/ScalarEvolution/trip-count2.ll2
-rw-r--r--test/Analysis/ScalarEvolution/trip-count3.ll6
-rw-r--r--test/Analysis/ScalarEvolution/trip-count5.ll48
-rw-r--r--test/Analysis/ScalarEvolution/xor-and.ll12
-rw-r--r--test/CodeGen/ARM/2009-06-15-RegScavengerAssert.ll344
-rw-r--r--test/CodeGen/ARM/2009-06-18-ThumbCommuteMul.ll8
-rw-r--r--test/CodeGen/ARM/2009-06-19-RegScavengerAssert.ll30
-rw-r--r--test/CodeGen/ARM/ifcvt9.ll12
-rw-r--r--test/CodeGen/ARM/ldrd.ll14
-rw-r--r--test/CodeGen/ARM/stm.ll2
-rw-r--r--test/CodeGen/ARM/thumb2-add.ll50
-rw-r--r--test/CodeGen/ARM/thumb2-mov.ll127
-rw-r--r--test/CodeGen/ARM/thumb2-mov2.ll65
-rw-r--r--test/CodeGen/ARM/thumb2-shifter.ll40
-rw-r--r--test/CodeGen/ARM/vargs2.ll4
-rw-r--r--test/CodeGen/CellSPU/mul-with-overflow.ll15
-rw-r--r--test/CodeGen/PowerPC/mul-with-overflow.ll15
-rw-r--r--test/CodeGen/X86/2009-06-15-not-a-tail-call.ll14
-rw-r--r--test/CodeGen/X86/2009-06-18-movlp-shuffle-register.ll9
-rw-r--r--test/CodeGen/X86/fmul-zero.ll2
-rw-r--r--test/CodeGen/X86/inline-asm-fpstack2.ll10
-rw-r--r--test/CodeGen/X86/iv-users-in-other-loops.ll10
-rw-r--r--test/CodeGen/X86/optimize-max-0.ll (renamed from test/CodeGen/X86/optimize-smax.ll)229
-rw-r--r--test/CodeGen/X86/optimize-max-1.ll78
-rw-r--r--test/CodeGen/X86/optimize-max-2.ll30
-rw-r--r--test/CodeGen/X86/pic_jumptable.ll2
-rw-r--r--test/CodeGen/X86/tls1-pic.ll2
-rw-r--r--test/CodeGen/X86/tls1.ll2
-rw-r--r--test/CodeGen/X86/tls2-pic.ll4
-rw-r--r--test/CodeGen/X86/tls3-pic.ll2
-rw-r--r--test/CodeGen/X86/tls4-pic.ll2
-rw-r--r--test/CodeGen/X86/umul-with-overflow.ll8
-rw-r--r--test/DebugInfo/2009-06-15-InlineFuncStart.ll77
-rw-r--r--test/DebugInfo/2009-06-15-abstract_origin.ll275
-rw-r--r--test/Feature/vector-cast-constant-exprs.ll37
-rw-r--r--test/FrontendC++/2009-06-16-DebugInfoCrash.cpp10
-rw-r--r--test/FrontendC++/2009-06-20-DarwinPPCLayout.cpp32
-rw-r--r--test/FrontendC/2009-06-14-HighlyAligned.c8
-rw-r--r--test/FrontendC/2009-06-18-StaticInitTailPadPack.c26
-rw-r--r--test/Transforms/ConstProp/2009-06-20-constexpr-zero-lhs.ll11
-rw-r--r--test/Transforms/ConstProp/div-zero.ll12
-rw-r--r--test/Transforms/GVN/2009-06-17-InvalidPRE.ll72
-rw-r--r--test/Transforms/GVN/pre-single-pred.ll9
-rw-r--r--test/Transforms/IndVarSimplify/ashr-tripcount.ll107
-rw-r--r--test/Transforms/IndVarSimplify/loop_evaluate_6.ll6
-rw-r--r--test/Transforms/IndVarSimplify/masked-iv.ll4
-rw-r--r--test/Transforms/IndVarSimplify/pointer.ll38
-rw-r--r--test/Transforms/IndVarSimplify/shrunk-constant.ll15
-rw-r--r--test/Transforms/InstCombine/2009-06-11-StoreAddrSpace.ll2
-rw-r--r--test/Transforms/InstCombine/2009-06-16-SRemDemandedBits.ll9
-rw-r--r--test/Transforms/InstCombine/select-load-call.ll15
-rw-r--r--test/Transforms/InstCombine/trunc-mask-ext.ll38
-rw-r--r--test/Transforms/InstCombine/vector-casts-0.ll55
-rw-r--r--test/Transforms/InstCombine/vector-casts-1.ll15
-rw-r--r--test/Transforms/JumpThreading/branch-no-const.ll21
-rw-r--r--test/Transforms/JumpThreading/dup-cond.ll30
-rw-r--r--test/Transforms/LoopStrengthReduce/quadradic-exit-value.ll18
-rw-r--r--test/Transforms/SimplifyCFG/2009-06-15-InvokeCrash.ll557
-rw-r--r--test/Transforms/SimplifyLibCalls/2008-12-20-StrcmpMemcmp.ll10
-rw-r--r--test/Transforms/TailCallElim/dont_reorder_load.ll64
-rw-r--r--test/Transforms/TailCallElim/reorder_load.ll101
-rw-r--r--tools/CMakeLists.txt1
-rw-r--r--tools/Makefile3
-rw-r--r--tools/gold/gold-plugin.cpp17
-rw-r--r--tools/llc/llc.cpp4
-rw-r--r--tools/lli/lli.cpp5
-rw-r--r--tools/llvm-mc/AsmLexer.cpp258
-rw-r--r--tools/llvm-mc/AsmLexer.h109
-rw-r--r--tools/llvm-mc/AsmParser.cpp351
-rw-r--r--tools/llvm-mc/AsmParser.h48
-rw-r--r--tools/llvm-mc/CMakeLists.txt7
-rw-r--r--tools/llvm-mc/Makefile17
-rw-r--r--tools/llvm-mc/llvm-mc.cpp161
-rw-r--r--tools/llvmc/doc/LLVMC-Reference.rst76
-rw-r--r--tools/llvmc/doc/LLVMC-Tutorial.rst21
-rw-r--r--tools/llvmc/driver/Makefile4
-rw-r--r--tools/lto/LTOCodeGenerator.cpp23
-rwxr-xr-xutils/NewNightlyTest.pl58
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp6
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp6
-rw-r--r--utils/TableGen/Record.h18
-rw-r--r--utils/TableGen/TGLexer.cpp44
-rw-r--r--utils/TableGen/TGLexer.h20
-rw-r--r--utils/TableGen/TGParser.cpp40
-rw-r--r--utils/TableGen/TGParser.h18
-rw-r--r--utils/TableGen/TableGen.cpp16
337 files changed, 11233 insertions, 2598 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2e2cf358e413..543ee7f88079 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -81,14 +81,23 @@ if( LLVM_TARGETS_TO_BUILD STREQUAL "all" )
set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} )
endif()
+set(LLVM_ENUM_TARGETS "")
foreach(c ${LLVM_TARGETS_TO_BUILD})
list(FIND LLVM_ALL_TARGETS ${c} idx)
if( idx LESS 0 )
message(FATAL_ERROR "The target `${c}' does not exists.
It should be one of\n${LLVM_ALL_TARGETS}")
+ else()
+ set(LLVM_ENUM_TARGETS "${LLVM_ENUM_TARGETS}LLVM_TARGET(${c})\n")
endif()
endforeach(c)
+# Produce llvm/Config/Targets.def
+configure_file(
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/Targets.def.in
+ ${LLVM_BINARY_DIR}/include/llvm/Config/Targets.def
+ )
+
set(llvm_builded_incs_dir ${LLVM_BINARY_DIR}/include/llvm)
# The USE_EXPLICIT_DEPENDENCIES variable will be TRUE to indicate that
@@ -250,14 +259,23 @@ add_subdirectory(lib/Linker)
add_subdirectory(lib/Analysis)
add_subdirectory(lib/Analysis/IPA)
-foreach(t ${LLVM_TARGETS_TO_BUILD})
+ set(LLVM_ENUM_ASM_PRINTERS "")
+ foreach(t ${LLVM_TARGETS_TO_BUILD})
message(STATUS "Targeting ${t}")
add_subdirectory(lib/Target/${t})
if( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmPrinter/CMakeLists.txt )
- add_subdirectory(lib/Target/${t}/AsmPrinter)
- endif( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmPrinter/CMakeLists.txt )
+ add_subdirectory(lib/Target/${t}/AsmPrinter)
+ set(LLVM_ENUM_ASM_PRINTERS
+ "${LLVM_ENUM_ASM_PRINTERS}LLVM_ASM_PRINTER(${t})\n")
+ endif( EXISTS ${LLVM_MAIN_SRC_DIR}/lib/Target/${t}/AsmPrinter/CMakeLists.txt )
endforeach(t)
+# Produce llvm/Config/AsmPrinters.def
+configure_file(
+ ${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/AsmPrinters.def.in
+ ${LLVM_BINARY_DIR}/include/llvm/Config/AsmPrinters.def
+ )
+
add_subdirectory(lib/ExecutionEngine)
add_subdirectory(lib/ExecutionEngine/Interpreter)
add_subdirectory(lib/ExecutionEngine/JIT)
@@ -269,7 +287,10 @@ add_subdirectory(lib/Archive)
add_subdirectory(projects)
add_subdirectory(tools)
-add_subdirectory(examples)
+option(LLVM_EXAMPLES "Build LLVM example programs." OFF)
+if (LLVM_EXAMPLES)
+ add_subdirectory(examples)
+endif ()
install(DIRECTORY include
DESTINATION .
diff --git a/Makefile b/Makefile
index 123595dc55ec..e750889ae45c 100644
--- a/Makefile
+++ b/Makefile
@@ -134,6 +134,8 @@ install-libs: install
#------------------------------------------------------------------------
FilesToConfig := \
include/llvm/Config/config.h \
+ include/llvm/Config/Targets.def \
+ include/llvm/Config/AsmPrinters.def \
include/llvm/Support/DataTypes.h \
include/llvm/ADT/iterator.h
FilesToConfigPATH := $(addprefix $(LLVM_OBJ_ROOT)/,$(FilesToConfig))
diff --git a/Makefile.rules b/Makefile.rules
index 4a77bf536dff..9325ca4b5d1b 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -287,10 +287,8 @@ endif
ifdef ENABLE_COVERAGE
BuildMode := $(BuildMode)+Coverage
- # These only go to .NoRelink because otherwise we will end up
- # linking -lgcov into the .o libraries that get built.
- CXX.Flags.NoRelink += -ftest-coverage -fprofile-arcs
- C.Flags.NoRelink += -ftest-coverage -fprofile-arcs
+ CXX.Flags += -ftest-coverage -fprofile-arcs
+ C.Flags += -ftest-coverage -fprofile-arcs
endif
# If DISABLE_ASSERTIONS=1 is specified (make command line or configured),
@@ -315,7 +313,6 @@ endif
# defined/on.
ifdef LOADABLE_MODULE
SHARED_LIBRARY := 1
- DONT_BUILD_RELINKED := 1
LINK_LIBS_IN_SHARED := 1
endif
@@ -522,10 +519,10 @@ endif
#----------------------------------------------------------
ifndef NO_PEDANTIC
-CompileCommonOpts += -pedantic
+CompileCommonOpts += -pedantic -Wno-long-long
endif
-CompileCommonOpts += -Wall -W -Wwrite-strings -Wno-long-long \
- -Wunused -Wno-unused-parameter $(EXTRA_OPTIONS)
+CompileCommonOpts += -Wall -W -Wno-unused-parameter -Wwrite-strings \
+ $(EXTRA_OPTIONS)
ifeq ($(OS),HP-UX)
CompileCommonOpts := -D_REENTRANT -D_HPUX_SOURCE
@@ -548,10 +545,8 @@ ifdef UNIVERSAL
endif
UNIVERSAL_ARCH_OPTIONS := $(UNIVERSAL_ARCH:%=-arch %)
CompileCommonOpts += $(UNIVERSAL_ARCH_OPTIONS)
- Relink.Flags := $(UNIVERSAL_ARCH_OPTIONS)
ifdef UNIVERSAL_SDK_PATH
CompileCommonOpts += -isysroot $(UNIVERSAL_SDK_PATH)
- Relink.Flags += -isysroot $(UNIVERSAL_SDK_PATH)
endif
# Building universal cannot compute dependencies automatically.
@@ -582,27 +577,23 @@ CPP.Flags += $(sort -I$(PROJ_OBJ_DIR) -I$(PROJ_SRC_DIR) \
$(CPP.BaseFlags)
ifeq ($(BUILD_COMPONENT), 1)
- Compile.C = $(BUILD_CC) $(CPP.Flags) $(C.Flags) $(C.Flags.NoRelink) \
+ Compile.C = $(BUILD_CC) $(CPP.Flags) $(C.Flags) \
$(TargetCommonOpts) $(CompileCommonOpts) -c
- Compile.CXX = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXX.Flags.NoRelink) \
+ Compile.CXX = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) \
$(TargetCommonOpts) $(CompileCommonOpts) -c
Preprocess.CXX= $(BUILD_CXX) $(CPP.Flags) $(TargetCommonOpts) \
- $(CompileCommonOpts) $(CXX.Flags) $(CXX.Flags.NoRelink) -E
- Link = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXX.Flags.NoRelink) \
+ $(CompileCommonOpts) $(CXX.Flags) -E
+ Link = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) \
$(TargetCommonOpts) $(CompileCommonOpts) $(LD.Flags) $(Strip)
- Relink = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(TargetCommonOpts) \
- $(CompileCommonOpts) $(Relink.Flags)
else
- Compile.C = $(CC) $(CPP.Flags) $(C.Flags) $(C.Flags.NoRelink) \
+ Compile.C = $(CC) $(CPP.Flags) $(C.Flags) \
$(TargetCommonOpts) $(CompileCommonOpts) -c
- Compile.CXX = $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXX.Flags.NoRelink) \
+ Compile.CXX = $(CXX) $(CPP.Flags) $(CXX.Flags) \
$(TargetCommonOpts) $(CompileCommonOpts) -c
Preprocess.CXX= $(CXX) $(CPP.Flags) $(TargetCommonOpts) \
- $(CompileCommonOpts) $(CXX.Flags) $(CXX.Flags.NoRelink) -E
- Link = $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXX.Flags.NoRelink) \
+ $(CompileCommonOpts) $(CXX.Flags) -E
+ Link = $(CXX) $(CPP.Flags) $(CXX.Flags) \
$(TargetCommonOpts) $(CompileCommonOpts) $(LD.Flags) $(Strip)
- Relink = $(CXX) $(CPP.Flags) $(CXX.Flags) $(TargetCommonOpts) \
- $(CompileCommonOpts) $(Relink.Flags)
endif
BCCompile.C = $(LLVMGCCWITHPATH) $(CPP.Flags) $(C.Flags) \
@@ -1048,48 +1039,13 @@ endif
endif
#---------------------------------------------------------
-# ReLinked Library Targets:
-# If the user explicitly requests a relinked library with
-# BUILD_RELINKED, provide it. Otherwise, if they specify
-# neither of BUILD_ARCHIVE or DONT_BUILD_RELINKED, give
-# them one.
+# Library Targets:
+# If neither BUILD_ARCHIVE or LOADABLE_MODULE are specified, default to
+# building an archive.
#---------------------------------------------------------
ifndef BUILD_ARCHIVE
-ifndef DONT_BUILD_RELINKED
-BUILD_RELINKED = 1
-endif
-endif
-
-ifdef BUILD_RELINKED
-
-all-local:: $(LibName.O)
-
-$(LibName.O): $(ObjectsO) $(LibDir)/.dir
- $(Echo) Linking $(BuildMode) Object Library $(notdir $@)
- $(Verb) $(Relink) -r -nodefaultlibs -nostdlib -nostartfiles -o $@ $(ObjectsO)
-
-clean-local::
-ifneq ($(strip $(LibName.O)),)
- -$(Verb) $(RM) -f $(LibName.O)
-endif
-
-ifdef NO_INSTALL
-install-local::
- $(Echo) Install circumvented with NO_INSTALL
-uninstall-local::
- $(Echo) Uninstall circumvented with NO_INSTALL
-else
-DestRelinkedLib = $(PROJ_libdir)/$(LIBRARYNAME).o
-
-install-local:: $(DestRelinkedLib)
-
-$(DestRelinkedLib): $(LibName.O) $(PROJ_libdir)
- $(Echo) Installing $(BuildMode) Object Library $(DestRelinkedLib)
- $(Verb) $(INSTALL) $(LibName.O) $(DestRelinkedLib)
-
-uninstall-local::
- $(Echo) Uninstalling $(BuildMode) Object Library $(DestRelinkedLib)
- -$(Verb) $(RM) -f $(DestRelinkedLib)
+ifndef LOADABLE_MODULE
+BUILD_ARCHIVE = 1
endif
endif
diff --git a/autoconf/configure.ac b/autoconf/configure.ac
index 64b78a49eb6d..bd05891a9dc7 100644
--- a/autoconf/configure.ac
+++ b/autoconf/configure.ac
@@ -234,6 +234,13 @@ if test "$llvm_cv_target_arch" = "Unknown" ; then
AC_MSG_WARN([Configuring LLVM for an unknown target archicture])
fi
+# Determine the LLVM native architecture for the target
+case "$llvm_cv_target_arch" in
+ x86) LLVM_NATIVE_ARCH="X86" ;;
+ x86_64) LLVM_NATIVE_ARCH="X86" ;;
+ *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;;
+esac
+
dnl Define a substitution, ARCH, for the target architecture
AC_SUBST(ARCH,$llvm_cv_target_arch)
@@ -436,6 +443,28 @@ case "$enableval" in
esac
AC_SUBST(TARGETS_TO_BUILD,$TARGETS_TO_BUILD)
+# Determine whether we are building LLVM support for the native architecture.
+# If so, define LLVM_NATIVE_ARCH to that LLVM target.
+for a_target in $TARGETS_TO_BUILD; do
+ if test "$a_target" = "$LLVM_NATIVE_ARCH"; then
+ AC_DEFINE_UNQUOTED(LLVM_NATIVE_ARCH,$LLVM_NATIVE_ARCH,
+ [LLVM architecture name for the native architecture, if available])
+ fi
+done
+
+# Build the LLVM_TARGET and LLVM_ASM_PRINTER macro uses for
+# Targets.def and AsmPrinters.def.
+LLVM_ENUM_TARGETS=""
+LLVM_ENUM_ASM_PRINTERS=""
+for target_to_build in $TARGETS_TO_BUILD; do
+ LLVM_ENUM_TARGETS="LLVM_TARGET($target_to_build) $LLVM_ENUM_TARGETS"
+ if test -f ${srcdir}/lib/Target/${target_to_build}/AsmPrinter/Makefile ; then
+ LLVM_ENUM_ASM_PRINTERS="LLVM_ASM_PRINTER($target_to_build) $LLVM_ENUM_ASM_PRINTERS";
+ fi
+done
+AC_SUBST(LLVM_ENUM_TARGETS)
+AC_SUBST(LLVM_ENUM_ASM_PRINTERS)
+
dnl Prevent the CBackend from using printf("%a") for floating point so older
dnl C compilers that cannot deal with the 0x0p+0 hex floating point format
dnl can still compile the CBE's output
@@ -796,6 +825,9 @@ if test "$ENABLE_THREADS" -eq 1 ; then
AC_SEARCH_LIBS(pthread_mutex_lock,pthread,
AC_DEFINE([HAVE_PTHREAD_MUTEX_LOCK],[1],
[Have pthread_mutex_lock]))
+ AC_SEARCH_LIBS(pthread_rwlock_init,pthread,
+ AC_DEFINE([HAVE_PTHREAD_RWLOCK_INIT],[1],
+ [Have pthread_rwlock_init]))
fi
dnl Allow extra x86-disassembler library
@@ -919,6 +951,8 @@ AC_LINK_IFELSE(
volatile unsigned long val = 1;
__sync_synchronize();
__sync_val_compare_and_swap(&val, 1, 0);
+ __sync_add_and_fetch(&val, 1);
+ __sync_sub_and_fetch(&val, 1);
return 0;
}
]]),
@@ -1108,6 +1142,8 @@ dnl you MUST also update Makefile.rules so that the variable FilesToConfig
dnl contains the same list of files as AC_CONFIG_HEADERS below. This ensures the
dnl files can be updated automatically when their *.in sources change.
AC_CONFIG_HEADERS([include/llvm/Config/config.h])
+AC_CONFIG_FILES([include/llvm/Config/Targets.def])
+AC_CONFIG_FILES([include/llvm/Config/AsmPrinters.def])
AC_CONFIG_HEADERS([include/llvm/Support/DataTypes.h])
AC_CONFIG_HEADERS([include/llvm/ADT/iterator.h])
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index c18ac44172f9..c460fa2aa058 100755
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -78,6 +78,50 @@ include(GetTargetTriple)
get_target_triple(LLVM_HOSTTRIPLE)
message(STATUS "LLVM_HOSTTRIPLE: ${LLVM_HOSTTRIPLE}")
+# Determine the native architecture.
+# FIXME: this will have to change for cross-compiling.
+string(REGEX MATCH "^[^-]*" LLVM_NATIVE_ARCH ${LLVM_HOSTTRIPLE})
+if (LLVM_NATIVE_ARCH MATCHES "i[2-6]86")
+ set(LLVM_NATIVE_ARCH X86)
+elseif (LLVM_NATIVE_ARCH STREQUAL amd64)
+ set(LLVM_NATIVE_ARCH X86)
+elseif (LLVM_NATIVE_ARCH STREQUAL x86_64)
+ set(LLVM_NATIVE_ARCH X86)
+elseif (LLVM_NATIVE_ARCH MATCHES "sparc")
+ set(LLVM_NATIVE_ARCH Sparc)
+elseif (LLVM_NATIVE_ARCH MATCHES "powerpc")
+ set(LLVM_NATIVE_ARCH PowerPC)
+elseif (LLVM_NATIVE_ARCH MATCHES "alpha")
+ set(LLVM_NATIVE_ARCH Alpha)
+elseif (LLVM_NATIVE_ARCH MATCHES "ia64")
+ set(LLVM_NATIVE_ARCH IA64)
+elseif (LLVM_NATIVE_ARCH MATCHES "arm")
+ set(LLVM_NATIVE_ARCH ARM)
+elseif (LLVM_NATIVE_ARCH MATCHES "mips")
+ set(LLVM_NATIVE_ARCH Mips)
+elseif (LLVM_NATIVE_ARCH MATCHES "pic16")
+ set(LLVM_NATIVE_ARCH "PIC16")
+elseif (LLVM_NATIVE_ARCH MATCHES "xcore")
+ set(LLVM_NATIVE_ARCH XCore)
+elseif (LLVM_NATIVE_ARCH MATCHES "msp430")
+ set(LLVM_NATIVE_ARCH MSP430)
+else ()
+ message(STATUS
+ "Unknown architecture ${LLVM_NATIVE_ARCH}; lli will not JIT code")
+ set(LLVM_NATIVE_ARCH)
+endif ()
+
+if (LLVM_NATIVE_ARCH)
+ list(FIND LLVM_TARGETS_TO_BUILD ${LLVM_NATIVE_ARCH} NATIVE_ARCH_IDX)
+ if (NATIVE_ARCH_IDX EQUAL -1)
+ message(STATUS
+ "Native target ${LLVM_NATIVE_ARCH} is not selected; lli will not JIT code")
+ set(LLVM_NATIVE_ARCH)
+ else ()
+ message(STATUS "Native target architecture is ${LLVM_NATIVE_ARCH}")
+ endif ()
+endif()
+
if( MINGW )
set(HAVE_LIBIMAGEHLP 1)
set(HAVE_LIBPSAPI 1)
diff --git a/configure b/configure
index 9a30c297cd37..3c9925153abe 100755
--- a/configure
+++ b/configure
@@ -841,6 +841,8 @@ ENABLE_DOXYGEN
ENABLE_THREADS
ENABLE_PIC
TARGETS_TO_BUILD
+LLVM_ENUM_TARGETS
+LLVM_ENUM_ASM_PRINTERS
ENABLE_CBE_PRINTF_A
EXTRA_OPTIONS
BINUTILS_INCDIR
@@ -2401,6 +2403,13 @@ if test "$llvm_cv_target_arch" = "Unknown" ; then
echo "$as_me: WARNING: Configuring LLVM for an unknown target archicture" >&2;}
fi
+# Determine the LLVM native architecture for the target
+case "$llvm_cv_target_arch" in
+ x86) LLVM_NATIVE_ARCH="X86" ;;
+ x86_64) LLVM_NATIVE_ARCH="X86" ;;
+ *) LLVM_NATIVE_ARCH="$llvm_cv_target_arch" ;;
+esac
+
ARCH=$llvm_cv_target_arch
@@ -4959,6 +4968,31 @@ esac
TARGETS_TO_BUILD=$TARGETS_TO_BUILD
+# Determine whether we are building LLVM support for the native architecture.
+# If so, define LLVM_NATIVE_ARCH to that LLVM target.
+for a_target in $TARGETS_TO_BUILD; do
+ if test "$a_target" = "$LLVM_NATIVE_ARCH"; then
+
+cat >>confdefs.h <<_ACEOF
+#define LLVM_NATIVE_ARCH $LLVM_NATIVE_ARCH
+_ACEOF
+
+ fi
+done
+
+# Build the LLVM_TARGET and LLVM_ASM_PRINTER macro uses for
+# Targets.def and AsmPrinters.def.
+LLVM_ENUM_TARGETS=""
+LLVM_ENUM_ASM_PRINTERS=""
+for target_to_build in $TARGETS_TO_BUILD; do
+ LLVM_ENUM_TARGETS="LLVM_TARGET($target_to_build) $LLVM_ENUM_TARGETS"
+ if test -f ${srcdir}/lib/Target/${target_to_build}/AsmPrinter/Makefile ; then
+ LLVM_ENUM_ASM_PRINTERS="LLVM_ASM_PRINTER($target_to_build) $LLVM_ENUM_ASM_PRINTERS";
+ fi
+done
+
+
+
# Check whether --enable-cbe-printf-a was given.
if test "${enable_cbe_printf_a+set}" = set; then
enableval=$enable_cbe_printf_a;
@@ -10594,7 +10628,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 10597 "configure"
+#line 10631 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12738,7 +12772,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
- echo '#line 12741 "configure"' > conftest.$ac_ext
+ echo '#line 12775 "configure"' > conftest.$ac_ext
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -14456,11 +14490,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14459: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14493: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:14463: \$? = $ac_status" >&5
+ echo "$as_me:14497: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -14724,11 +14758,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14727: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14761: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:14731: \$? = $ac_status" >&5
+ echo "$as_me:14765: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -14828,11 +14862,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:14831: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:14865: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:14835: \$? = $ac_status" >&5
+ echo "$as_me:14869: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -17280,7 +17314,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 17283 "configure"
+#line 17317 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -17380,7 +17414,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<EOF
-#line 17383 "configure"
+#line 17417 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -19748,11 +19782,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:19751: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:19785: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:19755: \$? = $ac_status" >&5
+ echo "$as_me:19789: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -19852,11 +19886,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:19855: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:19889: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:19859: \$? = $ac_status" >&5
+ echo "$as_me:19893: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -21422,11 +21456,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:21425: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:21459: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:21429: \$? = $ac_status" >&5
+ echo "$as_me:21463: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -21526,11 +21560,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:21529: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:21563: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:21533: \$? = $ac_status" >&5
+ echo "$as_me:21567: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -23761,11 +23795,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:23764: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:23798: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:23768: \$? = $ac_status" >&5
+ echo "$as_me:23802: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -24029,11 +24063,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:24032: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:24066: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
- echo "$as_me:24036: \$? = $ac_status" >&5
+ echo "$as_me:24070: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -24133,11 +24167,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
- (eval echo "\"\$as_me:24136: $lt_compile\"" >&5)
+ (eval echo "\"\$as_me:24170: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
- echo "$as_me:24140: \$? = $ac_status" >&5
+ echo "$as_me:24174: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -27896,6 +27930,109 @@ _ACEOF
fi
+ { echo "$as_me:$LINENO: checking for library containing pthread_rwlock_init" >&5
+echo $ECHO_N "checking for library containing pthread_rwlock_init... $ECHO_C" >&6; }
+if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_rwlock_init ();
+int
+main ()
+{
+return pthread_rwlock_init ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' pthread; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_search_pthread_rwlock_init=$ac_res
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then
+ break
+fi
+done
+if test "${ac_cv_search_pthread_rwlock_init+set}" = set; then
+ :
+else
+ ac_cv_search_pthread_rwlock_init=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_search_pthread_rwlock_init" >&5
+echo "${ECHO_T}$ac_cv_search_pthread_rwlock_init" >&6; }
+ac_res=$ac_cv_search_pthread_rwlock_init
+if test "$ac_res" != no; then
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTHREAD_RWLOCK_INIT 1
+_ACEOF
+
+fi
+
fi
@@ -33642,6 +33779,8 @@ int main() {
volatile unsigned long val = 1;
__sync_synchronize();
__sync_val_compare_and_swap(&val, 1, 0);
+ __sync_add_and_fetch(&val, 1);
+ __sync_sub_and_fetch(&val, 1);
return 0;
}
@@ -34120,6 +34259,10 @@ fi
ac_config_headers="$ac_config_headers include/llvm/Config/config.h"
+ac_config_files="$ac_config_files include/llvm/Config/Targets.def"
+
+ac_config_files="$ac_config_files include/llvm/Config/AsmPrinters.def"
+
ac_config_headers="$ac_config_headers include/llvm/Support/DataTypes.h"
ac_config_headers="$ac_config_headers include/llvm/ADT/iterator.h"
@@ -34746,6 +34889,8 @@ for ac_config_target in $ac_config_targets
do
case $ac_config_target in
"include/llvm/Config/config.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Config/config.h" ;;
+ "include/llvm/Config/Targets.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/Targets.def" ;;
+ "include/llvm/Config/AsmPrinters.def") CONFIG_FILES="$CONFIG_FILES include/llvm/Config/AsmPrinters.def" ;;
"include/llvm/Support/DataTypes.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/Support/DataTypes.h" ;;
"include/llvm/ADT/iterator.h") CONFIG_HEADERS="$CONFIG_HEADERS include/llvm/ADT/iterator.h" ;;
"Makefile.config") CONFIG_FILES="$CONFIG_FILES Makefile.config" ;;
@@ -34914,6 +35059,8 @@ ENABLE_DOXYGEN!$ENABLE_DOXYGEN$ac_delim
ENABLE_THREADS!$ENABLE_THREADS$ac_delim
ENABLE_PIC!$ENABLE_PIC$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
ENABLE_CBE_PRINTF_A!$ENABLE_CBE_PRINTF_A$ac_delim
EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim
BINUTILS_INCDIR!$BINUTILS_INCDIR$ac_delim
@@ -34924,8 +35071,6 @@ NM!$NM$ac_delim
ifGNUmake!$ifGNUmake$ac_delim
LN_S!$LN_S$ac_delim
CMP!$CMP$ac_delim
-CP!$CP$ac_delim
-DATE!$DATE$ac_delim
_ACEOF
if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then
@@ -34967,6 +35112,8 @@ _ACEOF
ac_delim='%!_!# '
for ac_last_try in false false false false false :; do
cat >conf$$subs.sed <<_ACEOF
+CP!$CP$ac_delim
+DATE!$DATE$ac_delim
FIND!$FIND$ac_delim
MKDIR!$MKDIR$ac_delim
MV!$MV$ac_delim
@@ -35048,7 +35195,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` = 79; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 81; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html
index 7fada98278d4..25101fc31bf6 100644
--- a/docs/CodeGenerator.html
+++ b/docs/CodeGenerator.html
@@ -1773,6 +1773,8 @@ define fastcc i32 @tailcaller(i32 %in1, i32 %in2) {
<li><b>i386-pc-mingw32msvc</b> &mdash; MingW crosscompiler on Linux</li>
<li><b>i686-apple-darwin*</b> &mdash; Apple Darwin on X86</li>
+
+ <li><b>x86_64-unknown-linux-gnu</b> &mdash; Linux</li>
</ul>
</div>
@@ -2116,7 +2118,7 @@ MOVSX32rm16 -&gt; movsx, 32-bit register, 16-bit memory
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2009-05-13 23:33:08 +0200 (Wed, 13 May 2009) $
+ Last modified: $Date: 2009-06-15 12:17:44 +0000 (Mon, 15 Jun 2009) $
</address>
</body>
diff --git a/docs/CommandLine.html b/docs/CommandLine.html
index c4e567b43020..d6cf48ce5111 100644
--- a/docs/CommandLine.html
+++ b/docs/CommandLine.html
@@ -1116,9 +1116,9 @@ command-line parser sees <b><tt>cl::init</tt></b>, it knows where to put the
initial value. (You will get an error at runtime if you don't put them in
the right order.)</li>
-<li><a name="cl::location">The <b><tt>cl::location</tt></b></a> attribute where to
-store the value for a parsed command line option if using external storage. See
-the section on <a href="#storage">Internal vs External Storage</a> for more
+<li><a name="cl::location">The <b><tt>cl::location</tt></b></a> attribute where
+to store the value for a parsed command line option if using external storage.
+See the section on <a href="#storage">Internal vs External Storage</a> for more
information.</li>
<li><a name="cl::aliasopt">The <b><tt>cl::aliasopt</tt></b></a> attribute
@@ -1146,6 +1146,11 @@ specify macro options where the option name doesn't equal the enum name. For
this macro, the first argument is the enum value, the second is the flag name,
and the second is the description.</li>
+</ol>
+
+You will get a compile time error if you try to use cl::values with a parser
+that does not support it.</li>
+
<li><a name="cl::multi_val">The <b><tt>cl::multi_val</tt></b></a>
attribute specifies that this option takes has multiple values
(example: <tt>-sectalign segname sectname sectvalue</tt>). This
@@ -1156,12 +1161,6 @@ types). It is allowed to use all of the usual modifiers on
multi-valued options (besides <tt>cl::ValueDisallowed</tt>,
obviously).</li>
-
-</ol>
-
-You will get a compile time error if you try to use cl::values with a parser
-that does not support it.</li>
-
</ul>
</div>
@@ -1973,7 +1972,7 @@ tutorial.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2009-04-08 05:43:51 +0200 (Wed, 08 Apr 2009) $
+ Last modified: $Date: 2009-06-17 03:09:39 +0000 (Wed, 17 Jun 2009) $
</address>
</body>
diff --git a/docs/CompilerDriver.html b/docs/CompilerDriver.html
index ab436974b531..5b42148bdb3b 100644
--- a/docs/CompilerDriver.html
+++ b/docs/CompilerDriver.html
@@ -21,21 +21,22 @@ The ReST source lives in the directory 'tools/llvmc/doc'. -->
<li><a class="reference internal" href="#compiling-with-llvmc" id="id5">Compiling with LLVMC</a></li>
<li><a class="reference internal" href="#predefined-options" id="id6">Predefined options</a></li>
<li><a class="reference internal" href="#compiling-llvmc-plugins" id="id7">Compiling LLVMC plugins</a></li>
-<li><a class="reference internal" href="#customizing-llvmc-the-compilation-graph" id="id8">Customizing LLVMC: the compilation graph</a></li>
-<li><a class="reference internal" href="#describing-options" id="id9">Describing options</a><ul>
-<li><a class="reference internal" href="#external-options" id="id10">External options</a></li>
+<li><a class="reference internal" href="#compiling-standalone-llvmc-based-drivers" id="id8">Compiling standalone LLVMC-based drivers</a></li>
+<li><a class="reference internal" href="#customizing-llvmc-the-compilation-graph" id="id9">Customizing LLVMC: the compilation graph</a></li>
+<li><a class="reference internal" href="#describing-options" id="id10">Describing options</a><ul>
+<li><a class="reference internal" href="#external-options" id="id11">External options</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#conditional-evaluation" id="id11">Conditional evaluation</a></li>
-<li><a class="reference internal" href="#writing-a-tool-description" id="id12">Writing a tool description</a><ul>
-<li><a class="reference internal" href="#actions" id="id13">Actions</a></li>
+<li><a class="reference internal" href="#conditional-evaluation" id="id12">Conditional evaluation</a></li>
+<li><a class="reference internal" href="#writing-a-tool-description" id="id13">Writing a tool description</a><ul>
+<li><a class="reference internal" href="#actions" id="id14">Actions</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#language-map" id="id14">Language map</a></li>
-<li><a class="reference internal" href="#more-advanced-topics" id="id15">More advanced topics</a><ul>
-<li><a class="reference internal" href="#hooks-and-environment-variables" id="id16">Hooks and environment variables</a></li>
-<li><a class="reference internal" href="#how-plugins-are-loaded" id="id17">How plugins are loaded</a></li>
-<li><a class="reference internal" href="#debugging" id="id18">Debugging</a></li>
+<li><a class="reference internal" href="#language-map" id="id15">Language map</a></li>
+<li><a class="reference internal" href="#more-advanced-topics" id="id16">More advanced topics</a><ul>
+<li><a class="reference internal" href="#hooks-and-environment-variables" id="id17">Hooks and environment variables</a></li>
+<li><a class="reference internal" href="#how-plugins-are-loaded" id="id18">How plugins are loaded</a></li>
+<li><a class="reference internal" href="#debugging" id="id19">Debugging</a></li>
</ul>
</li>
</ul>
@@ -56,7 +57,7 @@ abstract graph. The structure of this graph is completely determined
by plugins, which can be either statically or dynamically linked. This
makes it possible to easily adapt LLVMC for other purposes - for
example, as a build tool for game resources.</p>
-<p>Because LLVMC employs <a class="reference external" href="http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html">TableGen</a> as its configuration language, you
+<p>Because LLVMC employs <a class="reference external" href="http://llvm.org/docs/TableGenFundamentals.html">TableGen</a> as its configuration language, you
need to be familiar with it to customize LLVMC.</p>
</div>
<div class="section" id="compiling-with-llvmc">
@@ -70,12 +71,12 @@ $ llvmc -O3 -Wall hello.cpp
$ ./a.out
hello
</pre>
-<p>One nice feature of LLVMC is that one doesn't have to distinguish
-between different compilers for different languages (think <tt class="docutils literal"><span class="pre">g++</span></tt> and
-<tt class="docutils literal"><span class="pre">gcc</span></tt>) - the right toolchain is chosen automatically based on input
-language names (which are, in turn, determined from file
-extensions). If you want to force files ending with &quot;.c&quot; to compile as
-C++, use the <tt class="docutils literal"><span class="pre">-x</span></tt> option, just like you would do it with <tt class="docutils literal"><span class="pre">gcc</span></tt>:</p>
+<p>One nice feature of LLVMC is that one doesn't have to distinguish between
+different compilers for different languages (think <tt class="docutils literal"><span class="pre">g++</span></tt> vs. <tt class="docutils literal"><span class="pre">gcc</span></tt>) - the
+right toolchain is chosen automatically based on input language names (which
+are, in turn, determined from file extensions). If you want to force files
+ending with &quot;.c&quot; to compile as C++, use the <tt class="docutils literal"><span class="pre">-x</span></tt> option, just like you would
+do it with <tt class="docutils literal"><span class="pre">gcc</span></tt>:</p>
<pre class="literal-block">
$ # hello.c is really a C++ file
$ llvmc -x c++ hello.c
@@ -110,16 +111,17 @@ until the next -x option.</li>
<li><tt class="docutils literal"><span class="pre">-v</span></tt> - Enable verbose mode, i.e. print out all executed commands.</li>
<li><tt class="docutils literal"><span class="pre">--check-graph</span></tt> - Check the compilation for common errors like mismatched
output/input language names, multiple default edges and cycles. Because of
-plugins, these checks can't be performed at compile-time. Exit with code zero if
-no errors were found, and return the number of found errors otherwise. Hidden
-option, useful for debugging LLVMC plugins.</li>
+plugins, these checks can't be performed at compile-time. Exit with code zero
+if no errors were found, and return the number of found errors
+otherwise. Hidden option, useful for debugging LLVMC plugins.</li>
<li><tt class="docutils literal"><span class="pre">--view-graph</span></tt> - Show a graphical representation of the compilation graph
and exit. Requires that you have <tt class="docutils literal"><span class="pre">dot</span></tt> and <tt class="docutils literal"><span class="pre">gv</span></tt> programs installed. Hidden
option, useful for debugging LLVMC plugins.</li>
<li><tt class="docutils literal"><span class="pre">--write-graph</span></tt> - Write a <tt class="docutils literal"><span class="pre">compilation-graph.dot</span></tt> file in the current
directory with the compilation graph description in Graphviz format (identical
-to the file used by the <tt class="docutils literal"><span class="pre">--view-graph</span></tt> option). The <tt class="docutils literal"><span class="pre">-o</span></tt> option can be used
-to set the output file name. Hidden option, useful for debugging LLVMC plugins.</li>
+to the file used by the <tt class="docutils literal"><span class="pre">--view-graph</span></tt> option). The <tt class="docutils literal"><span class="pre">-o</span></tt> option can be
+used to set the output file name. Hidden option, useful for debugging LLVMC
+plugins.</li>
<li><tt class="docutils literal"><span class="pre">--save-temps</span></tt> - Write temporary files to the current directory
and do not delete them on exit. Hidden option, useful for debugging.</li>
<li><tt class="docutils literal"><span class="pre">--help</span></tt>, <tt class="docutils literal"><span class="pre">--help-hidden</span></tt>, <tt class="docutils literal"><span class="pre">--version</span></tt> - These options have
@@ -154,33 +156,58 @@ generic:</p>
<pre class="literal-block">
$ mv Simple.td MyPlugin.td
</pre>
-<p>Note that the plugin source directory must be placed under
-<tt class="docutils literal"><span class="pre">$LLVMC_DIR/plugins</span></tt> to make use of the existing build
-infrastructure. To build a version of the LLVMC executable called
-<tt class="docutils literal"><span class="pre">mydriver</span></tt> with your plugin compiled in, use the following command:</p>
-<pre class="literal-block">
-$ cd $LLVMC_DIR
-$ make BUILTIN_PLUGINS=MyPlugin DRIVER_NAME=mydriver
-</pre>
<p>To build your plugin as a dynamic library, just <tt class="docutils literal"><span class="pre">cd</span></tt> to its source
directory and run <tt class="docutils literal"><span class="pre">make</span></tt>. The resulting file will be called
-<tt class="docutils literal"><span class="pre">LLVMC$(LLVMC_PLUGIN).$(DLL_EXTENSION)</span></tt> (in our case,
-<tt class="docutils literal"><span class="pre">LLVMCMyPlugin.so</span></tt>). This library can be then loaded in with the
+<tt class="docutils literal"><span class="pre">plugin_llvmc_$(LLVMC_PLUGIN).$(DLL_EXTENSION)</span></tt> (in our case,
+<tt class="docutils literal"><span class="pre">plugin_llvmc_MyPlugin.so</span></tt>). This library can be then loaded in with the
<tt class="docutils literal"><span class="pre">-load</span></tt> option. Example:</p>
<pre class="literal-block">
$ cd $LLVMC_DIR/plugins/Simple
$ make
-$ llvmc -load $LLVM_DIR/Release/lib/LLVMCSimple.so
+$ llvmc -load $LLVM_DIR/Release/lib/plugin_llvmc_Simple.so
+</pre>
+</div>
+<div class="section" id="compiling-standalone-llvmc-based-drivers">
+<h1><a class="toc-backref" href="#id8">Compiling standalone LLVMC-based drivers</a></h1>
+<p>By default, the <tt class="docutils literal"><span class="pre">llvmc</span></tt> executable consists of a driver core plus several
+statically linked plugins (<tt class="docutils literal"><span class="pre">Base</span></tt> and <tt class="docutils literal"><span class="pre">Clang</span></tt> at the moment). You can
+produce a standalone LLVMC-based driver executable by linking the core with your
+own plugins. The recommended way to do this is by starting with the provided
+<tt class="docutils literal"><span class="pre">Skeleton</span></tt> example (<tt class="docutils literal"><span class="pre">$LLVMC_DIR/example/Skeleton</span></tt>):</p>
+<pre class="literal-block">
+$ cd $LLVMC_DIR/example/
+$ cp -r Skeleton mydriver
+$ cd mydriver
+$ vim Makefile
+[...]
+$ make
+</pre>
+<p>If you're compiling LLVM with different source and object directories, then you
+must perform the following additional steps before running <tt class="docutils literal"><span class="pre">make</span></tt>:</p>
+<pre class="literal-block">
+# LLVMC_SRC_DIR = $LLVM_SRC_DIR/tools/llvmc/
+# LLVMC_OBJ_DIR = $LLVM_OBJ_DIR/tools/llvmc/
+$ cp $LLVMC_SRC_DIR/example/mydriver/Makefile \
+ $LLVMC_OBJ_DIR/example/mydriver/
+$ cd $LLVMC_OBJ_DIR/example/mydriver
+$ make
+</pre>
+<p>Another way to do the same thing is by using the following command:</p>
+<pre class="literal-block">
+$ cd $LLVMC_DIR
+$ make LLVMC_BUILTIN_PLUGINS=MyPlugin LLVMC_BASED_DRIVER_NAME=mydriver
</pre>
+<p>This works with both srcdir == objdir and srcdir != objdir, but assumes that the
+plugin source directory was placed under <tt class="docutils literal"><span class="pre">$LLVMC_DIR/plugins</span></tt>.</p>
<p>Sometimes, you will want a 'bare-bones' version of LLVMC that has no
built-in plugins. It can be compiled with the following command:</p>
<pre class="literal-block">
$ cd $LLVMC_DIR
-$ make BUILTIN_PLUGINS=&quot;&quot;
+$ make LLVMC_BUILTIN_PLUGINS=&quot;&quot;
</pre>
</div>
<div class="section" id="customizing-llvmc-the-compilation-graph">
-<h1><a class="toc-backref" href="#id8">Customizing LLVMC: the compilation graph</a></h1>
+<h1><a class="toc-backref" href="#id9">Customizing LLVMC: the compilation graph</a></h1>
<p>Each TableGen configuration file should include the common
definitions:</p>
<pre class="literal-block">
@@ -248,7 +275,7 @@ debugging), run <tt class="docutils literal"><span class="pre">llvmc</span> <spa
<tt class="docutils literal"><span class="pre">gsview</span></tt> installed for this to work properly.</p>
</div>
<div class="section" id="describing-options">
-<h1><a class="toc-backref" href="#id9">Describing options</a></h1>
+<h1><a class="toc-backref" href="#id10">Describing options</a></h1>
<p>Command-line options that the plugin supports are defined by using an
<tt class="docutils literal"><span class="pre">OptionList</span></tt>:</p>
<pre class="literal-block">
@@ -317,7 +344,7 @@ the <tt class="docutils literal"><span class="pre">one_or_more</span></tt> and <
</li>
</ul>
<div class="section" id="external-options">
-<h2><a class="toc-backref" href="#id10">External options</a></h2>
+<h2><a class="toc-backref" href="#id11">External options</a></h2>
<p>Sometimes, when linking several plugins together, one plugin needs to
access options defined in some other plugin. Because of the way
options are implemented, such options must be marked as
@@ -332,7 +359,7 @@ for. Example:</p>
</div>
</div>
<div class="section" id="conditional-evaluation">
-<span id="case"></span><h1><a class="toc-backref" href="#id11">Conditional evaluation</a></h1>
+<span id="case"></span><h1><a class="toc-backref" href="#id12">Conditional evaluation</a></h1>
<p>The 'case' construct is the main means by which programmability is
achieved in LLVMC. It can be used to calculate edge weights, program
actions and modify the shell commands to be executed. The 'case'
@@ -412,7 +439,7 @@ one of its arguments returns true. Example: <tt class="docutils literal"><span c
</ul>
</div>
<div class="section" id="writing-a-tool-description">
-<h1><a class="toc-backref" href="#id12">Writing a tool description</a></h1>
+<h1><a class="toc-backref" href="#id13">Writing a tool description</a></h1>
<p>As was said earlier, nodes in the compilation graph represent tools,
which are described separately. A tool definition looks like this
(taken from the <tt class="docutils literal"><span class="pre">include/llvm/CompilerDriver/Tools.td</span></tt> file):</p>
@@ -454,7 +481,7 @@ below).</li>
</li>
</ul>
<div class="section" id="actions">
-<h2><a class="toc-backref" href="#id13">Actions</a></h2>
+<h2><a class="toc-backref" href="#id14">Actions</a></h2>
<p>A tool often needs to react to command-line options, and this is
precisely what the <tt class="docutils literal"><span class="pre">actions</span></tt> property is for. The next example
illustrates this feature:</p>
@@ -515,7 +542,7 @@ Example: <tt class="docutils literal"><span class="pre">(unpack_values</span> <s
</div>
</div>
<div class="section" id="language-map">
-<h1><a class="toc-backref" href="#id14">Language map</a></h1>
+<h1><a class="toc-backref" href="#id15">Language map</a></h1>
<p>If you are adding support for a new language to LLVMC, you'll need to
modify the language map, which defines mappings from file extensions
to language names. It is used to choose the proper toolchain(s) for a
@@ -538,9 +565,9 @@ multiple output languages, for nodes &quot;inside&quot; the graph the input and
output languages should match. This is enforced at compile-time.</p>
</div>
<div class="section" id="more-advanced-topics">
-<h1><a class="toc-backref" href="#id15">More advanced topics</a></h1>
+<h1><a class="toc-backref" href="#id16">More advanced topics</a></h1>
<div class="section" id="hooks-and-environment-variables">
-<span id="hooks"></span><h2><a class="toc-backref" href="#id16">Hooks and environment variables</a></h2>
+<span id="hooks"></span><h2><a class="toc-backref" href="#id17">Hooks and environment variables</a></h2>
<p>Normally, LLVMC executes programs from the system <tt class="docutils literal"><span class="pre">PATH</span></tt>. Sometimes,
this is not sufficient: for example, we may want to specify tool paths
or names in the configuration file. This can be easily achieved via
@@ -573,7 +600,7 @@ the <tt class="docutils literal"><span class="pre">case</span></tt> expression (
</pre>
</div>
<div class="section" id="how-plugins-are-loaded">
-<span id="priorities"></span><h2><a class="toc-backref" href="#id17">How plugins are loaded</a></h2>
+<span id="priorities"></span><h2><a class="toc-backref" href="#id18">How plugins are loaded</a></h2>
<p>It is possible for LLVMC plugins to depend on each other. For example,
one can create edges between nodes defined in some other plugin. To
make this work, however, that plugin should be loaded first. To
@@ -589,7 +616,7 @@ with 0. Therefore, the plugin with the highest priority value will be
loaded last.</p>
</div>
<div class="section" id="debugging">
-<h2><a class="toc-backref" href="#id18">Debugging</a></h2>
+<h2><a class="toc-backref" href="#id19">Debugging</a></h2>
<p>When writing LLVMC plugins, it can be useful to get a visual view of
the resulting compilation graph. This can be achieved via the command
line option <tt class="docutils literal"><span class="pre">--view-graph</span></tt>. This command assumes that <a class="reference external" href="http://www.graphviz.org/">Graphviz</a> and
@@ -615,7 +642,7 @@ errors as its status code.</p>
<a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
-Last modified: $Date: 2009-05-06 03:41:47 +0200 (Wed, 06 May 2009) $
+Last modified: $Date: 2009-06-17 02:56:48 +0000 (Wed, 17 Jun 2009) $
</address></div>
</div>
</div>
diff --git a/docs/CompilerDriverTutorial.html b/docs/CompilerDriverTutorial.html
index a57801737957..317b1d127127 100644
--- a/docs/CompilerDriverTutorial.html
+++ b/docs/CompilerDriverTutorial.html
@@ -48,23 +48,28 @@ command-line LLVMC usage, refer to the <tt class="docutils literal"><span class=
</div>
<div class="section" id="using-llvmc-to-generate-toolchain-drivers">
<h1><a class="toc-backref" href="#id3">Using LLVMC to generate toolchain drivers</a></h1>
-<p>LLVMC plugins are written mostly using <a class="reference external" href="http://llvm.cs.uiuc.edu/docs/TableGenFundamentals.html">TableGen</a>, so you need to
+<p>LLVMC plugins are written mostly using <a class="reference external" href="http://llvm.org/docs/TableGenFundamentals.html">TableGen</a>, so you need to
be familiar with it to get anything done.</p>
-<p>Start by compiling <tt class="docutils literal"><span class="pre">plugins/Simple/Simple.td</span></tt>, which is a primitive
-wrapper for <tt class="docutils literal"><span class="pre">gcc</span></tt>:</p>
+<p>Start by compiling <tt class="docutils literal"><span class="pre">example/Simple</span></tt>, which is a primitive wrapper for
+<tt class="docutils literal"><span class="pre">gcc</span></tt>:</p>
<pre class="literal-block">
$ cd $LLVM_DIR/tools/llvmc
-$ make DRIVER_NAME=mygcc BUILTIN_PLUGINS=Simple
+$ cp -r example/Simple plugins/Simple
+
+ # NB: A less verbose way to compile standalone LLVMC-based drivers is
+ # described in the reference manual.
+
+$ make LLVMC_BASED_DRIVER_NAME=mygcc LLVMC_BUILTIN_PLUGINS=Simple
$ cat &gt; hello.c
[...]
$ mygcc hello.c
$ ./hello.out
Hello
</pre>
-<p>Here we link our plugin with the LLVMC core statically to form an
-executable file called <tt class="docutils literal"><span class="pre">mygcc</span></tt>. It is also possible to build our
-plugin as a standalone dynamic library; this is described in the
-reference manual.</p>
+<p>Here we link our plugin with the LLVMC core statically to form an executable
+file called <tt class="docutils literal"><span class="pre">mygcc</span></tt>. It is also possible to build our plugin as a dynamic
+library to be loaded by the <tt class="docutils literal"><span class="pre">llvmc</span></tt> executable (or any other LLVMC-based
+standalone driver); this is described in the reference manual.</p>
<p>Contents of the file <tt class="docutils literal"><span class="pre">Simple.td</span></tt> look like this:</p>
<pre class="literal-block">
// Include common definitions
diff --git a/docs/DeveloperPolicy.html b/docs/DeveloperPolicy.html
index 34d201810d00..13a908e5a9d3 100644
--- a/docs/DeveloperPolicy.html
+++ b/docs/DeveloperPolicy.html
@@ -108,7 +108,7 @@
<li>Patches should be made with this command:
<div class="doc_code">
<pre>
-svn diff -x -u
+svn diff
</pre>
</div>
or with the utility <tt>utils/mkpatch</tt>, which makes it easy to read
@@ -592,7 +592,7 @@ Changes</a></div>
Written by the
<a href="mailto:llvm-oversight@cs.uiuc.edu">LLVM Oversight Group</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2009-04-05 14:38:44 +0200 (Sun, 05 Apr 2009) $
+ Last modified: $Date: 2009-06-15 04:18:54 +0000 (Mon, 15 Jun 2009) $
</address>
</body>
</html>
diff --git a/docs/LangRef.html b/docs/LangRef.html
index 897654df9569..f229150ea300 100644
--- a/docs/LangRef.html
+++ b/docs/LangRef.html
@@ -1106,8 +1106,9 @@ an <tt>ssp</tt> attribute, then the resulting function will have
an <tt>sspreq</tt> attribute.</dd>
<dt><tt>noredzone</tt></dt>
-<dd>This attribute indicates that the code generator should not enforce red zone
-mandated by target specific ABI.</dd>
+<dd>This attribute indicates that the code generator should not use a
+red zone, even if the target-specific ABI normally permits it.
+</dd>
<dt><tt>noimplicitfloat</tt></dt>
<dd>This attributes disables implicit floating point instructions.</dd>
@@ -3531,9 +3532,10 @@ address space (address space zero).</p>
bytes of memory from the operating system and returns a pointer of the
appropriate type to the program. If "NumElements" is specified, it is the
number of elements allocated, otherwise "NumElements" is defaulted to be one.
-If a constant alignment is specified, the value result of the allocation is guaranteed to
-be aligned to at least that boundary. If not specified, or if zero, the target can
-choose to align the allocation on any convenient boundary.</p>
+If a constant alignment is specified, the value result of the allocation is
+guaranteed to be aligned to at least that boundary. If not specified, or if
+zero, the target can choose to align the allocation on any convenient boundary
+compatible with the type.</p>
<p>'<tt>type</tt>' must be a sized type.</p>
@@ -3624,9 +3626,10 @@ space (address space zero).</p>
bytes of memory on the runtime stack, returning a pointer of the
appropriate type to the program. If "NumElements" is specified, it is the
number of elements allocated, otherwise "NumElements" is defaulted to be one.
-If a constant alignment is specified, the value result of the allocation is guaranteed
-to be aligned to at least that boundary. If not specified, or if zero, the target
-can choose to align the allocation on any convenient boundary.</p>
+If a constant alignment is specified, the value result of the allocation is
+guaranteed to be aligned to at least that boundary. If not specified, or if
+zero, the target can choose to align the allocation on any convenient boundary
+compatible with the type.</p>
<p>'<tt>type</tt>' may be any sized type.</p>
@@ -6428,9 +6431,6 @@ on any integer bit width.</p>
<h5>Overview:</h5>
-<p><i><b>Warning:</b> '<tt>llvm.umul.with.overflow</tt>' is badly broken. It is
-actively being fixed, but it should not currently be used!</i></p>
-
<p>The '<tt>llvm.umul.with.overflow</tt>' family of intrinsic functions perform
a unsigned multiplication of the two arguments, and indicate whether an overflow
occurred during the unsigned multiplication.</p>
@@ -7221,7 +7221,7 @@ declare void @llvm.stackprotector( i8* &lt;guard&gt;, i8** &lt;slot&gt; )
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2009-06-12 21:45:19 +0200 (Fri, 12 Jun 2009) $
+ Last modified: $Date: 2009-06-20 13:26:06 +0000 (Sat, 20 Jun 2009) $
</address>
</body>
diff --git a/docs/MakefileGuide.html b/docs/MakefileGuide.html
index a5e78efac807..39a04f7c84d1 100644
--- a/docs/MakefileGuide.html
+++ b/docs/MakefileGuide.html
@@ -232,17 +232,16 @@
Normally, the makefile system will build all the software into a single
<tt>libname.o</tt> (pre-linked) object. This means the library is not
searchable and that the distinction between compilation units has been
- dissolved. Optionally, you can ask for a shared library (.so), archive library
- (.a) or to not have the default (relinked) library built. For example:</p>
+ dissolved. Optionally, you can ask for a shared library (.so) or archive
+ library (.a) built. Archive libraries are the default. For example:</p>
<pre><tt>
LIBRARYNAME = mylib
SHARED_LIBRARY = 1
ARCHIVE_LIBRARY = 1
- DONT_BUILD_RELINKED = 1
</tt></pre>
<p>says to build a library named "mylib" with both a shared library
- (<tt>mylib.so</tt>) and an archive library (<tt>mylib.a</tt>) version but
- not to build the relinked object (<tt>mylib.o</tt>). The contents of all the
+ (<tt>mylib.so</tt>) and an archive library (<tt>mylib.a</tt>) version. The
+ contents of all the
libraries produced will be the same, they are just constructed differently.
Note that you normally do not need to specify the sources involved. The LLVM
Makefile system will infer the source files from the contents of the source
@@ -307,8 +306,6 @@
on.</li>
<li>The <a href="#LINK_LIBS_IN_SHARED">LINK_LIBS_IN_SHARED</a> variable
is turned on.</li>
- <li>The <a href="#DONT_BUILD_RELINKED">DONT_BUILD_RELINKED</a> variable
- is turned on.</li>
</ol>
<p>A loadable module is loaded by LLVM via the facilities of libtool's libltdl
library which is part of <tt>lib/System</tt> implementation.</p>
@@ -637,11 +634,6 @@
<dd>If set to any value, causes the makefiles to <b>not</b> automatically
generate dependencies when running the compiler. Use of this feature is
discouraged and it may be removed at a later date.</dd>
- <dt><a name="DONT_BUILD_RELINKED"><tt>DONT_BUILD_RELINKED</tt></a></dt>
- <dd>If set to any value, causes a relinked library (.o) not to be built. By
- default, libraries are built as re-linked since most LLVM libraries are
- needed in their entirety and re-linked libraries will be linked more quickly
- than equivalent archive libraries.</dd>
<dt><a name="ENABLE_OPTIMIZED"><tt>ENABLE_OPTIMIZED</tt></a></dt>
<dd>If set to any value, causes the build to generate optimized objects,
libraries and executables. This alters the flags specified to the compilers
@@ -960,7 +952,6 @@
DestArchiveLib
DestBitcodeLib
DestModule
- DestRelinkedLib
DestSharedLib
DestTool
DistAlways
@@ -1004,7 +995,6 @@
ProjUsedLibs
Ranlib
RecursiveTargets
- Relink
SrcMakefiles
Strip
StripWarnMsg
@@ -1026,7 +1016,7 @@
<a href="mailto:rspencer@x10sys.com">Reid Spencer</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2009-04-26 00:08:52 +0200 (Sun, 26 Apr 2009) $
+ Last modified: $Date: 2009-06-16 23:00:42 +0000 (Tue, 16 Jun 2009) $
</address>
</body>
</html>
diff --git a/docs/ProgrammersManual.html b/docs/ProgrammersManual.html
index e7b2ad0b80fd..b45a60b7611d 100644
--- a/docs/ProgrammersManual.html
+++ b/docs/ProgrammersManual.html
@@ -2,6 +2,7 @@
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
+ <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>LLVM Programmer's Manual</title>
<link rel="stylesheet" href="llvm.css" type="text/css">
</head>
@@ -129,6 +130,15 @@ with another <tt>Value</tt></a> </li>
</ul>
</li>
+ <li><a href="#threading">Threads and LLVM</a>
+ <ul>
+ <li><a href="#startmultithreaded">Entering and Exiting Multithreaded Mode
+ </a></li>
+ <li><a href="#shutdown">Ending execution with <tt>llvm_shutdown()</tt></a></li>
+ <li><a href="#managedstatic">Lazy initialization with <tt>ManagedStatic</tt></a></li>
+ </ul>
+ </li>
+
<li><a href="#advanced">Advanced Topics</a>
<ul>
<li><a href="#TypeResolve">LLVM Type Resolution</a>
@@ -176,8 +186,9 @@ with another <tt>Value</tt></a> </li>
<p>Written by <a href="mailto:sabre@nondot.org">Chris Lattner</a>,
<a href="mailto:dhurjati@cs.uiuc.edu">Dinakar Dhurjati</a>,
<a href="mailto:ggreif@gmail.com">Gabor Greif</a>,
- <a href="mailto:jstanley@cs.uiuc.edu">Joel Stanley</a> and
- <a href="mailto:rspencer@x10sys.com">Reid Spencer</a></p>
+ <a href="mailto:jstanley@cs.uiuc.edu">Joel Stanley</a>,
+ <a href="mailto:rspencer@x10sys.com">Reid Spencer</a> and
+ <a href="mailto:owen@apple.com">Owen Anderson</a></p>
</div>
<!-- *********************************************************************** -->
@@ -2118,7 +2129,7 @@ FunctionType *ft = TypeBuilder&lt;types::i&lt;8&gt;(types::i&lt;32&gt;*), true&g
<div class="doc_code">
<pre>
-std::vector<const Type*> params;
+std::vector&lt;const Type*&gt; params;
params.push_back(PointerType::getUnqual(Type::Int32Ty));
FunctionType *ft = FunctionType::get(Type::Int8Ty, params, false);
</pre>
@@ -2131,6 +2142,123 @@ comment</a> for more details.</p>
<!-- *********************************************************************** -->
<div class="doc_section">
+ <a name="threading">Threads and LLVM</a>
+</div>
+<!-- *********************************************************************** -->
+
+<div class="doc_text">
+<p>
+This section describes the interaction of the LLVM APIs with multithreading,
+both on the part of client applications, and in the JIT, in the hosted
+application.
+</p>
+
+<p>
+Note that LLVM's support for multithreading is still relatively young. Up
+through version 2.5, the execution of threaded hosted applications was
+supported, but not threaded client access to the APIs. While this use case is
+now supported, clients <em>must</em> adhere to the guidelines specified below to
+ensure proper operation in multithreaded mode.
+</p>
+
+<p>
+Note that, on Unix-like platforms, LLVM requires the presence of GCC's atomic
+intrinsics in order to support threaded operation. If you need a
+multhreading-capable LLVM on a platform without a suitably modern system
+compiler, consider compiling LLVM and LLVM-GCC in single-threaded mode, and
+using the resultant compiler to build a copy of LLVM with multithreading
+support.
+</p>
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsection">
+ <a name="startmultithreaded">Entering and Exiting Multithreaded Mode</a>
+</div>
+
+<div class="doc_text">
+
+<p>
+In order to properly protect its internal data structures while avoiding
+excessive locking overhead in the single-threaded case, the LLVM must intialize
+certain data structures necessary to provide guards around its internals. To do
+so, the client program must invoke <tt>llvm_start_multithreaded()</tt> before
+making any concurrent LLVM API calls. To subsequently tear down these
+structures, use the <tt>llvm_stop_multithreaded()</tt> call. You can also use
+the <tt>llvm_is_multithreaded()</tt> call to check the status of multithreaded
+mode.
+</p>
+
+<p>
+Note that both of these calls must be made <em>in isolation</em>. That is to
+say that no other LLVM API calls may be executing at any time during the
+execution of <tt>llvm_start_multithreaded()</tt> or <tt>llvm_stop_multithreaded
+</tt>. It's is the client's responsibility to enforce this isolation.
+</p>
+
+<p>
+The return value of <tt>llvm_start_multithreaded()</tt> indicates the success or
+failure of the initialization. Failure typically indicates that your copy of
+LLVM was built without multithreading support, typically because GCC atomic
+intrinsics were not found in your system compiler. In this case, the LLVM API
+will not be safe for concurrent calls. However, it <em>will</em> be safe for
+hosting threaded applications in the JIT, though care must be taken to ensure
+that side exits and the like do not accidentally result in concurrent LLVM API
+calls.
+</p>
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsection">
+ <a name="shutdown">Ending Execution with <tt>llvm_shutdown()</tt></a>
+</div>
+
+<div class="doc_text">
+<p>
+When you are done using the LLVM APIs, you should call <tt>llvm_shutdown()</tt>
+to deallocate memory used for internal structures. This will also invoke
+<tt>llvm_stop_multithreaded()</tt> if LLVM is operating in multithreaded mode.
+As such, <tt>llvm_shutdown()</tt> requires the same isolation guarantees as
+<tt>llvm_stop_multithreaded()</tt>.
+</p>
+
+<p>
+Note that, if you use scope-based shutdown, you can use the
+<tt>llvm_shutdown_obj</tt> class, which calls <tt>llvm_shutdown()</tt> in its
+destructor.
+</div>
+
+<!-- ======================================================================= -->
+<div class="doc_subsection">
+ <a name="managedstatic">Lazy Initialization with <tt>ManagedStatic</tt></a>
+</div>
+
+<div class="doc_text">
+<p>
+<tt>ManagedStatic</tt> is a utility class in LLVM used to implement static
+initialization of static resources, such as the global type tables. Before the
+invocation of <tt>llvm_shutdown()</tt>, it implements a simple lazy
+initialization scheme. Once <tt>llvm_start_multithreaded()</tt> returns,
+however, it uses double-checked locking to implement thread-safe lazy
+initialization.
+</p>
+
+<p>
+Note that, because no other threads are allowed to issue LLVM API calls before
+<tt>llvm_start_multithreaded()</tt> returns, it is possible to have
+<tt>ManagedStatic</tt>s of <tt>llvm::sys::Mutex</tt>s.
+</p>
+
+<p>
+The <tt>llvm_acquire_global_lock()</tt> and <tt>llvm_release_global_lock</tt>
+APIs provide access to the global lock used to implement the double-checked
+locking for lazy initialization. These should only be used internally to LLVM,
+and only if you know what you're doing!
+</p>
+</div>
+
+<!-- *********************************************************************** -->
+<div class="doc_section">
<a name="advanced">Advanced Topics</a>
</div>
<!-- *********************************************************************** -->
@@ -3430,7 +3558,7 @@ never change at runtime).</p>
<p><tt>#include "<a
href="/doxygen/BasicBlock_8h-source.html">llvm/BasicBlock.h</a>"</tt><br>
-doxygen info: <a href="/doxygen/structllvm_1_1BasicBlock.html">BasicBlock
+doxygen info: <a href="/doxygen/classllvm_1_1BasicBlock.html">BasicBlock
Class</a><br>
Superclass: <a href="#Value"><tt>Value</tt></a></p>
@@ -3536,7 +3664,7 @@ arguments. An argument has a pointer to the parent Function.</p>
<a href="mailto:dhurjati@cs.uiuc.edu">Dinakar Dhurjati</a> and
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2009-05-01 22:40:51 +0200 (Fri, 01 May 2009) $
+ Last modified: $Date: 2009-06-17 21:12:26 +0000 (Wed, 17 Jun 2009) $
</address>
</body>
diff --git a/docs/WritingAnLLVMPass.html b/docs/WritingAnLLVMPass.html
index a039f619c9da..b1b2c7874ed2 100644
--- a/docs/WritingAnLLVMPass.html
+++ b/docs/WritingAnLLVMPass.html
@@ -1537,7 +1537,7 @@ need some way to free analysis results when they are no longer useful. The
<p>If you are writing an analysis or any other pass that retains a significant
amount of state (for use by another pass which "requires" your pass and uses the
<a href="#getAnalysis">getAnalysis</a> method) you should implement
-<tt>releaseMEmory</tt> to, well, release the memory allocated to maintain this
+<tt>releaseMemory</tt> to, well, release the memory allocated to maintain this
internal state. This method is called after the <tt>run*</tt> method for the
class, before the next call of <tt>run*</tt> in your pass.</p>
@@ -1821,7 +1821,7 @@ Despite that, we have kept the LLVM passes SMP ready, and you should too.</p>
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
- Last modified: $Date: 2009-02-18 06:09:16 +0100 (Wed, 18 Feb 2009) $
+ Last modified: $Date: 2009-06-15 18:22:49 +0000 (Mon, 15 Jun 2009) $
</address>
</body>
diff --git a/examples/BrainF/BrainFDriver.cpp b/examples/BrainF/BrainFDriver.cpp
index 34fb80617722..06e77d2e2a3e 100644
--- a/examples/BrainF/BrainFDriver.cpp
+++ b/examples/BrainF/BrainFDriver.cpp
@@ -34,6 +34,7 @@
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Target/TargetSelect.h"
#include <fstream>
#include <iostream>
using namespace llvm;
@@ -135,6 +136,8 @@ int main(int argc, char **argv) {
//Write it out
if (JIT) {
+ InitializeNativeTarget();
+
std::cout << "------- Running JIT -------\n";
ExistingModuleProvider *mp = new ExistingModuleProvider(mod);
ExecutionEngine *ee = ExecutionEngine::create(mp, false);
diff --git a/examples/HowToUseJIT/HowToUseJIT.cpp b/examples/HowToUseJIT/HowToUseJIT.cpp
index b5c6d111914f..a9f10009e1ec 100644
--- a/examples/HowToUseJIT/HowToUseJIT.cpp
+++ b/examples/HowToUseJIT/HowToUseJIT.cpp
@@ -42,11 +42,15 @@
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/Target/TargetSelect.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
int main() {
+
+ InitializeNativeTarget();
+
// Create some module to put our function into it.
Module *M = new Module("test");
diff --git a/examples/Kaleidoscope/toy.cpp b/examples/Kaleidoscope/toy.cpp
index bec430c41f5a..c75014a69ba4 100644
--- a/examples/Kaleidoscope/toy.cpp
+++ b/examples/Kaleidoscope/toy.cpp
@@ -5,6 +5,7 @@
#include "llvm/PassManager.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetSelect.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/IRBuilder.h"
#include <cstdio>
@@ -1081,6 +1082,8 @@ double printd(double X) {
//===----------------------------------------------------------------------===//
int main() {
+ InitializeNativeTarget();
+
// Install standard binary operators.
// 1 is lowest precedence.
BinopPrecedence['='] = 2;
diff --git a/examples/ParallelJIT/ParallelJIT.cpp b/examples/ParallelJIT/ParallelJIT.cpp
index e812d84eafc8..a6d7dcf7b556 100644
--- a/examples/ParallelJIT/ParallelJIT.cpp
+++ b/examples/ParallelJIT/ParallelJIT.cpp
@@ -26,6 +26,7 @@
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/ExecutionEngine/Interpreter.h"
#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/Target/TargetSelect.h"
#include <iostream>
using namespace llvm;
@@ -229,8 +230,9 @@ void* callFunc( void* param )
return (void*)(intptr_t)gv.IntVal.getZExtValue();
}
-int main()
-{
+int main() {
+ InitializeNativeTarget();
+
// Create some module to put our function into it.
Module *M = new Module("test");
diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h
index bf7ce9d0bb6a..b477d0a8f0f5 100644
--- a/include/llvm/ADT/PostOrderIterator.h
+++ b/include/llvm/ADT/PostOrderIterator.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include <set>
#include <stack>
#include <vector>
@@ -39,9 +40,9 @@ public:
};
template<class GraphT,
- class SetType = std::set<typename GraphTraits<GraphT>::NodeType*>,
- bool ExtStorage = false,
- class GT = GraphTraits<GraphT> >
+ class SetType = llvm::SmallPtrSet<typename GraphTraits<GraphT>::NodeType*, 8>,
+ bool ExtStorage = false,
+ class GT = GraphTraits<GraphT> >
class po_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t>,
public po_iterator_storage<SetType, ExtStorage> {
typedef forward_iterator<typename GT::NodeType, ptrdiff_t> super;
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index b260f984948e..b3f742e0a59b 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -49,6 +49,7 @@ public:
enum OSType {
UnknownOS,
+ AuroraUX,
Darwin,
DragonFly,
FreeBSD,
diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h
index 36ff07b678e6..ac785d5c54a9 100644
--- a/include/llvm/Analysis/IVUsers.h
+++ b/include/llvm/Analysis/IVUsers.h
@@ -35,9 +35,9 @@ class IVStrideUse : public CallbackVH, public ilist_node<IVStrideUse> {
public:
IVStrideUse(IVUsersOfOneStride *parent,
const SCEVHandle &offset,
- Instruction* U, Value *O, bool issigned)
+ Instruction* U, Value *O)
: CallbackVH(U), Parent(parent), Offset(offset),
- OperandValToReplace(O), IsSigned(issigned),
+ OperandValToReplace(O),
IsUseOfPostIncrementedValue(false) {
}
@@ -57,8 +57,7 @@ public:
/// getOffset - Return the offset to add to a theoeretical induction
/// variable that starts at zero and counts up by the stride to compute
- /// the value for the use. This always has the same type as the stride,
- /// which may need to be casted to match the type of the use.
+ /// the value for the use. This always has the same type as the stride.
SCEVHandle getOffset() const { return Offset; }
/// setOffset - Assign a new offset to this use.
@@ -78,13 +77,6 @@ public:
OperandValToReplace = Op;
}
- /// isSigned - The stride (and thus also the Offset) of this use may be in
- /// a narrower type than the use itself (OperandValToReplace->getType()).
- /// When this is the case, isSigned() indicates whether the IV expression
- /// should be signed-extended instead of zero-extended to fit the type of
- /// the use.
- bool isSigned() const { return IsSigned; }
-
/// 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
@@ -110,10 +102,6 @@ private:
/// that this IVStrideUse is representing.
WeakVH OperandValToReplace;
- /// IsSigned - Determines whether the replacement value is sign or
- /// zero extended to the type of the use.
- bool IsSigned;
-
/// IsUseOfPostIncrementedValue - True if this should use the
/// post-incremented version of this IV, not the preincremented version.
bool IsUseOfPostIncrementedValue;
@@ -170,9 +158,8 @@ public:
/// initial value and the operand that uses the IV.
ilist<IVStrideUse> Users;
- void addUser(const SCEVHandle &Offset,Instruction *User, Value *Operand,
- bool isSigned) {
- Users.push_back(new IVStrideUse(this, Offset, User, Operand, isSigned));
+ void addUser(const SCEVHandle &Offset, Instruction *User, Value *Operand) {
+ Users.push_back(new IVStrideUse(this, Offset, User, Operand));
}
};
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index 41725be1ca3e..8d5136cea2c3 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -25,6 +25,7 @@
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ValueHandle.h"
+#include "llvm/ADT/DenseMap.h"
#include <iosfwd>
namespace llvm {
@@ -34,6 +35,7 @@ namespace llvm {
class SCEVHandle;
class ScalarEvolution;
class TargetData;
+ template<> struct DenseMapInfo<SCEVHandle>;
/// SCEV - This class represents an analyzed expression in the program. These
/// are reference-counted opaque objects that the client is not allowed to
@@ -44,18 +46,22 @@ namespace llvm {
mutable unsigned RefCount;
friend class SCEVHandle;
+ friend class DenseMapInfo<SCEVHandle>;
void addRef() const { ++RefCount; }
void dropRef() const {
if (--RefCount == 0)
delete this;
}
+ const ScalarEvolution* parent;
+
SCEV(const SCEV &); // DO NOT IMPLEMENT
void operator=(const SCEV &); // DO NOT IMPLEMENT
protected:
virtual ~SCEV();
public:
- explicit SCEV(unsigned SCEVTy) : SCEVType(SCEVTy), RefCount(0) {}
+ explicit SCEV(unsigned SCEVTy, const ScalarEvolution* p) :
+ SCEVType(SCEVTy), RefCount(0), parent(p) {}
unsigned getSCEVType() const { return SCEVType; }
@@ -123,7 +129,7 @@ namespace llvm {
/// None of the standard SCEV operations are valid on this class, it is just a
/// marker.
struct SCEVCouldNotCompute : public SCEV {
- SCEVCouldNotCompute();
+ SCEVCouldNotCompute(const ScalarEvolution* p);
~SCEVCouldNotCompute();
// None of these methods are valid for this object.
@@ -197,6 +203,31 @@ namespace llvm {
template<> struct simplify_type<SCEVHandle>
: public simplify_type<const SCEVHandle> {};
+ // Specialize DenseMapInfo for SCEVHandle so that SCEVHandle may be used
+ // as a key in DenseMaps.
+ template<>
+ struct DenseMapInfo<SCEVHandle> {
+ static inline SCEVHandle getEmptyKey() {
+ static SCEVCouldNotCompute Empty(0);
+ if (Empty.RefCount == 0)
+ Empty.addRef();
+ return &Empty;
+ }
+ static inline SCEVHandle getTombstoneKey() {
+ static SCEVCouldNotCompute Tombstone(0);
+ if (Tombstone.RefCount == 0)
+ Tombstone.addRef();
+ return &Tombstone;
+ }
+ static unsigned getHashValue(const SCEVHandle &Val) {
+ return DenseMapInfo<const SCEV *>::getHashValue(Val);
+ }
+ static bool isEqual(const SCEVHandle &LHS, const SCEVHandle &RHS) {
+ return LHS == RHS;
+ }
+ static bool isPod() { return false; }
+ };
+
/// ScalarEvolution - This class is the main scalar evolution driver. Because
/// client code (intentionally) can't do much with the SCEV objects directly,
/// they must ask this class for services.
@@ -301,6 +332,13 @@ namespace llvm {
const SCEVHandle &SymName,
const SCEVHandle &NewVal);
+ /// getBECount - Subtract the end and start values and divide by the step,
+ /// rounding up, to get the number of times the backedge is executed. Return
+ /// CouldNotCompute if an intermediate computation overflows.
+ SCEVHandle getBECount(const SCEVHandle &Start,
+ const SCEVHandle &End,
+ const SCEVHandle &Step);
+
/// getBackedgeTakenInfo - Return the BackedgeTakenInfo for the given
/// loop, lazily computing new values if the loop hasn't been analyzed
/// yet.
@@ -310,6 +348,31 @@ namespace llvm {
/// loop will iterate.
BackedgeTakenInfo ComputeBackedgeTakenCount(const Loop *L);
+ /// ComputeBackedgeTakenCountFromExit - Compute the number of times the
+ /// backedge of the specified loop will execute if it exits via the
+ /// specified block.
+ BackedgeTakenInfo ComputeBackedgeTakenCountFromExit(const Loop *L,
+ BasicBlock *ExitingBlock);
+
+ /// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the
+ /// backedge of the specified loop will execute if its exit condition
+ /// were a conditional branch of ExitCond, TBB, and FBB.
+ BackedgeTakenInfo
+ ComputeBackedgeTakenCountFromExitCond(const Loop *L,
+ Value *ExitCond,
+ BasicBlock *TBB,
+ BasicBlock *FBB);
+
+ /// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of
+ /// times the backedge of the specified loop will execute if its exit
+ /// condition were a conditional branch of the ICmpInst ExitCond, TBB,
+ /// and FBB.
+ BackedgeTakenInfo
+ ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L,
+ ICmpInst *ExitCond,
+ BasicBlock *TBB,
+ BasicBlock *FBB);
+
/// ComputeLoadConstantCompareBackedgeTakenCount - Given an exit condition
/// of 'icmp op load X, cst', try to see if we can compute the trip count.
SCEVHandle
@@ -390,28 +453,29 @@ namespace llvm {
SCEVHandle getConstant(ConstantInt *V);
SCEVHandle getConstant(const APInt& Val);
+ SCEVHandle getConstant(const Type *Ty, uint64_t V, bool isSigned = false);
SCEVHandle getTruncateExpr(const SCEVHandle &Op, const Type *Ty);
SCEVHandle getZeroExtendExpr(const SCEVHandle &Op, const Type *Ty);
SCEVHandle getSignExtendExpr(const SCEVHandle &Op, const Type *Ty);
SCEVHandle getAnyExtendExpr(const SCEVHandle &Op, const Type *Ty);
- SCEVHandle getAddExpr(std::vector<SCEVHandle> &Ops);
+ SCEVHandle getAddExpr(SmallVectorImpl<SCEVHandle> &Ops);
SCEVHandle getAddExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
- std::vector<SCEVHandle> Ops;
+ SmallVector<SCEVHandle, 2> Ops;
Ops.push_back(LHS);
Ops.push_back(RHS);
return getAddExpr(Ops);
}
SCEVHandle getAddExpr(const SCEVHandle &Op0, const SCEVHandle &Op1,
const SCEVHandle &Op2) {
- std::vector<SCEVHandle> Ops;
+ SmallVector<SCEVHandle, 3> Ops;
Ops.push_back(Op0);
Ops.push_back(Op1);
Ops.push_back(Op2);
return getAddExpr(Ops);
}
- SCEVHandle getMulExpr(std::vector<SCEVHandle> &Ops);
+ SCEVHandle getMulExpr(SmallVectorImpl<SCEVHandle> &Ops);
SCEVHandle getMulExpr(const SCEVHandle &LHS, const SCEVHandle &RHS) {
- std::vector<SCEVHandle> Ops;
+ SmallVector<SCEVHandle, 2> Ops;
Ops.push_back(LHS);
Ops.push_back(RHS);
return getMulExpr(Ops);
@@ -419,17 +483,19 @@ namespace llvm {
SCEVHandle getUDivExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
SCEVHandle getAddRecExpr(const SCEVHandle &Start, const SCEVHandle &Step,
const Loop *L);
- SCEVHandle getAddRecExpr(std::vector<SCEVHandle> &Operands,
+ SCEVHandle getAddRecExpr(SmallVectorImpl<SCEVHandle> &Operands,
const Loop *L);
- SCEVHandle getAddRecExpr(const std::vector<SCEVHandle> &Operands,
+ SCEVHandle getAddRecExpr(const SmallVectorImpl<SCEVHandle> &Operands,
const Loop *L) {
- std::vector<SCEVHandle> NewOp(Operands);
+ SmallVector<SCEVHandle, 4> NewOp(Operands.begin(), Operands.end());
return getAddRecExpr(NewOp, L);
}
SCEVHandle getSMaxExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
- SCEVHandle getSMaxExpr(std::vector<SCEVHandle> Operands);
+ SCEVHandle getSMaxExpr(SmallVectorImpl<SCEVHandle> &Operands);
SCEVHandle getUMaxExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
- SCEVHandle getUMaxExpr(std::vector<SCEVHandle> Operands);
+ SCEVHandle getUMaxExpr(SmallVectorImpl<SCEVHandle> &Operands);
+ SCEVHandle getSMinExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
+ SCEVHandle getUMinExpr(const SCEVHandle &LHS, const SCEVHandle &RHS);
SCEVHandle getUnknown(Value *V);
SCEVHandle getCouldNotCompute();
@@ -481,6 +547,12 @@ namespace llvm {
/// specified signed integer value and return a SCEV for the constant.
SCEVHandle getIntegerSCEV(int Val, const Type *Ty);
+ /// getUMaxFromMismatchedTypes - Promote the operands to the wider of
+ /// the types using zero-extension, and then perform a umax operation
+ /// with them.
+ SCEVHandle getUMaxFromMismatchedTypes(const SCEVHandle &LHS,
+ const SCEVHandle &RHS);
+
/// hasSCEV - Return true if the SCEV for this value has already been
/// computed.
bool hasSCEV(Value *V) const;
@@ -539,6 +611,20 @@ namespace llvm {
/// is deleted.
void forgetLoopBackedgeTakenCount(const Loop *L);
+ /// GetMinTrailingZeros - Determine the minimum number of zero bits that S is
+ /// guaranteed to end in (at every loop iteration). It is, at the same time,
+ /// the minimum number of times S is divisible by 2. For example, given {4,+,8}
+ /// it returns 2. If S is guaranteed to be 0, it returns the bitwidth of S.
+ uint32_t GetMinTrailingZeros(const SCEVHandle &S);
+
+ /// GetMinLeadingZeros - Determine the minimum number of zero bits that S is
+ /// guaranteed to begin with (at every loop iteration).
+ uint32_t GetMinLeadingZeros(const SCEVHandle &S);
+
+ /// GetMinSignBits - Determine the minimum number of sign bits that S is
+ /// guaranteed to begin with.
+ uint32_t GetMinSignBits(const SCEVHandle &S);
+
virtual bool runOnFunction(Function &F);
virtual void releaseMemory();
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h
index 1978055b1af6..28423569d2e3 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -36,7 +36,8 @@ namespace llvm {
friend class ScalarEvolution;
ConstantInt *V;
- explicit SCEVConstant(ConstantInt *v) : SCEV(scConstant), V(v) {}
+ explicit SCEVConstant(ConstantInt *v, const ScalarEvolution* p) :
+ SCEV(scConstant, p), V(v) {}
virtual ~SCEVConstant();
public:
@@ -79,7 +80,8 @@ namespace llvm {
SCEVHandle Op;
const Type *Ty;
- SCEVCastExpr(unsigned SCEVTy, const SCEVHandle &op, const Type *ty);
+ SCEVCastExpr(unsigned SCEVTy, const SCEVHandle &op, const Type *ty,
+ const ScalarEvolution* p);
virtual ~SCEVCastExpr();
public:
@@ -112,7 +114,8 @@ namespace llvm {
class SCEVTruncateExpr : public SCEVCastExpr {
friend class ScalarEvolution;
- SCEVTruncateExpr(const SCEVHandle &op, const Type *ty);
+ SCEVTruncateExpr(const SCEVHandle &op, const Type *ty,
+ const ScalarEvolution* p);
virtual ~SCEVTruncateExpr();
public:
@@ -141,7 +144,8 @@ namespace llvm {
class SCEVZeroExtendExpr : public SCEVCastExpr {
friend class ScalarEvolution;
- SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty);
+ SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty,
+ const ScalarEvolution* p);
virtual ~SCEVZeroExtendExpr();
public:
@@ -170,7 +174,8 @@ namespace llvm {
class SCEVSignExtendExpr : public SCEVCastExpr {
friend class ScalarEvolution;
- SCEVSignExtendExpr(const SCEVHandle &op, const Type *ty);
+ SCEVSignExtendExpr(const SCEVHandle &op, const Type *ty,
+ const ScalarEvolution* p);
virtual ~SCEVSignExtendExpr();
public:
@@ -199,10 +204,11 @@ namespace llvm {
///
class SCEVNAryExpr : public SCEV {
protected:
- std::vector<SCEVHandle> Operands;
+ SmallVector<SCEVHandle, 8> Operands;
- SCEVNAryExpr(enum SCEVTypes T, const std::vector<SCEVHandle> &ops)
- : SCEV(T), Operands(ops) {}
+ SCEVNAryExpr(enum SCEVTypes T, const SmallVectorImpl<SCEVHandle> &ops,
+ const ScalarEvolution* p)
+ : SCEV(T, p), Operands(ops.begin(), ops.end()) {}
virtual ~SCEVNAryExpr() {}
public:
@@ -212,8 +218,8 @@ namespace llvm {
return Operands[i];
}
- const std::vector<SCEVHandle> &getOperands() const { return Operands; }
- typedef std::vector<SCEVHandle>::const_iterator op_iterator;
+ const SmallVectorImpl<SCEVHandle> &getOperands() const { return Operands; }
+ typedef SmallVectorImpl<SCEVHandle>::const_iterator op_iterator;
op_iterator op_begin() const { return Operands.begin(); }
op_iterator op_end() const { return Operands.end(); }
@@ -259,8 +265,10 @@ namespace llvm {
///
class SCEVCommutativeExpr : public SCEVNAryExpr {
protected:
- SCEVCommutativeExpr(enum SCEVTypes T, const std::vector<SCEVHandle> &ops)
- : SCEVNAryExpr(T, ops) {}
+ SCEVCommutativeExpr(enum SCEVTypes T,
+ const SmallVectorImpl<SCEVHandle> &ops,
+ const ScalarEvolution* p)
+ : SCEVNAryExpr(T, ops, p) {}
~SCEVCommutativeExpr();
public:
@@ -289,8 +297,9 @@ namespace llvm {
class SCEVAddExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
- explicit SCEVAddExpr(const std::vector<SCEVHandle> &ops)
- : SCEVCommutativeExpr(scAddExpr, ops) {
+ explicit SCEVAddExpr(const SmallVectorImpl<SCEVHandle> &ops,
+ const ScalarEvolution* p)
+ : SCEVCommutativeExpr(scAddExpr, ops, p) {
}
public:
@@ -309,8 +318,9 @@ namespace llvm {
class SCEVMulExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
- explicit SCEVMulExpr(const std::vector<SCEVHandle> &ops)
- : SCEVCommutativeExpr(scMulExpr, ops) {
+ explicit SCEVMulExpr(const SmallVectorImpl<SCEVHandle> &ops,
+ const ScalarEvolution* p)
+ : SCEVCommutativeExpr(scMulExpr, ops, p) {
}
public:
@@ -331,8 +341,9 @@ namespace llvm {
friend class ScalarEvolution;
SCEVHandle LHS, RHS;
- SCEVUDivExpr(const SCEVHandle &lhs, const SCEVHandle &rhs)
- : SCEV(scUDivExpr), LHS(lhs), RHS(rhs) {}
+ SCEVUDivExpr(const SCEVHandle &lhs, const SCEVHandle &rhs,
+ const ScalarEvolution* p)
+ : SCEV(scUDivExpr, p), LHS(lhs), RHS(rhs) {}
virtual ~SCEVUDivExpr();
public:
@@ -387,8 +398,9 @@ namespace llvm {
const Loop *L;
- SCEVAddRecExpr(const std::vector<SCEVHandle> &ops, const Loop *l)
- : SCEVNAryExpr(scAddRecExpr, ops), L(l) {
+ SCEVAddRecExpr(const SmallVectorImpl<SCEVHandle> &ops, const Loop *l,
+ const ScalarEvolution* p)
+ : SCEVNAryExpr(scAddRecExpr, ops, p), L(l) {
for (size_t i = 0, e = Operands.size(); i != e; ++i)
assert(Operands[i]->isLoopInvariant(l) &&
"Operands of AddRec must be loop-invariant!");
@@ -404,7 +416,7 @@ namespace llvm {
/// of degree N, it returns a chrec of degree N-1.
SCEVHandle getStepRecurrence(ScalarEvolution &SE) const {
if (isAffine()) return getOperand(1);
- return SE.getAddRecExpr(std::vector<SCEVHandle>(op_begin()+1,op_end()),
+ return SE.getAddRecExpr(SmallVector<SCEVHandle, 3>(op_begin()+1,op_end()),
getLoop());
}
@@ -463,8 +475,9 @@ namespace llvm {
class SCEVSMaxExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
- explicit SCEVSMaxExpr(const std::vector<SCEVHandle> &ops)
- : SCEVCommutativeExpr(scSMaxExpr, ops) {
+ explicit SCEVSMaxExpr(const SmallVectorImpl<SCEVHandle> &ops,
+ const ScalarEvolution* p)
+ : SCEVCommutativeExpr(scSMaxExpr, ops, p) {
}
public:
@@ -484,8 +497,9 @@ namespace llvm {
class SCEVUMaxExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
- explicit SCEVUMaxExpr(const std::vector<SCEVHandle> &ops)
- : SCEVCommutativeExpr(scUMaxExpr, ops) {
+ explicit SCEVUMaxExpr(const SmallVectorImpl<SCEVHandle> &ops,
+ const ScalarEvolution* p)
+ : SCEVCommutativeExpr(scUMaxExpr, ops, p) {
}
public:
@@ -508,7 +522,8 @@ namespace llvm {
friend class ScalarEvolution;
Value *V;
- explicit SCEVUnknown(Value *v) : SCEV(scUnknown), V(v) {}
+ explicit SCEVUnknown(Value *v, const ScalarEvolution* p) :
+ SCEV(scUnknown, p), V(v) {}
protected:
~SCEVUnknown();
diff --git a/include/llvm/CallingConv.h b/include/llvm/CallingConv.h
index 072f7c386302..318ea287510e 100644
--- a/include/llvm/CallingConv.h
+++ b/include/llvm/CallingConv.h
@@ -57,7 +57,18 @@ namespace CallingConv {
/// X86_FastCall - 'fast' analog of X86_StdCall. Passes first two arguments
/// in ECX:EDX registers, others - via stack. Callee is responsible for
/// stack cleaning.
- X86_FastCall = 65
+ X86_FastCall = 65,
+
+ /// ARM_APCS - ARM Procedure Calling Standard calling convention (obsolete,
+ /// but still used on some targets).
+ ARM_APCS = 66,
+
+ /// ARM_AAPCS - ARM Architecture Procedure Calling Standard calling
+ /// convention (aka EABI). Soft float variant.
+ ARM_AAPCS = 67,
+
+ /// ARM_AAPCS_VFP - Same as ARM_AAPCS, but uses hard floating point ABI.
+ ARM_AAPCS_VFP = 68
};
} // End CallingConv namespace
diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h
index 38c1710d7103..c7b1a42d06b6 100644
--- a/include/llvm/CodeGen/FastISel.h
+++ b/include/llvm/CodeGen/FastISel.h
@@ -16,7 +16,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
-#include "llvm/CodeGen/DebugLoc.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
namespace llvm {
diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h
index f1ae587ac195..0cb7e9004387 100644
--- a/include/llvm/CodeGen/LiveInterval.h
+++ b/include/llvm/CodeGen/LiveInterval.h
@@ -29,29 +29,112 @@
namespace llvm {
class MachineInstr;
+ class MachineRegisterInfo;
class TargetRegisterInfo;
struct LiveInterval;
- /// VNInfo - If the value number definition is undefined (e.g. phi
- /// merge point), it contains ~0u,x. If the value number is not in use, it
- /// contains ~1u,x to indicate that the value # is not used.
- /// def - Instruction # of the definition.
- /// - or reg # of the definition if it's a stack slot liveinterval.
- /// copy - Copy iff val# is defined by a copy; zero otherwise.
- /// hasPHIKill - One or more of the kills are PHI nodes.
- /// redefByEC - Re-defined by early clobber somewhere during the live range.
- /// kills - Instruction # of the kills.
- struct VNInfo {
+ /// VNInfo - Value Number Information.
+ /// This class holds information about a machine level values, including
+ /// definition and use points.
+ ///
+ /// Care must be taken in interpreting the def index of the value. The
+ /// following rules apply:
+ ///
+ /// If the isDefAccurate() method returns false then def does not contain the
+ /// index of the defining MachineInstr, or even (necessarily) to a
+ /// MachineInstr at all. In general such a def index is not meaningful
+ /// and should not be used. The exception is that, for values originally
+ /// defined by PHI instructions, after PHI elimination def will contain the
+ /// index of the MBB in which the PHI originally existed. This can be used
+ /// to insert code (spills or copies) which deals with the value, which will
+ /// be live in to the block.
+
+ class VNInfo {
+ private:
+ enum {
+ HAS_PHI_KILL = 1,
+ REDEF_BY_EC = 1 << 1,
+ IS_PHI_DEF = 1 << 2,
+ IS_UNUSED = 1 << 3,
+ IS_DEF_ACCURATE = 1 << 4
+ };
+
+ unsigned char flags;
+
+ public:
+ /// The ID number of this value.
unsigned id;
+
+ /// The index of the defining instruction (if isDefAccurate() returns true).
unsigned def;
MachineInstr *copy;
- bool hasPHIKill : 1;
- bool redefByEC : 1;
SmallVector<unsigned, 4> kills;
+
VNInfo()
- : id(~1U), def(~1U), copy(0), hasPHIKill(false), redefByEC(false) {}
+ : flags(IS_UNUSED), id(~1U), def(0), copy(0) {}
+
+ /// VNInfo constructor.
+ /// d is presumed to point to the actual defining instr. If it doesn't
+ /// setIsDefAccurate(false) should be called after construction.
VNInfo(unsigned i, unsigned d, MachineInstr *c)
- : id(i), def(d), copy(c), hasPHIKill(false), redefByEC(false) {}
+ : flags(IS_DEF_ACCURATE), id(i), def(d), copy(c) {}
+
+ /// VNInfo construtor, copies values from orig, except for the value number.
+ VNInfo(unsigned i, const VNInfo &orig)
+ : flags(orig.flags), id(i), def(orig.def), copy(orig.copy),
+ kills(orig.kills) {}
+
+ /// Used for copying value number info.
+ unsigned getFlags() const { return flags; }
+ void setFlags(unsigned flags) { this->flags = flags; }
+
+ /// Returns true if one or more kills are PHI nodes.
+ bool hasPHIKill() const { return flags & HAS_PHI_KILL; }
+ void setHasPHIKill(bool hasKill) {
+ if (hasKill)
+ flags |= HAS_PHI_KILL;
+ else
+ flags &= ~HAS_PHI_KILL;
+ }
+
+ /// Returns true if this value is re-defined by an early clobber somewhere
+ /// during the live range.
+ bool hasRedefByEC() const { return flags & REDEF_BY_EC; }
+ void setHasRedefByEC(bool hasRedef) {
+ if (hasRedef)
+ flags |= REDEF_BY_EC;
+ else
+ flags &= ~REDEF_BY_EC;
+ }
+
+ /// Returns true if this value is defined by a PHI instruction (or was,
+ /// PHI instrucions may have been eliminated).
+ bool isPHIDef() const { return flags & IS_PHI_DEF; }
+ void setIsPHIDef(bool phiDef) {
+ if (phiDef)
+ flags |= IS_PHI_DEF;
+ else
+ flags &= ~IS_PHI_DEF;
+ }
+
+ /// Returns true if this value is unused.
+ bool isUnused() const { return flags & IS_UNUSED; }
+ void setIsUnused(bool unused) {
+ if (unused)
+ flags |= IS_UNUSED;
+ else
+ flags &= ~IS_UNUSED;
+ }
+
+ /// Returns true if the def is accurate.
+ bool isDefAccurate() const { return flags & IS_DEF_ACCURATE; }
+ void setIsDefAccurate(bool defAccurate) {
+ if (defAccurate)
+ flags |= IS_DEF_ACCURATE;
+ else
+ flags &= ~IS_DEF_ACCURATE;
+ }
+
};
/// LiveRange structure - This represents a simple register range in the
@@ -108,7 +191,6 @@ namespace llvm {
unsigned reg; // the register or stack slot of this interval
// if the top bits is set, it represents a stack slot.
float weight; // weight of this interval
- unsigned short preference; // preferred register for this interval
Ranges ranges; // the ranges in which this register is live
VNInfoList valnos; // value#'s
@@ -134,7 +216,7 @@ namespace llvm {
};
LiveInterval(unsigned Reg, float Weight, bool IsSS = false)
- : reg(Reg), weight(Weight), preference(0) {
+ : reg(Reg), weight(Weight) {
if (IsSS)
reg = reg | (1U << (sizeof(unsigned)*CHAR_BIT-1));
}
@@ -210,15 +292,17 @@ namespace llvm {
void copyValNumInfo(VNInfo *DstValNo, const VNInfo *SrcValNo) {
DstValNo->def = SrcValNo->def;
DstValNo->copy = SrcValNo->copy;
- DstValNo->hasPHIKill = SrcValNo->hasPHIKill;
- DstValNo->redefByEC = SrcValNo->redefByEC;
+ DstValNo->setFlags(SrcValNo->getFlags());
DstValNo->kills = SrcValNo->kills;
}
/// getNextValue - Create a new value number and return it. MIIdx specifies
/// the instruction that defines the value number.
VNInfo *getNextValue(unsigned MIIdx, MachineInstr *CopyMI,
- BumpPtrAllocator &VNInfoAllocator) {
+ bool isDefAccurate, BumpPtrAllocator &VNInfoAllocator) {
+
+ assert(MIIdx != ~0u && MIIdx != ~1u &&
+ "PHI def / unused flags should now be passed explicitly.");
#ifdef __GNUC__
unsigned Alignment = (unsigned)__alignof__(VNInfo);
#else
@@ -229,6 +313,26 @@ namespace llvm {
static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo),
Alignment));
new (VNI) VNInfo((unsigned)valnos.size(), MIIdx, CopyMI);
+ VNI->setIsDefAccurate(isDefAccurate);
+ valnos.push_back(VNI);
+ return VNI;
+ }
+
+ /// Create a copy of the given value. The new value will be identical except
+ /// for the Value number.
+ VNInfo *createValueCopy(const VNInfo *orig, BumpPtrAllocator &VNInfoAllocator) {
+
+#ifdef __GNUC__
+ unsigned Alignment = (unsigned)__alignof__(VNInfo);
+#else
+ // FIXME: ugly.
+ unsigned Alignment = 8;
+#endif
+ VNInfo *VNI =
+ static_cast<VNInfo*>(VNInfoAllocator.Allocate((unsigned)sizeof(VNInfo),
+ Alignment));
+
+ new (VNI) VNInfo((unsigned)valnos.size(), *orig);
valnos.push_back(VNI);
return VNI;
}
@@ -339,7 +443,8 @@ namespace llvm {
/// Copy - Copy the specified live interval. This copies all the fields
/// except for the register of the interval.
- void Copy(const LiveInterval &RHS, BumpPtrAllocator &VNInfoAllocator);
+ void Copy(const LiveInterval &RHS, MachineRegisterInfo *MRI,
+ BumpPtrAllocator &VNInfoAllocator);
bool empty() const { return ranges.empty(); }
@@ -416,7 +521,8 @@ namespace llvm {
/// the intervals are not joinable, this aborts.
void join(LiveInterval &Other, const int *ValNoAssignments,
const int *RHSValNoAssignments,
- SmallVector<VNInfo*, 16> &NewVNInfo);
+ SmallVector<VNInfo*, 16> &NewVNInfo,
+ MachineRegisterInfo *MRI);
/// isInOneLiveRange - Return true if the range specified is entirely in the
/// a single LiveRange of the live interval.
diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h
index a110e5846ac9..0074f1a5f2ca 100644
--- a/include/llvm/CodeGen/MachineFunction.h
+++ b/include/llvm/CodeGen/MachineFunction.h
@@ -19,7 +19,7 @@
#define LLVM_CODEGEN_MACHINEFUNCTION_H
#include "llvm/ADT/ilist.h"
-#include "llvm/CodeGen/DebugLoc.h"
+#include "llvm/Support/DebugLoc.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/Support/Annotation.h"
#include "llvm/Support/Allocator.h"
diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h
index d61e5d8a5eb4..2b2f24a88371 100644
--- a/include/llvm/CodeGen/MachineInstr.h
+++ b/include/llvm/CodeGen/MachineInstr.h
@@ -22,7 +22,7 @@
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/Target/TargetInstrDesc.h"
-#include "llvm/CodeGen/DebugLoc.h"
+#include "llvm/Support/DebugLoc.h"
#include <list>
#include <vector>
@@ -104,7 +104,7 @@ public:
/// getDebugLoc - Returns the debug location id of this MachineInstr.
///
- const DebugLoc getDebugLoc() const { return debugLoc; }
+ DebugLoc getDebugLoc() const { return debugLoc; }
/// getDesc - Returns the target instruction descriptor of this
/// MachineInstr.
diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h
index 7a4168447b62..ba538d795ffd 100644
--- a/include/llvm/CodeGen/MachineOperand.h
+++ b/include/llvm/CodeGen/MachineOperand.h
@@ -33,15 +33,15 @@ class raw_ostream;
class MachineOperand {
public:
enum MachineOperandType {
- MO_Register, ///< Register operand.
- MO_Immediate, ///< Immediate operand
- MO_FPImmediate, ///< Floating-point immediate operand
- MO_MachineBasicBlock, ///< MachineBasicBlock reference
- MO_FrameIndex, ///< Abstract Stack Frame Index
- MO_ConstantPoolIndex, ///< Address of indexed Constant in Constant Pool
- MO_JumpTableIndex, ///< Address of indexed Jump Table for switch
- MO_ExternalSymbol, ///< Name of external global symbol
- MO_GlobalAddress ///< Address of a global value
+ MO_Register, ///< Register operand.
+ MO_Immediate, ///< Immediate operand
+ MO_FPImmediate, ///< Floating-point immediate operand
+ MO_MachineBasicBlock, ///< MachineBasicBlock reference
+ MO_FrameIndex, ///< Abstract Stack Frame Index
+ MO_ConstantPoolIndex, ///< Address of indexed Constant in Constant Pool
+ MO_JumpTableIndex, ///< Address of indexed Jump Table for switch
+ MO_ExternalSymbol, ///< Name of external global symbol
+ MO_GlobalAddress ///< Address of a global value
};
private:
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index 02f9b7c686e2..80c37b39ca0c 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -37,6 +37,15 @@ class MachineRegisterInfo {
/// virtual registers. For each target register class, it keeps a list of
/// virtual registers belonging to the class.
std::vector<std::vector<unsigned> > RegClass2VRegMap;
+
+ /// RegAllocHints - This vector records register allocation hints for virtual
+ /// registers. For each virtual register, it keeps a register and hint type
+ /// pair making up the allocation hint. Hint type is target specific except
+ /// for the value 0 which means the second value of the pair is the preferred
+ /// register for allocation. For example, if the hint is <0, 1024>, it means
+ /// the allocator should prefer the physical register allocated to the virtual
+ /// register of the hint.
+ std::vector<std::pair<unsigned, unsigned> > RegAllocHints;
/// PhysRegUseDefLists - This is an array of the head of the use/def list for
/// physical registers.
@@ -170,7 +179,25 @@ public:
std::vector<unsigned> &getRegClassVirtRegs(const TargetRegisterClass *RC) {
return RegClass2VRegMap[RC->getID()];
}
-
+
+ /// setRegAllocationHint - Specify a register allocation hint for the
+ /// specified virtual register.
+ void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) {
+ Reg -= TargetRegisterInfo::FirstVirtualRegister;
+ assert(Reg < VRegInfo.size() && "Invalid vreg!");
+ RegAllocHints[Reg].first = Type;
+ RegAllocHints[Reg].second = PrefReg;
+ }
+
+ /// getRegAllocationHint - Return the register allocation hint for the
+ /// specified virtual register.
+ std::pair<unsigned, unsigned>
+ getRegAllocationHint(unsigned Reg) const {
+ Reg -= TargetRegisterInfo::FirstVirtualRegister;
+ assert(Reg < VRegInfo.size() && "Invalid vreg!");
+ return RegAllocHints[Reg];
+ }
+
//===--------------------------------------------------------------------===//
// Physical Register Use Info
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h
index dd76fcc11b5e..7f2c8bc36840 100644
--- a/include/llvm/CodeGen/RuntimeLibcalls.h
+++ b/include/llvm/CodeGen/RuntimeLibcalls.h
@@ -153,6 +153,8 @@ namespace RTLIB {
FPROUND_PPCF128_F32,
FPROUND_F80_F64,
FPROUND_PPCF128_F64,
+ FPTOSINT_F32_I8,
+ FPTOSINT_F32_I16,
FPTOSINT_F32_I32,
FPTOSINT_F32_I64,
FPTOSINT_F32_I128,
@@ -165,6 +167,8 @@ namespace RTLIB {
FPTOSINT_PPCF128_I32,
FPTOSINT_PPCF128_I64,
FPTOSINT_PPCF128_I128,
+ FPTOUINT_F32_I8,
+ FPTOUINT_F32_I16,
FPTOUINT_F32_I32,
FPTOUINT_F32_I64,
FPTOUINT_F32_I128,
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index ad485103fb7e..1b6fecd556e1 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -31,7 +31,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/RecyclingAllocator.h"
#include "llvm/Support/DataTypes.h"
-#include "llvm/CodeGen/DebugLoc.h"
+#include "llvm/Support/DebugLoc.h"
#include <cassert>
#include <climits>
diff --git a/include/llvm/Config/AsmPrinters.def.in b/include/llvm/Config/AsmPrinters.def.in
new file mode 100644
index 000000000000..9729bd75eb40
--- /dev/null
+++ b/include/llvm/Config/AsmPrinters.def.in
@@ -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_ENUM_ASM_PRINTERS@
+
+#undef LLVM_ASM_PRINTER
diff --git a/include/llvm/Config/Targets.def.in b/include/llvm/Config/Targets.def.in
new file mode 100644
index 000000000000..a3884729e118
--- /dev/null
+++ b/include/llvm/Config/Targets.def.in
@@ -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_ENUM_TARGETS@
+
+#undef LLVM_TARGET
diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake
index 33e2e002e231..c59ed23d8b25 100644
--- a/include/llvm/Config/config.h.cmake
+++ b/include/llvm/Config/config.h.cmake
@@ -580,3 +580,6 @@
/* Define to a function implementing strdup */
#cmakedefine strdup ${strdup}
+
+/* Native LLVM architecture */
+#cmakedefine LLVM_NATIVE_ARCH ${LLVM_NATIVE_ARCH}
diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in
index eee2f946148b..ac60f4dc3a50 100644
--- a/include/llvm/Config/config.h.in
+++ b/include/llvm/Config/config.h.in
@@ -285,6 +285,9 @@
/* 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 <stdlib.h> */
#undef HAVE_RAND48
@@ -473,6 +476,9 @@
/* Build multithreading support into LLVM */
#undef LLVM_MULTITHREADED
+/* LLVM architecture name for the native architecture, if available */
+#undef LLVM_NATIVE_ARCH
+
/* Define if this is Unixish platform */
#undef LLVM_ON_UNIX
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index ed0fe2740f92..52fff2020c74 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -102,19 +102,28 @@ public:
return CreateTrueFalseVals(false);
}
- /// Return a ConstantInt with the specified value for the specified type. The
- /// value V will be canonicalized to an unsigned APInt. Accessing it with
- /// either getSExtValue() or getZExtValue() will yield a correctly sized and
- /// signed value for the type Ty.
+ /// Return a ConstantInt with the specified integer value for the specified
+ /// type. If the type is wider than 64 bits, the value will be zero-extended
+ /// to fit the type, unless isSigned is true, in which case the value will
+ /// be interpreted as a 64-bit signed integer and sign-extended to fit
+ /// the type.
/// @brief Get a ConstantInt for a specific value.
- static ConstantInt *get(const Type *Ty, uint64_t V, bool isSigned = false);
+ static ConstantInt *get(const IntegerType *Ty,
+ uint64_t V, bool isSigned = false);
+
+ /// If Ty is a vector type, return a Constant with a splat of the given
+ /// value. Otherwise return a ConstantInt for the given value.
+ static Constant *get(const Type *Ty, uint64_t V, bool isSigned = false);
/// Return a ConstantInt with the specified value for the specified type. The
/// value V will be canonicalized to a an unsigned APInt. Accessing it with
/// either getSExtValue() or getZExtValue() will yield a correctly sized and
/// signed value for the type Ty.
/// @brief Get a ConstantInt for a specific signed value.
- static ConstantInt *getSigned(const Type *Ty, int64_t V) {
+ static ConstantInt *getSigned(const IntegerType *Ty, int64_t V) {
+ return get(Ty, V, true);
+ }
+ static Constant *getSigned(const Type *Ty, int64_t V) {
return get(Ty, V, true);
}
@@ -122,6 +131,10 @@ public:
/// type is the integer type that corresponds to the bit width of the value.
static ConstantInt *get(const APInt &V);
+ /// If Ty is a vector type, return a Constant with a splat of the given
+ /// value. Otherwise return a ConstantInt for the given value.
+ static Constant *get(const Type *Ty, const APInt &V);
+
/// getType - Specialize the getType() method to always return an IntegerType,
/// which reduces the amount of casting needed in parts of the compiler.
///
@@ -248,10 +261,11 @@ public:
/// get() - Static factory methods - Return objects of the specified value
static ConstantFP *get(const APFloat &V);
- /// get() - This returns a constant fp for the specified value in the
- /// specified type. This should only be used for simple constant values like
- /// 2.0/1.0 etc, that are known-valid both as double and as the target format.
- static ConstantFP *get(const Type *Ty, double V);
+ /// get() - This returns a ConstantFP, or a vector containing a splat of a
+ /// ConstantFP, for the specified value in the specified type. This should
+ /// only be used for simple constant values like 2.0/1.0 etc, that are
+ /// known-valid both as host double and as the target format.
+ static Constant *get(const Type *Ty, double V);
/// isValueValidForType - return true if Ty is big enough to represent V.
static bool isValueValidForType(const Type *Ty, const APFloat& V);
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h
index fa951bf70d05..b5824f8f8156 100644
--- a/include/llvm/DerivedTypes.h
+++ b/include/llvm/DerivedTypes.h
@@ -50,6 +50,10 @@ protected:
///
void dropAllTypeUses();
+ /// unlockedRefineAbstractTypeTo - Internal version of refineAbstractTypeTo
+ /// that performs no locking. Only used for internal recursion.
+ void unlockedRefineAbstractTypeTo(const Type *NewType);
+
public:
//===--------------------------------------------------------------------===//
diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h
new file mode 100644
index 000000000000..cadc23ab7109
--- /dev/null
+++ b/include/llvm/MC/MCInst.h
@@ -0,0 +1,125 @@
+//===-- llvm/MC/MCInst.h - MCInst class -------------------------*- 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 MCInst and MCOperand classes, which
+// is the basic representation used to represent low-level machine code
+// instructions.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_MC_MCINST_H
+#define LLVM_MC_MCINST_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/DebugLoc.h"
+
+namespace llvm {
+
+/// MCOperand - Instances of this class represent operands of the MCInst class.
+/// This is a simple discriminated union.
+class MCOperand {
+ enum MachineOperandType {
+ kInvalid, ///< Uninitialized.
+ kRegister, ///< Register operand.
+ kImmediate, ///< Immediate operand.
+ kMBBLabel ///< Basic block label.
+ };
+ unsigned char Kind;
+
+ union {
+ unsigned RegVal;
+ int64_t ImmVal;
+ struct {
+ unsigned FunctionNo;
+ unsigned BlockNo;
+ } MBBLabel;
+ };
+public:
+
+ MCOperand() : Kind(kInvalid) {}
+ MCOperand(const MCOperand &RHS) { *this = RHS; }
+
+ bool isReg() const { return Kind == kRegister; }
+ bool isImm() const { return Kind == kImmediate; }
+ bool isMBBLabel() const { return Kind == kMBBLabel; }
+
+ /// getReg - Returns the register number.
+ unsigned getReg() const {
+ assert(isReg() && "This is not a register operand!");
+ return RegVal;
+ }
+
+ /// setReg - Set the register number.
+ void setReg(unsigned Reg) {
+ assert(isReg() && "This is not a register operand!");
+ RegVal = Reg;
+ }
+
+ int64_t getImm() const {
+ assert(isImm() && "This is not an immediate");
+ return ImmVal;
+ }
+ void setImm(int64_t Val) {
+ assert(isImm() && "This is not an immediate");
+ ImmVal = Val;
+ }
+
+ unsigned getMBBLabelFunction() const {
+ assert(isMBBLabel() && "Wrong accessor");
+ return MBBLabel.FunctionNo;
+ }
+ unsigned getMBBLabelBlock() const {
+ assert(isMBBLabel() && "Wrong accessor");
+ return MBBLabel.BlockNo;
+ }
+
+ void MakeReg(unsigned Reg) {
+ Kind = kRegister;
+ RegVal = Reg;
+ }
+ void MakeImm(int64_t Val) {
+ Kind = kImmediate;
+ ImmVal = Val;
+ }
+ void MakeMBBLabel(unsigned Fn, unsigned MBB) {
+ Kind = kMBBLabel;
+ MBBLabel.FunctionNo = Fn;
+ MBBLabel.BlockNo = MBB;
+ }
+};
+
+
+/// MCInst - Instances of this class represent a single low-level machine
+/// instruction.
+class MCInst {
+ unsigned Opcode;
+ SmallVector<MCOperand, 8> Operands;
+public:
+ MCInst() : Opcode(~0U) {}
+
+ void setOpcode(unsigned Op) { Opcode = Op; }
+
+ unsigned getOpcode() const { return Opcode; }
+ DebugLoc getDebugLoc() const { return DebugLoc(); }
+
+ const MCOperand &getOperand(unsigned i) const { return Operands[i]; }
+ MCOperand &getOperand(unsigned i) { return Operands[i]; }
+
+ void addOperand(const MCOperand &Op) {
+ Operands.push_back(Op);
+ }
+
+};
+
+
+} // end namespace llvm
+
+#endif
diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h
index fa3b8701d349..3ae50136e4a9 100644
--- a/include/llvm/Support/CommandLine.h
+++ b/include/llvm/Support/CommandLine.h
@@ -539,7 +539,7 @@ template<>
class parser<bool> : public basic_parser<bool> {
const char *ArgStr;
public:
-
+
// parse - Return true on error.
bool parse(Option &O, const char *ArgName, const std::string &Arg, bool &Val);
@@ -1105,7 +1105,7 @@ public:
}
};
-// multi_arg - Modifier to set the number of additional values.
+// multi_val - Modifier to set the number of additional values.
struct multi_val {
unsigned AdditionalVals;
explicit multi_val(unsigned N) : AdditionalVals(N) {}
diff --git a/include/llvm/CodeGen/DebugLoc.h b/include/llvm/Support/DebugLoc.h
index 77e6733f696a..5c089efc98ce 100644
--- a/include/llvm/CodeGen/DebugLoc.h
+++ b/include/llvm/Support/DebugLoc.h
@@ -1,4 +1,4 @@
-//===---- llvm/CodeGen/DebugLoc.h - Debug Location Information --*- C++ -*-===//
+//===---- llvm/DebugLoc.h - Debug Location Information ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,13 +7,13 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines a number of light weight data structures used by the code
-// generator to describe and track debug location information.
+// This file defines a number of light weight data structures used
+// to describe and track debug location information.
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CODEGEN_DEBUGLOC_H
-#define LLVM_CODEGEN_DEBUGLOC_H
+#ifndef LLVM_DEBUGLOC_H
+#define LLVM_DEBUGLOC_H
#include "llvm/ADT/DenseMap.h"
#include <vector>
@@ -98,4 +98,4 @@ namespace llvm {
} // end namespace llvm
-#endif /* LLVM_CODEGEN_DEBUGLOC_H */
+#endif /* LLVM_DEBUGLOC_H */
diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h
index 7942de7857a2..ed6a3f19ef7a 100644
--- a/include/llvm/Support/IRBuilder.h
+++ b/include/llvm/Support/IRBuilder.h
@@ -17,6 +17,7 @@
#include "llvm/Constants.h"
#include "llvm/Instructions.h"
+#include "llvm/GlobalAlias.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Function.h"
#include "llvm/Support/ConstantFolder.h"
@@ -202,7 +203,7 @@ public:
Value *CreateFMul(Value *LHS, Value *RHS, const char *Name = "") {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
- return Folder.CreateMul(LC, RC);
+ return Folder.CreateFMul(LC, RC);
return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name);
}
Value *CreateUDiv(Value *LHS, Value *RHS, const char *Name = "") {
@@ -291,6 +292,11 @@ public:
return Folder.CreateNeg(VC);
return Insert(BinaryOperator::CreateNeg(V), Name);
}
+ Value *CreateFNeg(Value *V, const char *Name = "") {
+ if (Constant *VC = dyn_cast<Constant>(V))
+ return Folder.CreateFNeg(VC);
+ return Insert(BinaryOperator::CreateFNeg(V), Name);
+ }
Value *CreateNot(Value *V, const char *Name = "") {
if (Constant *VC = dyn_cast<Constant>(V))
return Folder.CreateNot(VC);
diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h
index 619cc2055250..4fc648319ad4 100644
--- a/include/llvm/Support/ManagedStatic.h
+++ b/include/llvm/Support/ManagedStatic.h
@@ -15,6 +15,7 @@
#define LLVM_SUPPORT_MANAGED_STATIC_H
#include "llvm/System/Atomic.h"
+#include "llvm/System/Threading.h"
namespace llvm {
@@ -60,28 +61,28 @@ public:
// Accessors.
C &operator*() {
void* tmp = Ptr;
- sys::MemoryFence();
+ if (llvm_is_multithreaded()) sys::MemoryFence();
if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>);
return *static_cast<C*>(Ptr);
}
C *operator->() {
void* tmp = Ptr;
- sys::MemoryFence();
+ if (llvm_is_multithreaded()) sys::MemoryFence();
if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>);
return static_cast<C*>(Ptr);
}
const C &operator*() const {
void* tmp = Ptr;
- sys::MemoryFence();
+ if (llvm_is_multithreaded()) sys::MemoryFence();
if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>);
return *static_cast<C*>(Ptr);
}
const C *operator->() const {
void* tmp = Ptr;
- sys::MemoryFence();
+ if (llvm_is_multithreaded()) sys::MemoryFence();
if (!tmp) RegisterManagedStatic(object_creator<C>, object_deleter<C>);
return static_cast<C*>(Ptr);
@@ -94,13 +95,6 @@ public:
void Register() { RegisterManagedStatic(0, CleanupFn); }
};
-
-/// llvm_start_multithreaded - Allocate and initialize structures needed to
-/// make LLVM safe for multithreading. The return value indicates whether
-/// multithreaded initialization succeeded. LLVM will still be operational
-/// on "failed" return, but will not be safe to run multithreaded.
-bool llvm_start_multithreaded();
-
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
void llvm_shutdown();
diff --git a/utils/TableGen/TGSourceMgr.h b/include/llvm/Support/SourceMgr.h
index 69fb74ca20c6..25775cb74419 100644
--- a/utils/TableGen/TGSourceMgr.h
+++ b/include/llvm/Support/SourceMgr.h
@@ -1,4 +1,4 @@
-//===- TGSourceMgr.h - Manager for Source Buffers & Diagnostics -*- C++ -*-===//
+//===- SourceMgr.h - Manager for Source Buffers & Diagnostics ---*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,12 +7,14 @@
//
//===----------------------------------------------------------------------===//
//
-// This file declares the TGSourceMgr class.
+// This file declares the SourceMgr class. This class is used as a simple
+// substrate for diagnostics, #include handling, and other low level things for
+// simple parsers.
//
//===----------------------------------------------------------------------===//
-#ifndef TGSOURCEMGR_H
-#define TGSOURCEMGR_H
+#ifndef SUPPORT_SOURCEMGR_H
+#define SUPPORT_SOURCEMGR_H
#include <string>
#include <vector>
@@ -20,46 +22,54 @@
namespace llvm {
class MemoryBuffer;
- class TGSourceMgr;
+ class SourceMgr;
-class TGLoc {
+class SMLoc {
const char *Ptr;
public:
- TGLoc() : Ptr(0) {}
- TGLoc(const TGLoc &RHS) : Ptr(RHS.Ptr) {}
+ SMLoc() : Ptr(0) {}
+ SMLoc(const SMLoc &RHS) : Ptr(RHS.Ptr) {}
- bool operator==(const TGLoc &RHS) const { return RHS.Ptr == Ptr; }
- bool operator!=(const TGLoc &RHS) const { return RHS.Ptr != Ptr; }
+ bool operator==(const SMLoc &RHS) const { return RHS.Ptr == Ptr; }
+ bool operator!=(const SMLoc &RHS) const { return RHS.Ptr != Ptr; }
const char *getPointer() const { return Ptr; }
- static TGLoc getFromPointer(const char *Ptr) {
- TGLoc L;
+ static SMLoc getFromPointer(const char *Ptr) {
+ SMLoc L;
L.Ptr = Ptr;
return L;
}
};
-/// TGSourceMgr - This owns the files read by tblgen, handles include stacks,
+/// SourceMgr - This owns the files read by tblgen, handles include stacks,
/// and handles printing of diagnostics.
-class TGSourceMgr {
+class SourceMgr {
struct SrcBuffer {
/// Buffer - The memory buffer for the file.
MemoryBuffer *Buffer;
/// IncludeLoc - This is the location of the parent include, or null if at
/// the top level.
- TGLoc IncludeLoc;
+ SMLoc IncludeLoc;
};
/// Buffers - This is all of the buffers that we are reading from.
std::vector<SrcBuffer> Buffers;
- TGSourceMgr(const TGSourceMgr&); // DO NOT IMPLEMENT
- void operator=(const TGSourceMgr&); // DO NOT IMPLEMENT
+ // IncludeDirectories - This is the list of directories we should search for
+ // include files in.
+ std::vector<std::string> IncludeDirectories;
+
+ SourceMgr(const SourceMgr&); // DO NOT IMPLEMENT
+ void operator=(const SourceMgr&); // DO NOT IMPLEMENT
public:
- TGSourceMgr() {}
- ~TGSourceMgr();
+ SourceMgr() {}
+ ~SourceMgr();
+
+ void setIncludeDirs(const std::vector<std::string> &Dirs) {
+ IncludeDirectories = Dirs;
+ }
const SrcBuffer &getBufferInfo(unsigned i) const {
assert(i < Buffers.size() && "Invalid Buffer ID!");
@@ -71,12 +81,12 @@ public:
return Buffers[i].Buffer;
}
- TGLoc getParentIncludeLoc(unsigned i) const {
+ SMLoc getParentIncludeLoc(unsigned i) const {
assert(i < Buffers.size() && "Invalid Buffer ID!");
return Buffers[i].IncludeLoc;
}
- unsigned AddNewSourceBuffer(MemoryBuffer *F, TGLoc IncludeLoc) {
+ unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) {
SrcBuffer NB;
NB.Buffer = F;
NB.IncludeLoc = IncludeLoc;
@@ -84,21 +94,25 @@ public:
return Buffers.size()-1;
}
+ /// AddIncludeFile - Search for a file with the specified name in the current
+ /// directory or in one of the IncludeDirs. If no file is found, this returns
+ /// ~0, otherwise it returns the buffer ID of the stacked file.
+ unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc);
+
/// FindBufferContainingLoc - Return the ID of the buffer containing the
/// specified location, returning -1 if not found.
- int FindBufferContainingLoc(TGLoc Loc) const;
+ int FindBufferContainingLoc(SMLoc Loc) const;
/// FindLineNumber - Find the line number for the specified location in the
/// specified file. This is not a fast method.
- unsigned FindLineNumber(TGLoc Loc, int BufferID = -1) const;
-
+ unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const;
- /// PrintError - Emit an error message about the specified location with the
+ /// PrintMessage - Emit a message about the specified location with the
/// specified string.
- void PrintError(TGLoc ErrorLoc, const std::string &Msg) const;
+ void PrintMessage(SMLoc Loc, const std::string &Msg) const;
private:
- void PrintIncludeStack(TGLoc IncludeLoc) const;
+ void PrintIncludeStack(SMLoc IncludeLoc) const;
};
} // end llvm namespace
diff --git a/include/llvm/System/Atomic.h b/include/llvm/System/Atomic.h
index cb9277cc35ec..adbb975298e8 100644
--- a/include/llvm/System/Atomic.h
+++ b/include/llvm/System/Atomic.h
@@ -24,6 +24,8 @@ namespace llvm {
cas_flag CompareAndSwap(volatile cas_flag* ptr,
cas_flag new_value,
cas_flag old_value);
+ cas_flag AtomicIncrement(volatile cas_flag* ptr);
+ cas_flag AtomicDecrement(volatile cas_flag* ptr);
}
}
diff --git a/include/llvm/System/Mutex.h b/include/llvm/System/Mutex.h
index 4f3849341aa1..d2c457dbc91c 100644
--- a/include/llvm/System/Mutex.h
+++ b/include/llvm/System/Mutex.h
@@ -14,12 +14,15 @@
#ifndef LLVM_SYSTEM_MUTEX_H
#define LLVM_SYSTEM_MUTEX_H
+#include "llvm/System/Threading.h"
+#include <cassert>
+
namespace llvm
{
namespace sys
{
/// @brief Platform agnostic Mutex class.
- class Mutex
+ class MutexImpl
{
/// @name Constructors
/// @{
@@ -30,11 +33,11 @@ namespace llvm
/// also more likely to deadlock (same thread can't acquire more than
/// once).
/// @brief Default Constructor.
- explicit Mutex(bool recursive = true);
+ explicit MutexImpl(bool recursive = true);
/// Releases and removes the lock
/// @brief Destructor
- ~Mutex();
+ ~MutexImpl();
/// @}
/// @name Methods
@@ -66,18 +69,81 @@ namespace llvm
/// @name Platform Dependent Data
/// @{
private:
-#ifdef ENABLE_THREADS
void* data_; ///< We don't know what the data will be
-#endif
/// @}
/// @name Do Not Implement
/// @{
private:
- Mutex(const Mutex & original);
- void operator=(const Mutex &);
+ MutexImpl(const MutexImpl & original);
+ void operator=(const MutexImpl &);
/// @}
};
+
+
+ /// SmartMutex - A mutex with a compile time constant parameter that
+ /// indicates whether this mutex should become a no-op when we're not
+ /// running in multithreaded mode.
+ template<bool mt_only>
+ class SmartMutex : public MutexImpl {
+ unsigned acquired;
+ bool recursive;
+ public:
+ explicit SmartMutex(bool rec = true) :
+ MutexImpl(rec), acquired(0), recursive(rec) { }
+
+ bool acquire() {
+ if (!mt_only || llvm_is_multithreaded())
+ return MutexImpl::acquire();
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ assert((recursive || acquired == 0) && "Lock already acquired!!");
+ ++acquired;
+ return true;
+ }
+
+ bool release() {
+ if (!mt_only || llvm_is_multithreaded())
+ return MutexImpl::release();
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ assert(((recursive && acquired) || (acquired == 1)) &&
+ "Lock not acquired before release!");
+ --acquired;
+ return true;
+ }
+
+ bool tryacquire() {
+ if (!mt_only || llvm_is_multithreaded())
+ return MutexImpl::tryacquire();
+ return true;
+ }
+
+ private:
+ SmartMutex(const SmartMutex<mt_only> & original);
+ void operator=(const SmartMutex<mt_only> &);
+ };
+
+ /// Mutex - A standard, always enforced mutex.
+ typedef SmartMutex<false> Mutex;
+
+ template<bool mt_only>
+ class SmartScopedLock {
+ SmartMutex<mt_only>* mtx;
+
+ public:
+ SmartScopedLock(SmartMutex<mt_only>* m) : mtx(m) {
+ mtx->acquire();
+ }
+
+ ~SmartScopedLock() {
+ mtx->release();
+ }
+ };
+
+ typedef SmartScopedLock<false> ScopedLock;
}
}
diff --git a/include/llvm/System/Path.h b/include/llvm/System/Path.h
index de2f173ae417..05be2212758b 100644
--- a/include/llvm/System/Path.h
+++ b/include/llvm/System/Path.h
@@ -309,6 +309,11 @@ namespace sys {
/// @brief Determine if the path is absolute.
bool isAbsolute() const;
+ /// This function determines if the path name is absolute, as opposed to
+ /// relative.
+ /// @brief Determine if the path is absolute.
+ static bool isAbsolute(const char *NameStart, unsigned NameLen);
+
/// This function opens the file associated with the path name provided by
/// the Path object and reads its magic number. If the magic number at the
/// start of the file matches \p magic, true is returned. In all other
diff --git a/include/llvm/System/RWMutex.h b/include/llvm/System/RWMutex.h
new file mode 100644
index 000000000000..e577d457afb5
--- /dev/null
+++ b/include/llvm/System/RWMutex.h
@@ -0,0 +1,175 @@
+//===- RWMutex.h - Reader/Writer Mutual Exclusion Lock ----------*- 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 llvm::sys::RWMutex class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SYSTEM_RWMUTEX_H
+#define LLVM_SYSTEM_RWMUTEX_H
+
+#include "llvm/System/Threading.h"
+#include <cassert>
+
+namespace llvm
+{
+ namespace sys
+ {
+ /// @brief Platform agnostic RWMutex class.
+ class RWMutexImpl
+ {
+ /// @name Constructors
+ /// @{
+ public:
+
+ /// Initializes the lock but doesn't acquire it.
+ /// @brief Default Constructor.
+ explicit RWMutexImpl();
+
+ /// Releases and removes the lock
+ /// @brief Destructor
+ ~RWMutexImpl();
+
+ /// @}
+ /// @name Methods
+ /// @{
+ public:
+
+ /// Attempts to unconditionally acquire the lock in reader mode. If the
+ /// lock is held by a writer, this method will wait until it can acquire
+ /// the lock.
+ /// @returns false if any kind of error occurs, true otherwise.
+ /// @brief Unconditionally acquire the lock in reader mode.
+ bool reader_acquire();
+
+ /// Attempts to release the lock in reader mode.
+ /// @returns false if any kind of error occurs, true otherwise.
+ /// @brief Unconditionally release the lock in reader mode.
+ bool reader_release();
+
+ /// Attempts to unconditionally acquire the lock in reader mode. If the
+ /// lock is held by any readers, this method will wait until it can
+ /// acquire the lock.
+ /// @returns false if any kind of error occurs, true otherwise.
+ /// @brief Unconditionally acquire the lock in writer mode.
+ bool writer_acquire();
+
+ /// Attempts to release the lock in writer mode.
+ /// @returns false if any kind of error occurs, true otherwise.
+ /// @brief Unconditionally release the lock in write mode.
+ bool writer_release();
+
+ //@}
+ /// @name Platform Dependent Data
+ /// @{
+ private:
+ void* data_; ///< We don't know what the data will be
+
+ /// @}
+ /// @name Do Not Implement
+ /// @{
+ private:
+ RWMutexImpl(const RWMutexImpl & original);
+ void operator=(const RWMutexImpl &);
+ /// @}
+ };
+
+ /// SmartMutex - An R/W mutex with a compile time constant parameter that
+ /// indicates whether this mutex should become a no-op when we're not
+ /// running in multithreaded mode.
+ template<bool mt_only>
+ class SmartRWMutex : public RWMutexImpl {
+ unsigned readers, writers;
+ public:
+ explicit SmartRWMutex() : RWMutexImpl(), readers(0), writers(0) { }
+
+ bool reader_acquire() {
+ if (!mt_only || llvm_is_multithreaded())
+ return RWMutexImpl::reader_acquire();
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ ++readers;
+ return true;
+ }
+
+ bool reader_release() {
+ if (!mt_only || llvm_is_multithreaded())
+ return RWMutexImpl::reader_release();
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ assert(readers > 0 && "Reader lock not acquired before release!");
+ --readers;
+ return true;
+ }
+
+ bool writer_acquire() {
+ if (!mt_only || llvm_is_multithreaded())
+ return RWMutexImpl::writer_acquire();
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ assert(writers == 0 && "Writer lock already acquired!");
+ ++writers;
+ return true;
+ }
+
+ bool writer_release() {
+ if (!mt_only || llvm_is_multithreaded())
+ return RWMutexImpl::writer_release();
+
+ // Single-threaded debugging code. This would be racy in multithreaded
+ // mode, but provides not sanity checks in single threaded mode.
+ assert(writers == 1 && "Writer lock not acquired before release!");
+ --writers;
+ return true;
+ }
+
+ private:
+ SmartRWMutex(const SmartRWMutex<mt_only> & original);
+ void operator=(const SmartRWMutex<mt_only> &);
+ };
+ typedef SmartRWMutex<false> RWMutex;
+
+ /// ScopedReader - RAII acquisition of a reader lock
+ template<bool mt_only>
+ struct SmartScopedReader {
+ SmartRWMutex<mt_only>* mutex;
+
+ explicit SmartScopedReader(SmartRWMutex<mt_only>* m) {
+ mutex = m;
+ mutex->reader_acquire();
+ }
+
+ ~SmartScopedReader() {
+ mutex->reader_release();
+ }
+ };
+ typedef SmartScopedReader<false> ScopedReader;
+
+ /// ScopedWriter - RAII acquisition of a writer lock
+ template<bool mt_only>
+ struct SmartScopedWriter {
+ SmartRWMutex<mt_only>* mutex;
+
+ explicit SmartScopedWriter(SmartRWMutex<mt_only>* m) {
+ mutex = m;
+ mutex->writer_acquire();
+ }
+
+ ~SmartScopedWriter() {
+ mutex->writer_release();
+ }
+ };
+ typedef SmartScopedWriter<false> ScopedWriter;
+ }
+}
+
+#endif
diff --git a/include/llvm/System/Threading.h b/include/llvm/System/Threading.h
new file mode 100644
index 000000000000..42d2f89bcb82
--- /dev/null
+++ b/include/llvm/System/Threading.h
@@ -0,0 +1,45 @@
+//===-- llvm/System/Threading.h - Control multithreading mode --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// TThis file defines llvm_start_multithreaded() and friends.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SYSTEM_THREADING_H
+#define LLVM_SYSTEM_THREADING_H
+
+namespace llvm {
+ /// llvm_start_multithreaded - Allocate and initialize structures needed to
+ /// make LLVM safe for multithreading. The return value indicates whether
+ /// multithreaded initialization succeeded. LLVM will still be operational
+ /// on "failed" return, and will still be safe for hosting threading
+ /// applications in the JIT, but will not be safe for concurrent calls to the
+ /// LLVM APIs.
+ /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS.
+ bool llvm_start_multithreaded();
+
+ /// llvm_stop_multithreaded - Deallocate structures necessary to make LLVM
+ /// safe for multithreading.
+ /// THIS MUST EXECUTE IN ISOLATION FROM ALL OTHER LLVM API CALLS.
+ void llvm_stop_multithreaded();
+
+ /// llvm_is_multithreaded - Check whether LLVM is executing in thread-safe
+ /// mode or not.
+ bool llvm_is_multithreaded();
+
+ /// acquire_global_lock - Acquire the global lock. This is a no-op if called
+ /// before llvm_start_multithreaded().
+ void llvm_acquire_global_lock();
+
+ /// release_global_lock - Release the global lock. This is a no-op if called
+ /// before llvm_start_multithreaded().
+ void llvm_release_global_lock();
+}
+
+#endif
diff --git a/include/llvm/Target/DarwinTargetAsmInfo.h b/include/llvm/Target/DarwinTargetAsmInfo.h
index 6241ffe29b8f..171a6b3e1177 100644
--- a/include/llvm/Target/DarwinTargetAsmInfo.h
+++ b/include/llvm/Target/DarwinTargetAsmInfo.h
@@ -23,7 +23,7 @@ namespace llvm {
class Type;
class Mangler;
- struct DarwinTargetAsmInfo: public TargetAsmInfo {
+ struct DarwinTargetAsmInfo : public TargetAsmInfo {
const Section* TextCoalSection;
const Section* ConstTextCoalSection;
const Section* ConstDataCoalSection;
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 3f1cdd27ca39..ebd826a6f4a1 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -274,6 +274,7 @@ def unknown;
class Operand<ValueType ty> {
ValueType Type = ty;
string PrintMethod = "printOperand";
+ string AsmOperandLowerMethod = ?;
dag MIOperandInfo = (ops);
}
diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h
index f223f4765f98..670b0996cc35 100644
--- a/include/llvm/Target/TargetAsmInfo.h
+++ b/include/llvm/Target/TargetAsmInfo.h
@@ -130,7 +130,6 @@ namespace llvm {
private:
mutable StringMap<Section> Sections;
mutable SectionFlags::FlagsStringsMapType FlagsStrings;
- void fillDefaultValues();
protected:
/// TM - The current TargetMachine.
const TargetMachine &TM;
@@ -278,6 +277,10 @@ namespace llvm {
/// use '\1' as the first character.
const char *StringConstantPrefix; // Defaults to ".str"
+ /// AllowQuotesInName - This is true if the assembler allows for complex
+ /// symbol names to be surrounded in quotes. This defaults to false.
+ bool AllowQuotesInName;
+
//===--- Data Emission Directives -------------------------------------===//
/// ZeroDirective - this should be set to the directive used to get some
@@ -308,8 +311,7 @@ namespace llvm {
/// directives for various sizes and non-default address spaces.
virtual const char *getASDirective(unsigned size,
unsigned AS) const {
- assert (AS > 0
- && "Dont know the directives for default addr space");
+ assert(AS > 0 && "Dont know the directives for default addr space");
return NULL;
}
@@ -472,10 +474,6 @@ namespace llvm {
/// encode inline subroutine information.
bool DwarfUsesInlineInfoSection; // Defaults to false.
- /// SupportsMacInfo - true if the Dwarf output supports macro information
- ///
- bool SupportsMacInfoSection; // Defaults to true
-
/// NonLocalEHFrameLabel - If set, the EH_frame label needs to be non-local.
///
bool NonLocalEHFrameLabel; // Defaults to false.
@@ -536,9 +534,9 @@ namespace llvm {
///
const char *DwarfRangesSection; // Defaults to ".debug_ranges".
- /// DwarfMacInfoSection - Section directive for Dwarf info.
+ /// DwarfMacroInfoSection - Section directive for DWARF macro info.
///
- const char *DwarfMacInfoSection; // Defaults to ".debug_macinfo".
+ const char *DwarfMacroInfoSection; // Defaults to ".debug_macinfo".
/// DwarfEHFrameSection - Section directive for Exception frames.
///
@@ -749,6 +747,9 @@ namespace llvm {
const char *getStringConstantPrefix() const {
return StringConstantPrefix;
}
+ bool doesAllowQuotesInName() const {
+ return AllowQuotesInName;
+ }
const char *getZeroDirective() const {
return ZeroDirective;
}
@@ -866,9 +867,6 @@ namespace llvm {
bool doesDwarfUsesInlineInfoSection() const {
return DwarfUsesInlineInfoSection;
}
- bool doesSupportMacInfoSection() const {
- return SupportsMacInfoSection;
- }
bool doesRequireNonLocalEHFrameLabel() const {
return NonLocalEHFrameLabel;
}
@@ -914,8 +912,8 @@ namespace llvm {
const char *getDwarfRangesSection() const {
return DwarfRangesSection;
}
- const char *getDwarfMacInfoSection() const {
- return DwarfMacInfoSection;
+ const char *getDwarfMacroInfoSection() const {
+ return DwarfMacroInfoSection;
}
const char *getDwarfEHFrameSection() const {
return DwarfEHFrameSection;
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 47dcc6c8e48f..40b0e7be480b 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -30,7 +30,7 @@
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/CodeGen/DebugLoc.h"
+#include "llvm/Support/DebugLoc.h"
#include "llvm/Target/TargetMachine.h"
#include <climits>
#include <map>
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index a8db68c59789..33fc45161a6e 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -78,11 +78,13 @@ namespace CodeGenOpt {
};
}
+
+// Possible float ABI settings. Used with FloatABIType in TargetOptions.h.
namespace FloatABI {
enum ABIType {
- Default,
- Soft,
- Hard
+ Default, // Target-specific (either soft of hard depending on triple, etc).
+ Soft, // Soft float.
+ Hard // Hard float.
};
}
diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h
index 0218bfdb2ae3..91e8f80fd108 100644
--- a/include/llvm/Target/TargetRegisterInfo.h
+++ b/include/llvm/Target/TargetRegisterInfo.h
@@ -519,6 +519,36 @@ public:
return NULL;
}
+ /// getAllocationOrder - Returns the register allocation order for a specified
+ /// register class in the form of a pair of TargetRegisterClass iterators.
+ virtual std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
+ getAllocationOrder(const TargetRegisterClass *RC,
+ unsigned HintType, unsigned HintReg,
+ const MachineFunction &MF) const {
+ return std::make_pair(RC->allocation_order_begin(MF),
+ RC->allocation_order_end(MF));
+ }
+
+ /// ResolveRegAllocHint - Resolves the specified register allocation hint
+ /// to a physical register. Returns the physical register if it is successful.
+ virtual unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg,
+ const MachineFunction &MF) const {
+ if (Type == 0 && Reg && isPhysicalRegister(Reg))
+ return Reg;
+ return 0;
+ }
+
+ /// UpdateRegAllocHint - A callback to allow target a chance to update
+ /// register allocation hints when a register is "changed" (e.g. coalesced)
+ /// to another register. e.g. On ARM, some virtual registers should target
+ /// register pairs, if one of pair is coalesced to another register, the
+ /// allocation hint of the other half of the pair should be changed to point
+ /// to the new register.
+ virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
+ MachineFunction &MF) const {
+ // Do nothing.
+ }
+
/// targetHandlesStackFrameRounding - Returns true if the target is
/// responsible for rounding up the stack frame (probably at emitPrologue
/// time).
diff --git a/include/llvm/Target/TargetSelect.h b/include/llvm/Target/TargetSelect.h
new file mode 100644
index 000000000000..8544eed76be7
--- /dev/null
+++ b/include/llvm/Target/TargetSelect.h
@@ -0,0 +1,65 @@
+//===- TargetSelect.h - Target Selection & Registration -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides utilities to make sure that certain classes of targets are
+// linked into the main application executable, and initialize them as
+// appropriate.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_TARGETSELECT_H
+#define LLVM_TARGET_TARGETSELECT_H
+
+#include "llvm/Config/config.h"
+
+namespace llvm {
+ // Declare all of the target-initialization functions that are available.
+#define LLVM_TARGET(TargetName) void Initialize##TargetName##Target();
+#include "llvm/Config/Targets.def"
+
+ // Declare all of the available asm-printer initialization functions.
+ // Declare all of the target-initialization functions.
+#define LLVM_ASM_PRINTER(TargetName) void Initialize##TargetName##AsmPrinter();
+#include "llvm/Config/AsmPrinters.def"
+
+ /// InitializeAllTargets - The main program should call this function if it
+ /// wants to link in all available targets that LLVM is configured to support.
+ inline void InitializeAllTargets() {
+#define LLVM_TARGET(TargetName) llvm::Initialize##TargetName##Target();
+#include "llvm/Config/Targets.def"
+ }
+
+ /// InitializeAllAsmPrinters - The main program should call this function if
+ /// it wants all asm printers that LLVM is configured to support. This will
+ /// cause them to be linked into its executable.
+ inline void InitializeAllAsmPrinters() {
+#define LLVM_ASM_PRINTER(TargetName) Initialize##TargetName##AsmPrinter();
+#include "llvm/Config/AsmPrinters.def"
+ }
+
+
+ /// InitializeNativeTarget - The main program should call this function to
+ /// initialize the native target corresponding to the host. This is useful
+ /// for JIT applications to ensure that the target gets linked in correctly.
+ inline bool InitializeNativeTarget() {
+ // If we have a native target, initialize it to ensure it is linked in.
+#ifdef LLVM_NATIVE_ARCH
+#define DoInit2(TARG, MOD) llvm::Initialize ## TARG ## MOD()
+#define DoInit(T, M) DoInit2(T, M)
+ DoInit(LLVM_NATIVE_ARCH, Target);
+ return false;
+#undef DoInit
+#undef DoInit2
+#else
+ return true;
+#endif
+ }
+}
+
+#endif
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index 2c3fdd4a7884..971baeef9100 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -143,10 +143,10 @@ Pass *createLoopIndexSplitPass();
// this pass is:
//
// FROM CODE TO CODE
-// %X = alloca int, uint 1 ret int 42
-// store int 42, int *%X
-// %Y = load int* %X
-// ret int %Y
+// %X = alloca i32, i32 1 ret i32 42
+// store i32 42, i32 *%X
+// %Y = load i32* %X
+// ret i32 %Y
//
FunctionPass *createPromoteMemoryToRegisterPass();
extern const PassInfo *const PromoteMemoryToRegisterID;
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index 5ea1a500c59e..7ab8721af76c 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -31,6 +31,16 @@ struct DbgInfoIntrinsic;
template<typename T> class SmallVectorImpl;
//===----------------------------------------------------------------------===//
+// Local analysis.
+//
+
+/// isSafeToLoadUnconditionally - Return true if we know that executing a load
+/// from this value cannot trap. If it is not obviously safe to load from the
+/// specified pointer, we do a quick local scan of the basic block containing
+/// ScanFrom, to determine if the address is already accessed.
+bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom);
+
+//===----------------------------------------------------------------------===//
// Local constant propagation.
//
diff --git a/include/llvm/Type.h b/include/llvm/Type.h
index c1732af09bdd..d439233d8c05 100644
--- a/include/llvm/Type.h
+++ b/include/llvm/Type.h
@@ -14,6 +14,7 @@
#include "llvm/AbstractTypeUser.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DataTypes.h"
+#include "llvm/System/Atomic.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator.h"
#include <string>
@@ -102,7 +103,7 @@ private:
/// has no AbstractTypeUsers, the type is deleted. This is only sensical for
/// derived types.
///
- mutable unsigned RefCount;
+ mutable sys::cas_flag RefCount;
const Type *getForwardedTypeInternal() const;
@@ -268,19 +269,16 @@ public:
/// primitive type.
///
unsigned getPrimitiveSizeInBits() const;
-
+
+ /// getScalarSizeInBits - If this is a vector type, return the
+ /// getPrimitiveSizeInBits value for the element type. Otherwise return the
+ /// getPrimitiveSizeInBits value for this type.
+ unsigned getScalarSizeInBits() const;
+
/// getFPMantissaWidth - Return the width of the mantissa of this type. This
- /// is only valid on scalar floating point types. If the FP type does not
+ /// is only valid on floating point types. If the FP type does not
/// have a stable mantissa (e.g. ppc long double), this method returns -1.
- int getFPMantissaWidth() const {
- assert(isFloatingPoint() && "Not a floating point type!");
- if (ID == FloatTyID) return 24;
- if (ID == DoubleTyID) return 53;
- if (ID == X86_FP80TyID) return 64;
- if (ID == FP128TyID) return 113;
- assert(ID == PPC_FP128TyID && "unknown fp type");
- return -1;
- }
+ int getFPMantissaWidth() const;
/// getForwardedType - Return the type that this type has been resolved to if
/// it has been resolved to anything. This is used to implement the
@@ -296,6 +294,10 @@ public:
/// function.
const Type *getVAArgsPromotedType() const;
+ /// getScalarType - If this is a vector type, return the element type,
+ /// otherwise return this.
+ const Type *getScalarType() const;
+
//===--------------------------------------------------------------------===//
// Type Iteration support
//
@@ -336,7 +338,7 @@ public:
void addRef() const {
assert(isAbstract() && "Cannot add a reference to a non-abstract type!");
- ++RefCount;
+ sys::AtomicIncrement(&RefCount);
}
void dropRef() const {
@@ -345,17 +347,15 @@ public:
// If this is the last PATypeHolder using this object, and there are no
// PATypeHandles using it, the type is dead, delete it now.
- if (--RefCount == 0 && AbstractTypeUsers.empty())
+ sys::cas_flag OldCount = sys::AtomicDecrement(&RefCount);
+ if (OldCount == 0 && AbstractTypeUsers.empty())
this->destroy();
}
/// addAbstractTypeUser - Notify an abstract type that there is a new user of
/// it. This function is called primarily by the PATypeHandle class.
///
- void addAbstractTypeUser(AbstractTypeUser *U) const {
- assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!");
- AbstractTypeUsers.push_back(U);
- }
+ void addAbstractTypeUser(AbstractTypeUser *U) const;
/// removeAbstractTypeUser - Notify an abstract type that a user of the class
/// no longer has a handle to the type. This function is called primarily by
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index 261c635feb4a..5aa4d56c4e67 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -365,7 +365,7 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy,
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ops[0])) {
if (TD && CE->getOpcode() == Instruction::IntToPtr) {
Constant *Input = CE->getOperand(0);
- unsigned InWidth = Input->getType()->getPrimitiveSizeInBits();
+ unsigned InWidth = Input->getType()->getScalarSizeInBits();
if (TD->getPointerSizeInBits() < InWidth) {
Constant *Mask =
ConstantInt::get(APInt::getLowBitsSet(InWidth,
@@ -384,7 +384,7 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, const Type *DestTy,
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ops[0])) {
if (TD &&
TD->getPointerSizeInBits() <=
- CE->getType()->getPrimitiveSizeInBits()) {
+ CE->getType()->getScalarSizeInBits()) {
if (CE->getOpcode() == Instruction::PtrToInt) {
Constant *Input = CE->getOperand(0);
Constant *C = FoldBitCast(Input, DestTy, *TD);
diff --git a/lib/Analysis/DebugInfo.cpp b/lib/Analysis/DebugInfo.cpp
index 6bdb64c975cc..adda5eeeb93a 100644
--- a/lib/Analysis/DebugInfo.cpp
+++ b/lib/Analysis/DebugInfo.cpp
@@ -352,7 +352,7 @@ Constant *DIFactory::GetStringConstant(const std::string &String) {
const PointerType *DestTy = PointerType::getUnqual(Type::Int8Ty);
- // If empty string then use a sbyte* null instead.
+ // If empty string then use a i8* null instead.
if (String.empty())
return Slot = ConstantPointerNull::get(DestTy);
diff --git a/lib/Analysis/IVUsers.cpp b/lib/Analysis/IVUsers.cpp
index 7af91304754d..6a53a83665c2 100644
--- a/lib/Analysis/IVUsers.cpp
+++ b/lib/Analysis/IVUsers.cpp
@@ -82,11 +82,8 @@ static bool containsAddRecFromDifferentLoop(SCEVHandle S, Loop *L) {
/// outer loop of the current loop.
static bool getSCEVStartAndStride(const SCEVHandle &SH, Loop *L, Loop *UseLoop,
SCEVHandle &Start, SCEVHandle &Stride,
- bool &isSigned,
ScalarEvolution *SE, DominatorTree *DT) {
SCEVHandle TheAddRec = Start; // Initialize to zero.
- bool isSExt = false;
- bool isZExt = false;
// If the outer level is an AddExpr, the operands are all start values except
// for a nested AddRecExpr.
@@ -101,13 +98,6 @@ static bool getSCEVStartAndStride(const SCEVHandle &SH, Loop *L, Loop *UseLoop,
} else {
Start = SE->getAddExpr(Start, AE->getOperand(i));
}
-
- } else if (const SCEVZeroExtendExpr *Z = dyn_cast<SCEVZeroExtendExpr>(SH)) {
- TheAddRec = Z->getOperand();
- isZExt = true;
- } else if (const SCEVSignExtendExpr *S = dyn_cast<SCEVSignExtendExpr>(SH)) {
- TheAddRec = S->getOperand();
- isSExt = true;
} else if (isa<SCEVAddRecExpr>(SH)) {
TheAddRec = SH;
} else {
@@ -120,9 +110,8 @@ static bool getSCEVStartAndStride(const SCEVHandle &SH, Loop *L, Loop *UseLoop,
// Use getSCEVAtScope to attempt to simplify other loops out of
// the picture.
SCEVHandle AddRecStart = AddRec->getStart();
- SCEVHandle BetterAddRecStart = SE->getSCEVAtScope(AddRecStart, UseLoop);
- if (!isa<SCEVCouldNotCompute>(BetterAddRecStart))
- AddRecStart = BetterAddRecStart;
+ AddRecStart = SE->getSCEVAtScope(AddRecStart, UseLoop);
+ SCEVHandle 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
@@ -131,24 +120,20 @@ static bool getSCEVStartAndStride(const SCEVHandle &SH, Loop *L, Loop *UseLoop,
if (containsAddRecFromDifferentLoop(AddRecStart, L))
return false;
- if (isSExt || isZExt)
- Start = SE->getTruncateExpr(Start, AddRec->getType());
-
Start = SE->getAddExpr(Start, AddRecStart);
- if (!isa<SCEVConstant>(AddRec->getStepRecurrence(*SE))) {
- // If stride is an instruction, make sure it dominates the loop preheader.
- // Otherwise we could end up with a use before def situation.
+ // If stride is an instruction, make sure it dominates the loop preheader.
+ // Otherwise we could end up with a use before def situation.
+ if (!isa<SCEVConstant>(AddRecStride)) {
BasicBlock *Preheader = L->getLoopPreheader();
- if (!AddRec->getStepRecurrence(*SE)->dominates(Preheader, DT))
+ if (!AddRecStride->dominates(Preheader, DT))
return false;
DOUT << "[" << L->getHeader()->getName()
<< "] Variable stride: " << *AddRec << "\n";
}
- Stride = AddRec->getStepRecurrence(*SE);
- isSigned = isSExt;
+ Stride = AddRecStride;
return true;
}
@@ -218,9 +203,8 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) {
Loop *UseLoop = LI->getLoopFor(I->getParent());
SCEVHandle Start = SE->getIntegerSCEV(0, ISE->getType());
SCEVHandle Stride = Start;
- bool isSigned = false; // Arbitrary initial value - pacifies compiler.
- if (!getSCEVStartAndStride(ISE, L, UseLoop, Start, Stride, isSigned, SE, DT))
+ if (!getSCEVStartAndStride(ISE, L, UseLoop, Start, Stride, SE, DT))
return false; // Non-reducible symbolic expression, bail out.
SmallPtrSet<Instruction *, 4> UniqueUsers;
@@ -271,11 +255,11 @@ bool IVUsers::AddUsersIfInteresting(Instruction *I) {
// The value used will be incremented by the stride more than we are
// expecting, so subtract this off.
SCEVHandle NewStart = SE->getMinusSCEV(Start, Stride);
- StrideUses->addUser(NewStart, User, I, isSigned);
+ StrideUses->addUser(NewStart, User, I);
StrideUses->Users.back().setIsUseOfPostIncrementedValue(true);
DOUT << " USING POSTINC SCEV, START=" << *NewStart<< "\n";
} else {
- StrideUses->addUser(Start, User, I, isSigned);
+ StrideUses->addUser(Start, User, I);
}
}
}
@@ -312,7 +296,6 @@ bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) {
/// getReplacementExpr - Return a SCEV expression which computes the
/// value of the OperandValToReplace of the given IVStrideUse.
SCEVHandle IVUsers::getReplacementExpr(const IVStrideUse &U) const {
- const Type *UseTy = U.getOperandValToReplace()->getType();
// Start with zero.
SCEVHandle RetVal = SE->getIntegerSCEV(0, U.getParent()->Stride->getType());
// Create the basic add recurrence.
@@ -326,17 +309,9 @@ SCEVHandle IVUsers::getReplacementExpr(const IVStrideUse &U) const {
// Evaluate the expression out of the loop, if possible.
if (!L->contains(U.getUser()->getParent())) {
SCEVHandle ExitVal = SE->getSCEVAtScope(RetVal, L->getParentLoop());
- if (!isa<SCEVCouldNotCompute>(ExitVal) && ExitVal->isLoopInvariant(L))
+ if (ExitVal->isLoopInvariant(L))
RetVal = ExitVal;
}
- // Promote the result to the type of the use.
- if (SE->getTypeSizeInBits(RetVal->getType()) !=
- SE->getTypeSizeInBits(UseTy)) {
- if (U.isSigned())
- RetVal = SE->getSignExtendExpr(RetVal, UseTy);
- else
- RetVal = SE->getZeroExtendExpr(RetVal, UseTy);
- }
return RetVal;
}
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index 98ab6f484ea1..68aa595aa8dd 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -68,6 +68,7 @@
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CommandLine.h"
@@ -132,7 +133,8 @@ bool SCEV::isOne() const {
return false;
}
-SCEVCouldNotCompute::SCEVCouldNotCompute() : SCEV(scCouldNotCompute) {}
+SCEVCouldNotCompute::SCEVCouldNotCompute(const ScalarEvolution* p) :
+ SCEV(scCouldNotCompute, p) {}
SCEVCouldNotCompute::~SCEVCouldNotCompute() {}
bool SCEVCouldNotCompute::isLoopInvariant(const Loop *L) const {
@@ -178,7 +180,7 @@ SCEVConstant::~SCEVConstant() {
SCEVHandle ScalarEvolution::getConstant(ConstantInt *V) {
SCEVConstant *&R = (*SCEVConstants)[V];
- if (R == 0) R = new SCEVConstant(V);
+ if (R == 0) R = new SCEVConstant(V, this);
return R;
}
@@ -186,6 +188,11 @@ SCEVHandle ScalarEvolution::getConstant(const APInt& Val) {
return getConstant(ConstantInt::get(Val));
}
+SCEVHandle
+ScalarEvolution::getConstant(const Type *Ty, uint64_t V, bool isSigned) {
+ return getConstant(ConstantInt::get(cast<IntegerType>(Ty), V, isSigned));
+}
+
const Type *SCEVConstant::getType() const { return V->getType(); }
void SCEVConstant::print(raw_ostream &OS) const {
@@ -193,8 +200,9 @@ void SCEVConstant::print(raw_ostream &OS) const {
}
SCEVCastExpr::SCEVCastExpr(unsigned SCEVTy,
- const SCEVHandle &op, const Type *ty)
- : SCEV(SCEVTy), Op(op), Ty(ty) {}
+ const SCEVHandle &op, const Type *ty,
+ const ScalarEvolution* p)
+ : SCEV(SCEVTy, p), Op(op), Ty(ty) {}
SCEVCastExpr::~SCEVCastExpr() {}
@@ -208,8 +216,9 @@ bool SCEVCastExpr::dominates(BasicBlock *BB, DominatorTree *DT) const {
static ManagedStatic<std::map<std::pair<const SCEV*, const Type*>,
SCEVTruncateExpr*> > SCEVTruncates;
-SCEVTruncateExpr::SCEVTruncateExpr(const SCEVHandle &op, const Type *ty)
- : SCEVCastExpr(scTruncate, op, ty) {
+SCEVTruncateExpr::SCEVTruncateExpr(const SCEVHandle &op, const Type *ty,
+ const ScalarEvolution* p)
+ : SCEVCastExpr(scTruncate, op, ty, p) {
assert((Op->getType()->isInteger() || isa<PointerType>(Op->getType())) &&
(Ty->isInteger() || isa<PointerType>(Ty)) &&
"Cannot truncate non-integer value!");
@@ -229,8 +238,9 @@ void SCEVTruncateExpr::print(raw_ostream &OS) const {
static ManagedStatic<std::map<std::pair<const SCEV*, const Type*>,
SCEVZeroExtendExpr*> > SCEVZeroExtends;
-SCEVZeroExtendExpr::SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty)
- : SCEVCastExpr(scZeroExtend, op, ty) {
+SCEVZeroExtendExpr::SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty,
+ const ScalarEvolution* p)
+ : SCEVCastExpr(scZeroExtend, op, ty, p) {
assert((Op->getType()->isInteger() || isa<PointerType>(Op->getType())) &&
(Ty->isInteger() || isa<PointerType>(Ty)) &&
"Cannot zero extend non-integer value!");
@@ -250,8 +260,9 @@ void SCEVZeroExtendExpr::print(raw_ostream &OS) const {
static ManagedStatic<std::map<std::pair<const SCEV*, const Type*>,
SCEVSignExtendExpr*> > SCEVSignExtends;
-SCEVSignExtendExpr::SCEVSignExtendExpr(const SCEVHandle &op, const Type *ty)
- : SCEVCastExpr(scSignExtend, op, ty) {
+SCEVSignExtendExpr::SCEVSignExtendExpr(const SCEVHandle &op, const Type *ty,
+ const ScalarEvolution* p)
+ : SCEVCastExpr(scSignExtend, op, ty, p) {
assert((Op->getType()->isInteger() || isa<PointerType>(Op->getType())) &&
(Ty->isInteger() || isa<PointerType>(Ty)) &&
"Cannot sign extend non-integer value!");
@@ -293,7 +304,7 @@ replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
SCEVHandle H =
getOperand(i)->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H != getOperand(i)) {
- std::vector<SCEVHandle> NewOps;
+ SmallVector<SCEVHandle, 8> NewOps;
NewOps.reserve(getNumOperands());
for (unsigned j = 0; j != i; ++j)
NewOps.push_back(getOperand(j));
@@ -373,7 +384,7 @@ replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
SCEVHandle H =
getOperand(i)->replaceSymbolicValuesWithConcrete(Sym, Conc, SE);
if (H != getOperand(i)) {
- std::vector<SCEVHandle> NewOps;
+ SmallVector<SCEVHandle, 8> NewOps;
NewOps.reserve(getNumOperands());
for (unsigned j = 0; j != i; ++j)
NewOps.push_back(getOperand(j));
@@ -504,9 +515,18 @@ namespace {
return false;
}
- // Constant sorting doesn't matter since they'll be folded.
- if (isa<SCEVConstant>(LHS))
- return false;
+ // Compare constant values.
+ if (const SCEVConstant *LC = dyn_cast<SCEVConstant>(LHS)) {
+ const SCEVConstant *RC = cast<SCEVConstant>(RHS);
+ return LC->getValue()->getValue().ult(RC->getValue()->getValue());
+ }
+
+ // Compare addrec loop depths.
+ if (const SCEVAddRecExpr *LA = dyn_cast<SCEVAddRecExpr>(LHS)) {
+ const SCEVAddRecExpr *RA = cast<SCEVAddRecExpr>(RHS);
+ if (LA->getLoop()->getLoopDepth() != RA->getLoop()->getLoopDepth())
+ return LA->getLoop()->getLoopDepth() < RA->getLoop()->getLoopDepth();
+ }
// Lexicographically compare n-ary expressions.
if (const SCEVNAryExpr *LC = dyn_cast<SCEVNAryExpr>(LHS)) {
@@ -558,7 +578,7 @@ namespace {
/// this to depend on where the addresses of various SCEV objects happened to
/// land in memory.
///
-static void GroupByComplexity(std::vector<SCEVHandle> &Ops,
+static void GroupByComplexity(SmallVectorImpl<SCEVHandle> &Ops,
LoopInfo *LI) {
if (Ops.size() < 2) return; // Noop
if (Ops.size() == 2) {
@@ -763,17 +783,16 @@ SCEVHandle ScalarEvolution::getTruncateExpr(const SCEVHandle &Op,
if (const SCEVZeroExtendExpr *SZ = dyn_cast<SCEVZeroExtendExpr>(Op))
return getTruncateOrZeroExtend(SZ->getOperand(), Ty);
- // If the input value is a chrec scev made out of constants, truncate
- // all of the constants.
+ // If the input value is a chrec scev, truncate the chrec's operands.
if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Op)) {
- std::vector<SCEVHandle> Operands;
+ SmallVector<SCEVHandle, 4> Operands;
for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i)
Operands.push_back(getTruncateExpr(AddRec->getOperand(i), Ty));
return getAddRecExpr(Operands, AddRec->getLoop());
}
SCEVTruncateExpr *&Result = (*SCEVTruncates)[std::make_pair(Op, Ty)];
- if (Result == 0) Result = new SCEVTruncateExpr(Op, Ty);
+ if (Result == 0) Result = new SCEVTruncateExpr(Op, Ty, this);
return Result;
}
@@ -861,7 +880,7 @@ SCEVHandle ScalarEvolution::getZeroExtendExpr(const SCEVHandle &Op,
}
SCEVZeroExtendExpr *&Result = (*SCEVZeroExtends)[std::make_pair(Op, Ty)];
- if (Result == 0) Result = new SCEVZeroExtendExpr(Op, Ty);
+ if (Result == 0) Result = new SCEVZeroExtendExpr(Op, Ty, this);
return Result;
}
@@ -933,7 +952,7 @@ SCEVHandle ScalarEvolution::getSignExtendExpr(const SCEVHandle &Op,
}
SCEVSignExtendExpr *&Result = (*SCEVSignExtends)[std::make_pair(Op, Ty)];
- if (Result == 0) Result = new SCEVSignExtendExpr(Op, Ty);
+ if (Result == 0) Result = new SCEVSignExtendExpr(Op, Ty, this);
return Result;
}
@@ -979,9 +998,105 @@ SCEVHandle ScalarEvolution::getAnyExtendExpr(const SCEVHandle &Op,
return ZExt;
}
+/// CollectAddOperandsWithScales - Process the given Ops list, which is
+/// a list of operands to be added under the given scale, update the given
+/// map. This is a helper function for getAddRecExpr. As an example of
+/// what it does, given a sequence of operands that would form an add
+/// expression like this:
+///
+/// m + n + 13 + (A * (o + p + (B * q + m + 29))) + r + (-1 * r)
+///
+/// where A and B are constants, update the map with these values:
+///
+/// (m, 1+A*B), (n, 1), (o, A), (p, A), (q, A*B), (r, 0)
+///
+/// and add 13 + A*B*29 to AccumulatedConstant.
+/// This will allow getAddRecExpr to produce this:
+///
+/// 13+A*B*29 + n + (m * (1+A*B)) + ((o + p) * A) + (q * A*B)
+///
+/// This form often exposes folding opportunities that are hidden in
+/// the original operand list.
+///
+/// Return true iff it appears that any interesting folding opportunities
+/// may be exposed. This helps getAddRecExpr short-circuit extra work in
+/// the common case where no interesting opportunities are present, and
+/// is also used as a check to avoid infinite recursion.
+///
+static bool
+CollectAddOperandsWithScales(DenseMap<SCEVHandle, APInt> &M,
+ SmallVector<SCEVHandle, 8> &NewOps,
+ APInt &AccumulatedConstant,
+ const SmallVectorImpl<SCEVHandle> &Ops,
+ const APInt &Scale,
+ ScalarEvolution &SE) {
+ bool Interesting = false;
+
+ // Iterate over the add operands.
+ for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
+ const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[i]);
+ if (Mul && isa<SCEVConstant>(Mul->getOperand(0))) {
+ APInt NewScale =
+ Scale * cast<SCEVConstant>(Mul->getOperand(0))->getValue()->getValue();
+ if (Mul->getNumOperands() == 2 && isa<SCEVAddExpr>(Mul->getOperand(1))) {
+ // A multiplication of a constant with another add; recurse.
+ Interesting |=
+ CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant,
+ cast<SCEVAddExpr>(Mul->getOperand(1))
+ ->getOperands(),
+ NewScale, SE);
+ } else {
+ // A multiplication of a constant with some other value. Update
+ // the map.
+ SmallVector<SCEVHandle, 4> MulOps(Mul->op_begin()+1, Mul->op_end());
+ SCEVHandle Key = SE.getMulExpr(MulOps);
+ std::pair<DenseMap<SCEVHandle, APInt>::iterator, bool> Pair =
+ M.insert(std::make_pair(Key, APInt()));
+ if (Pair.second) {
+ Pair.first->second = NewScale;
+ NewOps.push_back(Pair.first->first);
+ } else {
+ Pair.first->second += NewScale;
+ // The map already had an entry for this value, which may indicate
+ // a folding opportunity.
+ Interesting = true;
+ }
+ }
+ } else if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Ops[i])) {
+ // Pull a buried constant out to the outside.
+ if (Scale != 1 || AccumulatedConstant != 0 || C->isZero())
+ Interesting = true;
+ AccumulatedConstant += Scale * C->getValue()->getValue();
+ } else {
+ // An ordinary operand. Update the map.
+ std::pair<DenseMap<SCEVHandle, APInt>::iterator, bool> Pair =
+ M.insert(std::make_pair(Ops[i], APInt()));
+ if (Pair.second) {
+ Pair.first->second = Scale;
+ NewOps.push_back(Pair.first->first);
+ } else {
+ Pair.first->second += Scale;
+ // The map already had an entry for this value, which may indicate
+ // a folding opportunity.
+ Interesting = true;
+ }
+ }
+ }
+
+ return Interesting;
+}
+
+namespace {
+ struct APIntCompare {
+ bool operator()(const APInt &LHS, const APInt &RHS) const {
+ return LHS.ult(RHS);
+ }
+ };
+}
+
/// getAddExpr - Get a canonical add expression, or something simpler if
/// possible.
-SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
+SCEVHandle ScalarEvolution::getAddExpr(SmallVectorImpl<SCEVHandle> &Ops) {
assert(!Ops.empty() && "Cannot get empty add!");
if (Ops.size() == 1) return Ops[0];
#ifndef NDEBUG
@@ -1001,11 +1116,10 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
assert(Idx < Ops.size());
while (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(Ops[Idx])) {
// We found two constants, fold them together!
- ConstantInt *Fold = ConstantInt::get(LHSC->getValue()->getValue() +
- RHSC->getValue()->getValue());
- Ops[0] = getConstant(Fold);
+ Ops[0] = getConstant(LHSC->getValue()->getValue() +
+ RHSC->getValue()->getValue());
+ if (Ops.size() == 2) return Ops[0];
Ops.erase(Ops.begin()+1); // Erase the folded element
- if (Ops.size() == 1) return Ops[0];
LHSC = cast<SCEVConstant>(Ops[0]);
}
@@ -1043,7 +1157,7 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
const SCEVTruncateExpr *Trunc = cast<SCEVTruncateExpr>(Ops[Idx]);
const Type *DstType = Trunc->getType();
const Type *SrcType = Trunc->getOperand()->getType();
- std::vector<SCEVHandle> LargeOps;
+ SmallVector<SCEVHandle, 8> LargeOps;
bool Ok = true;
// Check all the operands to see if they can be represented in the
// source type of the truncate.
@@ -1059,7 +1173,7 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
// is much more likely to be foldable here.
LargeOps.push_back(getSignExtendExpr(C, SrcType));
} else if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Ops[i])) {
- std::vector<SCEVHandle> LargeMulOps;
+ SmallVector<SCEVHandle, 8> LargeMulOps;
for (unsigned j = 0, f = M->getNumOperands(); j != f && Ok; ++j) {
if (const SCEVTruncateExpr *T =
dyn_cast<SCEVTruncateExpr>(M->getOperand(j))) {
@@ -1120,6 +1234,38 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
while (Idx < Ops.size() && Ops[Idx]->getSCEVType() < scMulExpr)
++Idx;
+ // Check to see if there are any folding opportunities present with
+ // operands multiplied by constant values.
+ if (Idx < Ops.size() && isa<SCEVMulExpr>(Ops[Idx])) {
+ uint64_t BitWidth = getTypeSizeInBits(Ty);
+ DenseMap<SCEVHandle, APInt> M;
+ SmallVector<SCEVHandle, 8> NewOps;
+ APInt AccumulatedConstant(BitWidth, 0);
+ if (CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant,
+ Ops, APInt(BitWidth, 1), *this)) {
+ // Some interesting folding opportunity is present, so its worthwhile to
+ // re-generate the operands list. Group the operands by constant scale,
+ // to avoid multiplying by the same constant scale multiple times.
+ std::map<APInt, SmallVector<SCEVHandle, 4>, APIntCompare> MulOpLists;
+ for (SmallVector<SCEVHandle, 8>::iterator I = NewOps.begin(),
+ E = NewOps.end(); I != E; ++I)
+ MulOpLists[M.find(*I)->second].push_back(*I);
+ // Re-generate the operands list.
+ Ops.clear();
+ if (AccumulatedConstant != 0)
+ Ops.push_back(getConstant(AccumulatedConstant));
+ for (std::map<APInt, SmallVector<SCEVHandle, 4>, APIntCompare>::iterator I =
+ MulOpLists.begin(), E = MulOpLists.end(); I != E; ++I)
+ if (I->first != 0)
+ Ops.push_back(getMulExpr(getConstant(I->first), getAddExpr(I->second)));
+ if (Ops.empty())
+ return getIntegerSCEV(0, Ty);
+ if (Ops.size() == 1)
+ return Ops[0];
+ return getAddExpr(Ops);
+ }
+ }
+
// If we are adding something to a multiply expression, make sure the
// something is not already an operand of the multiply. If so, merge it into
// the multiply.
@@ -1128,13 +1274,13 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
for (unsigned MulOp = 0, e = Mul->getNumOperands(); MulOp != e; ++MulOp) {
const SCEV *MulOpSCEV = Mul->getOperand(MulOp);
for (unsigned AddOp = 0, e = Ops.size(); AddOp != e; ++AddOp)
- if (MulOpSCEV == Ops[AddOp] && !isa<SCEVConstant>(MulOpSCEV)) {
+ if (MulOpSCEV == Ops[AddOp] && !isa<SCEVConstant>(Ops[AddOp])) {
// Fold W + X + (X * Y * Z) --> W + (X * ((Y*Z)+1))
SCEVHandle InnerMul = Mul->getOperand(MulOp == 0);
if (Mul->getNumOperands() != 2) {
// If the multiply has more than two operands, we must get the
// Y*Z term.
- std::vector<SCEVHandle> MulOps(Mul->op_begin(), Mul->op_end());
+ SmallVector<SCEVHandle, 4> MulOps(Mul->op_begin(), Mul->op_end());
MulOps.erase(MulOps.begin()+MulOp);
InnerMul = getMulExpr(MulOps);
}
@@ -1166,13 +1312,13 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
// Fold X + (A*B*C) + (A*D*E) --> X + (A*(B*C+D*E))
SCEVHandle InnerMul1 = Mul->getOperand(MulOp == 0);
if (Mul->getNumOperands() != 2) {
- std::vector<SCEVHandle> MulOps(Mul->op_begin(), Mul->op_end());
+ SmallVector<SCEVHandle, 4> MulOps(Mul->op_begin(), Mul->op_end());
MulOps.erase(MulOps.begin()+MulOp);
InnerMul1 = getMulExpr(MulOps);
}
SCEVHandle InnerMul2 = OtherMul->getOperand(OMulOp == 0);
if (OtherMul->getNumOperands() != 2) {
- std::vector<SCEVHandle> MulOps(OtherMul->op_begin(),
+ SmallVector<SCEVHandle, 4> MulOps(OtherMul->op_begin(),
OtherMul->op_end());
MulOps.erase(MulOps.begin()+OMulOp);
InnerMul2 = getMulExpr(MulOps);
@@ -1199,7 +1345,7 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
for (; Idx < Ops.size() && isa<SCEVAddRecExpr>(Ops[Idx]); ++Idx) {
// Scan all of the other operands to this add and add them to the vector if
// they are loop invariant w.r.t. the recurrence.
- std::vector<SCEVHandle> LIOps;
+ SmallVector<SCEVHandle, 8> LIOps;
const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
if (Ops[i]->isLoopInvariant(AddRec->getLoop())) {
@@ -1213,7 +1359,8 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
// NLI + LI + {Start,+,Step} --> NLI + {LI+Start,+,Step}
LIOps.push_back(AddRec->getStart());
- std::vector<SCEVHandle> AddRecOps(AddRec->op_begin(), AddRec->op_end());
+ SmallVector<SCEVHandle, 4> AddRecOps(AddRec->op_begin(),
+ AddRec->op_end());
AddRecOps[0] = getAddExpr(LIOps);
SCEVHandle NewRec = getAddRecExpr(AddRecOps, AddRec->getLoop());
@@ -1238,7 +1385,7 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
const SCEVAddRecExpr *OtherAddRec = cast<SCEVAddRecExpr>(Ops[OtherIdx]);
if (AddRec->getLoop() == OtherAddRec->getLoop()) {
// Other + {A,+,B} + {C,+,D} --> Other + {A+C,+,B+D}
- std::vector<SCEVHandle> NewOps(AddRec->op_begin(), AddRec->op_end());
+ SmallVector<SCEVHandle, 4> NewOps(AddRec->op_begin(), AddRec->op_end());
for (unsigned i = 0, e = OtherAddRec->getNumOperands(); i != e; ++i) {
if (i >= NewOps.size()) {
NewOps.insert(NewOps.end(), OtherAddRec->op_begin()+i,
@@ -1267,14 +1414,14 @@ SCEVHandle ScalarEvolution::getAddExpr(std::vector<SCEVHandle> &Ops) {
std::vector<const SCEV*> SCEVOps(Ops.begin(), Ops.end());
SCEVCommutativeExpr *&Result = (*SCEVCommExprs)[std::make_pair(scAddExpr,
SCEVOps)];
- if (Result == 0) Result = new SCEVAddExpr(Ops);
+ if (Result == 0) Result = new SCEVAddExpr(Ops, this);
return Result;
}
/// getMulExpr - Get a canonical multiply expression, or something simpler if
/// possible.
-SCEVHandle ScalarEvolution::getMulExpr(std::vector<SCEVHandle> &Ops) {
+SCEVHandle ScalarEvolution::getMulExpr(SmallVectorImpl<SCEVHandle> &Ops) {
assert(!Ops.empty() && "Cannot get empty mul!");
#ifndef NDEBUG
for (unsigned i = 1, e = Ops.size(); i != e; ++i)
@@ -1355,7 +1502,7 @@ SCEVHandle ScalarEvolution::getMulExpr(std::vector<SCEVHandle> &Ops) {
for (; Idx < Ops.size() && isa<SCEVAddRecExpr>(Ops[Idx]); ++Idx) {
// Scan all of the other operands to this mul and add them to the vector if
// they are loop invariant w.r.t. the recurrence.
- std::vector<SCEVHandle> LIOps;
+ SmallVector<SCEVHandle, 8> LIOps;
const SCEVAddRecExpr *AddRec = cast<SCEVAddRecExpr>(Ops[Idx]);
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
if (Ops[i]->isLoopInvariant(AddRec->getLoop())) {
@@ -1367,7 +1514,7 @@ SCEVHandle ScalarEvolution::getMulExpr(std::vector<SCEVHandle> &Ops) {
// If we found some loop invariants, fold them into the recurrence.
if (!LIOps.empty()) {
// NLI * LI * {Start,+,Step} --> NLI * {LI*Start,+,LI*Step}
- std::vector<SCEVHandle> NewOps;
+ SmallVector<SCEVHandle, 4> NewOps;
NewOps.reserve(AddRec->getNumOperands());
if (LIOps.size() == 1) {
const SCEV *Scale = LIOps[0];
@@ -1375,7 +1522,7 @@ SCEVHandle ScalarEvolution::getMulExpr(std::vector<SCEVHandle> &Ops) {
NewOps.push_back(getMulExpr(Scale, AddRec->getOperand(i)));
} else {
for (unsigned i = 0, e = AddRec->getNumOperands(); i != e; ++i) {
- std::vector<SCEVHandle> MulOps(LIOps);
+ SmallVector<SCEVHandle, 4> MulOps(LIOps.begin(), LIOps.end());
MulOps.push_back(AddRec->getOperand(i));
NewOps.push_back(getMulExpr(MulOps));
}
@@ -1433,7 +1580,7 @@ SCEVHandle ScalarEvolution::getMulExpr(std::vector<SCEVHandle> &Ops) {
SCEVCommutativeExpr *&Result = (*SCEVCommExprs)[std::make_pair(scMulExpr,
SCEVOps)];
if (Result == 0)
- Result = new SCEVMulExpr(Ops);
+ Result = new SCEVMulExpr(Ops, this);
return Result;
}
@@ -1473,14 +1620,14 @@ SCEVHandle ScalarEvolution::getUDivExpr(const SCEVHandle &LHS,
getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy),
getZeroExtendExpr(Step, ExtTy),
AR->getLoop())) {
- std::vector<SCEVHandle> Operands;
+ SmallVector<SCEVHandle, 4> Operands;
for (unsigned i = 0, e = AR->getNumOperands(); i != e; ++i)
Operands.push_back(getUDivExpr(AR->getOperand(i), RHS));
return getAddRecExpr(Operands, AR->getLoop());
}
// (A*B)/C --> A*(B/C) if safe and B/C can be folded.
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(LHS)) {
- std::vector<SCEVHandle> Operands;
+ SmallVector<SCEVHandle, 4> Operands;
for (unsigned i = 0, e = M->getNumOperands(); i != e; ++i)
Operands.push_back(getZeroExtendExpr(M->getOperand(i), ExtTy));
if (getZeroExtendExpr(M, ExtTy) == getMulExpr(Operands))
@@ -1489,7 +1636,9 @@ SCEVHandle ScalarEvolution::getUDivExpr(const SCEVHandle &LHS,
SCEVHandle Op = M->getOperand(i);
SCEVHandle Div = getUDivExpr(Op, RHSC);
if (!isa<SCEVUDivExpr>(Div) && getMulExpr(Div, RHSC) == Op) {
- Operands = M->getOperands();
+ const SmallVectorImpl<SCEVHandle> &MOperands = M->getOperands();
+ Operands = SmallVector<SCEVHandle, 4>(MOperands.begin(),
+ MOperands.end());
Operands[i] = Div;
return getMulExpr(Operands);
}
@@ -1497,7 +1646,7 @@ SCEVHandle ScalarEvolution::getUDivExpr(const SCEVHandle &LHS,
}
// (A+B)/C --> (A/C + B/C) if safe and A/C and B/C can be folded.
if (const SCEVAddRecExpr *A = dyn_cast<SCEVAddRecExpr>(LHS)) {
- std::vector<SCEVHandle> Operands;
+ SmallVector<SCEVHandle, 4> Operands;
for (unsigned i = 0, e = A->getNumOperands(); i != e; ++i)
Operands.push_back(getZeroExtendExpr(A->getOperand(i), ExtTy));
if (getZeroExtendExpr(A, ExtTy) == getAddExpr(Operands)) {
@@ -1522,7 +1671,7 @@ SCEVHandle ScalarEvolution::getUDivExpr(const SCEVHandle &LHS,
}
SCEVUDivExpr *&Result = (*SCEVUDivs)[std::make_pair(LHS, RHS)];
- if (Result == 0) Result = new SCEVUDivExpr(LHS, RHS);
+ if (Result == 0) Result = new SCEVUDivExpr(LHS, RHS, this);
return Result;
}
@@ -1531,7 +1680,7 @@ SCEVHandle ScalarEvolution::getUDivExpr(const SCEVHandle &LHS,
/// Simplify the expression as much as possible.
SCEVHandle ScalarEvolution::getAddRecExpr(const SCEVHandle &Start,
const SCEVHandle &Step, const Loop *L) {
- std::vector<SCEVHandle> Operands;
+ SmallVector<SCEVHandle, 4> Operands;
Operands.push_back(Start);
if (const SCEVAddRecExpr *StepChrec = dyn_cast<SCEVAddRecExpr>(Step))
if (StepChrec->getLoop() == L) {
@@ -1546,7 +1695,7 @@ SCEVHandle ScalarEvolution::getAddRecExpr(const SCEVHandle &Start,
/// getAddRecExpr - Get an add recurrence expression for the specified loop.
/// Simplify the expression as much as possible.
-SCEVHandle ScalarEvolution::getAddRecExpr(std::vector<SCEVHandle> &Operands,
+SCEVHandle ScalarEvolution::getAddRecExpr(SmallVectorImpl<SCEVHandle> &Operands,
const Loop *L) {
if (Operands.size() == 1) return Operands[0];
#ifndef NDEBUG
@@ -1565,8 +1714,8 @@ SCEVHandle ScalarEvolution::getAddRecExpr(std::vector<SCEVHandle> &Operands,
if (const SCEVAddRecExpr *NestedAR = dyn_cast<SCEVAddRecExpr>(Operands[0])) {
const Loop* NestedLoop = NestedAR->getLoop();
if (L->getLoopDepth() < NestedLoop->getLoopDepth()) {
- std::vector<SCEVHandle> NestedOperands(NestedAR->op_begin(),
- NestedAR->op_end());
+ SmallVector<SCEVHandle, 4> NestedOperands(NestedAR->op_begin(),
+ NestedAR->op_end());
SCEVHandle NestedARHandle(NestedAR);
Operands[0] = NestedAR->getStart();
NestedOperands[0] = getAddRecExpr(Operands, L);
@@ -1576,19 +1725,20 @@ SCEVHandle ScalarEvolution::getAddRecExpr(std::vector<SCEVHandle> &Operands,
std::vector<const SCEV*> SCEVOps(Operands.begin(), Operands.end());
SCEVAddRecExpr *&Result = (*SCEVAddRecExprs)[std::make_pair(L, SCEVOps)];
- if (Result == 0) Result = new SCEVAddRecExpr(Operands, L);
+ if (Result == 0) Result = new SCEVAddRecExpr(Operands, L, this);
return Result;
}
SCEVHandle ScalarEvolution::getSMaxExpr(const SCEVHandle &LHS,
const SCEVHandle &RHS) {
- std::vector<SCEVHandle> Ops;
+ SmallVector<SCEVHandle, 2> Ops;
Ops.push_back(LHS);
Ops.push_back(RHS);
return getSMaxExpr(Ops);
}
-SCEVHandle ScalarEvolution::getSMaxExpr(std::vector<SCEVHandle> Ops) {
+SCEVHandle
+ScalarEvolution::getSMaxExpr(SmallVectorImpl<SCEVHandle> &Ops) {
assert(!Ops.empty() && "Cannot get empty smax!");
if (Ops.size() == 1) return Ops[0];
#ifndef NDEBUG
@@ -1662,19 +1812,20 @@ SCEVHandle ScalarEvolution::getSMaxExpr(std::vector<SCEVHandle> Ops) {
std::vector<const SCEV*> SCEVOps(Ops.begin(), Ops.end());
SCEVCommutativeExpr *&Result = (*SCEVCommExprs)[std::make_pair(scSMaxExpr,
SCEVOps)];
- if (Result == 0) Result = new SCEVSMaxExpr(Ops);
+ if (Result == 0) Result = new SCEVSMaxExpr(Ops, this);
return Result;
}
SCEVHandle ScalarEvolution::getUMaxExpr(const SCEVHandle &LHS,
const SCEVHandle &RHS) {
- std::vector<SCEVHandle> Ops;
+ SmallVector<SCEVHandle, 2> Ops;
Ops.push_back(LHS);
Ops.push_back(RHS);
return getUMaxExpr(Ops);
}
-SCEVHandle ScalarEvolution::getUMaxExpr(std::vector<SCEVHandle> Ops) {
+SCEVHandle
+ScalarEvolution::getUMaxExpr(SmallVectorImpl<SCEVHandle> &Ops) {
assert(!Ops.empty() && "Cannot get empty umax!");
if (Ops.size() == 1) return Ops[0];
#ifndef NDEBUG
@@ -1748,17 +1899,29 @@ SCEVHandle ScalarEvolution::getUMaxExpr(std::vector<SCEVHandle> Ops) {
std::vector<const SCEV*> SCEVOps(Ops.begin(), Ops.end());
SCEVCommutativeExpr *&Result = (*SCEVCommExprs)[std::make_pair(scUMaxExpr,
SCEVOps)];
- if (Result == 0) Result = new SCEVUMaxExpr(Ops);
+ if (Result == 0) Result = new SCEVUMaxExpr(Ops, this);
return Result;
}
+SCEVHandle ScalarEvolution::getSMinExpr(const SCEVHandle &LHS,
+ const SCEVHandle &RHS) {
+ // ~smax(~x, ~y) == smin(x, y).
+ return getNotSCEV(getSMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS)));
+}
+
+SCEVHandle ScalarEvolution::getUMinExpr(const SCEVHandle &LHS,
+ const SCEVHandle &RHS) {
+ // ~umax(~x, ~y) == umin(x, y)
+ return getNotSCEV(getUMaxExpr(getNotSCEV(LHS), getNotSCEV(RHS)));
+}
+
SCEVHandle ScalarEvolution::getUnknown(Value *V) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
return getConstant(CI);
if (isa<ConstantPointerNull>(V))
return getIntegerSCEV(0, V->getType());
SCEVUnknown *&Result = (*SCEVUnknowns)[V];
- if (Result == 0) Result = new SCEVUnknown(V);
+ if (Result == 0) Result = new SCEVUnknown(V, this);
return Result;
}
@@ -1977,6 +2140,22 @@ ScalarEvolution::getTruncateOrNoop(const SCEVHandle &V, const Type *Ty) {
return getTruncateExpr(V, Ty);
}
+/// getUMaxFromMismatchedTypes - Promote the operands to the wider of
+/// the types using zero-extension, and then perform a umax operation
+/// with them.
+SCEVHandle ScalarEvolution::getUMaxFromMismatchedTypes(const SCEVHandle &LHS,
+ const SCEVHandle &RHS) {
+ SCEVHandle PromotedLHS = LHS;
+ SCEVHandle PromotedRHS = RHS;
+
+ if (getTypeSizeInBits(LHS->getType()) > getTypeSizeInBits(RHS->getType()))
+ PromotedRHS = getZeroExtendExpr(RHS, LHS->getType());
+ else
+ PromotedLHS = getNoopOrZeroExtend(LHS, RHS->getType());
+
+ return getUMaxExpr(PromotedLHS, PromotedRHS);
+}
+
/// ReplaceSymbolicValueWithConcrete - This looks up the computed SCEV value for
/// the specified instruction and replaces any references to the symbolic value
/// SymName with the specified value. This is used during PHI resolution.
@@ -2040,7 +2219,7 @@ SCEVHandle ScalarEvolution::createNodeForPHI(PHINode *PN) {
if (FoundIndex != Add->getNumOperands()) {
// Create an add with everything but the specified operand.
- std::vector<SCEVHandle> Ops;
+ SmallVector<SCEVHandle, 8> Ops;
for (unsigned i = 0, e = Add->getNumOperands(); i != e; ++i)
if (i != FoundIndex)
Ops.push_back(Add->getOperand(i));
@@ -2143,73 +2322,134 @@ SCEVHandle ScalarEvolution::createNodeForGEP(User *GEP) {
/// guaranteed to end in (at every loop iteration). It is, at the same time,
/// the minimum number of times S is divisible by 2. For example, given {4,+,8}
/// it returns 2. If S is guaranteed to be 0, it returns the bitwidth of S.
-static uint32_t GetMinTrailingZeros(SCEVHandle S, const ScalarEvolution &SE) {
+uint32_t
+ScalarEvolution::GetMinTrailingZeros(const SCEVHandle &S) {
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
return C->getValue()->getValue().countTrailingZeros();
if (const SCEVTruncateExpr *T = dyn_cast<SCEVTruncateExpr>(S))
- return std::min(GetMinTrailingZeros(T->getOperand(), SE),
- (uint32_t)SE.getTypeSizeInBits(T->getType()));
+ return std::min(GetMinTrailingZeros(T->getOperand()),
+ (uint32_t)getTypeSizeInBits(T->getType()));
if (const SCEVZeroExtendExpr *E = dyn_cast<SCEVZeroExtendExpr>(S)) {
- uint32_t OpRes = GetMinTrailingZeros(E->getOperand(), SE);
- return OpRes == SE.getTypeSizeInBits(E->getOperand()->getType()) ?
- SE.getTypeSizeInBits(E->getType()) : OpRes;
+ uint32_t OpRes = GetMinTrailingZeros(E->getOperand());
+ return OpRes == getTypeSizeInBits(E->getOperand()->getType()) ?
+ getTypeSizeInBits(E->getType()) : OpRes;
}
if (const SCEVSignExtendExpr *E = dyn_cast<SCEVSignExtendExpr>(S)) {
- uint32_t OpRes = GetMinTrailingZeros(E->getOperand(), SE);
- return OpRes == SE.getTypeSizeInBits(E->getOperand()->getType()) ?
- SE.getTypeSizeInBits(E->getType()) : OpRes;
+ uint32_t OpRes = GetMinTrailingZeros(E->getOperand());
+ return OpRes == getTypeSizeInBits(E->getOperand()->getType()) ?
+ getTypeSizeInBits(E->getType()) : OpRes;
}
if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(S)) {
// The result is the min of all operands results.
- uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0), SE);
+ uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0));
for (unsigned i = 1, e = A->getNumOperands(); MinOpRes && i != e; ++i)
- MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i), SE));
+ MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i)));
return MinOpRes;
}
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(S)) {
// The result is the sum of all operands results.
- uint32_t SumOpRes = GetMinTrailingZeros(M->getOperand(0), SE);
- uint32_t BitWidth = SE.getTypeSizeInBits(M->getType());
+ uint32_t SumOpRes = GetMinTrailingZeros(M->getOperand(0));
+ uint32_t BitWidth = getTypeSizeInBits(M->getType());
for (unsigned i = 1, e = M->getNumOperands();
SumOpRes != BitWidth && i != e; ++i)
- SumOpRes = std::min(SumOpRes + GetMinTrailingZeros(M->getOperand(i), SE),
+ SumOpRes = std::min(SumOpRes + GetMinTrailingZeros(M->getOperand(i)),
BitWidth);
return SumOpRes;
}
if (const SCEVAddRecExpr *A = dyn_cast<SCEVAddRecExpr>(S)) {
// The result is the min of all operands results.
- uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0), SE);
+ uint32_t MinOpRes = GetMinTrailingZeros(A->getOperand(0));
for (unsigned i = 1, e = A->getNumOperands(); MinOpRes && i != e; ++i)
- MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i), SE));
+ MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(A->getOperand(i)));
return MinOpRes;
}
if (const SCEVSMaxExpr *M = dyn_cast<SCEVSMaxExpr>(S)) {
// The result is the min of all operands results.
- uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0), SE);
+ uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0));
for (unsigned i = 1, e = M->getNumOperands(); MinOpRes && i != e; ++i)
- MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i), SE));
+ MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i)));
return MinOpRes;
}
if (const SCEVUMaxExpr *M = dyn_cast<SCEVUMaxExpr>(S)) {
// The result is the min of all operands results.
- uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0), SE);
+ uint32_t MinOpRes = GetMinTrailingZeros(M->getOperand(0));
for (unsigned i = 1, e = M->getNumOperands(); MinOpRes && i != e; ++i)
- MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i), SE));
+ MinOpRes = std::min(MinOpRes, GetMinTrailingZeros(M->getOperand(i)));
return MinOpRes;
}
- // SCEVUDivExpr, SCEVUnknown
+ if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(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);
+ return Zeros.countTrailingOnes();
+ }
+
+ // SCEVUDivExpr
return 0;
}
+uint32_t
+ScalarEvolution::GetMinLeadingZeros(const SCEVHandle &S) {
+ // TODO: Handle other SCEV expression types here.
+
+ if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S))
+ return C->getValue()->getValue().countLeadingZeros();
+
+ if (const SCEVZeroExtendExpr *C = dyn_cast<SCEVZeroExtendExpr>(S)) {
+ // A zero-extension cast adds zero bits.
+ return GetMinLeadingZeros(C->getOperand()) +
+ (getTypeSizeInBits(C->getType()) -
+ getTypeSizeInBits(C->getOperand()->getType()));
+ }
+
+ if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(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);
+ return Zeros.countLeadingOnes();
+ }
+
+ return 1;
+}
+
+uint32_t
+ScalarEvolution::GetMinSignBits(const SCEVHandle &S) {
+ // TODO: Handle other SCEV expression types here.
+
+ if (const SCEVConstant *C = dyn_cast<SCEVConstant>(S)) {
+ const APInt &A = C->getValue()->getValue();
+ return A.isNegative() ? A.countLeadingOnes() :
+ A.countLeadingZeros();
+ }
+
+ if (const SCEVSignExtendExpr *C = dyn_cast<SCEVSignExtendExpr>(S)) {
+ // A sign-extension cast adds sign bits.
+ return GetMinSignBits(C->getOperand()) +
+ (getTypeSizeInBits(C->getType()) -
+ getTypeSizeInBits(C->getOperand()->getType()));
+ }
+
+ if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
+ // For a SCEVUnknown, ask ValueTracking.
+ return ComputeNumSignBits(U->getValue(), TD);
+ }
+
+ return 1;
+}
+
/// createSCEV - We know that there is no SCEV for the specified value.
/// Analyze the expression.
///
@@ -2248,14 +2488,27 @@ SCEVHandle ScalarEvolution::createSCEV(Value *V) {
if (CI->isAllOnesValue())
return getSCEV(U->getOperand(0));
const APInt &A = CI->getValue();
- unsigned Ones = A.countTrailingOnes();
- if (APIntOps::isMask(Ones, A))
+
+ // Instcombine's ShrinkDemandedConstant may strip bits out of
+ // constants, obscuring what would otherwise be a low-bits mask.
+ // Use ComputeMaskedBits to compute what ShrinkDemandedConstant
+ // knew about to reconstruct a low-bits mask value.
+ unsigned LZ = A.countLeadingZeros();
+ unsigned BitWidth = A.getBitWidth();
+ APInt AllOnes = APInt::getAllOnesValue(BitWidth);
+ APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
+ ComputeMaskedBits(U->getOperand(0), AllOnes, KnownZero, KnownOne, TD);
+
+ APInt EffectiveMask = APInt::getLowBitsSet(BitWidth, BitWidth - LZ);
+
+ if (LZ != 0 && !((~A & ~KnownZero) & EffectiveMask))
return
getZeroExtendExpr(getTruncateExpr(getSCEV(U->getOperand(0)),
- IntegerType::get(Ones)),
+ IntegerType::get(BitWidth - LZ)),
U->getType());
}
break;
+
case Instruction::Or:
// If the RHS of the Or is a constant, we may have something like:
// X*4+1 which got turned into X*4|1. Handle this as an Add so loop
@@ -2266,7 +2519,7 @@ SCEVHandle ScalarEvolution::createSCEV(Value *V) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(U->getOperand(1))) {
SCEVHandle LHS = getSCEV(U->getOperand(0));
const APInt &CIVal = CI->getValue();
- if (GetMinTrailingZeros(LHS, *this) >=
+ if (GetMinTrailingZeros(LHS) >=
(CIVal.getBitWidth() - CIVal.countLeadingZeros()))
return getAddExpr(LHS, getSCEV(U->getOperand(1)));
}
@@ -2292,9 +2545,27 @@ SCEVHandle ScalarEvolution::createSCEV(Value *V) {
if (BO->getOpcode() == Instruction::And &&
LCI->getValue() == CI->getValue())
if (const SCEVZeroExtendExpr *Z =
- dyn_cast<SCEVZeroExtendExpr>(getSCEV(U->getOperand(0))))
- return getZeroExtendExpr(getNotSCEV(Z->getOperand()),
- U->getType());
+ dyn_cast<SCEVZeroExtendExpr>(getSCEV(U->getOperand(0)))) {
+ const Type *UTy = U->getType();
+ SCEVHandle Z0 = Z->getOperand();
+ const Type *Z0Ty = Z0->getType();
+ unsigned Z0TySize = getTypeSizeInBits(Z0Ty);
+
+ // If C is a low-bits mask, the zero extend is zerving to
+ // mask off the high bits. Complement the operand and
+ // re-apply the zext.
+ if (APIntOps::isMask(Z0TySize, CI->getValue()))
+ return getZeroExtendExpr(getNotSCEV(Z0), UTy);
+
+ // If C is a single bit, it may be in the sign-bit position
+ // before the zero-extend. In this case, represent the xor
+ // using an add, which is equivalent, and re-apply the zext.
+ APInt Trunc = APInt(CI->getValue()).trunc(Z0TySize);
+ if (APInt(Trunc).zext(getTypeSizeInBits(UTy)) == CI->getValue() &&
+ Trunc.isSignBit())
+ return getZeroExtendExpr(getAddExpr(Z0, getConstant(Trunc)),
+ UTy);
+ }
}
break;
@@ -2385,10 +2656,7 @@ SCEVHandle ScalarEvolution::createSCEV(Value *V) {
if (LHS == U->getOperand(1) && RHS == U->getOperand(2))
return getSMaxExpr(getSCEV(LHS), getSCEV(RHS));
else if (LHS == U->getOperand(2) && RHS == U->getOperand(1))
- // ~smax(~x, ~y) == smin(x, y).
- return getNotSCEV(getSMaxExpr(
- getNotSCEV(getSCEV(LHS)),
- getNotSCEV(getSCEV(RHS))));
+ return getSMinExpr(getSCEV(LHS), getSCEV(RHS));
break;
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_ULE:
@@ -2399,9 +2667,25 @@ SCEVHandle ScalarEvolution::createSCEV(Value *V) {
if (LHS == U->getOperand(1) && RHS == U->getOperand(2))
return getUMaxExpr(getSCEV(LHS), getSCEV(RHS));
else if (LHS == U->getOperand(2) && RHS == U->getOperand(1))
- // ~umax(~x, ~y) == umin(x, y)
- return getNotSCEV(getUMaxExpr(getNotSCEV(getSCEV(LHS)),
- getNotSCEV(getSCEV(RHS))));
+ return getUMinExpr(getSCEV(LHS), getSCEV(RHS));
+ break;
+ case ICmpInst::ICMP_NE:
+ // n != 0 ? n : 1 -> umax(n, 1)
+ if (LHS == U->getOperand(1) &&
+ isa<ConstantInt>(U->getOperand(2)) &&
+ cast<ConstantInt>(U->getOperand(2))->isOne() &&
+ isa<ConstantInt>(RHS) &&
+ cast<ConstantInt>(RHS)->isZero())
+ return getUMaxExpr(getSCEV(LHS), getSCEV(U->getOperand(2)));
+ break;
+ case ICmpInst::ICMP_EQ:
+ // n == 0 ? 1 : n -> umax(n, 1)
+ if (LHS == U->getOperand(2) &&
+ isa<ConstantInt>(U->getOperand(1)) &&
+ cast<ConstantInt>(U->getOperand(1))->isOne() &&
+ isa<ConstantInt>(RHS) &&
+ cast<ConstantInt>(RHS)->isZero())
+ return getUMaxExpr(getSCEV(LHS), getSCEV(U->getOperand(1)));
break;
default:
break;
@@ -2462,9 +2746,13 @@ ScalarEvolution::getBackedgeTakenInfo(const Loop *L) {
// Update the value in the map.
Pair.first->second = ItCount;
- } else if (isa<PHINode>(L->getHeader()->begin())) {
- // Only count loops that have phi nodes as not being computable.
- ++NumTripCountsNotComputed;
+ } else {
+ if (ItCount.Max != CouldNotCompute)
+ // Update the value in the map.
+ Pair.first->second = ItCount;
+ if (isa<PHINode>(L->getHeader()->begin()))
+ // Only count loops that have phi nodes as not being computable.
+ ++NumTripCountsNotComputed;
}
// Now that we know more about the trip count for this loop, forget any
@@ -2520,19 +2808,58 @@ void ScalarEvolution::forgetLoopPHIs(const Loop *L) {
/// of the specified loop will execute.
ScalarEvolution::BackedgeTakenInfo
ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) {
- // If the loop has a non-one exit block count, we can't analyze it.
- BasicBlock *ExitBlock = L->getExitBlock();
- if (!ExitBlock)
- return CouldNotCompute;
+ SmallVector<BasicBlock*, 8> ExitingBlocks;
+ L->getExitingBlocks(ExitingBlocks);
+
+ // Examine all exits and pick the most conservative values.
+ SCEVHandle BECount = CouldNotCompute;
+ SCEVHandle MaxBECount = CouldNotCompute;
+ bool CouldNotComputeBECount = false;
+ bool CouldNotComputeMaxBECount = false;
+ for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
+ BackedgeTakenInfo NewBTI =
+ ComputeBackedgeTakenCountFromExit(L, ExitingBlocks[i]);
+
+ if (NewBTI.Exact == CouldNotCompute) {
+ // We couldn't compute an exact value for this exit, so
+ // we don't be able to compute an exact value for the loop.
+ CouldNotComputeBECount = true;
+ BECount = CouldNotCompute;
+ } else if (!CouldNotComputeBECount) {
+ if (BECount == CouldNotCompute)
+ BECount = NewBTI.Exact;
+ else {
+ // TODO: More analysis could be done here. For example, a
+ // loop with a short-circuiting && operator has an exact count
+ // of the min of both sides.
+ CouldNotComputeBECount = true;
+ BECount = CouldNotCompute;
+ }
+ }
+ if (NewBTI.Max == CouldNotCompute) {
+ // We couldn't compute an maximum value for this exit, so
+ // we don't be able to compute an maximum value for the loop.
+ CouldNotComputeMaxBECount = true;
+ MaxBECount = CouldNotCompute;
+ } else if (!CouldNotComputeMaxBECount) {
+ if (MaxBECount == CouldNotCompute)
+ MaxBECount = NewBTI.Max;
+ else
+ MaxBECount = getUMaxFromMismatchedTypes(MaxBECount, NewBTI.Max);
+ }
+ }
+
+ return BackedgeTakenInfo(BECount, MaxBECount);
+}
- // Okay, there is one exit block. Try to find the condition that causes the
- // loop to be exited.
- BasicBlock *ExitingBlock = L->getExitingBlock();
- if (!ExitingBlock)
- return CouldNotCompute; // More than one block exiting!
+/// ComputeBackedgeTakenCountFromExit - Compute the number of times the backedge
+/// of the specified loop will execute if it exits via the specified block.
+ScalarEvolution::BackedgeTakenInfo
+ScalarEvolution::ComputeBackedgeTakenCountFromExit(const Loop *L,
+ BasicBlock *ExitingBlock) {
- // Okay, we've computed the exiting block. See what condition causes us to
- // exit.
+ // Okay, we've chosen an exiting block. See what condition causes us to
+ // exit at this block.
//
// FIXME: we should be able to handle switch instructions (with a single exit)
BranchInst *ExitBr = dyn_cast<BranchInst>(ExitingBlock->getTerminator());
@@ -2547,23 +2874,154 @@ ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) {
// Currently we check for this by checking to see if the Exit branch goes to
// the loop header. If so, we know it will always execute the same number of
// times as the loop. We also handle the case where the exit block *is* the
- // loop header. This is common for un-rotated loops. More extensive analysis
- // could be done to handle more cases here.
+ // loop header. This is common for un-rotated loops.
+ //
+ // If both of those tests fail, walk up the unique predecessor chain to the
+ // header, stopping if there is an edge that doesn't exit the loop. If the
+ // header is reached, the execution count of the branch will be equal to the
+ // trip count of the loop.
+ //
+ // More extensive analysis could be done to handle more cases here.
+ //
if (ExitBr->getSuccessor(0) != L->getHeader() &&
ExitBr->getSuccessor(1) != L->getHeader() &&
- ExitBr->getParent() != L->getHeader())
- return CouldNotCompute;
-
- ICmpInst *ExitCond = dyn_cast<ICmpInst>(ExitBr->getCondition());
+ ExitBr->getParent() != L->getHeader()) {
+ // The simple checks failed, try climbing the unique predecessor chain
+ // up to the header.
+ bool Ok = false;
+ for (BasicBlock *BB = ExitBr->getParent(); BB; ) {
+ BasicBlock *Pred = BB->getUniquePredecessor();
+ if (!Pred)
+ return CouldNotCompute;
+ TerminatorInst *PredTerm = Pred->getTerminator();
+ for (unsigned i = 0, e = PredTerm->getNumSuccessors(); i != e; ++i) {
+ BasicBlock *PredSucc = PredTerm->getSuccessor(i);
+ if (PredSucc == BB)
+ continue;
+ // If the predecessor has a successor that isn't BB and isn't
+ // outside the loop, assume the worst.
+ if (L->contains(PredSucc))
+ return CouldNotCompute;
+ }
+ if (Pred == L->getHeader()) {
+ Ok = true;
+ break;
+ }
+ BB = Pred;
+ }
+ if (!Ok)
+ return CouldNotCompute;
+ }
+
+ // Procede to the next level to examine the exit condition expression.
+ return ComputeBackedgeTakenCountFromExitCond(L, ExitBr->getCondition(),
+ ExitBr->getSuccessor(0),
+ ExitBr->getSuccessor(1));
+}
+
+/// ComputeBackedgeTakenCountFromExitCond - Compute the number of times the
+/// backedge of the specified loop will execute if its exit condition
+/// were a conditional branch of ExitCond, TBB, and FBB.
+ScalarEvolution::BackedgeTakenInfo
+ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L,
+ Value *ExitCond,
+ BasicBlock *TBB,
+ BasicBlock *FBB) {
+ // Check if the controlling expression for this loop is an and or or. In
+ // such cases, an exact backedge-taken count may be infeasible, but a
+ // maximum count may still be feasible.
+ if (BinaryOperator *BO = dyn_cast<BinaryOperator>(ExitCond)) {
+ if (BO->getOpcode() == Instruction::And) {
+ // Recurse on the operands of the and.
+ BackedgeTakenInfo BTI0 =
+ ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB);
+ BackedgeTakenInfo BTI1 =
+ ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB);
+ SCEVHandle BECount = CouldNotCompute;
+ SCEVHandle MaxBECount = CouldNotCompute;
+ if (L->contains(TBB)) {
+ // Both conditions must be true for the loop to continue executing.
+ // Choose the less conservative count.
+ // TODO: Take the minimum of the exact counts.
+ if (BTI0.Exact == BTI1.Exact)
+ BECount = BTI0.Exact;
+ // TODO: Take the minimum of the maximum counts.
+ if (BTI0.Max == CouldNotCompute)
+ MaxBECount = BTI1.Max;
+ else if (BTI1.Max == CouldNotCompute)
+ MaxBECount = BTI0.Max;
+ else if (const SCEVConstant *C0 = dyn_cast<SCEVConstant>(BTI0.Max))
+ if (const SCEVConstant *C1 = dyn_cast<SCEVConstant>(BTI1.Max))
+ MaxBECount = getConstant(APIntOps::umin(C0->getValue()->getValue(),
+ C1->getValue()->getValue()));
+ } else {
+ // Both conditions must be true for the loop to exit.
+ assert(L->contains(FBB) && "Loop block has no successor in loop!");
+ if (BTI0.Exact != CouldNotCompute && BTI1.Exact != CouldNotCompute)
+ BECount = getUMaxFromMismatchedTypes(BTI0.Exact, BTI1.Exact);
+ if (BTI0.Max != CouldNotCompute && BTI1.Max != CouldNotCompute)
+ MaxBECount = getUMaxFromMismatchedTypes(BTI0.Max, BTI1.Max);
+ }
+
+ return BackedgeTakenInfo(BECount, MaxBECount);
+ }
+ if (BO->getOpcode() == Instruction::Or) {
+ // Recurse on the operands of the or.
+ BackedgeTakenInfo BTI0 =
+ ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(0), TBB, FBB);
+ BackedgeTakenInfo BTI1 =
+ ComputeBackedgeTakenCountFromExitCond(L, BO->getOperand(1), TBB, FBB);
+ SCEVHandle BECount = CouldNotCompute;
+ SCEVHandle MaxBECount = CouldNotCompute;
+ if (L->contains(FBB)) {
+ // Both conditions must be false for the loop to continue executing.
+ // Choose the less conservative count.
+ // TODO: Take the minimum of the exact counts.
+ if (BTI0.Exact == BTI1.Exact)
+ BECount = BTI0.Exact;
+ // TODO: Take the minimum of the maximum counts.
+ if (BTI0.Max == CouldNotCompute)
+ MaxBECount = BTI1.Max;
+ else if (BTI1.Max == CouldNotCompute)
+ MaxBECount = BTI0.Max;
+ else if (const SCEVConstant *C0 = dyn_cast<SCEVConstant>(BTI0.Max))
+ if (const SCEVConstant *C1 = dyn_cast<SCEVConstant>(BTI1.Max))
+ MaxBECount = getConstant(APIntOps::umin(C0->getValue()->getValue(),
+ C1->getValue()->getValue()));
+ } else {
+ // Both conditions must be false for the loop to exit.
+ assert(L->contains(TBB) && "Loop block has no successor in loop!");
+ if (BTI0.Exact != CouldNotCompute && BTI1.Exact != CouldNotCompute)
+ BECount = getUMaxFromMismatchedTypes(BTI0.Exact, BTI1.Exact);
+ if (BTI0.Max != CouldNotCompute && BTI1.Max != CouldNotCompute)
+ MaxBECount = getUMaxFromMismatchedTypes(BTI0.Max, BTI1.Max);
+ }
+
+ return BackedgeTakenInfo(BECount, MaxBECount);
+ }
+ }
+
+ // With an icmp, it may be feasible to compute an exact backedge-taken count.
+ // Procede to the next level to examine the icmp.
+ if (ICmpInst *ExitCondICmp = dyn_cast<ICmpInst>(ExitCond))
+ return ComputeBackedgeTakenCountFromExitCondICmp(L, ExitCondICmp, TBB, FBB);
// If it's not an integer or pointer comparison then compute it the hard way.
- if (ExitCond == 0)
- return ComputeBackedgeTakenCountExhaustively(L, ExitBr->getCondition(),
- ExitBr->getSuccessor(0) == ExitBlock);
+ return ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB));
+}
+
+/// ComputeBackedgeTakenCountFromExitCondICmp - Compute the number of times the
+/// backedge of the specified loop will execute if its exit condition
+/// were a conditional branch of the ICmpInst ExitCond, TBB, and FBB.
+ScalarEvolution::BackedgeTakenInfo
+ScalarEvolution::ComputeBackedgeTakenCountFromExitCondICmp(const Loop *L,
+ ICmpInst *ExitCond,
+ BasicBlock *TBB,
+ BasicBlock *FBB) {
// If the condition was exit on true, convert the condition to exit on false
ICmpInst::Predicate Cond;
- if (ExitBr->getSuccessor(1) == ExitBlock)
+ if (!L->contains(FBB))
Cond = ExitCond->getPredicate();
else
Cond = ExitCond->getInversePredicate();
@@ -2573,7 +3031,12 @@ ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) {
if (Constant *RHS = dyn_cast<Constant>(ExitCond->getOperand(1))) {
SCEVHandle ItCnt =
ComputeLoadConstantCompareBackedgeTakenCount(LI, RHS, L, Cond);
- if (!isa<SCEVCouldNotCompute>(ItCnt)) return ItCnt;
+ if (!isa<SCEVCouldNotCompute>(ItCnt)) {
+ unsigned BitWidth = getTypeSizeInBits(ItCnt->getType());
+ return BackedgeTakenInfo(ItCnt,
+ isa<SCEVConstant>(ItCnt) ? ItCnt :
+ getConstant(APInt::getMaxValue(BitWidth)-1));
+ }
}
SCEVHandle LHS = getSCEV(ExitCond->getOperand(0));
@@ -2651,8 +3114,7 @@ ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) {
break;
}
return
- ComputeBackedgeTakenCountExhaustively(L, ExitCond,
- ExitBr->getSuccessor(0) == ExitBlock);
+ ComputeBackedgeTakenCountExhaustively(L, ExitCond, !L->contains(TBB));
}
static ConstantInt *
@@ -2750,7 +3212,7 @@ ComputeLoadConstantCompareBackedgeTakenCount(LoadInst *LI, Constant *RHS,
unsigned MaxSteps = MaxBruteForceIterations;
for (unsigned IterationNum = 0; IterationNum != MaxSteps; ++IterationNum) {
ConstantInt *ItCst =
- ConstantInt::get(IdxExpr->getType(), IterationNum);
+ ConstantInt::get(cast<IntegerType>(IdxExpr->getType()), IterationNum);
ConstantInt *Val = EvaluateConstantChrecAtConstant(IdxExpr, ItCst, *this);
// Form the GEP offset.
@@ -2945,7 +3407,7 @@ ComputeBackedgeTakenCountExhaustively(const Loop *L, Value *Cond, bool ExitWhen)
if (CondVal->getValue() == uint64_t(ExitWhen)) {
ConstantEvolutionLoopExitValue[PN] = PHIVal;
++NumBruteForceTripCountsComputed;
- return getConstant(ConstantInt::get(Type::Int32Ty, IterationNum));
+ return getConstant(Type::Int32Ty, IterationNum);
}
// Compute the value of the PHI node for the next iteration.
@@ -3074,7 +3536,7 @@ SCEVHandle ScalarEvolution::getSCEVAtScope(const SCEV *V, const Loop *L) {
if (OpAtScope != Comm->getOperand(i)) {
// Okay, at least one of these operands is loop variant but might be
// foldable. Build a new instance of the folded commutative expression.
- std::vector<SCEVHandle> NewOps(Comm->op_begin(), Comm->op_begin()+i);
+ SmallVector<SCEVHandle, 8> NewOps(Comm->op_begin(), Comm->op_begin()+i);
NewOps.push_back(OpAtScope);
for (++i; i != e; ++i) {
@@ -3394,6 +3856,29 @@ ScalarEvolution::getPredecessorWithUniqueSuccessorForBB(BasicBlock *BB) {
return 0;
}
+/// HasSameValue - SCEV structural equivalence is usually sufficient for
+/// testing whether two expressions are equal, however for the purposes of
+/// looking for a condition guarding a loop, it can be useful to be a little
+/// more general, since a front-end may have replicated the controlling
+/// expression.
+///
+static bool HasSameValue(const SCEVHandle &A, const SCEVHandle &B) {
+ // Quick check to see if they are the same SCEV.
+ if (A == B) return true;
+
+ // Otherwise, if they're both SCEVUnknown, it's possible that they hold
+ // two different instructions with the same value. Check for this case.
+ if (const SCEVUnknown *AU = dyn_cast<SCEVUnknown>(A))
+ if (const SCEVUnknown *BU = dyn_cast<SCEVUnknown>(B))
+ if (const Instruction *AI = dyn_cast<Instruction>(AU->getValue()))
+ if (const Instruction *BI = dyn_cast<Instruction>(BU->getValue()))
+ if (AI->isIdenticalTo(BI))
+ return true;
+
+ // Otherwise assume they may have a different value.
+ return false;
+}
+
/// isLoopGuardedByCond - Test whether entry to the loop is protected by
/// a conditional between LHS and RHS. This is used to help avoid max
/// expressions in loop trip counts.
@@ -3494,15 +3979,43 @@ bool ScalarEvolution::isLoopGuardedByCond(const Loop *L,
SCEVHandle PreCondLHSSCEV = getSCEV(PreCondLHS);
SCEVHandle PreCondRHSSCEV = getSCEV(PreCondRHS);
- if ((LHS == PreCondLHSSCEV && RHS == PreCondRHSSCEV) ||
- (LHS == getNotSCEV(PreCondRHSSCEV) &&
- RHS == getNotSCEV(PreCondLHSSCEV)))
+ if ((HasSameValue(LHS, PreCondLHSSCEV) &&
+ HasSameValue(RHS, PreCondRHSSCEV)) ||
+ (HasSameValue(LHS, getNotSCEV(PreCondRHSSCEV)) &&
+ HasSameValue(RHS, getNotSCEV(PreCondLHSSCEV))))
return true;
}
return false;
}
+/// getBECount - Subtract the end and start values and divide by the step,
+/// rounding up, to get the number of times the backedge is executed. Return
+/// CouldNotCompute if an intermediate computation overflows.
+SCEVHandle ScalarEvolution::getBECount(const SCEVHandle &Start,
+ const SCEVHandle &End,
+ const SCEVHandle &Step) {
+ const Type *Ty = Start->getType();
+ SCEVHandle NegOne = getIntegerSCEV(-1, Ty);
+ SCEVHandle Diff = getMinusSCEV(End, Start);
+ SCEVHandle RoundUp = getAddExpr(Step, NegOne);
+
+ // Add an adjustment to the difference between End and Start so that
+ // the division will effectively round up.
+ SCEVHandle Add = getAddExpr(Diff, RoundUp);
+
+ // Check Add for unsigned overflow.
+ // TODO: More sophisticated things could be done here.
+ const Type *WideTy = IntegerType::get(getTypeSizeInBits(Ty) + 1);
+ SCEVHandle OperandExtendedAdd =
+ getAddExpr(getZeroExtendExpr(Diff, WideTy),
+ getZeroExtendExpr(RoundUp, WideTy));
+ if (getZeroExtendExpr(Add, WideTy) != OperandExtendedAdd)
+ return CouldNotCompute;
+
+ return getUDivExpr(Add, Step);
+}
+
/// HowManyLessThans - Return the number of times a backedge containing the
/// specified less-than comparison will execute. If not computable, return
/// CouldNotCompute.
@@ -3520,7 +4033,6 @@ HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
// FORNOW: We only support unit strides.
unsigned BitWidth = getTypeSizeInBits(AddRec->getType());
SCEVHandle Step = AddRec->getStepRecurrence(*this);
- SCEVHandle NegOne = getIntegerSCEV(-1, AddRec->getType());
// TODO: handle non-constant strides.
const SCEVConstant *CStep = dyn_cast<SCEVConstant>(Step);
@@ -3575,22 +4087,20 @@ HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
: getUMaxExpr(RHS, Start);
// Determine the maximum constant end value.
- SCEVHandle MaxEnd = isa<SCEVConstant>(End) ? End :
- getConstant(isSigned ? APInt::getSignedMaxValue(BitWidth) :
- APInt::getMaxValue(BitWidth));
+ SCEVHandle MaxEnd =
+ isa<SCEVConstant>(End) ? End :
+ getConstant(isSigned ? APInt::getSignedMaxValue(BitWidth)
+ .ashr(GetMinSignBits(End) - 1) :
+ APInt::getMaxValue(BitWidth)
+ .lshr(GetMinLeadingZeros(End)));
// Finally, we subtract these two values and divide, rounding up, to get
// the number of times the backedge is executed.
- SCEVHandle BECount = getUDivExpr(getAddExpr(getMinusSCEV(End, Start),
- getAddExpr(Step, NegOne)),
- Step);
+ SCEVHandle BECount = getBECount(Start, End, Step);
// The maximum backedge count is similar, except using the minimum start
// value and the maximum end value.
- SCEVHandle MaxBECount = getUDivExpr(getAddExpr(getMinusSCEV(MaxEnd,
- MinStart),
- getAddExpr(Step, NegOne)),
- Step);
+ SCEVHandle MaxBECount = getBECount(MinStart, MaxEnd, Step);;
return BackedgeTakenInfo(BECount, MaxBECount);
}
@@ -3611,7 +4121,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range,
// If the start is a non-zero constant, shift the range to simplify things.
if (const SCEVConstant *SC = dyn_cast<SCEVConstant>(getStart()))
if (!SC->getValue()->isZero()) {
- std::vector<SCEVHandle> Operands(op_begin(), op_end());
+ SmallVector<SCEVHandle, 4> Operands(op_begin(), op_end());
Operands[0] = SE.getIntegerSCEV(0, SC->getType());
SCEVHandle Shifted = SE.getAddRecExpr(Operands, getLoop());
if (const SCEVAddRecExpr *ShiftedAddRec =
@@ -3636,7 +4146,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range,
// iteration exits.
unsigned BitWidth = SE.getTypeSizeInBits(getType());
if (!Range.contains(APInt(BitWidth, 0)))
- return SE.getConstant(ConstantInt::get(getType(),0));
+ return SE.getIntegerSCEV(0, getType());
if (isAffine()) {
// If this is an affine expression then we have this situation:
@@ -3672,7 +4182,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range,
// quadratic equation to solve it. To do this, we must frame our problem in
// terms of figuring out when zero is crossed, instead of when
// Range.getUpper() is crossed.
- std::vector<SCEVHandle> NewOps(op_begin(), op_end());
+ SmallVector<SCEVHandle, 4> NewOps(op_begin(), op_end());
NewOps[0] = SE.getNegativeSCEV(SE.getConstant(Range.getUpper()));
SCEVHandle NewAddRec = SE.getAddRecExpr(NewOps, getLoop());
@@ -3783,7 +4293,7 @@ ScalarEvolution::SCEVCallbackVH::SCEVCallbackVH(Value *V, ScalarEvolution *se)
//===----------------------------------------------------------------------===//
ScalarEvolution::ScalarEvolution()
- : FunctionPass(&ID), CouldNotCompute(new SCEVCouldNotCompute()) {
+ : FunctionPass(&ID), CouldNotCompute(new SCEVCouldNotCompute(0)) {
}
bool ScalarEvolution::runOnFunction(Function &F) {
@@ -3847,11 +4357,18 @@ void ScalarEvolution::print(raw_ostream &OS, const Module* ) const {
OS << " --> ";
SCEVHandle SV = SE.getSCEV(&*I);
SV->print(OS);
- OS << "\t\t";
- if (const Loop *L = LI->getLoopFor((*I).getParent())) {
- OS << "Exits: ";
- SCEVHandle ExitValue = SE.getSCEVAtScope(&*I, L->getParentLoop());
+ const Loop *L = LI->getLoopFor((*I).getParent());
+
+ SCEVHandle AtUse = SE.getSCEVAtScope(SV, L);
+ if (AtUse != SV) {
+ OS << " --> ";
+ AtUse->print(OS);
+ }
+
+ if (L) {
+ OS << "\t\t" "Exits: ";
+ SCEVHandle ExitValue = SE.getSCEVAtScope(SV, L->getParentLoop());
if (!ExitValue->isLoopInvariant(L)) {
OS << "<<Unknown>>";
} else {
diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp
index e1f8fa421f5a..2a73c27405a8 100644
--- a/lib/Analysis/ScalarEvolutionExpander.cpp
+++ b/lib/Analysis/ScalarEvolutionExpander.cpp
@@ -182,7 +182,8 @@ static bool FactorOutConstant(SCEVHandle &S,
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(S))
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(M->getOperand(0)))
if (!C->getValue()->getValue().srem(Factor)) {
- std::vector<SCEVHandle> NewMulOps(M->getOperands());
+ const SmallVectorImpl<SCEVHandle> &MOperands = M->getOperands();
+ SmallVector<SCEVHandle, 4> NewMulOps(MOperands.begin(), MOperands.end());
NewMulOps[0] =
SE.getConstant(C->getValue()->getValue().sdiv(Factor));
S = SE.getMulExpr(NewMulOps);
@@ -239,7 +240,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEVHandle *op_begin,
Value *V) {
const Type *ElTy = PTy->getElementType();
SmallVector<Value *, 4> GepIndices;
- std::vector<SCEVHandle> Ops(op_begin, op_end);
+ SmallVector<SCEVHandle, 8> Ops(op_begin, op_end);
bool AnyNonZeroIndices = false;
// Decend down the pointer's type and attempt to convert the other
@@ -250,8 +251,8 @@ Value *SCEVExpander::expandAddToGEP(const SCEVHandle *op_begin,
for (;;) {
APInt ElSize = APInt(SE.getTypeSizeInBits(Ty),
ElTy->isSized() ? SE.TD->getTypeAllocSize(ElTy) : 0);
- std::vector<SCEVHandle> NewOps;
- std::vector<SCEVHandle> ScaledOps;
+ SmallVector<SCEVHandle, 8> NewOps;
+ SmallVector<SCEVHandle, 8> ScaledOps;
for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
// Split AddRecs up into parts as either of the parts may be usable
// without the other.
@@ -297,9 +298,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEVHandle *op_begin,
GepIndices.push_back(ConstantInt::get(Type::Int32Ty, ElIdx));
ElTy = STy->getTypeAtIndex(ElIdx);
Ops[0] =
- SE.getConstant(ConstantInt::get(Ty,
- FullOffset -
- SL.getElementOffset(ElIdx)));
+ SE.getConstant(Ty, FullOffset - SL.getElementOffset(ElIdx));
AnyNonZeroIndices = true;
continue;
}
@@ -365,7 +364,7 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {
// comments on expandAddToGEP for details.
if (SE.TD)
if (const PointerType *PTy = dyn_cast<PointerType>(V->getType())) {
- const std::vector<SCEVHandle> &Ops = S->getOperands();
+ const SmallVectorImpl<SCEVHandle> &Ops = S->getOperands();
return expandAddToGEP(&Ops[0], &Ops[Ops.size() - 1],
PTy, Ty, V);
}
@@ -432,7 +431,7 @@ static void ExposePointerBase(SCEVHandle &Base, SCEVHandle &Rest,
}
if (const SCEVAddExpr *A = dyn_cast<SCEVAddExpr>(Base)) {
Base = A->getOperand(A->getNumOperands()-1);
- std::vector<SCEVHandle> NewAddOps(A->op_begin(), A->op_end());
+ SmallVector<SCEVHandle, 8> NewAddOps(A->op_begin(), A->op_end());
NewAddOps.back() = Rest;
Rest = SE.getAddExpr(NewAddOps);
ExposePointerBase(Base, Rest, SE);
@@ -473,7 +472,8 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
// {X,+,F} --> X + {0,+,F}
if (!S->getStart()->isZero()) {
- std::vector<SCEVHandle> NewOps(S->getOperands());
+ const SmallVectorImpl<SCEVHandle> &SOperands = S->getOperands();
+ SmallVector<SCEVHandle, 4> NewOps(SOperands.begin(), SOperands.end());
NewOps[0] = SE.getIntegerSCEV(0, Ty);
SCEVHandle Rest = SE.getAddRecExpr(NewOps, L);
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index 45f97b8f64b1..17ffa2d2de6b 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -52,11 +52,12 @@ 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()->isInteger() || isa<PointerType>(V->getType())) &&
+ assert((V->getType()->isIntOrIntVector() || isa<PointerType>(V->getType())) &&
"Not integer or pointer type!");
- assert((!TD || TD->getTypeSizeInBits(V->getType()) == BitWidth) &&
- (!isa<IntegerType>(V->getType()) ||
- V->getType()->getPrimitiveSizeInBits() == BitWidth) &&
+ assert((!TD ||
+ TD->getTypeSizeInBits(V->getType()->getScalarType()) == BitWidth) &&
+ (!V->getType()->isIntOrIntVector() ||
+ V->getType()->getScalarSizeInBits() == BitWidth) &&
KnownZero.getBitWidth() == BitWidth &&
KnownOne.getBitWidth() == BitWidth &&
"V, Mask, KnownOne and KnownZero should have same BitWidth");
@@ -67,12 +68,26 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask,
KnownZero = ~KnownOne & Mask;
return;
}
- // Null is all-zeros.
- if (isa<ConstantPointerNull>(V)) {
+ // Null and aggregate-zero are all-zeros.
+ if (isa<ConstantPointerNull>(V) ||
+ isa<ConstantAggregateZero>(V)) {
KnownOne.clear();
KnownZero = Mask;
return;
}
+ // Handle a constant vector by taking the intersection of the known bits of
+ // each element.
+ if (ConstantVector *CV = dyn_cast<ConstantVector>(V)) {
+ KnownZero.set(); KnownOne.set();
+ for (unsigned i = 0, e = CV->getNumOperands(); i != e; ++i) {
+ APInt KnownZero2(BitWidth, 0), KnownOne2(BitWidth, 0);
+ ComputeMaskedBits(CV->getOperand(i), Mask, KnownZero2, KnownOne2,
+ TD, Depth);
+ KnownZero &= KnownZero2;
+ KnownOne &= KnownOne2;
+ }
+ return;
+ }
// The address of an aligned GlobalValue has trailing zeros.
if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
unsigned Align = GV->getAlignment();
@@ -218,7 +233,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask,
const Type *SrcTy = I->getOperand(0)->getType();
unsigned SrcBitWidth = TD ?
TD->getTypeSizeInBits(SrcTy) :
- SrcTy->getPrimitiveSizeInBits();
+ SrcTy->getScalarSizeInBits();
APInt MaskIn(Mask);
MaskIn.zextOrTrunc(SrcBitWidth);
KnownZero.zextOrTrunc(SrcBitWidth);
@@ -480,7 +495,7 @@ void llvm::ComputeMaskedBits(Value *V, const APInt &Mask,
// Handle array index arithmetic.
const Type *IndexedTy = GTI.getIndexedType();
if (!IndexedTy->isSized()) return;
- unsigned GEPOpiBits = Index->getType()->getPrimitiveSizeInBits();
+ unsigned GEPOpiBits = Index->getType()->getScalarSizeInBits();
uint64_t TypeSize = TD ? TD->getTypeAllocSize(IndexedTy) : 1;
LocalMask = APInt::getAllOnesValue(GEPOpiBits);
LocalKnownZero = LocalKnownOne = APInt(GEPOpiBits, 0);
@@ -609,8 +624,8 @@ bool llvm::MaskedValueIsZero(Value *V, const APInt &Mask,
/// 'Op' must have a scalar integer type.
///
unsigned llvm::ComputeNumSignBits(Value *V, TargetData *TD, unsigned Depth) {
- const IntegerType *Ty = cast<IntegerType>(V->getType());
- unsigned TyBits = Ty->getBitWidth();
+ const Type *Ty = V->getType();
+ unsigned TyBits = Ty->getScalarSizeInBits();
unsigned Tmp, Tmp2;
unsigned FirstAnswer = 1;
diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp
index c5190efc4dac..b3f7cdb3c379 100644
--- a/lib/AsmParser/LLLexer.cpp
+++ b/lib/AsmParser/LLLexer.cpp
@@ -526,6 +526,10 @@ lltok::Kind LLLexer::LexIdentifier() {
KEYWORD(coldcc);
KEYWORD(x86_stdcallcc);
KEYWORD(x86_fastcallcc);
+ KEYWORD(arm_apcscc);
+ KEYWORD(arm_aapcscc);
+ KEYWORD(arm_aapcs_vfpcc);
+
KEYWORD(cc);
KEYWORD(c);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 4863f3c5116a..909370cb669d 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -808,8 +808,11 @@ bool LLParser::ParseOptionalVisibility(unsigned &Res) {
/// ::= 'coldcc'
/// ::= 'x86_stdcallcc'
/// ::= 'x86_fastcallcc'
+/// ::= 'arm_apcscc'
+/// ::= 'arm_aapcscc'
+/// ::= 'arm_aapcs_vfpcc'
/// ::= 'cc' UINT
-///
+///
bool LLParser::ParseOptionalCallingConv(unsigned &CC) {
switch (Lex.getKind()) {
default: CC = CallingConv::C; return false;
@@ -818,6 +821,9 @@ bool LLParser::ParseOptionalCallingConv(unsigned &CC) {
case lltok::kw_coldcc: CC = CallingConv::Cold; break;
case lltok::kw_x86_stdcallcc: CC = CallingConv::X86_StdCall; break;
case lltok::kw_x86_fastcallcc: CC = CallingConv::X86_FastCall; break;
+ case lltok::kw_arm_apcscc: CC = CallingConv::ARM_APCS; break;
+ case lltok::kw_arm_aapcscc: CC = CallingConv::ARM_AAPCS; break;
+ case lltok::kw_arm_aapcs_vfpcc:CC = CallingConv::ARM_AAPCS_VFP; break;
case lltok::kw_cc: Lex.Lex(); return ParseUInt32(CC);
}
Lex.Lex();
@@ -1743,7 +1749,7 @@ bool LLParser::ParseValID(ValID &ID) {
Lex.Lex();
if (ParseToken(lltok::lparen, "expected '(' after constantexpr cast") ||
ParseGlobalTypeAndValue(SrcVal) ||
- ParseToken(lltok::kw_to, "expected 'to' int constantexpr cast") ||
+ ParseToken(lltok::kw_to, "expected 'to' in constantexpr cast") ||
ParseType(DestTy) ||
ParseToken(lltok::rparen, "expected ')' at end of constantexpr cast"))
return true;
@@ -3145,7 +3151,7 @@ bool LLParser::ParseFree(Instruction *&Inst, PerFunctionState &PFS) {
}
/// ParseLoad
-/// ::= 'volatile'? 'load' TypeAndValue (',' 'align' uint)?
+/// ::= 'volatile'? 'load' TypeAndValue (',' 'align' i32)?
bool LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS,
bool isVolatile) {
Value *Val; LocTy Loc;
@@ -3163,7 +3169,7 @@ bool LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS,
}
/// ParseStore
-/// ::= 'volatile'? 'store' TypeAndValue ',' TypeAndValue (',' 'align' uint)?
+/// ::= 'volatile'? 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)?
bool LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS,
bool isVolatile) {
Value *Val, *Ptr; LocTy Loc, PtrLoc;
@@ -3186,7 +3192,7 @@ bool LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS,
}
/// ParseGetResult
-/// ::= 'getresult' TypeAndValue ',' uint
+/// ::= 'getresult' TypeAndValue ',' i32
/// FIXME: Remove support for getresult in LLVM 3.0
bool LLParser::ParseGetResult(Instruction *&Inst, PerFunctionState &PFS) {
Value *Val; LocTy ValLoc, EltLoc;
diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h
index 9335d19612a5..cff89f8e472f 100644
--- a/lib/AsmParser/LLToken.h
+++ b/lib/AsmParser/LLToken.h
@@ -60,7 +60,9 @@ namespace lltok {
kw_gc,
kw_c,
- kw_cc, kw_ccc, kw_fastcc, kw_coldcc, kw_x86_stdcallcc, kw_x86_fastcallcc,
+ kw_cc, kw_ccc, kw_fastcc, kw_coldcc,
+ kw_x86_stdcallcc, kw_x86_fastcallcc,
+ kw_arm_apcscc, kw_arm_aapcscc, kw_arm_aapcs_vfpcc,
kw_signext,
kw_zeroext,
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 3b44f56421f4..6b9606c5d14b 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -2040,14 +2040,13 @@ void BitcodeReader::dematerializeFunction(Function *F) {
Module *BitcodeReader::materializeModule(std::string *ErrInfo) {
- for (DenseMap<Function*, std::pair<uint64_t, unsigned> >::iterator I =
- DeferredFunctionInfo.begin(), E = DeferredFunctionInfo.end(); I != E;
- ++I) {
- Function *F = I->first;
+ // Iterate over the module, deserializing any functions that are still on
+ // disk.
+ for (Module::iterator F = TheModule->begin(), E = TheModule->end();
+ F != E; ++F)
if (F->hasNotBeenReadFromBitcode() &&
materializeFunction(F, ErrInfo))
return 0;
- }
// Upgrade any intrinsic calls that slipped through (should not happen!) and
// delete the old functions to clean up. We can't do this unless the entire
@@ -2123,7 +2122,7 @@ Module *llvm::ParseBitcodeFile(MemoryBuffer *Buffer, std::string *ErrMsg){
// is run.
if (M)
M = R->releaseModule(ErrMsg);
-
+
delete R;
return M;
}
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 45462da0d26a..e93190462347 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -152,6 +152,9 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
bool AsmPrinter::doInitialization(Module &M) {
Mang = new Mangler(M, TAI->getGlobalPrefix(), TAI->getPrivateGlobalPrefix());
+ if (TAI->doesAllowQuotesInName())
+ Mang->setUseQuotes(true);
+
GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
assert(MI && "AsmPrinter didn't require GCModuleInfo?");
@@ -174,9 +177,17 @@ bool AsmPrinter::doInitialization(Module &M) {
SwitchToDataSection(""); // Reset back to no section.
- MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
- if (MMI) MMI->AnalyzeModule(M);
- DW = getAnalysisIfAvailable<DwarfWriter>();
+ if (TAI->doesSupportDebugInformation()
+ || TAI->doesSupportExceptionHandling()) {
+ MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
+ if (MMI) {
+ MMI->AnalyzeModule(M);
+ DW = getAnalysisIfAvailable<DwarfWriter>();
+ if (DW)
+ DW->BeginModule(&M, MMI, O, this, TAI);
+ }
+ }
+
return false;
}
@@ -347,8 +358,9 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI,
const char* JumpTableDataSection = TAI->getJumpTableDataSection();
const Function *F = MF.getFunction();
unsigned SectionFlags = TAI->SectionFlagsForGlobal(F);
+ bool JTInDiffSection = false;
if ((IsPic && !(LoweringInfo && LoweringInfo->usesGlobalOffsetTable())) ||
- !JumpTableDataSection ||
+ !JumpTableDataSection ||
SectionFlags & SectionFlags::Linkonce) {
// In PIC mode, we need to emit the jump table to the same section as the
// function body itself, otherwise the label differences won't make sense.
@@ -357,6 +369,7 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI,
SwitchToSection(TAI->SectionForGlobal(F));
} else {
SwitchToDataSection(JumpTableDataSection);
+ JTInDiffSection = true;
}
EmitAlignment(Log2_32(MJTI->getAlignment()));
@@ -380,8 +393,10 @@ void AsmPrinter::EmitJumpTableInfo(MachineJumpTableInfo *MJTI,
// before each jump table. The first label is never referenced, but tells
// the assembler and linker the extents of the jump table object. The
// second label is actually referenced by the code.
- if (const char *JTLabelPrefix = TAI->getJumpTableSpecialLabelPrefix())
- O << JTLabelPrefix << "JTI" << getFunctionNumber() << '_' << i << ":\n";
+ if (JTInDiffSection) {
+ if (const char *JTLabelPrefix = TAI->getJumpTableSpecialLabelPrefix())
+ O << JTLabelPrefix << "JTI" << getFunctionNumber() << '_' << i << ":\n";
+ }
O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
<< '_' << i << ":\n";
@@ -502,7 +517,7 @@ const GlobalValue * AsmPrinter::findGlobalValue(const Constant *CV) {
void AsmPrinter::EmitLLVMUsedList(Constant *List) {
const char *Directive = TAI->getUsedDirective();
- // Should be an array of 'sbyte*'.
+ // Should be an array of 'i8*'.
ConstantArray *InitList = dyn_cast<ConstantArray>(List);
if (InitList == 0) return;
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index c773378bb015..9d340e3aee58 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1757,6 +1757,9 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
if (TimePassesIsEnabled)
DebugTimer->startTimer();
+ CompileUnit *Unit = MainCU;
+ if (!Unit)
+ Unit = &FindCompileUnit(SP.getCompileUnit());
GlobalVariable *GV = SP.getGV();
DenseMap<const GlobalVariable *, DbgScope *>::iterator
II = AbstractInstanceRootMap.find(GV);
@@ -1767,7 +1770,6 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
DbgScope *Scope = new DbgScope(NULL, DIDescriptor(GV));
// Get the compile unit context.
- CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
DIE *SPDie = Unit->getDieMapSlotFor(GV);
if (!SPDie)
SPDie = CreateSubprogramDIE(Unit, SP, false, true);
@@ -1789,7 +1791,6 @@ unsigned DwarfDebug::RecordInlinedFnStart(DISubprogram &SP, DICompileUnit CU,
// Create a concrete inlined instance for this inlined function.
DbgConcreteScope *ConcreteScope = new DbgConcreteScope(DIDescriptor(GV));
DIE *ScopeDie = new DIE(dwarf::DW_TAG_inlined_subroutine);
- CompileUnit *Unit = &FindCompileUnit(SP.getCompileUnit());
ScopeDie->setAbstractCompileUnit(Unit);
DIE *Origin = Unit->getDieMapSlotFor(GV);
@@ -1850,7 +1851,14 @@ unsigned DwarfDebug::RecordInlinedFnEnd(DISubprogram &SP) {
}
SmallVector<DbgScope *, 8> &Scopes = I->second;
- assert(!Scopes.empty() && "We should have at least one debug scope!");
+ if (Scopes.empty()) {
+ // Returned ID is 0 if this is unbalanced "end of inlined
+ // scope". This could happen if optimizer eats dbg intrinsics
+ // or "beginning of inlined scope" is not recoginized due to
+ // missing location info. In such cases, ignore this region.end.
+ return 0;
+ }
+
DbgScope *Scope = Scopes.back(); Scopes.pop_back();
unsigned ID = MMI->NextLabelID();
MMI->RecordUsedDbgLabel(ID);
@@ -1987,8 +1995,8 @@ void DwarfDebug::EmitInitial() {
Asm->SwitchToDataSection(TAI->getDwarfARangesSection());
EmitLabel("section_aranges", 0);
- if (TAI->doesSupportMacInfoSection()) {
- Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection());
+ if (const char *LineInfoDirective = TAI->getDwarfMacroInfoSection()) {
+ Asm->SwitchToDataSection(LineInfoDirective);
EmitLabel("section_macinfo", 0);
}
@@ -2534,9 +2542,9 @@ void DwarfDebug::EmitDebugRanges() {
/// EmitDebugMacInfo - Emit visible names into a debug macinfo section.
///
void DwarfDebug::EmitDebugMacInfo() {
- if (TAI->doesSupportMacInfoSection()) {
+ if (const char *LineInfoDirective = TAI->getDwarfMacroInfoSection()) {
// Start the dwarf macinfo section.
- Asm->SwitchToDataSection(TAI->getDwarfMacInfoSection());
+ Asm->SwitchToDataSection(LineInfoDirective);
Asm->EOL();
}
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
index f7ca4f4c9045..a1b97df82afc 100644
--- a/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfPrinter.cpp
@@ -190,7 +190,7 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
Asm->EmitULEB128Bytes(Offset);
Asm->EOL("Offset");
} else {
- assert(0 && "Machine move no supported yet.");
+ assert(0 && "Machine move not supported yet.");
}
} else if (Src.isReg() &&
Src.getReg() == MachineLocation::VirtualFP) {
@@ -200,7 +200,7 @@ void Dwarf::EmitFrameMoves(const char *BaseLabel, unsigned BaseLabelID,
Asm->EmitULEB128Bytes(RI->getDwarfRegNum(Dst.getReg(), isEH));
Asm->EOL("Register");
} else {
- assert(0 && "Machine move no supported yet.");
+ assert(0 && "Machine move not supported yet.");
}
} else {
unsigned Reg = RI->getDwarfRegNum(Src.getReg(), isEH);
diff --git a/lib/CodeGen/IfConversion.cpp b/lib/CodeGen/IfConversion.cpp
index 1d0887f843d8..4d5c3c2c7dc7 100644
--- a/lib/CodeGen/IfConversion.cpp
+++ b/lib/CodeGen/IfConversion.cpp
@@ -547,7 +547,11 @@ void IfConverter::ScanInstructions(BBInfo &BBI) {
// fallthrough.
if (!BBI.FalseBB)
BBI.FalseBB = findFalseBlock(BBI.BB, BBI.TrueBB);
- assert(BBI.FalseBB && "Expected to find the fallthrough block!");
+ if (!BBI.FalseBB) {
+ // Malformed bcc? True and false blocks are the same?
+ BBI.IsUnpredicable = true;
+ return;
+ }
}
// Then scan all the instructions.
@@ -663,6 +667,13 @@ IfConverter::BBInfo &IfConverter::AnalyzeBlock(MachineBasicBlock *BB,
return BBI;
}
+ // Do not ifcvt if true and false fallthrough blocks are the same.
+ if (!BBI.FalseBB) {
+ BBI.IsBeingAnalyzed = false;
+ BBI.IsAnalyzed = true;
+ return BBI;
+ }
+
BBInfo &TrueBBI = AnalyzeBlock(BBI.TrueBB, Tokens);
BBInfo &FalseBBI = AnalyzeBlock(BBI.FalseBB, Tokens);
diff --git a/lib/CodeGen/LazyLiveness.cpp b/lib/CodeGen/LazyLiveness.cpp
index 6fb35d235a7f..a951c99ddb7a 100644
--- a/lib/CodeGen/LazyLiveness.cpp
+++ b/lib/CodeGen/LazyLiveness.cpp
@@ -32,10 +32,12 @@ void LazyLiveness::computeBackedgeChain(MachineFunction& mf,
calculated.set(preorder[MBB]);
for (SparseBitVector<128>::iterator I = tmp.begin(); I != tmp.end(); ++I) {
+ assert(rev_preorder.size() > *I && "Unknown block!");
+
MachineBasicBlock* SrcMBB = rev_preorder[*I];
- for (MachineBasicBlock::succ_iterator SI = SrcMBB->succ_begin();
- SI != SrcMBB->succ_end(); ++SI) {
+ for (MachineBasicBlock::succ_iterator SI = SrcMBB->succ_begin(),
+ SE = SrcMBB->succ_end(); SI != SE; ++SI) {
MachineBasicBlock* TgtMBB = *SI;
if (backedges.count(std::make_pair(SrcMBB, TgtMBB)) &&
@@ -44,7 +46,8 @@ void LazyLiveness::computeBackedgeChain(MachineFunction& mf,
computeBackedgeChain(mf, TgtMBB);
tv[MBB].set(preorder[TgtMBB]);
- tv[MBB] |= tv[TgtMBB];
+ SparseBitVector<128> right = tv[TgtMBB];
+ tv[MBB] |= right;
}
}
@@ -60,6 +63,12 @@ bool LazyLiveness::runOnMachineFunction(MachineFunction &mf) {
backedge_target.clear();
calculated.clear();
preorder.clear();
+ rev_preorder.clear();
+
+ rv.resize(mf.size());
+ tv.resize(mf.size());
+ preorder.resize(mf.size());
+ rev_preorder.reserve(mf.size());
MRI = &mf.getRegInfo();
MachineDominatorTree& MDT = getAnalysis<MachineDominatorTree>();
@@ -106,8 +115,8 @@ bool LazyLiveness::runOnMachineFunction(MachineFunction &mf) {
for (MachineBasicBlock::succ_iterator SI = (*POI)->succ_begin(),
SE = (*POI)->succ_end(); SI != SE; ++SI)
if (!backedges.count(std::make_pair(*POI, *SI)) && tv.count(*SI)) {
- SparseBitVector<128>& PBV = tv[*POI];
- PBV = tv[*SI];
+ SparseBitVector<128> right = tv[*SI];
+ tv[*POI] |= right;
}
for (po_iterator<MachineBasicBlock*> POI = po_begin(&*mf.begin()),
diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp
index 67120b879886..cac92530df8f 100644
--- a/lib/CodeGen/LiveInterval.cpp
+++ b/lib/CodeGen/LiveInterval.cpp
@@ -19,6 +19,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/LiveInterval.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/STLExtras.h"
@@ -305,9 +306,9 @@ void LiveInterval::removeRange(unsigned Start, unsigned End,
VNInfo *VNI = valnos.back();
valnos.pop_back();
VNI->~VNInfo();
- } while (!valnos.empty() && valnos.back()->def == ~1U);
+ } while (!valnos.empty() && valnos.back()->isUnused());
} else {
- ValNo->def = ~1U;
+ ValNo->setIsUnused(true);
}
}
}
@@ -353,9 +354,9 @@ void LiveInterval::removeValNo(VNInfo *ValNo) {
VNInfo *VNI = valnos.back();
valnos.pop_back();
VNI->~VNInfo();
- } while (!valnos.empty() && valnos.back()->def == ~1U);
+ } while (!valnos.empty() && valnos.back()->isUnused());
} else {
- ValNo->def = ~1U;
+ ValNo->setIsUnused(true);
}
}
@@ -371,9 +372,8 @@ void LiveInterval::scaleNumbering(unsigned factor) {
// Scale VNI info.
for (vni_iterator VNI = vni_begin(), VNIE = vni_end(); VNI != VNIE; ++VNI) {
VNInfo *vni = *VNI;
- if (vni->def != ~0U && vni->def != ~1U) {
- vni->def = InstrSlots::scale(vni->def, factor);
- }
+
+ vni->def = InstrSlots::scale(vni->def, factor);
for (unsigned i = 0; i < vni->kills.size(); ++i) {
if (vni->kills[i] != 0)
@@ -421,13 +421,13 @@ VNInfo *LiveInterval::findDefinedVNInfo(unsigned DefIdxOrReg) const {
return VNI;
}
-
/// join - Join two live intervals (this, and other) together. This applies
/// mappings to the value numbers in the LHS/RHS intervals as specified. If
/// the intervals are not joinable, this aborts.
void LiveInterval::join(LiveInterval &Other, const int *LHSValNoAssignments,
const int *RHSValNoAssignments,
- SmallVector<VNInfo*, 16> &NewVNInfo) {
+ SmallVector<VNInfo*, 16> &NewVNInfo,
+ MachineRegisterInfo *MRI) {
// Determine if any of our live range values are mapped. This is uncommon, so
// we want to avoid the interval scan if not.
bool MustMapCurValNos = false;
@@ -502,8 +502,18 @@ void LiveInterval::join(LiveInterval &Other, const int *LHSValNoAssignments,
}
weight += Other.weight;
- if (Other.preference && !preference)
- preference = Other.preference;
+
+ // Update regalloc hint if currently there isn't one.
+ if (TargetRegisterInfo::isVirtualRegister(reg) &&
+ TargetRegisterInfo::isVirtualRegister(Other.reg)) {
+ std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(reg);
+ if (Hint.first == 0 && Hint.second == 0) {
+ std::pair<unsigned, unsigned> OtherHint =
+ MRI->getRegAllocationHint(Other.reg);
+ if (OtherHint.first || OtherHint.second)
+ MRI->setRegAllocationHint(reg, OtherHint.first, OtherHint.second);
+ }
+ }
}
/// MergeRangesInAsValue - Merge all of the intervals in RHS into this live
@@ -582,9 +592,9 @@ void LiveInterval::MergeValueInAsValue(const LiveInterval &RHS,
VNInfo *VNI = valnos.back();
valnos.pop_back();
VNI->~VNInfo();
- } while (!valnos.empty() && valnos.back()->def == ~1U);
+ } while (!valnos.empty() && valnos.back()->isUnused());
} else {
- V1->def = ~1U;
+ V1->setIsUnused(true);
}
}
}
@@ -611,7 +621,7 @@ void LiveInterval::MergeInClobberRanges(const LiveInterval &Clobbers,
else if (UnusedValNo)
ClobberValNo = UnusedValNo;
else {
- UnusedValNo = ClobberValNo = getNextValue(~0U, 0, VNInfoAllocator);
+ UnusedValNo = ClobberValNo = getNextValue(0, 0, false, VNInfoAllocator);
ValNoMaps.insert(std::make_pair(I->valno, ClobberValNo));
}
@@ -664,7 +674,7 @@ void LiveInterval::MergeInClobberRange(unsigned Start, unsigned End,
BumpPtrAllocator &VNInfoAllocator) {
// Find a value # to use for the clobber ranges. If there is already a value#
// for unknown values, use it.
- VNInfo *ClobberValNo = getNextValue(~0U, 0, VNInfoAllocator);
+ VNInfo *ClobberValNo = getNextValue(0, 0, false, VNInfoAllocator);
iterator IP = begin();
IP = std::upper_bound(IP, end(), Start);
@@ -747,24 +757,26 @@ VNInfo* LiveInterval::MergeValueNumberInto(VNInfo *V1, VNInfo *V2) {
VNInfo *VNI = valnos.back();
valnos.pop_back();
VNI->~VNInfo();
- } while (valnos.back()->def == ~1U);
+ } while (valnos.back()->isUnused());
} else {
- V1->def = ~1U;
+ V1->setIsUnused(true);
}
return V2;
}
void LiveInterval::Copy(const LiveInterval &RHS,
+ MachineRegisterInfo *MRI,
BumpPtrAllocator &VNInfoAllocator) {
ranges.clear();
valnos.clear();
- preference = RHS.preference;
+ std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(RHS.reg);
+ MRI->setRegAllocationHint(reg, Hint.first, Hint.second);
+
weight = RHS.weight;
for (unsigned i = 0, e = RHS.getNumValNums(); i != e; ++i) {
const VNInfo *VNI = RHS.getValNumInfo(i);
- VNInfo *NewVNI = getNextValue(~0U, 0, VNInfoAllocator);
- copyValNumInfo(NewVNI, VNI);
+ createValueCopy(VNI, VNInfoAllocator);
}
for (unsigned i = 0, e = RHS.ranges.size(); i != e; ++i) {
const LiveRange &LR = RHS.ranges[i];
@@ -816,22 +828,22 @@ void LiveInterval::print(std::ostream &OS,
const VNInfo *vni = *i;
if (vnum) OS << " ";
OS << vnum << "@";
- if (vni->def == ~1U) {
+ if (vni->isUnused()) {
OS << "x";
} else {
- if (vni->def == ~0U)
+ if (!vni->isDefAccurate())
OS << "?";
else
OS << vni->def;
unsigned ee = vni->kills.size();
- if (ee || vni->hasPHIKill) {
+ if (ee || vni->hasPHIKill()) {
OS << "-(";
for (unsigned j = 0; j != ee; ++j) {
OS << vni->kills[j];
if (j != ee-1)
OS << " ";
}
- if (vni->hasPHIKill) {
+ if (vni->hasPHIKill()) {
if (ee)
OS << " ";
OS << "phi";
diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp
index cf0a648b629d..d6931df896dc 100644
--- a/lib/CodeGen/LiveIntervalAnalysis.cpp
+++ b/lib/CodeGen/LiveIntervalAnalysis.cpp
@@ -199,7 +199,7 @@ void LiveIntervals::computeNumbering() {
// Remap the VNInfo def index, which works the same as the
// start indices above. VN's with special sentinel defs
// don't need to be remapped.
- if (vni->def != ~0U && vni->def != ~1U) {
+ if (vni->isDefAccurate() && !vni->isUnused()) {
unsigned index = vni->def / InstrSlots::NUM;
unsigned offset = vni->def % InstrSlots::NUM;
if (offset == InstrSlots::LOAD) {
@@ -447,7 +447,7 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
tii_->isMoveInstr(*mi, SrcReg, DstReg, SrcSubReg, DstSubReg))
CopyMI = mi;
// Earlyclobbers move back one.
- ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator);
+ ValNo = interval.getNextValue(defIndex, CopyMI, true, VNInfoAllocator);
assert(ValNo->id == 0 && "First value in interval is not 0?");
@@ -539,13 +539,15 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
// The new value number (#1) is defined by the instruction we claimed
// defined value #0.
VNInfo *ValNo = interval.getNextValue(OldValNo->def, OldValNo->copy,
+ false, // update at *
VNInfoAllocator);
-
+ ValNo->setFlags(OldValNo->getFlags()); // * <- updating here
+
// Value#0 is now defined by the 2-addr instruction.
OldValNo->def = RedefIndex;
OldValNo->copy = 0;
if (MO.isEarlyClobber())
- OldValNo->redefByEC = true;
+ OldValNo->setHasRedefByEC(true);
// Add the new live interval which replaces the range for the input copy.
LiveRange LR(DefIndex, RedefIndex, ValNo);
@@ -577,12 +579,14 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
DOUT << " Removing [" << Start << "," << End << "] from: ";
interval.print(DOUT, tri_); DOUT << "\n";
interval.removeRange(Start, End);
- VNI->hasPHIKill = true;
+ VNI->setHasPHIKill(true);
DOUT << " RESULT: "; interval.print(DOUT, tri_);
// 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(~0, 0, VNInfoAllocator));
+ LiveRange LR(Start, End,
+ interval.getNextValue(mbb->getNumber(), 0, false, VNInfoAllocator));
+ LR.valno->setIsPHIDef(true);
DOUT << " replace range with " << LR;
interval.addRange(LR);
interval.addKill(LR.valno, End);
@@ -604,13 +608,13 @@ void LiveIntervals::handleVirtualRegisterDef(MachineBasicBlock *mbb,
mi->getOpcode() == TargetInstrInfo::SUBREG_TO_REG ||
tii_->isMoveInstr(*mi, SrcReg, DstReg, SrcSubReg, DstSubReg))
CopyMI = mi;
- ValNo = interval.getNextValue(defIndex, CopyMI, VNInfoAllocator);
+ ValNo = interval.getNextValue(defIndex, CopyMI, true, VNInfoAllocator);
unsigned killIndex = getMBBEndIdx(mbb) + 1;
LiveRange LR(defIndex, killIndex, ValNo);
interval.addRange(LR);
interval.addKill(ValNo, killIndex);
- ValNo->hasPHIKill = true;
+ ValNo->setHasPHIKill(true);
DOUT << " +" << LR;
}
}
@@ -692,9 +696,9 @@ exit:
LiveInterval::iterator OldLR = interval.FindLiveRangeContaining(start);
bool Extend = OldLR != interval.end();
VNInfo *ValNo = Extend
- ? OldLR->valno : interval.getNextValue(start, CopyMI, VNInfoAllocator);
+ ? OldLR->valno : interval.getNextValue(start, CopyMI, true, VNInfoAllocator);
if (MO.isEarlyClobber() && Extend)
- ValNo->redefByEC = true;
+ ValNo->setHasRedefByEC(true);
LiveRange LR(start, end, ValNo);
interval.addRange(LR);
interval.addKill(LR.valno, end);
@@ -750,7 +754,7 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
DOUT << " killed";
end = getUseIndex(baseIndex) + 1;
SeenDefUse = true;
- goto exit;
+ break;
} else if (mi->modifiesRegister(interval.reg, tri_)) {
// Another instruction redefines the register before it is ever read.
// Then the register is essentially dead at the instruction that defines
@@ -759,7 +763,7 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
DOUT << " dead";
end = getDefIndex(start) + 1;
SeenDefUse = true;
- goto exit;
+ break;
}
baseIndex += InstrSlots::NUM;
@@ -771,7 +775,6 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
}
}
-exit:
// Live-in register might not be used at all.
if (!SeenDefUse) {
if (isAlias) {
@@ -783,7 +786,11 @@ exit:
}
}
- LiveRange LR(start, end, interval.getNextValue(~0U, 0, VNInfoAllocator));
+ VNInfo *vni =
+ interval.getNextValue(MBB->getNumber(), 0, false, VNInfoAllocator);
+ vni->setIsPHIDef(true);
+ LiveRange LR(start, end, vni);
+
interval.addRange(LR);
interval.addKill(LR.valno, end);
DOUT << " +" << LR << '\n';
@@ -896,7 +903,7 @@ LiveInterval* LiveIntervals::createInterval(unsigned reg) {
/// managing the allocated memory.
LiveInterval* LiveIntervals::dupInterval(LiveInterval *li) {
LiveInterval *NewLI = createInterval(li->reg);
- NewLI->Copy(*li, getVNInfoAllocator());
+ NewLI->Copy(*li, mri_, getVNInfoAllocator());
return NewLI;
}
@@ -1099,13 +1106,12 @@ bool LiveIntervals::isReMaterializable(const LiveInterval &li,
for (LiveInterval::const_vni_iterator i = li.vni_begin(), e = li.vni_end();
i != e; ++i) {
const VNInfo *VNI = *i;
- unsigned DefIdx = VNI->def;
- if (DefIdx == ~1U)
+ if (VNI->isUnused())
continue; // Dead val#.
// Is the def for the val# rematerializable?
- if (DefIdx == ~0u)
+ if (!VNI->isDefAccurate())
return false;
- MachineInstr *ReMatDefMI = getInstructionFromIndex(DefIdx);
+ MachineInstr *ReMatDefMI = getInstructionFromIndex(VNI->def);
bool DefIsLoad = false;
if (!ReMatDefMI ||
!isReMaterializable(li, VNI, ReMatDefMI, SpillIs, DefIsLoad))
@@ -1450,7 +1456,7 @@ rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
if (HasUse) {
if (CreatedNewVReg) {
LiveRange LR(getLoadIndex(index), getUseIndex(index)+1,
- nI.getNextValue(~0U, 0, VNInfoAllocator));
+ nI.getNextValue(0, 0, false, VNInfoAllocator));
DOUT << " +" << LR;
nI.addRange(LR);
} else {
@@ -1464,7 +1470,7 @@ rewriteInstructionForSpills(const LiveInterval &li, const VNInfo *VNI,
}
if (HasDef) {
LiveRange LR(getDefIndex(index), getStoreIndex(index),
- nI.getNextValue(~0U, 0, VNInfoAllocator));
+ nI.getNextValue(0, 0, false, VNInfoAllocator));
DOUT << " +" << LR;
nI.addRange(LR);
}
@@ -1840,14 +1846,14 @@ addIntervalsForSpillsFast(const LiveInterval &li,
unsigned index = getInstructionIndex(MI);
if (HasUse) {
LiveRange LR(getLoadIndex(index), getUseIndex(index),
- nI.getNextValue(~0U, 0, getVNInfoAllocator()));
+ nI.getNextValue(0, 0, false, getVNInfoAllocator()));
DOUT << " +" << LR;
nI.addRange(LR);
vrm.addRestorePoint(NewVReg, MI);
}
if (HasDef) {
LiveRange LR(getDefIndex(index), getStoreIndex(index),
- nI.getNextValue(~0U, 0, getVNInfoAllocator()));
+ nI.getNextValue(0, 0, false, getVNInfoAllocator()));
DOUT << " +" << LR;
nI.addRange(LR);
vrm.addSpillPoint(NewVReg, true, MI);
@@ -1961,12 +1967,11 @@ addIntervalsForSpills(const LiveInterval &li,
i != e; ++i) {
const VNInfo *VNI = *i;
unsigned VN = VNI->id;
- unsigned DefIdx = VNI->def;
- if (DefIdx == ~1U)
+ if (VNI->isUnused())
continue; // Dead val#.
// Is the def for the val# rematerializable?
- MachineInstr *ReMatDefMI = (DefIdx == ~0u)
- ? 0 : getInstructionFromIndex(DefIdx);
+ MachineInstr *ReMatDefMI = VNI->isDefAccurate()
+ ? getInstructionFromIndex(VNI->def) : 0;
bool dummy;
if (ReMatDefMI && isReMaterializable(li, VNI, ReMatDefMI, SpillIs, dummy)) {
// Remember how to remat the def of this val#.
@@ -1977,7 +1982,7 @@ addIntervalsForSpills(const LiveInterval &li,
ReMatDefs[VN] = Clone;
bool CanDelete = true;
- if (VNI->hasPHIKill) {
+ if (VNI->hasPHIKill()) {
// A kill is a phi node, not all of its uses can be rematerialized.
// It must not be deleted.
CanDelete = false;
@@ -2287,8 +2292,8 @@ LiveRange LiveIntervals::addLiveRangeToEndOfBlock(unsigned reg,
LiveInterval& Interval = getOrCreateInterval(reg);
VNInfo* VN = Interval.getNextValue(
getInstructionIndex(startInst) + InstrSlots::DEF,
- startInst, getVNInfoAllocator());
- VN->hasPHIKill = true;
+ startInst, true, getVNInfoAllocator());
+ VN->setHasPHIKill(true);
VN->kills.push_back(getMBBEndIdx(startInst->getParent()));
LiveRange LR(getInstructionIndex(startInst) + InstrSlots::DEF,
getMBBEndIdx(startInst->getParent()) + 1, VN);
diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp
index 622882169128..bd845085bbf5 100644
--- a/lib/CodeGen/LiveVariables.cpp
+++ b/lib/CodeGen/LiveVariables.cpp
@@ -359,12 +359,11 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
// That is, unless we are currently processing the last reference itself.
LastRefOrPartRef->addRegisterDead(Reg, TRI, true);
- /* Partial uses. Mark register def dead and add implicit def of
- sub-registers which are used.
- FIXME: LiveIntervalAnalysis can't handle this yet!
- EAX<dead> = op AL<imp-def>
- That is, EAX def is dead but AL def extends pass it.
- Enable this after live interval analysis is fixed to improve codegen!
+ // Partial uses. Mark register def dead and add implicit def of
+ // sub-registers which are used.
+ // EAX<dead> = op AL<imp-def>
+ // That is, EAX def is dead but AL def extends pass it.
+ // Enable this after live interval analysis is fixed to improve codegen!
else if (!PhysRegUse[Reg]) {
PhysRegDef[Reg]->addRegisterDead(Reg, TRI, true);
for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
@@ -377,7 +376,7 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
PartUses.erase(*SS);
}
}
- } */
+ }
else
LastRefOrPartRef->addRegisterKilled(Reg, TRI, true);
return true;
diff --git a/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp
index 4f5ab1f5860e..544d83a33f7f 100644
--- a/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/lib/CodeGen/MachineRegisterInfo.cpp
@@ -16,6 +16,7 @@ using namespace llvm;
MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI) {
VRegInfo.reserve(256);
+ RegAllocHints.reserve(256);
RegClass2VRegMap.resize(TRI.getNumRegClasses()+1); // RC ID starts at 1.
UsedPhysRegs.resize(TRI.getNumRegs());
@@ -64,6 +65,7 @@ MachineRegisterInfo::createVirtualRegister(const TargetRegisterClass *RegClass){
// Add a reg, but keep track of whether the vector reallocated or not.
void *ArrayBase = VRegInfo.empty() ? 0 : &VRegInfo[0];
VRegInfo.push_back(std::make_pair(RegClass, (MachineOperand*)0));
+ RegAllocHints.push_back(std::make_pair(0, 0));
if (!((&VRegInfo[0] == ArrayBase || VRegInfo.size() == 1)))
// The vector reallocated, handle this now.
diff --git a/lib/CodeGen/PreAllocSplitting.cpp b/lib/CodeGen/PreAllocSplitting.cpp
index 97d4728348e5..ae60c86c3d7c 100644
--- a/lib/CodeGen/PreAllocSplitting.cpp
+++ b/lib/CodeGen/PreAllocSplitting.cpp
@@ -343,7 +343,7 @@ int PreAllocSplitting::CreateSpillStackSlot(unsigned Reg,
if (CurrSLI->hasAtLeastOneValue())
CurrSValNo = CurrSLI->getValNumInfo(0);
else
- CurrSValNo = CurrSLI->getNextValue(~0U, 0, LSs->getVNInfoAllocator());
+ CurrSValNo = CurrSLI->getNextValue(0, 0, false, LSs->getVNInfoAllocator());
return SS;
}
@@ -637,8 +637,9 @@ PreAllocSplitting::PerformPHIConstructionFallBack(MachineBasicBlock::iterator Us
if (Phis.count(MBB)) return Phis[MBB];
unsigned StartIndex = LIs->getMBBStartIdx(MBB);
- VNInfo *RetVNI = Phis[MBB] = LI->getNextValue(~0U, /*FIXME*/ 0,
- LIs->getVNInfoAllocator());
+ VNInfo *RetVNI = Phis[MBB] =
+ LI->getNextValue(0, /*FIXME*/ 0, false, LIs->getVNInfoAllocator());
+
if (!IsIntraBlock) LiveOut[MBB] = RetVNI;
// If there are no uses or defs between our starting point and the
@@ -654,7 +655,7 @@ PreAllocSplitting::PerformPHIConstructionFallBack(MachineBasicBlock::iterator Us
IncomingVNs[*PI] = Incoming;
}
- if (MBB->pred_size() == 1 && !RetVNI->hasPHIKill) {
+ if (MBB->pred_size() == 1 && !RetVNI->hasPHIKill()) {
VNInfo* OldVN = RetVNI;
VNInfo* NewVN = IncomingVNs.begin()->second;
VNInfo* MergedVN = LI->MergeValueNumberInto(OldVN, NewVN);
@@ -678,7 +679,7 @@ PreAllocSplitting::PerformPHIConstructionFallBack(MachineBasicBlock::iterator Us
// VNInfo to represent the joined value.
for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator I =
IncomingVNs.begin(), E = IncomingVNs.end(); I != E; ++I) {
- I->second->hasPHIKill = true;
+ I->second->setHasPHIKill(true);
unsigned KillIndex = LIs->getMBBEndIdx(I->first);
if (!LiveInterval::isKill(I->second, KillIndex))
LI->addKill(I->second, KillIndex);
@@ -730,7 +731,9 @@ void PreAllocSplitting::ReconstructLiveInterval(LiveInterval* LI) {
unsigned DefIdx = LIs->getInstructionIndex(&*DI);
DefIdx = LiveIntervals::getDefIndex(DefIdx);
- VNInfo* NewVN = LI->getNextValue(DefIdx, 0, Alloc);
+ assert(DI->getOpcode() != TargetInstrInfo::PHI &&
+ "Following NewVN isPHIDef flag incorrect. Fix me!");
+ VNInfo* NewVN = LI->getNextValue(DefIdx, 0, true, Alloc);
// If the def is a move, set the copy field.
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
@@ -793,7 +796,7 @@ void PreAllocSplitting::RenumberValno(VNInfo* VN) {
// Bail out if we ever encounter a valno that has a PHI kill. We can't
// renumber these.
- if (OldVN->hasPHIKill) return;
+ if (OldVN->hasPHIKill()) return;
VNsToCopy.push_back(OldVN);
@@ -823,9 +826,7 @@ void PreAllocSplitting::RenumberValno(VNInfo* VN) {
VNInfo* OldVN = *OI;
// Copy the valno over
- VNInfo* NewVN = NewLI.getNextValue(OldVN->def, OldVN->copy,
- LIs->getVNInfoAllocator());
- NewLI.copyValNumInfo(NewVN, OldVN);
+ VNInfo* NewVN = NewLI.createValueCopy(OldVN, LIs->getVNInfoAllocator());
NewLI.MergeValueInAsValue(*CurrLI, OldVN, NewVN);
// Remove the valno from the old interval
@@ -873,7 +874,7 @@ bool PreAllocSplitting::Rematerialize(unsigned vreg, VNInfo* ValNo,
MachineBasicBlock::iterator KillPt = BarrierMBB->end();
unsigned KillIdx = 0;
- if (ValNo->def == ~0U || DefMI->getParent() == BarrierMBB)
+ if (!ValNo->isDefAccurate() || DefMI->getParent() == BarrierMBB)
KillPt = findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB, KillIdx);
else
KillPt = findNextEmptySlot(DefMI->getParent(), DefMI, KillIdx);
@@ -942,7 +943,7 @@ MachineInstr* PreAllocSplitting::FoldSpill(unsigned vreg,
if (CurrSLI->hasAtLeastOneValue())
CurrSValNo = CurrSLI->getValNumInfo(0);
else
- CurrSValNo = CurrSLI->getNextValue(~0U, 0, LSs->getVNInfoAllocator());
+ CurrSValNo = CurrSLI->getNextValue(0, 0, false, LSs->getVNInfoAllocator());
}
return FMI;
@@ -1032,13 +1033,13 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
CurrLI->FindLiveRangeContaining(LIs->getUseIndex(BarrierIdx));
VNInfo *ValNo = LR->valno;
- if (ValNo->def == ~1U) {
+ if (ValNo->isUnused()) {
// Defined by a dead def? How can this be?
assert(0 && "Val# is defined by a dead def?");
abort();
}
- MachineInstr *DefMI = (ValNo->def != ~0U)
+ MachineInstr *DefMI = ValNo->isDefAccurate()
? LIs->getInstructionFromIndex(ValNo->def) : NULL;
// If this would create a new join point, do not split.
@@ -1072,8 +1073,8 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
unsigned SpillIndex = 0;
MachineInstr *SpillMI = NULL;
int SS = -1;
- if (ValNo->def == ~0U) {
- // If it's defined by a phi, we must split just before the barrier.
+ if (!ValNo->isDefAccurate()) {
+ // If we don't know where the def is we must split just before the barrier.
if ((SpillMI = FoldSpill(LI->reg, RC, 0, Barrier,
BarrierMBB, SS, RefsInMBB))) {
SpillIndex = LIs->getInstructionIndex(SpillMI);
@@ -1254,17 +1255,16 @@ bool PreAllocSplitting::removeDeadSpills(SmallPtrSet<LiveInterval*, 8>& split) {
// We don't currently try to handle definitions with PHI kills, because
// it would involve processing more than one VNInfo at once.
- if (CurrVN->hasPHIKill) continue;
+ if (CurrVN->hasPHIKill()) continue;
// We also don't try to handle the results of PHI joins, since there's
// no defining instruction to analyze.
- unsigned DefIdx = CurrVN->def;
- if (DefIdx == ~0U || DefIdx == ~1U) continue;
+ if (!CurrVN->isDefAccurate() || CurrVN->isUnused()) continue;
// We're only interested in eliminating cruft introduced by the splitter,
// is of the form load-use or load-use-store. First, check that the
// definition is a load, and remember what stack slot we loaded it from.
- MachineInstr* DefMI = LIs->getInstructionFromIndex(DefIdx);
+ MachineInstr* DefMI = LIs->getInstructionFromIndex(CurrVN->def);
int FrameIndex;
if (!TII->isLoadFromStackSlot(DefMI, FrameIndex)) continue;
@@ -1383,7 +1383,7 @@ bool PreAllocSplitting::createsNewJoin(LiveRange* LR,
if (DefMBB == BarrierMBB)
return false;
- if (LR->valno->hasPHIKill)
+ if (LR->valno->hasPHIKill())
return false;
unsigned MBBEnd = LIs->getMBBEndIdx(BarrierMBB);
diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp
index 804fae55e545..41a42fd22d3b 100644
--- a/lib/CodeGen/RegAllocLinearScan.cpp
+++ b/lib/CodeGen/RegAllocLinearScan.cpp
@@ -281,7 +281,8 @@ namespace {
/// getFreePhysReg - return a free physical register for this virtual
/// register interval if we have one, otherwise return 0.
unsigned getFreePhysReg(LiveInterval* cur);
- unsigned getFreePhysReg(const TargetRegisterClass *RC,
+ unsigned getFreePhysReg(LiveInterval* cur,
+ const TargetRegisterClass *RC,
unsigned MaxInactiveCount,
SmallVector<unsigned, 256> &inactiveCounts,
bool SkipDGRegs);
@@ -352,11 +353,12 @@ void RALinScan::ComputeRelatedRegClasses() {
/// different register classes or because the coalescer was overly
/// conservative.
unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
- if ((cur.preference && cur.preference == Reg) || !cur.containsOneValue())
+ unsigned Preference = vrm_->getRegAllocPref(cur.reg);
+ if ((Preference && Preference == Reg) || !cur.containsOneValue())
return Reg;
VNInfo *vni = cur.begin()->valno;
- if (!vni->def || vni->def == ~1U || vni->def == ~0U)
+ if (!vni->def || vni->isUnused() || !vni->isDefAccurate())
return Reg;
MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg, PhysReg;
@@ -584,7 +586,7 @@ void RALinScan::linearScan()
// register allocator had to spill other registers in its register class.
if (ls_->getNumIntervals() == 0)
return;
- if (!vrm_->FindUnusedRegisters(tri_, li_))
+ if (!vrm_->FindUnusedRegisters(li_))
return;
}
@@ -743,7 +745,7 @@ static void addStackInterval(LiveInterval *cur, LiveStacks *ls_,
if (SI.hasAtLeastOneValue())
VNI = SI.getValNumInfo(0);
else
- VNI = SI.getNextValue(~0U, 0, ls_->getVNInfoAllocator());
+ VNI = SI.getNextValue(0, 0, false, ls_->getVNInfoAllocator());
LiveInterval &RI = li_->getInterval(cur->reg);
// FIXME: This may be overly conservative.
@@ -897,7 +899,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
// This is an implicitly defined live interval, just assign any register.
const TargetRegisterClass *RC = mri_->getRegClass(cur->reg);
if (cur->empty()) {
- unsigned physReg = cur->preference;
+ unsigned physReg = vrm_->getRegAllocPref(cur->reg);
if (!physReg)
physReg = *RC->allocation_order_begin(*mf_);
DOUT << tri_->getName(physReg) << '\n';
@@ -917,9 +919,9 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
// register class, then we should try to assign it the same register.
// This can happen when the move is from a larger register class to a smaller
// one, e.g. X86::mov32to32_. These move instructions are not coalescable.
- if (!cur->preference && cur->hasAtLeastOneValue()) {
+ if (!vrm_->getRegAllocPref(cur->reg) && cur->hasAtLeastOneValue()) {
VNInfo *vni = cur->begin()->valno;
- if (vni->def && vni->def != ~1U && vni->def != ~0U) {
+ if (vni->def && !vni->isUnused() && vni->isDefAccurate()) {
MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
unsigned SrcReg, DstReg, SrcSubReg, DstSubReg;
if (CopyMI &&
@@ -935,7 +937,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
if (DstSubReg)
Reg = tri_->getMatchingSuperReg(Reg, DstSubReg, RC);
if (Reg && allocatableRegs_[Reg] && RC->contains(Reg))
- cur->preference = Reg;
+ mri_->setRegAllocationHint(cur->reg, 0, Reg);
}
}
}
@@ -1044,7 +1046,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
if (LiveInterval *NextReloadLI = hasNextReloadInterval(cur)) {
// "Downgrade" physReg to try to keep physReg from being allocated until
// the next reload from the same SS is allocated.
- NextReloadLI->preference = physReg;
+ mri_->setRegAllocationHint(NextReloadLI->reg, 0, physReg);
DowngradeRegister(cur, physReg);
}
return;
@@ -1071,7 +1073,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
// Find a register to spill.
float minWeight = HUGE_VALF;
- unsigned minReg = 0; /*cur->preference*/; // Try the pref register first.
+ unsigned minReg = 0;
bool Found = false;
std::vector<std::pair<unsigned,float> > RegsWeights;
@@ -1290,7 +1292,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
// It interval has a preference, it must be defined by a copy. Clear the
// preference now since the source interval allocation may have been
// undone as well.
- i->preference = 0;
+ mri_->setRegAllocationHint(i->reg, 0, 0);
else {
UpgradeRegister(ii->second);
}
@@ -1346,15 +1348,23 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
}
}
-unsigned RALinScan::getFreePhysReg(const TargetRegisterClass *RC,
+unsigned RALinScan::getFreePhysReg(LiveInterval* cur,
+ const TargetRegisterClass *RC,
unsigned MaxInactiveCount,
SmallVector<unsigned, 256> &inactiveCounts,
bool SkipDGRegs) {
unsigned FreeReg = 0;
unsigned FreeRegInactiveCount = 0;
- TargetRegisterClass::iterator I = RC->allocation_order_begin(*mf_);
- TargetRegisterClass::iterator E = RC->allocation_order_end(*mf_);
+ std::pair<unsigned, unsigned> Hint = mri_->getRegAllocationHint(cur->reg);
+ // Resolve second part of the hint (if possible) given the current allocation.
+ unsigned physReg = Hint.second;
+ if (physReg &&
+ TargetRegisterInfo::isVirtualRegister(physReg) && vrm_->hasPhys(physReg))
+ physReg = vrm_->getPhys(physReg);
+
+ TargetRegisterClass::iterator I, E;
+ tie(I, E) = tri_->getAllocationOrder(RC, Hint.first, physReg, *mf_);
assert(I != E && "No allocatable register in this register class!");
// Scan for the first available register.
@@ -1377,7 +1387,7 @@ unsigned RALinScan::getFreePhysReg(const TargetRegisterClass *RC,
// return this register.
if (FreeReg == 0 || FreeRegInactiveCount == MaxInactiveCount)
return FreeReg;
-
+
// Continue scanning the registers, looking for the one with the highest
// inactive count. Alkis found that this reduced register pressure very
// slightly on X86 (in rev 1.94 of this file), though this should probably be
@@ -1428,20 +1438,21 @@ unsigned RALinScan::getFreePhysReg(LiveInterval *cur) {
// If copy coalescer has assigned a "preferred" register, check if it's
// available first.
- if (cur->preference) {
- DOUT << "(preferred: " << tri_->getName(cur->preference) << ") ";
- if (isRegAvail(cur->preference) &&
- RC->contains(cur->preference))
- return cur->preference;
+ unsigned Preference = vrm_->getRegAllocPref(cur->reg);
+ if (Preference) {
+ DOUT << "(preferred: " << tri_->getName(Preference) << ") ";
+ if (isRegAvail(Preference) &&
+ RC->contains(Preference))
+ return Preference;
}
if (!DowngradedRegs.empty()) {
- unsigned FreeReg = getFreePhysReg(RC, MaxInactiveCount, inactiveCounts,
+ unsigned FreeReg = getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts,
true);
if (FreeReg)
return FreeReg;
}
- return getFreePhysReg(RC, MaxInactiveCount, inactiveCounts, false);
+ return getFreePhysReg(cur, RC, MaxInactiveCount, inactiveCounts, false);
}
FunctionPass* llvm::createLinearScanRegisterAllocator() {
diff --git a/lib/CodeGen/RegAllocPBQP.cpp b/lib/CodeGen/RegAllocPBQP.cpp
index 61450a7cca7c..89e2c59fe805 100644
--- a/lib/CodeGen/RegAllocPBQP.cpp
+++ b/lib/CodeGen/RegAllocPBQP.cpp
@@ -651,7 +651,7 @@ void PBQPRegAlloc::addStackInterval(const LiveInterval *spilled,
if (stackInterval.getNumValNums() != 0)
vni = stackInterval.getValNumInfo(0);
else
- vni = stackInterval.getNextValue(-0U, 0, lss->getVNInfoAllocator());
+ vni = stackInterval.getNextValue(0, 0, false, lss->getVNInfoAllocator());
LiveInterval &rhsInterval = lis->getInterval(spilled->reg);
stackInterval.MergeRangesInAsValue(rhsInterval, vni);
@@ -733,8 +733,7 @@ void PBQPRegAlloc::finalizeAlloc() const {
itr != end; ++itr) {
LiveInterval *li = *itr;
- unsigned physReg = li->preference;
-
+ unsigned physReg = vrm->getRegAllocPref(li->reg);
if (physReg == 0) {
const TargetRegisterClass *liRC = mri->getRegClass(li->reg);
physReg = *liRC->allocation_order_begin(*mf);
diff --git a/lib/CodeGen/SelectionDAG/FastISel.cpp b/lib/CodeGen/SelectionDAG/FastISel.cpp
index 4a7dbebe2de8..24fccf00eec4 100644
--- a/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -47,7 +47,6 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/CodeGen/DebugLoc.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/Analysis/DebugInfo.h"
#include "llvm/Target/TargetData.h"
@@ -361,7 +360,7 @@ bool FastISel::SelectCall(User *I) {
// Returned ID is 0 if this is unbalanced "end of inlined
// scope". This could happen if optimizer eats dbg intrinsics
// or "beginning of inlined scope" is not recoginized due to
- // missing location info. In such cases, do ignore this region.end.
+ // missing location info. In such cases, ignore this region.end.
BuildMI(MBB, DL, II).addImm(ID);
} else {
const TargetInstrDesc &II = TII.get(TargetInstrInfo::DBG_LABEL);
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index f3c2833e0fe3..1bb80901ded0 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -2768,6 +2768,53 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
ISD::SETULT : ISD::SETUGT));
break;
}
+ case ISD::UMULO:
+ case ISD::SMULO: {
+ MVT VT = Node->getValueType(0);
+ SDValue LHS = Node->getOperand(0);
+ SDValue RHS = Node->getOperand(1);
+ SDValue BottomHalf;
+ SDValue TopHalf;
+ static unsigned Ops[2][3] =
+ { { ISD::MULHU, ISD::UMUL_LOHI, ISD::ZERO_EXTEND },
+ { ISD::MULHS, ISD::SMUL_LOHI, ISD::SIGN_EXTEND }};
+ bool isSigned = Node->getOpcode() == ISD::SMULO;
+ if (TLI.isOperationLegalOrCustom(Ops[isSigned][0], VT)) {
+ BottomHalf = DAG.getNode(ISD::MUL, dl, VT, LHS, RHS);
+ TopHalf = DAG.getNode(Ops[isSigned][0], dl, VT, LHS, RHS);
+ } else if (TLI.isOperationLegalOrCustom(Ops[isSigned][1], VT)) {
+ BottomHalf = DAG.getNode(Ops[isSigned][1], dl, DAG.getVTList(VT, VT), LHS,
+ RHS);
+ TopHalf = BottomHalf.getValue(1);
+ } else if (TLI.isTypeLegal(MVT::getIntegerVT(VT.getSizeInBits() * 2))) {
+ MVT WideVT = MVT::getIntegerVT(VT.getSizeInBits() * 2);
+ LHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, LHS);
+ RHS = DAG.getNode(Ops[isSigned][2], dl, WideVT, RHS);
+ Tmp1 = DAG.getNode(ISD::MUL, dl, WideVT, LHS, RHS);
+ BottomHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Tmp1,
+ DAG.getIntPtrConstant(0));
+ TopHalf = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, VT, Tmp1,
+ DAG.getIntPtrConstant(1));
+ } else {
+ // FIXME: We should be able to fall back to a libcall with an illegal
+ // type in some cases cases.
+ // Also, we can fall back to a division in some cases, but that's a big
+ // performance hit in the general case.
+ assert(0 && "Don't know how to expand this operation yet!");
+ }
+ if (isSigned) {
+ Tmp1 = DAG.getConstant(VT.getSizeInBits() - 1, TLI.getShiftAmountTy());
+ Tmp1 = DAG.getNode(ISD::SRA, dl, VT, BottomHalf, Tmp1);
+ TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf, Tmp1,
+ ISD::SETNE);
+ } else {
+ TopHalf = DAG.getSetCC(dl, TLI.getSetCCResultType(VT), TopHalf,
+ DAG.getConstant(0, VT), ISD::SETNE);
+ }
+ Results.push_back(BottomHalf);
+ Results.push_back(TopHalf);
+ break;
+ }
case ISD::BUILD_PAIR: {
MVT PairTy = Node->getValueType(0);
Tmp1 = DAG.getNode(ISD::ZERO_EXTEND, dl, PairTy, Node->getOperand(0));
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
index b7d7818d6e02..6e5adee84c34 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
@@ -95,14 +95,13 @@ void DAGTypeLegalizer::ExpandRes_BIT_CONVERT(SDNode *N, SDValue &Lo,
if (InVT.isVector() && OutVT.isInteger()) {
// Handle cases like i64 = BIT_CONVERT v1i64 on x86, where the operand
// is legal but the result is not.
- MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OutVT), 2);
+ MVT NVT = MVT::getVectorVT(NOutVT, 2);
if (isTypeLegal(NVT)) {
SDValue CastInOp = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, InOp);
- MVT EltNVT = NVT.getVectorElementType();
- Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltNVT, CastInOp,
+ Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp,
DAG.getIntPtrConstant(0));
- Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltNVT, CastInOp,
+ Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NOutVT, CastInOp,
DAG.getIntPtrConstant(1));
if (TLI.isBigEndian())
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index 93750d6b98c4..48ebd0ff0d4f 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -5317,8 +5317,12 @@ void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
if ((OpFlag & 7) == 2 /*REGDEF*/
|| (OpFlag & 7) == 6 /* EARLYCLOBBER REGDEF */) {
// Add (OpFlag&0xffff)>>3 registers to MatchedRegs.
- assert(!OpInfo.isIndirect &&
- "Don't know how to handle tied indirect register inputs yet!");
+ if (OpInfo.isIndirect) {
+ cerr << "llvm: error: "
+ "Don't know how to handle tied indirect "
+ "register inputs yet!\n";
+ exit(1);
+ }
RegsForValue MatchedRegs;
MatchedRegs.TLI = &TLI;
MatchedRegs.ValueVTs.push_back(InOperandVal.getValueType());
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index ab4cd515531c..a771d4695a52 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -171,6 +171,8 @@ static void InitLibcallNames(const char **Names) {
Names[RTLIB::FPROUND_PPCF128_F32] = "__trunctfsf2";
Names[RTLIB::FPROUND_F80_F64] = "__truncxfdf2";
Names[RTLIB::FPROUND_PPCF128_F64] = "__trunctfdf2";
+ Names[RTLIB::FPTOSINT_F32_I8] = "__fixsfi8";
+ Names[RTLIB::FPTOSINT_F32_I16] = "__fixsfi16";
Names[RTLIB::FPTOSINT_F32_I32] = "__fixsfsi";
Names[RTLIB::FPTOSINT_F32_I64] = "__fixsfdi";
Names[RTLIB::FPTOSINT_F32_I128] = "__fixsfti";
@@ -183,6 +185,8 @@ static void InitLibcallNames(const char **Names) {
Names[RTLIB::FPTOSINT_PPCF128_I32] = "__fixtfsi";
Names[RTLIB::FPTOSINT_PPCF128_I64] = "__fixtfdi";
Names[RTLIB::FPTOSINT_PPCF128_I128] = "__fixtfti";
+ Names[RTLIB::FPTOUINT_F32_I8] = "__fixunssfi8";
+ Names[RTLIB::FPTOUINT_F32_I16] = "__fixunssfi16";
Names[RTLIB::FPTOUINT_F32_I32] = "__fixunssfsi";
Names[RTLIB::FPTOUINT_F32_I64] = "__fixunssfdi";
Names[RTLIB::FPTOUINT_F32_I128] = "__fixunssfti";
@@ -271,6 +275,10 @@ RTLIB::Libcall RTLIB::getFPROUND(MVT OpVT, MVT RetVT) {
/// UNKNOWN_LIBCALL if there is none.
RTLIB::Libcall RTLIB::getFPTOSINT(MVT OpVT, MVT RetVT) {
if (OpVT == MVT::f32) {
+ if (RetVT == MVT::i8)
+ return FPTOSINT_F32_I8;
+ if (RetVT == MVT::i16)
+ return FPTOSINT_F32_I16;
if (RetVT == MVT::i32)
return FPTOSINT_F32_I32;
if (RetVT == MVT::i64)
@@ -306,6 +314,10 @@ RTLIB::Libcall RTLIB::getFPTOSINT(MVT OpVT, MVT RetVT) {
/// UNKNOWN_LIBCALL if there is none.
RTLIB::Libcall RTLIB::getFPTOUINT(MVT OpVT, MVT RetVT) {
if (OpVT == MVT::f32) {
+ if (RetVT == MVT::i8)
+ return FPTOUINT_F32_I8;
+ if (RetVT == MVT::i16)
+ return FPTOUINT_F32_I16;
if (RetVT == MVT::i32)
return FPTOUINT_F32_I32;
if (RetVT == MVT::i64)
@@ -2584,8 +2596,12 @@ bool TargetLowering::CheckTailCallReturnConstraints(CallSDNode *TheCall,
// Check that operand of the RET node sources from the CALL node. The RET node
// has at least two operands. Operand 0 holds the chain. Operand 1 holds the
// value.
+ // Also we need to check that there is no code in between the call and the
+ // return. Hence we also check that the incomming chain to the return sources
+ // from the outgoing chain of the call.
if (NumOps > 1 &&
- IgnoreHarmlessInstructions(Ret.getOperand(1)) == SDValue(TheCall,0))
+ IgnoreHarmlessInstructions(Ret.getOperand(1)) == SDValue(TheCall,0) &&
+ Ret.getOperand(0) == SDValue(TheCall, TheCall->getNumValues()-1))
return true;
// void return: The RET node has the chain result value of the CALL node as
// input.
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp
index 2bc234f7d09e..20348055bd96 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.cpp
+++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp
@@ -141,7 +141,7 @@ bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(LiveInterval &IntA,
// The live interval of ECX is represented as this:
// %reg20,inf = [46,47:1)[174,230:0) 0@174-(230) 1@46-(47)
// The coalescer has no idea there was a def in the middle of [174,230].
- if (AValNo->redefByEC)
+ if (AValNo->hasRedefByEC())
return false;
// If AValNo is defined as a copy from IntB, we can potentially process this.
@@ -203,7 +203,8 @@ bool SimpleRegisterCoalescing::AdjustCopiesBackFrom(LiveInterval &IntA,
for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) {
LiveInterval &SRLI = li_->getInterval(*SR);
SRLI.addRange(LiveRange(FillerStart, FillerEnd,
- SRLI.getNextValue(FillerStart, 0, li_->getVNInfoAllocator())));
+ SRLI.getNextValue(FillerStart, 0, true,
+ li_->getVNInfoAllocator())));
}
}
@@ -304,8 +305,10 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA,
assert(ALR != IntA.end() && "Live range not found!");
VNInfo *AValNo = ALR->valno;
// If other defs can reach uses of this def, then it's not safe to perform
- // the optimization.
- if (AValNo->def == ~0U || AValNo->def == ~1U || AValNo->hasPHIKill)
+ // the optimization. FIXME: Do isPHIDef and isDefAccurate both need to be
+ // tested?
+ if (AValNo->isPHIDef() || !AValNo->isDefAccurate() ||
+ AValNo->isUnused() || AValNo->hasPHIKill())
return false;
MachineInstr *DefMI = li_->getInstructionFromIndex(AValNo->def);
const TargetInstrDesc &TID = DefMI->getDesc();
@@ -351,7 +354,7 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA,
unsigned OpIdx = NewMI->findRegisterUseOperandIdx(IntA.reg, false);
NewMI->getOperand(OpIdx).setIsKill();
- bool BHasPHIKill = BValNo->hasPHIKill;
+ bool BHasPHIKill = BValNo->hasPHIKill();
SmallVector<VNInfo*, 4> BDeadValNos;
SmallVector<unsigned, 4> BKills;
std::map<unsigned, unsigned> BExtend;
@@ -403,7 +406,7 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA,
// extended to the end of the existing live range defined by the copy.
unsigned DefIdx = li_->getDefIndex(UseIdx);
const LiveRange *DLR = IntB.getLiveRangeContaining(DefIdx);
- BHasPHIKill |= DLR->valno->hasPHIKill;
+ BHasPHIKill |= DLR->valno->hasPHIKill();
assert(DLR->valno->def == DefIdx);
BDeadValNos.push_back(DLR->valno);
BExtend[DLR->start] = DLR->end;
@@ -462,7 +465,7 @@ bool SimpleRegisterCoalescing::RemoveCopyByCommutingDef(LiveInterval &IntA,
}
}
IntB.addKills(ValNo, BKills);
- ValNo->hasPHIKill = BHasPHIKill;
+ ValNo->setHasPHIKill(BHasPHIKill);
DOUT << " result = "; IntB.print(DOUT, tri_);
DOUT << "\n";
@@ -578,8 +581,10 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
assert(SrcLR != SrcInt.end() && "Live range not found!");
VNInfo *ValNo = SrcLR->valno;
// If other defs can reach uses of this def, then it's not safe to perform
- // the optimization.
- if (ValNo->def == ~0U || ValNo->def == ~1U || ValNo->hasPHIKill)
+ // the optimization. FIXME: Do isPHIDef and isDefAccurate both need to be
+ // tested?
+ if (ValNo->isPHIDef() || !ValNo->isDefAccurate() ||
+ ValNo->isUnused() || ValNo->hasPHIKill())
return false;
MachineInstr *DefMI = li_->getInstructionFromIndex(ValNo->def);
const TargetInstrDesc &TID = DefMI->getDesc();
@@ -616,19 +621,17 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
}
MachineBasicBlock::iterator MII = next(MachineBasicBlock::iterator(CopyMI));
- CopyMI->removeFromParent();
tii_->reMaterialize(*MBB, MII, DstReg, DefMI);
MachineInstr *NewMI = prior(MII);
if (checkForDeadDef) {
- // PR4090 fix: Trim interval failed because there was no use of the
- // source interval in this MBB. If the def is in this MBB too then we
- // should mark it dead:
- if (DefMI->getParent() == MBB) {
- DefMI->addRegisterDead(SrcInt.reg, tri_);
- SrcLR->end = SrcLR->start + 1;
- }
-
+ // PR4090 fix: Trim interval failed because there was no use of the
+ // source interval in this MBB. If the def is in this MBB too then we
+ // should mark it dead:
+ if (DefMI->getParent() == MBB) {
+ DefMI->addRegisterDead(SrcInt.reg, tri_);
+ SrcLR->end = SrcLR->start + 1;
+ }
}
// CopyMI may have implicit operands, transfer them over to the newly
@@ -647,7 +650,7 @@ bool SimpleRegisterCoalescing::ReMaterializeTrivialDef(LiveInterval &SrcInt,
}
li_->ReplaceMachineInstrInMaps(CopyMI, NewMI);
- MBB->getParent()->DeleteMachineInstr(CopyMI);
+ CopyMI->eraseFromParent();
ReMatCopies.insert(CopyMI);
ReMatDefs.insert(DefMI);
++NumReMats;
@@ -673,7 +676,7 @@ bool SimpleRegisterCoalescing::isBackEdgeCopy(MachineInstr *CopyMI,
return false;
unsigned KillIdx = li_->getMBBEndIdx(MBB) + 1;
if (DstLR->valno->kills.size() == 1 &&
- DstLR->valno->kills[0] == KillIdx && DstLR->valno->hasPHIKill)
+ DstLR->valno->kills[0] == KillIdx && DstLR->valno->hasPHIKill())
return true;
return false;
}
@@ -937,7 +940,7 @@ bool SimpleRegisterCoalescing::CanCoalesceWithImpDef(MachineInstr *CopyMI,
LiveInterval::iterator LR = li.FindLiveRangeContaining(CopyIdx);
if (LR == li.end())
return false;
- if (LR->valno->hasPHIKill)
+ if (LR->valno->hasPHIKill())
return false;
if (LR->valno->def != CopyIdx)
return false;
@@ -965,11 +968,11 @@ bool SimpleRegisterCoalescing::CanCoalesceWithImpDef(MachineInstr *CopyMI,
}
-/// RemoveCopiesFromValNo - The specified value# is defined by an implicit
-/// def and it is being removed. Turn all copies from this value# into
-/// identity copies so they will be removed.
-void SimpleRegisterCoalescing::RemoveCopiesFromValNo(LiveInterval &li,
- VNInfo *VNI) {
+/// TurnCopiesFromValNoToImpDefs - The specified value# is defined by an
+/// implicit_def and it is being removed. Turn all copies from this value#
+/// into implicit_defs.
+void SimpleRegisterCoalescing::TurnCopiesFromValNoToImpDefs(LiveInterval &li,
+ VNInfo *VNI) {
SmallVector<MachineInstr*, 4> ImpDefs;
MachineOperand *LastUse = NULL;
unsigned LastUseIdx = li_->getUseIndex(VNI->def);
@@ -979,9 +982,8 @@ void SimpleRegisterCoalescing::RemoveCopiesFromValNo(LiveInterval &li,
MachineInstr *MI = &*RI;
++RI;
if (MO->isDef()) {
- if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
+ if (MI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF)
ImpDefs.push_back(MI);
- }
continue;
}
if (JoinedCopies.count(MI))
@@ -994,13 +996,18 @@ void SimpleRegisterCoalescing::RemoveCopiesFromValNo(LiveInterval &li,
unsigned SrcReg, DstReg, SrcSubIdx, DstSubIdx;
if (tii_->isMoveInstr(*MI, SrcReg, DstReg, SrcSubIdx, DstSubIdx) &&
SrcReg == li.reg) {
- // Each use MI may have multiple uses of this register. Change them all.
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand &MO = MI->getOperand(i);
- if (MO.isReg() && MO.getReg() == li.reg)
- MO.setReg(DstReg);
- }
- JoinedCopies.insert(MI);
+ // Change it to an implicit_def.
+ MI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF));
+ for (int i = MI->getNumOperands() - 1, e = 0; i > e; --i)
+ MI->RemoveOperand(i);
+ // It's no longer a copy, update the valno it defines.
+ unsigned DefIdx = li_->getDefIndex(UseIdx);
+ LiveInterval &DstInt = li_->getInterval(DstReg);
+ LiveInterval::iterator DLR = DstInt.FindLiveRangeContaining(DefIdx);
+ assert(DLR != DstInt.end() && "Live range not found!");
+ assert(DLR->valno->copy == MI);
+ DLR->valno->copy = NULL;
+ ReMatCopies.insert(MI);
} else if (UseIdx > LastUseIdx) {
LastUseIdx = UseIdx;
LastUse = MO;
@@ -1265,6 +1272,17 @@ SimpleRegisterCoalescing::CanJoinInsertSubRegToPhysReg(unsigned DstReg,
return true;
}
+/// getRegAllocPreference - Return register allocation preference register.
+///
+static unsigned getRegAllocPreference(unsigned Reg, MachineFunction &MF,
+ MachineRegisterInfo *MRI,
+ const TargetRegisterInfo *TRI) {
+ if (TargetRegisterInfo::isPhysicalRegister(Reg))
+ return 0;
+ std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(Reg);
+ return TRI->ResolveRegAllocHint(Hint.first, Hint.second, MF);
+}
+
/// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg,
/// which are the src/dst of the copy instruction CopyMI. This returns true
/// if the copy was successfully coalesced away. If it is not currently
@@ -1566,7 +1584,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
if (PhysJoinTweak) {
if (SrcIsPhys) {
if (!isWinToJoinVRWithSrcPhysReg(CopyMI, CopyMBB, DstInt, SrcInt)) {
- DstInt.preference = SrcReg;
+ mri_->setRegAllocationHint(DstInt.reg, 0, SrcReg);
++numAborts;
DOUT << "\tMay tie down a physical register, abort!\n";
Again = true; // May be possible to coalesce later.
@@ -1574,7 +1592,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
}
} else {
if (!isWinToJoinVRWithDstPhysReg(CopyMI, CopyMBB, DstInt, SrcInt)) {
- SrcInt.preference = DstReg;
+ mri_->setRegAllocationHint(SrcInt.reg, 0, DstReg);
++numAborts;
DOUT << "\tMay tie down a physical register, abort!\n";
Again = true; // May be possible to coalesce later.
@@ -1598,7 +1616,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
if (Length > Threshold &&
(((float)std::distance(mri_->use_begin(JoinVReg),
mri_->use_end()) / Length) < Ratio)) {
- JoinVInt.preference = JoinPReg;
+ mri_->setRegAllocationHint(JoinVInt.reg, 0, JoinPReg);
++numAborts;
DOUT << "\tMay tie down a physical register, abort!\n";
Again = true; // May be possible to coalesce later.
@@ -1669,9 +1687,9 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
E = SavedLI->vni_end(); I != E; ++I) {
const VNInfo *ValNo = *I;
VNInfo *NewValNo = RealInt.getNextValue(ValNo->def, ValNo->copy,
+ false, // updated at *
li_->getVNInfoAllocator());
- NewValNo->hasPHIKill = ValNo->hasPHIKill;
- NewValNo->redefByEC = ValNo->redefByEC;
+ NewValNo->setFlags(ValNo->getFlags()); // * updated here.
RealInt.addKills(NewValNo, ValNo->kills);
RealInt.MergeValueInAsValue(*SavedLI, ValNo, NewValNo);
}
@@ -1691,7 +1709,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
!SrcIsPhys && !DstIsPhys) {
if ((isExtSubReg && !Swapped) ||
((isInsSubReg || isSubRegToReg) && Swapped)) {
- ResSrcInt->Copy(*ResDstInt, li_->getVNInfoAllocator());
+ ResSrcInt->Copy(*ResDstInt, mri_, li_->getVNInfoAllocator());
std::swap(SrcReg, DstReg);
std::swap(ResSrcInt, ResDstInt);
}
@@ -1710,7 +1728,8 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
for (LiveInterval::const_vni_iterator i = ResSrcInt->vni_begin(),
e = ResSrcInt->vni_end(); i != e; ++i) {
const VNInfo *vni = *i;
- if (!vni->def || vni->def == ~1U || vni->def == ~0U)
+ // FIXME: Do isPHIDef and isDefAccurate both need to be tested?
+ if (!vni->def || vni->isUnused() || vni->isPHIDef() || !vni->isDefAccurate())
continue;
MachineInstr *CopyMI = li_->getInstructionFromIndex(vni->def);
unsigned NewSrcReg, NewDstReg, NewSrcSubIdx, NewDstSubIdx;
@@ -1747,6 +1766,9 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
// being merged.
li_->removeInterval(SrcReg);
+ // Update regalloc hint.
+ tri_->UpdateRegAllocHint(SrcReg, DstReg, *mf_);
+
// Manually deleted the live interval copy.
if (SavedLI) {
SavedLI->clear();
@@ -1762,7 +1784,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
VNInfo *ImpVal = LR->valno;
assert(ImpVal->def == CopyIdx);
unsigned NextDef = LR->end;
- RemoveCopiesFromValNo(*ResDstInt, ImpVal);
+ TurnCopiesFromValNoToImpDefs(*ResDstInt, ImpVal);
ResDstInt->removeValNo(ImpVal);
LR = ResDstInt->FindLiveRangeContaining(NextDef);
if (LR != ResDstInt->end() && LR->valno->def == NextDef) {
@@ -1778,11 +1800,12 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
// If resulting interval has a preference that no longer fits because of subreg
// coalescing, just clear the preference.
- if (ResDstInt->preference && (isExtSubReg || isInsSubReg || isSubRegToReg) &&
+ unsigned Preference = getRegAllocPreference(ResDstInt->reg, *mf_, mri_, tri_);
+ if (Preference && (isExtSubReg || isInsSubReg || isSubRegToReg) &&
TargetRegisterInfo::isVirtualRegister(ResDstInt->reg)) {
const TargetRegisterClass *RC = mri_->getRegClass(ResDstInt->reg);
- if (!RC->contains(ResDstInt->preference))
- ResDstInt->preference = 0;
+ if (!RC->contains(Preference))
+ mri_->setRegAllocationHint(ResDstInt->reg, 0, 0);
}
DOUT << "\n\t\tJoined. Result = "; ResDstInt->print(DOUT, tri_);
@@ -1856,7 +1879,8 @@ bool SimpleRegisterCoalescing::RangeIsDefinedByCopyFromReg(LiveInterval &li,
unsigned SrcReg = li_->getVNInfoSourceReg(LR->valno);
if (SrcReg == Reg)
return true;
- if (LR->valno->def == ~0U &&
+ // FIXME: Do isPHIDef and isDefAccurate both need to be tested?
+ if ((LR->valno->isPHIDef() || !LR->valno->isDefAccurate()) &&
TargetRegisterInfo::isPhysicalRegister(li.reg) &&
*tri_->getSuperRegisters(li.reg)) {
// It's a sub-register live interval, we may not have precise information.
@@ -2025,12 +2049,20 @@ bool SimpleRegisterCoalescing::SimpleJoin(LiveInterval &LHS, LiveInterval &RHS){
// Okay, the final step is to loop over the RHS live intervals, adding them to
// the LHS.
- LHSValNo->hasPHIKill |= VNI->hasPHIKill;
+ if (VNI->hasPHIKill())
+ LHSValNo->setHasPHIKill(true);
LHS.addKills(LHSValNo, VNI->kills);
LHS.MergeRangesInAsValue(RHS, LHSValNo);
LHS.weight += RHS.weight;
- if (RHS.preference && !LHS.preference)
- LHS.preference = RHS.preference;
+
+ // Update regalloc hint if both are virtual registers.
+ if (TargetRegisterInfo::isVirtualRegister(LHS.reg) &&
+ TargetRegisterInfo::isVirtualRegister(RHS.reg)) {
+ std::pair<unsigned, unsigned> RHSPref = mri_->getRegAllocationHint(RHS.reg);
+ std::pair<unsigned, unsigned> LHSPref = mri_->getRegAllocationHint(LHS.reg);
+ if (RHSPref != LHSPref)
+ mri_->setRegAllocationHint(LHS.reg, RHSPref.first, RHSPref.second);
+ }
// Update the liveintervals of sub-registers.
if (TargetRegisterInfo::isPhysicalRegister(LHS.reg))
@@ -2185,7 +2217,7 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
for (LiveInterval::vni_iterator i = LHS.vni_begin(), e = LHS.vni_end();
i != e; ++i) {
VNInfo *VNI = *i;
- if (VNI->def == ~1U || VNI->copy == 0) // Src not defined by a copy?
+ if (VNI->isUnused() || VNI->copy == 0) // Src not defined by a copy?
continue;
// DstReg is known to be a register in the LHS interval. If the src is
@@ -2202,7 +2234,7 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
for (LiveInterval::vni_iterator i = RHS.vni_begin(), e = RHS.vni_end();
i != e; ++i) {
VNInfo *VNI = *i;
- if (VNI->def == ~1U || VNI->copy == 0) // Src not defined by a copy?
+ if (VNI->isUnused() || VNI->copy == 0) // Src not defined by a copy?
continue;
// DstReg is known to be a register in the RHS interval. If the src is
@@ -2222,7 +2254,7 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
i != e; ++i) {
VNInfo *VNI = *i;
unsigned VN = VNI->id;
- if (LHSValNoAssignments[VN] >= 0 || VNI->def == ~1U)
+ if (LHSValNoAssignments[VN] >= 0 || VNI->isUnused())
continue;
ComputeUltimateVN(VNI, NewVNInfo,
LHSValsDefinedFromRHS, RHSValsDefinedFromLHS,
@@ -2232,7 +2264,7 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
i != e; ++i) {
VNInfo *VNI = *i;
unsigned VN = VNI->id;
- if (RHSValNoAssignments[VN] >= 0 || VNI->def == ~1U)
+ if (RHSValNoAssignments[VN] >= 0 || VNI->isUnused())
continue;
// If this value number isn't a copy from the LHS, it's a new number.
if (RHSValsDefinedFromLHS.find(VNI) == RHSValsDefinedFromLHS.end()) {
@@ -2296,7 +2328,8 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
VNInfo *VNI = I->first;
unsigned LHSValID = LHSValNoAssignments[VNI->id];
LiveInterval::removeKill(NewVNInfo[LHSValID], VNI->def);
- NewVNInfo[LHSValID]->hasPHIKill |= VNI->hasPHIKill;
+ if (VNI->hasPHIKill())
+ NewVNInfo[LHSValID]->setHasPHIKill(true);
RHS.addKills(NewVNInfo[LHSValID], VNI->kills);
}
@@ -2306,7 +2339,8 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
VNInfo *VNI = I->first;
unsigned RHSValID = RHSValNoAssignments[VNI->id];
LiveInterval::removeKill(NewVNInfo[RHSValID], VNI->def);
- NewVNInfo[RHSValID]->hasPHIKill |= VNI->hasPHIKill;
+ if (VNI->hasPHIKill())
+ NewVNInfo[RHSValID]->setHasPHIKill(true);
LHS.addKills(NewVNInfo[RHSValID], VNI->kills);
}
@@ -2315,10 +2349,12 @@ SimpleRegisterCoalescing::JoinIntervals(LiveInterval &LHS, LiveInterval &RHS,
if ((RHS.ranges.size() > LHS.ranges.size() &&
TargetRegisterInfo::isVirtualRegister(LHS.reg)) ||
TargetRegisterInfo::isPhysicalRegister(RHS.reg)) {
- RHS.join(LHS, &RHSValNoAssignments[0], &LHSValNoAssignments[0], NewVNInfo);
+ RHS.join(LHS, &RHSValNoAssignments[0], &LHSValNoAssignments[0], NewVNInfo,
+ mri_);
Swapped = true;
} else {
- LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo);
+ LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo,
+ mri_);
Swapped = false;
}
return true;
@@ -2620,6 +2656,11 @@ SimpleRegisterCoalescing::TurnCopyIntoImpDef(MachineBasicBlock::iterator &I,
return false;
LiveInterval &DstInt = li_->getInterval(DstReg);
const LiveRange *DstLR = DstInt.getLiveRangeContaining(CopyIdx);
+ // If the valno extends beyond this basic block, then it's not safe to delete
+ // the val# or else livein information won't be correct.
+ MachineBasicBlock *EndMBB = li_->getMBBFromIndex(DstLR->end);
+ if (EndMBB != MBB)
+ return false;
DstInt.removeValNo(DstLR->valno);
CopyMI->setDesc(tii_->get(TargetInstrInfo::IMPLICIT_DEF));
for (int i = CopyMI->getNumOperands() - 1, e = 0; i > e; --i)
@@ -2800,7 +2841,8 @@ bool SimpleRegisterCoalescing::runOnMachineFunction(MachineFunction &fn) {
}
// Slightly prefer live interval that has been assigned a preferred reg.
- if (LI.preference)
+ std::pair<unsigned, unsigned> Hint = mri_->getRegAllocationHint(LI.reg);
+ if (Hint.first || Hint.second)
LI.weight *= 1.01F;
// Divide the weight of the interval by its size. This encourages
diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h
index a495bfd644a5..d2c55810f60c 100644
--- a/lib/CodeGen/SimpleRegisterCoalescing.h
+++ b/lib/CodeGen/SimpleRegisterCoalescing.h
@@ -219,10 +219,10 @@ namespace llvm {
bool CanCoalesceWithImpDef(MachineInstr *CopyMI,
LiveInterval &li, LiveInterval &ImpLi) const;
- /// RemoveCopiesFromValNo - The specified value# is defined by an implicit
- /// def and it is being removed. Turn all copies from this value# into
- /// identity copies so they will be removed.
- void RemoveCopiesFromValNo(LiveInterval &li, VNInfo *VNI);
+ /// TurnCopiesFromValNoToImpDefs - The specified value# is defined by an
+ /// implicit_def and it is being removed. Turn all copies from this value#
+ /// into implicit_defs.
+ void TurnCopiesFromValNoToImpDefs(LiveInterval &li, VNInfo *VNI);
/// isWinToJoinVRWithSrcPhysReg - Return true if it's worth while to join a
/// a virtual destination register with physical source register.
diff --git a/lib/CodeGen/Spiller.cpp b/lib/CodeGen/Spiller.cpp
index ce63121251e3..919a0ce160f4 100644
--- a/lib/CodeGen/Spiller.cpp
+++ b/lib/CodeGen/Spiller.cpp
@@ -39,7 +39,8 @@ protected:
VirtRegMap *vrm;
/// Construct a spiller base.
- SpillerBase(MachineFunction *mf, LiveIntervals *lis, LiveStacks *ls, VirtRegMap *vrm) :
+ SpillerBase(MachineFunction *mf, LiveIntervals *lis, LiveStacks *ls,
+ VirtRegMap *vrm) :
mf(mf), lis(lis), ls(ls), vrm(vrm)
{
mfi = mf->getFrameInfo();
@@ -47,16 +48,24 @@ protected:
tii = mf->getTarget().getInstrInfo();
}
- /// Insert a store of the given vreg to the given stack slot immediately
- /// after the given instruction. Returns the base index of the inserted
- /// instruction. The caller is responsible for adding an appropriate
- /// LiveInterval to the LiveIntervals analysis.
- unsigned insertStoreFor(MachineInstr *mi, unsigned ss,
- unsigned newVReg,
- const TargetRegisterClass *trc) {
- MachineBasicBlock::iterator nextInstItr(mi);
- ++nextInstItr;
+ /// Ensures there is space before the given machine instruction, returns the
+ /// instruction's new number.
+ unsigned makeSpaceBefore(MachineInstr *mi) {
+ if (!lis->hasGapBeforeInstr(lis->getInstructionIndex(mi))) {
+ lis->scaleNumbering(2);
+ ls->scaleNumbering(2);
+ }
+
+ unsigned miIdx = lis->getInstructionIndex(mi);
+ assert(lis->hasGapBeforeInstr(miIdx));
+
+ return miIdx;
+ }
+
+ /// Ensure there is space after the given machine instruction, returns the
+ /// instruction's new number.
+ unsigned makeSpaceAfter(MachineInstr *mi) {
if (!lis->hasGapAfterInstr(lis->getInstructionIndex(mi))) {
lis->scaleNumbering(2);
ls->scaleNumbering(2);
@@ -66,7 +75,24 @@ protected:
assert(lis->hasGapAfterInstr(miIdx));
- tii->storeRegToStackSlot(*mi->getParent(), nextInstItr, newVReg,
+ return miIdx;
+ }
+
+
+ /// Insert a store of the given vreg to the given stack slot immediately
+ /// after the given instruction. Returns the base index of the inserted
+ /// instruction. The caller is responsible for adding an appropriate
+ /// LiveInterval to the LiveIntervals analysis.
+ unsigned insertStoreFor(MachineInstr *mi, unsigned ss,
+ unsigned vreg,
+ const TargetRegisterClass *trc) {
+
+ MachineBasicBlock::iterator nextInstItr(mi);
+ ++nextInstItr;
+
+ unsigned miIdx = makeSpaceAfter(mi);
+
+ tii->storeRegToStackSlot(*mi->getParent(), nextInstItr, vreg,
true, ss, trc);
MachineBasicBlock::iterator storeInstItr(mi);
++storeInstItr;
@@ -81,25 +107,35 @@ protected:
return storeInstIdx;
}
+ void insertStoreOnInterval(LiveInterval *li,
+ MachineInstr *mi, unsigned ss,
+ unsigned vreg,
+ const TargetRegisterClass *trc) {
+
+ unsigned storeInstIdx = insertStoreFor(mi, ss, vreg, trc);
+ unsigned start = lis->getDefIndex(lis->getInstructionIndex(mi)),
+ end = lis->getUseIndex(storeInstIdx);
+
+ VNInfo *vni =
+ li->getNextValue(storeInstIdx, 0, true, lis->getVNInfoAllocator());
+ vni->kills.push_back(storeInstIdx);
+ LiveRange lr(start, end, vni);
+
+ li->addRange(lr);
+ }
+
/// Insert a load of the given veg from the given stack slot immediately
/// before the given instruction. Returns the base index of the inserted
/// instruction. The caller is responsible for adding an appropriate
/// LiveInterval to the LiveIntervals analysis.
unsigned insertLoadFor(MachineInstr *mi, unsigned ss,
- unsigned newVReg,
+ unsigned vreg,
const TargetRegisterClass *trc) {
MachineBasicBlock::iterator useInstItr(mi);
-
- if (!lis->hasGapBeforeInstr(lis->getInstructionIndex(mi))) {
- lis->scaleNumbering(2);
- ls->scaleNumbering(2);
- }
-
- unsigned miIdx = lis->getInstructionIndex(mi);
-
- assert(lis->hasGapBeforeInstr(miIdx));
-
- tii->loadRegFromStackSlot(*mi->getParent(), useInstItr, newVReg, ss, trc);
+
+ unsigned miIdx = makeSpaceBefore(mi);
+
+ tii->loadRegFromStackSlot(*mi->getParent(), useInstItr, vreg, ss, trc);
MachineBasicBlock::iterator loadInstItr(mi);
--loadInstItr;
MachineInstr *loadInst = &*loadInstItr;
@@ -113,6 +149,24 @@ protected:
return loadInstIdx;
}
+ void insertLoadOnInterval(LiveInterval *li,
+ MachineInstr *mi, unsigned ss,
+ unsigned vreg,
+ const TargetRegisterClass *trc) {
+
+ unsigned loadInstIdx = insertLoadFor(mi, ss, vreg, trc);
+ unsigned start = lis->getDefIndex(loadInstIdx),
+ end = lis->getUseIndex(lis->getInstructionIndex(mi));
+
+ VNInfo *vni =
+ li->getNextValue(loadInstIdx, 0, true, lis->getVNInfoAllocator());
+ vni->kills.push_back(lis->getInstructionIndex(mi));
+ LiveRange lr(start, end, vni);
+
+ li->addRange(lr);
+ }
+
+
/// Add spill ranges for every use/def of the live interval, inserting loads
/// immediately before each use, and stores after each def. No folding is
@@ -173,35 +227,16 @@ protected:
assert(hasUse || hasDef);
if (hasUse) {
- unsigned loadInstIdx = insertLoadFor(mi, ss, newVReg, trc);
- unsigned start = lis->getDefIndex(loadInstIdx),
- end = lis->getUseIndex(lis->getInstructionIndex(mi));
-
- VNInfo *vni =
- newLI->getNextValue(loadInstIdx, 0, lis->getVNInfoAllocator());
- vni->kills.push_back(lis->getInstructionIndex(mi));
- LiveRange lr(start, end, vni);
-
- newLI->addRange(lr);
+ insertLoadOnInterval(newLI, mi, ss, newVReg, trc);
}
if (hasDef) {
- unsigned storeInstIdx = insertStoreFor(mi, ss, newVReg, trc);
- unsigned start = lis->getDefIndex(lis->getInstructionIndex(mi)),
- end = lis->getUseIndex(storeInstIdx);
-
- VNInfo *vni =
- newLI->getNextValue(storeInstIdx, 0, lis->getVNInfoAllocator());
- vni->kills.push_back(storeInstIdx);
- LiveRange lr(start, end, vni);
-
- newLI->addRange(lr);
+ insertStoreOnInterval(newLI, mi, ss, newVReg, trc);
}
added.push_back(newLI);
}
-
return added;
}
@@ -212,13 +247,44 @@ protected:
/// folding.
class TrivialSpiller : public SpillerBase {
public:
- TrivialSpiller(MachineFunction *mf, LiveIntervals *lis, LiveStacks *ls, VirtRegMap *vrm) :
+
+ TrivialSpiller(MachineFunction *mf, LiveIntervals *lis, LiveStacks *ls,
+ VirtRegMap *vrm) :
SpillerBase(mf, lis, ls, vrm) {}
std::vector<LiveInterval*> spill(LiveInterval *li) {
return trivialSpillEverywhere(li);
}
+ std::vector<LiveInterval*> intraBlockSplit(LiveInterval *li, VNInfo *valno) {
+ std::vector<LiveInterval*> spillIntervals;
+ MachineBasicBlock::iterator storeInsertPoint;
+
+ if (valno->isDefAccurate()) {
+ // If we have an accurate def we can just grab an iterator to the instr
+ // after the def.
+ storeInsertPoint =
+ next(MachineBasicBlock::iterator(lis->getInstructionFromIndex(valno->def)));
+ } else {
+ // If the def info isn't accurate we check if this is a PHI def.
+ // If it is then def holds the index of the defining Basic Block, and we
+ // can use that to get an insertion point.
+ if (valno->isPHIDef()) {
+
+ } else {
+ // We have no usable def info. We can't split this value sensibly.
+ // FIXME: Need sensible feedback for "failure to split", an empty
+ // set of spill intervals could be reasonably returned from a
+ // split where both the store and load are folded.
+ return spillIntervals;
+ }
+ }
+
+
+
+ return spillIntervals;
+ }
+
};
}
diff --git a/lib/CodeGen/Spiller.h b/lib/CodeGen/Spiller.h
index cad054d744c4..9c3900df0b57 100644
--- a/lib/CodeGen/Spiller.h
+++ b/lib/CodeGen/Spiller.h
@@ -13,11 +13,14 @@
#include <vector>
namespace llvm {
+
class LiveInterval;
class LiveIntervals;
class LiveStacks;
class MachineFunction;
+ class MachineInstr;
class VirtRegMap;
+ class VNInfo;
/// Spiller interface.
///
@@ -26,7 +29,15 @@ namespace llvm {
class Spiller {
public:
virtual ~Spiller() = 0;
+
+ /// Spill the given live range. The method used will depend on the Spiller
+ /// implementation selected.
virtual std::vector<LiveInterval*> spill(LiveInterval *li) = 0;
+
+ /// Intra-block split.
+ virtual std::vector<LiveInterval*> intraBlockSplit(LiveInterval *li,
+ VNInfo *valno) = 0;
+
};
/// Create and return a spiller object, as specified on the command line.
diff --git a/lib/CodeGen/StrongPHIElimination.cpp b/lib/CodeGen/StrongPHIElimination.cpp
index a2c12554f377..ca9952863b7c 100644
--- a/lib/CodeGen/StrongPHIElimination.cpp
+++ b/lib/CodeGen/StrongPHIElimination.cpp
@@ -827,7 +827,7 @@ void StrongPHIElimination::InsertCopies(MachineDomTreeNode* MDTN,
// Add a live range for the new vreg
LiveInterval& Int = LI.getInterval(I->getOperand(i).getReg());
VNInfo* FirstVN = *Int.vni_begin();
- FirstVN->hasPHIKill = false;
+ FirstVN->setHasPHIKill(false);
if (I->getOperand(i).isKill())
FirstVN->kills.push_back(
LiveIntervals::getUseIndex(LI.getInstructionIndex(I)));
@@ -886,10 +886,7 @@ bool StrongPHIElimination::mergeLiveIntervals(unsigned primary,
VNInfo* OldVN = R.valno;
VNInfo*& NewVN = VNMap[OldVN];
if (!NewVN) {
- NewVN = LHS.getNextValue(OldVN->def,
- OldVN->copy,
- LI.getVNInfoAllocator());
- NewVN->kills = OldVN->kills;
+ NewVN = LHS.createValueCopy(OldVN, LI.getVNInfoAllocator());
}
LiveRange LR (R.start, R.end, NewVN);
@@ -987,7 +984,7 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) {
LiveInterval& Int = LI.getOrCreateInterval(I->first);
const LiveRange* LR =
Int.getLiveRangeContaining(LI.getMBBEndIdx(SI->second));
- LR->valno->hasPHIKill = true;
+ LR->valno->setHasPHIKill(true);
I->second.erase(SI->first);
}
@@ -1037,7 +1034,7 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) {
// now has an unknown def.
unsigned idx = LI.getDefIndex(LI.getInstructionIndex(PInstr));
const LiveRange* PLR = PI.getLiveRangeContaining(idx);
- PLR->valno->def = ~0U;
+ PLR->valno->setIsPHIDef(true);
LiveRange R (LI.getMBBStartIdx(PInstr->getParent()),
PLR->start, PLR->valno);
PI.addRange(R);
diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp
index 29637b954f0b..4d3417fdff51 100644
--- a/lib/CodeGen/VirtRegMap.cpp
+++ b/lib/CodeGen/VirtRegMap.cpp
@@ -51,6 +51,7 @@ static RegisterPass<VirtRegMap>
X("virtregmap", "Virtual Register Map");
bool VirtRegMap::runOnMachineFunction(MachineFunction &mf) {
+ MRI = &mf.getRegInfo();
TII = mf.getTarget().getInstrInfo();
TRI = mf.getTarget().getRegisterInfo();
MF = &mf;
@@ -98,6 +99,18 @@ void VirtRegMap::grow() {
ImplicitDefed.resize(LastVirtReg-TargetRegisterInfo::FirstVirtualRegister+1);
}
+unsigned VirtRegMap::getRegAllocPref(unsigned virtReg) {
+ std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(virtReg);
+ unsigned physReg = Hint.second;
+ if (physReg &&
+ TargetRegisterInfo::isVirtualRegister(physReg) && hasPhys(physReg))
+ physReg = getPhys(physReg);
+ if (Hint.first == 0)
+ return (physReg && TargetRegisterInfo::isPhysicalRegister(physReg))
+ ? physReg : 0;
+ return TRI->ResolveRegAllocHint(Hint.first, physReg, *MF);
+}
+
int VirtRegMap::assignVirt2StackSlot(unsigned virtReg) {
assert(TargetRegisterInfo::isVirtualRegister(virtReg));
assert(Virt2StackSlotMap[virtReg] == NO_STACK_SLOT &&
@@ -213,8 +226,7 @@ void VirtRegMap::RemoveMachineInstrFromMaps(MachineInstr *MI) {
/// FindUnusedRegisters - Gather a list of allocatable registers that
/// have not been allocated to any virtual register.
-bool VirtRegMap::FindUnusedRegisters(const TargetRegisterInfo *TRI,
- LiveIntervals* LIs) {
+bool VirtRegMap::FindUnusedRegisters(LiveIntervals* LIs) {
unsigned NumRegs = TRI->getNumRegs();
UnusedRegs.reset();
UnusedRegs.resize(NumRegs);
diff --git a/lib/CodeGen/VirtRegMap.h b/lib/CodeGen/VirtRegMap.h
index 507557d24c08..fe767b7671e1 100644
--- a/lib/CodeGen/VirtRegMap.h
+++ b/lib/CodeGen/VirtRegMap.h
@@ -31,6 +31,7 @@ namespace llvm {
class LiveIntervals;
class MachineInstr;
class MachineFunction;
+ class MachineRegisterInfo;
class TargetInstrInfo;
class TargetRegisterInfo;
@@ -47,6 +48,7 @@ namespace llvm {
std::pair<unsigned, ModRef> > MI2VirtMapTy;
private:
+ MachineRegisterInfo *MRI;
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
MachineFunction *MF;
@@ -190,6 +192,9 @@ namespace llvm {
grow();
}
+ /// @brief returns the register allocation preference.
+ unsigned getRegAllocPref(unsigned virtReg);
+
/// @brief records virtReg is a split live interval from SReg.
void setIsSplitFromReg(unsigned virtReg, unsigned SReg) {
Virt2SplitMap[virtReg] = SReg;
@@ -445,8 +450,7 @@ namespace llvm {
/// FindUnusedRegisters - Gather a list of allocatable registers that
/// have not been allocated to any virtual register.
- bool FindUnusedRegisters(const TargetRegisterInfo *TRI,
- LiveIntervals* LIs);
+ bool FindUnusedRegisters(LiveIntervals* LIs);
/// HasUnusedRegisters - Return true if there are any allocatable registers
/// that have not been allocated to any virtual register.
diff --git a/lib/ExecutionEngine/ExecutionEngineBindings.cpp b/lib/ExecutionEngine/ExecutionEngineBindings.cpp
index 83397a586d53..401a22647e1d 100644
--- a/lib/ExecutionEngine/ExecutionEngineBindings.cpp
+++ b/lib/ExecutionEngine/ExecutionEngineBindings.cpp
@@ -118,7 +118,7 @@ int LLVMCreateJITCompiler(LLVMExecutionEngineRef *OutJIT,
char **OutError) {
std::string Error;
if (ExecutionEngine *JIT =
- ExecutionEngine::createJIT(unwrap(MP), &Error, 0,
+ ExecutionEngine::create(unwrap(MP), false, &Error,
(CodeGenOpt::Level)OptLevel)) {
*OutJIT = wrap(JIT);
return 0;
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 7c8ce706b610..e7a76cc3f236 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -19,6 +19,7 @@ add_llvm_library(LLVMSupport
PrettyStackTrace.cpp
SlowOperationInformer.cpp
SmallPtrSet.cpp
+ SourceMgr.cpp
Statistic.cpp
Streams.cpp
StringExtras.cpp
diff --git a/lib/Support/ManagedStatic.cpp b/lib/Support/ManagedStatic.cpp
index 6de65752b3d6..4e655a0f9eec 100644
--- a/lib/Support/ManagedStatic.cpp
+++ b/lib/Support/ManagedStatic.cpp
@@ -14,18 +14,15 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Config/config.h"
#include "llvm/System/Atomic.h"
-#include "llvm/System/Mutex.h"
#include <cassert>
using namespace llvm;
static const ManagedStaticBase *StaticList = 0;
-static sys::Mutex* ManagedStaticMutex = 0;
-
void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
void (*Deleter)(void*)) const {
- if (ManagedStaticMutex) {
- ManagedStaticMutex->acquire();
+ if (llvm_is_multithreaded()) {
+ llvm_acquire_global_lock();
if (Ptr == 0) {
void* tmp = Creator ? Creator() : 0;
@@ -39,7 +36,7 @@ void ManagedStaticBase::RegisterManagedStatic(void *(*Creator)(),
StaticList = this;
}
- ManagedStaticMutex->release();
+ llvm_release_global_lock();
} else {
assert(Ptr == 0 && DeleterFn == 0 && Next == 0 &&
"Partially initialized ManagedStatic!?");
@@ -68,24 +65,11 @@ void ManagedStaticBase::destroy() const {
DeleterFn = 0;
}
-bool llvm::llvm_start_multithreaded() {
-#if LLVM_MULTITHREADED
- assert(ManagedStaticMutex == 0 && "Multithreaded LLVM already initialized!");
- ManagedStaticMutex = new sys::Mutex(true);
- return true;
-#else
- return false;
-#endif
-}
-
/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
void llvm::llvm_shutdown() {
while (StaticList)
StaticList->destroy();
- if (ManagedStaticMutex) {
- delete ManagedStaticMutex;
- ManagedStaticMutex = 0;
- }
+ if (llvm_is_multithreaded()) llvm_stop_multithreaded();
}
diff --git a/utils/TableGen/TGSourceMgr.cpp b/lib/Support/SourceMgr.cpp
index 42bc75246c9f..d789f1010be2 100644
--- a/utils/TableGen/TGSourceMgr.cpp
+++ b/lib/Support/SourceMgr.cpp
@@ -1,4 +1,4 @@
-//===- TGSourceMgr.cpp - Manager for Source Buffers & Diagnostics ---------===//
+//===- SourceMgr.cpp - Manager for Simple Source Buffers & Diagnostics ----===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,25 +7,47 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements the TGSourceMgr class.
+// This file implements the SourceMgr class. This class is used as a simple
+// substrate for diagnostics, #include handling, and other low level things for
+// simple parsers.
//
//===----------------------------------------------------------------------===//
-#include "TGSourceMgr.h"
+#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-TGSourceMgr::~TGSourceMgr() {
+SourceMgr::~SourceMgr() {
while (!Buffers.empty()) {
delete Buffers.back().Buffer;
Buffers.pop_back();
}
}
+/// AddIncludeFile - Search for a file with the specified name in the current
+/// directory or in one of the IncludeDirs. If no file is found, this returns
+/// ~0, otherwise it returns the buffer ID of the stacked file.
+unsigned SourceMgr::AddIncludeFile(const std::string &Filename,
+ SMLoc IncludeLoc) {
+
+ MemoryBuffer *NewBuf = MemoryBuffer::getFile(Filename.c_str());
+
+ // If the file didn't exist directly, see if it's in an include path.
+ for (unsigned i = 0, e = IncludeDirectories.size(); i != e && !NewBuf; ++i) {
+ std::string IncFile = IncludeDirectories[i] + "/" + Filename;
+ NewBuf = MemoryBuffer::getFile(IncFile.c_str());
+ }
+
+ if (NewBuf == 0) return ~0U;
+
+ return AddNewSourceBuffer(NewBuf, IncludeLoc);
+}
+
+
/// FindBufferContainingLoc - Return the ID of the buffer containing the
/// specified location, returning -1 if not found.
-int TGSourceMgr::FindBufferContainingLoc(TGLoc Loc) const {
+int SourceMgr::FindBufferContainingLoc(SMLoc Loc) const {
for (unsigned i = 0, e = Buffers.size(); i != e; ++i)
if (Loc.getPointer() >= Buffers[i].Buffer->getBufferStart() &&
// Use <= here so that a pointer to the null at the end of the buffer
@@ -37,7 +59,7 @@ int TGSourceMgr::FindBufferContainingLoc(TGLoc Loc) const {
/// FindLineNumber - Find the line number for the specified location in the
/// specified file. This is not a fast method.
-unsigned TGSourceMgr::FindLineNumber(TGLoc Loc, int BufferID) const {
+unsigned SourceMgr::FindLineNumber(SMLoc Loc, int BufferID) const {
if (BufferID == -1) BufferID = FindBufferContainingLoc(Loc);
assert(BufferID != -1 && "Invalid Location!");
@@ -49,13 +71,13 @@ unsigned TGSourceMgr::FindLineNumber(TGLoc Loc, int BufferID) const {
const char *Ptr = Buff->getBufferStart();
- for (; TGLoc::getFromPointer(Ptr) != Loc; ++Ptr)
+ for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr)
if (*Ptr == '\n') ++LineNo;
return LineNo;
}
-void TGSourceMgr::PrintIncludeStack(TGLoc IncludeLoc) const {
- if (IncludeLoc == TGLoc()) return; // Top of stack.
+void SourceMgr::PrintIncludeStack(SMLoc IncludeLoc) const {
+ if (IncludeLoc == SMLoc()) return; // Top of stack.
int CurBuf = FindBufferContainingLoc(IncludeLoc);
assert(CurBuf != -1 && "Invalid or unspecified location!");
@@ -68,12 +90,12 @@ void TGSourceMgr::PrintIncludeStack(TGLoc IncludeLoc) const {
}
-void TGSourceMgr::PrintError(TGLoc ErrorLoc, const std::string &Msg) const {
+void SourceMgr::PrintMessage(SMLoc Loc, const std::string &Msg) const {
raw_ostream &OS = errs();
// First thing to do: find the current buffer containing the specified
// location.
- int CurBuf = FindBufferContainingLoc(ErrorLoc);
+ int CurBuf = FindBufferContainingLoc(Loc);
assert(CurBuf != -1 && "Invalid or unspecified location!");
PrintIncludeStack(getBufferInfo(CurBuf).IncludeLoc);
@@ -82,24 +104,24 @@ void TGSourceMgr::PrintError(TGLoc ErrorLoc, const std::string &Msg) const {
OS << "Parsing " << CurMB->getBufferIdentifier() << ":"
- << FindLineNumber(ErrorLoc, CurBuf) << ": ";
+ << FindLineNumber(Loc, CurBuf) << ": ";
OS << Msg << "\n";
// Scan backward to find the start of the line.
- const char *LineStart = ErrorLoc.getPointer();
+ const char *LineStart = Loc.getPointer();
while (LineStart != CurMB->getBufferStart() &&
LineStart[-1] != '\n' && LineStart[-1] != '\r')
--LineStart;
// Get the end of the line.
- const char *LineEnd = ErrorLoc.getPointer();
+ const char *LineEnd = Loc.getPointer();
while (LineEnd != CurMB->getBufferEnd() &&
LineEnd[0] != '\n' && LineEnd[0] != '\r')
++LineEnd;
// Print out the line.
OS << std::string(LineStart, LineEnd) << "\n";
// Print out spaces before the caret.
- for (const char *Pos = LineStart; Pos != ErrorLoc.getPointer(); ++Pos)
+ for (const char *Pos = LineStart; Pos != Loc.getPointer(); ++Pos)
OS << (*Pos == '\t' ? '\t' : ' ');
OS << "^\n";
}
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index e8cf69d81ff1..dd5c3d61c27b 100644
--- a/lib/Support/Triple.cpp
+++ b/lib/Support/Triple.cpp
@@ -43,6 +43,7 @@ const char *Triple::getOSTypeName(OSType Kind) {
switch (Kind) {
case UnknownOS: return "unknown";
+ case AuroraUX: return "auroraux";
case Darwin: return "darwin";
case DragonFly: return "dragonfly";
case FreeBSD: return "freebsd";
@@ -79,7 +80,9 @@ void Triple::Parse() const {
Vendor = UnknownVendor;
std::string OSName = getOSName();
- if (memcmp(&OSName[0], "darwin", 6) == 0)
+ if (memcmp(&OSName[0], "auroraux", 8) == 0)
+ OS = AuroraUX;
+ else if (memcmp(&OSName[0], "darwin", 6) == 0)
OS = Darwin;
else if (memcmp(&OSName[0], "dragonfly", 9) == 0)
OS = DragonFly;
diff --git a/lib/System/Atomic.cpp b/lib/System/Atomic.cpp
index 2827d8896594..416f981df827 100644
--- a/lib/System/Atomic.cpp
+++ b/lib/System/Atomic.cpp
@@ -51,3 +51,31 @@ sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
# error No compare-and-swap implementation for your platform!
#endif
}
+
+sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) {
+#if LLVM_MULTITHREADED==0
+ ++(*ptr);
+ return *ptr;
+#elif defined(__GNUC__)
+ return __sync_add_and_fetch(ptr, 1);
+#elif defined(_MSC_VER)
+ return InterlockedIncrement(ptr);
+#else
+# error No atomic increment implementation for your platform!
+#endif
+}
+
+sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) {
+#if LLVM_MULTITHREADED==0
+ --(*ptr);
+ return *ptr;
+#elif defined(__GNUC__)
+ return __sync_sub_and_fetch(ptr, 1);
+#elif defined(_MSC_VER)
+ return InterlockedDecrement(ptr);
+#else
+# error No atomic decrement implementation for your platform!
+#endif
+}
+
+
diff --git a/lib/System/CMakeLists.txt b/lib/System/CMakeLists.txt
index 5415dd6e300c..a5a56e832dc2 100644
--- a/lib/System/CMakeLists.txt
+++ b/lib/System/CMakeLists.txt
@@ -10,7 +10,9 @@ add_llvm_library(LLVMSystem
Path.cpp
Process.cpp
Program.cpp
+ RWMutex.cpp
Signals.cpp
+ Threading.cpp
TimeValue.cpp
)
diff --git a/lib/System/Mutex.cpp b/lib/System/Mutex.cpp
index d95c25b39eef..a5e9920ae3f0 100644
--- a/lib/System/Mutex.cpp
+++ b/lib/System/Mutex.cpp
@@ -23,11 +23,11 @@
// Define all methods as no-ops if threading is explicitly disabled
namespace llvm {
using namespace sys;
-Mutex::Mutex( bool recursive) { }
-Mutex::~Mutex() { }
-bool Mutex::acquire() { return true; }
-bool Mutex::release() { return true; }
-bool Mutex::tryacquire() { return true; }
+MutexImpl::MutexImpl( bool recursive) { }
+MutexImpl::~MutexImpl() { }
+bool MutexImpl::acquire() { return true; }
+bool MutexImpl::release() { return true; }
+bool MutexImpl::tryacquire() { return true; }
}
#else
@@ -55,7 +55,7 @@ using namespace sys;
static const bool pthread_enabled = true;
// Construct a Mutex using pthread calls
-Mutex::Mutex( bool recursive)
+MutexImpl::MutexImpl( bool recursive)
: data_(0)
{
if (pthread_enabled)
@@ -94,7 +94,7 @@ Mutex::Mutex( bool recursive)
}
// Destruct a Mutex
-Mutex::~Mutex()
+MutexImpl::~MutexImpl()
{
if (pthread_enabled)
{
@@ -106,7 +106,7 @@ Mutex::~Mutex()
}
bool
-Mutex::acquire()
+MutexImpl::acquire()
{
if (pthread_enabled)
{
@@ -120,7 +120,7 @@ Mutex::acquire()
}
bool
-Mutex::release()
+MutexImpl::release()
{
if (pthread_enabled)
{
@@ -134,7 +134,7 @@ Mutex::release()
}
bool
-Mutex::tryacquire()
+MutexImpl::tryacquire()
{
if (pthread_enabled)
{
diff --git a/lib/System/RWMutex.cpp b/lib/System/RWMutex.cpp
new file mode 100644
index 000000000000..15d98cb8f418
--- /dev/null
+++ b/lib/System/RWMutex.cpp
@@ -0,0 +1,175 @@
+//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- 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 llvm::sys::RWMutex class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "llvm/System/RWMutex.h"
+#include <cstring>
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0
+// Define all methods as no-ops if threading is explicitly disabled
+namespace llvm {
+using namespace sys;
+RWMutexImpl::RWMutexImpl() { }
+RWMutexImpl::~RWMutexImpl() { }
+bool RWMutexImpl::reader_acquire() { return true; }
+bool RWMutexImpl::reader_release() { return true; }
+bool RWMutexImpl::writer_acquire() { return true; }
+bool RWMutexImpl::writer_release() { return true; }
+}
+#else
+
+#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
+
+#include <cassert>
+#include <pthread.h>
+#include <stdlib.h>
+
+namespace llvm {
+using namespace sys;
+
+
+// This variable is useful for situations where the pthread library has been
+// compiled with weak linkage for its interface symbols. This allows the
+// threading support to be turned off by simply not linking against -lpthread.
+// In that situation, the value of pthread_mutex_init will be 0 and
+// consequently pthread_enabled will be false. In such situations, all the
+// pthread operations become no-ops and the functions all return false. If
+// pthread_rwlock_init does have an address, then rwlock support is enabled.
+// Note: all LLVM tools will link against -lpthread if its available since it
+// is configured into the LIBS variable.
+// Note: this line of code generates a warning if pthread_rwlock_init is not
+// declared with weak linkage. It's safe to ignore the warning.
+static const bool pthread_enabled = true;
+
+// Construct a RWMutex using pthread calls
+RWMutexImpl::RWMutexImpl()
+ : data_(0)
+{
+ if (pthread_enabled)
+ {
+ // Declare the pthread_rwlock data structures
+ pthread_rwlock_t* rwlock =
+ static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t)));
+
+#ifdef __APPLE__
+ // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
+ bzero(rwlock, sizeof(pthread_rwlock_t));
+#endif
+
+ pthread_rwlockattr_t attr;
+
+ // Initialize the rwlock attributes
+ int errorcode = pthread_rwlockattr_init(&attr);
+ assert(errorcode == 0);
+
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
+ // Make it a process local rwlock
+ errorcode = pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
+#endif
+
+ // Initialize the rwlock
+ errorcode = pthread_rwlock_init(rwlock, &attr);
+ assert(errorcode == 0);
+
+ // Destroy the attributes
+ errorcode = pthread_rwlockattr_destroy(&attr);
+ assert(errorcode == 0);
+
+ // Assign the data member
+ data_ = rwlock;
+ }
+}
+
+// Destruct a RWMutex
+RWMutexImpl::~RWMutexImpl()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+ pthread_rwlock_destroy(rwlock);
+ free(rwlock);
+ }
+}
+
+bool
+RWMutexImpl::reader_acquire()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+
+ int errorcode = pthread_rwlock_rdlock(rwlock);
+ return errorcode == 0;
+ }
+ return false;
+}
+
+bool
+RWMutexImpl::reader_release()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+
+ int errorcode = pthread_rwlock_unlock(rwlock);
+ return errorcode == 0;
+ }
+ return false;
+}
+
+bool
+RWMutexImpl::writer_acquire()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+
+ int errorcode = pthread_rwlock_wrlock(rwlock);
+ return errorcode == 0;
+ }
+ return false;
+}
+
+bool
+RWMutexImpl::writer_release()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+
+ int errorcode = pthread_rwlock_unlock(rwlock);
+ return errorcode == 0;
+ }
+ return false;
+}
+
+}
+
+#elif defined(LLVM_ON_UNIX)
+#include "Unix/RWMutex.inc"
+#elif defined( LLVM_ON_WIN32)
+#include "Win32/RWMutex.inc"
+#else
+#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp
+#endif
+#endif
diff --git a/lib/System/Threading.cpp b/lib/System/Threading.cpp
new file mode 100644
index 000000000000..a2d7f82715d9
--- /dev/null
+++ b/lib/System/Threading.cpp
@@ -0,0 +1,63 @@
+//===-- llvm/System/Threading.cpp- Control multithreading mode --*- 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 llvm_start_multithreaded() and friends.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/System/Threading.h"
+#include "llvm/System/Atomic.h"
+#include "llvm/System/Mutex.h"
+#include <cassert>
+
+using namespace llvm;
+
+static bool multithreaded_mode = false;
+
+static sys::Mutex* global_lock = 0;
+
+bool llvm::llvm_start_multithreaded() {
+#ifdef LLVM_MULTITHREADED
+ assert(!multithreaded_mode && "Already multithreaded!");
+ multithreaded_mode = true;
+ global_lock = new sys::Mutex(true);
+
+ // We fence here to ensure that all initialization is complete BEFORE we
+ // return from llvm_start_multithreaded().
+ sys::MemoryFence();
+ return true;
+#else
+ return false;
+#endif
+}
+
+void llvm::llvm_stop_multithreaded() {
+#ifdef LLVM_MULTITHREADED
+ assert(multithreaded_mode && "Not currently multithreaded!");
+
+ // We fence here to insure that all threaded operations are complete BEFORE we
+ // return from llvm_stop_multithreaded().
+ sys::MemoryFence();
+
+ multithreaded_mode = false;
+ delete global_lock;
+#endif
+}
+
+bool llvm::llvm_is_multithreaded() {
+ return multithreaded_mode;
+}
+
+void llvm::llvm_acquire_global_lock() {
+ if (multithreaded_mode) global_lock->acquire();
+}
+
+void llvm::llvm_release_global_lock() {
+ if (multithreaded_mode) global_lock->release();
+}
diff --git a/lib/System/Unix/Mutex.inc b/lib/System/Unix/Mutex.inc
index 4a015a676fc7..10e7ecb75a5f 100644
--- a/lib/System/Unix/Mutex.inc
+++ b/lib/System/Unix/Mutex.inc
@@ -20,28 +20,28 @@ namespace llvm
{
using namespace sys;
-Mutex::Mutex( bool recursive)
+MutexImpl::MutexImpl( bool recursive)
{
}
-Mutex::~Mutex()
+MutexImpl::~MutexImpl()
{
}
bool
-Mutex::acquire()
+MutexImpl::MutexImpl()
{
return true;
}
bool
-Mutex::release()
+MutexImpl::release()
{
return true;
}
bool
-Mutex::tryacquire( void )
+MutexImpl::tryacquire( void )
{
return true;
}
diff --git a/lib/System/Unix/Path.inc b/lib/System/Unix/Path.inc
index d5edee1b03b3..1f73571cf140 100644
--- a/lib/System/Unix/Path.inc
+++ b/lib/System/Unix/Path.inc
@@ -104,6 +104,14 @@ Path::isValid() const {
}
bool
+Path::isAbsolute(const char *NameStart, unsigned NameLen) {
+ assert(NameStart);
+ if (NameLen == 0)
+ return false;
+ return NameStart[0] == '/';
+}
+
+bool
Path::isAbsolute() const {
if (path.empty())
return false;
diff --git a/lib/System/Unix/RWMutex.inc b/lib/System/Unix/RWMutex.inc
new file mode 100644
index 000000000000..e83d41ef4cfe
--- /dev/null
+++ b/lib/System/Unix/RWMutex.inc
@@ -0,0 +1,43 @@
+//= llvm/System/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =//
+//
+// 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 Unix specific (non-pthread) RWMutex class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+using namespace sys;
+
+RWMutexImpl::RWMutexImpl() { }
+
+RWMutexImpl::~RWMutexImpl() { }
+
+bool RWMutexImpl::reader_acquire() {
+ return true;
+}
+
+bool RWMutexImpl::reader_release() {
+ return true;
+}
+
+bool RWMutexImpl::writer_acquire() {
+ return true;
+}
+
+bool RWMutexImpl::writer_release() {
+ return true;
+}
+
+}
diff --git a/lib/System/Unix/Unix.h b/lib/System/Unix/Unix.h
index 452226f4f79a..c2c06dd114e5 100644
--- a/lib/System/Unix/Unix.h
+++ b/lib/System/Unix/Unix.h
@@ -79,12 +79,19 @@ static inline bool MakeErrMsg(
return true;
char buffer[MAXPATHLEN];
buffer[0] = 0;
+ char* str = buffer;
if (errnum == -1)
errnum = errno;
#ifdef HAVE_STRERROR_R
// strerror_r is thread-safe.
if (errnum)
+# if defined(__GLIBC__) && defined(_GNU_SOURCE)
+ // glibc defines its own incompatible version of strerror_r
+ // which may not use the buffer supplied.
+ str = strerror_r(errnum,buffer,MAXPATHLEN-1);
+# else
strerror_r(errnum,buffer,MAXPATHLEN-1);
+# endif
#elif HAVE_STRERROR
// Copy the thread un-safe result of strerror into
// the buffer as fast as possible to minimize impact
@@ -97,7 +104,7 @@ static inline bool MakeErrMsg(
// but, oh well, just use a generic message
sprintf(buffer, "Error #%d", errnum);
#endif
- *ErrMsg = prefix + ": " + buffer;
+ *ErrMsg = prefix + ": " + str;
return true;
}
diff --git a/lib/System/Win32/Mutex.inc b/lib/System/Win32/Mutex.inc
index 7c1723be73fc..75f01fefacbb 100644
--- a/lib/System/Win32/Mutex.inc
+++ b/lib/System/Win32/Mutex.inc
@@ -22,13 +22,13 @@
namespace llvm {
using namespace sys;
-Mutex::Mutex(bool /*recursive*/)
+MutexImpl::MutexImpl(bool /*recursive*/)
{
data_ = new CRITICAL_SECTION;
InitializeCriticalSection((LPCRITICAL_SECTION)data_);
}
-Mutex::~Mutex()
+MutexImpl::~MutexImpl()
{
DeleteCriticalSection((LPCRITICAL_SECTION)data_);
delete (LPCRITICAL_SECTION)data_;
@@ -36,21 +36,21 @@ Mutex::~Mutex()
}
bool
-Mutex::acquire()
+MutexImpl::acquire()
{
EnterCriticalSection((LPCRITICAL_SECTION)data_);
return true;
}
bool
-Mutex::release()
+MutexImpl::release()
{
LeaveCriticalSection((LPCRITICAL_SECTION)data_);
return true;
}
bool
-Mutex::tryacquire()
+MutexImpl::tryacquire()
{
return TryEnterCriticalSection((LPCRITICAL_SECTION)data_);
}
diff --git a/lib/System/Win32/Path.inc b/lib/System/Win32/Path.inc
index fbf8f6688a57..683c94bba44e 100644
--- a/lib/System/Win32/Path.inc
+++ b/lib/System/Win32/Path.inc
@@ -125,6 +125,20 @@ Path::isValid() const {
return true;
}
+bool
+Path::isAbsolute(const char *NameStart, unsigned NameLen) {
+ assert(NameStart);
+ switch (NameLen) {
+ case 0:
+ return false;
+ case 1:
+ case 2:
+ return NameStart[0] == '/';
+ default:
+ return NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/');
+ }
+}
+
bool
Path::isAbsolute() const {
switch (path.length()) {
@@ -234,7 +248,9 @@ Path::GetCurrentDirectory() {
/// GetMainExecutable - Return the path to the main executable, given the
/// value of argv[0] from program startup.
Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
- return Path();
+ char pathname[MAX_PATH];
+ DWORD ret = ::GetModuleFileNameA(NULL, pathname, MAX_PATH);
+ return ret != MAX_PATH ? Path(pathname) : Path();
}
diff --git a/lib/System/Win32/RWMutex.inc b/lib/System/Win32/RWMutex.inc
new file mode 100644
index 000000000000..e2692269e3a0
--- /dev/null
+++ b/lib/System/Win32/RWMutex.inc
@@ -0,0 +1,58 @@
+//= llvm/System/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =//
+//
+// 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 Win32 specific (non-pthread) RWMutex class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#include "Win32.h"
+
+// FIXME: Windows does not have reader-writer locks pre-Vista. If you want
+// real reader-writer locks, you a pthreads implementation for Windows.
+
+namespace llvm {
+using namespace sys;
+
+RWMutexImpl::RWMutexImpl() {
+ data_ = calloc(1, sizeof(CRITICAL_SECTION));
+ InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+}
+
+RWMutexImpl::~RWMutexImpl() {
+ DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ free(data_);
+}
+
+bool RWMutexImpl::reader_acquire() {
+ EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ return true;
+}
+
+bool RWMutexImpl::reader_release() {
+ LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ return true;
+}
+
+bool RWMutexImpl::writer_acquire() {
+ EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ return true;
+}
+
+bool RWMutexImpl::writer_release() {
+ LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ return true;
+}
+
+
+}
diff --git a/lib/Target/ARM/ARM.td b/lib/Target/ARM/ARM.td
index 594811d6357f..9001e5033c7d 100644
--- a/lib/Target/ARM/ARM.td
+++ b/lib/Target/ARM/ARM.td
@@ -45,62 +45,72 @@ def FeatureThumb2 : SubtargetFeature<"thumb2", "ThumbMode", "Thumb2",
// ARM Processors supported.
//
-class Proc<string Name, list<SubtargetFeature> Features>
- : Processor<Name, NoItineraries, Features>;
+include "ARMSchedule.td"
+
+class ProcNoItin<string Name, list<SubtargetFeature> Features>
+ : Processor<Name, GenericItineraries, Features>;
// V4 Processors.
-def : Proc<"generic", []>;
-def : Proc<"arm8", []>;
-def : Proc<"arm810", []>;
-def : Proc<"strongarm", []>;
-def : Proc<"strongarm110", []>;
-def : Proc<"strongarm1100", []>;
-def : Proc<"strongarm1110", []>;
+def : ProcNoItin<"generic", []>;
+def : ProcNoItin<"arm8", []>;
+def : ProcNoItin<"arm810", []>;
+def : ProcNoItin<"strongarm", []>;
+def : ProcNoItin<"strongarm110", []>;
+def : ProcNoItin<"strongarm1100", []>;
+def : ProcNoItin<"strongarm1110", []>;
// V4T Processors.
-def : Proc<"arm7tdmi", [ArchV4T]>;
-def : Proc<"arm7tdmi-s", [ArchV4T]>;
-def : Proc<"arm710t", [ArchV4T]>;
-def : Proc<"arm720t", [ArchV4T]>;
-def : Proc<"arm9", [ArchV4T]>;
-def : Proc<"arm9tdmi", [ArchV4T]>;
-def : Proc<"arm920", [ArchV4T]>;
-def : Proc<"arm920t", [ArchV4T]>;
-def : Proc<"arm922t", [ArchV4T]>;
-def : Proc<"arm940t", [ArchV4T]>;
-def : Proc<"ep9312", [ArchV4T]>;
+def : ProcNoItin<"arm7tdmi", [ArchV4T]>;
+def : ProcNoItin<"arm7tdmi-s", [ArchV4T]>;
+def : ProcNoItin<"arm710t", [ArchV4T]>;
+def : ProcNoItin<"arm720t", [ArchV4T]>;
+def : ProcNoItin<"arm9", [ArchV4T]>;
+def : ProcNoItin<"arm9tdmi", [ArchV4T]>;
+def : ProcNoItin<"arm920", [ArchV4T]>;
+def : ProcNoItin<"arm920t", [ArchV4T]>;
+def : ProcNoItin<"arm922t", [ArchV4T]>;
+def : ProcNoItin<"arm940t", [ArchV4T]>;
+def : ProcNoItin<"ep9312", [ArchV4T]>;
// V5T Processors.
-def : Proc<"arm10tdmi", [ArchV5T]>;
-def : Proc<"arm1020t", [ArchV5T]>;
+def : ProcNoItin<"arm10tdmi", [ArchV5T]>;
+def : ProcNoItin<"arm1020t", [ArchV5T]>;
// V5TE Processors.
-def : Proc<"arm9e", [ArchV5TE]>;
-def : Proc<"arm926ej-s", [ArchV5TE]>;
-def : Proc<"arm946e-s", [ArchV5TE]>;
-def : Proc<"arm966e-s", [ArchV5TE]>;
-def : Proc<"arm968e-s", [ArchV5TE]>;
-def : Proc<"arm10e", [ArchV5TE]>;
-def : Proc<"arm1020e", [ArchV5TE]>;
-def : Proc<"arm1022e", [ArchV5TE]>;
-def : Proc<"xscale", [ArchV5TE]>;
-def : Proc<"iwmmxt", [ArchV5TE]>;
+def : ProcNoItin<"arm9e", [ArchV5TE]>;
+def : ProcNoItin<"arm926ej-s", [ArchV5TE]>;
+def : ProcNoItin<"arm946e-s", [ArchV5TE]>;
+def : ProcNoItin<"arm966e-s", [ArchV5TE]>;
+def : ProcNoItin<"arm968e-s", [ArchV5TE]>;
+def : ProcNoItin<"arm10e", [ArchV5TE]>;
+def : ProcNoItin<"arm1020e", [ArchV5TE]>;
+def : ProcNoItin<"arm1022e", [ArchV5TE]>;
+def : ProcNoItin<"xscale", [ArchV5TE]>;
+def : ProcNoItin<"iwmmxt", [ArchV5TE]>;
// V6 Processors.
-def : Proc<"arm1136j-s", [ArchV6]>;
-def : Proc<"arm1136jf-s", [ArchV6, FeatureVFP2]>;
-def : Proc<"arm1176jz-s", [ArchV6]>;
-def : Proc<"arm1176jzf-s", [ArchV6, FeatureVFP2]>;
-def : Proc<"mpcorenovfp", [ArchV6]>;
-def : Proc<"mpcore", [ArchV6, FeatureVFP2]>;
+def : Processor<"arm1136j-s", V6Itineraries,
+ [ArchV6]>;
+def : Processor<"arm1136jf-s", V6Itineraries,
+ [ArchV6, FeatureVFP2]>;
+def : Processor<"arm1176jz-s", V6Itineraries,
+ [ArchV6]>;
+def : Processor<"arm1176jzf-s", V6Itineraries,
+ [ArchV6, FeatureVFP2]>;
+def : Processor<"mpcorenovfp", V6Itineraries,
+ [ArchV6]>;
+def : Processor<"mpcore", V6Itineraries,
+ [ArchV6, FeatureVFP2]>;
// V6T2 Processors.
-def : Proc<"arm1156t2-s", [ArchV6T2, FeatureThumb2]>;
-def : Proc<"arm1156t2f-s", [ArchV6T2, FeatureThumb2, FeatureVFP2]>;
+def : Processor<"arm1156t2-s", V6Itineraries,
+ [ArchV6T2, FeatureThumb2]>;
+def : Processor<"arm1156t2f-s", V6Itineraries,
+ [ArchV6T2, FeatureThumb2, FeatureVFP2]>;
// V7 Processors.
-def : Proc<"cortex-a8", [ArchV7A, FeatureThumb2, FeatureNEON]>;
-def : Proc<"cortex-a9", [ArchV7A, FeatureThumb2, FeatureNEON]>;
+def : ProcNoItin<"cortex-a8", [ArchV7A, FeatureThumb2, FeatureNEON]>;
+def : ProcNoItin<"cortex-a9", [ArchV7A, FeatureThumb2, FeatureNEON]>;
//===----------------------------------------------------------------------===//
// Register File Description
diff --git a/lib/Target/ARM/ARMCallingConv.td b/lib/Target/ARM/ARMCallingConv.td
index f126760cd5e9..47151e667c40 100644
--- a/lib/Target/ARM/ARMCallingConv.td
+++ b/lib/Target/ARM/ARMCallingConv.td
@@ -17,11 +17,6 @@ class CCIfSubtarget<string F, CCAction A>:
class CCIfAlign<string Align, CCAction A>:
CCIf<!strconcat("ArgFlags.getOrigAlign() == ", Align), A>;
-/// CCIfFloatABI - Match of the float ABI and the arg. ABIType may be "Hard" or
-/// "Soft".
-class CCIfFloatABI<string ABIType, CCAction A>:
- CCIf<!strconcat("llvm::FloatABIType == llvm::FloatABI::", ABIType), A>;
-
//===----------------------------------------------------------------------===//
// ARM APCS Calling Convention
//===----------------------------------------------------------------------===//
@@ -105,25 +100,3 @@ def RetCC_ARM_AAPCS_VFP : CallingConv<[
S9, S10, S11, S12, S13, S14, S15]>>,
CCDelegateTo<RetCC_ARM_AAPCS_Common>
]>;
-
-//===----------------------------------------------------------------------===//
-// ARM Calling Convention Dispatch
-//===----------------------------------------------------------------------===//
-
-def CC_ARM : CallingConv<[
- CCIfSubtarget<"isAAPCS_ABI()",
- CCIfSubtarget<"hasVFP2()",
- CCIfFloatABI<"Hard",
- CCDelegateTo<CC_ARM_AAPCS_VFP>>>>,
- CCIfSubtarget<"isAAPCS_ABI()", CCDelegateTo<CC_ARM_AAPCS>>,
- CCDelegateTo<CC_ARM_APCS>
-]>;
-
-def RetCC_ARM : CallingConv<[
- CCIfSubtarget<"isAAPCS_ABI()",
- CCIfSubtarget<"hasVFP2()",
- CCIfFloatABI<"Hard",
- CCDelegateTo<RetCC_ARM_AAPCS_VFP>>>>,
- CCIfSubtarget<"isAAPCS_ABI()", CCDelegateTo<RetCC_ARM_AAPCS>>,
- CCDelegateTo<RetCC_ARM_APCS>
-]>;
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index 44fac12019b3..f6629fe3c875 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -900,6 +900,10 @@ void Emitter<CodeEmitter>::emitMiscLoadStoreInstruction(const MachineInstr &MI,
// Set first operand
Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;
+ // Skip LDRD and STRD's second operand.
+ if (TID.Opcode == ARM::LDRD || TID.Opcode == ARM::STRD)
+ ++OpIdx;
+
// Set second operand
if (ImplicitRn)
// Special handling for implicit use (e.g. PC).
diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp
index ca3a9cb40329..1ed9e8080a20 100644
--- a/lib/Target/ARM/ARMISelDAGToDAG.cpp
+++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp
@@ -52,8 +52,13 @@ public:
virtual const char *getPassName() const {
return "ARM Instruction Selection";
- }
-
+ }
+
+ /// getI32Imm - Return a target constant with the specified value, of type i32.
+ inline SDValue getI32Imm(unsigned Imm) {
+ return CurDAG->getTargetConstant(Imm, MVT::i32);
+ }
+
SDNode *Select(SDValue Op);
virtual void InstructionSelect();
bool SelectAddrMode2(SDValue Op, SDValue N, SDValue &Base,
@@ -84,6 +89,9 @@ public:
bool SelectThumbAddrModeSP(SDValue Op, SDValue N, SDValue &Base,
SDValue &OffImm);
+ bool SelectShifterOperand(SDValue Op, SDValue N,
+ SDValue &BaseReg, SDValue &Opc);
+
bool SelectShifterOperandReg(SDValue Op, SDValue N, SDValue &A,
SDValue &B, SDValue &C);
@@ -509,8 +517,30 @@ bool ARMDAGToDAGISel::SelectThumbAddrModeSP(SDValue Op, SDValue N,
return false;
}
+bool ARMDAGToDAGISel::SelectShifterOperand(SDValue Op,
+ SDValue N,
+ SDValue &BaseReg,
+ SDValue &Opc) {
+ ARM_AM::ShiftOpc ShOpcVal = ARM_AM::getShiftOpcForNode(N);
+
+ // Don't match base register only case. That is matched to a separate
+ // lower complexity pattern with explicit register operand.
+ if (ShOpcVal == ARM_AM::no_shift) return false;
+
+ BaseReg = N.getOperand(0);
+ unsigned ShImmVal = 0;
+ if (ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(N.getOperand(1)))
+ ShImmVal = RHS->getZExtValue() & 31;
+ else
+ return false;
+
+ Opc = getI32Imm(ARM_AM::getSORegOpc(ShOpcVal, ShImmVal));
+
+ return true;
+}
+
bool ARMDAGToDAGISel::SelectShifterOperandReg(SDValue Op,
- SDValue N,
+ SDValue N,
SDValue &BaseReg,
SDValue &ShReg,
SDValue &Opc) {
@@ -549,6 +579,10 @@ SDNode *ARMDAGToDAGISel::Select(SDValue Op) {
switch (N->getOpcode()) {
default: break;
case ISD::Constant: {
+ // ARMv6T2 and later should materialize imms via MOV / MOVT pair.
+ if (Subtarget->hasV6T2Ops() || Subtarget->hasThumb2())
+ break;
+
unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
bool UseCP = true;
if (Subtarget->isThumb())
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index ec8bd1f8b31a..2443625d4bdb 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -292,6 +292,25 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
setIfCvtBlockSizeLimit(Subtarget->isThumb() ? 0 : 10);
setIfCvtDupBlockSizeLimit(Subtarget->isThumb() ? 0 : 2);
+ if (!Subtarget->isThumb()) {
+ // Use branch latency information to determine if-conversion limits.
+ // FIXME: If-converter should use instruction latency of the branch being
+ // eliminated to compute the threshold. For ARMv6, the branch "latency"
+ // varies depending on whether it's dynamically or statically predicted
+ // and on whether the destination is in the prefetch buffer.
+ const TargetInstrInfo *TII = getTargetMachine().getInstrInfo();
+ const InstrItineraryData &InstrItins = Subtarget->getInstrItineraryData();
+ unsigned Latency= InstrItins.getLatency(TII->get(ARM::Bcc).getSchedClass());
+ if (Latency > 1) {
+ setIfCvtBlockSizeLimit(Latency-1);
+ if (Latency > 2)
+ setIfCvtDupBlockSizeLimit(Latency-2);
+ } else {
+ setIfCvtBlockSizeLimit(10);
+ setIfCvtDupBlockSizeLimit(2);
+ }
+ }
+
maxStoresPerMemcpy = 1; //// temporary - rewrite interface to use type
// Do not enable CodePlacementOpt for now: it currently runs after the
// ARMConstantIslandPass and messes up branch relaxation and placement
@@ -415,7 +434,7 @@ static bool CC_ARM_APCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
ARM::NoRegister };
unsigned Reg = State.AllocateReg(HiRegList, LoRegList, 4);
- if (Reg == 0)
+ if (Reg == 0)
return false; // we didn't handle it
unsigned i;
@@ -487,6 +506,33 @@ static bool RetCC_ARM_AAPCS_Custom_f64(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
State);
}
+/// CCAssignFnForNode - Selects the correct CCAssignFn for a the
+/// given CallingConvention value.
+CCAssignFn *ARMTargetLowering::CCAssignFnForNode(unsigned CC,
+ bool Return) const {
+ switch (CC) {
+ default:
+ assert(0 && "Unsupported calling convention");
+ case CallingConv::C:
+ case CallingConv::Fast:
+ // Use target triple & subtarget features to do actual dispatch.
+ if (Subtarget->isAAPCS_ABI()) {
+ if (Subtarget->hasVFP2() &&
+ FloatABIType == FloatABI::Hard)
+ return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
+ else
+ return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
+ } else
+ return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
+ case CallingConv::ARM_AAPCS_VFP:
+ return (Return ? RetCC_ARM_AAPCS_VFP: CC_ARM_AAPCS_VFP);
+ case CallingConv::ARM_AAPCS:
+ return (Return ? RetCC_ARM_AAPCS: CC_ARM_AAPCS);
+ case CallingConv::ARM_APCS:
+ return (Return ? RetCC_ARM_APCS: CC_ARM_APCS);
+ }
+}
+
/// LowerCallResult - Lower the result values of an ISD::CALL into the
/// appropriate copies out of appropriate physical registers. This assumes that
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
@@ -501,7 +547,8 @@ LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
SmallVector<CCValAssign, 16> RVLocs;
bool isVarArg = TheCall->isVarArg();
CCState CCInfo(CallingConv, isVarArg, getTargetMachine(), RVLocs);
- CCInfo.AnalyzeCallResult(TheCall, RetCC_ARM);
+ CCInfo.AnalyzeCallResult(TheCall,
+ CCAssignFnForNode(CallingConv, /* Return*/ true));
SmallVector<SDValue, 8> ResultVals;
@@ -586,8 +633,6 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
MVT RetVT = TheCall->getRetValType(0);
SDValue Chain = TheCall->getChain();
unsigned CC = TheCall->getCallingConv();
- assert((CC == CallingConv::C ||
- CC == CallingConv::Fast) && "unknown calling convention");
bool isVarArg = TheCall->isVarArg();
SDValue Callee = TheCall->getCallee();
DebugLoc dl = TheCall->getDebugLoc();
@@ -595,7 +640,7 @@ SDValue ARMTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) {
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- CCInfo.AnalyzeCallOperands(TheCall, CC_ARM);
+ CCInfo.AnalyzeCallOperands(TheCall, CCAssignFnForNode(CC, /* Return*/ false));
// Get a count of how many bytes are to be pushed on the stack.
unsigned NumBytes = CCInfo.getNextStackOffset();
@@ -788,7 +833,7 @@ SDValue ARMTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) {
CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs);
// Analyze return values of ISD::RET.
- CCInfo.AnalyzeReturn(Op.getNode(), RetCC_ARM);
+ CCInfo.AnalyzeReturn(Op.getNode(), CCAssignFnForNode(CC, /* Return */ true));
// If this is the first return lowered for this function, add
// the regs to the liveout set for the function.
@@ -1085,7 +1130,8 @@ ARMTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs);
- CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_ARM);
+ CCInfo.AnalyzeFormalArguments(Op.getNode(),
+ CCAssignFnForNode(CC, /* Return*/ false));
SmallVector<SDValue, 16> ArgValues;
@@ -1456,7 +1502,7 @@ SDValue ARMTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
MVT VT = Op.getValueType();
DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful
unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
- unsigned FrameReg = (Subtarget->isThumb() || Subtarget->useThumbBacktraces())
+ unsigned FrameReg = (Subtarget->isThumb() || Subtarget->isTargetDarwin())
? ARM::R7 : ARM::R11;
SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
while (Depth--)
diff --git a/lib/Target/ARM/ARMISelLowering.h b/lib/Target/ARM/ARMISelLowering.h
index 2dab2dbba663..8f53e396eaaf 100644
--- a/lib/Target/ARM/ARMISelLowering.h
+++ b/lib/Target/ARM/ARMISelLowering.h
@@ -151,6 +151,7 @@ namespace llvm {
///
unsigned ARMPCLabelIndex;
+ CCAssignFn *CCAssignFnForNode(unsigned CC, bool Return) const;
SDValue LowerMemOpCallTo(CallSDNode *TheCall, SelectionDAG &DAG,
const SDValue &StackPtr, const CCValAssign &VA,
SDValue Chain, SDValue Arg, ISD::ArgFlagsTy Flags);
diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp
index 4b0dbb5dacdb..d19fb8eea87f 100644
--- a/lib/Target/ARM/ARMInstrInfo.cpp
+++ b/lib/Target/ARM/ARMInstrInfo.cpp
@@ -697,7 +697,6 @@ restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
bool isVarArg = AFI->getVarArgsRegSaveSize() > 0;
MachineInstr *PopMI = MF.CreateMachineInstr(get(ARM::tPOP),MI->getDebugLoc());
- MBB.insert(MI, PopMI);
for (unsigned i = CSI.size(); i != 0; --i) {
unsigned Reg = CSI[i-1].getReg();
if (Reg == ARM::LR) {
@@ -706,10 +705,15 @@ restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
continue;
Reg = ARM::PC;
PopMI->setDesc(get(ARM::tPOP_RET));
- MBB.erase(MI);
+ MI = MBB.erase(MI);
}
PopMI->addOperand(MachineOperand::CreateReg(Reg, true));
}
+
+ // It's illegal to emit pop instruction without operands.
+ if (PopMI->getNumOperands() > 0)
+ MBB.insert(MI, PopMI);
+
return true;
}
diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td
index cc9f1a5759d0..4707e3b7a97f 100644
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -90,12 +90,12 @@ def ARMeh_sjlj_setjmp: SDNode<"ARMISD::EH_SJLJ_SETJMP", SDT_ARMEH_SJLJ_Setjmp>;
//===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions.
//
-def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
-def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">;
-def HasV6 : Predicate<"Subtarget->hasV6Ops()">;
-def IsThumb : Predicate<"Subtarget->isThumb()">;
-def IsThumb2 : Predicate<"Subtarget->isThumb2()">;
-def IsARM : Predicate<"!Subtarget->isThumb()">;
+def HasV5T : Predicate<"Subtarget->hasV5TOps()">;
+def HasV5TE : Predicate<"Subtarget->hasV5TEOps()">;
+def HasV6 : Predicate<"Subtarget->hasV6Ops()">;
+def IsThumb : Predicate<"Subtarget->isThumb()">;
+def HasThumb2 : Predicate<"Subtarget->hasThumb2()">;
+def IsARM : Predicate<"!Subtarget->isThumb()">;
//===----------------------------------------------------------------------===//
// ARM Flag Definitions.
@@ -539,7 +539,7 @@ let isReturn = 1, isTerminator = 1 in
LdStMulFrm, "ldm${p}${addr:submode} $addr, $dst1",
[]>;
-let isCall = 1,
+let isCall = 1, Itinerary = IIC_Br,
Defs = [R0, R1, R2, R3, R12, LR,
D0, D1, D2, D3, D4, D5, D6, D7, CPSR] in {
def BL : ABXI<0b1011, (outs), (ins i32imm:$func, variable_ops),
@@ -567,7 +567,7 @@ let isCall = 1,
}
}
-let isBranch = 1, isTerminator = 1 in {
+let isBranch = 1, isTerminator = 1, Itinerary = IIC_Br in {
// B is "predicable" since it can be xformed into a Bcc.
let isBarrier = 1 in {
let isPredicable = 1 in
@@ -647,9 +647,8 @@ def LDRSB : AI3ldsb<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
let mayLoad = 1 in {
// Load doubleword
-def LDRD : AI3ldd<(outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
- "ldr", "d $dst, $addr",
- []>, Requires<[IsARM, HasV5T]>;
+def LDRD : AI3ldd<(outs GPR:$dst1, GPR:$dst2), (ins addrmode3:$addr), LdMiscFrm,
+ "ldr", "d $dst1, $addr", []>, Requires<[IsARM, HasV5T]>;
// Indexed loads
def LDR_PRE : AI2ldwpr<(outs GPR:$dst, GPR:$base_wb),
@@ -709,9 +708,8 @@ def STRB : AI2stb<(outs), (ins GPR:$src, addrmode2:$addr), StFrm,
// Store doubleword
let mayStore = 1 in
-def STRD : AI3std<(outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm,
- "str", "d $src, $addr",
- []>, Requires<[IsARM, HasV5T]>;
+def STRD : AI3std<(outs), (ins GPR:$src1, GPR:$src2, addrmode3:$addr),StMiscFrm,
+ "str", "d $src1, $addr", []>, Requires<[IsARM, HasV5T]>;
// Indexed stores
def STR_PRE : AI2stwpr<(outs GPR:$base_wb),
@@ -1387,6 +1385,12 @@ def : ARMV5TEPat<(add GPR:$acc,
include "ARMInstrThumb.td"
//===----------------------------------------------------------------------===//
+// Thumb2 Support
+//
+
+include "ARMInstrThumb2.td"
+
+//===----------------------------------------------------------------------===//
// Floating Point Support
//
diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td
index 54232f6dfe6a..9297f08d800b 100644
--- a/lib/Target/ARM/ARMInstrThumb.td
+++ b/lib/Target/ARM/ARMInstrThumb.td
@@ -277,6 +277,7 @@ def tPUSH : TI<(outs), (ins reglist:$src1, variable_ops),
//
// Add with carry
+let isCommutable = 1 in
def tADC : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"adc $dst, $rhs",
[(set tGPR:$dst, (adde tGPR:$lhs, tGPR:$rhs))]>;
@@ -311,6 +312,7 @@ def tADDrSPi : TI<(outs tGPR:$dst), (ins GPR:$sp, i32imm:$rhs),
def tADDspi : TIt<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
"add $dst, $rhs * 4", []>;
+let isCommutable = 1 in
def tAND : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"and $dst, $rhs",
[(set tGPR:$dst, (and tGPR:$lhs, tGPR:$rhs))]>;
@@ -358,6 +360,7 @@ def tCMPNZr : TI<(outs), (ins tGPR:$lhs, tGPR:$rhs),
// TODO: A7-37: CMP(3) - cmp hi regs
+let isCommutable = 1 in
def tEOR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"eor $dst, $rhs",
[(set tGPR:$dst, (xor tGPR:$lhs, tGPR:$rhs))]>;
@@ -399,6 +402,7 @@ def tMOVhir2hir : TI<(outs GPR:$dst), (ins GPR:$src),
"cpy $dst, $src\t@ hir2hir", []>;
} // neverHasSideEffects
+let isCommutable = 1 in
def tMUL : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"mul $dst, $rhs",
[(set tGPR:$dst, (mul tGPR:$lhs, tGPR:$rhs))]>;
@@ -411,6 +415,7 @@ def tNEG : TI<(outs tGPR:$dst), (ins tGPR:$src),
"neg $dst, $src",
[(set tGPR:$dst, (ineg tGPR:$src))]>;
+let isCommutable = 1 in
def tORR : TIt<(outs tGPR:$dst), (ins tGPR:$lhs, tGPR:$rhs),
"orr $dst, $rhs",
[(set tGPR:$dst, (or tGPR:$lhs, tGPR:$rhs))]>;
diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td
index 168fb45f11ea..07c71da46d62 100644
--- a/lib/Target/ARM/ARMInstrThumb2.td
+++ b/lib/Target/ARM/ARMInstrThumb2.td
@@ -10,3 +10,199 @@
// This file describes the Thumb2 instruction set.
//
//===----------------------------------------------------------------------===//
+
+// Shifted operands. No register controlled shifts for Thumb2.
+// Note: We do not support rrx shifted operands yet.
+def t2_so_reg : Operand<i32>, // reg imm
+ ComplexPattern<i32, 2, "SelectShifterOperand",
+ [shl,srl,sra,rotr]> {
+ let PrintMethod = "printSOOperand";
+ let MIOperandInfo = (ops GPR, i32imm);
+}
+
+def LO16 : SDNodeXForm<imm, [{
+ // Transformation function: shift the immediate value down into the low bits.
+ return getI32Imm((unsigned short)N->getZExtValue());
+}]>;
+
+def HI16 : SDNodeXForm<imm, [{
+ // Transformation function: shift the immediate value down into the low bits.
+ return getI32Imm((unsigned)N->getZExtValue() >> 16);
+}]>;
+
+def imm16high : PatLeaf<(i32 imm), [{
+ // Returns true if all bits out of the [31..16] range are 0.
+ return ((N->getZExtValue() & 0xFFFF0000ULL) == N->getZExtValue());
+}], HI16>;
+
+def imm16high0xffff : PatLeaf<(i32 imm), [{
+ // Returns true if lo 16 bits are set and this is a 32-bit value.
+ return ((N->getZExtValue() & 0x0000FFFFULL) == 0xFFFFULL);
+}], HI16>;
+
+def imm0_4095 : PatLeaf<(i32 imm), [{
+ return (uint32_t)N->getZExtValue() < 4096;
+}]>;
+
+def imm0_4095_neg : PatLeaf<(i32 imm), [{
+ return (uint32_t)-N->getZExtValue() < 4096;
+}], imm_neg_XFORM>;
+
+def imm0_65535 : PatLeaf<(i32 imm), [{
+ return N->getZExtValue() < 65536;
+}]>;
+
+// A6.3.2 Modified immediate constants in Thumb instructions (#<const>)
+// FIXME: Move it the the addrmode matcher code.
+def t2_so_imm : PatLeaf<(i32 imm), [{
+ uint64_t v = N->getZExtValue();
+ if (v == 0 || v > 0xffffffffUL) return false;
+ // variant1 - 0b0000x - 8-bit which could be zero (not supported for now)
+
+ // variant2 - 0b00nnx - 8-bit repeated inside the 32-bit room
+ unsigned hi16 = (unsigned)(v >> 16);
+ unsigned lo16 = (unsigned)(v & 0xffffUL);
+ bool valid = (hi16 == lo16) && (
+ (v & 0x00ff00ffUL) == 0 || // type 0001x
+ (v & 0xff00ff00UL) == 0 || // type 0010x
+ ((lo16 >> 8) == (lo16 & 0xff))); // type 0011x
+ if (valid) return true;
+
+ // variant3 - 0b01000..0b11111 - 8-bit shifted inside the 32-bit room
+ unsigned shift = CountLeadingZeros_32(v);
+ uint64_t mask = (0xff000000ULL >> shift);
+ // If valid, it is type 01000 + shift
+ return ((shift < 24) && (v & mask) > 0) && ((v & (~mask)) == 0);
+}]>;
+
+
+//===----------------------------------------------------------------------===//
+// Thumb-2 to cover the functionality of the ARM instruction set.
+//
+
+/// T2I_bin_irs - Defines a set of (op reg, {so_imm|reg|so_reg}) patterns for a
+// binary operation that produces a value.
+multiclass T2I_bin_irs<string opc, PatFrag opnode> {
+ // shifted imm
+ def ri : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+ !strconcat(opc, " $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+ Requires<[HasThumb2]>;
+ // register
+ def rr : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ !strconcat(opc, " $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
+ Requires<[HasThumb2]>;
+ // shifted register
+ def rs : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+ !strconcat(opc, " $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
+ Requires<[HasThumb2]>;
+}
+
+/// T2I_bin_s_irs - Similar to T2I_bin_irs except it sets the 's' bit so the
+/// instruction modifies the CPSR register.
+let Defs = [CPSR] in {
+multiclass T2I_bin_s_irs<string opc, PatFrag opnode> {
+ // shifted imm
+ def ri : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+ !strconcat(opc, "s $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+ Requires<[HasThumb2]>;
+
+ // register
+ def rr : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs),
+ !strconcat(opc, "s $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
+ Requires<[HasThumb2]>;
+
+ // shifted register
+ def rs : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs),
+ !strconcat(opc, "s $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
+ Requires<[HasThumb2]>;
+}
+}
+
+/// T2I_bin_c_irs - Similar to T2I_bin_irs except it uses the 's' bit. Also the
+/// instruction can optionally set the CPSR register.
+let Uses = [CPSR] in {
+multiclass T2I_bin_c_irs<string opc, PatFrag opnode> {
+ // shifted imm
+ def ri : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs, cc_out:$s),
+ !strconcat(opc, "${s} $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_imm:$rhs))]>,
+ Requires<[HasThumb2]>;
+
+ // register
+ def rr : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, GPR:$rhs, cc_out:$s),
+ !strconcat(opc, "${s} $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, GPR:$rhs))]>,
+ Requires<[HasThumb2]>;
+
+ // shifted register
+ def rs : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, t2_so_reg:$rhs, cc_out:$s),
+ !strconcat(opc, "${s} $dst, $lhs, $rhs"),
+ [(set GPR:$dst, (opnode GPR:$lhs, t2_so_reg:$rhs))]>,
+ Requires<[HasThumb2]>;
+}
+}
+
+//===----------------------------------------------------------------------===//
+// Arithmetic Instructions.
+//
+
+//===----------------------------------------------------------------------===//
+// Move Instructions.
+//
+def tMOVi16 : PseudoInst<(outs GPR:$dst), (ins i32imm:$src),
+ "movw $dst, $src",
+ [(set GPR:$dst, imm0_65535:$src)]>,
+ Requires<[HasThumb2]>;
+
+let isTwoAddress = 1 in
+def tMOVTi16 : PseudoInst<(outs GPR:$dst), (ins GPR:$src, i32imm:$imm),
+ "movt $dst, $imm",
+ [(set GPR:$dst, (or (and GPR:$src, 0xffff),
+ imm16high:$imm))]>,
+ Requires<[HasThumb2]>;
+
+def : Pat<(and (or GPR:$src, imm16high:$imm1), imm16high0xffff:$imm2),
+ (tMOVTi16 GPR:$src, (HI16 imm16high:$imm1))>,
+ Requires<[HasThumb2]>;
+
+def : Pat<(i32 imm:$imm),
+ (tMOVTi16 (tMOVi16 (LO16 imm:$imm)),(HI16 imm:$imm))>,
+ Requires<[HasThumb2]>;
+
+//===----------------------------------------------------------------------===//
+// Arithmetic Instructions.
+//
+defm t2ADD : T2I_bin_irs <"add", BinOpFrag<(add node:$LHS, node:$RHS)>>;
+defm t2SUB : T2I_bin_irs <"sub", BinOpFrag<(sub node:$LHS, node:$RHS)>>;
+
+def tADDri12 : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+ "add $dst, $lhs, $rhs",
+ [(set GPR:$dst, (add GPR:$lhs, imm0_4095:$rhs))]>,
+ Requires<[HasThumb2]>;
+def tSUBri12 : PseudoInst<(outs GPR:$dst), (ins GPR:$lhs, i32imm:$rhs),
+ "sub $dst, $lhs, $rhs",
+ [(set GPR:$dst, (add GPR:$lhs, imm0_4095_neg:$rhs))]>,
+ Requires<[HasThumb2]>;
+
+defm t2ADDS : T2I_bin_s_irs<"add", BinOpFrag<(addc node:$LHS, node:$RHS)>>;
+defm t2SUBS : T2I_bin_s_irs<"sub", BinOpFrag<(subc node:$LHS, node:$RHS)>>;
+
+defm t2ADC : T2I_bin_c_irs<"adc", BinOpFrag<(adde node:$LHS, node:$RHS)>>;
+defm t2SBC : T2I_bin_c_irs<"sbc", BinOpFrag<(sube node:$LHS, node:$RHS)>>;
+
+
+def tMLS : PseudoInst<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
+ "mls $dst, $a, $b, $c",
+ [(set GPR:$dst, (sub GPR:$c, (mul GPR:$a, GPR:$b)))]>,
+ Requires<[HasThumb2]>;
+
+def tORNrs : PseudoInst<(outs GPR:$dst), (ins GPR:$src1, t2_so_reg:$src2),
+ "orn $dst, $src1, $src2",
+ [(set GPR:$dst, (or GPR:$src1, (not t2_so_reg: $src2)))]>,
+ Requires<[HasThumb2]>;
diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index 684ecb4ce793..59cf125a9b99 100644
--- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -17,19 +17,22 @@
#include "ARMAddressingModes.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMRegisterInfo.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
-#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
using namespace llvm;
@@ -39,6 +42,12 @@ STATISTIC(NumSTMGened , "Number of stm instructions generated");
STATISTIC(NumFLDMGened, "Number of fldm instructions generated");
STATISTIC(NumFSTMGened, "Number of fstm instructions generated");
STATISTIC(NumLdStMoved, "Number of load / store instructions moved");
+STATISTIC(NumLDRDFormed,"Number of ldrd created before allocation");
+STATISTIC(NumSTRDFormed,"Number of strd created before allocation");
+STATISTIC(NumLDRD2LDM, "Number of ldrd instructions turned back into ldm");
+STATISTIC(NumSTRD2STM, "Number of strd instructions turned back into stm");
+STATISTIC(NumLDRD2LDR, "Number of ldrd instructions turned back into ldr's");
+STATISTIC(NumSTRD2STR, "Number of strd instructions turned back into str's");
/// ARMAllocLoadStoreOpt - Post- register allocation pass the combine
/// load / store instructions to form ldm / stm instructions.
@@ -82,6 +91,8 @@ namespace {
SmallVector<MachineBasicBlock::iterator, 4> &Merges);
void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps);
+ bool FixInvalidRegPairOp(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &MBBI);
bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
bool MergeReturnIntoLDM(MachineBasicBlock &MBB);
};
@@ -586,13 +597,19 @@ void ARMLoadStoreOpt::AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps) {
static int getMemoryOpOffset(const MachineInstr *MI) {
int Opcode = MI->getOpcode();
bool isAM2 = Opcode == ARM::LDR || Opcode == ARM::STR;
+ bool isAM3 = Opcode == ARM::LDRD || Opcode == ARM::STRD;
unsigned NumOperands = MI->getDesc().getNumOperands();
unsigned OffField = MI->getOperand(NumOperands-3).getImm();
int Offset = isAM2
- ? ARM_AM::getAM2Offset(OffField) : ARM_AM::getAM5Offset(OffField) * 4;
+ ? ARM_AM::getAM2Offset(OffField)
+ : (isAM3 ? ARM_AM::getAM3Offset(OffField)
+ : ARM_AM::getAM5Offset(OffField) * 4);
if (isAM2) {
if (ARM_AM::getAM2Op(OffField) == ARM_AM::sub)
Offset = -Offset;
+ } else if (isAM3) {
+ if (ARM_AM::getAM3Op(OffField) == ARM_AM::sub)
+ Offset = -Offset;
} else {
if (ARM_AM::getAM5Op(OffField) == ARM_AM::sub)
Offset = -Offset;
@@ -600,6 +617,120 @@ static int getMemoryOpOffset(const MachineInstr *MI) {
return Offset;
}
+static void InsertLDR_STR(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &MBBI,
+ int OffImm, bool isDef,
+ DebugLoc dl, unsigned NewOpc,
+ unsigned Reg, bool RegDeadKill,
+ unsigned BaseReg, bool BaseKill,
+ unsigned OffReg, bool OffKill,
+ ARMCC::CondCodes Pred, unsigned PredReg,
+ const TargetInstrInfo *TII) {
+ unsigned Offset;
+ if (OffImm < 0)
+ Offset = ARM_AM::getAM2Opc(ARM_AM::sub, -OffImm, ARM_AM::no_shift);
+ else
+ Offset = ARM_AM::getAM2Opc(ARM_AM::add, OffImm, ARM_AM::no_shift);
+ if (isDef)
+ BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
+ .addReg(Reg, getDefRegState(true) | getDeadRegState(RegDeadKill))
+ .addReg(BaseReg, getKillRegState(BaseKill))
+ .addReg(OffReg, getKillRegState(OffKill))
+ .addImm(Offset)
+ .addImm(Pred).addReg(PredReg);
+ else
+ BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
+ .addReg(Reg, getKillRegState(RegDeadKill))
+ .addReg(BaseReg, getKillRegState(BaseKill))
+ .addReg(OffReg, getKillRegState(OffKill))
+ .addImm(Offset)
+ .addImm(Pred).addReg(PredReg);
+}
+
+bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &MBBI) {
+ MachineInstr *MI = &*MBBI;
+ unsigned Opcode = MI->getOpcode();
+ if (Opcode == ARM::LDRD || Opcode == ARM::STRD) {
+ unsigned EvenReg = MI->getOperand(0).getReg();
+ unsigned OddReg = MI->getOperand(1).getReg();
+ unsigned EvenRegNum = TRI->getDwarfRegNum(EvenReg, false);
+ unsigned OddRegNum = TRI->getDwarfRegNum(OddReg, false);
+ if ((EvenRegNum & 1) == 0 && (EvenRegNum + 1) == OddRegNum)
+ return false;
+
+ bool isLd = Opcode == ARM::LDRD;
+ bool EvenDeadKill = isLd ?
+ MI->getOperand(0).isDead() : MI->getOperand(0).isKill();
+ bool OddDeadKill = isLd ?
+ MI->getOperand(1).isDead() : MI->getOperand(1).isKill();
+ const MachineOperand &BaseOp = MI->getOperand(2);
+ unsigned BaseReg = BaseOp.getReg();
+ bool BaseKill = BaseOp.isKill();
+ const MachineOperand &OffOp = MI->getOperand(3);
+ unsigned OffReg = OffOp.getReg();
+ bool OffKill = OffOp.isKill();
+ int OffImm = getMemoryOpOffset(MI);
+ unsigned PredReg = 0;
+ ARMCC::CondCodes Pred = getInstrPredicate(MI, PredReg);
+
+ if (OddRegNum > EvenRegNum && OffReg == 0 && OffImm == 0) {
+ // Ascending register numbers and no offset. It's safe to change it to a
+ // ldm or stm.
+ unsigned NewOpc = (Opcode == ARM::LDRD) ? ARM::LDM : ARM::STM;
+ if (isLd) {
+ BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
+ .addReg(BaseReg, getKillRegState(BaseKill))
+ .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
+ .addImm(Pred).addReg(PredReg)
+ .addReg(EvenReg, getDefRegState(isLd) | getDeadRegState(EvenDeadKill))
+ .addReg(OddReg, getDefRegState(isLd) | getDeadRegState(OddDeadKill));
+ ++NumLDRD2LDM;
+ } else {
+ BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc))
+ .addReg(BaseReg, getKillRegState(BaseKill))
+ .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))
+ .addImm(Pred).addReg(PredReg)
+ .addReg(EvenReg, getKillRegState(EvenDeadKill))
+ .addReg(OddReg, getKillRegState(OddDeadKill));
+ ++NumSTRD2STM;
+ }
+ } else {
+ // Split into two instructions.
+ unsigned NewOpc = (Opcode == ARM::LDRD) ? ARM::LDR : ARM::STR;
+ DebugLoc dl = MBBI->getDebugLoc();
+ // If this is a load and base register is killed, it may have been
+ // re-defed by the load, make sure the first load does not clobber it.
+ if (isLd &&
+ (BaseKill || OffKill) &&
+ (TRI->regsOverlap(EvenReg, BaseReg) ||
+ (OffReg && TRI->regsOverlap(EvenReg, OffReg)))) {
+ assert(!TRI->regsOverlap(OddReg, BaseReg) &&
+ (!OffReg || !TRI->regsOverlap(OddReg, OffReg)));
+ InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc, OddReg, OddDeadKill,
+ BaseReg, false, OffReg, false, Pred, PredReg, TII);
+ InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc, EvenReg, EvenDeadKill,
+ BaseReg, BaseKill, OffReg, OffKill, Pred, PredReg, TII);
+ } else {
+ InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc,
+ EvenReg, EvenDeadKill, BaseReg, false, OffReg, false,
+ Pred, PredReg, TII);
+ InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc,
+ OddReg, OddDeadKill, BaseReg, BaseKill, OffReg, OffKill,
+ Pred, PredReg, TII);
+ }
+ if (isLd)
+ ++NumLDRD2LDR;
+ else
+ ++NumSTRD2STR;
+ }
+
+ MBBI = prior(MBBI);
+ MBB.erase(MI);
+ }
+ return false;
+}
+
/// LoadStoreMultipleOpti - An optimization pass to turn multiple LDR / STR
/// ops of the same base and incrementing offset into LDM / STM ops.
bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
@@ -617,6 +748,9 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
RS->enterBasicBlock(&MBB);
MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
while (MBBI != E) {
+ if (FixInvalidRegPairOp(MBB, MBBI))
+ continue;
+
bool Advance = false;
bool TryMerge = false;
bool Clobber = false;
@@ -817,8 +951,10 @@ namespace {
static char ID;
ARMPreAllocLoadStoreOpt() : MachineFunctionPass(&ID) {}
+ const TargetData *TD;
const TargetInstrInfo *TII;
const TargetRegisterInfo *TRI;
+ const ARMSubtarget *STI;
MachineRegisterInfo *MRI;
virtual bool runOnMachineFunction(MachineFunction &Fn);
@@ -828,6 +964,11 @@ namespace {
}
private:
+ bool CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1, DebugLoc &dl,
+ unsigned &NewOpc, unsigned &EvenReg,
+ unsigned &OddReg, unsigned &BaseReg,
+ unsigned &OffReg, unsigned &Offset,
+ unsigned &PredReg, ARMCC::CondCodes &Pred);
bool RescheduleOps(MachineBasicBlock *MBB,
SmallVector<MachineInstr*, 4> &Ops,
unsigned Base, bool isLd,
@@ -838,8 +979,10 @@ namespace {
}
bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
+ TD = Fn.getTarget().getTargetData();
TII = Fn.getTarget().getInstrInfo();
TRI = Fn.getTarget().getRegisterInfo();
+ STI = &Fn.getTarget().getSubtarget<ARMSubtarget>();
MRI = &Fn.getRegInfo();
bool Modified = false;
@@ -850,15 +993,19 @@ bool ARMPreAllocLoadStoreOpt::runOnMachineFunction(MachineFunction &Fn) {
return Modified;
}
-static bool IsSafeToMove(bool isLd, unsigned Base,
- MachineBasicBlock::iterator I,
- MachineBasicBlock::iterator E,
- SmallPtrSet<MachineInstr*, 4> MoveOps,
- const TargetRegisterInfo *TRI) {
+static bool IsSafeAndProfitableToMove(bool isLd, unsigned Base,
+ MachineBasicBlock::iterator I,
+ MachineBasicBlock::iterator E,
+ SmallPtrSet<MachineInstr*, 4> &MemOps,
+ SmallSet<unsigned, 4> &MemRegs,
+ const TargetRegisterInfo *TRI) {
// Are there stores / loads / calls between them?
// FIXME: This is overly conservative. We should make use of alias information
// some day.
+ SmallSet<unsigned, 4> AddedRegPressure;
while (++I != E) {
+ if (MemOps.count(&*I))
+ continue;
const TargetInstrDesc &TID = I->getDesc();
if (TID.isCall() || TID.isTerminator() || TID.hasUnmodeledSideEffects())
return false;
@@ -871,15 +1018,76 @@ static bool IsSafeToMove(bool isLd, unsigned Base,
// str r1, [r0]
// strh r5, [r0]
// str r4, [r0, #+4]
- if (TID.mayStore() && !MoveOps.count(&*I))
+ if (TID.mayStore())
return false;
}
for (unsigned j = 0, NumOps = I->getNumOperands(); j != NumOps; ++j) {
MachineOperand &MO = I->getOperand(j);
- if (MO.isReg() && MO.isDef() && TRI->regsOverlap(MO.getReg(), Base))
+ if (!MO.isReg())
+ continue;
+ unsigned Reg = MO.getReg();
+ if (MO.isDef() && TRI->regsOverlap(Reg, Base))
return false;
+ if (Reg != Base && !MemRegs.count(Reg))
+ AddedRegPressure.insert(Reg);
}
}
+
+ // Estimate register pressure increase due to the transformation.
+ if (MemRegs.size() <= 4)
+ // Ok if we are moving small number of instructions.
+ return true;
+ return AddedRegPressure.size() <= MemRegs.size() * 2;
+}
+
+bool
+ARMPreAllocLoadStoreOpt::CanFormLdStDWord(MachineInstr *Op0, MachineInstr *Op1,
+ DebugLoc &dl,
+ unsigned &NewOpc, unsigned &EvenReg,
+ unsigned &OddReg, unsigned &BaseReg,
+ unsigned &OffReg, unsigned &Offset,
+ unsigned &PredReg,
+ ARMCC::CondCodes &Pred) {
+ // FIXME: FLDS / FSTS -> FLDD / FSTD
+ unsigned Opcode = Op0->getOpcode();
+ if (Opcode == ARM::LDR)
+ NewOpc = ARM::LDRD;
+ else if (Opcode == ARM::STR)
+ NewOpc = ARM::STRD;
+ else
+ return 0;
+
+ // Must sure the base address satisfies i64 ld / st alignment requirement.
+ if (!Op0->hasOneMemOperand() ||
+ !Op0->memoperands_begin()->getValue() ||
+ Op0->memoperands_begin()->isVolatile())
+ return false;
+
+ unsigned Align = Op0->memoperands_begin()->getAlignment();
+ unsigned ReqAlign = STI->hasV6Ops()
+ ? TD->getPrefTypeAlignment(Type::Int64Ty) : 8; // Pre-v6 need 8-byte align
+ if (Align < ReqAlign)
+ return false;
+
+ // Then make sure the immediate offset fits.
+ int OffImm = getMemoryOpOffset(Op0);
+ ARM_AM::AddrOpc AddSub = ARM_AM::add;
+ if (OffImm < 0) {
+ AddSub = ARM_AM::sub;
+ OffImm = - OffImm;
+ }
+ if (OffImm >= 256) // 8 bits
+ return false;
+ Offset = ARM_AM::getAM3Opc(AddSub, OffImm);
+
+ EvenReg = Op0->getOperand(0).getReg();
+ OddReg = Op1->getOperand(0).getReg();
+ if (EvenReg == OddReg)
+ return false;
+ BaseReg = Op0->getOperand(1).getReg();
+ OffReg = Op0->getOperand(2).getReg();
+ Pred = getInstrPredicate(Op0, PredReg);
+ dl = Op0->getDebugLoc();
return true;
}
@@ -902,6 +1110,7 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
MachineInstr *FirstOp = 0;
MachineInstr *LastOp = 0;
int LastOffset = 0;
+ unsigned LastOpcode = 0;
unsigned LastBytes = 0;
unsigned NumMove = 0;
for (int i = Ops.size() - 1; i >= 0; --i) {
@@ -916,6 +1125,10 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
LastOp = Op;
}
+ unsigned Opcode = Op->getOpcode();
+ if (LastOpcode && Opcode != LastOpcode)
+ break;
+
int Offset = getMemoryOpOffset(Op);
unsigned Bytes = getLSMultipleTransferSize(Op);
if (LastBytes) {
@@ -924,34 +1137,80 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB,
}
LastOffset = Offset;
LastBytes = Bytes;
- if (++NumMove == 4)
+ LastOpcode = Opcode;
+ if (++NumMove == 8) // FIXME: Tune
break;
}
if (NumMove <= 1)
Ops.pop_back();
else {
- SmallPtrSet<MachineInstr*, 4> MoveOps;
- for (int i = NumMove-1; i >= 0; --i)
- MoveOps.insert(Ops[i]);
+ SmallPtrSet<MachineInstr*, 4> MemOps;
+ SmallSet<unsigned, 4> MemRegs;
+ for (int i = NumMove-1; i >= 0; --i) {
+ MemOps.insert(Ops[i]);
+ MemRegs.insert(Ops[i]->getOperand(0).getReg());
+ }
// Be conservative, if the instructions are too far apart, don't
// move them. We want to limit the increase of register pressure.
- bool DoMove = (LastLoc - FirstLoc) < NumMove*4;
+ bool DoMove = (LastLoc - FirstLoc) <= NumMove*4; // FIXME: Tune this.
if (DoMove)
- DoMove = IsSafeToMove(isLd, Base, FirstOp, LastOp, MoveOps, TRI);
+ DoMove = IsSafeAndProfitableToMove(isLd, Base, FirstOp, LastOp,
+ MemOps, MemRegs, TRI);
if (!DoMove) {
for (unsigned i = 0; i != NumMove; ++i)
Ops.pop_back();
} else {
// This is the new location for the loads / stores.
MachineBasicBlock::iterator InsertPos = isLd ? FirstOp : LastOp;
- while (InsertPos != MBB->end() && MoveOps.count(InsertPos))
+ while (InsertPos != MBB->end() && MemOps.count(InsertPos))
++InsertPos;
- for (unsigned i = 0; i != NumMove; ++i) {
- MachineInstr *Op = Ops.back();
+
+ // If we are moving a pair of loads / stores, see if it makes sense
+ // to try to allocate a pair of registers that can form register pairs.
+ MachineInstr *Op0 = Ops.back();
+ MachineInstr *Op1 = Ops[Ops.size()-2];
+ unsigned EvenReg = 0, OddReg = 0;
+ unsigned BaseReg = 0, OffReg = 0, PredReg = 0;
+ ARMCC::CondCodes Pred = ARMCC::AL;
+ unsigned NewOpc = 0;
+ unsigned Offset = 0;
+ DebugLoc dl;
+ if (NumMove == 2 && CanFormLdStDWord(Op0, Op1, dl, NewOpc,
+ EvenReg, OddReg, BaseReg, OffReg,
+ Offset, PredReg, Pred)) {
+ Ops.pop_back();
Ops.pop_back();
- MBB->splice(InsertPos, MBB, Op);
+
+ // Form the pair instruction.
+ if (isLd) {
+ BuildMI(*MBB, InsertPos, dl, TII->get(NewOpc))
+ .addReg(EvenReg, RegState::Define)
+ .addReg(OddReg, RegState::Define)
+ .addReg(BaseReg).addReg(0).addImm(Offset)
+ .addImm(Pred).addReg(PredReg);
+ ++NumLDRDFormed;
+ } else {
+ BuildMI(*MBB, InsertPos, dl, TII->get(NewOpc))
+ .addReg(EvenReg)
+ .addReg(OddReg)
+ .addReg(BaseReg).addReg(0).addImm(Offset)
+ .addImm(Pred).addReg(PredReg);
+ ++NumSTRDFormed;
+ }
+ MBB->erase(Op0);
+ MBB->erase(Op1);
+
+ // Add register allocation hints to form register pairs.
+ MRI->setRegAllocationHint(EvenReg, ARMRI::RegPairEven, OddReg);
+ MRI->setRegAllocationHint(OddReg, ARMRI::RegPairOdd, EvenReg);
+ } else {
+ for (unsigned i = 0; i != NumMove; ++i) {
+ MachineInstr *Op = Ops.back();
+ Ops.pop_back();
+ MBB->splice(InsertPos, MBB, Op);
+ }
}
NumLdStMoved += NumMove;
@@ -1039,7 +1298,8 @@ ARMPreAllocLoadStoreOpt::RescheduleLoadStoreInstrs(MachineBasicBlock *MBB) {
}
if (StopHere) {
- // Found a duplicate (a base+offset combination that's seen earlier). Backtrack.
+ // Found a duplicate (a base+offset combination that's seen earlier).
+ // Backtrack.
--Loc;
break;
}
diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp
index 199858f525c8..bbc13001ae55 100644
--- a/lib/Target/ARM/ARMRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMRegisterInfo.cpp
@@ -159,7 +159,7 @@ ARMRegisterInfo::ARMRegisterInfo(const TargetInstrInfo &tii,
const ARMSubtarget &sti)
: ARMGenRegisterInfo(ARM::ADJCALLSTACKDOWN, ARM::ADJCALLSTACKUP),
TII(tii), STI(sti),
- FramePtr((STI.useThumbBacktraces() || STI.isThumb()) ? ARM::R7 : ARM::R11) {
+ FramePtr((STI.isTargetDarwin() || STI.isThumb()) ? ARM::R7 : ARM::R11) {
}
static inline
@@ -194,10 +194,6 @@ void ARMRegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
.addReg(0).addImm(0).addImm(Pred).addReg(PredReg);
}
-const TargetRegisterClass *ARMRegisterInfo::getPointerRegClass() const {
- return &ARM::GPRRegClass;
-}
-
/// isLowRegister - Returns true if the register is low register r0-r7.
///
bool ARMRegisterInfo::isLowRegister(unsigned Reg) const {
@@ -304,6 +300,191 @@ ARMRegisterInfo::isReservedReg(const MachineFunction &MF, unsigned Reg) const {
return false;
}
+const TargetRegisterClass *ARMRegisterInfo::getPointerRegClass() const {
+ return &ARM::GPRRegClass;
+}
+
+/// getAllocationOrder - Returns the register allocation order for a specified
+/// register class in the form of a pair of TargetRegisterClass iterators.
+std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
+ARMRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC,
+ unsigned HintType, unsigned HintReg,
+ const MachineFunction &MF) const {
+ // Alternative register allocation orders when favoring even / odd registers
+ // of register pairs.
+
+ // No FP, R9 is available.
+ static const unsigned GPREven1[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8, ARM::R10,
+ ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7,
+ ARM::R9, ARM::R11
+ };
+ static const unsigned GPROdd1[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R9, ARM::R11,
+ ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6,
+ ARM::R8, ARM::R10
+ };
+
+ // FP is R7, R9 is available.
+ static const unsigned GPREven2[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R8, ARM::R10,
+ ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6,
+ ARM::R9, ARM::R11
+ };
+ static const unsigned GPROdd2[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R9, ARM::R11,
+ ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6,
+ ARM::R8, ARM::R10
+ };
+
+ // FP is R11, R9 is available.
+ static const unsigned GPREven3[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R8,
+ ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7,
+ ARM::R9
+ };
+ static const unsigned GPROdd3[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R6, ARM::R9,
+ ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R7,
+ ARM::R8
+ };
+
+ // No FP, R9 is not available.
+ static const unsigned GPREven4[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R6, ARM::R10,
+ ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8,
+ ARM::R11
+ };
+ static const unsigned GPROdd4[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R7, ARM::R11,
+ ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8,
+ ARM::R10
+ };
+
+ // FP is R7, R9 is not available.
+ static const unsigned GPREven5[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R10,
+ ARM::R1, ARM::R3, ARM::R12,ARM::LR, ARM::R5, ARM::R6, ARM::R8,
+ ARM::R11
+ };
+ static const unsigned GPROdd5[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R11,
+ ARM::R0, ARM::R2, ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8,
+ ARM::R10
+ };
+
+ // FP is R11, R9 is not available.
+ static const unsigned GPREven6[] = {
+ ARM::R0, ARM::R2, ARM::R4, ARM::R6,
+ ARM::R1, ARM::R3, ARM::R10,ARM::R12,ARM::LR, ARM::R5, ARM::R7, ARM::R8
+ };
+ static const unsigned GPROdd6[] = {
+ ARM::R1, ARM::R3, ARM::R5, ARM::R7,
+ ARM::R0, ARM::R2, ARM::R10,ARM::R12,ARM::LR, ARM::R4, ARM::R6, ARM::R8
+ };
+
+
+ if (HintType == ARMRI::RegPairEven) {
+ if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0)
+ // It's no longer possible to fulfill this hint. Return the default
+ // allocation order.
+ return std::make_pair(RC->allocation_order_begin(MF),
+ RC->allocation_order_end(MF));
+
+ if (!STI.isTargetDarwin() && !hasFP(MF)) {
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPREven1,
+ GPREven1 + (sizeof(GPREven1)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPREven4,
+ GPREven4 + (sizeof(GPREven4)/sizeof(unsigned)));
+ } else if (FramePtr == ARM::R7) {
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPREven2,
+ GPREven2 + (sizeof(GPREven2)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPREven5,
+ GPREven5 + (sizeof(GPREven5)/sizeof(unsigned)));
+ } else { // FramePtr == ARM::R11
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPREven3,
+ GPREven3 + (sizeof(GPREven3)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPREven6,
+ GPREven6 + (sizeof(GPREven6)/sizeof(unsigned)));
+ }
+ } else if (HintType == ARMRI::RegPairOdd) {
+ if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0)
+ // It's no longer possible to fulfill this hint. Return the default
+ // allocation order.
+ return std::make_pair(RC->allocation_order_begin(MF),
+ RC->allocation_order_end(MF));
+
+ if (!STI.isTargetDarwin() && !hasFP(MF)) {
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPROdd1,
+ GPROdd1 + (sizeof(GPROdd1)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPROdd4,
+ GPROdd4 + (sizeof(GPROdd4)/sizeof(unsigned)));
+ } else if (FramePtr == ARM::R7) {
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPROdd2,
+ GPROdd2 + (sizeof(GPROdd2)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPROdd5,
+ GPROdd5 + (sizeof(GPROdd5)/sizeof(unsigned)));
+ } else { // FramePtr == ARM::R11
+ if (!STI.isR9Reserved())
+ return std::make_pair(GPROdd3,
+ GPROdd3 + (sizeof(GPROdd3)/sizeof(unsigned)));
+ else
+ return std::make_pair(GPROdd6,
+ GPROdd6 + (sizeof(GPROdd6)/sizeof(unsigned)));
+ }
+ }
+ return std::make_pair(RC->allocation_order_begin(MF),
+ RC->allocation_order_end(MF));
+}
+
+/// ResolveRegAllocHint - Resolves the specified register allocation hint
+/// to a physical register. Returns the physical register if it is successful.
+unsigned
+ARMRegisterInfo::ResolveRegAllocHint(unsigned Type, unsigned Reg,
+ const MachineFunction &MF) const {
+ if (Reg == 0 || !isPhysicalRegister(Reg))
+ return 0;
+ if (Type == 0)
+ return Reg;
+ else if (Type == (unsigned)ARMRI::RegPairOdd)
+ // Odd register.
+ return getRegisterPairOdd(Reg, MF);
+ else if (Type == (unsigned)ARMRI::RegPairEven)
+ // Even register.
+ return getRegisterPairEven(Reg, MF);
+ return 0;
+}
+
+void
+ARMRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
+ MachineFunction &MF) const {
+ MachineRegisterInfo *MRI = &MF.getRegInfo();
+ std::pair<unsigned, unsigned> Hint = MRI->getRegAllocationHint(Reg);
+ if ((Hint.first == (unsigned)ARMRI::RegPairOdd ||
+ Hint.first == (unsigned)ARMRI::RegPairEven) &&
+ Hint.second && TargetRegisterInfo::isVirtualRegister(Hint.second)) {
+ // If 'Reg' is one of the even / odd register pair and it's now changed
+ // (e.g. coalesced) into a different register. The other register of the
+ // pair allocation hint must be updated to reflect the relationship
+ // change.
+ unsigned OtherReg = Hint.second;
+ Hint = MRI->getRegAllocationHint(OtherReg);
+ if (Hint.second == Reg)
+ // Make sure the pair has not already divorced.
+ MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg);
+ }
+}
+
bool
ARMRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const {
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
@@ -1506,9 +1687,8 @@ unsigned ARMRegisterInfo::getRARegister() const {
unsigned ARMRegisterInfo::getFrameRegister(MachineFunction &MF) const {
if (STI.isTargetDarwin() || hasFP(MF))
- return (STI.useThumbBacktraces() || STI.isThumb()) ? ARM::R7 : ARM::R11;
- else
- return ARM::SP;
+ return FramePtr;
+ return ARM::SP;
}
unsigned ARMRegisterInfo::getEHExceptionRegister() const {
@@ -1525,4 +1705,152 @@ int ARMRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
return ARMGenRegisterInfo::getDwarfRegNumFull(RegNum, 0);
}
+unsigned ARMRegisterInfo::getRegisterPairEven(unsigned Reg,
+ const MachineFunction &MF) const {
+ switch (Reg) {
+ default: break;
+ // Return 0 if either register of the pair is a special register.
+ // So no R12, etc.
+ case ARM::R1:
+ return ARM::R0;
+ case ARM::R3:
+ // FIXME!
+ return STI.isThumb() ? 0 : ARM::R2;
+ case ARM::R5:
+ return ARM::R4;
+ case ARM::R7:
+ return isReservedReg(MF, ARM::R7) ? 0 : ARM::R6;
+ case ARM::R9:
+ return isReservedReg(MF, ARM::R9) ? 0 :ARM::R8;
+ case ARM::R11:
+ return isReservedReg(MF, ARM::R11) ? 0 : ARM::R10;
+
+ case ARM::S1:
+ return ARM::S0;
+ case ARM::S3:
+ return ARM::S2;
+ case ARM::S5:
+ return ARM::S4;
+ case ARM::S7:
+ return ARM::S6;
+ case ARM::S9:
+ return ARM::S8;
+ case ARM::S11:
+ return ARM::S10;
+ case ARM::S13:
+ return ARM::S12;
+ case ARM::S15:
+ return ARM::S14;
+ case ARM::S17:
+ return ARM::S16;
+ case ARM::S19:
+ return ARM::S18;
+ case ARM::S21:
+ return ARM::S20;
+ case ARM::S23:
+ return ARM::S22;
+ case ARM::S25:
+ return ARM::S24;
+ case ARM::S27:
+ return ARM::S26;
+ case ARM::S29:
+ return ARM::S28;
+ case ARM::S31:
+ return ARM::S30;
+
+ case ARM::D1:
+ return ARM::D0;
+ case ARM::D3:
+ return ARM::D2;
+ case ARM::D5:
+ return ARM::D4;
+ case ARM::D7:
+ return ARM::D6;
+ case ARM::D9:
+ return ARM::D8;
+ case ARM::D11:
+ return ARM::D10;
+ case ARM::D13:
+ return ARM::D12;
+ case ARM::D15:
+ return ARM::D14;
+ }
+
+ return 0;
+}
+
+unsigned ARMRegisterInfo::getRegisterPairOdd(unsigned Reg,
+ const MachineFunction &MF) const {
+ switch (Reg) {
+ default: break;
+ // Return 0 if either register of the pair is a special register.
+ // So no R12, etc.
+ case ARM::R0:
+ return ARM::R1;
+ case ARM::R2:
+ // FIXME!
+ return STI.isThumb() ? 0 : ARM::R3;
+ case ARM::R4:
+ return ARM::R5;
+ case ARM::R6:
+ return isReservedReg(MF, ARM::R7) ? 0 : ARM::R7;
+ case ARM::R8:
+ return isReservedReg(MF, ARM::R9) ? 0 :ARM::R9;
+ case ARM::R10:
+ return isReservedReg(MF, ARM::R11) ? 0 : ARM::R11;
+
+ case ARM::S0:
+ return ARM::S1;
+ case ARM::S2:
+ return ARM::S3;
+ case ARM::S4:
+ return ARM::S5;
+ case ARM::S6:
+ return ARM::S7;
+ case ARM::S8:
+ return ARM::S9;
+ case ARM::S10:
+ return ARM::S11;
+ case ARM::S12:
+ return ARM::S13;
+ case ARM::S14:
+ return ARM::S15;
+ case ARM::S16:
+ return ARM::S17;
+ case ARM::S18:
+ return ARM::S19;
+ case ARM::S20:
+ return ARM::S21;
+ case ARM::S22:
+ return ARM::S23;
+ case ARM::S24:
+ return ARM::S25;
+ case ARM::S26:
+ return ARM::S27;
+ case ARM::S28:
+ return ARM::S29;
+ case ARM::S30:
+ return ARM::S31;
+
+ case ARM::D0:
+ return ARM::D1;
+ case ARM::D2:
+ return ARM::D3;
+ case ARM::D4:
+ return ARM::D5;
+ case ARM::D6:
+ return ARM::D7;
+ case ARM::D8:
+ return ARM::D9;
+ case ARM::D10:
+ return ARM::D11;
+ case ARM::D12:
+ return ARM::D13;
+ case ARM::D14:
+ return ARM::D15;
+ }
+
+ return 0;
+}
+
#include "ARMGenRegisterInfo.inc"
diff --git a/lib/Target/ARM/ARMRegisterInfo.h b/lib/Target/ARM/ARMRegisterInfo.h
index e1d9efbcabf7..e8f4fd805d5b 100644
--- a/lib/Target/ARM/ARMRegisterInfo.h
+++ b/lib/Target/ARM/ARMRegisterInfo.h
@@ -22,12 +22,17 @@ namespace llvm {
class TargetInstrInfo;
class Type;
+/// Register allocation hints.
+namespace ARMRI {
+ enum {
+ RegPairOdd = 1,
+ RegPairEven = 2
+ };
+}
+
struct ARMRegisterInfo : public ARMGenRegisterInfo {
const TargetInstrInfo &TII;
const ARMSubtarget &STI;
-private:
- /// FramePtr - ARM physical register used as frame ptr.
- unsigned FramePtr;
public:
ARMRegisterInfo(const TargetInstrInfo &tii, const ARMSubtarget &STI);
@@ -49,10 +54,6 @@ public:
/// if the register is a single precision VFP register.
static unsigned getRegisterNumbering(unsigned RegEnum, bool &isSPVFP);
- /// getPointerRegClass - Return the register class to use to hold pointers.
- /// This is used for addressing modes.
- const TargetRegisterClass *getPointerRegClass() const;
-
/// Code Generation virtual methods...
const TargetRegisterClass *
getPhysicalRegisterRegClass(unsigned Reg, MVT VT = MVT::Other) const;
@@ -65,6 +66,19 @@ public:
bool isReservedReg(const MachineFunction &MF, unsigned Reg) const;
+ const TargetRegisterClass *getPointerRegClass() const;
+
+ std::pair<TargetRegisterClass::iterator,TargetRegisterClass::iterator>
+ getAllocationOrder(const TargetRegisterClass *RC,
+ unsigned HintType, unsigned HintReg,
+ const MachineFunction &MF) const;
+
+ unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg,
+ const MachineFunction &MF) const;
+
+ void UpdateRegAllocHint(unsigned Reg, unsigned NewReg,
+ MachineFunction &MF) const;
+
bool requiresRegisterScavenging(const MachineFunction &MF) const;
bool hasFP(const MachineFunction &MF) const;
@@ -95,6 +109,15 @@ public:
int getDwarfRegNum(unsigned RegNum, bool isEH) const;
bool isLowRegister(unsigned Reg) const;
+
+private:
+ /// FramePtr - ARM physical register used as frame ptr.
+ unsigned FramePtr;
+
+ unsigned getRegisterPairEven(unsigned Reg, const MachineFunction &MF) const;
+
+ unsigned getRegisterPairOdd(unsigned Reg, const MachineFunction &MF) const;
+
};
} // end namespace llvm
diff --git a/lib/Target/ARM/ARMRegisterInfo.td b/lib/Target/ARM/ARMRegisterInfo.td
index ebe7d582a664..d864079f85e1 100644
--- a/lib/Target/ARM/ARMRegisterInfo.td
+++ b/lib/Target/ARM/ARMRegisterInfo.td
@@ -134,7 +134,7 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
GPRClass::allocation_order_begin(const MachineFunction &MF) const {
const TargetMachine &TM = MF.getTarget();
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
- if (Subtarget.useThumbBacktraces()) {
+ if (Subtarget.isTargetDarwin()) {
if (Subtarget.isR9Reserved())
return ARM_GPR_AO_4;
else
@@ -154,7 +154,7 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
const ARMSubtarget &Subtarget = TM.getSubtarget<ARMSubtarget>();
GPRClass::iterator I;
- if (Subtarget.useThumbBacktraces()) {
+ if (Subtarget.isTargetDarwin()) {
if (Subtarget.isR9Reserved()) {
I = ARM_GPR_AO_4 + (sizeof(ARM_GPR_AO_4)/sizeof(unsigned));
} else {
diff --git a/lib/Target/ARM/ARMSchedule.td b/lib/Target/ARM/ARMSchedule.td
new file mode 100644
index 000000000000..75fa707f9f93
--- /dev/null
+++ b/lib/Target/ARM/ARMSchedule.td
@@ -0,0 +1,35 @@
+//===- ARMSchedule.td - ARM Scheduling Definitions ---------*- tablegen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Functional units across ARM processors
+//
+def FU_iALU : FuncUnit; // Integer alu unit
+def FU_iLdSt : FuncUnit; // Integer load / store unit
+def FU_FpALU : FuncUnit; // FP alu unit
+def FU_FpLdSt : FuncUnit; // FP load / store unit
+def FU_Br : FuncUnit; // Branch unit
+
+//===----------------------------------------------------------------------===//
+// Instruction Itinerary classes used for ARM
+//
+def IIC_iALU : InstrItinClass;
+def IIC_iLoad : InstrItinClass;
+def IIC_iStore : InstrItinClass;
+def IIC_fpALU : InstrItinClass;
+def IIC_fpLoad : InstrItinClass;
+def IIC_fpStore : InstrItinClass;
+def IIC_Br : InstrItinClass;
+
+//===----------------------------------------------------------------------===//
+// Processor instruction itineraries.
+
+def GenericItineraries : ProcessorItineraries<[]>;
+
+include "ARMScheduleV6.td"
diff --git a/lib/Target/ARM/ARMScheduleV6.td b/lib/Target/ARM/ARMScheduleV6.td
new file mode 100644
index 000000000000..596a57f8aefd
--- /dev/null
+++ b/lib/Target/ARM/ARMScheduleV6.td
@@ -0,0 +1,22 @@
+//===- ARMSchedule.td - ARM v6 Scheduling Definitions ------*- 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 the itinerary class data for the ARM v6 processors.
+//
+//===----------------------------------------------------------------------===//
+
+def V6Itineraries : ProcessorItineraries<[
+ InstrItinData<IIC_iALU , [InstrStage<1, [FU_iALU]>]>,
+ InstrItinData<IIC_iLoad , [InstrStage<2, [FU_iLdSt]>]>,
+ InstrItinData<IIC_iStore , [InstrStage<1, [FU_iLdSt]>]>,
+ InstrItinData<IIC_fpALU , [InstrStage<6, [FU_FpALU]>]>,
+ InstrItinData<IIC_fpLoad , [InstrStage<2, [FU_FpLdSt]>]>,
+ InstrItinData<IIC_fpStore , [InstrStage<1, [FU_FpLdSt]>]>,
+ InstrItinData<IIC_Br , [InstrStage<3, [FU_Br]>]>
+]>;
diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp
index a978380b627f..7ac7b4923d68 100644
--- a/lib/Target/ARM/ARMSubtarget.cpp
+++ b/lib/Target/ARM/ARMSubtarget.cpp
@@ -24,7 +24,6 @@ ARMSubtarget::ARMSubtarget(const Module &M, const std::string &FS,
, ARMFPUType(None)
, IsThumb(isThumb)
, ThumbMode(Thumb1)
- , UseThumbBacktraces(false)
, IsR9Reserved(false)
, stackAlignment(4)
, CPUString("generic")
@@ -83,8 +82,6 @@ ARMSubtarget::ARMSubtarget(const Module &M, const std::string &FS,
if (isAAPCS_ABI())
stackAlignment = 8;
- if (isTargetDarwin()) {
- UseThumbBacktraces = true;
+ if (isTargetDarwin())
IsR9Reserved = true;
- }
}
diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h
index 07040558d878..c3cc7fff6e3f 100644
--- a/lib/Target/ARM/ARMSubtarget.h
+++ b/lib/Target/ARM/ARMSubtarget.h
@@ -14,6 +14,7 @@
#ifndef ARMSUBTARGET_H
#define ARMSUBTARGET_H
+#include "llvm/Target/TargetInstrItineraries.h"
#include "llvm/Target/TargetSubtarget.h"
#include <string>
@@ -48,9 +49,6 @@ protected:
/// ThumbMode - Indicates supported Thumb version.
ThumbTypeEnum ThumbMode;
- /// UseThumbBacktraces - True if we use thumb style backtraces.
- bool UseThumbBacktraces;
-
/// IsR9Reserved - True if R9 is a not available as general purpose register.
bool IsR9Reserved;
@@ -61,6 +59,9 @@ protected:
/// CPUString - String name of used CPU.
std::string CPUString;
+ /// Selected instruction itineraries (one entry per itinerary class.)
+ InstrItineraryData InstrItins;
+
public:
enum {
isELF, isDarwin
@@ -106,14 +107,17 @@ protected:
bool isAAPCS_ABI() const { return TargetABI == ARM_ABI_AAPCS; }
bool isThumb() const { return IsThumb; }
- bool isThumb1() const { return IsThumb && (ThumbMode == Thumb1); }
- bool isThumb2() const { return IsThumb && (ThumbMode >= Thumb2); }
+ bool isThumb1Only() const { return IsThumb && (ThumbMode == Thumb1); }
+ bool hasThumb2() const { return IsThumb && (ThumbMode >= Thumb2); }
- bool useThumbBacktraces() const { return UseThumbBacktraces; }
bool isR9Reserved() const { return IsR9Reserved; }
const std::string & getCPUString() const { return CPUString; }
+ /// getInstrItins - Return the instruction itineraies based on subtarget
+ /// selection.
+ const InstrItineraryData &getInstrItineraryData() const { return InstrItins; }
+
/// getStackAlignment - Returns the minimum alignment known to hold of the
/// stack frame on entry to the function and which must be maintained by every
/// function for this subtarget.
diff --git a/lib/Target/ARM/ARMTargetAsmInfo.cpp b/lib/Target/ARM/ARMTargetAsmInfo.cpp
index 4107dccd2a69..42b8eae5e056 100644
--- a/lib/Target/ARM/ARMTargetAsmInfo.cpp
+++ b/lib/Target/ARM/ARMTargetAsmInfo.cpp
@@ -17,80 +17,42 @@
#include <cctype>
using namespace llvm;
-
const char *const llvm::arm_asm_table[] = {
- "{r0}", "r0",
- "{r1}", "r1",
- "{r2}", "r2",
- "{r3}", "r3",
- "{r4}", "r4",
- "{r5}", "r5",
- "{r6}", "r6",
- "{r7}", "r7",
- "{r8}", "r8",
- "{r9}", "r9",
- "{r10}", "r10",
- "{r11}", "r11",
- "{r12}", "r12",
- "{r13}", "r13",
- "{r14}", "r14",
- "{lr}", "lr",
- "{sp}", "sp",
- "{ip}", "ip",
- "{fp}", "fp",
- "{sl}", "sl",
- "{memory}", "memory",
- "{cc}", "cc",
- 0,0};
+ "{r0}", "r0",
+ "{r1}", "r1",
+ "{r2}", "r2",
+ "{r3}", "r3",
+ "{r4}", "r4",
+ "{r5}", "r5",
+ "{r6}", "r6",
+ "{r7}", "r7",
+ "{r8}", "r8",
+ "{r9}", "r9",
+ "{r10}", "r10",
+ "{r11}", "r11",
+ "{r12}", "r12",
+ "{r13}", "r13",
+ "{r14}", "r14",
+ "{lr}", "lr",
+ "{sp}", "sp",
+ "{ip}", "ip",
+ "{fp}", "fp",
+ "{sl}", "sl",
+ "{memory}", "memory",
+ "{cc}", "cc",
+ 0,0
+};
ARMDarwinTargetAsmInfo::ARMDarwinTargetAsmInfo(const ARMTargetMachine &TM):
ARMTargetAsmInfo<DarwinTargetAsmInfo>(TM) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
- GlobalPrefix = "_";
- PrivateGlobalPrefix = "L";
- LessPrivateGlobalPrefix = "l";
- StringConstantPrefix = "\1LC";
- BSSSection = 0; // no BSS section
ZeroDirective = "\t.space\t";
ZeroFillDirective = "\t.zerofill\t"; // Uses .zerofill
SetDirective = "\t.set\t";
- WeakRefDirective = "\t.weak_reference\t";
- WeakDefDirective = "\t.weak_definition ";
- HiddenDirective = "\t.private_extern\t";
ProtectedDirective = NULL;
- JumpTableDataSection = ".const";
- CStringSection = "\t.cstring";
HasDotTypeDotSizeDirective = false;
- HasSingleParameterDotFile = false;
- NeedsIndirectEncoding = true;
- if (TM.getRelocationModel() == Reloc::Static) {
- StaticCtorsSection = ".constructor";
- StaticDtorsSection = ".destructor";
- } else {
- StaticCtorsSection = ".mod_init_func";
- StaticDtorsSection = ".mod_term_func";
- }
-
- // In non-PIC modes, emit a special label before jump tables so that the
- // linker can perform more accurate dead code stripping.
- if (TM.getRelocationModel() != Reloc::PIC_) {
- // Emit a local label that is preserved until the linker runs.
- JumpTableSpecialLabelPrefix = "l";
- }
-
- NeedsSet = true;
- DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
- DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
- DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
- DwarfFrameSection = ".section __DWARF,__debug_frame,regular,debug";
- DwarfPubNamesSection = ".section __DWARF,__debug_pubnames,regular,debug";
- DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes,regular,debug";
- DwarfStrSection = ".section __DWARF,__debug_str,regular,debug";
- DwarfLocSection = ".section __DWARF,__debug_loc,regular,debug";
- DwarfARangesSection = ".section __DWARF,__debug_aranges,regular,debug";
- DwarfRangesSection = ".section __DWARF,__debug_ranges,regular,debug";
- DwarfMacInfoSection = ".section __DWARF,__debug_macinfo,regular,debug";
+ SupportsDebugInformation = true;
}
ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMTargetMachine &TM):
@@ -115,7 +77,7 @@ ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMTargetMachine &TM):
DwarfLocSection = "\t.section\t.debug_loc,\"\",%progbits";
DwarfARangesSection = "\t.section\t.debug_aranges,\"\",%progbits";
DwarfRangesSection = "\t.section\t.debug_ranges,\"\",%progbits";
- DwarfMacInfoSection = "\t.section\t.debug_macinfo,\"\",%progbits";
+ DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",%progbits";
if (Subtarget->isAAPCS_ABI()) {
StaticCtorsSection = "\t.section .init_array,\"aw\",%init_array";
@@ -124,6 +86,7 @@ ARMELFTargetAsmInfo::ARMELFTargetAsmInfo(const ARMTargetMachine &TM):
StaticCtorsSection = "\t.section .ctors,\"aw\",%progbits";
StaticDtorsSection = "\t.section .dtors,\"aw\",%progbits";
}
+ SupportsDebugInformation = true;
}
/// Count the number of comma-separated arguments.
diff --git a/lib/Target/ARM/ARMTargetAsmInfo.h b/lib/Target/ARM/ARMTargetAsmInfo.h
index 9e6f8568f76a..683692f00aab 100644
--- a/lib/Target/ARM/ARMTargetAsmInfo.h
+++ b/lib/Target/ARM/ARMTargetAsmInfo.h
@@ -26,8 +26,7 @@ namespace llvm {
template <class BaseTAI>
struct ARMTargetAsmInfo : public BaseTAI {
- explicit ARMTargetAsmInfo(const ARMTargetMachine &TM):
- BaseTAI(TM) {
+ explicit ARMTargetAsmInfo(const ARMTargetMachine &TM) : BaseTAI(TM) {
BaseTAI::AsmTransCBE = arm_asm_table;
BaseTAI::AlignmentIsInBytes = false;
diff --git a/lib/Target/ARM/ARMTargetMachine.cpp b/lib/Target/ARM/ARMTargetMachine.cpp
index 7033907bbb01..8006b9be32eb 100644
--- a/lib/Target/ARM/ARMTargetMachine.cpp
+++ b/lib/Target/ARM/ARMTargetMachine.cpp
@@ -23,9 +23,6 @@
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
-static cl::opt<bool>
-EnablePreLdStOpti("arm-pre-alloc-loadstore-opti", cl::Hidden,
- cl::desc("Enable pre-regalloc load store optimization pass"));
static cl::opt<bool> DisableLdStOpti("disable-arm-loadstore-opti", cl::Hidden,
cl::desc("Disable load store optimization pass"));
static cl::opt<bool> DisableIfConversion("disable-arm-if-conversion",cl::Hidden,
@@ -42,6 +39,11 @@ int ARMTargetMachineModule = 0;
static RegisterTarget<ARMTargetMachine> X("arm", "ARM");
static RegisterTarget<ThumbTargetMachine> Y("thumb", "Thumb");
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeARMTarget() { }
+}
+
// No assembler printer by default
ARMTargetMachine::AsmPrinterCtorFn ARMTargetMachine::AsmPrinterCtor = 0;
@@ -97,7 +99,8 @@ ARMTargetMachine::ARMTargetMachine(const Module &M, const std::string &FS,
InstrInfo(Subtarget),
FrameInfo(Subtarget),
JITInfo(),
- TLInfo(*this) {
+ TLInfo(*this),
+ InstrItins(Subtarget.getInstrItineraryData()) {
DefRelocModel = getRelocationModel();
}
@@ -149,8 +152,6 @@ bool ARMTargetMachine::addInstSelector(PassManagerBase &PM,
bool ARMTargetMachine::addPreRegAlloc(PassManagerBase &PM,
CodeGenOpt::Level OptLevel) {
- if (!EnablePreLdStOpti)
- return false;
// FIXME: temporarily disabling load / store optimization pass for Thumb mode.
if (OptLevel != CodeGenOpt::None && !DisableLdStOpti && !Subtarget.isThumb())
PM.add(createARMLoadStoreOptimizationPass(true));
diff --git a/lib/Target/ARM/ARMTargetMachine.h b/lib/Target/ARM/ARMTargetMachine.h
index 7192c1bb6184..c4c8e6c1d985 100644
--- a/lib/Target/ARM/ARMTargetMachine.h
+++ b/lib/Target/ARM/ARMTargetMachine.h
@@ -28,13 +28,14 @@ namespace llvm {
class Module;
class ARMTargetMachine : public LLVMTargetMachine {
- ARMSubtarget Subtarget;
- const TargetData DataLayout; // Calculates type size & alignment
- ARMInstrInfo InstrInfo;
- ARMFrameInfo FrameInfo;
- ARMJITInfo JITInfo;
- ARMTargetLowering TLInfo;
- Reloc::Model DefRelocModel; // Reloc model before it's overridden.
+ ARMSubtarget Subtarget;
+ const TargetData DataLayout; // Calculates type size & alignment
+ ARMInstrInfo InstrInfo;
+ ARMFrameInfo FrameInfo;
+ ARMJITInfo JITInfo;
+ ARMTargetLowering TLInfo;
+ InstrItineraryData InstrItins;
+ Reloc::Model DefRelocModel; // Reloc model before it's overridden.
protected:
// To avoid having target depend on the asmprinter stuff libraries, asmprinter
@@ -59,6 +60,9 @@ public:
virtual ARMTargetLowering *getTargetLowering() const {
return const_cast<ARMTargetLowering*>(&TLInfo);
}
+ virtual const InstrItineraryData getInstrItineraryData() const {
+ return InstrItins;
+ }
static void registerAsmPrinter(AsmPrinterCtorFn F) {
AsmPrinterCtor = F;
diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
index d908cf436313..948a10070d47 100644
--- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
+++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp
@@ -45,7 +45,6 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed");
namespace {
class VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
DwarfWriter *DW;
- MachineModuleInfo *MMI;
/// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
/// make the right decision when printing asm code for different targets.
@@ -84,7 +83,7 @@ namespace {
explicit ARMAsmPrinter(raw_ostream &O, TargetMachine &TM,
const TargetAsmInfo *T, CodeGenOpt::Level OL,
bool V)
- : AsmPrinter(O, TM, T, OL, V), DW(0), MMI(NULL), AFI(NULL), MCP(NULL),
+ : AsmPrinter(O, TM, T, OL, V), DW(0), AFI(NULL), MCP(NULL),
InCPMode(false) {
Subtarget = &TM.getSubtarget<ARMSubtarget>();
}
@@ -97,6 +96,7 @@ namespace {
const char *Modifier = 0);
void printSOImmOperand(const MachineInstr *MI, int opNum);
void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
+ void printSOOperand(const MachineInstr *MI, int OpNum);
void printSORegOperand(const MachineInstr *MI, int opNum);
void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
@@ -396,6 +396,28 @@ void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
printSOImm(O, ARM_AM::getSOImmVal(V2), VerboseAsm, TAI);
}
+// Constant shifts so_reg is a 3-operand unit corresponding to register forms of
+// the A5.1 "Addressing Mode 1 - Data-processing operands" forms. This
+// includes:
+// REG 0 - e.g. R5
+// REG IMM, SH_OPC - e.g. R5, LSL #3
+void ARMAsmPrinter::printSOOperand(const MachineInstr *MI, int OpNum) {
+ const MachineOperand &MO1 = MI->getOperand(OpNum);
+ const MachineOperand &MO2 = MI->getOperand(OpNum+1);
+
+ unsigned Reg = MO1.getReg();
+ assert(TargetRegisterInfo::isPhysicalRegister(Reg));
+ O << TM.getRegisterInfo()->getAsmName(Reg);
+
+ // Print the shift opc.
+ O << ", "
+ << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
+ << " ";
+
+ assert(MO2.isImm() && "Not a valid t2_so_reg value!");
+ O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
+}
+
// so_reg is a 4-operand unit corresponding to register forms of the A5.1
// "Addressing Mode 1 - Data-processing operands" forms. This includes:
// REG 0 0 - e.g. R5
@@ -805,17 +827,11 @@ void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
bool ARMAsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
-
- // Emit initial debug information.
- MMI = getAnalysisIfAvailable<MachineModuleInfo>();
- assert(MMI);
DW = getAnalysisIfAvailable<DwarfWriter>();
- assert(DW && "Dwarf Writer is not available");
- DW->BeginModule(&M, MMI, O, this, TAI);
- // Darwin wants symbols to be quoted if they have complex names.
- if (Subtarget->isTargetDarwin())
- Mang->setUseQuotes(true);
+ // Thumb-2 instructions are supported only in unified assembler syntax mode.
+ if (Subtarget->hasThumb2())
+ O << "\t.syntax unified\n";
// Emit ARM Build Attributes
if (Subtarget->isTargetELF()) {
@@ -1115,3 +1131,9 @@ namespace {
}
} Registrator;
}
+
+// Force static initialization when called from
+// llvm/InitializeAllAsmPrinters.h
+namespace llvm {
+ void InitializeARMAsmPrinter() { }
+}
diff --git a/lib/Target/Alpha/AlphaISelLowering.cpp b/lib/Target/Alpha/AlphaISelLowering.cpp
index 7ed8ef60302d..1be171353573 100644
--- a/lib/Target/Alpha/AlphaISelLowering.cpp
+++ b/lib/Target/Alpha/AlphaISelLowering.cpp
@@ -39,7 +39,7 @@ static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg,
AlphaTargetLowering::AlphaTargetLowering(TargetMachine &TM) : TargetLowering(TM) {
// Set up the TargetLowering object.
- //I am having problems with shr n ubyte 1
+ //I am having problems with shr n i8 1
setShiftAmountType(MVT::i64);
setBooleanContents(ZeroOrOneBooleanContent);
diff --git a/lib/Target/Alpha/AlphaTargetMachine.cpp b/lib/Target/Alpha/AlphaTargetMachine.cpp
index 4c830541f16a..cdd4fa4b2445 100644
--- a/lib/Target/Alpha/AlphaTargetMachine.cpp
+++ b/lib/Target/Alpha/AlphaTargetMachine.cpp
@@ -21,16 +21,17 @@
using namespace llvm;
-/// AlphaTargetMachineModule - Note that this is used on hosts that cannot link
-/// in a library unless there are references into the library. In particular,
-/// it seems that it is not possible to get things to work on Win32 without
-/// this. Though it is unused, do not remove it.
-extern "C" int AlphaTargetMachineModule;
-int AlphaTargetMachineModule = 0;
-
// Register the targets
static RegisterTarget<AlphaTargetMachine> X("alpha", "Alpha [experimental]");
+// No assembler printer by default
+AlphaTargetMachine::AsmPrinterCtorFn AlphaTargetMachine::AsmPrinterCtor = 0;
+
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeAlphaTarget() { }
+}
+
const TargetAsmInfo *AlphaTargetMachine::createTargetAsmInfo() const {
return new AlphaTargetAsmInfo(*this);
}
@@ -92,23 +93,32 @@ bool AlphaTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
bool Verbose,
raw_ostream &Out) {
PM.add(createAlphaLLRPPass(*this));
- PM.add(createAlphaCodePrinterPass(Out, *this, OptLevel, Verbose));
+ // Output assembly language.
+ assert(AsmPrinterCtor && "AsmPrinter was not linked in");
+ if (AsmPrinterCtor)
+ PM.add(AsmPrinterCtor(Out, *this, OptLevel, Verbose));
return false;
}
bool AlphaTargetMachine::addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool DumpAsm, MachineCodeEmitter &MCE) {
PM.add(createAlphaCodeEmitterPass(*this, MCE));
- if (DumpAsm)
- PM.add(createAlphaCodePrinterPass(errs(), *this, OptLevel, true));
+ if (DumpAsm) {
+ assert(AsmPrinterCtor && "AsmPrinter was not linked in");
+ if (AsmPrinterCtor)
+ PM.add(AsmPrinterCtor(errs(), *this, OptLevel, true));
+ }
return false;
}
bool AlphaTargetMachine::addCodeEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool DumpAsm, JITCodeEmitter &JCE) {
PM.add(createAlphaJITCodeEmitterPass(*this, JCE));
- if (DumpAsm)
- PM.add(createAlphaCodePrinterPass(errs(), *this, OptLevel, true));
+ if (DumpAsm) {
+ assert(AsmPrinterCtor && "AsmPrinter was not linked in");
+ if (AsmPrinterCtor)
+ PM.add(AsmPrinterCtor(errs(), *this, OptLevel, true));
+ }
return false;
}
bool AlphaTargetMachine::addSimpleCodeEmitter(PassManagerBase &PM,
diff --git a/lib/Target/Alpha/AlphaTargetMachine.h b/lib/Target/Alpha/AlphaTargetMachine.h
index 51224e80de70..946ca559ca04 100644
--- a/lib/Target/Alpha/AlphaTargetMachine.h
+++ b/lib/Target/Alpha/AlphaTargetMachine.h
@@ -33,10 +33,18 @@ class AlphaTargetMachine : public LLVMTargetMachine {
AlphaJITInfo JITInfo;
AlphaSubtarget Subtarget;
AlphaTargetLowering TLInfo;
-
+
protected:
virtual const TargetAsmInfo *createTargetAsmInfo() const;
-
+
+ // To avoid having target depend on the asmprinter stuff libraries, asmprinter
+ // set this functions to ctor pointer at startup time if they are linked in.
+ typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
+ TargetMachine &tm,
+ CodeGenOpt::Level OptLevel,
+ bool verbose);
+ static AsmPrinterCtorFn AsmPrinterCtor;
+
public:
AlphaTargetMachine(const Module &M, const std::string &FS);
@@ -46,7 +54,7 @@ public:
virtual const AlphaRegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
}
- virtual AlphaTargetLowering* getTargetLowering() const {
+ virtual AlphaTargetLowering* getTargetLowering() const {
return const_cast<AlphaTargetLowering*>(&TLInfo);
}
virtual const TargetData *getTargetData() const { return &DataLayout; }
@@ -56,7 +64,7 @@ public:
static unsigned getJITMatchQuality();
static unsigned getModuleMatchQuality(const Module &M);
-
+
// Pass Pipeline Configuration
virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
@@ -75,6 +83,10 @@ public:
CodeGenOpt::Level OptLevel,
bool DumpAsm,
JITCodeEmitter &JCE);
+
+ static void registerAsmPrinter(AsmPrinterCtorFn F) {
+ AsmPrinterCtor = F;
+ }
};
} // end namespace llvm
diff --git a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
index 74b48ee66235..7b73bb302c38 100644
--- a/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
+++ b/lib/Target/Alpha/AsmPrinter/AlphaAsmPrinter.cpp
@@ -303,3 +303,17 @@ bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
O << ")";
return false;
}
+
+// Force static initialization when called from
+// llvm/InitializeAllAsmPrinters.h
+namespace llvm {
+ void InitializeAlphaAsmPrinter() { }
+}
+
+namespace {
+ static struct Register {
+ Register() {
+ AlphaTargetMachine::registerAsmPrinter(createAlphaCodePrinterPass);
+ }
+ } Registrator;
+}
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 5814d2750edc..c3554f6b5734 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -59,6 +59,11 @@ int CBackendTargetMachineModule = 0;
// Register the target.
static RegisterTarget<CTargetMachine> X("c", "C backend");
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeCBackendTarget() { }
+}
+
namespace {
/// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for
/// any unnamed structure types that are used by the program, and merges
@@ -1449,6 +1454,17 @@ std::string CWriter::GetValueName(const Value *Operand) {
/// writeInstComputationInline - Emit the computation for the specified
/// instruction inline, with no destination provided.
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::Int1Ty && Ty!=Type::Int8Ty &&
+ Ty!=Type::Int16Ty && Ty!=Type::Int32Ty && Ty!=Type::Int64Ty)) {
+ cerr << "The C backend does not currently support integer "
+ << "types of widths other than 1, 8, 16, 32, 64.\n";
+ cerr << "This is being tracked as PR 4158.\n";
+ abort();
+ }
+
// If this is a non-trivial bool computation, make sure to truncate down to
// a 1 bit value. This is important because we want "add i1 x, y" to return
// "0" when x and y are true, not "2" for example.
diff --git a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
index da1bf074de96..26a8ece21cf7 100644
--- a/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
+++ b/lib/Target/CellSPU/AsmPrinter/SPUAsmPrinter.cpp
@@ -287,12 +287,11 @@ namespace {
/// LinuxAsmPrinter - SPU assembly printer, customized for Linux
class VISIBILITY_HIDDEN LinuxAsmPrinter : public SPUAsmPrinter {
DwarfWriter *DW;
- MachineModuleInfo *MMI;
public:
explicit LinuxAsmPrinter(raw_ostream &O, SPUTargetMachine &TM,
const TargetAsmInfo *T, CodeGenOpt::Level F,
bool V)
- : SPUAsmPrinter(O, TM, T, F, V), DW(0), MMI(0) {}
+ : SPUAsmPrinter(O, TM, T, F, V), DW(0) {}
virtual const char *getPassName() const {
return "STI CBEA SPU Assembly Printer";
@@ -490,12 +489,8 @@ LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
bool LinuxAsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
- SwitchToTextSection("\t.text");
- // Emit initial debug information.
DW = getAnalysisIfAvailable<DwarfWriter>();
- assert(DW && "Dwarf Writer is not available");
- MMI = getAnalysisIfAvailable<MachineModuleInfo>();
- DW->BeginModule(&M, MMI, O, this, TAI);
+ SwitchToTextSection("\t.text");
return Result;
}
@@ -621,3 +616,17 @@ FunctionPass *llvm::createSPUAsmPrinterPass(raw_ostream &o,
bool verbose) {
return new LinuxAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
}
+
+// Force static initialization when called from
+// llvm/InitializeAllAsmPrinters.h
+namespace llvm {
+ void InitializeCellSPUAsmPrinter() { }
+}
+
+namespace {
+ static struct Register {
+ Register() {
+ SPUTargetMachine::registerAsmPrinter(createSPUAsmPrinterPass);
+ }
+ } Registrator;
+}
diff --git a/lib/Target/CellSPU/SPUISelLowering.cpp b/lib/Target/CellSPU/SPUISelLowering.cpp
index 864a914bba78..b28644378bda 100644
--- a/lib/Target/CellSPU/SPUISelLowering.cpp
+++ b/lib/Target/CellSPU/SPUISelLowering.cpp
@@ -249,6 +249,25 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
setOperationAction(ISD::MUL, MVT::i32, Legal);
setOperationAction(ISD::MUL, MVT::i64, Legal);
+ // Expand double-width multiplication
+ // FIXME: It would probably be reasonable to support some of these operations
+ setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand);
+ setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand);
+ setOperationAction(ISD::MULHU, MVT::i8, Expand);
+ setOperationAction(ISD::MULHS, MVT::i8, Expand);
+ setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand);
+ setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand);
+ setOperationAction(ISD::MULHU, MVT::i16, Expand);
+ setOperationAction(ISD::MULHS, MVT::i16, Expand);
+ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand);
+ setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand);
+ setOperationAction(ISD::MULHU, MVT::i32, Expand);
+ setOperationAction(ISD::MULHS, MVT::i32, Expand);
+ setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
+ setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
+ setOperationAction(ISD::MULHU, MVT::i64, Expand);
+ setOperationAction(ISD::MULHS, MVT::i64, Expand);
+
// Need to custom handle (some) common i8, i64 math ops
setOperationAction(ISD::ADD, MVT::i8, Custom);
setOperationAction(ISD::ADD, MVT::i64, Legal);
diff --git a/lib/Target/CellSPU/SPUTargetAsmInfo.cpp b/lib/Target/CellSPU/SPUTargetAsmInfo.cpp
index ff88ed810716..2868ff7592c2 100644
--- a/lib/Target/CellSPU/SPUTargetAsmInfo.cpp
+++ b/lib/Target/CellSPU/SPUTargetAsmInfo.cpp
@@ -41,7 +41,6 @@ SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) :
SupportsDebugInformation = true;
NeedsSet = true;
- SupportsMacInfoSection = false;
DwarfAbbrevSection = "\t.section .debug_abbrev,\"\",@progbits";
DwarfInfoSection = "\t.section .debug_info,\"\",@progbits";
DwarfLineSection = "\t.section .debug_line,\"\",@progbits";
@@ -52,7 +51,7 @@ SPULinuxTargetAsmInfo::SPULinuxTargetAsmInfo(const SPUTargetMachine &TM) :
DwarfLocSection = "\t.section .debug_loc,\"\",@progbits";
DwarfARangesSection = "\t.section .debug_aranges,\"\",@progbits";
DwarfRangesSection = "\t.section .debug_ranges,\"\",@progbits";
- DwarfMacInfoSection = "\t.section .debug_macinfo,\"\",progbits";
+ DwarfMacroInfoSection = 0; // macro info not supported.
// Exception handling is not supported on CellSPU (think about it: you only
// have 256K for code+data. Would you support exception handling?)
diff --git a/lib/Target/CellSPU/SPUTargetMachine.cpp b/lib/Target/CellSPU/SPUTargetMachine.cpp
index 7fa902243c7b..c675ebb09a61 100644
--- a/lib/Target/CellSPU/SPUTargetMachine.cpp
+++ b/lib/Target/CellSPU/SPUTargetMachine.cpp
@@ -23,20 +23,20 @@
using namespace llvm;
-/// CellSPUTargetMachineModule - Note that this is used on hosts that
-/// cannot link in a library unless there are references into the
-/// library. In particular, it seems that it is not possible to get
-/// things to work on Win32 without this. Though it is unused, do not
-/// remove it.
-extern "C" int CellSPUTargetMachineModule;
-int CellSPUTargetMachineModule = 0;
-
namespace {
// Register the targets
RegisterTarget<SPUTargetMachine>
CELLSPU("cellspu", "STI CBEA Cell SPU [experimental]");
}
+// No assembler printer by default
+SPUTargetMachine::AsmPrinterCtorFn SPUTargetMachine::AsmPrinterCtor = 0;
+
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeCellSPUTarget() { }
+}
+
const std::pair<unsigned, int> *
SPUFrameInfo::getCalleeSaveSpillSlots(unsigned &NumEntries) const {
NumEntries = 1;
@@ -93,6 +93,9 @@ bool SPUTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool Verbose,
raw_ostream &Out) {
- PM.add(createSPUAsmPrinterPass(Out, *this, OptLevel, Verbose));
+ // Output assembly language.
+ assert(AsmPrinterCtor && "AsmPrinter was not linked in");
+ if (AsmPrinterCtor)
+ PM.add(AsmPrinterCtor(Out, *this, OptLevel, Verbose));
return false;
}
diff --git a/lib/Target/CellSPU/SPUTargetMachine.h b/lib/Target/CellSPU/SPUTargetMachine.h
index cd3920333851..d8fe3000d980 100644
--- a/lib/Target/CellSPU/SPUTargetMachine.h
+++ b/lib/Target/CellSPU/SPUTargetMachine.h
@@ -35,10 +35,18 @@ class SPUTargetMachine : public LLVMTargetMachine {
SPUFrameInfo FrameInfo;
SPUTargetLowering TLInfo;
InstrItineraryData InstrItins;
-
+
protected:
virtual const TargetAsmInfo *createTargetAsmInfo() const;
-
+
+ // To avoid having target depend on the asmprinter stuff libraries, asmprinter
+ // set this functions to ctor pointer at startup time if they are linked in.
+ typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
+ SPUTargetMachine &tm,
+ CodeGenOpt::Level OptLevel,
+ bool verbose);
+ static AsmPrinterCtorFn AsmPrinterCtor;
+
public:
SPUTargetMachine(const Module &M, const std::string &FS);
@@ -78,7 +86,7 @@ public:
return &DataLayout;
}
- virtual const InstrItineraryData getInstrItineraryData() const {
+ virtual const InstrItineraryData getInstrItineraryData() const {
return InstrItins;
}
@@ -88,6 +96,10 @@ public:
virtual bool addAssemblyEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool Verbose, raw_ostream &Out);
+
+ static void registerAsmPrinter(AsmPrinterCtorFn F) {
+ AsmPrinterCtor = F;
+ }
};
} // end namespace llvm
diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp
index 04a6829d9cf6..1feea96e3d9d 100644
--- a/lib/Target/CppBackend/CPPBackend.cpp
+++ b/lib/Target/CppBackend/CPPBackend.cpp
@@ -82,6 +82,11 @@ int CppBackendTargetMachineModule = 0;
// Register the target.
static RegisterTarget<CPPTargetMachine> X("cpp", "C++ backend");
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeCppBackendTarget() { }
+}
+
namespace {
typedef std::vector<const Type*> TypeList;
typedef std::map<const Type*,std::string> TypeMap;
diff --git a/lib/Target/DarwinTargetAsmInfo.cpp b/lib/Target/DarwinTargetAsmInfo.cpp
index 05d235177642..d7d675abf255 100644
--- a/lib/Target/DarwinTargetAsmInfo.cpp
+++ b/lib/Target/DarwinTargetAsmInfo.cpp
@@ -50,6 +50,53 @@ DarwinTargetAsmInfo::DarwinTargetAsmInfo(const TargetMachine &TM)
ConstDataSection = getUnnamedSection(".const_data", SectionFlags::None);
DataCoalSection = getNamedSection("\t__DATA,__datacoal_nt,coalesced",
SectionFlags::Writeable);
+
+
+ // Common settings for all Darwin targets.
+ // Syntax:
+ GlobalPrefix = "_";
+ PrivateGlobalPrefix = "L";
+ LessPrivateGlobalPrefix = "l"; // Marker for some ObjC metadata
+ StringConstantPrefix = "\1LC";
+ NeedsSet = true;
+ NeedsIndirectEncoding = true;
+ AllowQuotesInName = true;
+ HasSingleParameterDotFile = false;
+
+ // In non-PIC modes, emit a special label before jump tables so that the
+ // linker can perform more accurate dead code stripping. We do not check the
+ // relocation model here since it can be overridden later.
+ JumpTableSpecialLabelPrefix = "l";
+
+ // Directives:
+ WeakDefDirective = "\t.weak_definition ";
+ WeakRefDirective = "\t.weak_reference ";
+ HiddenDirective = "\t.private_extern ";
+
+ // Sections:
+ CStringSection = "\t.cstring";
+ JumpTableDataSection = "\t.const\n";
+ BSSSection = 0;
+
+ if (TM.getRelocationModel() == Reloc::Static) {
+ StaticCtorsSection = ".constructor";
+ StaticDtorsSection = ".destructor";
+ } else {
+ StaticCtorsSection = ".mod_init_func";
+ StaticDtorsSection = ".mod_term_func";
+ }
+
+ DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
+ DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
+ DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
+ DwarfFrameSection = ".section __DWARF,__debug_frame,regular,debug";
+ DwarfPubNamesSection = ".section __DWARF,__debug_pubnames,regular,debug";
+ DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes,regular,debug";
+ DwarfStrSection = ".section __DWARF,__debug_str,regular,debug";
+ DwarfLocSection = ".section __DWARF,__debug_loc,regular,debug";
+ DwarfARangesSection = ".section __DWARF,__debug_aranges,regular,debug";
+ DwarfRangesSection = ".section __DWARF,__debug_ranges,regular,debug";
+ DwarfMacroInfoSection = ".section __DWARF,__debug_macinfo,regular,debug";
}
/// emitUsedDirectiveFor - On Darwin, internally linked data beginning with
diff --git a/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp b/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp
index fc54e23a44d7..662c667037fc 100644
--- a/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp
+++ b/lib/Target/IA64/AsmPrinter/IA64AsmPrinter.cpp
@@ -374,3 +374,18 @@ FunctionPass *llvm::createIA64CodePrinterPass(raw_ostream &o,
bool verbose) {
return new IA64AsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
}
+
+namespace {
+ static struct Register {
+ Register() {
+ IA64TargetMachine::registerAsmPrinter(createIA64CodePrinterPass);
+ }
+ } Registrator;
+}
+
+
+// Force static initialization when called from
+// llvm/InitializeAllAsmPrinters.h
+namespace llvm {
+ void InitializeIA64AsmPrinter() { }
+}
diff --git a/lib/Target/IA64/IA64ISelLowering.cpp b/lib/Target/IA64/IA64ISelLowering.cpp
index 34a0686564c0..c545b9c0eb1f 100644
--- a/lib/Target/IA64/IA64ISelLowering.cpp
+++ b/lib/Target/IA64/IA64ISelLowering.cpp
@@ -107,6 +107,10 @@ IA64TargetLowering::IA64TargetLowering(TargetMachine &TM)
// VASTART needs to be custom lowered to use the VarArgsFrameIndex
setOperationAction(ISD::VAARG , MVT::Other, Custom);
setOperationAction(ISD::VASTART , MVT::Other, Custom);
+
+ // FIXME: These should be legal
+ setOperationAction(ISD::BIT_CONVERT, MVT::i64, Expand);
+ setOperationAction(ISD::BIT_CONVERT, MVT::f64, Expand);
// Use the default implementation.
setOperationAction(ISD::VACOPY , MVT::Other, Expand);
diff --git a/lib/Target/IA64/IA64TargetMachine.cpp b/lib/Target/IA64/IA64TargetMachine.cpp
index 878a00a44518..0b93ee5c4ae8 100644
--- a/lib/Target/IA64/IA64TargetMachine.cpp
+++ b/lib/Target/IA64/IA64TargetMachine.cpp
@@ -19,16 +19,18 @@
#include "llvm/Target/TargetMachineRegistry.h"
using namespace llvm;
-/// IA64TargetMachineModule - Note that this is used on hosts that cannot link
-/// in a library unless there are references into the library. In particular,
-/// it seems that it is not possible to get things to work on Win32 without
-/// this. Though it is unused, do not remove it.
-extern "C" int IA64TargetMachineModule;
-int IA64TargetMachineModule = 0;
-
-static RegisterTarget<IA64TargetMachine> X("ia64",
+// Register the target
+static RegisterTarget<IA64TargetMachine> X("ia64",
"IA-64 (Itanium) [experimental]");
+// No assembler printer by default
+IA64TargetMachine::AsmPrinterCtorFn IA64TargetMachine::AsmPrinterCtor = 0;
+
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeIA64Target() { }
+}
+
const TargetAsmInfo *IA64TargetMachine::createTargetAsmInfo() const {
return new IA64TargetAsmInfo(*this);
}
@@ -88,7 +90,10 @@ bool IA64TargetMachine::addAssemblyEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool Verbose,
raw_ostream &Out) {
- PM.add(createIA64CodePrinterPass(Out, *this, OptLevel, Verbose));
+ // Output assembly language.
+ assert(AsmPrinterCtor && "AsmPrinter was not linked in");
+ if (AsmPrinterCtor)
+ PM.add(AsmPrinterCtor(Out, *this, OptLevel, Verbose));
return false;
}
diff --git a/lib/Target/IA64/IA64TargetMachine.h b/lib/Target/IA64/IA64TargetMachine.h
index 29d625ce673a..a64da9fca2b8 100644
--- a/lib/Target/IA64/IA64TargetMachine.h
+++ b/lib/Target/IA64/IA64TargetMachine.h
@@ -30,24 +30,32 @@ class IA64TargetMachine : public LLVMTargetMachine {
TargetFrameInfo FrameInfo;
//IA64JITInfo JITInfo;
IA64TargetLowering TLInfo;
-
+
protected:
virtual const TargetAsmInfo *createTargetAsmInfo() const;
+ // To avoid having target depend on the asmprinter stuff libraries, asmprinter
+ // set this functions to ctor pointer at startup time if they are linked in.
+ typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
+ IA64TargetMachine &tm,
+ CodeGenOpt::Level OptLevel,
+ bool verbose);
+ static AsmPrinterCtorFn AsmPrinterCtor;
+
public:
IA64TargetMachine(const Module &M, const std::string &FS);
virtual const IA64InstrInfo *getInstrInfo() const { return &InstrInfo; }
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
virtual const IA64Subtarget *getSubtargetImpl() const { return &Subtarget; }
- virtual IA64TargetLowering *getTargetLowering() const {
+ virtual IA64TargetLowering *getTargetLowering() const {
return const_cast<IA64TargetLowering*>(&TLInfo);
}
virtual const IA64RegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
}
virtual const TargetData *getTargetData() const { return &DataLayout; }
-
+
static unsigned getModuleMatchQuality(const Module &M);
// Pass Pipeline Configuration
@@ -56,6 +64,10 @@ public:
virtual bool addAssemblyEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool Verbose, raw_ostream &Out);
+
+ static void registerAsmPrinter(AsmPrinterCtorFn F) {
+ AsmPrinterCtor = F;
+ }
};
} // End llvm namespace
diff --git a/lib/Target/MSIL/MSILWriter.cpp b/lib/Target/MSIL/MSILWriter.cpp
index 37e5b1eccde4..0aff14fee26c 100644
--- a/lib/Target/MSIL/MSILWriter.cpp
+++ b/lib/Target/MSIL/MSILWriter.cpp
@@ -55,6 +55,11 @@ int MSILTargetMachineModule = 0;
static RegisterTarget<MSILTarget> X("msil", "MSIL backend");
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeMSILTarget() { }
+}
+
bool MSILModule::runOnModule(Module &M) {
ModulePtr = &M;
TD = &getAnalysis<TargetData>();
diff --git a/lib/Target/MSP430/MSP430TargetMachine.cpp b/lib/Target/MSP430/MSP430TargetMachine.cpp
index 78869463f3a2..0f5244d666fc 100644
--- a/lib/Target/MSP430/MSP430TargetMachine.cpp
+++ b/lib/Target/MSP430/MSP430TargetMachine.cpp
@@ -35,6 +35,11 @@ int MSP430TargetMachineModule = 0;
static RegisterTarget<MSP430TargetMachine>
X("msp430", "MSP430 [experimental]");
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeMSP430Target() { }
+}
+
MSP430TargetMachine::MSP430TargetMachine(const Module &M,
const std::string &FS) :
Subtarget(*this, M, FS),
diff --git a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
index dfb62382e75d..077ec96d17b7 100644
--- a/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/AsmPrinter/MipsAsmPrinter.cpp
@@ -578,3 +578,17 @@ doFinalization(Module &M)
return AsmPrinter::doFinalization(M);
}
+
+namespace {
+ static struct Register {
+ Register() {
+ MipsTargetMachine::registerAsmPrinter(createMipsCodePrinterPass);
+ }
+ } Registrator;
+}
+
+// Force static initialization when called from
+// llvm/InitializeAllAsmPrinters.h
+namespace llvm {
+ void InitializeMipsAsmPrinter() { }
+}
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 4517cfc96a43..42afcebabec7 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -95,6 +95,7 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::SELECT, MVT::f32, Custom);
+ setOperationAction(ISD::SELECT, MVT::f64, Custom);
setOperationAction(ISD::SELECT, MVT::i32, Custom);
setOperationAction(ISD::SETCC, MVT::f32, Custom);
setOperationAction(ISD::SETCC, MVT::f64, Custom);
@@ -122,6 +123,7 @@ MipsTargetLowering(MipsTargetMachine &TM): TargetLowering(TM)
setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand);
setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand);
setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand);
+ setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand);
// We don't have line number support yet.
setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand);
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index ef524e3ecd72..83b9b62e8ee8 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -31,6 +31,14 @@ int MipsTargetMachineModule = 0;
static RegisterTarget<MipsTargetMachine> X("mips", "Mips");
static RegisterTarget<MipselTargetMachine> Y("mipsel", "Mipsel");
+MipsTargetMachine::AsmPrinterCtorFn MipsTargetMachine::AsmPrinterCtor = 0;
+
+
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeMipsTarget() { }
+}
+
const TargetAsmInfo *MipsTargetMachine::
createTargetAsmInfo() const
{
@@ -125,9 +133,9 @@ addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel)
// true if AssemblyEmitter is supported
bool MipsTargetMachine::
addAssemblyEmitter(PassManagerBase &PM, CodeGenOpt::Level OptLevel,
- bool Verbose, raw_ostream &Out)
-{
+ bool Verbose, raw_ostream &Out) {
// Output assembly language.
- PM.add(createMipsCodePrinterPass(Out, *this, OptLevel, Verbose));
+ assert(AsmPrinterCtor && "AsmPrinter was not linked in");
+ PM.add(AsmPrinterCtor(Out, *this, OptLevel, Verbose));
return false;
}
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index a9e1df27ae7f..85fafadde7c4 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -33,10 +33,23 @@ namespace llvm {
protected:
virtual const TargetAsmInfo *createTargetAsmInfo() const;
-
+ protected:
+ // To avoid having target depend on the asmprinter stuff libraries,
+ // asmprinter set this functions to ctor pointer at startup time if they are
+ // linked in.
+ typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
+ MipsTargetMachine &tm,
+ CodeGenOpt::Level OptLevel,
+ bool verbose);
+ static AsmPrinterCtorFn AsmPrinterCtor;
+
public:
MipsTargetMachine(const Module &M, const std::string &FS, bool isLittle);
+ static void registerAsmPrinter(AsmPrinterCtorFn F) {
+ AsmPrinterCtor = F;
+ }
+
virtual const MipsInstrInfo *getInstrInfo() const
{ return &InstrInfo; }
virtual const TargetFrameInfo *getFrameInfo() const
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp
index f9a880126500..ca1089b6df08 100644
--- a/lib/Target/PIC16/PIC16AsmPrinter.cpp
+++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp
@@ -48,27 +48,10 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
const Function *F = MF.getFunction();
CurrentFnName = Mang->getValueName(F);
- // Iterate over the first basic block instructions to find if it has a
- // DebugLoc. If so emit .file directive. Instructions such as movlw do not
- // have valid DebugLoc, so need to iterate over instructions.
- MachineFunction::const_iterator I = MF.begin();
- for (MachineBasicBlock::const_iterator MBBI = I->begin(), E = I->end();
- MBBI != E; MBBI++) {
- const DebugLoc DLoc = MBBI->getDebugLoc();
- if (!DLoc.isUnknown()) {
- GlobalVariable *CU = MF.getDebugLocTuple(DLoc).CompileUnit;
- unsigned line = MF.getDebugLocTuple(DLoc).Line;
- DbgInfo.EmitFileDirective(CU);
- DbgInfo.SetFunctBeginLine(line);
- break;
- }
- }
-
// Emit the function frame (args and temps).
EmitFunctionFrame(MF);
- // Emit function begin debug directive.
- DbgInfo.EmitFunctBeginDI(F);
+ DbgInfo.BeginFunction(MF);
// Emit the autos section of function.
EmitAutos(CurrentFnName);
@@ -89,9 +72,7 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Emit function start label.
O << CurrentFnName << ":\n";
- // For emitting line directives, we need to keep track of the current
- // source line. When it changes then only emit the line directive.
- unsigned CurLine = 0;
+ DebugLoc CurDL;
O << "\n";
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
@@ -109,12 +90,9 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
// Emit the line directive if source line changed.
const DebugLoc DL = II->getDebugLoc();
- if (!DL.isUnknown()) {
- unsigned line = MF.getDebugLocTuple(DL).Line;
- if (line != CurLine) {
- O << "\t.line " << line << "\n";
- CurLine = line;
- }
+ if (!DL.isUnknown() && DL != CurDL) {
+ DbgInfo.ChangeDebugLoc(MF, DL);
+ CurDL = DL;
}
// Print the assembly for the instruction.
@@ -123,7 +101,7 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
}
// Emit function end debug directives.
- DbgInfo.EmitFunctEndDI(F, CurLine);
+ DbgInfo.EndFunction(MF);
return false; // we didn't modify anything.
}
@@ -226,7 +204,7 @@ bool PIC16AsmPrinter::doInitialization (Module &M) {
I->setSection(TAI->SectionForGlobal(I)->getName());
}
- DbgInfo.Init(M);
+ DbgInfo.BeginModule(M);
EmitFunctionDecls(M);
EmitUndefinedVars(M);
EmitDefinedVars(M);
@@ -313,8 +291,7 @@ void PIC16AsmPrinter::EmitRomData (Module &M)
bool PIC16AsmPrinter::doFinalization(Module &M) {
printLibcallDecls();
EmitRemainingAutos();
- DbgInfo.EmitVarDebugInfo(M);
- DbgInfo.EmitEOF();
+ DbgInfo.EndModule(M);
O << "\n\t" << "END\n";
bool Result = AsmPrinter::doFinalization(M);
return Result;
diff --git a/lib/Target/PIC16/PIC16AsmPrinter.h b/lib/Target/PIC16/PIC16AsmPrinter.h
index 8bdcf7258efa..3ec565965496 100644
--- a/lib/Target/PIC16/PIC16AsmPrinter.h
+++ b/lib/Target/PIC16/PIC16AsmPrinter.h
@@ -32,7 +32,7 @@ namespace llvm {
explicit PIC16AsmPrinter(raw_ostream &O, PIC16TargetMachine &TM,
const TargetAsmInfo *T, CodeGenOpt::Level OL,
bool V)
- : AsmPrinter(O, TM, T, OL, V), DbgInfo(O,T) {
+ : AsmPrinter(O, TM, T, OL, V), DbgInfo(O, T) {
PTLI = TM.getTargetLowering();
PTAI = static_cast<const PIC16TargetAsmInfo *> (T);
}
diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp
index d7ebea7fa9db..27551cd13d84 100644
--- a/lib/Target/PIC16/PIC16DebugInfo.cpp
+++ b/lib/Target/PIC16/PIC16DebugInfo.cpp
@@ -14,91 +14,23 @@
#include "PIC16.h"
#include "PIC16DebugInfo.h"
#include "llvm/GlobalVariable.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/Support/DebugLoc.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
-void PIC16DbgInfo::PopulateDebugInfo(DIType Ty, unsigned short &TypeNo,
- bool &HasAux, int Aux[],
- std::string &TypeName) {
- if (Ty.isBasicType(Ty.getTag())) {
- std::string Name = "";
- Ty.getName(Name);
- unsigned short BaseTy = GetTypeDebugNumber(Name);
- TypeNo = TypeNo << PIC16Dbg::S_BASIC;
- TypeNo = TypeNo | (0xffff & BaseTy);
- }
- else if (Ty.isDerivedType(Ty.getTag())) {
- switch(Ty.getTag())
- {
- case dwarf::DW_TAG_pointer_type:
- TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
- TypeNo = TypeNo | PIC16Dbg::DT_PTR;
- break;
- default:
- TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
- }
- DIType BaseType = DIDerivedType(Ty.getGV()).getTypeDerivedFrom();
- PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TypeName);
- }
- else if (Ty.isCompositeType(Ty.getTag())) {
- switch (Ty.getTag()) {
- case dwarf::DW_TAG_array_type: {
- DICompositeType CTy = DICompositeType(Ty.getGV());
- DIArray Elements = CTy.getTypeArray();
- unsigned short size = 1;
- unsigned short Dimension[4]={0,0,0,0};
- for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
- DIDescriptor Element = Elements.getElement(i);
- if (Element.getTag() == dwarf::DW_TAG_subrange_type) {
- TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
- TypeNo = TypeNo | PIC16Dbg::DT_ARY;
- DISubrange SubRange = DISubrange(Element.getGV());
- Dimension[i] = SubRange.getHi() - SubRange.getLo() + 1;
- // Each dimension is represented by 2 bytes starting at byte 9.
- Aux[8+i*2+0] = Dimension[i];
- Aux[8+i*2+1] = Dimension[i] >> 8;
- size = size * Dimension[i];
- }
- }
- HasAux = true;
- // In auxillary entry for array, 7th and 8th byte represent array size.
- Aux[6] = size & 0xff;
- Aux[7] = size >> 8;
- DIType BaseType = CTy.getTypeDerivedFrom();
- PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TypeName);
-
- break;
- }
- case dwarf:: DW_TAG_union_type:
- case dwarf::DW_TAG_structure_type: {
- DICompositeType CTy = DICompositeType(Ty.getGV());
- TypeNo = TypeNo << PIC16Dbg::S_BASIC;
- if (Ty.getTag() == dwarf::DW_TAG_structure_type)
- TypeNo = TypeNo | PIC16Dbg::T_STRUCT;
- else
- TypeNo = TypeNo | PIC16Dbg::T_UNION;
- CTy.getName(TypeName);
- // UniqueSuffix is .number where number is obtained from
- // llvm.dbg.composite<number>.
- std::string UniqueSuffix = "." + Ty.getGV()->getName().substr(18);
- TypeName += UniqueSuffix;
- unsigned short size = CTy.getSizeInBits()/8;
- // 7th and 8th byte represent size.
- HasAux = true;
- Aux[6] = size & 0xff;
- Aux[7] = size >> 8;
- break;
- }
- case dwarf::DW_TAG_enumeration_type: {
- TypeNo = TypeNo << PIC16Dbg::S_BASIC;
- TypeNo = TypeNo | PIC16Dbg::T_ENUM;
- break;
- }
- default:
- TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
- }
- }
+/// PopulateDebugInfo - Populate the TypeNo, Aux[] and TagName from Ty.
+///
+void PIC16DbgInfo::PopulateDebugInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+ if (Ty.isBasicType(Ty.getTag()))
+ PopulateBasicTypeInfo (Ty, TypeNo);
+ else if (Ty.isDerivedType(Ty.getTag()))
+ PopulateDerivedTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
+ else if (Ty.isCompositeType(Ty.getTag()))
+ PopulateCompositeTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
else {
TypeNo = PIC16Dbg::T_NULL;
HasAux = false;
@@ -106,7 +38,127 @@ void PIC16DbgInfo::PopulateDebugInfo(DIType Ty, unsigned short &TypeNo,
return;
}
+/// PopulateBasicTypeInfo- Populate TypeNo for basic type from Ty.
+///
+void PIC16DbgInfo::PopulateBasicTypeInfo (DIType Ty, unsigned short &TypeNo) {
+ std::string Name = "";
+ Ty.getName(Name);
+ unsigned short BaseTy = GetTypeDebugNumber(Name);
+ TypeNo = TypeNo << PIC16Dbg::S_BASIC;
+ TypeNo = TypeNo | (0xffff & BaseTy);
+}
+
+/// PopulateDerivedTypeInfo - Populate TypeNo, Aux[], TagName for derived type
+/// from Ty. Derived types are mostly pointers.
+///
+void PIC16DbgInfo::PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+
+ switch(Ty.getTag())
+ {
+ case dwarf::DW_TAG_pointer_type:
+ TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
+ TypeNo = TypeNo | PIC16Dbg::DT_PTR;
+ break;
+ default:
+ TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
+ }
+
+ // We also need to encode the the information about the base type of
+ // pointer in TypeNo.
+ DIType BaseType = DIDerivedType(Ty.getGV()).getTypeDerivedFrom();
+ PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName);
+}
+
+/// PopulateArrayTypeInfo - Populate TypeNo, Aux[] for array from Ty.
+void PIC16DbgInfo::PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+ DICompositeType CTy = DICompositeType(Ty.getGV());
+ DIArray Elements = CTy.getTypeArray();
+ unsigned short size = 1;
+ unsigned short Dimension[4]={0,0,0,0};
+ for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
+ DIDescriptor Element = Elements.getElement(i);
+ if (Element.getTag() == dwarf::DW_TAG_subrange_type) {
+ TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
+ TypeNo = TypeNo | PIC16Dbg::DT_ARY;
+ DISubrange SubRange = DISubrange(Element.getGV());
+ Dimension[i] = SubRange.getHi() - SubRange.getLo() + 1;
+ // Each dimension is represented by 2 bytes starting at byte 9.
+ Aux[8+i*2+0] = Dimension[i];
+ Aux[8+i*2+1] = Dimension[i] >> 8;
+ size = size * Dimension[i];
+ }
+ }
+ HasAux = true;
+ // In auxillary entry for array, 7th and 8th byte represent array size.
+ Aux[6] = size & 0xff;
+ Aux[7] = size >> 8;
+ DIType BaseType = CTy.getTypeDerivedFrom();
+ PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName);
+}
+
+/// PopulateStructOrUnionTypeInfo - Populate TypeNo, Aux[] , TagName for
+/// structure or union.
+///
+void PIC16DbgInfo::PopulateStructOrUnionTypeInfo (DIType Ty,
+ unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+ DICompositeType CTy = DICompositeType(Ty.getGV());
+ TypeNo = TypeNo << PIC16Dbg::S_BASIC;
+ if (Ty.getTag() == dwarf::DW_TAG_structure_type)
+ TypeNo = TypeNo | PIC16Dbg::T_STRUCT;
+ else
+ TypeNo = TypeNo | PIC16Dbg::T_UNION;
+ CTy.getName(TagName);
+ // UniqueSuffix is .number where number is obtained from
+ // llvm.dbg.composite<number>.
+ std::string UniqueSuffix = "." + Ty.getGV()->getName().substr(18);
+ TagName += UniqueSuffix;
+ unsigned short size = CTy.getSizeInBits()/8;
+ // 7th and 8th byte represent size.
+ HasAux = true;
+ Aux[6] = size & 0xff;
+ Aux[7] = size >> 8;
+}
+
+/// PopulateEnumTypeInfo - Populate TypeNo for enum from Ty.
+void PIC16DbgInfo::PopulateEnumTypeInfo (DIType Ty, unsigned short &TypeNo) {
+ TypeNo = TypeNo << PIC16Dbg::S_BASIC;
+ TypeNo = TypeNo | PIC16Dbg::T_ENUM;
+}
+
+/// PopulateCompositeTypeInfo - Populate TypeNo, Aux[] and TagName for
+/// composite types from Ty.
+///
+void PIC16DbgInfo::PopulateCompositeTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+ switch (Ty.getTag()) {
+ case dwarf::DW_TAG_array_type: {
+ PopulateArrayTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
+ break;
+ }
+ case dwarf:: DW_TAG_union_type:
+ case dwarf::DW_TAG_structure_type: {
+ PopulateStructOrUnionTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
+ break;
+ }
+ case dwarf::DW_TAG_enumeration_type: {
+ PopulateEnumTypeInfo (Ty, TypeNo);
+ break;
+ }
+ default:
+ TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
+ }
+}
+
+/// GetTypeDebugNumber - Get debug type number for given type.
+///
unsigned PIC16DbgInfo::GetTypeDebugNumber(std::string &type) {
if (type == "char")
return PIC16Dbg::T_CHAR;
@@ -127,8 +179,10 @@ unsigned PIC16DbgInfo::GetTypeDebugNumber(std::string &type) {
else
return 0;
}
-
-short PIC16DbgInfo::getClass(DIGlobalVariable DIGV) {
+
+/// GetStorageClass - Get storage class for give debug variable.
+///
+short PIC16DbgInfo::getStorageClass(DIGlobalVariable DIGV) {
short ClassNo;
if (PAN::isLocalName(DIGV.getGlobal()->getName())) {
// Generating C_AUTO here fails due to error in linker. Change it once
@@ -142,12 +196,126 @@ short PIC16DbgInfo::getClass(DIGlobalVariable DIGV) {
return ClassNo;
}
-void PIC16DbgInfo::Init(Module &M) {
- // Do all debug related initializations here.
- EmitFileDirective(M);
+/// BeginModule - Emit necessary debug info to start a Module and do other
+/// required initializations.
+void PIC16DbgInfo::BeginModule(Module &M) {
+ // Emit file directive for module.
+ GlobalVariable *CU = M.getNamedGlobal("llvm.dbg.compile_unit");
+ if (CU) {
+ EmitDebugDirectives = true;
+ SwitchToCU(CU);
+ }
+
+ // Emit debug info for decls of composite types.
EmitCompositeTypeDecls(M);
}
+/// Helper to find first valid debug loc for a function.
+///
+static const DebugLoc GetDebugLocForFunction(const MachineFunction &MF) {
+ DebugLoc DL;
+ for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
+ II != E; ++II) {
+ DL = II->getDebugLoc();
+ if (!DL.isUnknown())
+ return DL;
+ }
+ }
+ return DL;
+}
+
+/// BeginFunction - Emit necessary debug info to start a function.
+///
+void PIC16DbgInfo::BeginFunction(const MachineFunction &MF) {
+ if (! EmitDebugDirectives) return;
+
+ // Retreive the first valid debug Loc and process it.
+ const DebugLoc &DL = GetDebugLocForFunction(MF);
+ ChangeDebugLoc(MF, DL, true);
+
+ EmitFunctBeginDI(MF.getFunction());
+
+ // Set current line to 0 so that.line directive is genearted after .bf.
+ CurLine = 0;
+}
+
+/// ChangeDebugLoc - Take necessary steps when DebugLoc changes.
+/// CurFile and CurLine may change as a result of this.
+///
+void PIC16DbgInfo::ChangeDebugLoc(const MachineFunction &MF,
+ const DebugLoc &DL, bool IsInBeginFunction) {
+ if (! EmitDebugDirectives) return;
+ assert (! DL.isUnknown() && "can't change to invalid debug loc");
+
+ GlobalVariable *CU = MF.getDebugLocTuple(DL).CompileUnit;
+ unsigned line = MF.getDebugLocTuple(DL).Line;
+
+ SwitchToCU(CU);
+ SwitchToLine(line, IsInBeginFunction);
+}
+
+/// SwitchToLine - Emit line directive for a new line.
+///
+void PIC16DbgInfo::SwitchToLine(unsigned Line, bool IsInBeginFunction) {
+ if (CurLine == Line) return;
+ if (!IsInBeginFunction) O << "\n\t.line " << Line << "\n";
+ CurLine = Line;
+}
+
+/// EndFunction - Emit .ef for end of function.
+///
+void PIC16DbgInfo::EndFunction(const MachineFunction &MF) {
+ if (! EmitDebugDirectives) return;
+ EmitFunctEndDI(MF.getFunction(), CurLine);
+}
+
+/// EndModule - Emit .eof for end of module.
+///
+void PIC16DbgInfo::EndModule(Module &M) {
+ if (! EmitDebugDirectives) return;
+ EmitVarDebugInfo(M);
+ if (CurFile != "") O << "\n\t.eof";
+}
+
+/// EmitCompositeTypeElements - Emit debug information for members of a
+/// composite type.
+///
+void PIC16DbgInfo::EmitCompositeTypeElements (DICompositeType CTy,
+ std::string UniqueSuffix) {
+ unsigned long Value = 0;
+ DIArray Elements = CTy.getTypeArray();
+ for (unsigned i = 0, N = Elements.getNumElements(); i < N; i++) {
+ DIDescriptor Element = Elements.getElement(i);
+ unsigned short TypeNo = 0;
+ bool HasAux = false;
+ int ElementAux[PIC16Dbg::AuxSize] = { 0 };
+ std::string TagName = "";
+ std::string ElementName;
+ GlobalVariable *GV = Element.getGV();
+ DIDerivedType DITy(GV);
+ DITy.getName(ElementName);
+ unsigned short ElementSize = DITy.getSizeInBits()/8;
+ // Get mangleddd name for this structure/union element.
+ std::string MangMemName = ElementName + UniqueSuffix;
+ PopulateDebugInfo(DITy, TypeNo, HasAux, ElementAux, TagName);
+ short Class;
+ if( CTy.getTag() == dwarf::DW_TAG_union_type)
+ Class = PIC16Dbg::C_MOU;
+ else if (CTy.getTag() == dwarf::DW_TAG_structure_type)
+ Class = PIC16Dbg::C_MOS;
+ EmitSymbol(MangMemName, Class, TypeNo, Value);
+ if (CTy.getTag() == dwarf::DW_TAG_structure_type)
+ Value += ElementSize;
+ if (HasAux)
+ EmitAuxEntry(MangMemName, ElementAux, PIC16Dbg::AuxSize, TagName);
+ }
+}
+
+/// EmitCompositeTypeDecls - Emit composite type declarations like structure
+/// and union declarations.
+///
void PIC16DbgInfo::EmitCompositeTypeDecls(Module &M) {
for(iplist<GlobalVariable>::iterator I = M.getGlobalList().begin(),
E = M.getGlobalList().end(); I != E; I++) {
@@ -178,33 +346,10 @@ void PIC16DbgInfo::EmitCompositeTypeDecls(Module &M) {
// Emit auxiliary debug information for structure/union tag.
EmitAuxEntry(MangledCTyName, Aux, PIC16Dbg::AuxSize);
- unsigned long Value = 0;
- DIArray Elements = CTy.getTypeArray();
- for (unsigned i = 0, N = Elements.getNumElements(); i < N; i++) {
- DIDescriptor Element = Elements.getElement(i);
- unsigned short TypeNo = 0;
- bool HasAux = false;
- int ElementAux[PIC16Dbg::AuxSize] = { 0 };
- std::string TypeName = "";
- std::string ElementName;
- GlobalVariable *GV = Element.getGV();
- DIDerivedType DITy(GV);
- DITy.getName(ElementName);
- unsigned short ElementSize = DITy.getSizeInBits()/8;
- // Get mangleddd name for this structure/union element.
- std::string MangMemName = ElementName + UniqueSuffix;
- PopulateDebugInfo(DITy, TypeNo, HasAux, ElementAux, TypeName);
- short Class;
- if( CTy.getTag() == dwarf::DW_TAG_union_type)
- Class = PIC16Dbg::C_MOU;
- else if (CTy.getTag() == dwarf::DW_TAG_structure_type)
- Class = PIC16Dbg::C_MOS;
- EmitSymbol(MangMemName, Class, TypeNo, Value);
- if (CTy.getTag() == dwarf::DW_TAG_structure_type)
- Value += ElementSize;
- if (HasAux)
- EmitAuxEntry(MangMemName, ElementAux, PIC16Dbg::AuxSize, TypeName);
- }
+
+ // Emit members.
+ EmitCompositeTypeElements (CTy, UniqueSuffix);
+
// Emit mangled Symbol for end of structure/union.
std::string EOSSymbol = ".eos" + UniqueSuffix;
EmitSymbol(EOSSymbol, PIC16Dbg::C_EOS);
@@ -214,6 +359,8 @@ void PIC16DbgInfo::EmitCompositeTypeDecls(Module &M) {
}
}
+/// EmitFunctBeginDI - Emit .bf for function.
+///
void PIC16DbgInfo::EmitFunctBeginDI(const Function *F) {
std::string FunctName = F->getName();
if (EmitDebugDirectives) {
@@ -221,16 +368,20 @@ void PIC16DbgInfo::EmitFunctBeginDI(const Function *F) {
std::string BlockBeginSym = ".bb." + FunctName;
int BFAux[PIC16Dbg::AuxSize] = {0};
- BFAux[4] = FunctBeginLine;
- BFAux[5] = FunctBeginLine >> 8;
+ BFAux[4] = CurLine;
+ BFAux[5] = CurLine >> 8;
+
// Emit debug directives for beginning of function.
EmitSymbol(FunctBeginSym, PIC16Dbg::C_FCN);
EmitAuxEntry(FunctBeginSym, BFAux, PIC16Dbg::AuxSize);
+
EmitSymbol(BlockBeginSym, PIC16Dbg::C_BLOCK);
EmitAuxEntry(BlockBeginSym, BFAux, PIC16Dbg::AuxSize);
}
}
+/// EmitFunctEndDI - Emit .ef for function end.
+///
void PIC16DbgInfo::EmitFunctEndDI(const Function *F, unsigned Line) {
std::string FunctName = F->getName();
if (EmitDebugDirectives) {
@@ -241,8 +392,8 @@ void PIC16DbgInfo::EmitFunctEndDI(const Function *F, unsigned Line) {
EmitSymbol(BlockEndSym, PIC16Dbg::C_BLOCK);
int EFAux[PIC16Dbg::AuxSize] = {0};
// 5th and 6th byte stand for line number.
- EFAux[4] = Line;
- EFAux[5] = Line >> 8;
+ EFAux[4] = CurLine;
+ EFAux[5] = CurLine >> 8;
EmitAuxEntry(BlockEndSym, EFAux, PIC16Dbg::AuxSize);
EmitSymbol(FunctEndSym, PIC16Dbg::C_FCN);
EmitAuxEntry(FunctEndSym, EFAux, PIC16Dbg::AuxSize);
@@ -251,15 +402,18 @@ void PIC16DbgInfo::EmitFunctEndDI(const Function *F, unsigned Line) {
/// EmitAuxEntry - Emit Auxiliary debug information.
///
-void PIC16DbgInfo::EmitAuxEntry(const std::string VarName, int Aux[], int num,
- std::string tag) {
+void PIC16DbgInfo::EmitAuxEntry(const std::string VarName, int Aux[], int Num,
+ std::string TagName) {
O << "\n\t.dim " << VarName << ", 1" ;
- if (tag != "")
- O << ", " << tag;
- for (int i = 0; i<num; i++)
+ // TagName is emitted in case of structure/union objects.
+ if (TagName != "")
+ O << ", " << TagName;
+ for (int i = 0; i<Num; i++)
O << "," << Aux[i];
}
+/// EmitSymbol - Emit .def for a symbol. Value is offset for the member.
+///
void PIC16DbgInfo::EmitSymbol(std::string Name, short Class, unsigned short
Type, unsigned long Value) {
O << "\n\t" << ".def "<< Name << ", type = " << Type << ", class = "
@@ -268,6 +422,8 @@ void PIC16DbgInfo::EmitSymbol(std::string Name, short Class, unsigned short
O << ", value = " << Value;
}
+/// EmitVarDebugInfo - Emit debug information for all variables.
+///
void PIC16DbgInfo::EmitVarDebugInfo(Module &M) {
GlobalVariable *Root = M.getGlobalVariable("llvm.dbg.global_variables");
if (!Root)
@@ -283,47 +439,45 @@ void PIC16DbgInfo::EmitVarDebugInfo(Module &M) {
unsigned short TypeNo = 0;
bool HasAux = false;
int Aux[PIC16Dbg::AuxSize] = { 0 };
- std::string TypeName = "";
+ std::string TagName = "";
std::string VarName = TAI->getGlobalPrefix()+DIGV.getGlobal()->getName();
- PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TypeName);
+ PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TagName);
// Emit debug info only if type information is availaible.
if (TypeNo != PIC16Dbg::T_NULL) {
O << "\n\t.type " << VarName << ", " << TypeNo;
- short ClassNo = getClass(DIGV);
+ short ClassNo = getStorageClass(DIGV);
O << "\n\t.class " << VarName << ", " << ClassNo;
if (HasAux)
- EmitAuxEntry(VarName, Aux, PIC16Dbg::AuxSize, TypeName);
+ EmitAuxEntry(VarName, Aux, PIC16Dbg::AuxSize, TagName);
}
}
}
O << "\n";
}
-void PIC16DbgInfo::EmitFileDirective(Module &M) {
- GlobalVariable *CU = M.getNamedGlobal("llvm.dbg.compile_unit");
- if (CU) {
- EmitDebugDirectives = true;
- EmitFileDirective(CU, false);
- }
-}
+/// SwitchToCU - Switch to a new compilation unit.
+///
+void PIC16DbgInfo::SwitchToCU(GlobalVariable *CU) {
+ // Get the file path from CU.
+ DICompileUnit cu(CU);
+ std::string DirName, FileName;
+ std::string FilePath = cu.getDirectory(DirName) + "/" +
+ cu.getFilename(FileName);
-void PIC16DbgInfo::EmitFileDirective(GlobalVariable *CU, bool EmitEof) {
- std::string Dir, FN;
- DICompileUnit DIUnit(CU);
- std::string File = DIUnit.getDirectory(Dir) + "/" + DIUnit.getFilename(FN);
- if ( File != CurFile ) {
- if (EmitEof)
- EmitEOF();
- O << "\n\t.file\t\"" << File << "\"\n" ;
- CurFile = File;
- }
+ // Nothing to do if source file is still same.
+ if ( FilePath == CurFile ) return;
+
+ // Else, close the current one and start a new.
+ if (CurFile != "") O << "\n\t.eof";
+ O << "\n\t.file\t\"" << FilePath << "\"\n" ;
+ CurFile = FilePath;
+ CurLine = 0;
}
+/// EmitEOF - Emit .eof for end of file.
+///
void PIC16DbgInfo::EmitEOF() {
if (CurFile != "")
O << "\n\t.EOF";
}
-void PIC16DbgInfo::SetFunctBeginLine(unsigned line) {
- FunctBeginLine = line;
-}
diff --git a/lib/Target/PIC16/PIC16DebugInfo.h b/lib/Target/PIC16/PIC16DebugInfo.h
index 9d503807b205..d126d851b50e 100644
--- a/lib/Target/PIC16/PIC16DebugInfo.h
+++ b/lib/Target/PIC16/PIC16DebugInfo.h
@@ -20,6 +20,8 @@
#include <map>
namespace llvm {
+ class MachineFunction;
+ class DebugLoc;
namespace PIC16Dbg {
enum VarType {
T_NULL,
@@ -94,33 +96,64 @@ namespace llvm {
raw_ostream &O;
const TargetAsmInfo *TAI;
std::string CurFile;
+ unsigned CurLine;
+
// EmitDebugDirectives is set if debug information is available. Default
// value for it is false.
bool EmitDebugDirectives;
- unsigned FunctBeginLine;
+
public:
PIC16DbgInfo(raw_ostream &o, const TargetAsmInfo *T) : O(o), TAI(T) {
- CurFile = "";
+ CurFile = "";
+ CurLine = 0;
EmitDebugDirectives = false;
}
- void PopulateDebugInfo(DIType Ty, unsigned short &TypeNo, bool &HasAux,
+
+ void BeginModule (Module &M);
+ void BeginFunction (const MachineFunction &MF);
+ void ChangeDebugLoc (const MachineFunction &MF, const DebugLoc &DL,
+ bool IsInBeginFunction = false);
+ void EndFunction (const MachineFunction &MF);
+ void EndModule (Module &M);
+
+
+ private:
+ void SwitchToCU (GlobalVariable *CU);
+ void SwitchToLine (unsigned Line, bool IsInBeginFunction = false);
+
+ void PopulateDebugInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux,
int Aux[], std::string &TypeName);
- unsigned GetTypeDebugNumber(std::string &type);
- short getClass(DIGlobalVariable DIGV);
+ void PopulateBasicTypeInfo (DIType Ty, unsigned short &TypeNo);
+ void PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TypeName);
+
+ void PopulateCompositeTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TypeName);
+ void PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TypeName);
+
+ void PopulateStructOrUnionTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TypeName);
+ void PopulateEnumTypeInfo (DIType Ty, unsigned short &TypeNo);
+
+ unsigned GetTypeDebugNumber(std::string &Type);
+ short getStorageClass(DIGlobalVariable DIGV);
void EmitFunctBeginDI(const Function *F);
- void Init(Module &M);
void EmitCompositeTypeDecls(Module &M);
+ void EmitCompositeTypeElements (DICompositeType CTy,
+ std::string UniqueSuffix);
void EmitFunctEndDI(const Function *F, unsigned Line);
void EmitAuxEntry(const std::string VarName, int Aux[],
- int num = PIC16Dbg::AuxSize, std::string tag = "");
+ int num = PIC16Dbg::AuxSize, std::string TagName = "");
inline void EmitSymbol(std::string Name, short Class,
unsigned short Type = PIC16Dbg::T_NULL,
unsigned long Value = 0);
void EmitVarDebugInfo(Module &M);
- void EmitFileDirective(Module &M);
- void EmitFileDirective(GlobalVariable *CU, bool EmitEof = true);
void EmitEOF();
- void SetFunctBeginLine(unsigned line);
};
} // end namespace llvm;
#endif
diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp
index ba465f3fcc7a..f113a483d692 100644
--- a/lib/Target/PIC16/PIC16ISelLowering.cpp
+++ b/lib/Target/PIC16/PIC16ISelLowering.cpp
@@ -31,42 +31,72 @@ static const char *getIntrinsicName(unsigned opcode) {
std::string Basename;
switch(opcode) {
default: assert (0 && "do not know intrinsic name");
+ // Arithmetic Right shift for integer types.
case PIC16ISD::SRA_I8: Basename = "sra.i8"; break;
case RTLIB::SRA_I16: Basename = "sra.i16"; break;
case RTLIB::SRA_I32: Basename = "sra.i32"; break;
+ // Left shift for integer types.
case PIC16ISD::SLL_I8: Basename = "sll.i8"; break;
case RTLIB::SHL_I16: Basename = "sll.i16"; break;
case RTLIB::SHL_I32: Basename = "sll.i32"; break;
+ // Logical Right Shift for integer types.
case PIC16ISD::SRL_I8: Basename = "srl.i8"; break;
case RTLIB::SRL_I16: Basename = "srl.i16"; break;
case RTLIB::SRL_I32: Basename = "srl.i32"; break;
+ // Multiply for integer types.
case PIC16ISD::MUL_I8: Basename = "mul.i8"; break;
case RTLIB::MUL_I16: Basename = "mul.i16"; break;
case RTLIB::MUL_I32: Basename = "mul.i32"; break;
+ // Signed division for integers.
case RTLIB::SDIV_I16: Basename = "sdiv.i16"; break;
case RTLIB::SDIV_I32: Basename = "sdiv.i32"; break;
+
+ // Unsigned division for integers.
case RTLIB::UDIV_I16: Basename = "udiv.i16"; break;
case RTLIB::UDIV_I32: Basename = "udiv.i32"; break;
+ // Signed Modulas for integers.
case RTLIB::SREM_I16: Basename = "srem.i16"; break;
case RTLIB::SREM_I32: Basename = "srem.i32"; break;
+
+ // Unsigned Modulas for integers.
case RTLIB::UREM_I16: Basename = "urem.i16"; break;
case RTLIB::UREM_I32: Basename = "urem.i32"; break;
- case RTLIB::FPTOSINT_F32_I32:
- Basename = "f32_to_si32"; break;
- case RTLIB::SINTTOFP_I32_F32:
- Basename = "si32_to_f32"; break;
+ //////////////////////
+ // LIBCALLS FOR FLOATS
+ //////////////////////
+
+ // Float to signed integrals
+ case RTLIB::FPTOSINT_F32_I8: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOSINT_F32_I16: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOSINT_F32_I32: Basename = "f32_to_si32"; break;
+
+ // Signed integrals to float. char and int are first sign extended to i32
+ // before being converted to float, so an I8_F32 or I16_F32 isn't required.
+ case RTLIB::SINTTOFP_I32_F32: Basename = "si32_to_f32"; break;
+
+ // Float to Unsigned conversions.
+ // Signed conversion can be used for unsigned conversion as well.
+ // In signed and unsigned versions only the interpretation of the
+ // MSB is different. Bit representation remains the same.
+ case RTLIB::FPTOUINT_F32_I8: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOUINT_F32_I16: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOUINT_F32_I32: Basename = "f32_to_si32"; break;
+
+ // Unsigned to Float conversions. char and int are first zero extended
+ // before being converted to float.
+ case RTLIB::UINTTOFP_I32_F32: Basename = "ui32_to_f32"; break;
+ // Floating point add, sub, mul, div.
case RTLIB::ADD_F32: Basename = "add.f32"; break;
case RTLIB::SUB_F32: Basename = "sub.f32"; break;
case RTLIB::MUL_F32: Basename = "mul.f32"; break;
case RTLIB::DIV_F32: Basename = "div.f32"; break;
-
}
std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
@@ -83,7 +113,7 @@ static const char *getIntrinsicName(unsigned opcode) {
// PIC16TargetLowering Constructor.
PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
: TargetLowering(TM), TmpSize(0) {
-
+
Subtarget = &TM.getSubtarget<PIC16Subtarget>();
addRegisterClass(MVT::i8, PIC16::GPRRegisterClass);
@@ -114,6 +144,7 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
// Signed division lib call names
setLibcallName(RTLIB::SDIV_I16, getIntrinsicName(RTLIB::SDIV_I16));
setLibcallName(RTLIB::SDIV_I32, getIntrinsicName(RTLIB::SDIV_I32));
+
// Unsigned division lib call names
setLibcallName(RTLIB::UDIV_I16, getIntrinsicName(RTLIB::UDIV_I16));
setLibcallName(RTLIB::UDIV_I32, getIntrinsicName(RTLIB::UDIV_I32));
@@ -121,15 +152,36 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
// Signed remainder lib call names
setLibcallName(RTLIB::SREM_I16, getIntrinsicName(RTLIB::SREM_I16));
setLibcallName(RTLIB::SREM_I32, getIntrinsicName(RTLIB::SREM_I32));
+
// Unsigned remainder lib call names
setLibcallName(RTLIB::UREM_I16, getIntrinsicName(RTLIB::UREM_I16));
setLibcallName(RTLIB::UREM_I32, getIntrinsicName(RTLIB::UREM_I32));
- // Floating point operations
+ // Floating point to signed int conversions.
+ setLibcallName(RTLIB::FPTOSINT_F32_I8,
+ getIntrinsicName(RTLIB::FPTOSINT_F32_I8));
+ setLibcallName(RTLIB::FPTOSINT_F32_I16,
+ getIntrinsicName(RTLIB::FPTOSINT_F32_I16));
setLibcallName(RTLIB::FPTOSINT_F32_I32,
getIntrinsicName(RTLIB::FPTOSINT_F32_I32));
+
+ // Signed int to floats.
setLibcallName(RTLIB::SINTTOFP_I32_F32,
getIntrinsicName(RTLIB::SINTTOFP_I32_F32));
+
+ // Floating points to unsigned ints.
+ setLibcallName(RTLIB::FPTOUINT_F32_I8,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I8));
+ setLibcallName(RTLIB::FPTOUINT_F32_I16,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I16));
+ setLibcallName(RTLIB::FPTOUINT_F32_I32,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I32));
+
+ // Unsigned int to floats.
+ setLibcallName(RTLIB::UINTTOFP_I32_F32,
+ getIntrinsicName(RTLIB::UINTTOFP_I32_F32));
+
+ // Floating point add, sub, mul ,div.
setLibcallName(RTLIB::ADD_F32, getIntrinsicName(RTLIB::ADD_F32));
setLibcallName(RTLIB::SUB_F32, getIntrinsicName(RTLIB::SUB_F32));
setLibcallName(RTLIB::MUL_F32, getIntrinsicName(RTLIB::MUL_F32));
diff --git a/lib/Target/PIC16/PIC16TargetMachine.cpp b/lib/Target/PIC16/PIC16TargetMachine.cpp
index bda632608ea7..d4f46a494498 100644
--- a/lib/Target/PIC16/PIC16TargetMachine.cpp
+++ b/lib/Target/PIC16/PIC16TargetMachine.cpp
@@ -37,6 +37,11 @@ X("pic16", "PIC16 14-bit [experimental].");
static RegisterTarget<CooperTargetMachine>
Y("cooper", "PIC16 Cooper [experimental].");
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializePIC16Target() { }
+}
+
// PIC16TargetMachine - Traditional PIC16 Machine.
PIC16TargetMachine::PIC16TargetMachine(const Module &M, const std::string &FS,
bool Cooper)
diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
index 7723982f69ad..c7bfb6d1a1a3 100644
--- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
@@ -646,19 +646,10 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
bool PPCLinuxAsmPrinter::doInitialization(Module &M) {
bool Result = AsmPrinter::doInitialization(M);
-
- // Emit initial debug information.
+ DW = getAnalysisIfAvailable<DwarfWriter>();
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
assert(MMI);
- DW = getAnalysisIfAvailable<DwarfWriter>();
- assert(DW && "DwarfWriter is not available");
- DW->BeginModule(&M, MMI, O, this, TAI);
-
- // GNU as handles section names wrapped in quotes
- Mang->setUseQuotes(true);
-
SwitchToSection(TAI->getTextSection());
-
return Result;
}
@@ -875,18 +866,9 @@ bool PPCDarwinAsmPrinter::doInitialization(Module &M) {
O << "\t.machine " << CPUDirectives[Directive] << '\n';
bool Result = AsmPrinter::doInitialization(M);
-
- // Emit initial debug information.
- // We need this for Personality functions.
- // AsmPrinter::doInitialization should have done this analysis.
+ DW = getAnalysisIfAvailable<DwarfWriter>();
MMI = getAnalysisIfAvailable<MachineModuleInfo>();
assert(MMI);
- DW = getAnalysisIfAvailable<DwarfWriter>();
- assert(DW && "DwarfWriter is not available");
- DW->BeginModule(&M, MMI, O, this, TAI);
-
- // Darwin wants symbols to be quoted if they have complex names.
- Mang->setUseQuotes(true);
// Prime text sections so they are adjacent. This reduces the likelihood a
// large data or debug section causes a branch to exceed 16M limit.
@@ -1202,3 +1184,9 @@ namespace {
extern "C" int PowerPCAsmPrinterForceLink;
int PowerPCAsmPrinterForceLink = 0;
+
+// Force static initialization when called from
+// llvm/InitializeAllAsmPrinters.h
+namespace llvm {
+ void InitializePowerPCAsmPrinter() { }
+}
diff --git a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp
index c69e591a6632..ebffd693d644 100644
--- a/lib/Target/PowerPC/PPCTargetAsmInfo.cpp
+++ b/lib/Target/PowerPC/PPCTargetAsmInfo.cpp
@@ -19,59 +19,19 @@
using namespace llvm;
using namespace llvm::dwarf;
-PPCDarwinTargetAsmInfo::PPCDarwinTargetAsmInfo(const PPCTargetMachine &TM):
+PPCDarwinTargetAsmInfo::PPCDarwinTargetAsmInfo(const PPCTargetMachine &TM) :
PPCTargetAsmInfo<DarwinTargetAsmInfo>(TM) {
PCSymbol = ".";
CommentString = ";";
- GlobalPrefix = "_";
- PrivateGlobalPrefix = "L";
- LessPrivateGlobalPrefix = "l";
- StringConstantPrefix = "\1LC";
ConstantPoolSection = "\t.const\t";
- JumpTableDataSection = ".const";
- CStringSection = "\t.cstring";
- if (TM.getRelocationModel() == Reloc::Static) {
- StaticCtorsSection = ".constructor";
- StaticDtorsSection = ".destructor";
- } else {
- StaticCtorsSection = ".mod_init_func";
- StaticDtorsSection = ".mod_term_func";
- }
- HasSingleParameterDotFile = false;
- SwitchToSectionDirective = "\t.section ";
UsedDirective = "\t.no_dead_strip\t";
- WeakDefDirective = "\t.weak_definition ";
- WeakRefDirective = "\t.weak_reference ";
- HiddenDirective = "\t.private_extern ";
SupportsExceptionHandling = true;
- NeedsIndirectEncoding = true;
- NeedsSet = true;
- BSSSection = 0;
DwarfEHFrameSection =
- ".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support";
+ ".section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support";
DwarfExceptionSection = ".section __DATA,__gcc_except_tab";
GlobalEHDirective = "\t.globl\t";
SupportsWeakOmittedEHFrame = false;
-
- DwarfAbbrevSection = ".section __DWARF,__debug_abbrev,regular,debug";
- DwarfInfoSection = ".section __DWARF,__debug_info,regular,debug";
- DwarfLineSection = ".section __DWARF,__debug_line,regular,debug";
- DwarfFrameSection = ".section __DWARF,__debug_frame,regular,debug";
- DwarfPubNamesSection = ".section __DWARF,__debug_pubnames,regular,debug";
- DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes,regular,debug";
- DwarfStrSection = ".section __DWARF,__debug_str,regular,debug";
- DwarfLocSection = ".section __DWARF,__debug_loc,regular,debug";
- DwarfARangesSection = ".section __DWARF,__debug_aranges,regular,debug";
- DwarfRangesSection = ".section __DWARF,__debug_ranges,regular,debug";
- DwarfMacInfoSection = ".section __DWARF,__debug_macinfo,regular,debug";
-
- // In non-PIC modes, emit a special label before jump tables so that the
- // linker can perform more accurate dead code stripping.
- if (TM.getRelocationModel() != Reloc::PIC_) {
- // Emit a local label that is preserved until the linker runs.
- JumpTableSpecialLabelPrefix = "l";
- }
}
/// PreferredEHDataFormat - This hook allows the target to select data
@@ -131,7 +91,7 @@ PPCLinuxTargetAsmInfo::PPCLinuxTargetAsmInfo(const PPCTargetMachine &TM) :
DwarfLocSection = "\t.section\t.debug_loc,\"\",@progbits";
DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
DwarfRangesSection = "\t.section\t.debug_ranges,\"\",@progbits";
- DwarfMacInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
+ DwarfMacroInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
PCSymbol = ".";
diff --git a/lib/Target/PowerPC/PPCTargetMachine.cpp b/lib/Target/PowerPC/PPCTargetMachine.cpp
index ef3f0fc04219..3e89885a77eb 100644
--- a/lib/Target/PowerPC/PPCTargetMachine.cpp
+++ b/lib/Target/PowerPC/PPCTargetMachine.cpp
@@ -35,6 +35,11 @@ X("ppc32", "PowerPC 32");
static RegisterTarget<PPC64TargetMachine>
Y("ppc64", "PowerPC 64");
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializePowerPCTarget() { }
+}
+
// No assembler printer by default
PPCTargetMachine::AsmPrinterCtorFn PPCTargetMachine::AsmPrinterCtor = 0;
diff --git a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
index 61707f5556fb..6a2fdcac01d7 100644
--- a/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
+++ b/lib/Target/Sparc/AsmPrinter/SparcAsmPrinter.cpp
@@ -15,6 +15,7 @@
#define DEBUG_TYPE "asm-printer"
#include "Sparc.h"
#include "SparcInstrInfo.h"
+#include "SparcTargetMachine.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
@@ -24,8 +25,6 @@
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetAsmInfo.h"
-#include "llvm/Target/TargetData.h"
-#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/Statistic.h"
@@ -88,6 +87,7 @@ FunctionPass *llvm::createSparcCodePrinterPass(raw_ostream &o,
return new SparcAsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
}
+
/// runOnMachineFunction - This uses the printInstruction()
/// method to print assembly for each instruction.
///
@@ -353,3 +353,17 @@ bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
return false;
}
+
+namespace {
+ static struct Register {
+ Register() {
+ SparcTargetMachine::registerAsmPrinter(createSparcCodePrinterPass);
+ }
+ } Registrator;
+}
+
+// Force static initialization when called from
+// llvm/InitializeAllAsmPrinters.h
+namespace llvm {
+ void InitializeSparcAsmPrinter() { }
+}
diff --git a/lib/Target/Sparc/SparcTargetMachine.cpp b/lib/Target/Sparc/SparcTargetMachine.cpp
index eda030924100..fd0f12429a04 100644
--- a/lib/Target/Sparc/SparcTargetMachine.cpp
+++ b/lib/Target/Sparc/SparcTargetMachine.cpp
@@ -18,17 +18,18 @@
#include "llvm/Target/TargetMachineRegistry.h"
using namespace llvm;
-/// SparcTargetMachineModule - Note that this is used on hosts that
-/// cannot link in a library unless there are references into the
-/// library. In particular, it seems that it is not possible to get
-/// things to work on Win32 without this. Though it is unused, do not
-/// remove it.
-extern "C" int SparcTargetMachineModule;
-int SparcTargetMachineModule = 0;
-
// Register the target.
static RegisterTarget<SparcTargetMachine> X("sparc", "SPARC");
+// No assembler printer by default
+SparcTargetMachine::AsmPrinterCtorFn SparcTargetMachine::AsmPrinterCtor = 0;
+
+
+// Force static initialization when called from llvm/InitializeAllTargets.h
+namespace llvm {
+ void InitializeSparcTarget() { }
+}
+
const TargetAsmInfo *SparcTargetMachine::createTargetAsmInfo() const {
// FIXME: Handle Solaris subtarget someday :)
return new SparcELFTargetAsmInfo(*this);
@@ -89,6 +90,8 @@ bool SparcTargetMachine::addAssemblyEmitter(PassManagerBase &PM,
bool Verbose,
raw_ostream &Out) {
// Output assembly language.
- PM.add(createSparcCodePrinterPass(Out, *this, OptLevel, Verbose));
+ assert(AsmPrinterCtor && "AsmPrinter was not linked in");
+ if (AsmPrinterCtor)
+ PM.add(AsmPrinterCtor(Out, *this, OptLevel, Verbose));
return false;
}
diff --git a/lib/Target/Sparc/SparcTargetMachine.h b/lib/Target/Sparc/SparcTargetMachine.h
index 40b44f2fb34d..8afcc73f502e 100644
--- a/lib/Target/Sparc/SparcTargetMachine.h
+++ b/lib/Target/Sparc/SparcTargetMachine.h
@@ -35,6 +35,14 @@ class SparcTargetMachine : public LLVMTargetMachine {
protected:
virtual const TargetAsmInfo *createTargetAsmInfo() const;
+ // To avoid having target depend on the asmprinter stuff libraries, asmprinter
+ // set this functions to ctor pointer at startup time if they are linked in.
+ typedef FunctionPass *(*AsmPrinterCtorFn)(raw_ostream &o,
+ TargetMachine &tm,
+ CodeGenOpt::Level OptLevel,
+ bool verbose);
+ static AsmPrinterCtorFn AsmPrinterCtor;
+
public:
SparcTargetMachine(const Module &M, const std::string &FS);
@@ -56,6 +64,10 @@ public:
virtual bool addAssemblyEmitter(PassManagerBase &PM,
CodeGenOpt::Level OptLevel,
bool Verbose, raw_ostream &Out);
+
+ static void registerAsmPrinter(AsmPrinterCtorFn F) {
+ AsmPrinterCtor = F;
+ }
};
} // end namespace llvm
diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp
index 6a2de6f582a6..3f5f1bd3eb26 100644
--- a/lib/Target/TargetAsmInfo.cpp
+++ b/lib/Target/TargetAsmInfo.cpp
@@ -24,10 +24,10 @@
#include "llvm/Support/Dwarf.h"
#include <cctype>
#include <cstring>
-
using namespace llvm;
-void TargetAsmInfo::fillDefaultValues() {
+TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm)
+: TM(tm) {
BSSSection = "\t.bss";
BSSSection_ = 0;
ReadOnlySection = 0;
@@ -58,6 +58,7 @@ void TargetAsmInfo::fillDefaultValues() {
InlineAsmEnd = "#NO_APP";
AssemblerDialect = 0;
StringConstantPrefix = ".str";
+ AllowQuotesInName = false;
ZeroDirective = "\t.zero\t";
ZeroDirectiveSuffix = 0;
AsciiDirective = "\t.ascii\t";
@@ -102,7 +103,6 @@ void TargetAsmInfo::fillDefaultValues() {
SupportsExceptionHandling = false;
DwarfRequiresFrameSection = true;
DwarfUsesInlineInfoSection = false;
- SupportsMacInfoSection = true;
NonLocalEHFrameLabel = false;
GlobalEHDirective = 0;
SupportsWeakOmittedEHFrame = true;
@@ -118,7 +118,7 @@ void TargetAsmInfo::fillDefaultValues() {
DwarfLocSection = ".debug_loc";
DwarfARangesSection = ".debug_aranges";
DwarfRangesSection = ".debug_ranges";
- DwarfMacInfoSection = ".debug_macinfo";
+ DwarfMacroInfoSection = ".debug_macinfo";
DwarfEHFrameSection = ".eh_frame";
DwarfExceptionSection = ".gcc_except_table";
AsmTransCBE = 0;
@@ -126,11 +126,6 @@ void TargetAsmInfo::fillDefaultValues() {
DataSection = getUnnamedSection("\t.data", SectionFlags::Writeable);
}
-TargetAsmInfo::TargetAsmInfo(const TargetMachine &tm)
- : TM(tm) {
- fillDefaultValues();
-}
-
TargetAsmInfo::~TargetAsmInfo() {
}
diff --git a/lib/Target/X86/AsmPrinter/CMakeLists.txt b/lib/Target/X86/AsmPrinter/CMakeLists.txt
index dbd03d8b9633..368bcaa5ce34 100644
--- a/lib/Target/X86/AsmPrinter/CMakeLists.txt
+++ b/lib/Target/X86/AsmPrinter/CMakeLists.txt
@@ -2,6 +2,7 @@ include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/
add_partially_linked_object(LLVMX86AsmPrinter
X86ATTAsmPrinter.cpp
+ X86ATTInstPrinter.cpp
X86AsmPrinter.cpp
X86IntelAsmPrinter.cpp
)
diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
index 8afe2ea9e10b..60ed4f0c946a 100644
--- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
@@ -26,8 +26,10 @@
#include "llvm/Type.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/MC/MCInst.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Mangler.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetAsmInfo.h"
@@ -36,6 +38,9 @@ using namespace llvm;
STATISTIC(EmittedInsts, "Number of machine instrs printed");
+static cl::opt<bool> NewAsmPrinter("experimental-asm-printer",
+ cl::Hidden);
+
static std::string getPICLabelString(unsigned FnNum,
const TargetAsmInfo *TAI,
const X86Subtarget* Subtarget) {
@@ -266,7 +271,7 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
O << "\t.size\t" << CurrentFnName << ", .-" << CurrentFnName << '\n';
// Emit post-function debug information.
- if (TAI->doesSupportDebugInformation())
+ if (TAI->doesSupportDebugInformation() || TAI->doesSupportExceptionHandling())
DW->EndFunction(&MF);
// Print out jump tables referenced by the function.
@@ -291,6 +296,136 @@ static inline bool shouldPrintStub(TargetMachine &TM, const X86Subtarget* ST) {
return ST->isPICStyleStub() && TM.getRelocationModel() != Reloc::Static;
}
+/// print_pcrel_imm - This is used to print an immediate value that ends up
+/// being encoded as a pc-relative value. These print slightly differently, for
+/// example, a $ is not emitted.
+void X86ATTAsmPrinter::print_pcrel_imm(const MachineInstr *MI, unsigned OpNo) {
+ const MachineOperand &MO = MI->getOperand(OpNo);
+ switch (MO.getType()) {
+ default: assert(0 && "Unknown pcrel immediate operand");
+ case MachineOperand::MO_Immediate:
+ O << MO.getImm();
+ return;
+ case MachineOperand::MO_MachineBasicBlock:
+ printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
+ return;
+
+ case MachineOperand::MO_GlobalAddress: {
+ const GlobalValue *GV = MO.getGlobal();
+ std::string Name = Mang->getValueName(GV);
+ decorateName(Name, GV);
+
+ bool needCloseParen = false;
+ if (Name[0] == '$') {
+ // The name begins with a dollar-sign. In order to avoid having it look
+ // like an integer immediate to the assembler, enclose it in parens.
+ O << '(';
+ needCloseParen = true;
+ }
+
+ if (shouldPrintStub(TM, Subtarget)) {
+ // Link-once, declaration, or Weakly-linked global variables need
+ // non-lazily-resolved stubs
+ if (GV->isDeclaration() || GV->isWeakForLinker()) {
+ // Dynamically-resolved functions need a stub for the function.
+ if (isa<Function>(GV)) {
+ // Function stubs are no longer needed for Mac OS X 10.5 and up.
+ if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
+ O << Name;
+ } else {
+ FnStubs.insert(Name);
+ printSuffixedName(Name, "$stub");
+ }
+ } else if (GV->hasHiddenVisibility()) {
+ if (!GV->isDeclaration() && !GV->hasCommonLinkage())
+ // Definition is not definitely in the current translation unit.
+ O << Name;
+ else {
+ HiddenGVStubs.insert(Name);
+ printSuffixedName(Name, "$non_lazy_ptr");
+ }
+ } else {
+ GVStubs.insert(Name);
+ printSuffixedName(Name, "$non_lazy_ptr");
+ }
+ } else {
+ if (GV->hasDLLImportLinkage())
+ O << "__imp_";
+ O << Name;
+ }
+ } else {
+ if (GV->hasDLLImportLinkage()) {
+ O << "__imp_";
+ }
+ O << Name;
+
+ if (shouldPrintPLT(TM, Subtarget)) {
+ // Assemble call via PLT for externally visible symbols
+ if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
+ !GV->hasLocalLinkage())
+ O << "@PLT";
+ }
+ if (Subtarget->isTargetCygMing() && GV->isDeclaration())
+ // Save function name for later type emission
+ FnStubs.insert(Name);
+ }
+
+ if (GV->hasExternalWeakLinkage())
+ ExtWeakSymbols.insert(GV);
+
+ printOffset(MO.getOffset());
+
+ if (needCloseParen)
+ O << ')';
+ return;
+ }
+
+ case MachineOperand::MO_ExternalSymbol: {
+ bool needCloseParen = false;
+ std::string Name(TAI->getGlobalPrefix());
+ Name += MO.getSymbolName();
+ // Print function stub suffix unless it's Mac OS X 10.5 and up.
+ if (shouldPrintStub(TM, Subtarget) &&
+ !(Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9)) {
+ FnStubs.insert(Name);
+ printSuffixedName(Name, "$stub");
+ return;
+ }
+
+ if (Name[0] == '$') {
+ // The name begins with a dollar-sign. In order to avoid having it look
+ // like an integer immediate to the assembler, enclose it in parens.
+ O << '(';
+ needCloseParen = true;
+ }
+
+ O << Name;
+
+ if (shouldPrintPLT(TM, Subtarget)) {
+ std::string GOTName(TAI->getGlobalPrefix());
+ GOTName+="_GLOBAL_OFFSET_TABLE_";
+ if (Name == GOTName)
+ // HACK! Emit extra offset to PC during printing GOT offset to
+ // compensate for the size of popl instruction. The resulting code
+ // should look like:
+ // call .piclabel
+ // piclabel:
+ // popl %some_register
+ // addl $_GLOBAL_ADDRESS_TABLE_ + [.-piclabel], %some_register
+ O << " + [.-"
+ << getPICLabelString(getFunctionNumber(), TAI, Subtarget) << ']';
+
+ O << "@PLT";
+ }
+
+ if (needCloseParen)
+ O << ')';
+
+ return;
+ }
+ }
+}
+
void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
const char *Modifier, bool NotRIPRel) {
const MachineOperand &MO = MI->getOperand(OpNo);
@@ -312,14 +447,10 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
case MachineOperand::MO_Immediate:
if (!Modifier || (strcmp(Modifier, "debug") &&
- strcmp(Modifier, "mem") &&
- strcmp(Modifier, "call")))
+ strcmp(Modifier, "mem")))
O << '$';
O << MO.getImm();
return;
- case MachineOperand::MO_MachineBasicBlock:
- printBasicBlockLabel(MO.getMBB(), false, false, VerboseAsm);
- return;
case MachineOperand::MO_JumpTableIndex: {
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
if (!isMemOp) O << '$';
@@ -359,8 +490,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
return;
}
case MachineOperand::MO_GlobalAddress: {
- bool isCallOp = Modifier && !strcmp(Modifier, "call");
- bool isMemOp = Modifier && !strcmp(Modifier, "mem");
+ bool isMemOp = Modifier && !strcmp(Modifier, "mem");
bool needCloseParen = false;
const GlobalValue *GV = MO.getGlobal();
@@ -369,7 +499,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
// If GV is an alias then use the aliasee for determining
// thread-localness.
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV))
- GVar = dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
+ GVar =dyn_cast_or_null<GlobalVariable>(GA->resolveAliasedGlobal(false));
}
bool isThreadLocal = GVar && GVar->isThreadLocal();
@@ -377,7 +507,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
std::string Name = Mang->getValueName(GV);
decorateName(Name, GV);
- if (!isMemOp && !isCallOp)
+ if (!isMemOp)
O << '$';
else if (Name[0] == '$') {
// The name begins with a dollar-sign. In order to avoid having it look
@@ -391,15 +521,7 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
// non-lazily-resolved stubs
if (GV->isDeclaration() || GV->isWeakForLinker()) {
// Dynamically-resolved functions need a stub for the function.
- if (isCallOp && isa<Function>(GV)) {
- // Function stubs are no longer needed for Mac OS X 10.5 and up.
- if (Subtarget->isTargetDarwin() && Subtarget->getDarwinVers() >= 9) {
- O << Name;
- } else {
- FnStubs.insert(Name);
- printSuffixedName(Name, "$stub");
- }
- } else if (GV->hasHiddenVisibility()) {
+ if (GV->hasHiddenVisibility()) {
if (!GV->isDeclaration() && !GV->hasCommonLinkage())
// Definition is not definitely in the current translation unit.
O << Name;
@@ -417,25 +539,12 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
O << Name;
}
- if (!isCallOp && TM.getRelocationModel() == Reloc::PIC_)
+ if (TM.getRelocationModel() == Reloc::PIC_)
O << '-' << getPICLabelString(getFunctionNumber(), TAI, Subtarget);
} else {
- if (GV->hasDLLImportLinkage()) {
+ if (GV->hasDLLImportLinkage())
O << "__imp_";
- }
O << Name;
-
- if (isCallOp) {
- if (shouldPrintPLT(TM, Subtarget)) {
- // Assemble call via PLT for externally visible symbols
- if (!GV->hasHiddenVisibility() && !GV->hasProtectedVisibility() &&
- !GV->hasLocalLinkage())
- O << "@PLT";
- }
- if (Subtarget->isTargetCygMing() && GV->isDeclaration())
- // Save function name for later type emission
- FnStubs.insert(Name);
- }
}
if (GV->hasExternalWeakLinkage())
@@ -443,6 +552,10 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
printOffset(MO.getOffset());
+ if (needCloseParen)
+ O << ')';
+
+ bool isRIPRelative = false;
if (isThreadLocal) {
TLSModel::Model model = getTLSModel(GVar, TM.getRelocationModel());
switch (model) {
@@ -456,7 +569,8 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
case TLSModel::InitialExec:
if (Subtarget->is64Bit()) {
assert (!NotRIPRel);
- O << "@GOTTPOFF(%rip)";
+ O << "@GOTTPOFF";
+ isRIPRelative = true;
} else {
O << "@INDNTPOFF";
}
@@ -476,43 +590,33 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
O << "@GOT";
else
O << "@GOTOFF";
- } else if (Subtarget->isPICStyleRIPRel() && !NotRIPRel) {