summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortstellar <tstellar@91177308-0d34-0410-b5e6-96231b3b80d8>2012-10-16 17:52:57 +0000
committertstellar <tstellar@91177308-0d34-0410-b5e6-96231b3b80d8>2012-10-16 17:52:57 +0000
commit47ca737da5de48d621fa88adb89b6265fe224453 (patch)
tree7e60638529c99989f22bff7a0f40a71a9c3a7399
parent5f65515268b0a646b3e5ccedd85b6e0b5f831ac3 (diff)
Merge master branch
git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/R600/@166033 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Makefile1
-rw-r--r--Makefile.rules4
-rw-r--r--docs/BitCodeFormat.rst49
-rw-r--r--docs/DeveloperPolicy.rst3
-rw-r--r--docs/ExtendingLLVM.rst4
-rw-r--r--docs/GettingStarted.rst64
-rw-r--r--docs/HowToSetUpLLVMStyleRTTI.rst141
-rw-r--r--docs/Lexicon.rst13
-rw-r--r--docs/Phabricator.rst94
-rw-r--r--docs/SphinxQuickstartTemplate.rst125
-rw-r--r--docs/userguides.rst6
-rw-r--r--examples/ExceptionDemo/ExceptionDemo.cpp1177
-rw-r--r--include/llvm-c/Core.h2
-rw-r--r--include/llvm-c/Target.h10
-rw-r--r--include/llvm/ADT/BitVector.h56
-rw-r--r--include/llvm/ADT/ImmutableSet.h2
-rw-r--r--include/llvm/ADT/SmallBitVector.h30
-rw-r--r--include/llvm/ADT/Triple.h6
-rw-r--r--include/llvm/Analysis/DependenceAnalysis.h891
-rw-r--r--include/llvm/Analysis/Passes.h9
-rw-r--r--include/llvm/Analysis/ScalarEvolution.h1
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpander.h4
-rw-r--r--include/llvm/Analysis/ScalarEvolutionExpressions.h14
-rw-r--r--include/llvm/Argument.h1
-rw-r--r--include/llvm/Attributes.h272
-rw-r--r--include/llvm/BasicBlock.h1
-rw-r--r--include/llvm/Bitcode/BitstreamReader.h2
-rw-r--r--include/llvm/CodeGen/CommandFlags.h228
-rw-r--r--include/llvm/CodeGen/LiveIntervalAnalysis.h27
-rw-r--r--include/llvm/CodeGen/LiveVariables.h6
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h17
-rw-r--r--include/llvm/CodeGen/MachineRegisterInfo.h31
-rw-r--r--include/llvm/CodeGen/MachineScheduler.h4
-rw-r--r--include/llvm/CodeGen/PseudoSourceValue.h4
-rw-r--r--include/llvm/CodeGen/RegisterClassInfo.h19
-rw-r--r--include/llvm/CodeGen/RegisterScavenging.h9
-rw-r--r--include/llvm/CodeGen/ScheduleDAGILP.h86
-rw-r--r--include/llvm/CodeGen/SelectionDAGNodes.h30
-rw-r--r--include/llvm/Constant.h2
-rw-r--r--include/llvm/Constants.h13
-rw-r--r--include/llvm/DataLayout.h16
-rw-r--r--include/llvm/DerivedTypes.h8
-rw-r--r--include/llvm/Function.h13
-rw-r--r--include/llvm/GlobalAlias.h1
-rw-r--r--include/llvm/GlobalValue.h1
-rw-r--r--include/llvm/GlobalVariable.h1
-rw-r--r--include/llvm/InitializePasses.h2
-rw-r--r--include/llvm/InlineAsm.h1
-rw-r--r--include/llvm/InstrTypes.h5
-rw-r--r--include/llvm/Instruction.h1
-rw-r--r--include/llvm/Instructions.h127
-rw-r--r--include/llvm/IntrinsicInst.h9
-rw-r--r--include/llvm/Intrinsics.h4
-rw-r--r--include/llvm/LinkAllPasses.h1
-rw-r--r--include/llvm/MC/MCAssembler.h10
-rw-r--r--include/llvm/MC/MCExpr.h7
-rw-r--r--include/llvm/MC/MCParser/MCAsmParser.h22
-rw-r--r--include/llvm/MC/MCParser/MCParsedAsmOperand.h24
-rw-r--r--include/llvm/MC/MCSection.h2
-rw-r--r--include/llvm/MC/MCSectionCOFF.h1
-rw-r--r--include/llvm/MC/MCSectionELF.h1
-rw-r--r--include/llvm/MC/MCSectionMachO.h1
-rw-r--r--include/llvm/MC/MCStreamer.h5
-rw-r--r--include/llvm/MC/MCTargetAsmParser.h30
-rw-r--r--include/llvm/Metadata.h2
-rw-r--r--include/llvm/Object/Archive.h1
-rw-r--r--include/llvm/Object/Binary.h1
-rw-r--r--include/llvm/Object/COFF.h1
-rw-r--r--include/llvm/Object/ELF.h1
-rw-r--r--include/llvm/Object/MachO.h1
-rw-r--r--include/llvm/Object/ObjectFile.h23
-rw-r--r--include/llvm/Operator.h6
-rw-r--r--include/llvm/Support/Casting.h13
-rw-r--r--include/llvm/Support/Memory.h4
-rw-r--r--include/llvm/Support/YAMLParser.h7
-rw-r--r--include/llvm/TableGen/Record.h146
-rw-r--r--include/llvm/Target/TargetLowering.h4
-rw-r--r--include/llvm/Target/TargetMachine.h6
-rw-r--r--include/llvm/Target/TargetTransformImpl.h54
-rw-r--r--include/llvm/TargetTransformInfo.h128
-rw-r--r--include/llvm/Transforms/Instrumentation.h2
-rw-r--r--include/llvm/Transforms/Scalar.h7
-rw-r--r--include/llvm/Transforms/Utils/Local.h3
-rw-r--r--include/llvm/Transforms/Utils/SimplifyLibCalls.h43
-rw-r--r--include/llvm/Type.h3
-rw-r--r--include/llvm/User.h1
-rw-r--r--include/llvm/Value.h5
-rw-r--r--lib/Analysis/Analysis.cpp1
-rw-r--r--lib/Analysis/BasicAliasAnalysis.cpp7
-rw-r--r--lib/Analysis/CMakeLists.txt1
-rw-r--r--lib/Analysis/CodeMetrics.cpp6
-rw-r--r--lib/Analysis/ConstantFolding.cpp12
-rw-r--r--lib/Analysis/DependenceAnalysis.cpp3781
-rw-r--r--lib/Analysis/InlineCost.cpp15
-rw-r--r--lib/Analysis/InstructionSimplify.cpp11
-rw-r--r--lib/Analysis/ScalarEvolutionExpander.cpp12
-rw-r--r--lib/Analysis/ValueTracking.cpp6
-rw-r--r--lib/AsmParser/LLParser.cpp60
-rw-r--r--lib/AsmParser/LLParser.h2
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.cpp94
-rw-r--r--lib/Bitcode/Reader/BitcodeReader.h67
-rw-r--r--lib/Bitcode/Writer/BitcodeWriter.cpp123
-rw-r--r--lib/CodeGen/AggressiveAntiDepBreaker.cpp4
-rw-r--r--lib/CodeGen/AllocationOrder.cpp5
-rw-r--r--lib/CodeGen/Analysis.cpp6
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp8
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp8
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h8
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp18
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp2
-rw-r--r--lib/CodeGen/CalcSpillWeights.cpp2
-rw-r--r--lib/CodeGen/CallingConvLower.cpp2
-rw-r--r--lib/CodeGen/CriticalAntiDepBreaker.cpp2
-rw-r--r--lib/CodeGen/DeadMachineInstructionElim.cpp8
-rw-r--r--lib/CodeGen/LiveIntervalAnalysis.cpp720
-rw-r--r--lib/CodeGen/LiveRangeEdit.cpp2
-rw-r--r--lib/CodeGen/LiveVariables.cpp6
-rw-r--r--lib/CodeGen/MachineCSE.cpp8
-rw-r--r--lib/CodeGen/MachineCopyPropagation.cpp13
-rw-r--r--lib/CodeGen/MachineFunction.cpp4
-rw-r--r--lib/CodeGen/MachineRegisterInfo.cpp14
-rw-r--r--lib/CodeGen/MachineScheduler.cpp126
-rw-r--r--lib/CodeGen/MachineSink.cpp2
-rw-r--r--lib/CodeGen/MachineTraceMetrics.cpp14
-rw-r--r--lib/CodeGen/MachineTraceMetrics.h2
-rw-r--r--lib/CodeGen/MachineVerifier.cpp7
-rw-r--r--lib/CodeGen/Passes.cpp4
-rw-r--r--lib/CodeGen/PeepholeOptimizer.cpp5
-rw-r--r--lib/CodeGen/PostRASchedulerList.cpp5
-rw-r--r--lib/CodeGen/RegAllocFast.cpp8
-rw-r--r--lib/CodeGen/RegAllocPBQP.cpp6
-rw-r--r--lib/CodeGen/RegisterClassInfo.cpp10
-rw-r--r--lib/CodeGen/RegisterCoalescer.cpp86
-rw-r--r--lib/CodeGen/RegisterPressure.cpp12
-rw-r--r--lib/CodeGen/RegisterScavenging.cpp7
-rw-r--r--lib/CodeGen/ScheduleDAGInstrs.cpp93
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp81
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp50
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypes.h2
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp4
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp10
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp5
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp5
-rw-r--r--lib/CodeGen/TargetInstrInfoImpl.cpp2
-rw-r--r--lib/CodeGen/TargetLoweringObjectFileImpl.cpp4
-rw-r--r--lib/CodeGen/TargetSchedule.cpp40
-rw-r--r--lib/CodeGen/VirtRegMap.cpp5
-rw-r--r--lib/ExecutionEngine/ExecutionEngine.cpp12
-rw-r--r--lib/ExecutionEngine/Interpreter/Execution.cpp3
-rw-r--r--lib/ExecutionEngine/Interpreter/ExternalFunctions.cpp2
-rw-r--r--lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp14
-rw-r--r--lib/ExecutionEngine/JIT/JITEmitter.cpp14
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp22
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp11
-rw-r--r--lib/MC/MCAsmStreamer.cpp9
-rw-r--r--lib/MC/MCELFStreamer.cpp8
-rw-r--r--lib/MC/MCParser/AsmParser.cpp56
-rw-r--r--lib/MC/MCStreamer.cpp4
-rw-r--r--lib/Support/Triple.cpp4
-rw-r--r--lib/TableGen/CMakeLists.txt2
-rw-r--r--lib/TableGen/Makefile2
-rw-r--r--lib/TableGen/Record.cpp150
-rw-r--r--lib/TableGen/TGParser.cpp53
-rw-r--r--lib/Target/ARM/ARMConstantPoolValue.h5
-rw-r--r--lib/Target/ARM/ARMELFWriterInfo.cpp2
-rw-r--r--lib/Target/ARM/ARMISelLowering.cpp59
-rw-r--r--lib/Target/ARM/ARMISelLowering.h2
-rw-r--r--lib/Target/ARM/ARMInstrNEON.td25
-rw-r--r--lib/Target/ARM/ARMTargetMachine.cpp6
-rw-r--r--lib/Target/ARM/ARMTargetMachine.h18
-rw-r--r--lib/Target/ARM/AsmParser/ARMAsmParser.cpp18
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMMCExpr.h3
-rw-r--r--lib/Target/CMakeLists.txt1
-rw-r--r--lib/Target/CellSPU/SPUTargetMachine.cpp3
-rw-r--r--lib/Target/CellSPU/SPUTargetMachine.h9
-rw-r--r--lib/Target/CppBackend/CPPBackend.cpp10
-rw-r--r--lib/Target/Hexagon/HexagonTargetMachine.cpp5
-rw-r--r--lib/Target/Hexagon/HexagonTargetMachine.h11
-rw-r--r--lib/Target/MBlaze/AsmParser/MBlazeAsmParser.cpp17
-rw-r--r--lib/Target/MBlaze/MBlazeELFWriterInfo.cpp2
-rw-r--r--lib/Target/MBlaze/MBlazeIntrinsicInfo.cpp5
-rw-r--r--lib/Target/MBlaze/MBlazeTargetMachine.cpp2
-rw-r--r--lib/Target/MBlaze/MBlazeTargetMachine.h7
-rw-r--r--lib/Target/MSP430/MSP430ISelLowering.cpp4
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.cpp2
-rw-r--r--lib/Target/MSP430/MSP430TargetMachine.h10
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp18
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.cpp23
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.td41
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td30
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp2
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h9
-rw-r--r--lib/Target/NVPTX/NVPTXAsmPrinter.cpp8
-rw-r--r--lib/Target/NVPTX/NVPTXTargetMachine.cpp3
-rw-r--r--lib/Target/NVPTX/NVPTXTargetMachine.h10
-rw-r--r--lib/Target/PowerPC/PPCAsmPrinter.cpp10
-rw-r--r--lib/Target/PowerPC/PPCFrameLowering.cpp16
-rw-r--r--lib/Target/PowerPC/PPCISelDAGToDAG.cpp4
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp39
-rw-r--r--lib/Target/PowerPC/PPCInstrInfo.cpp18
-rw-r--r--lib/Target/PowerPC/PPCRegisterInfo.cpp2
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.cpp3
-rw-r--r--lib/Target/PowerPC/PPCTargetMachine.h9
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.cpp2
-rw-r--r--lib/Target/Sparc/SparcTargetMachine.h9
-rw-r--r--lib/Target/Target.cpp11
-rw-r--r--lib/Target/TargetTransformImpl.cpp43
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp99
-rw-r--r--lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp4
-rw-r--r--lib/Target/X86/X86AsmPrinter.cpp3
-rw-r--r--lib/Target/X86/X86FrameLowering.cpp4
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp4
-rw-r--r--lib/Target/X86/X86ISelLowering.cpp385
-rw-r--r--lib/Target/X86/X86ISelLowering.h20
-rw-r--r--lib/Target/X86/X86InstrCompiler.td27
-rw-r--r--lib/Target/X86/X86InstrFragmentsSIMD.td3
-rw-r--r--lib/Target/X86/X86InstrInfo.td8
-rw-r--r--lib/Target/X86/X86InstrSSE.td11
-rw-r--r--lib/Target/X86/X86MCInstLower.cpp26
-rw-r--r--lib/Target/X86/X86MCInstLower.h52
-rw-r--r--lib/Target/X86/X86RegisterInfo.cpp5
-rw-r--r--lib/Target/X86/X86RegisterInfo.h1
-rw-r--r--lib/Target/X86/X86TargetMachine.cpp6
-rw-r--r--lib/Target/X86/X86TargetMachine.h17
-rw-r--r--lib/Target/XCore/XCoreTargetMachine.cpp2
-rw-r--r--lib/Target/XCore/XCoreTargetMachine.h9
-rw-r--r--lib/Transforms/IPO/ArgumentPromotion.cpp33
-rw-r--r--lib/Transforms/IPO/DeadArgumentElimination.cpp44
-rw-r--r--lib/Transforms/IPO/FunctionAttrs.cpp20
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp12
-rw-r--r--lib/Transforms/IPO/IPO.cpp2
-rw-r--r--lib/Transforms/IPO/PruneEH.cpp6
-rw-r--r--lib/Transforms/InstCombine/InstCombine.h2
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp81
-rw-r--r--lib/Transforms/InstCombine/InstCombineCasts.cpp10
-rw-r--r--lib/Transforms/InstCombine/InstCombineCompares.cpp9
-rw-r--r--lib/Transforms/InstCombine/InstructionCombining.cpp3
-rw-r--r--lib/Transforms/Instrumentation/AddressSanitizer.cpp117
-rw-r--r--lib/Transforms/Scalar/CodeGenPrepare.cpp6
-rw-r--r--lib/Transforms/Scalar/DeadStoreElimination.cpp63
-rw-r--r--lib/Transforms/Scalar/LoopStrengthReduce.cpp134
-rw-r--r--lib/Transforms/Scalar/MemCpyOptimizer.cpp5
-rw-r--r--lib/Transforms/Scalar/ObjCARC.cpp51
-rw-r--r--lib/Transforms/Scalar/SROA.cpp371
-rw-r--r--lib/Transforms/Scalar/SimplifyLibCalls.cpp301
-rw-r--r--lib/Transforms/Utils/BuildLibCalls.cpp67
-rw-r--r--lib/Transforms/Utils/CMakeLists.txt1
-rw-r--r--lib/Transforms/Utils/CloneFunction.cpp8
-rw-r--r--lib/Transforms/Utils/Local.cpp3
-rw-r--r--lib/Transforms/Utils/LowerInvoke.cpp32
-rw-r--r--lib/Transforms/Utils/SimplifyCFG.cpp10
-rw-r--r--lib/Transforms/Utils/SimplifyLibCalls.cpp579
-rw-r--r--lib/VMCore/Attributes.cpp255
-rw-r--r--lib/VMCore/AttributesImpl.h (renamed from include/llvm/AttributesImpl.h)4
-rw-r--r--lib/VMCore/AutoUpgrade.cpp3
-rw-r--r--lib/VMCore/CMakeLists.txt1
-rw-r--r--lib/VMCore/Core.cpp39
-rw-r--r--lib/VMCore/Function.cpp6
-rw-r--r--lib/VMCore/Instructions.cpp18
-rw-r--r--lib/VMCore/LLVMContextImpl.cpp8
-rw-r--r--lib/VMCore/LLVMContextImpl.h2
-rw-r--r--lib/VMCore/TargetTransformInfo.cpp27
-rw-r--r--lib/VMCore/Verifier.cpp11
-rw-r--r--test/Analysis/DependenceAnalysis/Banerjee.ll595
-rw-r--r--test/Analysis/DependenceAnalysis/Coupled.ll509
-rw-r--r--test/Analysis/DependenceAnalysis/ExactRDIV.ll508
-rw-r--r--test/Analysis/DependenceAnalysis/ExactSIV.ll428
-rw-r--r--test/Analysis/DependenceAnalysis/GCD.ll597
-rw-r--r--test/Analysis/DependenceAnalysis/Preliminary.ll469
-rw-r--r--test/Analysis/DependenceAnalysis/Propagating.ll467
-rw-r--r--test/Analysis/DependenceAnalysis/Separability.ll267
-rw-r--r--test/Analysis/DependenceAnalysis/StrongSIV.ll342
-rw-r--r--test/Analysis/DependenceAnalysis/SymbolicRDIV.ll312
-rw-r--r--test/Analysis/DependenceAnalysis/SymbolicSIV.ll330
-rw-r--r--test/Analysis/DependenceAnalysis/WeakCrossingSIV.ll220
-rw-r--r--test/Analysis/DependenceAnalysis/WeakZeroDstSIV.ll212
-rw-r--r--test/Analysis/DependenceAnalysis/WeakZeroSrcSIV.ll212
-rw-r--r--test/Analysis/DependenceAnalysis/ZIV.ll53
-rw-r--r--test/Analysis/DependenceAnalysis/lit.local.cfg1
-rw-r--r--test/Assembler/invalid-fwdref1.ll4
-rw-r--r--test/Bitcode/function-encoding-rel-operands.ll49
-rw-r--r--test/CMakeLists.txt2
-rw-r--r--test/CodeGen/ARM/2011-06-16-TailCallByVal.ll5
-rw-r--r--test/CodeGen/ARM/2012-10-04-AAPCS-byval-align8.ll56
-rw-r--r--test/CodeGen/ARM/2012-10-04-LDRB_POST_IMM-Crash.ll17
-rw-r--r--test/CodeGen/ARM/coalesce-subregs.ll77
-rw-r--r--test/CodeGen/ARM/divmod.ll46
-rw-r--r--test/CodeGen/ARM/struct_byval.ll44
-rw-r--r--test/CodeGen/ARM/vbsl.ll48
-rw-r--r--test/CodeGen/ARM/vdup.ll36
-rw-r--r--test/CodeGen/ARM/vselect_imax.ll12
-rw-r--r--test/CodeGen/Mips/div.ll18
-rw-r--r--test/CodeGen/Mips/div_rem.ll21
-rw-r--r--test/CodeGen/Mips/divu.ll18
-rw-r--r--test/CodeGen/Mips/divu_remu.ll23
-rw-r--r--test/CodeGen/Mips/rem.ll19
-rw-r--r--test/CodeGen/Mips/remu.ll18
-rw-r--r--test/CodeGen/PowerPC/2012-10-12-bitcast.ll20
-rw-r--r--test/CodeGen/PowerPC/floatPSA.ll97
-rw-r--r--test/CodeGen/PowerPC/novrsave.ll15
-rw-r--r--test/CodeGen/PowerPC/structsinmem.ll227
-rw-r--r--test/CodeGen/PowerPC/structsinregs.ll48
-rw-r--r--test/CodeGen/PowerPC/vrspill.ll19
-rw-r--r--test/CodeGen/X86/crash.ll103
-rw-r--r--test/CodeGen/X86/early-ifcvt-crash.ll32
-rw-r--r--test/CodeGen/X86/fp-load-trunc.ll61
-rw-r--r--test/CodeGen/X86/fp-trunc.ll53
-rw-r--r--test/CodeGen/X86/handle-move.ll74
-rw-r--r--test/CodeGen/X86/misched-ilp.ll25
-rw-r--r--test/CodeGen/X86/misched-new.ll28
-rw-r--r--test/CodeGen/X86/pr14088.ll25
-rw-r--r--test/CodeGen/X86/select.ll13
-rw-r--r--test/CodeGen/X86/select_const.ll16
-rw-r--r--test/CodeGen/X86/sjlj.ll46
-rw-r--r--test/Instrumentation/AddressSanitizer/instrument_global.ll2
-rw-r--r--test/MC/Mips/mips-coprocessor-encodings.s37
-rw-r--r--test/MC/Mips/mips-register-names.s71
-rw-r--r--test/MC/Mips/mips64-register-names.s70
-rw-r--r--test/MC/X86/x86_nop.s12
-rw-r--r--test/Transforms/InstCombine/strcat-1.ll38
-rw-r--r--test/Transforms/InstCombine/strcat-2.ll32
-rw-r--r--test/Transforms/InstCombine/strcat-3.ll22
-rw-r--r--test/Transforms/InstCombine/strchr-1.ll54
-rw-r--r--test/Transforms/InstCombine/strchr-2.ll21
-rw-r--r--test/Transforms/InstCombine/strcmp-1.ll82
-rw-r--r--test/Transforms/InstCombine/strcmp-2.ll20
-rw-r--r--test/Transforms/InstCombine/strncat-1.ll37
-rw-r--r--test/Transforms/InstCombine/strncat-2.ll53
-rw-r--r--test/Transforms/InstCombine/strncat-3.ll22
-rw-r--r--test/Transforms/InstCombine/strncmp-1.ll97
-rw-r--r--test/Transforms/InstCombine/strncmp-2.ll20
-rw-r--r--test/Transforms/InstCombine/strrchr-1.ll54
-rw-r--r--test/Transforms/InstCombine/strrchr-2.ll21
-rw-r--r--test/Transforms/InstCombine/struct-assign-tbaa.ll30
-rw-r--r--test/Transforms/InstCombine/weak-symbols.ll33
-rw-r--r--test/Transforms/SROA/alignment.ll31
-rw-r--r--test/Transforms/SROA/basictest.ll99
-rw-r--r--test/Transforms/SROA/phi-and-select.ll42
-rw-r--r--test/Transforms/SROA/vector-promotion.ll16
-rw-r--r--test/Transforms/SimplifyLibCalls/StrCat.ll33
-rw-r--r--test/Transforms/SimplifyLibCalls/StrChr.ll26
-rw-r--r--test/Transforms/SimplifyLibCalls/StrCmp.ll65
-rw-r--r--test/Transforms/SimplifyLibCalls/StrNCat.ll31
-rw-r--r--test/Transforms/SimplifyLibCalls/StrNCmp.ll78
-rw-r--r--test/Transforms/SimplifyLibCalls/StrRChr.ll23
-rw-r--r--test/Transforms/SimplifyLibCalls/weak-symbols.ll26
-rw-r--r--tools/bugpoint-passes/bugpoint.exports1
-rw-r--r--tools/llc/llc.cpp215
-rw-r--r--tools/lli/lli.cpp28
-rw-r--r--tools/lto/LTOCodeGenerator.cpp22
-rw-r--r--tools/lto/LTOModule.cpp20
-rw-r--r--tools/opt/CMakeLists.txt2
-rw-r--r--tools/opt/LLVMBuild.txt2
-rw-r--r--tools/opt/Makefile2
-rw-r--r--tools/opt/opt.cpp78
-rw-r--r--unittests/ADT/BitVectorTest.cpp52
-rw-r--r--unittests/ADT/CMakeLists.txt1
-rw-r--r--unittests/ADT/ImmutableMapTest.cpp50
-rw-r--r--unittests/ADT/TripleTest.cpp12
-rw-r--r--unittests/ExecutionEngine/JIT/JITTest.cpp1
-rw-r--r--unittests/Support/Casting.cpp51
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp57
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp2
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp8
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp84
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp25
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp2
-rw-r--r--utils/TableGen/DAGISelMatcher.h2
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp10
-rw-r--r--utils/TableGen/FastISelEmitter.cpp11
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp14
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp6
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp10
-rw-r--r--utils/TableGen/Makefile1
-rw-r--r--utils/TableGen/PseudoLoweringEmitter.cpp8
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp4
-rw-r--r--utils/TableGen/SetTheory.cpp22
-rw-r--r--utils/TableGen/TGValueTypes.cpp26
381 files changed, 18653 insertions, 4194 deletions
diff --git a/Makefile b/Makefile
index 6ea55336b7a..e59441c4329 100644
--- a/Makefile
+++ b/Makefile
@@ -77,7 +77,6 @@ ifeq ($(MAKECMDGOALS),install-clang)
endif
ifeq ($(MAKECMDGOALS),clang-only)
- BUILD_CLANG_ONLY := YES
DIRS := $(filter-out tools docs unittests, $(DIRS)) \
tools/clang tools/lto
OPTIONAL_DIRS :=
diff --git a/Makefile.rules b/Makefile.rules
index b929ffea59f..b2b02c25d44 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -571,7 +571,11 @@ endif
#--------------------------------------------------------------------
ifeq ($(HOST_OS),Darwin)
+ ifdef MACOSX_DEPLOYMENT_TARGET
+ DARWIN_VERSION := $(MACOSX_DEPLOYMENT_TARGET)
+ else
DARWIN_VERSION := `sw_vers -productVersion`
+ endif
# Strip a number like 10.4.7 to 10.4
DARWIN_VERSION := $(shell echo $(DARWIN_VERSION)| sed -E 's/(10.[0-9]).*/\1/')
# Get "4" out of 10.4 for later pieces in the makefile.
diff --git a/docs/BitCodeFormat.rst b/docs/BitCodeFormat.rst
index d3995e7036b..bd26f7b1502 100644
--- a/docs/BitCodeFormat.rst
+++ b/docs/BitCodeFormat.rst
@@ -489,6 +489,8 @@ The magic number for LLVM IR files is:
When combined with the bitcode magic number and viewed as bytes, this is
``"BC 0xC0DE"``.
+.. _Signed VBRs:
+
Signed VBRs
^^^^^^^^^^^
@@ -507,6 +509,7 @@ As such, signed VBR values of a specific width are emitted as follows:
With this encoding, small positive and small negative values can both be emitted
efficiently. Signed VBR encoding is used in ``CST_CODE_INTEGER`` and
``CST_CODE_WIDE_INTEGER`` records within ``CONSTANTS_BLOCK`` blocks.
+It is also used for phi instruction operands in `MODULE_CODE_VERSION`_ 1.
LLVM IR Blocks
^^^^^^^^^^^^^^
@@ -553,13 +556,57 @@ block may contain the following sub-blocks:
* `FUNCTION_BLOCK`_
* `METADATA_BLOCK`_
+.. _MODULE_CODE_VERSION:
+
MODULE_CODE_VERSION Record
^^^^^^^^^^^^^^^^^^^^^^^^^^
``[VERSION, version#]``
The ``VERSION`` record (code 1) contains a single value indicating the format
-version. Only version 0 is supported at this time.
+version. Versions 0 and 1 are supported at this time. The difference between
+version 0 and 1 is in the encoding of instruction operands in
+each `FUNCTION_BLOCK`_.
+
+In version 0, each value defined by an instruction is assigned an ID
+unique to the function. Function-level value IDs are assigned starting from
+``NumModuleValues`` since they share the same namespace as module-level
+values. The value enumerator resets after each function. When a value is
+an operand of an instruction, the value ID is used to represent the operand.
+For large functions or large modules, these operand values can be large.
+
+The encoding in version 1 attempts to avoid large operand values
+in common cases. Instead of using the value ID directly, operands are
+encoded as relative to the current instruction. Thus, if an operand
+is the value defined by the previous instruction, the operand
+will be encoded as 1.
+
+For example, instead of
+
+.. code-block:: llvm
+
+ #n = load #n-1
+ #n+1 = icmp eq #n, #const0
+ br #n+1, label #(bb1), label #(bb2)
+
+version 1 will encode the instructions as
+
+.. code-block:: llvm
+
+ #n = load #1
+ #n+1 = icmp eq #1, (#n+1)-#const0
+ br #1, label #(bb1), label #(bb2)
+
+Note in the example that operands which are constants also use
+the relative encoding, while operands like basic block labels
+do not use the relative encoding.
+
+Forward references will result in a negative value.
+This can be inefficient, as operands are normally encoded
+as unsigned VBRs. However, forward references are rare, except in the
+case of phi instructions. For phi instructions, operands are encoded as
+`Signed VBRs`_ to deal with forward references.
+
MODULE_CODE_TRIPLE Record
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/docs/DeveloperPolicy.rst b/docs/DeveloperPolicy.rst
index f940dbc579a..e35e7295564 100644
--- a/docs/DeveloperPolicy.rst
+++ b/docs/DeveloperPolicy.rst
@@ -137,6 +137,9 @@ reviewees. If someone is kind enough to review your code, you should return the
favor for someone else. Note that anyone is welcome to review and give feedback
on a patch, but only people with Subversion write access can approve it.
+There is a web based code review tool that can optionally be used
+for code reviews. See :doc:`Phabricator`.
+
Code Owners
-----------
diff --git a/docs/ExtendingLLVM.rst b/docs/ExtendingLLVM.rst
index e41cfd996e5..6df08eee985 100644
--- a/docs/ExtendingLLVM.rst
+++ b/docs/ExtendingLLVM.rst
@@ -270,7 +270,7 @@ Adding a derived type
add support for derived type to:
- .. code:: c++
+ .. code-block:: c++
std::string getTypeDescription(const Type &Ty,
std::vector<const Type*> &TypeStack)
@@ -296,7 +296,7 @@ Adding a derived type
modify
- .. code:: c++
+ .. code-block:: c++
void calcTypeName(const Type *Ty,
std::vector<const Type*> &TypeStack,
diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst
index d78c78f1cc2..68768921f6a 100644
--- a/docs/GettingStarted.rst
+++ b/docs/GettingStarted.rst
@@ -505,7 +505,7 @@ directory:
If you would like to get the LLVM test suite (a separate package as of 1.4), you
get it from the Subversion repository:
-.. code:: bash
+.. code-block:: bash
% cd llvm/projects
% svn co http://llvm.org/svn/llvm-project/test-suite/trunk test-suite
@@ -523,13 +523,13 @@ marks (so, you can recreate git-svn metadata locally). Note that right now
mirrors reflect only ``trunk`` for each project. You can do the read-only GIT
clone of LLVM via:
-.. code:: bash
+.. code-block:: bash
% git clone http://llvm.org/git/llvm.git
If you want to check out clang too, run:
-.. code:: bash
+.. code-block:: bash
% git clone http://llvm.org/git/llvm.git
% cd llvm/tools
@@ -540,26 +540,26 @@ pull --rebase`` instead of ``git pull`` to avoid generating a non-linear history
in your clone. To configure ``git pull`` to pass ``--rebase`` by default on the
master branch, run the following command:
-.. code:: bash
+.. code-block:: bash
% git config branch.master.rebase true
Sending patches with Git
^^^^^^^^^^^^^^^^^^^^^^^^
-Please read `Developer Policy <DeveloperPolicy.html#patches>`_, too.
+Please read `Developer Policy <DeveloperPolicy.html#one-off-patches>`_, too.
Assume ``master`` points the upstream and ``mybranch`` points your working
branch, and ``mybranch`` is rebased onto ``master``. At first you may check
sanity of whitespaces:
-.. code:: bash
+.. code-block:: bash
% git diff --check master..mybranch
The easiest way to generate a patch is as below:
-.. code:: bash
+.. code-block:: bash
% git diff master..mybranch > /path/to/mybranch.diff
@@ -570,20 +570,20 @@ could be accepted with ``patch -p1 -N``.
But you may generate patchset with git-format-patch. It generates by-each-commit
patchset. To generate patch files to attach to your article:
-.. code:: bash
+.. code-block:: bash
% git format-patch --no-attach master..mybranch -o /path/to/your/patchset
If you would like to send patches directly, you may use git-send-email or
git-imap-send. Here is an example to generate the patchset in Gmail's [Drafts].
-.. code:: bash
+.. code-block:: bash
% git format-patch --attach master..mybranch --stdout | git imap-send
Then, your .git/config should have [imap] sections.
-.. code:: bash
+.. code-block:: bash
[imap]
host = imaps://imap.gmail.com
@@ -594,16 +594,16 @@ Then, your .git/config should have [imap] sections.
; in English
folder = "[Gmail]/Drafts"
; example for Japanese, "Modified UTF-7" encoded.
- folder = "[Gmail]/&amp;Tgtm+DBN-"
+ folder = "[Gmail]/&Tgtm+DBN-"
; example for Traditional Chinese
- folder = "[Gmail]/&amp;g0l6Pw-"
+ folder = "[Gmail]/&g0l6Pw-"
For developers to work with git-svn
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
To set up clone from which you can submit code using ``git-svn``, run:
-.. code:: bash
+.. code-block:: bash
% git clone http://llvm.org/git/llvm.git
% cd llvm
@@ -622,7 +622,7 @@ To set up clone from which you can submit code using ``git-svn``, run:
To update this clone without generating git-svn tags that conflict with the
upstream git repo, run:
-.. code:: bash
+.. code-block:: bash
% git fetch && (cd tools/clang && git fetch) # Get matching revisions of both trees.
% git checkout master
@@ -640,7 +640,7 @@ The git-svn metadata can get out of sync after you mess around with branches and
``dcommit``. When that happens, ``git svn dcommit`` stops working, complaining
about files with uncommitted changes. The fix is to rebuild the metadata:
-.. code:: bash
+.. code-block:: bash
% rm -rf .git/svn
% git svn rebase -l
@@ -722,13 +722,13 @@ To configure LLVM, follow these steps:
#. Change directory into the object root directory:
- .. code:: bash
+ .. code-block:: bash
% cd OBJ_ROOT
#. Run the ``configure`` script located in the LLVM source tree:
- .. code:: bash
+ .. code-block:: bash
% SRC_ROOT/configure --prefix=/install/path [other options]
@@ -764,7 +764,7 @@ Profile Builds
Once you have LLVM configured, you can build it by entering the *OBJ_ROOT*
directory and issuing the following command:
-.. code:: bash
+.. code-block:: bash
% gmake
@@ -775,7 +775,7 @@ If you have multiple processors in your machine, you may wish to use some of the
parallel build options provided by GNU Make. For example, you could use the
command:
-.. code:: bash
+.. code-block:: bash
% gmake -j2
@@ -866,13 +866,13 @@ This is accomplished in the typical autoconf manner:
* Change directory to where the LLVM object files should live:
- .. code:: bash
+ .. code-block:: bash
% cd OBJ_ROOT
* Run the ``configure`` script found in the LLVM source directory:
- .. code:: bash
+ .. code-block:: bash
% SRC_ROOT/configure
@@ -918,7 +918,7 @@ module, and you have root access on the system, you can set your system up to
execute LLVM bitcode files directly. To do this, use commands like this (the
first command may not be required if you are already using the module):
-.. code:: bash
+.. code-block:: bash
% mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
% echo ':llvm:M::BC::/path/to/lli:' > /proc/sys/fs/binfmt_misc/register
@@ -928,7 +928,7 @@ first command may not be required if you are already using the module):
This allows you to execute LLVM bitcode files directly. On Debian, you can also
use this command instead of the 'echo' command above:
-.. code:: bash
+.. code-block:: bash
% sudo update-binfmts --install llvm /path/to/lli --magic 'BC'
@@ -1208,7 +1208,7 @@ Example with clang
#. First, create a simple C file, name it 'hello.c':
- .. code:: c
+ .. code-block:: c
#include <stdio.h>
@@ -1219,7 +1219,7 @@ Example with clang
#. Next, compile the C file into a native executable:
- .. code:: bash
+ .. code-block:: bash
% clang hello.c -o hello
@@ -1230,7 +1230,7 @@ Example with clang
#. Next, compile the C file into a LLVM bitcode file:
- .. code:: bash
+ .. code-block:: bash
% clang -O3 -emit-llvm hello.c -c -o hello.bc
@@ -1240,13 +1240,13 @@ Example with clang
#. Run the program in both forms. To run the program, use:
- .. code:: bash
+ .. code-block:: bash
% ./hello
and
- .. code:: bash
+ .. code-block:: bash
% lli hello.bc
@@ -1255,19 +1255,19 @@ Example with clang
#. Use the ``llvm-dis`` utility to take a look at the LLVM assembly code:
- .. code:: bash
+ .. code-block:: bash
% llvm-dis < hello.bc | less
#. Compile the program to native assembly using the LLC code generator:
- .. code:: bash
+ .. code-block:: bash
% llc hello.bc -o hello.s
#. Assemble the native assembly language file into a program:
- .. code:: bash
+ .. code-block:: bash
**Solaris:** % /opt/SUNWspro/bin/cc -xarch=v9 hello.s -o hello.native
@@ -1275,7 +1275,7 @@ Example with clang
#. Execute the native code program:
- .. code:: bash
+ .. code-block:: bash
% ./hello.native
diff --git a/docs/HowToSetUpLLVMStyleRTTI.rst b/docs/HowToSetUpLLVMStyleRTTI.rst
index b5c1b78afeb..aa1ad84afee 100644
--- a/docs/HowToSetUpLLVMStyleRTTI.rst
+++ b/docs/HowToSetUpLLVMStyleRTTI.rst
@@ -65,10 +65,9 @@ steps:
#include "llvm/Support/Casting.h"
-
#. In the base class, introduce an enum which discriminates all of the
- different classes in the hierarchy, and stash the enum value somewhere in
- the base class.
+ different concrete classes in the hierarchy, and stash the enum value
+ somewhere in the base class.
Here is the code after introducing this change:
@@ -78,8 +77,8 @@ steps:
public:
+ /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
+ enum ShapeKind {
- + SquareKind,
- + CircleKind
+ + SK_Square,
+ + SK_Circle
+ };
+private:
+ const ShapeKind Kind;
@@ -103,7 +102,7 @@ steps:
You might wonder why the ``Kind`` enum doesn't have an entry for
``Shape``. The reason for this is that since ``Shape`` is abstract
(``computeArea() = 0;``), you will never actually have non-derived
- instances of exactly that class (only subclasses). See `Concrete Bases
+ instances of exactly that class (only subclasses). See `Concrete Bases
and Deeper Hierarchies`_ for information on how to deal with
non-abstract bases. It's worth mentioning here that unlike
``dynamic_cast<>``, LLVM-style RTTI can be used (and is often used) for
@@ -122,8 +121,8 @@ steps:
public:
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
enum ShapeKind {
- SquareKind,
- CircleKind
+ SK_Square,
+ SK_Circle
};
private:
const ShapeKind Kind;
@@ -139,7 +138,7 @@ steps:
double SideLength;
public:
- Square(double S) : SideLength(S) {}
- + Square(double S) : Shape(SquareKind), SideLength(S) {}
+ + Square(double S) : Shape(SK_Square), SideLength(S) {}
double computeArea() /* override */;
};
@@ -147,7 +146,7 @@ steps:
double Radius;
public:
- Circle(double R) : Radius(R) {}
- + Circle(double R) : Shape(CircleKind), Radius(R) {}
+ + Circle(double R) : Shape(SK_Circle), Radius(R) {}
double computeArea() /* override */;
};
@@ -164,8 +163,8 @@ steps:
public:
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
enum ShapeKind {
- SquareKind,
- CircleKind
+ SK_Square,
+ SK_Circle
};
private:
const ShapeKind Kind;
@@ -174,53 +173,72 @@ steps:
Shape(ShapeKind K) : Kind(K) {}
virtual double computeArea() = 0;
- +
- + static bool classof(const Shape *) { return true; }
};
class Square : public Shape {
double SideLength;
public:
- Square(double S) : Shape(SquareKind), SideLength(S) {}
+ Square(double S) : Shape(SK_Square), SideLength(S) {}
double computeArea() /* override */;
+
- + static bool classof(const Square *) { return true; }
+ static bool classof(const Shape *S) {
- + return S->getKind() == SquareKind;
+ + return S->getKind() == SK_Square;
+ }
};
class Circle : public Shape {
double Radius;
public:
- Circle(double R) : Shape(CircleKind), Radius(R) {}
+ Circle(double R) : Shape(SK_Circle), Radius(R) {}
double computeArea() /* override */;
+
- + static bool classof(const Circle *) { return true; }
+ static bool classof(const Shape *S) {
- + return S->getKind() == CircleKind;
+ + return S->getKind() == SK_Circle;
+ }
};
- Basically, the job of ``classof`` is to return ``true`` if its argument
- is of the enclosing class's type. As you can see, there are two general
- overloads of ``classof`` in use here.
+ The job of ``classof`` is to dynamically determine whether an object of
+ a base class is in fact of a particular derived class. In order to
+ downcast a type ``Base`` to a type ``Derived``, there needs to be a
+ ``classof`` in ``Derived`` which will accept an object of type ``Base``.
+
+ To be concrete, consider the following code:
+
+ .. code-block:: c++
+
+ Shape *S = ...;
+ if (isa<Circle>(S)) {
+ /* do something ... */
+ }
- #. The first, which just returns ``true``, means that if we know that the
- argument of the cast is of the enclosing type *at compile time*, then
- we don't need to bother to check anything since we already know that
- the type is convertible. This is an optimization for the case that we
- statically know the conversion is OK.
+ The code of the ``isa<>`` test in this code will eventually boil
+ down---after template instantiation and some other machinery---to a
+ check roughly like ``Circle::classof(S)``. For more information, see
+ :ref:`classof-contract`.
- #. The other overload takes a pointer to an object of the base of the
- class hierarchy: this is the "general case" of the cast. We need to
- check the ``Kind`` to dynamically decide if the argument is of (or
- derived from) the enclosing type.
+ The argument to ``classof`` should always be an *ancestor* class because
+ the implementation has logic to allow and optimize away
+ upcasts/up-``isa<>``'s automatically. It is as though every class
+ ``Foo`` automatically has a ``classof`` like:
+
+ .. code-block:: c++
- To be more precise, let ``classof`` be inside a class ``C``. Then the
- contract for ``classof`` is "return ``true`` if the argument is-a
- ``C``". As long as your implementation fulfills this contract, you can
- tweak and optimize it as much as you want.
+ class Foo {
+ [...]
+ template <class T>
+ static bool classof(const T *,
+ ::llvm::enable_if_c<
+ ::llvm::is_base_of<Foo, T>::value
+ >::type* = 0) { return true; }
+ [...]
+ };
+
+ Note that this is the reason that we did not need to introduce a
+ ``classof`` into ``Shape``: all relevant classes derive from ``Shape``,
+ and ``Shape`` itself is abstract (has no entry in the ``Kind`` enum),
+ so this notional inferred ``classof`` is all we need. See `Concrete
+ Bases and Deeper Hierarchies`_ for more information about how to extend
+ this example to more general hierarchies.
Although for this small example setting up LLVM-style RTTI seems like a lot
of "boilerplate", if your classes are doing anything interesting then this
@@ -231,29 +249,37 @@ Concrete Bases and Deeper Hierarchies
For concrete bases (i.e. non-abstract interior nodes of the inheritance
tree), the ``Kind`` check inside ``classof`` needs to be a bit more
-complicated. Say that ``SpecialSquare`` and ``OtherSpecialSquare`` derive
+complicated. The situation differs from the example above in that
+
+* Since the class is concrete, it must itself have an entry in the ``Kind``
+ enum because it is possible to have objects with this class as a dynamic
+ type.
+
+* Since the class has children, the check inside ``classof`` must take them
+ into account.
+
+Say that ``SpecialSquare`` and ``OtherSpecialSquare`` derive
from ``Square``, and so ``ShapeKind`` becomes:
.. code-block:: c++
enum ShapeKind {
- SquareKind,
- + SpecialSquareKind,
- + OtherSpecialSquareKind,
- CircleKind
+ SK_Square,
+ + SK_SpecialSquare,
+ + SK_OtherSpecialSquare,
+ SK_Circle
}
Then in ``Square``, we would need to modify the ``classof`` like so:
.. code-block:: c++
- static bool classof(const Square *) { return true; }
- static bool classof(const Shape *S) {
- - return S->getKind() == SquareKind;
+ - return S->getKind() == SK_Square;
- }
+ static bool classof(const Shape *S) {
- + return S->getKind() >= SquareKind &&
- + S->getKind() <= OtherSpecialSquareKind;
+ + return S->getKind() >= SK_Square &&
+ + S->getKind() <= SK_OtherSpecialSquare;
+ }
The reason that we need to test a range like this instead of just equality
@@ -273,9 +299,34 @@ ordering right::
| OtherSpecialSquare
| Circle
+.. _classof-contract:
+
+The Contract of ``classof``
+---------------------------
+
+To be more precise, let ``classof`` be inside a class ``C``. Then the
+contract for ``classof`` is "return ``true`` if the dynamic type of the
+argument is-a ``C``". As long as your implementation fulfills this
+contract, you can tweak and optimize it as much as you want.
+
.. TODO::
Touch on some of the more advanced features, like ``isa_impl`` and
``simplify_type``. However, those two need reference documentation in
the form of doxygen comments as well. We need the doxygen so that we can
say "for full details, see http://llvm.org/doxygen/..."
+
+Rules of Thumb
+==============
+
+#. The ``Kind`` enum should have one entry per concrete class, ordered
+ according to a preorder traversal of the inheritance tree.
+#. The argument to ``classof`` should be a ``const Base *``, where ``Base``
+ is some ancestor in the inheritance hierarchy. The argument should
+ *never* be a derived class or the class itself: the template machinery
+ for ``isa<>`` already handles this case and optimizes it.
+#. For each class in the hierarchy that has no children, implement a
+ ``classof`` that checks only against its ``Kind``.
+#. For each class in the hierarchy that has children, implement a
+ ``classof`` that checks a range of the first child's ``Kind`` and the
+ last child's ``Kind``.
diff --git a/docs/Lexicon.rst b/docs/Lexicon.rst
index 6ebe61429f9..d568c0b302e 100644
--- a/docs/Lexicon.rst
+++ b/docs/Lexicon.rst
@@ -20,8 +20,10 @@ A
B
-
-**BURS**
+**BB Vectorization**
+ Basic Block Vectorization
+**BURS**
Bottom Up Rewriting System --- A method of instruction selection for code
generation. An example is the `BURG
<http://www.program-transformation.org/Transform/BURG>`_ tool.
@@ -156,7 +158,7 @@ R
In garbage collection, a pointer variable lying outside of the `heap`_ from
which the collector begins its reachability analysis. In the context of code
generation, "root" almost always refers to a "stack root" --- a local or
- temporary variable within an executing function.</dd>
+ temporary variable within an executing function.
**RPO**
Reverse postorder
@@ -192,3 +194,10 @@ S
**Stack Map**
In garbage collection, metadata emitted by the code generator which
identifies `roots`_ within the stack frame of an executing function.
+
+T
+-
+
+**TBAA**
+ Type-Based Alias Analysis
+
diff --git a/docs/Phabricator.rst b/docs/Phabricator.rst
new file mode 100644
index 00000000000..cd984b09be3
--- /dev/null
+++ b/docs/Phabricator.rst
@@ -0,0 +1,94 @@
+=============================
+Code Reviews with Phabricator
+=============================
+
+.. contents::
+ :local:
+
+If you prefer to use a web user interface for code reviews,
+you can now submit your patches for Clang and LLVM at
+`LLVM's Phabricator`_.
+
+Sign up
+-------
+
+Sign up with one of the supported OAuth account types. If
+you use your Subversion user name as Phabricator user name,
+Phabricator will automatically connect your submits to your
+Phabricator user in the `Code Repository Browser`_.
+
+
+Requesting a review via the command line
+----------------------------------------
+
+Phabricator has a tool called *Arcanist* to upload patches from
+the command line. To get you set up, follow the
+`Arcanist Quick Start`_ instructions.
+
+You can learn more about how to use arc to interact with
+Phabricator in the `Arcanist User Guide`_.
+
+Requesting a review via the web interface
+-----------------------------------------
+
+The tool to create and review patches in Phabricator is called
+*Differential*.
+
+Note that you can upload patches created through various diff tools,
+including git and svn. To make reviews easier, please always include
+**as much context as possible** with your diff! Don't worry, Phabricator
+will automatically send a diff with a smaller context in the review
+email, but having the full file in the web interface will help the
+reviewer understand your code.
+
+To get a full diff, use one of the following commands (or just use Arcanist
+to upload your patch):
+
+* git diff -U999999 other-branch
+* svn diff --diff-cmd=diff -x -U999999
+
+To upload a new patch:
+
+* Click *Differential*.
+* Click *Create Revision*.
+* Paste the text diff or upload the patch file.
+ Note that TODO
+* Leave the drop down on *Create a new Revision...* and click *Continue*.
+* Enter a descriptive title and summary; add reviewers and mailing
+ lists that you want to be included in the review. If your patch is
+ for LLVM, cc llvm-commits; if your patch is for Clang, cc cfe-commits.
+* Click *Save*.
+
+To submit an updated patch:
+
+* Click *Differential*.
+* Click *Create Revision*.
+* Paste the updated diff.
+* Select the review you want to from the *Attach To* dropdown and click
+ *Continue*.
+* Click *Save*.
+
+Reviewing code with Phabricator
+-------------------------------
+
+Phabricator allows you to add inline comments as well as overall comments
+to a revision. To add an inline comment, select the lines of code you want
+to comment on by clicking and dragging the line numbers in the diff pane.
+
+You can add overall comments or submit your comments at the bottom of the page.
+
+Phabricator has many useful features, for example allowing you to select
+diffs between different versions of the patch as it was reviewed in the
+*Revision Update History*. Most features are self descriptive - explore, and
+if you have a question, drop by on #llvm in IRC to get help.
+
+Status
+------
+
+Currently, we're testing Phabricator for use with Clang/LLVM. Please let us
+know whether you like it and what could be improved!
+
+.. _LLVM's Phabricator: http://llvm-reviews.chandlerc.com
+.. _Code Repository Browser: http://llvm-reviews.chandlerc.com/diffusion/
+.. _Arcanist Quick Start: http://www.phabricator.com/docs/phabricator/article/Arcanist_Quick_Start.html
+.. _Arcanist User Guide: http://www.phabricator.com/docs/phabricator/article/Arcanist_User_Guide.html
diff --git a/docs/SphinxQuickstartTemplate.rst b/docs/SphinxQuickstartTemplate.rst
new file mode 100644
index 00000000000..75d916368e3
--- /dev/null
+++ b/docs/SphinxQuickstartTemplate.rst
@@ -0,0 +1,125 @@
+==========================
+Sphinx Quickstart Template
+==========================
+
+.. sectionauthor:: Sean Silva <silvas@purdue.edu>
+
+Introduction and Quickstart
+===========================
+
+This document is meant to get you writing documentation as fast as possible
+even if you have no previous experience with Sphinx. The goal is to take
+someone in the state of "I want to write documentation and get it added to
+LLVM's docs" and turn that into useful documentation mailed to llvm-commits
+with as little nonsense as possible.
+
+You can find this document in ``docs/SphinxQuickstartTemplate.rst``. You
+should copy it, open the new file in your text editor, write your docs, and
+then send the new document to llvm-commits for review.
+
+Focus on *content*. It is easy to fix the Sphinx (reStructuredText) syntax
+later if necessary, although reStructuredText tries to imitate common
+plain-text conventions so it should be quite natural. A basic knowledge of
+reStructuredText syntax is useful when writing the document, so the last
+~half of this document (starting with `Example Section`_) gives examples
+which should cover 99% of use cases.
+
+Let me say that again: focus on *content*.
+
+Once you have finished with the content, please send the ``.rst`` file to
+llvm-commits for review.
+
+Guidelines
+==========
+
+Try to answer the following questions in your first section:
+
+#. Why would I want to read this document?
+
+#. What should I know to be able to follow along with this document?
+
+#. What will I have learned by the end of this document?
+
+Common names for the first section are ``Introduction``, ``Overview``, or
+``Background``.
+
+If possible, make your document a "how to". Give it a name ``HowTo*.rst``
+like the other "how to" documents. This format is usually the easiest
+for another person to understand and also the most useful.
+
+You generally should not be writing documentation other than a "how to"
+unless there is already a "how to" about your topic. The reason for this
+is that without a "how to" document to read first, it is difficult for a
+person to understand a more advanced document.
+
+Focus on content (yes, I had to say it again).
+
+The rest of this document shows example reStructuredText markup constructs
+that are meant to be read by you in your text editor after you have copied
+this file into a new file for the documentation you are about to write.
+
+Example Section
+===============
+
+Your text can be *emphasized*, **bold**, or ``monospace``.
+
+Use blank lines to separate paragraphs.
+
+Headings (like ``Example Section`` just above) give your document
+structure. Use the same kind of adornments (e.g. ``======`` vs. ``------``)
+as are used in this document. The adornment must be the same length as the
+text above it. For Vim users, variations of ``yypVr=`` might be handy.
+
+Example Subsection
+------------------
+
+Make a link `like this <http://llvm.org/>`_. There is also a more
+sophisticated syntax which `can be more readable`_ for longer links since
+it disrupts the flow less. You can put the ``.. _`link text`: <URL>`` block
+pretty much anywhere later in the document.
+
+.. _`can be more readable`: http://en.wikipedia.org/wiki/LLVM
+
+Lists can be made like this:
+
+#. A list starting with ``#.`` will be automatically numbered.
+
+#. This is a second list element.
+
+ #. They nest too.
+
+You can also use unordered lists.
+
+* Stuff.
+
+ + Deeper stuff.
+
+* More stuff.
+
+Example Subsubsection
+^^^^^^^^^^^^^^^^^^^^^
+
+You can make blocks of code like this:
+
+.. code-block:: c++
+
+ int main() {
+ return 0
+ }
+
+For a shell session, use a ``bash`` code block:
+
+.. code-block:: bash
+
+ $ echo "Goodbye cruel world!"
+ $ rm -rf /
+
+If you need to show LLVM IR use the ``llvm`` code block.
+
+Hopefully you won't need to be this deep
+""""""""""""""""""""""""""""""""""""""""
+
+If you need to do fancier things than what has been shown in this document,
+you can mail the list or check Sphinx's `reStructuredText Primer`_.
+
+.. _`reStructuredText Primer`: http://sphinx.pocoo.org/rest.html
diff --git a/docs/userguides.rst b/docs/userguides.rst
index 6ff46ade480..8c1554dfce9 100644
--- a/docs/userguides.rst
+++ b/docs/userguides.rst
@@ -18,6 +18,8 @@ User Guides
HowToAddABuilder
yaml2obj
HowToSubmitABug
+ SphinxQuickstartTemplate
+ Phabricator
* :ref:`getting_started`
@@ -70,6 +72,10 @@ User Guides
Instructions for properly submitting information about any bugs you run into
in the LLVM system.
+* :doc:`SphinxQuickstartTemplate`
+
+ A template + tutorial for writing new Sphinx documentation. It is meant
+ to be read in source form.
* `LLVM Testing Infrastructure Guide <TestingGuide.html>`_
diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp
index 56d4d81b5c7..215cb4d3714 100644
--- a/examples/ExceptionDemo/ExceptionDemo.cpp
+++ b/examples/ExceptionDemo/ExceptionDemo.cpp
@@ -10,13 +10,13 @@
// Demo program which implements an example LLVM exception implementation, and
// shows several test cases including the handling of foreign exceptions.
// It is run with type info types arguments to throw. A test will
-// be run for each given type info type. While type info types with the value
+// be run for each given type info type. While type info types with the value
// of -1 will trigger a foreign C++ exception to be thrown; type info types
-// <= 6 and >= 1 will cause the associated generated exceptions to be thrown
+// <= 6 and >= 1 will cause the associated generated exceptions to be thrown
// and caught by generated test functions; and type info types > 6
// will result in exceptions which pass through to the test harness. All other
// type info types are not supported and could cause a crash. In all cases,
-// the "finally" blocks of every generated test functions will executed
+// the "finally" blocks of every generated test functions will executed
// regardless of whether or not that test function ignores or catches the
// thrown exception.
//
@@ -25,25 +25,25 @@
// ExceptionDemo
//
// causes a usage to be printed to stderr
-//
+//
// ExceptionDemo 2 3 7 -1
//
// results in the following cases:
-// - Value 2 causes an exception with a type info type of 2 to be
+// - Value 2 causes an exception with a type info type of 2 to be
// thrown and caught by an inner generated test function.
-// - Value 3 causes an exception with a type info type of 3 to be
+// - Value 3 causes an exception with a type info type of 3 to be
// thrown and caught by an outer generated test function.
-// - Value 7 causes an exception with a type info type of 7 to be
+// - Value 7 causes an exception with a type info type of 7 to be
// thrown and NOT be caught by any generated function.
// - Value -1 causes a foreign C++ exception to be thrown and not be
// caught by any generated function
//
// Cases -1 and 7 are caught by a C++ test harness where the validity of
-// of a C++ catch(...) clause catching a generated exception with a
-// type info type of 7 is explained by: example in rules 1.6.4 in
+// of a C++ catch(...) clause catching a generated exception with a
+// type info type of 7 is explained by: example in rules 1.6.4 in
// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
//
-// This code uses code from the llvm compiler-rt project and the llvm
+// This code uses code from the llvm compiler-rt project and the llvm
// Kaleidoscope project.
//
//===----------------------------------------------------------------------===//
@@ -63,12 +63,12 @@
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/TargetSelect.h"
-// FIXME: Although all systems tested with (Linux, OS X), do not need this
-// header file included. A user on ubuntu reported, undefined symbols
+// FIXME: Although all systems tested with (Linux, OS X), do not need this
+// header file included. A user on ubuntu reported, undefined symbols
// for stderr, and fprintf, and the addition of this include fixed the
-// issue for them. Given that LLVM's best practices include the goal
-// of reducing the number of redundant header files included, the
-// correct solution would be to find out why these symbols are not
+// issue for them. Given that LLVM's best practices include the goal
+// of reducing the number of redundant header files included, the
+// correct solution would be to find out why these symbols are not
// defined for the system in question, and fix the issue by finding out
// which LLVM header file, if any, would include these symbols.
#include <cstdio>
@@ -81,11 +81,11 @@
#define USE_GLOBAL_STR_CONSTS true
#endif
-// System C++ ABI unwind types from:
+// System C++ ABI unwind types from:
// http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22)
extern "C" {
-
+
typedef enum {
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
@@ -97,7 +97,7 @@ extern "C" {
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8
} _Unwind_Reason_Code;
-
+
typedef enum {
_UA_SEARCH_PHASE = 1,
_UA_CLEANUP_PHASE = 2,
@@ -105,34 +105,34 @@ extern "C" {
_UA_FORCE_UNWIND = 8,
_UA_END_OF_STACK = 16
} _Unwind_Action;
-
+
struct _Unwind_Exception;
-
+
typedef void (*_Unwind_Exception_Cleanup_Fn) (_Unwind_Reason_Code,
struct _Unwind_Exception *);
-
+
struct _Unwind_Exception {
uint64_t exception_class;
_Unwind_Exception_Cleanup_Fn exception_cleanup;
-
- uintptr_t private_1;
- uintptr_t private_2;
-
+
+ uintptr_t private_1;
+ uintptr_t private_2;
+
// @@@ The IA-64 ABI says that this structure must be double-word aligned.
- // Taking that literally does not make much sense generically. Instead
+ // Taking that literally does not make much sense generically. Instead
// we provide the maximum alignment required by any type for the machine.
} __attribute__((__aligned__));
-
+
struct _Unwind_Context;
typedef struct _Unwind_Context *_Unwind_Context_t;
-
+
extern const uint8_t *_Unwind_GetLanguageSpecificData (_Unwind_Context_t c);
extern uintptr_t _Unwind_GetGR (_Unwind_Context_t c, int i);
extern void _Unwind_SetGR (_Unwind_Context_t c, int i, uintptr_t n);
extern void _Unwind_SetIP (_Unwind_Context_t, uintptr_t new_value);
extern uintptr_t _Unwind_GetIP (_Unwind_Context_t context);
extern uintptr_t _Unwind_GetRegionStart (_Unwind_Context_t context);
-
+
} // extern "C"
//
@@ -148,13 +148,13 @@ struct OurExceptionType_t {
/// This is our Exception class which relies on a negative offset to calculate
/// pointers to its instances from pointers to its unwindException member.
-///
+///
/// Note: The above unwind.h defines struct _Unwind_Exception to be aligned
/// on a double word boundary. This is necessary to match the standard:
/// http://refspecs.freestandards.org/abi-eh-1.21.html
struct OurBaseException_t {
struct OurExceptionType_t type;
-
+
// Note: This is properly aligned in unwind.h
struct _Unwind_Exception unwindException;
};
@@ -165,7 +165,7 @@ typedef struct OurBaseException_t OurException;
typedef struct _Unwind_Exception OurUnwindException;
//
-// Various globals used to support typeinfo and generatted exceptions in
+// Various globals used to support typeinfo and generatted exceptions in
// general
//
@@ -173,7 +173,7 @@ static std::map<std::string, llvm::Value*> namedValues;
int64_t ourBaseFromUnwindOffset;
-const unsigned char ourBaseExcpClassChars[] =
+const unsigned char ourBaseExcpClassChars[] =
{'o', 'b', 'j', '\0', 'b', 'a', 's', '\0'};
@@ -203,7 +203,7 @@ typedef std::vector<llvm::Type*> ArgTypes;
/// @param retType function return type
/// @param theArgTypes function's ordered argument types
/// @param theArgNames function's ordered arguments needed if use of this
-/// function corresponds to a function definition. Use empty
+/// function corresponds to a function definition. Use empty
/// aggregate for function declarations.
/// @param functName function name
/// @param linkage function linkage
@@ -224,17 +224,17 @@ llvm::Function *createFunction(llvm::Module &module,
llvm::Function::Create(functType, linkage, functName, &module);
if (!ret || declarationOnly)
return(ret);
-
+
namedValues.clear();
- unsigned i = 0;
+ unsigned i = 0;
for (llvm::Function::arg_iterator argIndex = ret->arg_begin();
i != theArgNames.size();
++argIndex, ++i) {
-
+
argIndex->setName(theArgNames[i]);
namedValues[theArgNames[i]] = argIndex;
}
-
+
return(ret);
}
@@ -250,13 +250,13 @@ static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
const std::string &varName,
llvm::Type *type,
llvm::Constant *initWith = 0) {
- llvm::BasicBlock &block = function.getEntryBlock();
+ llvm::BasicBlock &block = function.getEntryBlock();
llvm::IRBuilder<> tmp(&block, block.begin());
llvm::AllocaInst *ret = tmp.CreateAlloca(type, 0, varName.c_str());
-
- if (initWith)
+
+ if (initWith)
tmp.CreateStore(initWith, ret);
-
+
return(ret);
}
@@ -266,7 +266,7 @@ static llvm::AllocaInst *createEntryBlockAlloca(llvm::Function &function,
//
//
-// Runtime C Library functions
+// Runtime C Library functions
//
// Note: using an extern "C" block so that static functions can be used
@@ -275,7 +275,7 @@ extern "C" {
// Note: Better ways to decide on bit width
//
/// Prints a 32 bit number, according to the format, to stderr.
-/// @param intToPrint integer to print
+/// @param intToPrint integer to print
/// @param format printf like format to use when printing
void print32Int(int intToPrint, const char *format) {
if (format) {
@@ -292,7 +292,7 @@ void print32Int(int intToPrint, const char *format) {
// Note: Better ways to decide on bit width
//
/// Prints a 64 bit number, according to the format, to stderr.
-/// @param intToPrint integer to print
+/// @param intToPrint integer to print
/// @param format printf like format to use when printing
void print64Int(long int intToPrint, const char *format) {
if (format) {
@@ -327,19 +327,19 @@ void deleteOurException(OurUnwindException *expToDelete) {
fprintf(stderr,
"deleteOurException(...).\n");
#endif
-
+
if (expToDelete &&
(expToDelete->exception_class == ourBaseExceptionClass)) {
-
+
free(((char*) expToDelete) + ourBaseFromUnwindOffset);
}
}
-/// This function is the struct _Unwind_Exception API mandated delete function
-/// used by foreign exception handlers when deleting our exception
+/// This function is the struct _Unwind_Exception API mandated delete function
+/// used by foreign exception handlers when deleting our exception
/// (OurException), instances.
-/// @param reason @link http://refspecs.freestandards.org/abi-eh-1.21.html
+/// @param reason @link http://refspecs.freestandards.org/abi-eh-1.21.html
/// @unlink
/// @param expToDelete exception instance to delete
void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
@@ -348,7 +348,7 @@ void deleteFromUnwindOurException(_Unwind_Reason_Code reason,
fprintf(stderr,
"deleteFromUnwindOurException(...).\n");
#endif
-
+
deleteOurException(expToDelete);
}
@@ -362,13 +362,13 @@ OurUnwindException *createOurException(int type) {
(ret->type).type = type;
(ret->unwindException).exception_class = ourBaseExceptionClass;
(ret->unwindException).exception_cleanup = deleteFromUnwindOurException;
-
+
return(&(ret->unwindException));
}
-/// Read a uleb128 encoded value and advance pointer
-/// See Variable Length Data in:
+/// Read a uleb128 encoded value and advance pointer
+/// See Variable Length Data in:
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
/// @param data reference variable holding memory pointer to decode from
/// @returns decoded value
@@ -377,22 +377,22 @@ static uintptr_t readULEB128(const uint8_t **data) {
uintptr_t shift = 0;
unsigned char byte;
const uint8_t *p = *data;
-
+
do {
byte = *p++;
result |= (byte & 0x7f) << shift;
shift += 7;
- }
+ }
while (byte & 0x80);
-
+
*data = p;
-
+
return result;
}
-/// Read a sleb128 encoded value and advance pointer
-/// See Variable Length Data in:
+/// Read a sleb128 encoded value and advance pointer
+/// See Variable Length Data in:
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
/// @param data reference variable holding memory pointer to decode from
/// @returns decoded value
@@ -401,26 +401,26 @@ static uintptr_t readSLEB128(const uint8_t **data) {
uintptr_t shift = 0;
unsigned char byte;
const uint8_t *p = *data;
-
+
do {
byte = *p++;
result |= (byte & 0x7f) << shift;
shift += 7;
- }
+ }
while (byte & 0x80);
-
+
*data = p;
-
+
if ((byte & 0x40) && (shift < (sizeof(result) << 3))) {
result |= (~0 << shift);
}
-
+
return result;
}
-/// Read a pointer encoded value and advance pointer
-/// See Variable Length Data in:
+/// Read a pointer encoded value and advance pointer
+/// See Variable Length Data in:
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
/// @param data reference variable holding memory pointer to decode from
/// @param encoding dwarf encoding type
@@ -428,11 +428,11 @@ static uintptr_t readSLEB128(const uint8_t **data) {
static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
uintptr_t result = 0;
const uint8_t *p = *data;
-
- if (encoding == llvm::dwarf::DW_EH_PE_omit)
+
+ if (encoding == llvm::dwarf::DW_EH_PE_omit)
return(result);
-
- // first get value
+
+ // first get value
switch (encoding & 0x0F) {
case llvm::dwarf::DW_EH_PE_absptr:
result = *((uintptr_t*)p);
@@ -470,15 +470,15 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
p += sizeof(int64_t);
break;
default:
- // not supported
+ // not supported
abort();
break;
}
-
- // then add relative offset
+
+ // then add relative offset
switch (encoding & 0x70) {
case llvm::dwarf::DW_EH_PE_absptr:
- // do nothing
+ // do nothing
break;
case llvm::dwarf::DW_EH_PE_pcrel:
result += (uintptr_t)(*data);
@@ -488,34 +488,34 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
case llvm::dwarf::DW_EH_PE_funcrel:
case llvm::dwarf::DW_EH_PE_aligned:
default:
- // not supported
+ // not supported
abort();
break;
}
-
- // then apply indirection
+
+ // then apply indirection
if (encoding & llvm::dwarf::DW_EH_PE_indirect) {
result = *((uintptr_t*)result);
}
-
+
*data = p;
-
+
return result;
}
-/// Deals with Dwarf actions matching our type infos
-/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted
-/// action matches the supplied exception type. If such a match succeeds,
-/// the resultAction argument will be set with > 0 index value. Only
-/// corresponding llvm.eh.selector type info arguments, cleanup arguments
+/// Deals with Dwarf actions matching our type infos
+/// (OurExceptionType_t instances). Returns whether or not a dwarf emitted
+/// action matches the supplied exception type. If such a match succeeds,
+/// the resultAction argument will be set with > 0 index value. Only
+/// corresponding llvm.eh.selector type info arguments, cleanup arguments
/// are supported. Filters are not supported.
-/// See Variable Length Data in:
+/// See Variable Length Data in:
/// @link http://dwarfstd.org/Dwarf3.pdf @unlink
/// Also see @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink
/// @param resultAction reference variable which will be set with result
/// @param classInfo our array of type info pointers (to globals)
-/// @param actionEntry index into above type info array or 0 (clean up).
+/// @param actionEntry index into above type info array or 0 (clean up).
/// We do not support filters.
/// @param exceptionClass exception class (_Unwind_Exception::exception_class)
/// of thrown exception.
@@ -523,22 +523,22 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) {
/// @returns whether or not a type info was found. False is returned if only
/// a cleanup was found
static bool handleActionValue(int64_t *resultAction,
- struct OurExceptionType_t **classInfo,
- uintptr_t actionEntry,
- uint64_t exceptionClass,
+ struct OurExceptionType_t **classInfo,
+ uintptr_t actionEntry,
+ uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject) {
bool ret = false;
-
- if (!resultAction ||
- !exceptionObject ||
+
+ if (!resultAction ||
+ !exceptionObject ||
(exceptionClass != ourBaseExceptionClass))
return(ret);
-
+
struct OurBaseException_t *excp = (struct OurBaseException_t*)
(((char*) exceptionObject) + ourBaseFromUnwindOffset);
struct OurExceptionType_t *excpType = &(excp->type);
int type = excpType->type;
-
+
#ifdef DEBUG
fprintf(stderr,
"handleActionValue(...): exceptionObject = <%p>, "
@@ -546,12 +546,12 @@ static bool handleActionValue(int64_t *resultAction,
exceptionObject,
excp);
#endif
-
+
const uint8_t *actionPos = (uint8_t*) actionEntry,
*tempActionPos;
int64_t typeOffset = 0,
actionOffset;
-
+
for (int i = 0; true; ++i) {
// Each emitted dwarf action corresponds to a 2 tuple of
// type info address offset, and action offset to the next
@@ -559,7 +559,7 @@ static bool handleActionValue(int64_t *resultAction,
typeOffset = readSLEB128(&actionPos);
tempActionPos = actionPos;
actionOffset = readSLEB128(&tempActionPos);
-
+
#ifdef DEBUG
fprintf(stderr,
"handleActionValue(...):typeOffset: <%lld>, "
@@ -567,9 +567,9 @@ static bool handleActionValue(int64_t *resultAction,
typeOffset,
actionOffset);
#endif
- assert((typeOffset >= 0) &&
+ assert((typeOffset >= 0) &&
"handleActionValue(...):filters are not supported.");
-
+
// Note: A typeOffset == 0 implies that a cleanup llvm.eh.selector
// argument has been matched.
if ((typeOffset > 0) &&
@@ -583,17 +583,17 @@ static bool handleActionValue(int64_t *resultAction,
ret = true;
break;
}
-
+
#ifdef DEBUG
fprintf(stderr,
"handleActionValue(...):actionValue not found.\n");
#endif
if (!actionOffset)
break;
-
+
actionPos += actionOffset;
}
-
+
return(ret);
}
@@ -602,52 +602,52 @@ static bool handleActionValue(int64_t *resultAction,
/// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink
/// @param version unsupported (ignored), unwind version
/// @param lsda language specific data area
-/// @param _Unwind_Action actions minimally supported unwind stage
+/// @param _Unwind_Action actions minimally supported unwind stage
/// (forced specifically not supported)
/// @param exceptionClass exception class (_Unwind_Exception::exception_class)
/// of thrown exception.
/// @param exceptionObject thrown _Unwind_Exception instance.
/// @param context unwind system context
-/// @returns minimally supported unwinding control indicator
-static _Unwind_Reason_Code handleLsda(int version,
+/// @returns minimally supported unwinding control indicator
+static _Unwind_Reason_Code handleLsda(int version,
const uint8_t *lsda,
_Unwind_Action actions,
- uint64_t exceptionClass,
+ uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject,
_Unwind_Context_t context) {
_Unwind_Reason_Code ret = _URC_CONTINUE_UNWIND;
-
+
if (!lsda)
return(ret);
-
+
#ifdef DEBUG
- fprintf(stderr,
+ fprintf(stderr,
"handleLsda(...):lsda is non-zero.\n");
#endif
-
+
// Get the current instruction pointer and offset it before next
// instruction in the current frame which threw the exception.
uintptr_t pc = _Unwind_GetIP(context)-1;
-
- // Get beginning current frame's code (as defined by the
+
+ // Get beginning current frame's code (as defined by the
// emitted dwarf code)
uintptr_t funcStart = _Unwind_GetRegionStart(context);
uintptr_t pcOffset = pc - funcStart;
struct OurExceptionType_t **classInfo = NULL;
-
+
// Note: See JITDwarfEmitter::EmitExceptionTable(...) for corresponding
// dwarf emission
-
+
// Parse LSDA header.
uint8_t lpStartEncoding = *lsda++;
-
+
if (lpStartEncoding != llvm::dwarf::DW_EH_PE_omit) {
- readEncodedPointer(&lsda, lpStartEncoding);
+ readEncodedPointer(&lsda, lpStartEncoding);
}
-
+
uint8_t ttypeEncoding = *lsda++;
uintptr_t classInfoOffset;
-
+
if (ttypeEncoding != llvm::dwarf::DW_EH_PE_omit) {
// Calculate type info locations in emitted dwarf code which
// were flagged by type info arguments to llvm.eh.selector
@@ -655,47 +655,47 @@ static _Unwind_Reason_Code handleLsda(int version,
classInfoOffset = readULEB128(&lsda);
classInfo = (struct OurExceptionType_t**) (lsda + classInfoOffset);
}
-
- // Walk call-site table looking for range that
- // includes current PC.
-
+
+ // Walk call-site table looking for range that
+ // includes current PC.
+
uint8_t callSiteEncoding = *lsda++;
uint32_t callSiteTableLength = readULEB128(&lsda);
const uint8_t *callSiteTableStart = lsda;
- const uint8_t *callSiteTableEnd = callSiteTableStart +
+ const uint8_t *callSiteTableEnd = callSiteTableStart +
callSiteTableLength;
const uint8_t *actionTableStart = callSiteTableEnd;
const uint8_t *callSitePtr = callSiteTableStart;
-
+
bool foreignException = false;
-
+
while (callSitePtr < callSiteTableEnd) {
- uintptr_t start = readEncodedPointer(&callSitePtr,
+ uintptr_t start = readEncodedPointer(&callSitePtr,
callSiteEncoding);
- uintptr_t length = readEncodedPointer(&callSitePtr,
+ uintptr_t length = readEncodedPointer(&callSitePtr,
callSiteEncoding);
- uintptr_t landingPad = readEncodedPointer(&callSitePtr,
+ uintptr_t landingPad = readEncodedPointer(&callSitePtr,
callSiteEncoding);
-
+
// Note: Action value
uintptr_t actionEntry = readULEB128(&callSitePtr);
-
+
if (exceptionClass != ourBaseExceptionClass) {
// We have been notified of a foreign exception being thrown,
// and we therefore need to execute cleanup landing pads
actionEntry = 0;
foreignException = true;
}
-
+
if (landingPad == 0) {
#ifdef DEBUG
fprintf(stderr,
"handleLsda(...): No landing pad found.\n");
#endif
-
+
continue; // no landing pad for this entry
}
-
+
if (actionEntry) {
actionEntry += ((uintptr_t) actionTableStart) - 1;
}
@@ -705,55 +705,55 @@ static _Unwind_Reason_Code handleLsda(int version,
"handleLsda(...):No action table found.\n");
#endif
}
-
+
bool exceptionMatched = false;
-
+
if ((start <= pcOffset) && (pcOffset < (start + length))) {
#ifdef DEBUG
fprintf(stderr,
"handleLsda(...): Landing pad found.\n");
#endif
int64_t actionValue = 0;
-
+
if (actionEntry) {
exceptionMatched = handleActionValue(&actionValue,
- classInfo,
- actionEntry,
- exceptionClass,
+ classInfo,
+ actionEntry,
+ exceptionClass,
exceptionObject);
}
-
+
if (!(actions & _UA_SEARCH_PHASE)) {
#ifdef DEBUG
fprintf(stderr,
"handleLsda(...): installed landing pad "
"context.\n");
#endif
-
+
// Found landing pad for the PC.
- // Set Instruction Pointer to so we re-enter function
- // at landing pad. The landing pad is created by the
+ // Set Instruction Pointer to so we re-enter function
+ // at landing pad. The landing pad is created by the
// compiler to take two parameters in registers.
- _Unwind_SetGR(context,
- __builtin_eh_return_data_regno(0),
+ _Unwind_SetGR(context,
+ __builtin_eh_return_data_regno(0),
(uintptr_t)exceptionObject);
-
+
// Note: this virtual register directly corresponds
// to the return of the llvm.eh.selector intrinsic
if (!actionEntry || !exceptionMatched) {
// We indicate cleanup only
- _Unwind_SetGR(context,
- __builtin_eh_return_data_regno(1),
+ _Unwind_SetGR(context,
+ __builtin_eh_return_data_regno(1),
0);
}
else {
// Matched type info index of llvm.eh.selector intrinsic
// passed here.
- _Unwind_SetGR(context,
- __builtin_eh_return_data_regno(1),
+ _Unwind_SetGR(context,
+ __builtin_eh_return_data_regno(1),
actionValue);
}
-
+
// To execute landing pad set here
_Unwind_SetIP(context, funcStart + landingPad);
ret = _URC_INSTALL_CONTEXT;
@@ -767,19 +767,19 @@ static _Unwind_Reason_Code handleLsda(int version,
}
else {
// Note: Only non-clean up handlers are marked as
- // found. Otherwise the clean up handlers will be
- // re-found and executed during the clean up
+ // found. Otherwise the clean up handlers will be
+ // re-found and executed during the clean up
// phase.
#ifdef DEBUG
fprintf(stderr,
"handleLsda(...): cleanup handler found.\n");
#endif
}
-
+
break;
}
}
-
+
return(ret);
}
@@ -788,23 +788,23 @@ static _Unwind_Reason_Code handleLsda(int version,
/// dwarf unwind info block. Again see: JITDwarfEmitter.cpp.
/// See @link http://refspecs.freestandards.org/abi-eh-1.21.html @unlink
/// @param version unsupported (ignored), unwind version
-/// @param _Unwind_Action actions minimally supported unwind stage
+/// @param _Unwind_Action actions minimally supported unwind stage
/// (forced specifically not supported)
/// @param exceptionClass exception class (_Unwind_Exception::exception_class)
/// of thrown exception.
/// @param exceptionObject thrown _Unwind_Exception instance.
/// @param context unwind system context
-/// @returns minimally supported unwinding control indicator
-_Unwind_Reason_Code ourPersonality(int version,
+/// @returns minimally supported unwinding control indicator
+_Unwind_Reason_Code ourPersonality(int version,
_Unwind_Action actions,
- uint64_t exceptionClass,
+ uint64_t exceptionClass,
struct _Unwind_Exception *exceptionObject,
_Unwind_Context_t context) {
#ifdef DEBUG
- fprintf(stderr,
+ fprintf(stderr,
"We are in ourPersonality(...):actions is <%d>.\n",
actions);
-
+
if (actions & _UA_SEARCH_PHASE) {
fprintf(stderr, "ourPersonality(...):In search phase.\n");
}
@@ -812,15 +812,15 @@ _Unwind_Reason_Code ourPersonality(int version,
fprintf(stderr, "ourPersonality(...):In non-search phase.\n");
}
#endif
-
+
const uint8_t *lsda = _Unwind_GetLanguageSpecificData(context);
-
+
#ifdef DEBUG
- fprintf(stderr,
+ fprintf(stderr,
"ourPersonality(...):lsda = <%p>.\n",
lsda);
#endif
-
+
// The real work of the personality function is captured here
return(handleLsda(version,
lsda,
@@ -841,12 +841,12 @@ _Unwind_Reason_Code ourPersonality(int version,
uint64_t genClass(const unsigned char classChars[], size_t classCharsSize)
{
uint64_t ret = classChars[0];
-
+
for (unsigned i = 1; i < classCharsSize; ++i) {
ret <<= 8;
ret += classChars[i];
}
-
+
return(ret);
}
@@ -865,37 +865,37 @@ uint64_t genClass(const unsigned char classChars[], size_t classCharsSize)
/// @param module code for module instance
/// @param builder builder instance
/// @param toPrint string to print
-/// @param useGlobal A value of true (default) indicates a GlobalValue is
-/// generated, and is used to hold the constant string. A value of
-/// false indicates that the constant string will be stored on the
+/// @param useGlobal A value of true (default) indicates a GlobalValue is
+/// generated, and is used to hold the constant string. A value of
+/// false indicates that the constant string will be stored on the
/// stack.
-void generateStringPrint(llvm::LLVMContext &context,
+void generateStringPrint(llvm::LLVMContext &context,
llvm::Module &module,
- llvm::IRBuilder<> &builder,
+ llvm::IRBuilder<> &builder,
std::string toPrint,
bool useGlobal = true) {
llvm::Function *printFunct = module.getFunction("printStr");
-
+
llvm::Value *stringVar;
- llvm::Constant *stringConstant =
+ llvm::Constant *stringConstant =
llvm::ConstantDataArray::getString(context, toPrint);
-
+
if (useGlobal) {
// Note: Does not work without allocation
- stringVar =
- new llvm::GlobalVariable(module,
+ stringVar =
+ new llvm::GlobalVariable(module,
stringConstant->getType(),
- true,
- llvm::GlobalValue::LinkerPrivateLinkage,
- stringConstant,
+ true,
+ llvm::GlobalValue::LinkerPrivateLinkage,
+ stringConstant,
"");
}
else {
stringVar = builder.CreateAlloca(stringConstant->getType());
builder.CreateStore(stringConstant, stringVar);
}
-
- llvm::Value *cast = builder.CreatePointerCast(stringVar,
+
+ llvm::Value *cast = builder.CreatePointerCast(stringVar,
builder.getInt8PtrTy());
builder.CreateCall(printFunct, cast);
}
@@ -909,49 +909,49 @@ void generateStringPrint(llvm::LLVMContext &context,
/// @param printFunct function used to "print" integer
/// @param toPrint string to print
/// @param format printf like formating string for print
-/// @param useGlobal A value of true (default) indicates a GlobalValue is
-/// generated, and is used to hold the constant string. A value of
-/// false indicates that the constant string will be stored on the
+/// @param useGlobal A value of true (default) indicates a GlobalValue is
+/// generated, and is used to hold the constant string. A value of
+/// false indicates that the constant string will be stored on the
/// stack.
-void generateIntegerPrint(llvm::LLVMContext &context,
+void generateIntegerPrint(llvm::LLVMContext &context,
llvm::Module &module,
- llvm::IRBuilder<> &builder,
+ llvm::IRBuilder<> &builder,
llvm::Function &printFunct,
llvm::Value &toPrint,
- std::string format,
+ std::string format,
bool useGlobal = true) {
llvm::Constant *stringConstant =
llvm::ConstantDataArray::getString(context, format);
llvm::Value *stringVar;
-
+
if (useGlobal) {
// Note: Does not seem to work without allocation
- stringVar =
- new llvm::GlobalVariable(module,
+ stringVar =
+ new llvm::GlobalVariable(module,
stringConstant->getType(),
- true,
- llvm::GlobalValue::LinkerPrivateLinkage,
- stringConstant,
+ true,
+ llvm::GlobalValue::LinkerPrivateLinkage,
+ stringConstant,
"");
}
else {
stringVar = builder.CreateAlloca(stringConstant->getType());
builder.CreateStore(stringConstant, stringVar);
}
-
- llvm::Value *cast = builder.CreateBitCast(stringVar,
+
+ llvm::Value *cast = builder.CreateBitCast(stringVar,
builder.getInt8PtrTy());
builder.CreateCall2(&printFunct, &toPrint, cast);
}
-/// Generates code to handle finally block type semantics: always runs
-/// regardless of whether a thrown exception is passing through or the
-/// parent function is simply exiting. In addition to printing some state
-/// to stderr, this code will resume the exception handling--runs the
-/// unwind resume block, if the exception has not been previously caught
-/// by a catch clause, and will otherwise execute the end block (terminator
-/// block). In addition this function creates the corresponding function's
+/// Generates code to handle finally block type semantics: always runs
+/// regardless of whether a thrown exception is passing through or the
+/// parent function is simply exiting. In addition to printing some state
+/// to stderr, this code will resume the exception handling--runs the
+/// unwind resume block, if the exception has not been previously caught
+/// by a catch clause, and will otherwise execute the end block (terminator
+/// block). In addition this function creates the corresponding function's
/// stack storage for the exception pointer and catch flag status.
/// @param context llvm context
/// @param module code for module instance
@@ -965,9 +965,9 @@ void generateIntegerPrint(llvm::LLVMContext &context,
/// @param exceptionStorage reference to exception pointer storage
/// @param caughtResultStorage reference to landingpad result storage
/// @returns newly created block
-static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
- llvm::Module &module,
- llvm::IRBuilder<> &builder,
+static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
+ llvm::Module &module,
+ llvm::IRBuilder<> &builder,
llvm::Function &toAddTo,
std::string &blockName,
std::string &functionId,
@@ -976,21 +976,21 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
llvm::Value **exceptionCaughtFlag,
llvm::Value **exceptionStorage,
llvm::Value **caughtResultStorage) {
- assert(exceptionCaughtFlag &&
+ assert(exceptionCaughtFlag &&
"ExceptionDemo::createFinallyBlock(...):exceptionCaughtFlag "
"is NULL");
- assert(exceptionStorage &&
+ assert(exceptionStorage &&
"ExceptionDemo::createFinallyBlock(...):exceptionStorage "
"is NULL");
- assert(caughtResultStorage &&
+ assert(caughtResultStorage &&
"ExceptionDemo::createFinallyBlock(...):caughtResultStorage "
"is NULL");
-
+
*exceptionCaughtFlag = createEntryBlockAlloca(toAddTo,
"exceptionCaught",
ourExceptionNotThrownState->getType(),
ourExceptionNotThrownState);
-
+
llvm::PointerType *exceptionStorageType = builder.getInt8PtrTy();
*exceptionStorage = createEntryBlockAlloca(toAddTo,
"exceptionStorage",
@@ -1002,35 +1002,35 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
ourCaughtResultType,
llvm::ConstantAggregateZero::get(
ourCaughtResultType));
-
+
llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
blockName,
&toAddTo);
-
+
builder.SetInsertPoint(ret);
-
+
std::ostringstream bufferToPrint;
bufferToPrint << "Gen: Executing finally block "
<< blockName << " in " << functionId << "\n";
- generateStringPrint(context,
- module,
- builder,
+ generateStringPrint(context,
+ module,
+ builder,
bufferToPrint.str(),
USE_GLOBAL_STR_CONSTS);
-
+
llvm::SwitchInst *theSwitch = builder.CreateSwitch(builder.CreateLoad(
- *exceptionCaughtFlag),
+ *exceptionCaughtFlag),
&terminatorBlock,
2);
theSwitch->addCase(ourExceptionCaughtState, &terminatorBlock);
theSwitch->addCase(ourExceptionThrownState, &unwindResumeBlock);
-
+
return(ret);
}
/// Generates catch block semantics which print a string to indicate type of
-/// catch executed, sets an exception caught flag, and executes passed in
+/// catch executed, sets an exception caught flag, and executes passed in
/// end block (terminator block).
/// @param context llvm context
/// @param module code for module instance
@@ -1041,52 +1041,52 @@ static llvm::BasicBlock *createFinallyBlock(llvm::LLVMContext &context,
/// @param terminatorBlock terminator "end" block
/// @param exceptionCaughtFlag exception caught/thrown status
/// @returns newly created block
-static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
- llvm::Module &module,
- llvm::IRBuilder<> &builder,
+static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
+ llvm::Module &module,
+ llvm::IRBuilder<> &builder,
llvm::Function &toAddTo,
std::string &blockName,
std::string &functionId,
llvm::BasicBlock &terminatorBlock,
llvm::Value &exceptionCaughtFlag) {
-
+
llvm::BasicBlock *ret = llvm::BasicBlock::Create(context,
blockName,
&toAddTo);
-
+
builder.SetInsertPoint(ret);
-
+
std::ostringstream bufferToPrint;
bufferToPrint << "Gen: Executing catch block "
<< blockName
<< " in "
<< functionId
<< std::endl;
- generateStringPrint(context,
- module,
- builder,
+ generateStringPrint(context,
+ module,
+ builder,
bufferToPrint.str(),
USE_GLOBAL_STR_CONSTS);
builder.CreateStore(ourExceptionCaughtState, &exceptionCaughtFlag);
builder.CreateBr(&terminatorBlock);
-
+
return(ret);
}
-/// Generates a function which invokes a function (toInvoke) and, whose
-/// unwind block will "catch" the type info types correspondingly held in the
-/// exceptionTypesToCatch argument. If the toInvoke function throws an
-/// exception which does not match any type info types contained in
-/// exceptionTypesToCatch, the generated code will call _Unwind_Resume
-/// with the raised exception. On the other hand the generated code will
+/// Generates a function which invokes a function (toInvoke) and, whose
+/// unwind block will "catch" the type info types correspondingly held in the
+/// exceptionTypesToCatch argument. If the toInvoke function throws an
+/// exception which does not match any type info types contained in
+/// exceptionTypesToCatch, the generated code will call _Unwind_Resume
+/// with the raised exception. On the other hand the generated code will
/// normally exit if the toInvoke function does not throw an exception.
-/// The generated "finally" block is always run regardless of the cause of
+/// The generated "finally" block is always run regardless of the cause of
/// the generated function exit.
/// The generated function is returned after being verified.
/// @param module code for module instance
/// @param builder builder instance
-/// @param fpm a function pass manager holding optional IR to IR
+/// @param fpm a function pass manager holding optional IR to IR
/// transformations
/// @param toInvoke inner function to invoke
/// @param ourId id used to printing purposes
@@ -1094,76 +1094,76 @@ static llvm::BasicBlock *createCatchBlock(llvm::LLVMContext &context,
/// @param exceptionTypesToCatch array of type info types to "catch"
/// @returns generated function
static
-llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
- llvm::IRBuilder<> &builder,
+llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
+ llvm::IRBuilder<> &builder,
llvm::FunctionPassManager &fpm,
llvm::Function &toInvoke,
std::string ourId,
unsigned numExceptionsToCatch,
unsigned exceptionTypesToCatch[]) {
-
+
llvm::LLVMContext &context = module.getContext();
llvm::Function *toPrint32Int = module.getFunction("print32Int");
-
+
ArgTypes argTypes;
argTypes.push_back(builder.getInt32Ty());
-
+
ArgNames argNames;
argNames.push_back("exceptTypeToThrow");
-
- llvm::Function *ret = createFunction(module,
+
+ llvm::Function *ret = createFunction(module,
builder.getVoidTy(),
- argTypes,
- argNames,
+ argTypes,
+ argNames,
ourId,
- llvm::Function::ExternalLinkage,
- false,
+ llvm::Function::ExternalLinkage,
+ false,
false);
-
+
// Block which calls invoke
llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
- "entry",
+ "entry",
ret);
// Normal block for invoke
- llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
- "normal",
+ llvm::BasicBlock *normalBlock = llvm::BasicBlock::Create(context,
+ "normal",
ret);
// Unwind block for invoke
- llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
- "exception",
+ llvm::BasicBlock *exceptionBlock = llvm::BasicBlock::Create(context,
+ "exception",
ret);
-
+
// Block which routes exception to correct catch handler block
- llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
- "exceptionRoute",
+ llvm::BasicBlock *exceptionRouteBlock = llvm::BasicBlock::Create(context,
+ "exceptionRoute",
ret);
-
+
// Foreign exception handler
- llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
- "externalException",
+ llvm::BasicBlock *externalExceptionBlock = llvm::BasicBlock::Create(context,
+ "externalException",
ret);
-
+
// Block which calls _Unwind_Resume
- llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
- "unwindResume",
+ llvm::BasicBlock *unwindResumeBlock = llvm::BasicBlock::Create(context,
+ "unwindResume",
ret);
-
+
// Clean up block which delete exception if needed
llvm::BasicBlock *endBlock = llvm::BasicBlock::Create(context, "end", ret);
-
+
std::string nextName;
std::vector<llvm::BasicBlock*> catchBlocks(numExceptionsToCatch);
llvm::Value *exceptionCaughtFlag = NULL;
llvm::Value *exceptionStorage = NULL;
llvm::Value *caughtResultStorage = NULL;
-
- // Finally block which will branch to unwindResumeBlock if
+
+ // Finally block which will branch to unwindResumeBlock if
// exception is not caught. Initializes/allocates stack locations.
- llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
- module,
- builder,
- *ret,
- nextName = "finally",
+ llvm::BasicBlock *finallyBlock = createFinallyBlock(context,
+ module,
+ builder,
+ *ret,
+ nextName = "finally",
ourId,
*endBlock,
*unwindResumeBlock,
@@ -1171,74 +1171,74 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
&exceptionStorage,
&caughtResultStorage
);
-
+
for (unsigned i = 0; i < numExceptionsToCatch; ++i) {
nextName = ourTypeInfoNames[exceptionTypesToCatch[i]];
-
+
// One catch block per type info to be caught
- catchBlocks[i] = createCatchBlock(context,
- module,
- builder,
+ catchBlocks[i] = createCatchBlock(context,
+ module,
+ builder,
*ret,
- nextName,
+ nextName,
ourId,
*finallyBlock,
*exceptionCaughtFlag);
}
-
+
// Entry Block
-
+
builder.SetInsertPoint(entryBlock);
-
+
std::vector<llvm::Value*> args;
args.push_back(namedValues["exceptTypeToThrow"]);
- builder.CreateInvoke(&toInvoke,
- normalBlock,
- exceptionBlock,
+ builder.CreateInvoke(&toInvoke,
+ normalBlock,
+ exceptionBlock,
args);
-
+
// End Block
-
+
builder.SetInsertPoint(endBlock);
-
- generateStringPrint(context,
+
+ generateStringPrint(context,
module,
- builder,
+ builder,
"Gen: In end block: exiting in " + ourId + ".\n",
USE_GLOBAL_STR_CONSTS);
llvm::Function *deleteOurException = module.getFunction("deleteOurException");
-
+
// Note: function handles NULL exceptions
- builder.CreateCall(deleteOurException,
+ builder.CreateCall(deleteOurException,
builder.CreateLoad(exceptionStorage));
builder.CreateRetVoid();
-
+
// Normal Block
-
+
builder.SetInsertPoint(normalBlock);
-
- generateStringPrint(context,
+
+ generateStringPrint(context,
module,
- builder,
+ builder,
"Gen: No exception in " + ourId + "!\n",
USE_GLOBAL_STR_CONSTS);
-
+
// Finally block is always called
builder.CreateBr(finallyBlock);
-
+
// Unwind Resume Block
-
+
builder.SetInsertPoint(unwindResumeBlock);
-
+
builder.CreateResume(builder.CreateLoad(caughtResultStorage));
-
+
// Exception Block
-
+
builder.SetInsertPoint(exceptionBlock);
-
+
llvm::Function *personality = module.getFunction("ourPersonality");
-
- llvm::LandingPadInst *caughtResult =
+
+ llvm::LandingPadInst *caughtResult =
builder.CreateLandingPad(ourCaughtResultType,
personality,
numExceptionsToCatch,
@@ -1255,48 +1255,48 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
llvm::Value *unwindException = builder.CreateExtractValue(caughtResult, 0);
llvm::Value *retTypeInfoIndex = builder.CreateExtractValue(caughtResult, 1);
- // FIXME: Redundant storage which, beyond utilizing value of
- // caughtResultStore for unwindException storage, may be alleviated
+ // FIXME: Redundant storage which, beyond utilizing value of
+ // caughtResultStore for unwindException storage, may be alleviated
// altogether with a block rearrangement
builder.CreateStore(caughtResult, caughtResultStorage);
builder.CreateStore(unwindException, exceptionStorage);
builder.CreateStore(ourExceptionThrownState, exceptionCaughtFlag);
-
- // Retrieve exception_class member from thrown exception
+
+ // Retrieve exception_class member from thrown exception
// (_Unwind_Exception instance). This member tells us whether or not
// the exception is foreign.
- llvm::Value *unwindExceptionClass =
+ llvm::Value *unwindExceptionClass =
builder.CreateLoad(builder.CreateStructGEP(
- builder.CreatePointerCast(unwindException,
- ourUnwindExceptionType->getPointerTo()),
+ builder.CreatePointerCast(unwindException,
+ ourUnwindExceptionType->getPointerTo()),
0));
-
+
// Branch to the externalExceptionBlock if the exception is foreign or
// to a catch router if not. Either way the finally block will be run.
builder.CreateCondBr(builder.CreateICmpEQ(unwindExceptionClass,
- llvm::ConstantInt::get(builder.getInt64Ty(),
+ llvm::ConstantInt::get(builder.getInt64Ty(),
ourBaseExceptionClass)),
exceptionRouteBlock,
externalExceptionBlock);
-
+
// External Exception Block
-
+
builder.SetInsertPoint(externalExceptionBlock);
-
- generateStringPrint(context,
+
+ generateStringPrint(context,
module,
- builder,
+ builder,
"Gen: Foreign exception received.\n",
USE_GLOBAL_STR_CONSTS);
-
+
// Branch to the finally block
builder.CreateBr(finallyBlock);
-
+
// Exception Route Block
-
+
builder.SetInsertPoint(exceptionRouteBlock);
-
- // Casts exception pointer (_Unwind_Exception instance) to parent
+
+ // Casts exception pointer (_Unwind_Exception instance) to parent
// (OurException instance).
//
// Note: ourBaseFromUnwindOffset is usually negative
@@ -1304,34 +1304,34 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
builder.CreateConstGEP1_64(unwindException,
ourBaseFromUnwindOffset),
ourExceptionType->getPointerTo());
-
+
// Retrieve thrown exception type info type
//
// Note: Index is not relative to pointer but instead to structure
// unlike a true getelementptr (GEP) instruction
typeInfoThrown = builder.CreateStructGEP(typeInfoThrown, 0);
-
- llvm::Value *typeInfoThrownType =
+
+ llvm::Value *typeInfoThrownType =
builder.CreateStructGEP(typeInfoThrown, 0);
-
- generateIntegerPrint(context,
+
+ generateIntegerPrint(context,
module,
- builder,
- *toPrint32Int,
+ builder,
+ *toPrint32Int,
*(builder.CreateLoad(typeInfoThrownType)),
- "Gen: Exception type <%d> received (stack unwound) "
- " in " +
- ourId +
+ "Gen: Exception type <%d> received (stack unwound) "
+ " in " +
+ ourId +
".\n",
USE_GLOBAL_STR_CONSTS);
-
+
// Route to matched type info catch block or run cleanup finally block
- llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
- finallyBlock,
+ llvm::SwitchInst *switchToCatchBlock = builder.CreateSwitch(retTypeInfoIndex,
+ finallyBlock,
numExceptionsToCatch);
-
+
unsigned nextTypeToCatch;
-
+
for (unsigned i = 1; i <= numExceptionsToCatch; ++i) {
nextTypeToCatch = i - 1;
switchToCatchBlock->addCase(llvm::ConstantInt::get(
@@ -1341,18 +1341,18 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
llvm::verifyFunction(*ret);
fpm.run(*ret);
-
+
return(ret);
}
/// Generates function which throws either an exception matched to a runtime
-/// determined type info type (argument to generated function), or if this
-/// runtime value matches nativeThrowType, throws a foreign exception by
+/// determined type info type (argument to generated function), or if this
+/// runtime value matches nativeThrowType, throws a foreign exception by
/// calling nativeThrowFunct.
/// @param module code for module instance
/// @param builder builder instance
-/// @param fpm a function pass manager holding optional IR to IR
+/// @param fpm a function pass manager holding optional IR to IR
/// transformations
/// @param ourId id used to printing purposes
/// @param nativeThrowType a runtime argument of this value results in
@@ -1361,8 +1361,8 @@ llvm::Function *createCatchWrappedInvokeFunction(llvm::Module &module,
/// if the above nativeThrowType matches generated function's arg.
/// @returns generated function
static
-llvm::Function *createThrowExceptionFunction(llvm::Module &module,
- llvm::IRBuilder<> &builder,
+llvm::Function *createThrowExceptionFunction(llvm::Module &module,
+ llvm::IRBuilder<> &builder,
llvm::FunctionPassManager &fpm,
std::string ourId,
int32_t nativeThrowType,
@@ -1373,7 +1373,7 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module,
unwindArgTypes.push_back(builder.getInt32Ty());
ArgNames unwindArgNames;
unwindArgNames.push_back("exceptTypeToThrow");
-
+
llvm::Function *ret = createFunction(module,
builder.getVoidTy(),
unwindArgTypes,
@@ -1382,88 +1382,88 @@ llvm::Function *createThrowExceptionFunction(llvm::Module &module,
llvm::Function::ExternalLinkage,
false,
false);
-
+
// Throws either one of our exception or a native C++ exception depending
// on a runtime argument value containing a type info type.
llvm::BasicBlock *entryBlock = llvm::BasicBlock::Create(context,
- "entry",
+ "entry",
ret);
// Throws a foreign exception
llvm::BasicBlock *nativeThrowBlock = llvm::BasicBlock::Create(context,
- "nativeThrow",
+ "nativeThrow",
ret);
// Throws one of our Exceptions
llvm::BasicBlock *generatedThrowBlock = llvm::BasicBlock::Create(context,
- "generatedThrow",
+ "generatedThrow",
ret);
// Retrieved runtime type info type to throw
llvm::Value *exceptionType = namedValues["exceptTypeToThrow"];
-
+
// nativeThrowBlock block
-
+
builder.SetInsertPoint(nativeThrowBlock);
-
+
// Throws foreign exception
builder.CreateCall(&nativeThrowFunct, exceptionType);
builder.CreateUnreachable();
-
+
// entry block
-
+
builder.SetInsertPoint(entryBlock);
-
+
llvm::Function *toPrint32Int = module.getFunction("print32Int");
- generateIntegerPrint(context,
+ generateIntegerPrint(context,
module,
- builder,
- *toPrint32Int,
- *exceptionType,
- "\nGen: About to throw exception type <%d> in " +
- ourId +
+ builder,
+ *toPrint32Int,
+ *exceptionType,
+ "\nGen: About to throw exception type <%d> in " +
+ ourId +
".\n",
USE_GLOBAL_STR_CONSTS);
-
+
// Switches on runtime type info type value to determine whether or not
- // a foreign exception is thrown. Defaults to throwing one of our
+ // a foreign exception is thrown. Defaults to throwing one of our
// generated exceptions.
llvm::SwitchInst *theSwitch = builder.CreateSwitch(exceptionType,
generatedThrowBlock,
1);
-
- theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
+
+ theSwitch->addCase(llvm::ConstantInt::get(llvm::Type::getInt32Ty(context),
nativeThrowType),
nativeThrowBlock);
-
+
// generatedThrow block
-
+
builder.SetInsertPoint(generatedThrowBlock);
-
+
llvm::Function *createOurException = module.getFunction("createOurException");
llvm::Function *raiseOurException = module.getFunction(
"_Unwind_RaiseException");
-
+
// Creates exception to throw with runtime type info type.
- llvm::Value *exception = builder.CreateCall(createOurException,
+ llvm::Value *exception = builder.CreateCall(createOurException,
namedValues["exceptTypeToThrow"]);
-
+
// Throw generated Exception
builder.CreateCall(raiseOurException, exception);
builder.CreateUnreachable();
-
+
llvm::verifyFunction(*ret);
fpm.run(*ret);
-
+
return(ret);
}
static void createStandardUtilityFunctions(unsigned numTypeInfos,
- llvm::Module &module,
+ llvm::Module &module,
llvm::IRBuilder<> &builder);
-/// Creates test code by generating and organizing these functions into the
+/// Creates test code by generating and organizing these functions into the
/// test case. The test case consists of an outer function setup to invoke
-/// an inner function within an environment having multiple catch and single
+/// an inner function within an environment having multiple catch and single
/// finally blocks. This inner function is also setup to invoke a throw
-/// function within an evironment similar in nature to the outer function's
+/// function within an evironment similar in nature to the outer function's
/// catch and finally blocks. Each of these two functions catch mutually
/// exclusive subsets (even or odd) of the type info types configured
/// for this this. All generated functions have a runtime argument which
@@ -1474,26 +1474,26 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
/// a supplied a function which in turn will throw a foreign exception.
/// @param module code for module instance
/// @param builder builder instance
-/// @param fpm a function pass manager holding optional IR to IR
+/// @param fpm a function pass manager holding optional IR to IR
/// transformations
/// @param nativeThrowFunctName name of external function which will throw
/// a foreign exception
/// @returns outermost generated test function.
-llvm::Function *createUnwindExceptionTest(llvm::Module &module,
- llvm::IRBuilder<> &builder,
+llvm::Function *createUnwindExceptionTest(llvm::Module &module,
+ llvm::IRBuilder<> &builder,
llvm::FunctionPassManager &fpm,
std::string nativeThrowFunctName) {
// Number of type infos to generate
unsigned numTypeInfos = 6;
-
+
// Initialze intrisics and external functions to use along with exception
// and type info globals.
createStandardUtilityFunctions(numTypeInfos,
module,
builder);
llvm::Function *nativeThrowFunct = module.getFunction(nativeThrowFunctName);
-
- // Create exception throw function using the value ~0 to cause
+
+ // Create exception throw function using the value ~0 to cause
// foreign exceptions to be thrown.
llvm::Function *throwFunct = createThrowExceptionFunction(module,
builder,
@@ -1503,9 +1503,9 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
*nativeThrowFunct);
// Inner function will catch even type infos
unsigned innerExceptionTypesToCatch[] = {6, 2, 4};
- size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
+ size_t numExceptionTypesToCatch = sizeof(innerExceptionTypesToCatch) /
sizeof(unsigned);
-
+
// Generate inner function.
llvm::Function *innerCatchFunct = createCatchWrappedInvokeFunction(module,
builder,
@@ -1514,12 +1514,12 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
"innerCatchFunct",
numExceptionTypesToCatch,
innerExceptionTypesToCatch);
-
+
// Outer function will catch odd type infos
unsigned outerExceptionTypesToCatch[] = {3, 1, 5};
- numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
+ numExceptionTypesToCatch = sizeof(outerExceptionTypesToCatch) /
sizeof(unsigned);
-
+
// Generate outer function
llvm::Function *outerCatchFunct = createCatchWrappedInvokeFunction(module,
builder,
@@ -1528,7 +1528,7 @@ llvm::Function *createUnwindExceptionTest(llvm::Module &module,
"outerCatchFunct",
numExceptionTypesToCatch,
outerExceptionTypesToCatch);
-
+
// Return outer function to run
return(outerCatchFunct);
}
@@ -1539,15 +1539,15 @@ class OurCppRunException : public std::runtime_error {
public:
OurCppRunException(const std::string reason) :
std::runtime_error(reason) {}
-
+
OurCppRunException (const OurCppRunException &toCopy) :
std::runtime_error(toCopy) {}
-
+
OurCppRunException &operator = (const OurCppRunException &toCopy) {
return(reinterpret_cast<OurCppRunException&>(
std::runtime_error::operator=(toCopy)));
}
-
+
~OurCppRunException (void) throw () {}
};
@@ -1562,7 +1562,7 @@ void throwCppException (int32_t ignoreIt) {
typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
-/// This is a test harness which runs test by executing generated
+/// This is a test harness which runs test by executing generated
/// function with a type info type to throw. Harness wraps the execution
/// of generated function in a C++ try catch clause.
/// @param engine execution engine to use for executing generated function.
@@ -1572,15 +1572,15 @@ typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow);
/// @param typeToThrow type info type of generated exception to throw, or
/// indicator to cause foreign exception to be thrown.
static
-void runExceptionThrow(llvm::ExecutionEngine *engine,
- llvm::Function *function,
+void runExceptionThrow(llvm::ExecutionEngine *engine,
+ llvm::Function *function,
int32_t typeToThrow) {
-
+
// Find test's function pointer
- OurExceptionThrowFunctType functPtr =
+ OurExceptionThrowFunctType functPtr =
reinterpret_cast<OurExceptionThrowFunctType>(
reinterpret_cast<intptr_t>(engine->getPointerToFunction(function)));
-
+
try {
// Run test
(*functPtr)(typeToThrow);
@@ -1589,15 +1589,15 @@ void runExceptionThrow(llvm::ExecutionEngine *engine,
// Catch foreign C++ exception
fprintf(stderr,
"\nrunExceptionThrow(...):In C++ catch OurCppRunException "
- "with reason: %s.\n",
+ "with reason: %s.\n",
exc.what());
}
catch (...) {
- // Catch all exceptions including our generated ones. This latter
+ // Catch all exceptions including our generated ones. This latter
// functionality works according to the example in rules 1.6.4 of
- // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22),
- // given that these will be exceptions foreign to C++
- // (the _Unwind_Exception::exception_class should be different from
+ // http://sourcery.mentor.com/public/cxx-abi/abi-eh.html (v1.22),
+ // given that these will be exceptions foreign to C++
+ // (the _Unwind_Exception::exception_class should be different from
// the one used by C++).
fprintf(stderr,
"\nrunExceptionThrow(...):In C++ catch all.\n");
@@ -1610,32 +1610,32 @@ void runExceptionThrow(llvm::ExecutionEngine *engine,
typedef llvm::ArrayRef<llvm::Type*> TypeArray;
-/// This initialization routine creates type info globals and
+/// This initialization routine creates type info globals and
/// adds external function declarations to module.
/// @param numTypeInfos number of linear type info associated type info types
/// to create as GlobalVariable instances, starting with the value 1.
/// @param module code for module instance
/// @param builder builder instance
static void createStandardUtilityFunctions(unsigned numTypeInfos,
- llvm::Module &module,
+ llvm::Module &module,
llvm::IRBuilder<> &builder) {
-
+
llvm::LLVMContext &context = module.getContext();
-
+
// Exception initializations
-
+
// Setup exception catch state
- ourExceptionNotThrownState =
+ ourExceptionNotThrownState =
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 0),
- ourExceptionThrownState =
+ ourExceptionThrownState =
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 1),
- ourExceptionCaughtState =
+ ourExceptionCaughtState =
llvm::ConstantInt::get(llvm::Type::getInt8Ty(context), 2),
-
-
-
+
+
+
// Create our type info type
- ourTypeInfoType = llvm::StructType::get(context,
+ ourTypeInfoType = llvm::StructType::get(context,
TypeArray(builder.getInt32Ty()));
llvm::Type *caughtResultFieldTypes[] = {
@@ -1648,47 +1648,47 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
TypeArray(caughtResultFieldTypes));
// Create OurException type
- ourExceptionType = llvm::StructType::get(context,
+ ourExceptionType = llvm::StructType::get(context,
TypeArray(ourTypeInfoType));
-
+
// Create portion of _Unwind_Exception type
//
// Note: Declaring only a portion of the _Unwind_Exception struct.
// Does this cause problems?
ourUnwindExceptionType =
- llvm::StructType::get(context,
+ llvm::StructType::get(context,
TypeArray(builder.getInt64Ty()));
struct OurBaseException_t dummyException;
-
+
// Calculate offset of OurException::unwindException member.
- ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
+ ourBaseFromUnwindOffset = ((uintptr_t) &dummyException) -
((uintptr_t) &(dummyException.unwindException));
-
+
#ifdef DEBUG
fprintf(stderr,
"createStandardUtilityFunctions(...):ourBaseFromUnwindOffset "
"= %lld, sizeof(struct OurBaseException_t) - "
"sizeof(struct _Unwind_Exception) = %lu.\n",
ourBaseFromUnwindOffset,
- sizeof(struct OurBaseException_t) -
+ sizeof(struct OurBaseException_t) -
sizeof(struct _Unwind_Exception));
#endif
-
+
size_t numChars = sizeof(ourBaseExcpClassChars) / sizeof(char);
-
+
// Create our _Unwind_Exception::exception_class value
ourBaseExceptionClass = genClass(ourBaseExcpClassChars, numChars);
-
+
// Type infos
-
+
std::string baseStr = "typeInfo", typeInfoName;
std::ostringstream typeInfoNameBuilder;
std::vector<llvm::Constant*> structVals;
-
+
llvm::Constant *nextStruct;
llvm::GlobalVariable *nextGlobal = NULL;
-
+
// Generate each type info
//
// Note: First type info is not used.
@@ -1696,202 +1696,202 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
structVals.clear();
structVals.push_back(llvm::ConstantInt::get(builder.getInt32Ty(), i));
nextStruct = llvm::ConstantStruct::get(ourTypeInfoType, structVals);
-
+
typeInfoNameBuilder.str("");
typeInfoNameBuilder << baseStr << i;
typeInfoName = typeInfoNameBuilder.str();
-
+
// Note: Does not seem to work without allocation
- nextGlobal =
- new llvm::GlobalVariable(module,
- ourTypeInfoType,
- true,
- llvm::GlobalValue::ExternalLinkage,
- nextStruct,
+ nextGlobal =
+ new llvm::GlobalVariable(module,
+ ourTypeInfoType,
+ true,
+ llvm::GlobalValue::ExternalLinkage,
+ nextStruct,
typeInfoName);
-
+
ourTypeInfoNames.push_back(typeInfoName);
ourTypeInfoNamesIndex[i] = typeInfoName;
}
-
+
ArgNames argNames;
ArgTypes argTypes;
llvm::Function *funct = NULL;
-
+
// print32Int
-
+
llvm::Type *retType = builder.getVoidTy();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt32Ty());
argTypes.push_back(builder.getInt8PtrTy());
-
+
argNames.clear();
-
- createFunction(module,
- retType,
- argTypes,
- argNames,
- "print32Int",
- llvm::Function::ExternalLinkage,
- true,
+
+ createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "print32Int",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
+
// print64Int
-
+
retType = builder.getVoidTy();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt64Ty());
argTypes.push_back(builder.getInt8PtrTy());
-
+
argNames.clear();
-
- createFunction(module,
- retType,
- argTypes,
- argNames,
- "print64Int",
- llvm::Function::ExternalLinkage,
- true,
+
+ createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "print64Int",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
+
// printStr
-
+
retType = builder.getVoidTy();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt8PtrTy());
-
+
argNames.clear();
-
- createFunction(module,
- retType,
- argTypes,
- argNames,
- "printStr",
- llvm::Function::ExternalLinkage,
- true,
+
+ createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "printStr",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
+
// throwCppException
-
+
retType = builder.getVoidTy();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt32Ty());
-
+
argNames.clear();
-
- createFunction(module,
- retType,
- argTypes,
- argNames,
- "throwCppException",
- llvm::Function::ExternalLinkage,
- true,
+
+ createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "throwCppException",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
+
// deleteOurException
-
+
retType = builder.getVoidTy();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt8PtrTy());
-
+
argNames.clear();
-
- createFunction(module,
- retType,
- argTypes,
- argNames,
- "deleteOurException",
- llvm::Function::ExternalLinkage,
- true,
+
+ createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "deleteOurException",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
+
// createOurException
-
+
retType = builder.getInt8PtrTy();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt32Ty());
-
+
argNames.clear();
-
- createFunction(module,
- retType,
- argTypes,
- argNames,
- "createOurException",
- llvm::Function::ExternalLinkage,
- true,
+
+ createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "createOurException",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
+
// _Unwind_RaiseException
-
+
retType = builder.getInt32Ty();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt8PtrTy());
-
+
argNames.clear();
-
- funct = createFunction(module,
- retType,
- argTypes,
- argNames,
- "_Unwind_RaiseException",
- llvm::Function::ExternalLinkage,
- true,
+
+ funct = createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "_Unwind_RaiseException",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
- funct->addFnAttr(llvm::Attribute::NoReturn);
-
+
+ funct->setDoesNotReturn();
+
// _Unwind_Resume
-
+
retType = builder.getInt32Ty();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt8PtrTy());
-
+
argNames.clear();
-
- funct = createFunction(module,
- retType,
- argTypes,
- argNames,
- "_Unwind_Resume",
- llvm::Function::ExternalLinkage,
- true,
+
+ funct = createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "_Unwind_Resume",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
- funct->addFnAttr(llvm::Attribute::NoReturn);
-
+
+ funct->setDoesNotReturn();
+
// ourPersonality
-
+
retType = builder.getInt32Ty();
-
+
argTypes.clear();
argTypes.push_back(builder.getInt32Ty());
argTypes.push_back(builder.getInt32Ty());
argTypes.push_back(builder.getInt64Ty());
argTypes.push_back(builder.getInt8PtrTy());
argTypes.push_back(builder.getInt8PtrTy());
-
+
argNames.clear();
-
- createFunction(module,
- retType,
- argTypes,
- argNames,
- "ourPersonality",
- llvm::Function::ExternalLinkage,
- true,
+
+ createFunction(module,
+ retType,
+ argTypes,
+ argNames,
+ "ourPersonality",
+ llvm::Function::ExternalLinkage,
+ true,
false);
-
+
// llvm.eh.typeid.for intrinsic
-
+
getDeclaration(&module, llvm::Intrinsic::eh_typeid_for);
}
@@ -1901,7 +1901,7 @@ static void createStandardUtilityFunctions(unsigned numTypeInfos,
//===----------------------------------------------------------------------===//
/// Demo main routine which takes the type info types to throw. A test will
-/// be run for each given type info type. While type info types with the value
+/// be run for each given type info type. While type info types with the value
/// of -1 will trigger a foreign C++ exception to be thrown; type info types
/// <= 6 and >= 1 will be caught by test functions; and type info types > 6
/// will result in exceptions which pass through to the test harness. All other
@@ -1920,87 +1920,86 @@ int main(int argc, char *argv[]) {
" for a full test.\n\n");
return(0);
}
-
+
// If not set, exception handling will not be turned on
llvm::TargetOptions Opts;
Opts.JITExceptionHandling = true;
-
+
llvm::InitializeNativeTarget();
llvm::LLVMContext &context = llvm::getGlobalContext();
llvm::IRBuilder<> theBuilder(context);
-
+
// Make the module, which holds all the code.
llvm::Module *module = new llvm::Module("my cool jit", context);
-
+
// Build engine with JIT
llvm::EngineBuilder factory(module);
factory.setEngineKind(llvm::EngineKind::JIT);
factory.setAllocateGVsWithCode(false);
factory.setTargetOptions(Opts);
llvm::ExecutionEngine *executionEngine = factory.create();
-
+
{
llvm::FunctionPassManager fpm(module);
-
- // Set up the optimizer pipeline.
+
+ // Set up the optimizer pipeline.
// Start with registering info about how the
// target lays out data structures.
fpm.add(new llvm::DataLayout(*executionEngine->getDataLayout()));
-
+
// Optimizations turned on
#ifdef ADD_OPT_PASSES
-
+
// Basic AliasAnslysis support for GVN.
fpm.add(llvm::createBasicAliasAnalysisPass());
-
+
// Promote allocas to registers.
fpm.add(llvm::createPromoteMemoryToRegisterPass());
-
+
// Do simple "peephole" optimizations and bit-twiddling optzns.
fpm.add(llvm::createInstructionCombiningPass());
-
+
// Reassociate expressions.
fpm.add(llvm::createReassociatePass());
-
+
// Eliminate Common SubExpressions.
fpm.add(llvm::createGVNPass());
-
- // Simplify the control flow graph (deleting unreachable
+
+ // Simplify the control flow graph (deleting unreachable
// blocks, etc).
fpm.add(llvm::createCFGSimplificationPass());
#endif // ADD_OPT_PASSES
-
+
fpm.doInitialization();
-
+
// Generate test code using function throwCppException(...) as
// the function which throws foreign exceptions.
- llvm::Function *toRun =
- createUnwindExceptionTest(*module,
- theBuilder,
+ llvm::Function *toRun =
+ createUnwindExceptionTest(*module,
+ theBuilder,
fpm,
"throwCppException");
-
+
fprintf(stderr, "\nBegin module dump:\n\n");
-
+
module->dump();
-
+
fprintf(stderr, "\nEnd module dump:\n");
-
+
fprintf(stderr, "\n\nBegin Test:\n");
-
+
for (int i = 1; i < argc; ++i) {
// Run test for each argument whose value is the exception
// type to throw.
- runExceptionThrow(executionEngine,
- toRun,
+ runExceptionThrow(executionEngine,
+ toRun,
(unsigned) strtoul(argv[i], NULL, 10));
}
-
+
fprintf(stderr, "\nEnd Test:\n\n");
- }
-
+ }
+
delete executionEngine;
-
+
return 0;
}
-
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h
index 8cf03c268cd..620d0887be7 100644
--- a/include/llvm-c/Core.h
+++ b/include/llvm-c/Core.h
@@ -1803,7 +1803,7 @@ LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg);
* Set the alignment for a function parameter.
*
* @see llvm::Argument::addAttr()
- * @see llvm::Attributes::constructAlignmentFromInt()
+ * @see llvm::AttrBuilder::addAlignmentAttr()
*/
void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align);
diff --git a/include/llvm-c/Target.h b/include/llvm-c/Target.h
index 92228701e31..57abfa0207f 100644
--- a/include/llvm-c/Target.h
+++ b/include/llvm-c/Target.h
@@ -172,10 +172,20 @@ enum LLVMByteOrdering LLVMByteOrder(LLVMTargetDataRef);
See the method llvm::DataLayout::getPointerSize. */
unsigned LLVMPointerSize(LLVMTargetDataRef);
+/** Returns the pointer size in bytes for a target for a specified
+ address space.
+ See the method llvm::DataLayout::getPointerSize. */
+unsigned LLVMPointerSizeForAS(LLVMTargetDataRef, unsigned AS);
+
/** Returns the integer type that is the same size as a pointer on a target.
See the method llvm::DataLayout::getIntPtrType. */
LLVMTypeRef LLVMIntPtrType(LLVMTargetDataRef);
+/** Returns the integer type that is the same size as a pointer on a target.
+ This version allows the address space to be specified.
+ See the method llvm::DataLayout::getIntPtrType. */
+LLVMTypeRef LLVMIntPtrTypeForAS(LLVMTargetDataRef, unsigned AS);
+
/** Computes the size of a type in bytes for a target.
See the method llvm::DataLayout::getTypeSizeInBits. */
unsigned long long LLVMSizeOfTypeInBits(LLVMTargetDataRef, LLVMTypeRef);
diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h
index 26ec346b182..9d6388f7ee6 100644
--- a/include/llvm/ADT/BitVector.h
+++ b/include/llvm/ADT/BitVector.h
@@ -237,6 +237,34 @@ public:
return *this;
}
+ /// set - Efficiently set a range of bits in [I, E)
+ BitVector &set(unsigned I, unsigned E) {
+ assert(I <= E && "Attempted to set backwards range!");
+ assert(E <= size() && "Attempted to set out-of-bounds range!");
+
+ if (I == E) return *this;
+
+ if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
+ BitWord EMask = 1UL << (E % BITWORD_SIZE);
+ BitWord IMask = 1UL << (I % BITWORD_SIZE);
+ BitWord Mask = EMask - IMask;
+ Bits[I / BITWORD_SIZE] |= Mask;
+ return *this;
+ }
+
+ BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
+ Bits[I / BITWORD_SIZE] |= PrefixMask;
+ I = RoundUpToAlignment(I, BITWORD_SIZE);
+
+ for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
+ Bits[I / BITWORD_SIZE] = ~0UL;
+
+ BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
+ Bits[I / BITWORD_SIZE] |= PostfixMask;
+
+ return *this;
+ }
+
BitVector &reset() {
init_words(Bits, Capacity, false);
return *this;
@@ -247,6 +275,34 @@ public:
return *this;
}
+ /// reset - Efficiently reset a range of bits in [I, E)
+ BitVector &reset(unsigned I, unsigned E) {
+ assert(I <= E && "Attempted to reset backwards range!");
+ assert(E <= size() && "Attempted to reset out-of-bounds range!");
+
+ if (I == E) return *this;
+
+ if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
+ BitWord EMask = 1UL << (E % BITWORD_SIZE);
+ BitWord IMask = 1UL << (I % BITWORD_SIZE);
+ BitWord Mask = EMask - IMask;
+ Bits[I / BITWORD_SIZE] &= ~Mask;
+ return *this;
+ }
+
+ BitWord PrefixMask = ~0UL << (I % BITWORD_SIZE);
+ Bits[I / BITWORD_SIZE] &= ~PrefixMask;
+ I = RoundUpToAlignment(I, BITWORD_SIZE);
+
+ for (; I + BITWORD_SIZE <= E; I += BITWORD_SIZE)
+ Bits[I / BITWORD_SIZE] = 0UL;
+
+ BitWord PostfixMask = (1UL << (E % BITWORD_SIZE)) - 1;
+ Bits[I / BITWORD_SIZE] &= ~PostfixMask;
+
+ return *this;
+ }
+
BitVector &flip() {
for (unsigned i = 0; i < NumBitWords(size()); ++i)
Bits[i] = ~Bits[i];
diff --git a/include/llvm/ADT/ImmutableSet.h b/include/llvm/ADT/ImmutableSet.h
index 261d0494e2d..3900f96be16 100644
--- a/include/llvm/ADT/ImmutableSet.h
+++ b/include/llvm/ADT/ImmutableSet.h
@@ -89,7 +89,7 @@ public:
ImutAVLTree* getMaxElement() {
ImutAVLTree *T = this;
ImutAVLTree *Right = T->getRight();
- while (Right) { T = right; right = T->getRight(); }
+ while (Right) { T = Right; Right = T->getRight(); }
return T;
}
diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h
index 7a645e0c724..fba1d12542a 100644
--- a/include/llvm/ADT/SmallBitVector.h
+++ b/include/llvm/ADT/SmallBitVector.h
@@ -300,6 +300,21 @@ public:
return *this;
}
+ /// set - Efficiently set a range of bits in [I, E)
+ SmallBitVector &set(unsigned I, unsigned E) {
+ assert(I <= E && "Attempted to set backwards range!");
+ assert(E <= size() && "Attempted to set out-of-bounds range!");
+ if (I == E) return *this;
+ if (isSmall()) {
+ uintptr_t EMask = 1 << E;
+ uintptr_t IMask = 1 << I;
+ uintptr_t Mask = EMask - IMask;
+ setSmallBits(getSmallBits() | Mask);
+ } else
+ getPointer()->set(I, E);
+ return *this;
+ }
+
SmallBitVector &reset() {
if (isSmall())
setSmallBits(0);
@@ -316,6 +331,21 @@ public:
return *this;
}
+ /// reset - Efficiently reset a range of bits in [I, E)
+ SmallBitVector &reset(unsigned I, unsigned E) {
+ assert(I <= E && "Attempted to reset backwards range!");
+ assert(E <= size() && "Attempted to reset out-of-bounds range!");
+ if (I == E) return *this;
+ if (isSmall()) {
+ uintptr_t EMask = 1 << E;
+ uintptr_t IMask = 1 << I;
+ uintptr_t Mask = EMask - IMask;
+ setSmallBits(getSmallBits() & ~Mask);
+ } else
+ getPointer()->reset(I, E);
+ return *this;
+ }
+
SmallBitVector &flip() {
if (isSmall())
setSmallBits(~getSmallBits());
diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h
index a0527683f67..15fe55fbe3b 100644
--- a/include/llvm/ADT/Triple.h
+++ b/include/llvm/ADT/Triple.h
@@ -76,7 +76,8 @@ public:
SCEI,
BGP,
BGQ,
- Freescale
+ Freescale,
+ IBM
};
enum OSType {
UnknownOS,
@@ -101,7 +102,8 @@ public:
RTEMS,
NativeClient,
CNK, // BG/P Compute-Node Kernel
- Bitrig
+ Bitrig,
+ AIX
};
enum EnvironmentType {
UnknownEnvironment,
diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h
new file mode 100644
index 00000000000..9b6a6bbd3ed
--- /dev/null
+++ b/include/llvm/Analysis/DependenceAnalysis.h
@@ -0,0 +1,891 @@
+//===-- llvm/Analysis/DependenceAnalysis.h -------------------- -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// DependenceAnalysis is an LLVM pass that analyses dependences between memory
+// accesses. Currently, it is an implementation of the approach described in
+//
+// Practical Dependence Testing
+// Goff, Kennedy, Tseng
+// PLDI 1991
+//
+// There's a single entry point that analyzes the dependence between a pair
+// of memory references in a function, returning either NULL, for no dependence,
+// or a more-or-less detailed description of the dependence between them.
+//
+// Please note that this is work in progress and the interface is subject to
+// change.
+//
+// Plausible changes:
+// Return a set of more precise dependences instead of just one dependence
+// summarizing all.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
+#define LLVM_ANALYSIS_DEPENDENCEANALYSIS_H
+
+#include "llvm/BasicBlock.h"
+#include "llvm/Function.h"
+#include "llvm/Instruction.h"
+#include "llvm/Pass.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "llvm/Analysis/ScalarEvolution.h"
+#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Support/raw_ostream.h"
+
+
+namespace llvm {
+ class AliasAnalysis;
+ class ScalarEvolution;
+ class SCEV;
+ class Value;
+ class raw_ostream;
+
+ /// Dependence - This class represents a dependence between two memory
+ /// memory references in a function. It contains minimal information and
+ /// is used in the very common situation where the compiler is unable to
+ /// determine anything beyond the existence of a dependence; that is, it
+ /// represents a confused dependence (see also FullDependence). In most
+ /// cases (for output, flow, and anti dependences), the dependence implies
+ /// an ordering, where the source must preceed the destination; in contrast,
+ /// input dependences are unordered.
+ class Dependence {
+ public:
+ Dependence(const Instruction *Source,
+ const Instruction *Destination) :
+ Src(Source), Dst(Destination) {}
+ virtual ~Dependence() {}
+
+ /// Dependence::DVEntry - Each level in the distance/direction vector
+ /// has a direction (or perhaps a union of several directions), and
+ /// perhaps a distance.
+ struct DVEntry {
+ enum { NONE = 0,
+ LT = 1,
+ EQ = 2,
+ LE = 3,
+ GT = 4,
+ NE = 5,
+ GE = 6,
+ ALL = 7 };
+ unsigned char Direction : 3; // Init to ALL, then refine.
+ bool Scalar : 1; // Init to true.
+ bool PeelFirst : 1; // Peeling the first iteration will break dependence.
+ bool PeelLast : 1; // Peeling the last iteration will break the dependence.
+ bool Splitable : 1; // Splitting the loop will break dependence.
+ const SCEV *Distance; // NULL implies no distance available.
+ DVEntry() : Direction(ALL), Scalar(true), PeelFirst(false),
+ PeelLast(false), Splitable(false), Distance(NULL) { }
+ };
+
+ /// getSrc - Returns the source instruction for this dependence.
+ ///
+ const Instruction *getSrc() const { return Src; }
+
+ /// getDst - Returns the destination instruction for this dependence.
+ ///
+ const Instruction *getDst() const { return Dst; }
+
+ /// isInput - Returns true if this is an input dependence.
+ ///
+ bool isInput() const;
+
+ /// isOutput - Returns true if this is an output dependence.
+ ///
+ bool isOutput() const;
+
+ /// isFlow - Returns true if this is a flow (aka true) dependence.
+ ///
+ bool isFlow() const;
+
+ /// isAnti - Returns true if this is an anti dependence.
+ ///
+ bool isAnti() const;
+
+ /// isOrdered - Returns true if dependence is Output, Flow, or Anti
+ ///
+ bool isOrdered() const { return isOutput() || isFlow() || isAnti(); }
+
+ /// isUnordered - Returns true if dependence is Input
+ ///
+ bool isUnordered() const { return isInput(); }
+
+ /// isLoopIndependent - Returns true if this is a loop-independent
+ /// dependence.
+ virtual bool isLoopIndependent() const { return true; }
+
+ /// isConfused - Returns true if this dependence is confused
+ /// (the compiler understands nothing and makes worst-case
+ /// assumptions).
+ virtual bool isConfused() const { return true; }
+
+ /// isConsistent - Returns true if this dependence is consistent
+ /// (occurs every time the source and destination are executed).
+ virtual bool isConsistent() const { return false; }
+
+ /// getLevels - Returns the number of common loops surrounding the
+ /// souce and destination of the dependence.
+ virtual unsigned getLevels() const { return 0; }
+
+ /// getDirection - Returns the direction associated with a particular
+ /// level.
+ virtual unsigned getDirection(unsigned Level) const { return DVEntry::ALL; }
+
+ /// getDistance - Returns the distance (or NULL) associated with a
+ /// particular level.
+ virtual const SCEV *getDistance(unsigned Level) const { return NULL; }
+
+ /// isPeelFirst - Returns true if peeling the first iteration from
+ /// this loop will break this dependence.
+ virtual bool isPeelFirst(unsigned Level) const { return false; }
+
+ /// isPeelLast - Returns true if peeling the last iteration from
+ /// this loop will break this dependence.
+ virtual bool isPeelLast(unsigned Level) const { return false; }
+
+ /// isSplitable - Returns true if splitting this loop will break
+ /// the dependence.
+ virtual bool isSplitable(unsigned Level) const { return false; }
+
+ /// isScalar - Returns true if a particular level is scalar; that is,
+ /// if no subscript in the source or destination mention the induction
+ /// variable associated with the loop at this level.
+ virtual bool isScalar(unsigned Level) const;
+
+ /// dump - For debugging purposes, dumps a dependence to OS.
+ ///
+ void dump(raw_ostream &OS) const;
+ private:
+ const Instruction *Src, *Dst;
+ friend class DependenceAnalysis;
+ };
+
+
+ /// FullDependence - This class represents a dependence between two memory
+ /// references in a function. It contains detailed information about the
+ /// dependence (direction vectors, etc) and is used when the compiler is
+ /// able to accurately analyze the interaction of the references; that is,
+ /// it is not a confused dependence (see Dependence). In most cases
+ /// (for output, flow, and anti dependences), the dependence implies an
+ /// ordering, where the source must preceed the destination; in contrast,
+ /// input dependences are unordered.
+ class FullDependence : public Dependence {
+ public:
+ FullDependence(const Instruction *Src,
+ const Instruction *Dst,
+ bool LoopIndependent,
+ unsigned Levels);
+ ~FullDependence() {
+ delete DV;
+ }
+
+ /// isLoopIndependent - Returns true if this is a loop-independent
+ /// dependence.
+ bool isLoopIndependent() const { return LoopIndependent; }
+
+ /// isConfused - Returns true if this dependence is confused
+ /// (the compiler understands nothing and makes worst-case
+ /// assumptions).
+ bool isConfused() const { return false; }
+
+ /// isConsistent - Returns true if this dependence is consistent
+ /// (occurs every time the source and destination are executed).
+ bool isConsistent() const { return Consistent; }
+
+ /// getLevels - Returns the number of common loops surrounding the
+ /// souce and destination of the dependence.
+ unsigned getLevels() const { return Levels; }
+
+ /// getDirection - Returns the direction associated with a particular
+ /// level.
+ unsigned getDirection(unsigned Level) const;
+
+ /// getDistance - Returns the distance (or NULL) associated with a
+ /// particular level.
+ const SCEV *getDistance(unsigned Level) const;
+
+ /// isPeelFirst - Returns true if peeling the first iteration from
+ /// this loop will break this dependence.
+ bool isPeelFirst(unsigned Level) const;
+
+ /// isPeelLast - Returns true if peeling the last iteration from
+ /// this loop will break this dependence.
+ bool isPeelLast(unsigned Level) const;
+
+ /// isSplitable - Returns true if splitting the loop will break
+ /// the dependence.
+ bool isSplitable(unsigned Level) const;
+
+ /// isScalar - Returns true if a particular level is scalar; that is,
+ /// if no subscript in the source or destination mention the induction
+ /// variable associated with the loop at this level.
+ bool isScalar(unsigned Level) const;
+ private:
+ unsigned short Levels;
+ bool LoopIndependent;
+ bool Consistent; // Init to true, then refine.
+ DVEntry *DV;
+ friend class DependenceAnalysis;
+ };
+
+
+ /// DependenceAnalysis - This class is the main dependence-analysis driver.
+ ///
+ class DependenceAnalysis : public FunctionPass {
+ void operator=(const DependenceAnalysis &); // do not implement
+ DependenceAnalysis(const DependenceAnalysis &); // do not implement
+ public:
+ /// depends - Tests for a dependence between the Src and Dst instructions.
+ /// Returns NULL if no dependence; otherwise, returns a Dependence (or a
+ /// FullDependence) with as much information as can be gleaned.
+ /// The flag PossiblyLoopIndependent should be set by the caller
+ /// if it appears that control flow can reach from Src to Dst
+ /// without traversing a loop back edge.
+ Dependence *depends(const Instruction *Src,
+ const Instruction *Dst,
+ bool PossiblyLoopIndependent);
+
+ /// getSplitIteration - Give a dependence that's splitable at some
+ /// particular level, return the iteration that should be used to split
+ /// the loop.
+ ///
+ /// Generally, the dependence analyzer will be used to build
+ /// a dependence graph for a function (basically a map from instructions
+ /// to dependences). Looking for cycles in the graph shows us loops
+ /// that cannot be trivially vectorized/parallelized.
+ ///
+ /// We can try to improve the situation by examining all the dependences
+ /// that make up the cycle, looking for ones we can break.
+ /// Sometimes, peeling the first or last iteration of a loop will break
+ /// dependences, and there are flags for those possibilities.
+ /// Sometimes, splitting a loop at some other iteration will do the trick,
+ /// and we've got a flag for that case. Rather than waste the space to
+ /// record the exact iteration (since we rarely know), we provide
+ /// a method that calculates the iteration. It's a drag that it must work
+ /// from scratch, but wonderful in that it's possible.
+ ///
+ /// Here's an example:
+ ///
+ /// for (i = 0; i < 10; i++)
+ /// A[i] = ...
+ /// ... = A[11 - i]
+ ///
+ /// There's a loop-carried flow dependence from the store to the load,
+ /// found by the weak-crossing SIV test. The dependence will have a flag,
+ /// indicating that the dependence can be broken by splitting the loop.
+ /// Calling getSplitIteration will return 5.
+ /// Splitting the loop breaks the dependence, like so:
+ ///
+ /// for (i = 0; i <= 5; i++)
+ /// A[i] = ...
+ /// ... = A[11 - i]
+ /// for (i = 6; i < 10; i++)
+ /// A[i] = ...
+ /// ... = A[11 - i]
+ ///
+ /// breaks the dependence and allows us to vectorize/parallelize
+ /// both loops.
+ const SCEV *getSplitIteration(const Dependence *Dep, unsigned Level);
+
+ private:
+ AliasAnalysis *AA;
+ ScalarEvolution *SE;
+ LoopInfo *LI;
+ Function *F;
+
+ /// Subscript - This private struct represents a pair of subscripts from
+ /// a pair of potentially multi-dimensional array references. We use a
+ /// vector of them to guide subscript partitioning.
+ struct Subscript {
+ const SCEV *Src;
+ const SCEV *Dst;
+ enum ClassificationKind { ZIV, SIV, RDIV, MIV, NonLinear } Classification;
+ SmallBitVector Loops;
+ SmallBitVector GroupLoops;
+ SmallBitVector Group;
+ };
+
+ struct CoefficientInfo {
+ const SCEV *Coeff;
+ const SCEV *PosPart;
+ const SCEV *NegPart;
+ const SCEV *Iterations;
+ };
+
+ struct BoundInfo {
+ const SCEV *Iterations;
+ const SCEV *Upper[8];
+ const SCEV *Lower[8];
+ unsigned char Direction;
+ unsigned char DirSet;
+ };
+
+ /// Constraint - This private class represents a constraint, as defined
+ /// in the paper
+ ///
+ /// Practical Dependence Testing
+ /// Goff, Kennedy, Tseng
+ /// PLDI 1991
+ ///
+ /// There are 5 kinds of constraint, in a hierarchy.
+ /// 1) Any - indicates no constraint, any dependence is possible.
+ /// 2) Line - A line ax + by = c, where a, b, and c are parameters,
+ /// representing the dependence equation.
+ /// 3) Distance - The value d of the dependence distance;
+ /// 4) Point - A point <x, y> representing the dependence from
+ /// iteration x to iteration y.
+ /// 5) Empty - No dependence is possible.
+ class Constraint {
+ private:
+ enum ConstraintKind { Empty, Point, Distance, Line, Any } Kind;
+ ScalarEvolution *SE;
+ const SCEV *A;
+ const SCEV *B;
+ const SCEV *C;
+ const Loop *AssociatedLoop;
+ public:
+ /// isEmpty - Return true if the constraint is of kind Empty.
+ bool isEmpty() const { return Kind == Empty; }
+
+ /// isPoint - Return true if the constraint is of kind Point.
+ bool isPoint() const { return Kind == Point; }
+
+ /// isDistance - Return true if the constraint is of kind Distance.
+ bool isDistance() const { return Kind == Distance; }
+
+ /// isLine - Return true if the constraint is of kind Line.
+ /// Since Distance's can also be represented as Lines, we also return
+ /// true if the constraint is of kind Distance.
+ bool isLine() const { return Kind == Line || Kind == Distance; }
+
+ /// isAny - Return true if the constraint is of kind Any;
+ bool isAny() const { return Kind == Any; }
+
+ /// getX - If constraint is a point <X, Y>, returns X.
+ /// Otherwise assert.
+ const SCEV *getX() const;
+
+ /// getY - If constraint is a point <X, Y>, returns Y.
+ /// Otherwise assert.
+ const SCEV *getY() const;
+
+ /// getA - If constraint is a line AX + BY = C, returns A.
+ /// Otherwise assert.
+ const SCEV *getA() const;
+
+ /// getB - If constraint is a line AX + BY = C, returns B.
+ /// Otherwise assert.
+ const SCEV *getB() const;
+
+ /// getC - If constraint is a line AX + BY = C, returns C.
+ /// Otherwise assert.
+ const SCEV *getC() const;
+
+ /// getD - If constraint is a distance, returns D.
+ /// Otherwise assert.
+ const SCEV *getD() const;
+
+ /// getAssociatedLoop - Returns the loop associated with this constraint.
+ const Loop *getAssociatedLoop() const;
+
+ /// setPoint - Change a constraint to Point.
+ void setPoint(const SCEV *X, const SCEV *Y, const Loop *CurrentLoop);
+
+ /// setLine - Change a constraint to Line.
+ void setLine(const SCEV *A, const SCEV *B,
+ const SCEV *C, const Loop *CurrentLoop);
+
+ /// setDistance - Change a constraint to Distance.
+ void setDistance(const SCEV *D, const Loop *CurrentLoop);
+
+ /// setEmpty - Change a constraint to Empty.
+ void setEmpty();
+
+ /// setAny - Change a constraint to Any.
+ void setAny(ScalarEvolution *SE);
+
+ /// dump - For debugging purposes. Dumps the constraint
+ /// out to OS.
+ void dump(raw_ostream &OS) const;
+ };
+
+
+ /// establishNestingLevels - Examines the loop nesting of the Src and Dst
+ /// instructions and establishes their shared loops. Sets the variables
+ /// CommonLevels, SrcLevels, and MaxLevels.
+ /// The source and destination instructions needn't be contained in the same
+ /// loop. The routine establishNestingLevels finds the level of most deeply
+ /// nested loop that contains them both, CommonLevels. An instruction that's
+ /// not contained in a loop is at level = 0. MaxLevels is equal to the level
+ /// of the source plus the level of the destination, minus CommonLevels.
+ /// This lets us allocate vectors MaxLevels in length, with room for every
+ /// distinct loop referenced in both the source and destination subscripts.
+ /// The variable SrcLevels is the nesting depth of the source instruction.
+ /// It's used to help calculate distinct loops referenced by the destination.
+ /// Here's the map from loops to levels:
+ /// 0 - unused
+ /// 1 - outermost common loop
+ /// ... - other common loops
+ /// CommonLevels - innermost common loop
+ /// ... - loops containing Src but not Dst
+ /// SrcLevels - innermost loop containing Src but not Dst
+ /// ... - loops containing Dst but not Src
+ /// MaxLevels - innermost loop containing Dst but not Src
+ /// Consider the follow code fragment:
+ /// for (a = ...) {
+ /// for (b = ...) {
+ /// for (c = ...) {
+ /// for (d = ...) {
+ /// A[] = ...;
+ /// }
+ /// }
+ /// for (e = ...) {
+ /// for (f = ...) {
+ /// for (g = ...) {
+ /// ... = A[];
+ /// }
+ /// }
+ /// }
+ /// }
+ /// }
+ /// If we're looking at the possibility of a dependence between the store
+ /// to A (the Src) and the load from A (the Dst), we'll note that they
+ /// have 2 loops in common, so CommonLevels will equal 2 and the direction
+ /// vector for Result will have 2 entries. SrcLevels = 4 and MaxLevels = 7.
+ /// A map from loop names to level indices would look like
+ /// a - 1
+ /// b - 2 = CommonLevels
+ /// c - 3
+ /// d - 4 = SrcLevels
+ /// e - 5
+ /// f - 6
+ /// g - 7 = MaxLevels
+ void establishNestingLevels(const Instruction *Src,
+ const Instruction *Dst);
+
+ unsigned CommonLevels, SrcLevels, MaxLevels;
+
+ /// mapSrcLoop - Given one of the loops containing the source, return
+ /// its level index in our numbering scheme.
+ unsigned mapSrcLoop(const Loop *SrcLoop) const;
+
+ /// mapDstLoop - Given one of the loops containing the destination,
+ /// return its level index in our numbering scheme.
+ unsigned mapDstLoop(const Loop *DstLoop) const;
+
+ /// isLoopInvariant - Returns true if Expression is loop invariant
+ /// in LoopNest.
+ bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const;
+
+ /// removeMatchingExtensions - Examines a subscript pair.
+ /// If the source and destination are identically sign (or zero)
+ /// extended, it strips off the extension in an effort to
+ /// simplify the actual analysis.
+ void removeMatchingExtensions(Subscript *Pair);
+
+ /// collectCommonLoops - Finds the set of loops from the LoopNest that
+ /// have a level <= CommonLevels and are referred to by the SCEV Expression.
+ void collectCommonLoops(const SCEV *Expression,
+ const Loop *LoopNest,
+ SmallBitVector &Loops) const;
+
+ /// checkSrcSubscript - Examines the SCEV Src, returning true iff it's
+ /// linear. Collect the set of loops mentioned by Src.
+ bool checkSrcSubscript(const SCEV *Src,
+ const Loop *LoopNest,
+ SmallBitVector &Loops);
+
+ /// checkDstSubscript - Examines the SCEV Dst, returning true iff it's
+ /// linear. Collect the set of loops mentioned by Dst.
+ bool checkDstSubscript(const SCEV *Dst,
+ const Loop *LoopNest,
+ SmallBitVector &Loops);
+
+ /// isKnownPredicate - Compare X and Y using the predicate Pred.
+ /// Basically a wrapper for SCEV::isKnownPredicate,
+ /// but tries harder, especially in the presense of sign and zero
+ /// extensions and symbolics.
+ bool isKnownPredicate(ICmpInst::Predicate Pred,
+ const SCEV *X,
+ const SCEV *Y) const;
+
+ /// collectUpperBound - All subscripts are the same type (on my machine,
+ /// an i64). The loop bound may be a smaller type. collectUpperBound
+ /// find the bound, if available, and zero extends it to the Type T.
+ /// (I zero extend since the bound should always be >= 0.)
+ /// If no upper bound is available, return NULL.
+ const SCEV *collectUpperBound(const Loop *l, Type *T) const;
+
+ /// collectConstantUpperBound - Calls collectUpperBound(), then
+ /// attempts to cast it to SCEVConstant. If the cast fails,
+ /// returns NULL.
+ const SCEVConstant *collectConstantUpperBound(const Loop *l, Type *T) const;
+
+ /// classifyPair - Examines the subscript pair (the Src and Dst SCEVs)
+ /// and classifies it as either ZIV, SIV, RDIV, MIV, or Nonlinear.
+ /// Collects the associated loops in a set.
+ Subscript::ClassificationKind classifyPair(const SCEV *Src,
+ const Loop *SrcLoopNest,
+ const SCEV *Dst,
+ const Loop *DstLoopNest,
+ SmallBitVector &Loops);
+
+ /// testZIV - Tests the ZIV subscript pair (Src and Dst) for dependence.
+ /// Returns true if any possible dependence is disproved.
+ /// If there might be a dependence, returns false.
+ /// If the dependence isn't proven to exist,
+ /// marks the Result as inconsistent.
+ bool testZIV(const SCEV *Src,
+ const SCEV *Dst,
+ FullDependence &Result) const;
+
+ /// testSIV - Tests the SIV subscript pair (Src and Dst) for dependence.
+ /// Things of the form [c1 + a1*i] and [c2 + a2*j], where
+ /// i and j are induction variables, c1 and c2 are loop invariant,
+ /// and a1 and a2 are constant.
+ /// Returns true if any possible dependence is disproved.
+ /// If there might be a dependence, returns false.
+ /// Sets appropriate direction vector entry and, when possible,
+ /// the distance vector entry.
+ /// If the dependence isn't proven to exist,
+ /// marks the Result as inconsistent.
+ bool testSIV(const SCEV *Src,
+ const SCEV *Dst,
+ unsigned &Level,
+ FullDependence &Result,
+ Constraint &NewConstraint,
+ const SCEV *&SplitIter) const;
+
+ /// testRDIV - Tests the RDIV subscript pair (Src and Dst) for dependence.
+ /// Things of the form [c1 + a1*i] and [c2 + a2*j]
+ /// where i and j are induction variables, c1 and c2 are loop invariant,
+ /// and a1 and a2 are constant.
+ /// With minor algebra, this test can also be used for things like
+ /// [c1 + a1*i + a2*j][c2].
+ /// Returns true if any possible dependence is disproved.
+ /// If there might be a dependence, returns false.
+ /// Marks the Result as inconsistent.
+ bool testRDIV(const SCEV *Src,
+ const SCEV *Dst,
+ FullDependence &Result) const;
+
+ /// testMIV - Tests the MIV subscript pair (Src and Dst) for dependence.
+ /// Returns true if dependence disproved.
+ /// Can sometimes refine direction vectors.
+ bool testMIV(const SCEV *Src,
+ const SCEV *Dst,
+ const SmallBitVector &Loops,
+ FullDependence &Result) const;
+
+ /// strongSIVtest - Tests the strong SIV subscript pair (Src and Dst)
+ /// for dependence.
+ /// Things of the form [c1 + a*i] and [c2 + a*i],
+ /// where i is an induction variable, c1 and c2 are loop invariant,
+ /// and a is a constant
+ /// Returns true if any possible dependence is disproved.
+ /// If there might be a dependence, returns false.
+ /// Sets appropriate direction and distance.
+ bool strongSIVtest(const SCEV *Coeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurrentLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint) const;
+
+ /// weakCrossingSIVtest - Tests the weak-crossing SIV subscript pair
+ /// (Src and Dst) for dependence.
+ /// Things of the form [c1 + a*i] and [c2 - a*i],
+ /// where i is an induction variable, c1 and c2 are loop invariant,
+ /// and a is a constant.
+ /// Returns true if any possible dependence is disproved.
+ /// If there might be a dependence, returns false.
+ /// Sets appropriate direction entry.
+ /// Set consistent to false.
+ /// Marks the dependence as splitable.
+ bool weakCrossingSIVtest(const SCEV *SrcCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurrentLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint,
+ const SCEV *&SplitIter) const;
+
+ /// ExactSIVtest - Tests the SIV subscript pair
+ /// (Src and Dst) for dependence.
+ /// Things of the form [c1 + a1*i] and [c2 + a2*i],
+ /// where i is an induction variable, c1 and c2 are loop invariant,
+ /// and a1 and a2 are constant.
+ /// Returns true if any possible dependence is disproved.
+ /// If there might be a dependence, returns false.
+ /// Sets appropriate direction entry.
+ /// Set consistent to false.
+ bool exactSIVtest(const SCEV *SrcCoeff,
+ const SCEV *DstCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurrentLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint) const;
+
+ /// weakZeroSrcSIVtest - Tests the weak-zero SIV subscript pair
+ /// (Src and Dst) for dependence.
+ /// Things of the form [c1] and [c2 + a*i],
+ /// where i is an induction variable, c1 and c2 are loop invariant,
+ /// and a is a constant. See also weakZeroDstSIVtest.
+ /// Returns true if any possible dependence is disproved.
+ /// If there might be a dependence, returns false.
+ /// Sets appropriate direction entry.
+ /// Set consistent to false.
+ /// If loop peeling will break the dependence, mark appropriately.
+ bool weakZeroSrcSIVtest(const SCEV *DstCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurrentLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint) const;
+
+ /// weakZeroDstSIVtest - Tests the weak-zero SIV subscript pair
+ /// (Src and Dst) for dependence.
+ /// Things of the form [c1 + a*i] and [c2],
+ /// where i is an induction variable, c1 and c2 are loop invariant,
+ /// and a is a constant. See also weakZeroSrcSIVtest.
+ /// Returns true if any possible dependence is disproved.
+ /// If there might be a dependence, returns false.
+ /// Sets appropriate direction entry.
+ /// Set consistent to false.
+ /// If loop peeling will break the dependence, mark appropriately.
+ bool weakZeroDstSIVtest(const SCEV *SrcCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurrentLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint) const;
+
+ /// exactRDIVtest - Tests the RDIV subscript pair for dependence.
+ /// Things of the form [c1 + a*i] and [c2 + b*j],
+ /// where i and j are induction variable, c1 and c2 are loop invariant,
+ /// and a and b are constants.
+ /// Returns true if any possible dependence is disproved.
+ /// Marks the result as inconsistant.
+ /// Works in some cases that symbolicRDIVtest doesn't,
+ /// and vice versa.
+ bool exactRDIVtest(const SCEV *SrcCoeff,
+ const SCEV *DstCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *SrcLoop,
+ const Loop *DstLoop,
+ FullDependence &Result) const;
+
+ /// symbolicRDIVtest - Tests the RDIV subscript pair for dependence.
+ /// Things of the form [c1 + a*i] and [c2 + b*j],
+ /// where i and j are induction variable, c1 and c2 are loop invariant,
+ /// and a and b are constants.
+ /// Returns true if any possible dependence is disproved.
+ /// Marks the result as inconsistant.
+ /// Works in some cases that exactRDIVtest doesn't,
+ /// and vice versa. Can also be used as a backup for
+ /// ordinary SIV tests.
+ bool symbolicRDIVtest(const SCEV *SrcCoeff,
+ const SCEV *DstCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *SrcLoop,
+ const Loop *DstLoop) const;
+
+ /// gcdMIVtest - Tests an MIV subscript pair for dependence.
+ /// Returns true if any possible dependence is disproved.
+ /// Marks the result as inconsistant.
+ /// Can sometimes disprove the equal direction for 1 or more loops.
+ // Can handle some symbolics that even the SIV tests don't get,
+ /// so we use it as a backup for everything.
+ bool gcdMIVtest(const SCEV *Src,
+ const SCEV *Dst,
+ FullDependence &Result) const;
+
+ /// banerjeeMIVtest - Tests an MIV subscript pair for dependence.
+ /// Returns true if any possible dependence is disproved.
+ /// Marks the result as inconsistant.
+ /// Computes directions.
+ bool banerjeeMIVtest(const SCEV *Src,
+ const SCEV *Dst,
+ const SmallBitVector &Loops,
+ FullDependence &Result) const;
+
+ /// collectCoefficientInfo - Walks through the subscript,
+ /// collecting each coefficient, the associated loop bounds,
+ /// and recording its positive and negative parts for later use.
+ CoefficientInfo *collectCoeffInfo(const SCEV *Subscript,
+ bool SrcFlag,
+ const SCEV *&Constant) const;
+
+ /// getPositivePart - X^+ = max(X, 0).
+ ///
+ const SCEV *getPositivePart(const SCEV *X) const;
+
+ /// getNegativePart - X^- = min(X, 0).
+ ///
+ const SCEV *getNegativePart(const SCEV *X) const;
+
+ /// getLowerBound - Looks through all the bounds info and
+ /// computes the lower bound given the current direction settings
+ /// at each level.
+ const SCEV *getLowerBound(BoundInfo *Bound) const;
+
+ /// getUpperBound - Looks through all the bounds info and
+ /// computes the upper bound given the current direction settings
+ /// at each level.
+ const SCEV *getUpperBound(BoundInfo *Bound) const;
+
+ /// exploreDirections - Hierarchically expands the direction vector
+ /// search space, combining the directions of discovered dependences
+ /// in the DirSet field of Bound. Returns the number of distinct
+ /// dependences discovered. If the dependence is disproved,
+ /// it will return 0.
+ unsigned exploreDirections(unsigned Level,
+ CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ const SmallBitVector &Loops,
+ unsigned &DepthExpanded,
+ const SCEV *Delta) const;
+
+ /// testBounds - Returns true iff the current bounds are plausible.
+ ///
+ bool testBounds(unsigned char DirKind,
+ unsigned Level,
+ BoundInfo *Bound,
+ const SCEV *Delta) const;
+
+ /// findBoundsALL - Computes the upper and lower bounds for level K
+ /// using the * direction. Records them in Bound.
+ void findBoundsALL(CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ unsigned K) const;
+
+ /// findBoundsLT - Computes the upper and lower bounds for level K
+ /// using the < direction. Records them in Bound.
+ void findBoundsLT(CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ unsigned K) const;
+
+ /// findBoundsGT - Computes the upper and lower bounds for level K
+ /// using the > direction. Records them in Bound.
+ void findBoundsGT(CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ unsigned K) const;
+
+ /// findBoundsEQ - Computes the upper and lower bounds for level K
+ /// using the = direction. Records them in Bound.
+ void findBoundsEQ(CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ unsigned K) const;
+
+ /// intersectConstraints - Updates X with the intersection
+ /// of the Constraints X and Y. Returns true if X has changed.
+ bool intersectConstraints(Constraint *X,
+ const Constraint *Y);
+
+ /// propagate - Review the constraints, looking for opportunities
+ /// to simplify a subscript pair (Src and Dst).
+ /// Return true if some simplification occurs.
+ /// If the simplification isn't exact (that is, if it is conservative
+ /// in terms of dependence), set consistent to false.
+ bool propagate(const SCEV *&Src,
+ const SCEV *&Dst,
+ SmallBitVector &Loops,
+ SmallVector<Constraint, 4> &Constraints,
+ bool &Consistent);
+
+ /// propagateDistance - Attempt to propagate a distance
+ /// constraint into a subscript pair (Src and Dst).
+ /// Return true if some simplification occurs.
+ /// If the simplification isn't exact (that is, if it is conservative
+ /// in terms of dependence), set consistent to false.
+ bool propagateDistance(const SCEV *&Src,
+ const SCEV *&Dst,
+ Constraint &CurConstraint,
+ bool &Consistent);
+
+ /// propagatePoint - Attempt to propagate a point
+ /// constraint into a subscript pair (Src and Dst).
+ /// Return true if some simplification occurs.
+ bool propagatePoint(const SCEV *&Src,
+ const SCEV *&Dst,
+ Constraint &CurConstraint);
+
+ /// propagateLine - Attempt to propagate a line
+ /// constraint into a subscript pair (Src and Dst).
+ /// Return true if some simplification occurs.
+ /// If the simplification isn't exact (that is, if it is conservative
+ /// in terms of dependence), set consistent to false.
+ bool propagateLine(const SCEV *&Src,
+ const SCEV *&Dst,
+ Constraint &CurConstraint,
+ bool &Consistent);
+
+ /// findCoefficient - Given a linear SCEV,
+ /// return the coefficient corresponding to specified loop.
+ /// If there isn't one, return the SCEV constant 0.
+ /// For example, given a*i + b*j + c*k, returning the coefficient
+ /// corresponding to the j loop would yield b.
+ const SCEV *findCoefficient(const SCEV *Expr,
+ const Loop *TargetLoop) const;
+
+ /// zeroCoefficient - Given a linear SCEV,
+ /// return the SCEV given by zeroing out the coefficient
+ /// corresponding to the specified loop.
+ /// For example, given a*i + b*j + c*k, zeroing the coefficient
+ /// corresponding to the j loop would yield a*i + c*k.
+ const SCEV *zeroCoefficient(const SCEV *Expr,
+ const Loop *TargetLoop) const;
+
+ /// addToCoefficient - Given a linear SCEV Expr,
+ /// return the SCEV given by adding some Value to the
+ /// coefficient corresponding to the specified TargetLoop.
+ /// For example, given a*i + b*j + c*k, adding 1 to the coefficient
+ /// corresponding to the j loop would yield a*i + (b+1)*j + c*k.
+ const SCEV *addToCoefficient(const SCEV *Expr,
+ const Loop *TargetLoop,
+ const SCEV *Value) const;
+
+ /// updateDirection - Update direction vector entry
+ /// based on the current constraint.
+ void updateDirection(Dependence::DVEntry &Level,
+ const Constraint &CurConstraint) const;
+ public:
+ static char ID; // Class identification, replacement for typeinfo
+ DependenceAnalysis() : FunctionPass(ID) {
+ initializeDependenceAnalysisPass(*PassRegistry::getPassRegistry());
+ }
+
+ bool runOnFunction(Function &F);
+ void releaseMemory();
+ void getAnalysisUsage(AnalysisUsage &) const;
+ void print(raw_ostream &, const Module * = 0) const;
+ }; // class DependenceAnalysis
+
+ /// createDependenceAnalysisPass - This creates an instance of the
+ /// DependenceAnalysis pass.
+ FunctionPass *createDependenceAnalysisPass();
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h
index c52f846b5ca..c127830e0e5 100644
--- a/include/llvm/Analysis/Passes.h
+++ b/include/llvm/Analysis/Passes.h
@@ -180,11 +180,20 @@ namespace llvm {
//===--------------------------------------------------------------------===//
//
+ // createDependenceAnalysisPass - This creates an instance of the
+ // DependenceAnalysis pass.
+ //
+ FunctionPass *createDependenceAnalysisPass();
+
+ //===--------------------------------------------------------------------===//
+ //
// createLoopDependenceAnalysisPass - This creates an instance of the
// LoopDependenceAnalysis pass.
//
LoopPass *createLoopDependenceAnalysisPass();
+ //===--------------------------------------------------------------------===//
+ //
// Minor pass prototypes, allowing us to expose them through bugpoint and
// analyze.
FunctionPass *createInstCountPass();
diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h
index a055195352a..67c9a4d14fe 100644
--- a/include/llvm/Analysis/ScalarEvolution.h
+++ b/include/llvm/Analysis/ScalarEvolution.h
@@ -162,7 +162,6 @@ namespace llvm {
SCEVCouldNotCompute();
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVCouldNotCompute *S) { return true; }
static bool classof(const SCEV *S);
};
diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h
index 3f8f149cb42..3ab9c8256bb 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpander.h
+++ b/include/llvm/Analysis/ScalarEvolutionExpander.h
@@ -22,7 +22,7 @@
#include <set>
namespace llvm {
- class TargetLowering;
+ class ScalarTargetTransformInfo;
/// Return true if the given expression is safe to expand in the sense that
/// all materialized values are safe to speculate.
@@ -129,7 +129,7 @@ namespace llvm {
/// representative. Return the number of phis eliminated.
unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT,
SmallVectorImpl<WeakVH> &DeadInsts,
- const TargetLowering *TLI = NULL);
+ const ScalarTargetTransformInfo *STTI = NULL);
/// expandCodeFor - Insert code to directly compute the specified SCEV
/// expression into the program. The inserted code is inserted into the
diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h
index ded12974fac..54db7d6bcf0 100644
--- a/include/llvm/Analysis/ScalarEvolutionExpressions.h
+++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h
@@ -46,7 +46,6 @@ namespace llvm {
Type *getType() const { return V->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVConstant *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scConstant;
}
@@ -68,7 +67,6 @@ namespace llvm {
Type *getType() const { return Ty; }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVCastExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scTruncate ||
S->getSCEVType() == scZeroExtend ||
@@ -88,7 +86,6 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVTruncateExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scTruncate;
}
@@ -106,7 +103,6 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVZeroExtendExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scZeroExtend;
}
@@ -124,7 +120,6 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVSignExtendExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scSignExtend;
}
@@ -166,7 +161,6 @@ namespace llvm {
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVNAryExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scAddExpr ||
S->getSCEVType() == scMulExpr ||
@@ -188,7 +182,6 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVCommutativeExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scAddExpr ||
S->getSCEVType() == scMulExpr ||
@@ -223,7 +216,6 @@ namespace llvm {
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVAddExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scAddExpr;
}
@@ -242,7 +234,6 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVMulExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scMulExpr;
}
@@ -274,7 +265,6 @@ namespace llvm {
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVUDivExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scUDivExpr;
}
@@ -358,7 +348,6 @@ namespace llvm {
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVAddRecExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scAddRecExpr;
}
@@ -380,7 +369,6 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVSMaxExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scSMaxExpr;
}
@@ -402,7 +390,6 @@ namespace llvm {
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVUMaxExpr *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scUMaxExpr;
}
@@ -449,7 +436,6 @@ namespace llvm {
Type *getType() const { return getValPtr()->getType(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SCEVUnknown *S) { return true; }
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scUnknown;
}
diff --git a/include/llvm/Argument.h b/include/llvm/Argument.h
index 1155b974ecd..b1c22185191 100644
--- a/include/llvm/Argument.h
+++ b/include/llvm/Argument.h
@@ -81,7 +81,6 @@ public:
/// classof - Methods for support type inquiry through isa, cast, and
/// dyn_cast:
///
- static inline bool classof(const Argument *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == ArgumentVal;
}
diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h
index d20a47a286e..a28aa183473 100644
--- a/include/llvm/Attributes.h
+++ b/include/llvm/Attributes.h
@@ -15,7 +15,6 @@
#ifndef LLVM_ATTRIBUTES_H
#define LLVM_ATTRIBUTES_H
-#include "llvm/AttributesImpl.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/ADT/ArrayRef.h"
#include <cassert>
@@ -23,13 +22,11 @@
namespace llvm {
+class AttrBuilder;
+class AttributesImpl;
class LLVMContext;
class Type;
-/// AttributeImpl - The internal representation of the Attributes class. This is
-/// uniquified.
-class AttributesImpl;
-
/// Attributes - A bitset of attributes.
class Attributes {
public:
@@ -37,15 +34,15 @@ public:
/// should be treated by optimizations and code generation. This enumeration
/// lists the attributes that can be associated with parameters, function
/// results or the function itself.
- ///
+ ///
/// Note that uwtable is about the ABI or the user mandating an entry in the
/// unwind table. The nounwind attribute is about an exception passing by the
/// function.
- ///
+ ///
/// In a theoretical system that uses tables for profiling and sjlj for
/// exceptions, they would be fully independent. In a normal system that uses
/// tables for both, the semantics are:
- ///
+ ///
/// nil = Needs an entry because an exception might pass by.
/// nounwind = No need for an entry
/// uwtable = Needs an entry because the ABI says so and because
@@ -53,6 +50,7 @@ public:
/// uwtable + nounwind = Needs an entry because the ABI says so.
enum AttrVal {
+ // IR-Level Attributes
None = 0, ///< No attributes have been set
AddressSafety = 1, ///< Address safety checking is on.
Alignment = 2, ///< Alignment of parameter (5 bits)
@@ -89,74 +87,26 @@ public:
ZExt = 27 ///< Zero extended before/after call
};
private:
- AttributesImpl Attrs;
-
- explicit Attributes(AttributesImpl *A);
+ AttributesImpl *Attrs;
+ Attributes(AttributesImpl *A) : Attrs(A) {}
public:
Attributes() : Attrs(0) {}
- explicit Attributes(uint64_t Val);
- Attributes(const Attributes &A);
-
- class Builder {
- friend class Attributes;
- uint64_t Bits;
- public:
- Builder() : Bits(0) {}
- Builder(const Attributes &A) : Bits(A.Raw()) {}
-
- void clear() { Bits = 0; }
-
- bool hasAttribute(Attributes::AttrVal A) const;
- bool hasAttributes() const;
- bool hasAttributes(const Attributes &A) const;
- bool hasAlignmentAttr() const;
-
- uint64_t getAlignment() const;
- uint64_t getStackAlignment() const;
-
- Builder &addAttribute(Attributes::AttrVal Val);
- Builder &removeAttribute(Attributes::AttrVal Val);
-
- void addAlignmentAttr(unsigned Align);
- void addStackAlignmentAttr(unsigned Align);
-
- void removeAttributes(const Attributes &A);
-
- /// @brief Remove attributes that are used on functions only.
- void removeFunctionOnlyAttrs() {
- removeAttribute(Attributes::NoReturn)
- .removeAttribute(Attributes::NoUnwind)
- .removeAttribute(Attributes::ReadNone)
- .removeAttribute(Attributes::ReadOnly)
- .removeAttribute(Attributes::NoInline)
- .removeAttribute(Attributes::AlwaysInline)
- .removeAttribute(Attributes::OptimizeForSize)
- .removeAttribute(Attributes::StackProtect)
- .removeAttribute(Attributes::StackProtectReq)
- .removeAttribute(Attributes::NoRedZone)
- .removeAttribute(Attributes::NoImplicitFloat)
- .removeAttribute(Attributes::Naked)
- .removeAttribute(Attributes::InlineHint)
- .removeAttribute(Attributes::StackAlignment)
- .removeAttribute(Attributes::UWTable)
- .removeAttribute(Attributes::NonLazyBind)
- .removeAttribute(Attributes::ReturnsTwice)
- .removeAttribute(Attributes::AddressSafety);
- }
- };
+ Attributes(const Attributes &A) : Attrs(A.Attrs) {}
+ Attributes &operator=(const Attributes &A) {
+ Attrs = A.Attrs;
+ return *this;
+ }
/// get - Return a uniquified Attributes object. This takes the uniquified
/// value from the Builder and wraps it in the Attributes class.
- static Attributes get(Builder &B);
- static Attributes get(LLVMContext &Context, Builder &B);
+ static Attributes get(LLVMContext &Context, ArrayRef<AttrVal> Vals);
+ static Attributes get(LLVMContext &Context, AttrBuilder &B);
/// @brief Return true if the attribute is present.
bool hasAttribute(AttrVal Val) const;
/// @brief Return true if attributes exist
- bool hasAttributes() const {
- return Attrs.hasAttributes();
- }
+ bool hasAttributes() const;
/// @brief Return true if the attributes are a non-null intersection.
bool hasAttributes(const Attributes &A) const;
@@ -205,91 +155,29 @@ public:
hasAttribute(Attributes::AddressSafety);
}
- bool isEmptyOrSingleton() const;
-
- // This is a "safe bool() operator".
- operator const void *() const { return Attrs.Bits ? this : 0; }
- bool operator == (const Attributes &A) const {
- return Attrs.Bits == A.Attrs.Bits;
+ bool operator==(const Attributes &A) const {
+ return Attrs == A.Attrs;
}
- bool operator != (const Attributes &A) const {
- return Attrs.Bits != A.Attrs.Bits;
+ bool operator!=(const Attributes &A) const {
+ return Attrs != A.Attrs;
}
- Attributes operator | (const Attributes &A) const;
- Attributes operator & (const Attributes &A) const;
- Attributes operator ^ (const Attributes &A) const;
- Attributes &operator |= (const Attributes &A);
- Attributes &operator &= (const Attributes &A);
- Attributes operator ~ () const;
-
uint64_t Raw() const;
- /// constructAlignmentFromInt - This turns an int alignment (a power of 2,
- /// normally) into the form used internally in Attributes.
- static Attributes constructAlignmentFromInt(unsigned i) {
- // Default alignment, allow the target to define how to align it.
- if (i == 0)
- return Attributes();
-
- assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
- assert(i <= 0x40000000 && "Alignment too large.");
- return Attributes((Log2_32(i)+1) << 16);
- }
-
- /// constructStackAlignmentFromInt - This turns an int stack alignment (which
- /// must be a power of 2) into the form used internally in Attributes.
- static Attributes constructStackAlignmentFromInt(unsigned i) {
- // Default alignment, allow the target to define how to align it.
- if (i == 0)
- return Attributes();
-
- assert(isPowerOf2_32(i) && "Alignment must be a power of two.");
- assert(i <= 0x100 && "Alignment too large.");
- return Attributes((Log2_32(i)+1) << 26);
- }
-
/// @brief Which attributes cannot be applied to a type.
static Attributes typeIncompatible(Type *Ty);
/// encodeLLVMAttributesForBitcode - This returns an integer containing an
/// encoding of all the LLVM attributes found in the given attribute bitset.
/// Any change to this encoding is a breaking change to bitcode compatibility.
- static uint64_t encodeLLVMAttributesForBitcode(Attributes Attrs) {
- // FIXME: It doesn't make sense to store the alignment information as an
- // expanded out value, we should store it as a log2 value. However, we
- // can't just change that here without breaking bitcode compatibility. If
- // this ever becomes a problem in practice, we should introduce new tag
- // numbers in the bitcode file and have those tags use a more efficiently
- // encoded alignment field.
-
- // Store the alignment in the bitcode as a 16-bit raw value instead of a
- // 5-bit log2 encoded value. Shift the bits above the alignment up by 11
- // bits.
- uint64_t EncodedAttrs = Attrs.Raw() & 0xffff;
- if (Attrs.hasAttribute(Attributes::Alignment))
- EncodedAttrs |= Attrs.getAlignment() << 16;
- EncodedAttrs |= (Attrs.Raw() & (0xfffULL << 21)) << 11;
- return EncodedAttrs;
- }
+ static uint64_t encodeLLVMAttributesForBitcode(Attributes Attrs);
/// decodeLLVMAttributesForBitcode - This returns an attribute bitset
/// containing the LLVM attributes that have been decoded from the given
/// integer. This function must stay in sync with
/// 'encodeLLVMAttributesForBitcode'.
- static Attributes decodeLLVMAttributesForBitcode(uint64_t EncodedAttrs) {
- // The alignment is stored as a 16-bit raw value from bits 31--16. We shift
- // the bits above 31 down by 11 bits.
- unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16;
- assert((!Alignment || isPowerOf2_32(Alignment)) &&
- "Alignment must be a power of two.");
-
- Attributes Attrs(EncodedAttrs & 0xffff);
- if (Alignment)
- Attrs |= Attributes::constructAlignmentFromInt(Alignment);
- Attrs |= Attributes((EncodedAttrs & (0xfffULL << 32)) >> 11);
- return Attrs;
- }
+ static Attributes decodeLLVMAttributesForBitcode(LLVMContext &C,
+ uint64_t EncodedAttrs);
/// getAsString - The set of Attributes set in Attributes is converted to a
/// string of equivalent mnemonics. This is, presumably, for writing out the
@@ -299,6 +187,96 @@ public:
};
//===----------------------------------------------------------------------===//
+/// AttrBuilder - This class is used in conjunction with the Attributes::get
+/// method to create an Attributes object. The object itself is uniquified. The
+/// Builder's value, however, is not. So this can be used as a quick way to test
+/// for equality, presence of attributes, etc.
+class AttrBuilder {
+ uint64_t Bits;
+public:
+ AttrBuilder() : Bits(0) {}
+ explicit AttrBuilder(uint64_t B) : Bits(B) {}
+ AttrBuilder(const Attributes &A) : Bits(A.Raw()) {}
+ AttrBuilder(const AttrBuilder &B) : Bits(B.Bits) {}
+
+ void clear() { Bits = 0; }
+
+ /// addAttribute - Add an attribute to the builder.
+ AttrBuilder &addAttribute(Attributes::AttrVal Val);
+
+ /// removeAttribute - Remove an attribute from the builder.
+ AttrBuilder &removeAttribute(Attributes::AttrVal Val);
+
+ /// addAttribute - Add the attributes from A to the builder.
+ AttrBuilder &addAttributes(const Attributes &A);
+
+ /// removeAttribute - Remove the attributes from A from the builder.
+ AttrBuilder &removeAttributes(const Attributes &A);
+
+ /// hasAttribute - Return true if the builder has the specified attribute.
+ bool hasAttribute(Attributes::AttrVal A) const;
+
+ /// hasAttributes - Return true if the builder has IR-level attributes.
+ bool hasAttributes() const;
+
+ /// hasAttributes - Return true if the builder has any attribute that's in the
+ /// specified attribute.
+ bool hasAttributes(const Attributes &A) const;
+
+ /// hasAlignmentAttr - Return true if the builder has an alignment attribute.
+ bool hasAlignmentAttr() const;
+
+ /// getAlignment - Retrieve the alignment attribute, if it exists.
+ uint64_t getAlignment() const;
+
+ /// getStackAlignment - Retrieve the stack alignment attribute, if it exists.
+ uint64_t getStackAlignment() const;
+
+ /// addAlignmentAttr - This turns an int alignment (which must be a power of
+ /// 2) into the form used internally in Attributes.
+ AttrBuilder &addAlignmentAttr(unsigned Align);
+
+ /// addStackAlignmentAttr - This turns an int stack alignment (which must be a
+ /// power of 2) into the form used internally in Attributes.
+ AttrBuilder &addStackAlignmentAttr(unsigned Align);
+
+ /// addRawValue - Add the raw value to the internal representation.
+ /// N.B. This should be used ONLY for decoding LLVM bitcode!
+ AttrBuilder &addRawValue(uint64_t Val);
+
+ /// @brief Remove attributes that are used on functions only.
+ void removeFunctionOnlyAttrs() {
+ removeAttribute(Attributes::NoReturn)
+ .removeAttribute(Attributes::NoUnwind)
+ .removeAttribute(Attributes::ReadNone)
+ .removeAttribute(Attributes::ReadOnly)
+ .removeAttribute(Attributes::NoInline)
+ .removeAttribute(Attributes::AlwaysInline)
+ .removeAttribute(Attributes::OptimizeForSize)
+ .removeAttribute(Attributes::StackProtect)
+ .removeAttribute(Attributes::StackProtectReq)
+ .removeAttribute(Attributes::NoRedZone)
+ .removeAttribute(Attributes::NoImplicitFloat)
+ .removeAttribute(Attributes::Naked)
+ .removeAttribute(Attributes::InlineHint)
+ .removeAttribute(Attributes::StackAlignment)
+ .removeAttribute(Attributes::UWTable)
+ .removeAttribute(Attributes::NonLazyBind)
+ .removeAttribute(Attributes::ReturnsTwice)
+ .removeAttribute(Attributes::AddressSafety);
+ }
+
+ uint64_t Raw() const { return Bits; }
+
+ bool operator==(const AttrBuilder &B) {
+ return Bits == B.Bits;
+ }
+ bool operator!=(const AttrBuilder &B) {
+ return Bits != B.Bits;
+ }
+};
+
+//===----------------------------------------------------------------------===//
// AttributeWithIndex
//===----------------------------------------------------------------------===//
@@ -310,9 +288,9 @@ struct AttributeWithIndex {
///< Index 0 is used for return value attributes.
///< Index ~0U is used for function attributes.
- static AttributeWithIndex get(unsigned Idx,
+ static AttributeWithIndex get(LLVMContext &C, unsigned Idx,
ArrayRef<Attributes::AttrVal> Attrs) {
- Attributes::Builder B;
+ AttrBuilder B;
for (ArrayRef<Attributes::AttrVal>::iterator I = Attrs.begin(),
E = Attrs.end(); I != E; ++I)
@@ -320,7 +298,7 @@ struct AttributeWithIndex {
AttributeWithIndex P;
P.Index = Idx;
- P.Attrs = Attributes::get(B);
+ P.Attrs = Attributes::get(C, B);
return P;
}
static AttributeWithIndex get(unsigned Idx, Attributes Attrs) {
@@ -340,6 +318,12 @@ class AttributeListImpl;
/// AttrListPtr - This class manages the ref count for the opaque
/// AttributeListImpl object and provides accessors for it.
class AttrListPtr {
+public:
+ enum AttrIndex {
+ ReturnIndex = 0U,
+ FunctionIndex = ~0U
+ };
+private:
/// AttrList - The attributes that we are managing. This can be null
/// to represent the empty attributes list.
AttributeListImpl *AttrList;
@@ -359,12 +343,12 @@ public:
/// addAttr - Add the specified attribute at the specified index to this
/// attribute list. Since attribute lists are immutable, this
/// returns the new list.
- AttrListPtr addAttr(unsigned Idx, Attributes Attrs) const;
+ AttrListPtr addAttr(LLVMContext &C, unsigned Idx, Attributes Attrs) const;
/// removeAttr - Remove the specified attribute at the specified index from
/// this attribute list. Since attribute lists are immutable, this
/// returns the new list.
- AttrListPtr removeAttr(unsigned Idx, Attributes Attrs) const;
+ AttrListPtr removeAttr(LLVMContext &C, unsigned Idx, Attributes Attrs) const;
//===--------------------------------------------------------------------===//
// Attribute List Accessors
@@ -378,12 +362,12 @@ public:
/// getRetAttributes - The attributes for the ret value are
/// returned.
Attributes getRetAttributes() const {
- return getAttributes(0);
+ return getAttributes(ReturnIndex);
}
/// getFnAttributes - The function attributes are returned.
Attributes getFnAttributes() const {
- return getAttributes(~0U);
+ return getAttributes(FunctionIndex);
}
/// paramHasAttr - Return true if the specified parameter index has the
@@ -411,8 +395,6 @@ public:
bool operator!=(const AttrListPtr &RHS) const
{ return AttrList != RHS.AttrList; }
- void dump() const;
-
//===--------------------------------------------------------------------===//
// Attribute List Introspection
//===--------------------------------------------------------------------===//
@@ -442,6 +424,8 @@ public:
/// holds a index number plus a set of attributes.
const AttributeWithIndex &getSlot(unsigned Slot) const;
+ void dump() const;
+
private:
explicit AttrListPtr(AttributeListImpl *L);
diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h
index 9ab4a74e5a5..02c2a96b6c6 100644
--- a/include/llvm/BasicBlock.h
+++ b/include/llvm/BasicBlock.h
@@ -213,7 +213,6 @@ public:
ValueSymbolTable *getValueSymbolTable();
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const BasicBlock *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == Value::BasicBlockVal;
}
diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h
index 3daef789d61..840f57e7526 100644
--- a/include/llvm/Bitcode/BitstreamReader.h
+++ b/include/llvm/Bitcode/BitstreamReader.h
@@ -409,7 +409,7 @@ public:
}
/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
- /// the block, and return true if the block is valid.
+ /// the block, and return true if the block has an error.
bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0) {
// Save the current block's state on BlockScope.
BlockScope.push_back(Block(CurCodeSize));
diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h
new file mode 100644
index 00000000000..90ee2342449
--- /dev/null
+++ b/include/llvm/CodeGen/CommandFlags.h
@@ -0,0 +1,228 @@
+//===-- CommandFlags.h - Register Coalescing Interface ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains codegen-specific flags that are shared between different
+// command line tools. The tools "llc" and "opt" both use this file to prevent
+// flag duplication.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_COMMAND_LINE_FLAGS_H
+#define LLVM_CODEGEN_COMMAND_LINE_FLAGS_H
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Target/TargetMachine.h"
+
+#include <string>
+using namespace llvm;
+
+cl::opt<std::string>
+MArch("march", cl::desc("Architecture to generate code for (see --version)"));
+
+cl::opt<std::string>
+MCPU("mcpu",
+ cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+ cl::value_desc("cpu-name"),
+ cl::init(""));
+
+cl::list<std::string>
+MAttrs("mattr",
+ cl::CommaSeparated,
+ cl::desc("Target specific attributes (-mattr=help for details)"),
+ cl::value_desc("a1,+a2,-a3,..."));
+
+cl::opt<Reloc::Model>
+RelocModel("relocation-model",
+ cl::desc("Choose relocation model"),
+ cl::init(Reloc::Default),
+ cl::values(
+ clEnumValN(Reloc::Default, "default",
+ "Target default relocation model"),
+ clEnumValN(Reloc::Static, "static",
+ "Non-relocatable code"),
+ clEnumValN(Reloc::PIC_, "pic",
+ "Fully relocatable, position independent code"),
+ clEnumValN(Reloc::DynamicNoPIC, "dynamic-no-pic",
+ "Relocatable external references, non-relocatable code"),
+ clEnumValEnd));
+
+cl::opt<llvm::CodeModel::Model>
+CMModel("code-model",
+ cl::desc("Choose code model"),
+ cl::init(CodeModel::Default),
+ cl::values(clEnumValN(CodeModel::Default, "default",
+ "Target default code model"),
+ clEnumValN(CodeModel::Small, "small",
+ "Small code model"),
+ clEnumValN(CodeModel::Kernel, "kernel",
+ "Kernel code model"),
+ clEnumValN(CodeModel::Medium, "medium",
+ "Medium code model"),
+ clEnumValN(CodeModel::Large, "large",
+ "Large code model"),
+ clEnumValEnd));
+
+cl::opt<bool>
+RelaxAll("mc-relax-all",
+ cl::desc("When used with filetype=obj, "
+ "relax all fixups in the emitted object file"));
+
+cl::opt<TargetMachine::CodeGenFileType>
+FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile),
+ cl::desc("Choose a file type (not all types are supported by all targets):"),
+ cl::values(
+ clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm",
+ "Emit an assembly ('.s') file"),
+ clEnumValN(TargetMachine::CGFT_ObjectFile, "obj",
+ "Emit a native object ('.o') file"),
+ clEnumValN(TargetMachine::CGFT_Null, "null",
+ "Emit nothing, for performance testing"),
+ clEnumValEnd));
+
+cl::opt<bool> DisableDotLoc("disable-dot-loc", cl::Hidden,
+ cl::desc("Do not use .loc entries"));
+
+cl::opt<bool> DisableCFI("disable-cfi", cl::Hidden,
+ cl::desc("Do not use .cfi_* directives"));
+
+cl::opt<bool> EnableDwarfDirectory("enable-dwarf-directory", cl::Hidden,
+ cl::desc("Use .file directives with an explicit directory."));
+
+cl::opt<bool>
+DisableRedZone("disable-red-zone",
+ cl::desc("Do not emit code that uses the red zone."),
+ cl::init(false));
+
+cl::opt<bool>
+EnableFPMAD("enable-fp-mad",
+ cl::desc("Enable less precise MAD instructions to be generated"),
+ cl::init(false));
+
+cl::opt<bool>
+DisableFPElim("disable-fp-elim",
+ cl::desc("Disable frame pointer elimination optimization"),
+ cl::init(false));
+
+cl::opt<bool>
+DisableFPElimNonLeaf("disable-non-leaf-fp-elim",
+ cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"),
+ cl::init(false));
+
+cl::opt<bool>
+EnableUnsafeFPMath("enable-unsafe-fp-math",
+ cl::desc("Enable optimizations that may decrease FP precision"),
+ cl::init(false));
+
+cl::opt<bool>
+EnableNoInfsFPMath("enable-no-infs-fp-math",
+ cl::desc("Enable FP math optimizations that assume no +-Infs"),
+ cl::init(false));
+
+cl::opt<bool>
+EnableNoNaNsFPMath("enable-no-nans-fp-math",
+ cl::desc("Enable FP math optimizations that assume no NaNs"),
+ cl::init(false));
+
+cl::opt<bool>
+EnableHonorSignDependentRoundingFPMath("enable-sign-dependent-rounding-fp-math",
+ cl::Hidden,
+ cl::desc("Force codegen to assume rounding mode can change dynamically"),
+ cl::init(false));
+
+cl::opt<bool>
+GenerateSoftFloatCalls("soft-float",
+ cl::desc("Generate software floating point library calls"),
+ cl::init(false));
+
+cl::opt<llvm::FloatABI::ABIType>
+FloatABIForCalls("float-abi",
+ cl::desc("Choose float ABI type"),
+ cl::init(FloatABI::Default),
+ cl::values(
+ clEnumValN(FloatABI::Default, "default",
+ "Target default float ABI type"),
+ clEnumValN(FloatABI::Soft, "soft",
+ "Soft float ABI (implied by -soft-float)"),
+ clEnumValN(FloatABI::Hard, "hard",
+ "Hard float ABI (uses FP registers)"),
+ clEnumValEnd));
+
+cl::opt<llvm::FPOpFusion::FPOpFusionMode>
+FuseFPOps("fp-contract",
+ cl::desc("Enable aggresive formation of fused FP ops"),
+ cl::init(FPOpFusion::Standard),
+ cl::values(
+ clEnumValN(FPOpFusion::Fast, "fast",
+ "Fuse FP ops whenever profitable"),
+ clEnumValN(FPOpFusion::Standard, "on",
+ "Only fuse 'blessed' FP ops."),
+ clEnumValN(FPOpFusion::Strict, "off",
+ "Only fuse FP ops when the result won't be effected."),
+ clEnumValEnd));
+
+cl::opt<bool>
+DontPlaceZerosInBSS("nozero-initialized-in-bss",
+ cl::desc("Don't place zero-initialized symbols into bss section"),
+ cl::init(false));
+
+cl::opt<bool>
+EnableGuaranteedTailCallOpt("tailcallopt",
+ cl::desc("Turn fastcc calls into tail calls by (potentially) changing ABI."),
+ cl::init(false));
+
+cl::opt<bool>
+DisableTailCalls("disable-tail-calls",
+ cl::desc("Never emit tail calls"),
+ cl::init(false));
+
+cl::opt<unsigned>
+OverrideStackAlignment("stack-alignment",
+ cl::desc("Override default stack alignment"),
+ cl::init(0));
+
+cl::opt<bool>
+EnableRealignStack("realign-stack",
+ cl::desc("Realign stack if needed"),
+ cl::init(true));
+
+cl::opt<std::string>
+TrapFuncName("trap-func", cl::Hidden,
+ cl::desc("Emit a call to trap function rather than a trap instruction"),
+ cl::init(""));
+
+cl::opt<bool>
+EnablePIE("enable-pie",
+ cl::desc("Assume the creation of a position independent executable."),
+ cl::init(false));
+
+cl::opt<bool>
+SegmentedStacks("segmented-stacks",
+ cl::desc("Use segmented stacks if possible."),
+ cl::init(false));
+
+cl::opt<bool>
+UseInitArray("use-init-array",
+ cl::desc("Use .init_array instead of .ctors."),
+ cl::init(false));
+
+cl::opt<std::string> StopAfter("stop-after",
+ cl::desc("Stop compilation after a specific pass"),
+ cl::value_desc("pass-name"),
+ cl::init(""));
+cl::opt<std::string> StartAfter("start-after",
+ cl::desc("Resume compilation after a specific pass"),
+ cl::value_desc("pass-name"),
+ cl::init(""));
+
+cl::opt<unsigned>
+SSPBufferSize("stack-protector-buffer-size", cl::init(8),
+ cl::desc("Lower bound for a buffer to be considered for "
+ "stack protection"));
+#endif
diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h
index 1e8dde12553..b421753dd53 100644
--- a/include/llvm/CodeGen/LiveIntervalAnalysis.h
+++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h
@@ -65,12 +65,6 @@ namespace llvm {
/// Live interval pointers for all the virtual registers.
IndexedMap<LiveInterval*, VirtReg2IndexFunctor> VirtRegIntervals;
- /// AllocatableRegs - A bit vector of allocatable registers.
- BitVector AllocatableRegs;
-
- /// ReservedRegs - A bit vector of reserved registers.
- BitVector ReservedRegs;
-
/// RegMaskSlots - Sorted list of instructions with register mask operands.
/// Always use the 'r' slot, RegMasks are normal clobbers, not early
/// clobbers.
@@ -123,18 +117,6 @@ namespace llvm {
return VirtRegIntervals.inBounds(Reg) && VirtRegIntervals[Reg];
}
- /// isAllocatable - is the physical register reg allocatable in the current
- /// function?
- bool isAllocatable(unsigned reg) const {
- return AllocatableRegs.test(reg);
- }
-
- /// isReserved - is the physical register reg reserved in the current
- /// function
- bool isReserved(unsigned reg) const {
- return ReservedRegs.test(reg);
- }
-
// Interval creation.
LiveInterval &getOrCreateInterval(unsigned Reg) {
if (!hasInterval(Reg)) {
@@ -278,15 +260,20 @@ namespace llvm {
/// instruction 'mi' has been moved within a basic block. This will update
/// the live intervals for all operands of mi. Moves between basic blocks
/// are not supported.
- void handleMove(MachineInstr* MI);
+ ///
+ /// \param UpdateFlags Update live intervals for nonallocatable physregs.
+ void handleMove(MachineInstr* MI, bool UpdateFlags = false);
/// moveIntoBundle - Update intervals for operands of MI so that they
/// begin/end on the SlotIndex for BundleStart.
///
+ /// \param UpdateFlags Update live intervals for nonallocatable physregs.
+ ///
/// Requires MI and BundleStart to have SlotIndexes, and assumes
/// existing liveness is accurate. BundleStart should be the first
/// instruction in the Bundle.
- void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart);
+ void handleMoveIntoBundle(MachineInstr* MI, MachineInstr* BundleStart,
+ bool UpdateFlags = false);
// Register mask functions.
//
diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h
index d4bb409e060..3bb134b8fb2 100644
--- a/include/llvm/CodeGen/LiveVariables.h
+++ b/include/llvm/CodeGen/LiveVariables.h
@@ -126,12 +126,6 @@ private:
/// building live intervals.
SparseBitVector<> PHIJoins;
- /// ReservedRegisters - This vector keeps track of which registers
- /// are reserved register which are not allocatable by the target machine.
- /// We can not track liveness for values that are in this set.
- ///
- BitVector ReservedRegisters;
-
private: // Intermediate data structures
MachineFunction *MF;
diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h
index 654361f9d42..770685358ab 100644
--- a/include/llvm/CodeGen/MachineInstrBuilder.h
+++ b/include/llvm/CodeGen/MachineInstrBuilder.h
@@ -176,15 +176,24 @@ public:
}
// Add a displacement from an existing MachineOperand with an added offset.
- const MachineInstrBuilder &addDisp(const MachineOperand &Disp,
- int64_t off) const {
+ const MachineInstrBuilder &addDisp(const MachineOperand &Disp, int64_t off,
+ unsigned char TargetFlags = 0) const {
switch (Disp.getType()) {
default:
llvm_unreachable("Unhandled operand type in addDisp()");
case MachineOperand::MO_Immediate:
return addImm(Disp.getImm() + off);
- case MachineOperand::MO_GlobalAddress:
- return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off);
+ case MachineOperand::MO_GlobalAddress: {
+ // If caller specifies new TargetFlags then use it, otherwise the
+ // default behavior is to copy the target flags from the existing
+ // MachineOperand. This means if the caller wants to clear the
+ // target flags it needs to do so explicitly.
+ if (TargetFlags)
+ return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off,
+ TargetFlags);
+ return addGlobalAddress(Disp.getGlobal(), Disp.getOffset() + off,
+ Disp.getTargetFlags());
+ }
}
}
};
diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h
index 91d24dd0fc0..a5bc7f7d391 100644
--- a/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -95,9 +95,6 @@ class MachineRegisterInfo {
/// started.
BitVector ReservedRegs;
- /// AllocatableRegs - From TRI->getAllocatableSet.
- mutable BitVector AllocatableRegs;
-
/// LiveIns/LiveOuts - Keep track of the physical registers that are
/// livein/liveout of the function. Live in values are typically arguments in
/// registers, live out values are typically return values in registers.
@@ -427,6 +424,34 @@ public:
return !reservedRegsFrozen() || ReservedRegs.test(PhysReg);
}
+ /// getReservedRegs - Returns a reference to the frozen set of reserved
+ /// registers. This method should always be preferred to calling
+ /// TRI::getReservedRegs() when possible.
+ const BitVector &getReservedRegs() const {
+ assert(reservedRegsFrozen() &&
+ "Reserved registers haven't been frozen yet. "
+ "Use TRI::getReservedRegs().");
+ return ReservedRegs;
+ }
+
+ /// isReserved - Returns true when PhysReg is a reserved register.
+ ///
+ /// Reserved registers may belong to an allocatable register class, but the
+ /// target has explicitly requested that they are not used.
+ ///
+ bool isReserved(unsigned PhysReg) const {
+ return getReservedRegs().test(PhysReg);
+ }
+
+ /// isAllocatable - Returns true when PhysReg belongs to an allocatable
+ /// register class and it hasn't been reserved.
+ ///
+ /// Allocatable registers may show up in the allocation order of some virtual
+ /// register, so a register allocator needs to track its liveness and
+ /// availability.
+ bool isAllocatable(unsigned PhysReg) const {
+ return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg);
+ }
//===--------------------------------------------------------------------===//
// LiveIn/LiveOut Management
diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h
index 93990e164d1..2b96c7abe42 100644
--- a/include/llvm/CodeGen/MachineScheduler.h
+++ b/include/llvm/CodeGen/MachineScheduler.h
@@ -110,6 +110,10 @@ public:
/// Initialize the strategy after building the DAG for a new region.
virtual void initialize(ScheduleDAGMI *DAG) = 0;
+ /// Notify this strategy that all roots have been released (including those
+ /// that depend on EntrySU or ExitSU).
+ virtual void registerRoots() {}
+
/// Pick the next node to schedule, or return NULL. Set IsTopNode to true to
/// schedule the node at the top of the unscheduled region. Otherwise it will
/// be scheduled at the bottom.
diff --git a/include/llvm/CodeGen/PseudoSourceValue.h b/include/llvm/CodeGen/PseudoSourceValue.h
index 7dab4f94862..8f52d3bf47d 100644
--- a/include/llvm/CodeGen/PseudoSourceValue.h
+++ b/include/llvm/CodeGen/PseudoSourceValue.h
@@ -50,7 +50,6 @@ namespace llvm {
/// classof - Methods for support type inquiry through isa, cast, and
/// dyn_cast:
///
- static inline bool classof(const PseudoSourceValue *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == PseudoSourceValueVal ||
V->getValueID() == FixedStackPseudoSourceValueVal;
@@ -90,9 +89,6 @@ namespace llvm {
/// classof - Methods for support type inquiry through isa, cast, and
/// dyn_cast:
///
- static inline bool classof(const FixedStackPseudoSourceValue *) {
- return true;
- }
static inline bool classof(const Value *V) {
return V->getValueID() == FixedStackPseudoSourceValueVal;
}
diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h
index 400e1f48ce5..4467b62f237 100644
--- a/include/llvm/CodeGen/RegisterClassInfo.h
+++ b/include/llvm/CodeGen/RegisterClassInfo.h
@@ -106,25 +106,6 @@ public:
return CalleeSaved[N-1];
return 0;
}
-
- /// isReserved - Returns true when PhysReg is a reserved register.
- ///
- /// Reserved registers may belong to an allocatable register class, but the
- /// target has explicitly requested that they are not used.
- ///
- bool isReserved(unsigned PhysReg) const {
- return Reserved.test(PhysReg);
- }
-
- /// isAllocatable - Returns true when PhysReg belongs to an allocatable
- /// register class and it hasn't been reserved.
- ///
- /// Allocatable registers may show up in the allocation order of some virtual
- /// register, so a register allocator needs to track its liveness and
- /// availability.
- bool isAllocatable(unsigned PhysReg) const {
- return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg);
- }
};
} // end namespace llvm
diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h
index 3986a8dd7da..08d316992ec 100644
--- a/include/llvm/CodeGen/RegisterScavenging.h
+++ b/include/llvm/CodeGen/RegisterScavenging.h
@@ -18,6 +18,7 @@
#define LLVM_CODEGEN_REGISTER_SCAVENGING_H
#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/ADT/BitVector.h"
namespace llvm {
@@ -59,10 +60,6 @@ class RegScavenger {
///
BitVector CalleeSavedRegs;
- /// ReservedRegs - A bitvector of reserved registers.
- ///
- BitVector ReservedRegs;
-
/// RegsAvailable - The current state of all the physical registers immediately
/// before MBBI. One bit per physical register. If bit is set that means it's
/// available, unset means the register is currently being used.
@@ -130,12 +127,12 @@ public:
void setUsed(unsigned Reg);
private:
/// isReserved - Returns true if a register is reserved. It is never "unused".
- bool isReserved(unsigned Reg) const { return ReservedRegs.test(Reg); }
+ bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); }
/// isUsed / isUnused - Test if a register is currently being used.
///
bool isUsed(unsigned Reg) const {
- return !RegsAvailable.test(Reg) || ReservedRegs.test(Reg);
+ return !RegsAvailable.test(Reg) || isReserved(Reg);
}
/// isAliasUsed - Is Reg or an alias currently in use?
diff --git a/include/llvm/CodeGen/ScheduleDAGILP.h b/include/llvm/CodeGen/ScheduleDAGILP.h
new file mode 100644
index 00000000000..1aa40584217
--- /dev/null
+++ b/include/llvm/CodeGen/ScheduleDAGILP.h
@@ -0,0 +1,86 @@
+//===- ScheduleDAGILP.h - ILP metric for ScheduleDAGInstrs ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Definition of an ILP metric for machine level instruction scheduling.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_SCHEDULEDAGILP_H
+#define LLVM_CODEGEN_SCHEDULEDAGILP_H
+
+#include "llvm/Support/DataTypes.h"
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+class ScheduleDAGInstrs;
+class SUnit;
+
+/// \brief Represent the ILP of the subDAG rooted at a DAG node.
+struct ILPValue {
+ unsigned InstrCount;
+ unsigned Cycles;
+
+ ILPValue(): InstrCount(0), Cycles(0) {}
+
+ ILPValue(unsigned count, unsigned cycles):
+ InstrCount(count), Cycles(cycles) {}
+
+ bool isValid() const { return Cycles > 0; }
+
+ // Order by the ILP metric's value.
+ bool operator<(ILPValue RHS) const {
+ return (uint64_t)InstrCount * RHS.Cycles
+ < (uint64_t)Cycles * RHS.InstrCount;
+ }
+ bool operator>(ILPValue RHS) const {
+ return RHS < *this;
+ }
+ bool operator<=(ILPValue RHS) const {
+ return (uint64_t)InstrCount * RHS.Cycles
+ <= (uint64_t)Cycles * RHS.InstrCount;
+ }
+ bool operator>=(ILPValue RHS) const {
+ return RHS <= *this;
+ }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ void print(raw_ostream &OS) const;
+
+ void dump() const;
+#endif
+};
+
+/// \brief Compute the values of each DAG node for an ILP metric.
+///
+/// This metric assumes that the DAG is a forest of trees with roots at the
+/// bottom of the schedule.
+class ScheduleDAGILP {
+ bool IsBottomUp;
+ std::vector<ILPValue> ILPValues;
+
+public:
+ ScheduleDAGILP(bool IsBU): IsBottomUp(IsBU) {}
+
+ /// \brief Initialize the result data with the size of the DAG.
+ void resize(unsigned NumSUnits);
+
+ /// \brief Compute the ILP metric for the subDAG at this root.
+ void computeILP(const SUnit *Root);
+
+ /// \brief Get the ILP value for a DAG node.
+ ILPValue getILP(const SUnit *SU);
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const ILPValue &Val);
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h
index 63d47592650..2c828751080 100644
--- a/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -662,9 +662,6 @@ public:
///
void dumprWithDepth(const SelectionDAG *G = 0, unsigned depth = 100) const;
-
- static bool classof(const SDNode *) { return true; }
-
/// Profile - Gather unique data for the node.
///
void Profile(FoldingSetNodeID &ID) const;
@@ -976,7 +973,6 @@ public:
}
// Methods to support isa and dyn_cast
- static bool classof(const MemSDNode *) { return true; }
static bool classof(const SDNode *N) {
// For some targets, we lower some target intrinsics to a MemIntrinsicNode
// with either an intrinsic or a target opcode.
@@ -1061,7 +1057,6 @@ public:
}
// Methods to support isa and dyn_cast
- static bool classof(const AtomicSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::ATOMIC_CMP_SWAP ||
N->getOpcode() == ISD::ATOMIC_SWAP ||
@@ -1093,7 +1088,6 @@ public:
}
// Methods to support isa and dyn_cast
- static bool classof(const MemIntrinsicSDNode *) { return true; }
static bool classof(const SDNode *N) {
// We lower some target intrinsics to their target opcode
// early a node with a target opcode can be of this class
@@ -1148,7 +1142,6 @@ public:
}
static bool isSplatMask(const int *Mask, EVT VT);
- static bool classof(const ShuffleVectorSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::VECTOR_SHUFFLE;
}
@@ -1172,7 +1165,6 @@ public:
bool isNullValue() const { return Value->isNullValue(); }
bool isAllOnesValue() const { return Value->isAllOnesValue(); }
- static bool classof(const ConstantSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::Constant ||
N->getOpcode() == ISD::TargetConstant;
@@ -1219,7 +1211,6 @@ public:
static bool isValueValidForType(EVT VT, const APFloat& Val);
- static bool classof(const ConstantFPSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::ConstantFP ||
N->getOpcode() == ISD::TargetConstantFP;
@@ -1241,7 +1232,6 @@ public:
// Return the address space this GlobalAddress belongs to.
unsigned getAddressSpace() const;
- static bool classof(const GlobalAddressSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::GlobalAddress ||
N->getOpcode() == ISD::TargetGlobalAddress ||
@@ -1261,7 +1251,6 @@ public:
int getIndex() const { return FI; }
- static bool classof(const FrameIndexSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::FrameIndex ||
N->getOpcode() == ISD::TargetFrameIndex;
@@ -1281,7 +1270,6 @@ public:
int getIndex() const { return JTI; }
unsigned char getTargetFlags() const { return TargetFlags; }
- static bool classof(const JumpTableSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::JumpTable ||
N->getOpcode() == ISD::TargetJumpTable;
@@ -1342,7 +1330,6 @@ public:
Type *getType() const;
- static bool classof(const ConstantPoolSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::ConstantPool ||
N->getOpcode() == ISD::TargetConstantPool;
@@ -1366,7 +1353,6 @@ public:
int getIndex() const { return Index; }
int64_t getOffset() const { return Offset; }
- static bool classof(const TargetIndexSDNode*) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::TargetIndex;
}
@@ -1385,7 +1371,6 @@ public:
MachineBasicBlock *getBasicBlock() const { return MBB; }
- static bool classof(const BasicBlockSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::BasicBlock;
}
@@ -1410,7 +1395,6 @@ public:
unsigned &SplatBitSize, bool &HasAnyUndefs,
unsigned MinSplatBits = 0, bool isBigEndian = false);
- static inline bool classof(const BuildVectorSDNode *) { return true; }
static inline bool classof(const SDNode *N) {
return N->getOpcode() == ISD::BUILD_VECTOR;
}
@@ -1431,7 +1415,6 @@ public:
/// getValue - return the contained Value.
const Value *getValue() const { return V; }
- static bool classof(const SrcValueSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::SRCVALUE;
}
@@ -1446,7 +1429,6 @@ public:
const MDNode *getMD() const { return MD; }
- static bool classof(const MDNodeSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::MDNODE_SDNODE;
}
@@ -1463,7 +1445,6 @@ public:
unsigned getReg() const { return Reg; }
- static bool classof(const RegisterSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::Register;
}
@@ -1480,7 +1461,6 @@ public:
const uint32_t *getRegMask() const { return RegMask; }
- static bool classof(const RegisterMaskSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::RegisterMask;
}
@@ -1501,7 +1481,6 @@ public:
int64_t getOffset() const { return Offset; }
unsigned char getTargetFlags() const { return TargetFlags; }
- static bool classof(const BlockAddressSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::BlockAddress ||
N->getOpcode() == ISD::TargetBlockAddress;
@@ -1519,7 +1498,6 @@ class EHLabelSDNode : public SDNode {
public:
MCSymbol *getLabel() const { return Label; }
- static bool classof(const EHLabelSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::EH_LABEL;
}
@@ -1539,7 +1517,6 @@ public:
const char *getSymbol() const { return Symbol; }
unsigned char getTargetFlags() const { return TargetFlags; }
- static bool classof(const ExternalSymbolSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::ExternalSymbol ||
N->getOpcode() == ISD::TargetExternalSymbol;
@@ -1557,7 +1534,6 @@ public:
ISD::CondCode get() const { return Condition; }
- static bool classof(const CondCodeSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::CONDCODE;
}
@@ -1577,7 +1553,6 @@ class CvtRndSatSDNode : public SDNode {
public:
ISD::CvtCode getCvtCode() const { return CvtCode; }
- static bool classof(const CvtRndSatSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::CONVERT_RNDSAT;
}
@@ -1596,7 +1571,6 @@ public:
EVT getVT() const { return ValueType; }
- static bool classof(const VTSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::VALUETYPE;
}
@@ -1640,7 +1614,6 @@ public:
/// isUnindexed - Return true if this is NOT a pre/post inc/dec load/store.
bool isUnindexed() const { return getAddressingMode() == ISD::UNINDEXED; }
- static bool classof(const LSBaseSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::LOAD ||
N->getOpcode() == ISD::STORE;
@@ -1672,7 +1645,6 @@ public:
const SDValue &getBasePtr() const { return getOperand(1); }
const SDValue &getOffset() const { return getOperand(2); }
- static bool classof(const LoadSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::LOAD;
}
@@ -1703,7 +1675,6 @@ public:
const SDValue &getBasePtr() const { return getOperand(2); }
const SDValue &getOffset() const { return getOperand(3); }
- static bool classof(const StoreSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::STORE;
}
@@ -1744,7 +1715,6 @@ public:
MemRefsEnd = NewMemRefsEnd;
}
- static bool classof(const MachineSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->isMachineOpcode();
}
diff --git a/include/llvm/Constant.h b/include/llvm/Constant.h
index 7464dce3303..7fecf4c7b45 100644
--- a/include/llvm/Constant.h
+++ b/include/llvm/Constant.h
@@ -108,8 +108,6 @@ public:
virtual void destroyConstant() { llvm_unreachable("Not reached!"); }
//// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Constant *) { return true; }
- static inline bool classof(const GlobalValue *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() >= ConstantFirstVal &&
V->getValueID() <= ConstantLastVal;
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index 85fed4259d3..b56b9cad117 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -221,7 +221,6 @@ public:
}
/// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const ConstantInt *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantIntVal;
}
@@ -291,7 +290,6 @@ public:
return isExactlyValue(FV);
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ConstantFP *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantFPVal;
}
@@ -334,7 +332,6 @@ public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
///
- static bool classof(const ConstantAggregateZero *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantAggregateZeroVal;
}
@@ -367,7 +364,6 @@ public:
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ConstantArray *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantArrayVal;
}
@@ -426,7 +422,6 @@ public:
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ConstantStruct *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantStructVal;
}
@@ -474,7 +469,6 @@ public:
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ConstantVector *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantVectorVal;
}
@@ -517,7 +511,6 @@ public:
}
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ConstantPointerNull *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantPointerNullVal;
}
@@ -639,7 +632,6 @@ public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
///
- static bool classof(const ConstantDataSequential *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantDataArrayVal ||
V->getValueID() == ConstantDataVectorVal;
@@ -695,7 +687,6 @@ public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
///
- static bool classof(const ConstantDataArray *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantDataArrayVal;
}
@@ -749,7 +740,6 @@ public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
///
- static bool classof(const ConstantDataVector *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == ConstantDataVectorVal;
}
@@ -781,7 +771,6 @@ public:
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const BlockAddress *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == BlockAddressVal;
}
@@ -1094,7 +1083,6 @@ public:
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ConstantExpr *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == ConstantExprVal;
}
@@ -1159,7 +1147,6 @@ public:
virtual void destroyConstant();
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const UndefValue *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == UndefValueVal;
}
diff --git a/include/llvm/DataLayout.h b/include/llvm/DataLayout.h
index a24737e842b..c9ac0b7feaa 100644
--- a/include/llvm/DataLayout.h
+++ b/include/llvm/DataLayout.h
@@ -231,9 +231,7 @@ public:
}
/// Layout pointer alignment
- /// FIXME: The defaults need to be removed once all of
- /// the backends/clients are updated.
- unsigned getPointerABIAlignment(unsigned AS = 0) const {
+ unsigned getPointerABIAlignment(unsigned AS) const {
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
if (val == Pointers.end()) {
val = Pointers.find(0);
@@ -241,9 +239,7 @@ public:
return val->second.ABIAlign;
}
/// Return target's alignment for stack-based pointers
- /// FIXME: The defaults need to be removed once all of
- /// the backends/clients are updated.
- unsigned getPointerPrefAlignment(unsigned AS = 0) const {
+ unsigned getPointerPrefAlignment(unsigned AS) const {
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
if (val == Pointers.end()) {
val = Pointers.find(0);
@@ -251,9 +247,7 @@ public:
return val->second.PrefAlign;
}
/// Layout pointer size
- /// FIXME: The defaults need to be removed once all of
- /// the backends/clients are updated.
- unsigned getPointerSize(unsigned AS = 0) const {
+ unsigned getPointerSize(unsigned AS) const {
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
if (val == Pointers.end()) {
val = Pointers.find(0);
@@ -261,9 +255,7 @@ public:
return val->second.TypeBitWidth;
}
/// Layout pointer size, in bits
- /// FIXME: The defaults need to be removed once all of
- /// the backends/clients are updated.
- unsigned getPointerSizeInBits(unsigned AS = 0) const {
+ unsigned getPointerSizeInBits(unsigned AS) const {
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
if (val == Pointers.end()) {
val = Pointers.find(0);
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h
index da1e62dc043..c862c2c8bb2 100644
--- a/include/llvm/DerivedTypes.h
+++ b/include/llvm/DerivedTypes.h
@@ -85,7 +85,6 @@ public:
bool isPowerOf2ByteWidth() const;
// Methods for support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const IntegerType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == IntegerTyID;
}
@@ -134,7 +133,6 @@ public:
unsigned getNumParams() const { return NumContainedTys - 1; }
// Methods for support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const FunctionType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == FunctionTyID;
}
@@ -157,7 +155,6 @@ public:
bool indexValid(unsigned Idx) const;
// Methods for support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const CompositeType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == ArrayTyID ||
T->getTypeID() == StructTyID ||
@@ -293,7 +290,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const StructType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == StructTyID;
}
@@ -323,7 +319,6 @@ public:
Type *getElementType() const { return ContainedTys[0]; }
// Methods for support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const SequentialType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == ArrayTyID ||
T->getTypeID() == PointerTyID ||
@@ -353,7 +348,6 @@ public:
uint64_t getNumElements() const { return NumElements; }
// Methods for support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const ArrayType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == ArrayTyID;
}
@@ -420,7 +414,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const VectorType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == VectorTyID;
}
@@ -452,7 +445,6 @@ public:
inline unsigned getAddressSpace() const { return getSubclassData(); }
// Implement support type inquiry through isa, cast, and dyn_cast.
- static inline bool classof(const PointerType *) { return true; }
static inline bool classof(const Type *T) {
return T->getTypeID() == PointerTyID;
}
diff --git a/include/llvm/Function.h b/include/llvm/Function.h
index 855c926bf5c..e211e9ab52a 100644
--- a/include/llvm/Function.h
+++ b/include/llvm/Function.h
@@ -178,9 +178,7 @@ public:
///
void addFnAttr(Attributes::AttrVal N) {
// Function Attributes are stored at ~0 index
- Attributes::Builder B;
- B.addAttribute(N);
- addAttribute(~0U, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex, Attributes::get(getContext(), N));
}
/// removeFnAttr - Remove function attributes from this function.
@@ -278,9 +276,7 @@ public:
return getParamAttributes(n).hasAttribute(Attributes::NoAlias);
}
void setDoesNotAlias(unsigned n) {
- Attributes::Builder B;
- B.addAttribute(Attributes::NoAlias);
- addAttribute(n, Attributes::get(B));
+ addAttribute(n, Attributes::get(getContext(), Attributes::NoAlias));
}
/// @brief Determine if the parameter can be captured.
@@ -289,9 +285,7 @@ public:
return getParamAttributes(n).hasAttribute(Attributes::NoCapture);
}
void setDoesNotCapture(unsigned n) {
- Attributes::Builder B;
- B.addAttribute(Attributes::NoCapture);
- addAttribute(n, Attributes::get(B));
+ addAttribute(n, Attributes::get(getContext(), Attributes::NoCapture));
}
/// copyAttributesFrom - copy all additional attributes (those not needed to
@@ -404,7 +398,6 @@ public:
void viewCFGOnly() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Function *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == Value::FunctionVal;
}
diff --git a/include/llvm/GlobalAlias.h b/include/llvm/GlobalAlias.h
index a97ecd30c9d..d0f014733fc 100644
--- a/include/llvm/GlobalAlias.h
+++ b/include/llvm/GlobalAlias.h
@@ -76,7 +76,6 @@ public:
const GlobalValue *resolveAliasedGlobal(bool stopOnWeak = true) const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const GlobalAlias *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == Value::GlobalAliasVal;
}
diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h
index 58d02576c17..7f7f74b1e2d 100644
--- a/include/llvm/GlobalValue.h
+++ b/include/llvm/GlobalValue.h
@@ -287,7 +287,6 @@ public:
inline const Module *getParent() const { return Parent; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const GlobalValue *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == Value::FunctionVal ||
V->getValueID() == Value::GlobalVariableVal ||
diff --git a/include/llvm/GlobalVariable.h b/include/llvm/GlobalVariable.h
index 27a2ea7fb9f..b9d3f68642f 100644
--- a/include/llvm/GlobalVariable.h
+++ b/include/llvm/GlobalVariable.h
@@ -174,7 +174,6 @@ public:
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U);
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const GlobalVariable *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == Value::GlobalVariableVal;
}
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 409246cf148..ee9b1c5852e 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -94,6 +94,7 @@ void initializeDCEPass(PassRegistry&);
void initializeDSEPass(PassRegistry&);
void initializeDeadInstEliminationPass(PassRegistry&);
void initializeDeadMachineInstructionElimPass(PassRegistry&);
+void initializeDependenceAnalysisPass(PassRegistry&);
void initializeDomOnlyPrinterPass(PassRegistry&);
void initializeDomOnlyViewerPass(PassRegistry&);
void initializeDomPrinterPass(PassRegistry&);
@@ -247,6 +248,7 @@ void initializeTailCallElimPass(PassRegistry&);
void initializeTailDuplicatePassPass(PassRegistry&);
void initializeTargetPassConfigPass(PassRegistry&);
void initializeDataLayoutPass(PassRegistry&);
+void initializeTargetTransformInfoPass(PassRegistry&);
void initializeTargetLibraryInfoPass(PassRegistry&);
void initializeTwoAddressInstructionPassPass(PassRegistry&);
void initializeTypeBasedAliasAnalysisPass(PassRegistry&);
diff --git a/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h
index 58c1e84e53f..c6e0aab05e7 100644
--- a/include/llvm/InlineAsm.h
+++ b/include/llvm/InlineAsm.h
@@ -189,7 +189,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const InlineAsm *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() == Value::InlineAsmVal;
}
diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h
index bda9d79da75..cfc79394b22 100644
--- a/include/llvm/InstrTypes.h
+++ b/include/llvm/InstrTypes.h
@@ -73,7 +73,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const TerminatorInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->isTerminator();
}
@@ -113,7 +112,6 @@ public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const UnaryInstruction *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Alloca ||
I->getOpcode() == Instruction::Load ||
@@ -361,7 +359,6 @@ public:
bool isExact() const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const BinaryOperator *) { return true; }
static inline bool classof(const Instruction *I) {
return I->isBinaryOp();
}
@@ -611,7 +608,6 @@ public:
static bool castIsValid(Instruction::CastOps op, Value *S, Type *DstTy);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const CastInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->isCast();
}
@@ -816,7 +812,6 @@ public:
static bool isFalseWhenEqual(unsigned short predicate);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const CmpInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::ICmp ||
I->getOpcode() == Instruction::FCmp;
diff --git a/include/llvm/Instruction.h b/include/llvm/Instruction.h
index c85eda28f42..8aa8a56bf82 100644
--- a/include/llvm/Instruction.h
+++ b/include/llvm/Instruction.h
@@ -310,7 +310,6 @@ public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Instruction *) { return true; }
static inline bool classof(const Value *V) {
return V->getValueID() >= Value::InstructionVal;
}
diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h
index a1a2bd53c82..40dbbaabe69 100644
--- a/include/llvm/Instructions.h
+++ b/include/llvm/Instructions.h
@@ -112,7 +112,6 @@ public:
bool isStaticAlloca() const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const AllocaInst *) { return true; }
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::Alloca);
}
@@ -232,7 +231,6 @@ public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const LoadInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Load;
}
@@ -350,11 +348,19 @@ public:
static unsigned getPointerOperandIndex() { return 1U; }
unsigned getPointerAddressSpace() const {
- return cast<PointerType>(getPointerOperand()->getType())->getAddressSpace();
+ if (getPointerOperand()->getType()->isPointerTy())
+ return cast<PointerType>(getPointerOperand()->getType())
+ ->getAddressSpace();
+ if (getPointerOperand()->getType()->isVectorTy()
+ && cast<VectorType>(getPointerOperand()->getType())->isPointerTy())
+ return cast<PointerType>(cast<VectorType>(
+ getPointerOperand()->getType())->getElementType())
+ ->getAddressSpace();
+ llvm_unreachable("Only a vector of pointers or pointers can be used!");
+ return 0;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const StoreInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Store;
}
@@ -426,7 +432,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const FenceInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Fence;
}
@@ -526,7 +531,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const AtomicCmpXchgInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::AtomicCmpXchg;
}
@@ -670,7 +674,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const AtomicRMWInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::AtomicRMW;
}
@@ -849,7 +852,6 @@ public:
bool isInBounds() const;
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const GetElementPtrInst *) { return true; }
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::GetElementPtr);
}
@@ -1031,7 +1033,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ICmpInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::ICmp;
}
@@ -1141,7 +1142,6 @@ public:
}
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const FCmpInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::FCmp;
}
@@ -1281,9 +1281,8 @@ public:
/// @brief Return true if the call should not be inlined.
bool isNoInline() const { return hasFnAttr(Attributes::NoInline); }
void setIsNoInline() {
- Attributes::Builder B;
- B.addAttribute(Attributes::NoInline);
- addAttribute(~0, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::NoInline));
}
/// @brief Return true if the call can return twice
@@ -1291,9 +1290,8 @@ public:
return hasFnAttr(Attributes::ReturnsTwice);
}
void setCanReturnTwice() {
- Attributes::Builder B;
- B.addAttribute(Attributes::ReturnsTwice);
- addAttribute(~0U, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::ReturnsTwice));
}
/// @brief Determine if the call does not access memory.
@@ -1301,9 +1299,8 @@ public:
return hasFnAttr(Attributes::ReadNone);
}
void setDoesNotAccessMemory() {
- Attributes::Builder B;
- B.addAttribute(Attributes::ReadNone);
- addAttribute(~0U, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::ReadNone));
}
/// @brief Determine if the call does not access or only reads memory.
@@ -1311,25 +1308,22 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attributes::ReadOnly);
}
void setOnlyReadsMemory() {
- Attributes::Builder B;
- B.addAttribute(Attributes::ReadOnly);
- addAttribute(~0, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::ReadOnly));
}
/// @brief Determine if the call cannot return.
bool doesNotReturn() const { return hasFnAttr(Attributes::NoReturn); }
void setDoesNotReturn() {
- Attributes::Builder B;
- B.addAttribute(Attributes::NoReturn);
- addAttribute(~0, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::NoReturn));
}
/// @brief Determine if the call cannot unwind.
bool doesNotThrow() const { return hasFnAttr(Attributes::NoUnwind); }
- void setDoesNotThrow(bool DoesNotThrow = true) {
- Attributes::Builder B;
- B.addAttribute(Attributes::NoUnwind);
- addAttribute(~0, Attributes::get(B));
+ void setDoesNotThrow() {
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::NoUnwind));
}
/// @brief Determine if the call returns a structure through first
@@ -1370,7 +1364,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const CallInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Call;
}
@@ -1476,7 +1469,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SelectInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Select;
}
@@ -1519,7 +1511,6 @@ public:
static unsigned getPointerOperandIndex() { return 0U; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const VAArgInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == VAArg;
}
@@ -1573,7 +1564,6 @@ public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ExtractElementInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::ExtractElement;
}
@@ -1632,7 +1622,6 @@ public:
DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const InsertElementInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::InsertElement;
}
@@ -1713,7 +1702,6 @@ public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ShuffleVectorInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::ShuffleVector;
}
@@ -1809,7 +1797,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ExtractValueInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::ExtractValue;
}
@@ -1931,7 +1918,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const InsertValueInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::InsertValue;
}
@@ -2148,7 +2134,6 @@ public:
Value *hasConstantValue() const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const PHINode *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::PHI;
}
@@ -2256,7 +2241,6 @@ public:
void reserveClauses(unsigned Size) { growOperands(Size); }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const LandingPadInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::LandingPad;
}
@@ -2325,7 +2309,6 @@ public:
unsigned getNumSuccessors() const { return 0; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ReturnInst *) { return true; }
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::Ret);
}
@@ -2425,7 +2408,6 @@ public:
void swapSuccessors();
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const BranchInst *) { return true; }
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::Br);
}
@@ -2836,7 +2818,6 @@ public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SwitchInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Switch;
}
@@ -2935,7 +2916,6 @@ public:
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const IndirectBrInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::IndirectBr;
}
@@ -3050,9 +3030,8 @@ public:
/// @brief Return true if the call should not be inlined.
bool isNoInline() const { return hasFnAttr(Attributes::NoInline); }
void setIsNoInline() {
- Attributes::Builder B;
- B.addAttribute(Attributes::NoInline);
- addAttribute(~0, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::NoInline));
}
/// @brief Determine if the call does not access memory.
@@ -3060,9 +3039,8 @@ public:
return hasFnAttr(Attributes::ReadNone);
}
void setDoesNotAccessMemory() {
- Attributes::Builder B;
- B.addAttribute(Attributes::ReadNone);
- addAttribute(~0, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::ReadNone));
}
/// @brief Determine if the call does not access or only reads memory.
@@ -3070,25 +3048,22 @@ public:
return doesNotAccessMemory() || hasFnAttr(Attributes::ReadOnly);
}
void setOnlyReadsMemory() {
- Attributes::Builder B;
- B.addAttribute(Attributes::ReadOnly);
- addAttribute(~0, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::ReadOnly));
}
/// @brief Determine if the call cannot return.
bool doesNotReturn() const { return hasFnAttr(Attributes::NoReturn); }
void setDoesNotReturn() {
- Attributes::Builder B;
- B.addAttribute(Attributes::NoReturn);
- addAttribute(~0, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::NoReturn));
}
/// @brief Determine if the call cannot unwind.
bool doesNotThrow() const { return hasFnAttr(Attributes::NoUnwind); }
void setDoesNotThrow() {
- Attributes::Builder B;
- B.addAttribute(Attributes::NoUnwind);
- addAttribute(~0, Attributes::get(B));
+ addAttribute(AttrListPtr::FunctionIndex,
+ Attributes::get(getContext(), Attributes::NoUnwind));
}
/// @brief Determine if the call returns a structure through first
@@ -3154,7 +3129,6 @@ public:
unsigned getNumSuccessors() const { return 2; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const InvokeInst *) { return true; }
static inline bool classof(const Instruction *I) {
return (I->getOpcode() == Instruction::Invoke);
}
@@ -3234,7 +3208,6 @@ public:
unsigned getNumSuccessors() const { return 0; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ResumeInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Resume;
}
@@ -3279,7 +3252,6 @@ public:
unsigned getNumSuccessors() const { return 0; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const UnreachableInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Unreachable;
}
@@ -3320,7 +3292,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const TruncInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Trunc;
}
@@ -3357,7 +3328,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const ZExtInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == ZExt;
}
@@ -3394,7 +3364,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SExtInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == SExt;
}
@@ -3431,7 +3400,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const FPTruncInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == FPTrunc;
}
@@ -3468,7 +3436,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const FPExtInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == FPExt;
}
@@ -3505,7 +3472,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const UIToFPInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == UIToFP;
}
@@ -3542,7 +3508,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const SIToFPInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == SIToFP;
}
@@ -3579,7 +3544,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const FPToUIInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == FPToUI;
}
@@ -3616,7 +3580,6 @@ public:
);
/// @brief Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const FPToSIInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == FPToSI;
}
@@ -3653,11 +3616,18 @@ public:
/// @brief return the address space of the pointer.
unsigned getAddressSpace() const {
- return cast<PointerType>(getType())->getAddressSpace();
+ if (getType()->isPointerTy())
+ return cast<PointerType>(getType())->getAddressSpace();
+ if (getType()->isVectorTy() &&
+ cast<VectorType>(getType())->getElementType()->isPointerTy())
+ return cast<PointerType>(
+ cast<VectorType>(getType())->getElementType())
+ ->getAddressSpace();
+ llvm_unreachable("Must be a pointer or a vector of pointers.");
+ return 0;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const IntToPtrInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == IntToPtr;
}
@@ -3695,11 +3665,19 @@ public:
/// @brief return the address space of the pointer.
unsigned getPointerAddressSpace() const {
- return cast<PointerType>(getOperand(0)->getType())->getAddressSpace();
+ Type *Ty = getOperand(0)->getType();
+ if (Ty->isPointerTy())
+ return cast<PointerType>(Ty)->getAddressSpace();
+ if (Ty->isVectorTy()
+ && cast<VectorType>(Ty)->getElementType()->isPointerTy())
+ return cast<PointerType>(
+ cast<VectorType>(Ty)->getElementType())
+ ->getAddressSpace();
+ llvm_unreachable("Must be a pointer or a vector of pointers.");
+ return 0;
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const PtrToIntInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == PtrToInt;
}
@@ -3736,7 +3714,6 @@ public:
);
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const BitCastInst *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == BitCast;
}
diff --git a/include/llvm/IntrinsicInst.h b/include/llvm/IntrinsicInst.h
index e9bf0f6759b..a31220355f6 100644
--- a/include/llvm/IntrinsicInst.h
+++ b/include/llvm/IntrinsicInst.h
@@ -45,7 +45,6 @@ namespace llvm {
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const IntrinsicInst *) { return true; }
static inline bool classof(const CallInst *I) {
if (const Function *CF = I->getCalledFunction())
return CF->getIntrinsicID() != 0;
@@ -62,7 +61,6 @@ namespace llvm {
public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const DbgInfoIntrinsic *) { return true; }
static inline bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
case Intrinsic::dbg_declare:
@@ -86,7 +84,6 @@ namespace llvm {
MDNode *getVariable() const { return cast<MDNode>(getArgOperand(1)); }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const DbgDeclareInst *) { return true; }
static inline bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_declare;
}
@@ -108,7 +105,6 @@ namespace llvm {
MDNode *getVariable() const { return cast<MDNode>(getArgOperand(2)); }
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const DbgValueInst *) { return true; }
static inline bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_value;
}
@@ -175,7 +171,6 @@ namespace llvm {
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const MemIntrinsic *) { return true; }
static inline bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
case Intrinsic::memcpy:
@@ -205,7 +200,6 @@ namespace llvm {
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const MemSetInst *) { return true; }
static inline bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::memset;
}
@@ -238,7 +232,6 @@ namespace llvm {
}
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const MemTransferInst *) { return true; }
static inline bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::memcpy ||
I->getIntrinsicID() == Intrinsic::memmove;
@@ -254,7 +247,6 @@ namespace llvm {
class MemCpyInst : public MemTransferInst {
public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const MemCpyInst *) { return true; }
static inline bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::memcpy;
}
@@ -268,7 +260,6 @@ namespace llvm {
class MemMoveInst : public MemTransferInst {
public:
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const MemMoveInst *) { return true; }
static inline bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::memmove;
}
diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h
index c3503889e70..3108a8e5251 100644
--- a/include/llvm/Intrinsics.h
+++ b/include/llvm/Intrinsics.h
@@ -50,7 +50,7 @@ namespace Intrinsic {
/// Intrinsic::getType(ID) - Return the function type for an intrinsic.
///
FunctionType *getType(LLVMContext &Context, ID id,
- ArrayRef<Type*> Tys = ArrayRef<Type*>());
+ ArrayRef<Type*> Tys = ArrayRef<Type*>());
/// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be
/// overloaded.
@@ -58,7 +58,7 @@ namespace Intrinsic {
/// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic.
///
- AttrListPtr getAttributes(ID id);
+ AttrListPtr getAttributes(LLVMContext &C, ID id);
/// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function
/// declaration for an intrinsic, and return it.
diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h
index c01e4710248..4b10d0e5415 100644
--- a/include/llvm/LinkAllPasses.h
+++ b/include/llvm/LinkAllPasses.h
@@ -64,6 +64,7 @@ namespace {
(void) llvm::createDeadCodeEliminationPass();
(void) llvm::createDeadInstEliminationPass();
(void) llvm::createDeadStoreEliminationPass();
+ (void) llvm::createDependenceAnalysisPass();
(void) llvm::createDomOnlyPrinterPass();
(void) llvm::createDomPrinterPass();
(void) llvm::createDomOnlyViewerPass();
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
index 83c01ec5b98..5771415c81c 100644
--- a/include/llvm/MC/MCAssembler.h
+++ b/include/llvm/MC/MCAssembler.h
@@ -99,8 +99,6 @@ public:
unsigned getLayoutOrder() const { return LayoutOrder; }
void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
- static bool classof(const MCFragment *O) { return true; }
-
void dump();
};
@@ -151,7 +149,6 @@ public:
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Data;
}
- static bool classof(const MCDataFragment *) { return true; }
};
// FIXME: This current incarnation of MCInstFragment doesn't make much sense, as
@@ -213,7 +210,6 @@ public:
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Inst;
}
- static bool classof(const MCInstFragment *) { return true; }
};
class MCAlignFragment : public MCFragment {
@@ -263,7 +259,6 @@ public:
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Align;
}
- static bool classof(const MCAlignFragment *) { return true; }
};
class MCFillFragment : public MCFragment {
@@ -302,7 +297,6 @@ public:
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Fill;
}
- static bool classof(const MCFillFragment *) { return true; }
};
class MCOrgFragment : public MCFragment {
@@ -331,7 +325,6 @@ public:
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Org;
}
- static bool classof(const MCOrgFragment *) { return true; }
};
class MCLEBFragment : public MCFragment {
@@ -364,7 +357,6 @@ public:
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_LEB;
}
- static bool classof(const MCLEBFragment *) { return true; }
};
class MCDwarfLineAddrFragment : public MCFragment {
@@ -401,7 +393,6 @@ public:
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_Dwarf;
}
- static bool classof(const MCDwarfLineAddrFragment *) { return true; }
};
class MCDwarfCallFrameFragment : public MCFragment {
@@ -431,7 +422,6 @@ public:
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_DwarfFrame;
}
- static bool classof(const MCDwarfCallFrameFragment *) { return true; }
};
// FIXME: Should this be a separate class, or just merged into MCSection? Since
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index 50328872485..4c10e5114a3 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -99,8 +99,6 @@ public:
const MCSection *FindAssociatedSection() const;
/// @}
-
- static bool classof(const MCExpr *) { return true; }
};
inline raw_ostream &operator<<(raw_ostream &OS, const MCExpr &E) {
@@ -132,7 +130,6 @@ public:
static bool classof(const MCExpr *E) {
return E->getKind() == MCExpr::Constant;
}
- static bool classof(const MCConstantExpr *) { return true; }
};
/// MCSymbolRefExpr - Represent a reference to a symbol from inside an
@@ -248,7 +245,6 @@ public:
static bool classof(const MCExpr *E) {
return E->getKind() == MCExpr::SymbolRef;
}
- static bool classof(const MCSymbolRefExpr *) { return true; }
};
/// MCUnaryExpr - Unary assembler expressions.
@@ -302,7 +298,6 @@ public:
static bool classof(const MCExpr *E) {
return E->getKind() == MCExpr::Unary;
}
- static bool classof(const MCUnaryExpr *) { return true; }
};
/// MCBinaryExpr - Binary assembler expressions.
@@ -437,7 +432,6 @@ public:
static bool classof(const MCExpr *E) {
return E->getKind() == MCExpr::Binary;
}
- static bool classof(const MCBinaryExpr *) { return true; }
};
/// MCTargetExpr - This is an extension point for target-specific MCExpr
@@ -461,7 +455,6 @@ public:
static bool classof(const MCExpr *E) {
return E->getKind() == MCExpr::Target;
}
- static bool classof(const MCTargetExpr *) { return true; }
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h
index adc960d27e0..08758cda226 100644
--- a/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/include/llvm/MC/MCParser/MCAsmParser.h
@@ -20,6 +20,7 @@ class MCAsmLexer;
class MCAsmParserExtension;
class MCContext;
class MCExpr;
+class MCParsedAsmOperand;
class MCStreamer;
class MCTargetAsmParser;
class SMLoc;
@@ -73,6 +74,27 @@ public:
/// Run - Run the parser on the input source buffer.
virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0;
+ virtual void setParsingInlineAsm(bool V) = 0;
+
+ /// ParseStatement - Parse the next statement.
+ virtual bool ParseStatement() = 0;
+
+ /// getNumParsedOperands - Returns the number of MCAsmParsedOperands from the
+ /// previously parsed statement.
+ virtual unsigned getNumParsedOperands() = 0;
+
+ /// getParsedOperand - Get a MCAsmParsedOperand.
+ virtual MCParsedAsmOperand &getParsedOperand(unsigned OpNum) = 0;
+
+ /// freeParsedOperands - Free the MCAsmParsedOperands.
+ virtual void freeParsedOperands() = 0;
+
+ /// isInstruction - Was the previously parsed statement an instruction?
+ virtual bool isInstruction() = 0;
+
+ /// getOpcode - Get the opcode from the previously parsed instruction.
+ virtual unsigned getOpcode() = 0;
+
/// Warning - Emit a warning at the location \p L, with the message \p Msg.
///
/// \return The return value is true, if warnings are fatal.
diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h
index 0ce32d617ef..280145bfbc8 100644
--- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h
+++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h
@@ -19,10 +19,34 @@ class raw_ostream;
/// base class is used by target-independent clients and is the interface
/// between parsing an asm instruction and recognizing it.
class MCParsedAsmOperand {
+ /// MCOperandNum - The corresponding MCInst operand number. Only valid when
+ /// parsing MS-style inline assembly.
+ unsigned MCOperandNum;
+
+ /// Constraint - The constraint on this operand. Only valid when parsing
+ /// MS-style inline assembly.
+ std::string Constraint;
+
public:
MCParsedAsmOperand() {}
virtual ~MCParsedAsmOperand() {}
+ void setConstraint(StringRef C) { Constraint = C.str(); }
+ StringRef getConstraint() { return Constraint; }
+
+ void setMCOperandNum (unsigned OpNum) { MCOperandNum = OpNum; }
+ unsigned getMCOperandNum() { return MCOperandNum; }
+
+ unsigned getNameLen() {
+ assert (getStartLoc().isValid() && "Invalid StartLoc!");
+ assert (getEndLoc().isValid() && "Invalid EndLoc!");
+ return getEndLoc().getPointer() - getStartLoc().getPointer();
+ }
+
+ StringRef getName() {
+ return StringRef(getStartLoc().getPointer(), getNameLen());
+ }
+
/// isToken - Is this a token operand?
virtual bool isToken() const = 0;
/// isImm - Is this an immediate operand?
diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h
index a92fc379e19..21fdb6bd39b 100644
--- a/include/llvm/MC/MCSection.h
+++ b/include/llvm/MC/MCSection.h
@@ -64,8 +64,6 @@ namespace llvm {
/// isVirtualSection - Check whether this section is "virtual", that is
/// has no actual object file contents.
virtual bool isVirtualSection() const = 0;
-
- static bool classof(const MCSection *) { return true; }
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h
index 7eacde57f48..b050c0f442b 100644
--- a/include/llvm/MC/MCSectionCOFF.h
+++ b/include/llvm/MC/MCSectionCOFF.h
@@ -61,7 +61,6 @@ namespace llvm {
static bool classof(const MCSection *S) {
return S->getVariant() == SV_COFF;
}
- static bool classof(const MCSectionCOFF *) { return true; }
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h
index 7321ca83e89..4d54465760d 100644
--- a/include/llvm/MC/MCSectionELF.h
+++ b/include/llvm/MC/MCSectionELF.h
@@ -76,7 +76,6 @@ public:
static bool classof(const MCSection *S) {
return S->getVariant() == SV_ELF;
}
- static bool classof(const MCSectionELF *) { return true; }
// Return the entry size for sections with fixed-width data.
static unsigned DetermineEntrySize(SectionKind Kind);
diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h
index 15eb4f4a768..71ea8f3e901 100644
--- a/include/llvm/MC/MCSectionMachO.h
+++ b/include/llvm/MC/MCSectionMachO.h
@@ -174,7 +174,6 @@ public:
static bool classof(const MCSection *S) {
return S->getVariant() == SV_MachO;
}
- static bool classof(const MCSectionMachO *) { return true; }
};
} // end namespace llvm
diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h
index 44698989c17..230d27ef2ef 100644
--- a/include/llvm/MC/MCStreamer.h
+++ b/include/llvm/MC/MCStreamer.h
@@ -554,6 +554,11 @@ namespace llvm {
virtual void EmitRegSave(const SmallVectorImpl<unsigned> &RegList,
bool isVector);
+ /// PPC-related methods.
+ /// FIXME: Eventually replace it with some "target MC streamer" and move
+ /// these methods there.
+ virtual void EmitTCEntry(const MCSymbol &S);
+
/// FinishImpl - Streamer specific finalization.
virtual void FinishImpl() = 0;
/// Finish - Finish emission of machine code.
diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h
index a966a6b8b32..c9ea5ae4846 100644
--- a/include/llvm/MC/MCTargetAsmParser.h
+++ b/include/llvm/MC/MCTargetAsmParser.h
@@ -50,12 +50,6 @@ public:
virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) = 0;
- /// MapAndConstraints - Map inline assembly operands to MCInst operands
- /// and an associated constraint.
- typedef std::pair< unsigned, std::string > MapAndConstraint;
- typedef SmallVector<MapAndConstraint, 4> MatchInstMapAndConstraints;
- typedef SmallVectorImpl<MapAndConstraint> MatchInstMapAndConstraintsImpl;
-
/// ParseInstruction - Parse one assembly instruction.
///
/// The parser is positioned following the instruction name. The target
@@ -88,22 +82,6 @@ public:
/// otherwise.
virtual bool mnemonicIsValid(StringRef Mnemonic) = 0;
- /// MatchInstruction - Recognize a series of operands of a parsed instruction
- /// as an actual MCInst. This returns false on success and returns true on
- /// failure to match.
- ///
- /// On failure, the target parser is responsible for emitting a diagnostic
- /// explaining the match failure.
- virtual bool
- MatchInstruction(SMLoc IDLoc,
- SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- MCStreamer &Out, unsigned &Kind, unsigned &Opcode,
- MatchInstMapAndConstraintsImpl &MapAndConstraints,
- unsigned &OrigErrorInfo, bool matchingInlineAsm = false) {
- OrigErrorInfo = ~0x0;
- return true;
- }
-
/// MatchAndEmitInstruction - Recognize a series of operands of a parsed
/// instruction as an actual MCInst and emit it to the specified MCStreamer.
/// This returns false on success and returns true on failure to match.
@@ -111,9 +89,10 @@ public:
/// On failure, the target parser is responsible for emitting a diagnostic
/// explaining the match failure.
virtual bool
- MatchAndEmitInstruction(SMLoc IDLoc,
+ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- MCStreamer &Out) = 0;
+ MCStreamer &Out, unsigned &ErrorInfo,
+ bool MatchingInlineAsm) = 0;
/// checkTargetMatchPredicate - Validate the instruction match against
/// any complex target predicates not expressible via match classes.
@@ -122,8 +101,7 @@ public:
}
virtual void convertToMapAndConstraints(unsigned Kind,
- const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- MatchInstMapAndConstraintsImpl &MapAndConstraints) = 0;
+ const SmallVectorImpl<MCParsedAsmOperand*> &Operands) = 0;
};
} // End llvm namespace
diff --git a/include/llvm/Metadata.h b/include/llvm/Metadata.h
index d0e65246233..0fbbb959888 100644
--- a/include/llvm/Metadata.h
+++ b/include/llvm/Metadata.h
@@ -59,7 +59,6 @@ public:
iterator end() const { return getName().end(); }
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const MDString *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == MDStringVal;
}
@@ -161,7 +160,6 @@ public:
void Profile(FoldingSetNodeID &ID) const;
/// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const MDNode *) { return true; }
static bool classof(const Value *V) {
return V->getValueID() == MDNodeVal;
}
diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h
index 358b27a416c..f3d824960c2 100644
--- a/include/llvm/Object/Archive.h
+++ b/include/llvm/Object/Archive.h
@@ -129,7 +129,6 @@ public:
symbol_iterator end_symbols() const;
// Cast methods.
- static inline bool classof(Archive const *v) { return true; }
static inline bool classof(Binary const *v) {
return v->isArchive();
}
diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h
index baed81827d0..d555de3accc 100644
--- a/include/llvm/Object/Binary.h
+++ b/include/llvm/Object/Binary.h
@@ -64,7 +64,6 @@ public:
// Cast methods.
unsigned int getType() const { return TypeID; }
- static inline bool classof(const Binary *v) { return true; }
// Convenience methods
bool isObject() const {
diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h
index ba81058ae40..d6b92ed0213 100644
--- a/include/llvm/Object/COFF.h
+++ b/include/llvm/Object/COFF.h
@@ -198,7 +198,6 @@ public:
static inline bool classof(const Binary *v) {
return v->isCOFF();
}
- static inline bool classof(const COFFObjectFile *v) { return true; }
};
}
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index 3ca69bcb153..204348c0c50 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -723,7 +723,6 @@ public:
return v->getType() == getELFType(target_endianness == support::little,
is64Bits);
}
- static inline bool classof(const ELFObjectFile *v) { return true; }
};
// Iterate through the version definitions, and place each Elf_Verdef
diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h
index ecb9e256050..97cd4191aa6 100644
--- a/include/llvm/Object/MachO.h
+++ b/include/llvm/Object/MachO.h
@@ -49,7 +49,6 @@ public:
static inline bool classof(const Binary *v) {
return v->isMachO();
}
- static inline bool classof(const MachOObjectFile *v) { return true; }
protected:
virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const;
diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h
index 99ddb3b87b8..41959bd34e1 100644
--- a/include/llvm/Object/ObjectFile.h
+++ b/include/llvm/Object/ObjectFile.h
@@ -76,13 +76,13 @@ public:
}
};
-inline bool operator ==(const DataRefImpl &a, const DataRefImpl &b) {
+inline bool operator==(const DataRefImpl &a, const DataRefImpl &b) {
// Check bitwise identical. This is the only legal way to compare a union w/o
// knowing which member is in use.
return std::memcmp(&a, &b, sizeof(DataRefImpl)) == 0;
}
-inline bool operator <(const DataRefImpl &a, const DataRefImpl &b) {
+inline bool operator<(const DataRefImpl &a, const DataRefImpl &b) {
// Check bitwise identical. This is the only legal way to compare a union w/o
// knowing which member is in use.
return std::memcmp(&a, &b, sizeof(DataRefImpl)) < 0;
@@ -144,7 +144,7 @@ public:
SectionRef(DataRefImpl SectionP, const ObjectFile *Owner);
bool operator==(const SectionRef &Other) const;
- bool operator <(const SectionRef &Other) const;
+ bool operator<(const SectionRef &Other) const;
error_code getNext(SectionRef &Result) const;
@@ -208,7 +208,7 @@ public:
SymbolRef(DataRefImpl SymbolP, const ObjectFile *Owner);
bool operator==(const SymbolRef &Other) const;
- bool operator <(const SymbolRef &Other) const;
+ bool operator<(const SymbolRef &Other) const;
error_code getNext(SymbolRef &Result) const;
@@ -251,7 +251,7 @@ public:
LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner);
bool operator==(const LibraryRef &Other) const;
- bool operator <(const LibraryRef &Other) const;
+ bool operator<(const LibraryRef &Other) const;
error_code getNext(LibraryRef &Result) const;
@@ -290,8 +290,8 @@ protected:
friend class SymbolRef;
virtual error_code getSymbolNext(DataRefImpl Symb, SymbolRef &Res) const = 0;
virtual error_code getSymbolName(DataRefImpl Symb, StringRef &Res) const = 0;
- virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const =0;
- virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res) const =0;
+ virtual error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const = 0;
+ virtual error_code getSymbolFileOffset(DataRefImpl Symb, uint64_t &Res)const=0;
virtual error_code getSymbolSize(DataRefImpl Symb, uint64_t &Res) const = 0;
virtual error_code getSymbolType(DataRefImpl Symb,
SymbolRef::Type &Res) const = 0;
@@ -317,7 +317,7 @@ protected:
// A section is 'virtual' if its contents aren't present in the object image.
virtual error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const = 0;
virtual error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const = 0;
- virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const = 0;
+ virtual error_code isSectionReadOnlyData(DataRefImpl Sec, bool &Res) const =0;
virtual error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb,
bool &Result) const = 0;
virtual relocation_iterator getSectionRelBegin(DataRefImpl Sec) const = 0;
@@ -388,7 +388,6 @@ public:
static inline bool classof(const Binary *v) {
return v->isObject();
}
- static inline bool classof(const ObjectFile *v) { return true; }
public:
static ObjectFile *createCOFFObjectFile(MemoryBuffer *Object);
@@ -405,7 +404,7 @@ inline bool SymbolRef::operator==(const SymbolRef &Other) const {
return SymbolPimpl == Other.SymbolPimpl;
}
-inline bool SymbolRef::operator <(const SymbolRef &Other) const {
+inline bool SymbolRef::operator<(const SymbolRef &Other) const {
return SymbolPimpl < Other.SymbolPimpl;
}
@@ -460,7 +459,7 @@ inline bool SectionRef::operator==(const SectionRef &Other) const {
return SectionPimpl == Other.SectionPimpl;
}
-inline bool SectionRef::operator <(const SectionRef &Other) const {
+inline bool SectionRef::operator<(const SectionRef &Other) const {
return SectionPimpl < Other.SectionPimpl;
}
@@ -594,7 +593,7 @@ inline bool LibraryRef::operator==(const LibraryRef &Other) const {
return LibraryPimpl == Other.LibraryPimpl;
}
-inline bool LibraryRef::operator <(const LibraryRef &Other) const {
+inline bool LibraryRef::operator<(const LibraryRef &Other) const {
return LibraryPimpl < Other.LibraryPimpl;
}
diff --git a/include/llvm/Operator.h b/include/llvm/Operator.h
index 61ac163d4a1..bc5da8e8aa3 100644
--- a/include/llvm/Operator.h
+++ b/include/llvm/Operator.h
@@ -60,7 +60,6 @@ public:
return Instruction::UserOp1;
}
- static inline bool classof(const Operator *) { return true; }
static inline bool classof(const Instruction *) { return true; }
static inline bool classof(const ConstantExpr *) { return true; }
static inline bool classof(const Value *V) {
@@ -106,7 +105,6 @@ public:
return (SubclassOptionalData & NoSignedWrap) != 0;
}
- static inline bool classof(const OverflowingBinaryOperator *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Instruction::Add ||
I->getOpcode() == Instruction::Sub ||
@@ -180,7 +178,6 @@ public:
/// default precision.
float getFPAccuracy() const;
- static inline bool classof(const FPMathOperator *) { return true; }
static inline bool classof(const Instruction *I) {
return I->getType()->isFPOrFPVectorTy();
}
@@ -196,9 +193,6 @@ template<typename SuperClass, unsigned Opc>
class ConcreteOperator : public SuperClass {
~ConcreteOperator() LLVM_DELETED_FUNCTION;
public:
- static inline bool classof(const ConcreteOperator<SuperClass, Opc> *) {
- return true;
- }
static inline bool classof(const Instruction *I) {
return I->getOpcode() == Opc;
}
diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h
index d35febbe6d8..0c71882a77b 100644
--- a/include/llvm/Support/Casting.h
+++ b/include/llvm/Support/Casting.h
@@ -15,6 +15,7 @@
#ifndef LLVM_SUPPORT_CASTING_H
#define LLVM_SUPPORT_CASTING_H
+#include "llvm/Support/type_traits.h"
#include <cassert>
namespace llvm {
@@ -44,13 +45,23 @@ template<typename From> struct simplify_type<const From> {
// The core of the implementation of isa<X> is here; To and From should be
// the names of classes. This template can be specialized to customize the
// implementation of isa<> without rewriting it from scratch.
-template <typename To, typename From>
+template <typename To, typename From, typename Enabler = void>
struct isa_impl {
static inline bool doit(const From &Val) {
return To::classof(&Val);
}
};
+/// \brief Always allow upcasts, and perform no dynamic check for them.
+template <typename To, typename From>
+struct isa_impl<To, From,
+ typename llvm::enable_if_c<
+ llvm::is_base_of<To, From>::value
+ >::type
+ > {
+ static inline bool doit(const From &) { return true; }
+};
+
template <typename To, typename From> struct isa_impl_cl {
static inline bool doit(const From &Val) {
return isa_impl<To, From>::doit(Val);
diff --git a/include/llvm/Support/Memory.h b/include/llvm/Support/Memory.h
index 8227c84bffa..025eee7f9f3 100644
--- a/include/llvm/Support/Memory.h
+++ b/include/llvm/Support/Memory.h
@@ -98,8 +98,8 @@ namespace sys {
/// \p ErrMsg [out] returns a string describing any error that occured.
///
/// If \p Flags is MF_WRITE, the actual behavior varies
- /// with the operating system (i.e. MF_READWRITE on Windows) and the
- /// target architecture (i.e. MF_WRITE -> MF_READWRITE on i386).
+ /// with the operating system (i.e. MF_READ | MF_WRITE on Windows) and the
+ /// target architecture (i.e. MF_WRITE -> MF_READ | MF_WRITE on i386).
///
/// \r error_success if the function was successful, or an error_code
/// describing the failure if an error occurred.
diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h
index eacd651394c..12958fa173d 100644
--- a/include/llvm/Support/YAMLParser.h
+++ b/include/llvm/Support/YAMLParser.h
@@ -133,7 +133,6 @@ public:
virtual void skip() {}
unsigned int getType() const { return TypeID; }
- static inline bool classof(const Node *) { return true; }
void *operator new ( size_t Size
, BumpPtrAllocator &Alloc
@@ -166,7 +165,6 @@ class NullNode : public Node {
public:
NullNode(OwningPtr<Document> &D) : Node(NK_Null, D, StringRef()) {}
- static inline bool classof(const NullNode *) { return true; }
static inline bool classof(const Node *N) {
return N->getType() == NK_Null;
}
@@ -199,7 +197,6 @@ public:
/// This happens with escaped characters and multi-line literals.
StringRef getValue(SmallVectorImpl<char> &Storage) const;
- static inline bool classof(const ScalarNode *) { return true; }
static inline bool classof(const Node *N) {
return N->getType() == NK_Scalar;
}
@@ -246,7 +243,6 @@ public:
getValue()->skip();
}
- static inline bool classof(const KeyValueNode *) { return true; }
static inline bool classof(const Node *N) {
return N->getType() == NK_KeyValue;
}
@@ -362,7 +358,6 @@ public:
yaml::skip(*this);
}
- static inline bool classof(const MappingNode *) { return true; }
static inline bool classof(const Node *N) {
return N->getType() == NK_Mapping;
}
@@ -425,7 +420,6 @@ public:
yaml::skip(*this);
}
- static inline bool classof(const SequenceNode *) { return true; }
static inline bool classof(const Node *N) {
return N->getType() == NK_Sequence;
}
@@ -450,7 +444,6 @@ public:
StringRef getName() const { return Name; }
Node *getTarget();
- static inline bool classof(const ScalarNode *) { return true; }
static inline bool classof(const Node *N) {
return N->getType() == NK_Alias;
}
diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h
index 079dc8ce8ed..319298c1325 100644
--- a/include/llvm/TableGen/Record.h
+++ b/include/llvm/TableGen/Record.h
@@ -85,7 +85,6 @@ private:
virtual void anchor();
public:
- static bool classof(const RecTy *) { return true; }
RecTyKind getRecTyKind() const { return Kind; }
RecTy(RecTyKind K) : Kind(K), ListTy(0) {}
@@ -153,7 +152,6 @@ class BitRecTy : public RecTy {
static BitRecTy Shared;
BitRecTy() : RecTy(BitRecTyKind) {}
public:
- static bool classof(const BitRecTy *) { return true; }
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == BitRecTyKind;
}
@@ -199,7 +197,6 @@ class BitsRecTy : public RecTy {
unsigned Size;
explicit BitsRecTy(unsigned Sz) : RecTy(BitsRecTyKind), Size(Sz) {}
public:
- static bool classof(const BitsRecTy *) { return true; }
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == BitsRecTyKind;
}
@@ -248,7 +245,6 @@ class IntRecTy : public RecTy {
static IntRecTy Shared;
IntRecTy() : RecTy(IntRecTyKind) {}
public:
- static bool classof(const IntRecTy *) { return true; }
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == IntRecTyKind;
}
@@ -293,7 +289,6 @@ class StringRecTy : public RecTy {
static StringRecTy Shared;
StringRecTy() : RecTy(StringRecTyKind) {}
public:
- static bool classof(const StringRecTy *) { return true; }
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == StringRecTyKind;
}
@@ -342,7 +337,6 @@ class ListRecTy : public RecTy {
explicit ListRecTy(RecTy *T) : RecTy(ListRecTyKind), Ty(T) {}
friend ListRecTy *RecTy::getListTy();
public:
- static bool classof(const ListRecTy *) { return true; }
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == ListRecTyKind;
}
@@ -389,7 +383,6 @@ class DagRecTy : public RecTy {
static DagRecTy Shared;
DagRecTy() : RecTy(DagRecTyKind) {}
public:
- static bool classof(const DagRecTy *) { return true; }
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == DagRecTyKind;
}
@@ -436,7 +429,6 @@ class RecordRecTy : public RecTy {
explicit RecordRecTy(Record *R) : RecTy(RecordRecTyKind), Rec(R) {}
friend class Record;
public:
- static bool classof(const RecordRecTy *) { return true; }
static bool classof(const RecTy *RT) {
return RT->getRecTyKind() == RecordRecTyKind;
}
@@ -485,12 +477,53 @@ RecTy *resolveTypes(RecTy *T1, RecTy *T2);
//===----------------------------------------------------------------------===//
class Init {
+protected:
+ /// \brief Discriminator enum (for isa<>, dyn_cast<>, et al.)
+ ///
+ /// This enum is laid out by a preorder traversal of the inheritance
+ /// hierarchy, and does not contain an entry for abstract classes, as per
+ /// the recommendation in docs/HowToSetUpLLVMStyleRTTI.rst.
+ ///
+ /// We also explicitly include "first" and "last" values for each
+ /// interior node of the inheritance tree, to make it easier to read the
+ /// corresponding classof().
+ ///
+ /// We could pack these a bit tighter by not having the IK_FirstXXXInit
+ /// and IK_LastXXXInit be their own values, but that would degrade
+ /// readability for really no benefit.
+ enum InitKind {
+ IK_BitInit,
+ IK_BitsInit,
+ IK_FirstTypedInit,
+ IK_DagInit,
+ IK_DefInit,
+ IK_FieldInit,
+ IK_IntInit,
+ IK_ListInit,
+ IK_FirstOpInit,
+ IK_BinOpInit,
+ IK_TernOpInit,
+ IK_UnOpInit,
+ IK_LastOpInit,
+ IK_StringInit,
+ IK_VarInit,
+ IK_VarListElementInit,
+ IK_LastTypedInit,
+ IK_UnsetInit,
+ IK_VarBitInit
+ };
+
+private:
+ const InitKind Kind;
Init(const Init &) LLVM_DELETED_FUNCTION;
Init &operator=(const Init &) LLVM_DELETED_FUNCTION;
virtual void anchor();
+public:
+ InitKind getKind() const { return Kind; }
+
protected:
- Init(void) {}
+ explicit Init(InitKind K) : Kind(K) {}
public:
virtual ~Init() {}
@@ -591,9 +624,13 @@ class TypedInit : public Init {
TypedInit &operator=(const TypedInit &Other) LLVM_DELETED_FUNCTION;
protected:
- explicit TypedInit(RecTy *T) : Ty(T) {}
+ explicit TypedInit(InitKind K, RecTy *T) : Init(K), Ty(T) {}
public:
+ static bool classof(const Init *I) {
+ return I->getKind() >= IK_FirstTypedInit &&
+ I->getKind() <= IK_LastTypedInit;
+ }
RecTy *getType() const { return Ty; }
virtual Init *
@@ -618,12 +655,15 @@ public:
/// UnsetInit - ? - Represents an uninitialized value
///
class UnsetInit : public Init {
- UnsetInit() : Init() {}
+ UnsetInit() : Init(IK_UnsetInit) {}
UnsetInit(const UnsetInit &) LLVM_DELETED_FUNCTION;
UnsetInit &operator=(const UnsetInit &Other) LLVM_DELETED_FUNCTION;
virtual void anchor();
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_UnsetInit;
+ }
static UnsetInit *get();
virtual Init *convertInitializerTo(RecTy *Ty) const {
@@ -644,12 +684,15 @@ public:
class BitInit : public Init {
bool Value;
- explicit BitInit(bool V) : Value(V) {}
+ explicit BitInit(bool V) : Init(IK_BitInit), Value(V) {}
BitInit(const BitInit &Other) LLVM_DELETED_FUNCTION;
BitInit &operator=(BitInit &Other) LLVM_DELETED_FUNCTION;
virtual void anchor();
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_BitInit;
+ }
static BitInit *get(bool V);
bool getValue() const { return Value; }
@@ -672,12 +715,16 @@ public:
class BitsInit : public Init, public FoldingSetNode {
std::vector<Init*> Bits;
- BitsInit(ArrayRef<Init *> Range) : Bits(Range.begin(), Range.end()) {}
+ BitsInit(ArrayRef<Init *> Range)
+ : Init(IK_BitsInit), Bits(Range.begin(), Range.end()) {}
BitsInit(const BitsInit &Other) LLVM_DELETED_FUNCTION;
BitsInit &operator=(const BitsInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_BitsInit;
+ }
static BitsInit *get(ArrayRef<Init *> Range);
void Profile(FoldingSetNodeID &ID) const;
@@ -716,12 +763,16 @@ public:
class IntInit : public TypedInit {
int64_t Value;
- explicit IntInit(int64_t V) : TypedInit(IntRecTy::get()), Value(V) {}
+ explicit IntInit(int64_t V)
+ : TypedInit(IK_IntInit, IntRecTy::get()), Value(V) {}
IntInit(const IntInit &Other) LLVM_DELETED_FUNCTION;
IntInit &operator=(const IntInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_IntInit;
+ }
static IntInit *get(int64_t V);
int64_t getValue() const { return Value; }
@@ -754,13 +805,16 @@ class StringInit : public TypedInit {
std::string Value;
explicit StringInit(const std::string &V)
- : TypedInit(StringRecTy::get()), Value(V) {}
+ : TypedInit(IK_StringInit, StringRecTy::get()), Value(V) {}
StringInit(const StringInit &Other) LLVM_DELETED_FUNCTION;
StringInit &operator=(const StringInit &Other) LLVM_DELETED_FUNCTION;
virtual void anchor();
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_StringInit;
+ }
static StringInit *get(StringRef);
const std::string &getValue() const { return Value; }
@@ -794,12 +848,16 @@ public:
private:
explicit ListInit(ArrayRef<Init *> Range, RecTy *EltTy)
- : TypedInit(ListRecTy::get(EltTy)), Values(Range.begin(), Range.end()) {}
+ : TypedInit(IK_ListInit, ListRecTy::get(EltTy)),
+ Values(Range.begin(), Range.end()) {}
ListInit(const ListInit &Other) LLVM_DELETED_FUNCTION;
ListInit &operator=(const ListInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_ListInit;
+ }
static ListInit *get(ArrayRef<Init *> Range, RecTy *EltTy);
void Profile(FoldingSetNodeID &ID) const;
@@ -855,9 +913,13 @@ class OpInit : public TypedInit {
OpInit &operator=(OpInit &Other) LLVM_DELETED_FUNCTION;
protected:
- explicit OpInit(RecTy *Type) : TypedInit(Type) {}
+ explicit OpInit(InitKind K, RecTy *Type) : TypedInit(K, Type) {}
public:
+ static bool classof(const Init *I) {
+ return I->getKind() >= IK_FirstOpInit &&
+ I->getKind() <= IK_LastOpInit;
+ }
// Clone - Clone this operator, replacing arguments with the new list
virtual OpInit *clone(std::vector<Init *> &Operands) const = 0;
@@ -889,12 +951,15 @@ private:
Init *LHS;
UnOpInit(UnaryOp opc, Init *lhs, RecTy *Type)
- : OpInit(Type), Opc(opc), LHS(lhs) {}
+ : OpInit(IK_UnOpInit, Type), Opc(opc), LHS(lhs) {}
UnOpInit(const UnOpInit &Other) LLVM_DELETED_FUNCTION;
UnOpInit &operator=(const UnOpInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_UnOpInit;
+ }
static UnOpInit *get(UnaryOp opc, Init *lhs, RecTy *Type);
// Clone - Clone this operator, replacing arguments with the new list
@@ -932,12 +997,15 @@ private:
Init *LHS, *RHS;
BinOpInit(BinaryOp opc, Init *lhs, Init *rhs, RecTy *Type) :
- OpInit(Type), Opc(opc), LHS(lhs), RHS(rhs) {}
+ OpInit(IK_BinOpInit, Type), Opc(opc), LHS(lhs), RHS(rhs) {}
BinOpInit(const BinOpInit &Other) LLVM_DELETED_FUNCTION;
BinOpInit &operator=(const BinOpInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_BinOpInit;
+ }
static BinOpInit *get(BinaryOp opc, Init *lhs, Init *rhs,
RecTy *Type);
@@ -982,12 +1050,15 @@ private:
TernOpInit(TernaryOp opc, Init *lhs, Init *mhs, Init *rhs,
RecTy *Type) :
- OpInit(Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {}
+ OpInit(IK_TernOpInit, Type), Opc(opc), LHS(lhs), MHS(mhs), RHS(rhs) {}
TernOpInit(const TernOpInit &Other) LLVM_DELETED_FUNCTION;
TernOpInit &operator=(const TernOpInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_TernOpInit;
+ }
static TernOpInit *get(TernaryOp opc, Init *lhs,
Init *mhs, Init *rhs,
RecTy *Type);
@@ -1036,14 +1107,17 @@ class VarInit : public TypedInit {
Init *VarName;
explicit VarInit(const std::string &VN, RecTy *T)
- : TypedInit(T), VarName(StringInit::get(VN)) {}
+ : TypedInit(IK_VarInit, T), VarName(StringInit::get(VN)) {}
explicit VarInit(Init *VN, RecTy *T)
- : TypedInit(T), VarName(VN) {}
+ : TypedInit(IK_VarInit, T), VarName(VN) {}
VarInit(const VarInit &Other) LLVM_DELETED_FUNCTION;
VarInit &operator=(const VarInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_VarInit;
+ }
static VarInit *get(const std::string &VN, RecTy *T);
static VarInit *get(Init *VN, RecTy *T);
@@ -1083,7 +1157,7 @@ class VarBitInit : public Init {
TypedInit *TI;
unsigned Bit;
- VarBitInit(TypedInit *T, unsigned B) : TI(T), Bit(B) {
+ VarBitInit(TypedInit *T, unsigned B) : Init(IK_VarBitInit), TI(T), Bit(B) {
assert(T->getType() &&
(isa<IntRecTy>(T->getType()) ||
(isa<BitsRecTy>(T->getType()) &&
@@ -1095,6 +1169,9 @@ class VarBitInit : public Init {
VarBitInit &operator=(const VarBitInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_VarBitInit;
+ }
static VarBitInit *get(TypedInit *T, unsigned B);
virtual Init *convertInitializerTo(RecTy *Ty) const {
@@ -1120,8 +1197,9 @@ class VarListElementInit : public TypedInit {
unsigned Element;
VarListElementInit(TypedInit *T, unsigned E)
- : TypedInit(cast<ListRecTy>(T->getType())->getElementType()),
- TI(T), Element(E) {
+ : TypedInit(IK_VarListElementInit,
+ cast<ListRecTy>(T->getType())->getElementType()),
+ TI(T), Element(E) {
assert(T->getType() && isa<ListRecTy>(T->getType()) &&
"Illegal VarBitInit expression!");
}
@@ -1130,6 +1208,9 @@ class VarListElementInit : public TypedInit {
void operator=(const VarListElementInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_VarListElementInit;
+ }
static VarListElementInit *get(TypedInit *T, unsigned E);
virtual Init *convertInitializerTo(RecTy *Ty) const {
@@ -1157,13 +1238,16 @@ public:
class DefInit : public TypedInit {
Record *Def;
- DefInit(Record *D, RecordRecTy *T) : TypedInit(T), Def(D) {}
+ DefInit(Record *D, RecordRecTy *T) : TypedInit(IK_DefInit, T), Def(D) {}
friend class Record;
DefInit(const DefInit &Other) LLVM_DELETED_FUNCTION;
DefInit &operator=(const DefInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_DefInit;
+ }
static DefInit *get(Record*);
virtual Init *convertInitializerTo(RecTy *Ty) const {
@@ -1201,7 +1285,7 @@ class FieldInit : public TypedInit {
std::string FieldName; // Field we are accessing
FieldInit(Init *R, const std::string &FN)
- : TypedInit(R->getFieldType(FN)), Rec(R), FieldName(FN) {
+ : TypedInit(IK_FieldInit, R->getFieldType(FN)), Rec(R), FieldName(FN) {
assert(getType() && "FieldInit with non-record type!");
}
@@ -1209,6 +1293,9 @@ class FieldInit : public TypedInit {
FieldInit &operator=(const FieldInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_FieldInit;
+ }
static FieldInit *get(Init *R, const std::string &FN);
static FieldInit *get(Init *R, const Init *FN);
@@ -1242,7 +1329,7 @@ class DagInit : public TypedInit, public FoldingSetNode {
DagInit(Init *V, const std::string &VN,
ArrayRef<Init *> ArgRange,
ArrayRef<std::string> NameRange)
- : TypedInit(DagRecTy::get()), Val(V), ValName(VN),
+ : TypedInit(IK_DagInit, DagRecTy::get()), Val(V), ValName(VN),
Args(ArgRange.begin(), ArgRange.end()),
ArgNames(NameRange.begin(), NameRange.end()) {}
@@ -1250,6 +1337,9 @@ class DagInit : public TypedInit, public FoldingSetNode {
DagInit &operator=(const DagInit &Other) LLVM_DELETED_FUNCTION;
public:
+ static bool classof(const Init *I) {
+ return I->getKind() == IK_DagInit;
+ }
static DagInit *get(Init *V, const std::string &VN,
ArrayRef<Init *> ArgRange,
ArrayRef<std::string> NameRange);
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index b3149e960a8..ad85c7e13ae 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -146,7 +146,7 @@ public:
// Return the pointer type for the given address space, defaults to
// the pointer type from the data layout.
// FIXME: The default needs to be removed once all the code is updated.
- virtual MVT getPointerTy(uint32_t addrspace = 0) const { return PointerTy; }
+ virtual MVT getPointerTy(uint32_t AS = 0) const { return PointerTy; }
virtual MVT getShiftAmountTy(EVT LHSTy) const;
/// isSelectExpensive - Return true if the select operation is expensive for
@@ -1366,7 +1366,7 @@ public:
}
/// HandleByVal - Target-specific cleanup for formal ByVal parameters.
- virtual void HandleByVal(CCState *, unsigned &) const {}
+ virtual void HandleByVal(CCState *, unsigned &, unsigned) const {}
/// CanLowerReturn - This hook should be implemented to check whether the
/// return values described by the Outs array can fit into the return
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index 988916f9d95..18e589e2bc0 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -17,6 +17,8 @@
#include "llvm/Pass.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/TargetTransformInfo.h"
+#include "llvm/Target/TargetTransformImpl.h"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <string>
@@ -107,6 +109,10 @@ public:
virtual const TargetLowering *getTargetLowering() const { return 0; }
virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const{ return 0; }
virtual const DataLayout *getDataLayout() const { return 0; }
+ virtual const ScalarTargetTransformInfo*
+ getScalarTargetTransformInfo() const { return 0; }
+ virtual const VectorTargetTransformInfo*
+ getVectorTargetTransformInfo() const { return 0; }
/// getMCAsmInfo - Return target specific asm information.
///
diff --git a/include/llvm/Target/TargetTransformImpl.h b/include/llvm/Target/TargetTransformImpl.h
new file mode 100644
index 00000000000..7648f4f935c
--- /dev/null
+++ b/include/llvm/Target/TargetTransformImpl.h
@@ -0,0 +1,54 @@
+//=- llvm/Target/TargetTransformImpl.h - Target Loop Trans Info----*- 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 target-specific implementations of the
+// TargetTransform interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_TARGET_TRANSFORMATION_IMPL_H
+#define LLVM_TARGET_TARGET_TRANSFORMATION_IMPL_H
+
+#include "llvm/TargetTransformInfo.h"
+
+namespace llvm {
+
+class TargetLowering;
+
+/// ScalarTargetTransformInfo - This is a default implementation for the
+/// ScalarTargetTransformInfo interface. Different targets can implement
+/// this interface differently.
+class ScalarTargetTransformImpl : public ScalarTargetTransformInfo {
+private:
+ const TargetLowering *TLI;
+
+public:
+ /// Ctor
+ explicit ScalarTargetTransformImpl(const TargetLowering *TL) : TLI(TL) {}
+
+ virtual bool isLegalAddImmediate(int64_t imm) const;
+
+ virtual bool isLegalICmpImmediate(int64_t imm) const;
+
+ virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const;
+
+ virtual bool isTruncateFree(Type *Ty1, Type *Ty2) const;
+
+ virtual bool isTypeLegal(Type *Ty) const;
+
+ virtual unsigned getJumpBufAlignment() const;
+
+ virtual unsigned getJumpBufSize() const;
+};
+
+class VectorTargetTransformImpl : public VectorTargetTransformInfo { };
+
+} // end llvm namespace
+
+#endif
diff --git a/include/llvm/TargetTransformInfo.h b/include/llvm/TargetTransformInfo.h
new file mode 100644
index 00000000000..82fc14dbd74
--- /dev/null
+++ b/include/llvm/TargetTransformInfo.h
@@ -0,0 +1,128 @@
+//===- llvm/Transforms/TargetTransformInfo.h --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass exposes codegen information to IR-level passes. Every
+// transformation that uses codegen information is broken into three parts:
+// 1. The IR-level analysis pass.
+// 2. The IR-level transformation interface which provides the needed
+// information.
+// 3. Codegen-level implementation which uses target-specific hooks.
+//
+// This file defines #2, which is the interface that IR-level transformations
+// use for querying the codegen.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_TARGET_TRANSFORM_INTERFACE
+#define LLVM_TRANSFORMS_TARGET_TRANSFORM_INTERFACE
+
+#include "llvm/Pass.h"
+#include "llvm/AddressingMode.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Type.h"
+
+namespace llvm {
+
+class ScalarTargetTransformInfo;
+class VectorTargetTransformInfo;
+
+/// TargetTransformInfo - This pass provides access to the codegen
+/// interfaces that are needed for IR-level transformations.
+class TargetTransformInfo : public ImmutablePass {
+private:
+ const ScalarTargetTransformInfo *STTI;
+ const VectorTargetTransformInfo *VTTI;
+public:
+ /// Default ctor.
+ ///
+ /// @note This has to exist, because this is a pass, but it should never be
+ /// used.
+ TargetTransformInfo();
+
+ explicit TargetTransformInfo(const ScalarTargetTransformInfo* S,
+ const VectorTargetTransformInfo *V)
+ : ImmutablePass(ID), STTI(S), VTTI(V) {
+ initializeTargetTransformInfoPass(*PassRegistry::getPassRegistry());
+ }
+
+ TargetTransformInfo(const TargetTransformInfo &T) :
+ ImmutablePass(ID), STTI(T.STTI), VTTI(T.VTTI) { }
+
+ const ScalarTargetTransformInfo* getScalarTargetTransformInfo() {
+ return STTI;
+ }
+ const VectorTargetTransformInfo* getVectorTargetTransformInfo() {
+ return VTTI;
+ }
+
+ /// Pass identification, replacement for typeid.
+ static char ID;
+};
+
+// ---------------------------------------------------------------------------//
+// The classes below are inherited and implemented by target-specific classes
+// in the codegen.
+// ---------------------------------------------------------------------------//
+
+/// ScalarTargetTransformInfo - This interface is used by IR-level passes
+/// that need target-dependent information for generic scalar transformations.
+/// LSR, and LowerInvoke use this interface.
+class ScalarTargetTransformInfo {
+public:
+ virtual ~ScalarTargetTransformInfo() {}
+
+ /// isLegalAddImmediate - Return true if the specified immediate is legal
+ /// add immediate, that is the target has add instructions which can add
+ /// a register with the immediate without having to materialize the
+ /// immediate into a register.
+ virtual bool isLegalAddImmediate(int64_t) const {
+ return false;
+ }
+ /// isLegalICmpImmediate - Return true if the specified immediate is legal
+ /// icmp immediate, that is the target has icmp instructions which can compare
+ /// a register against the immediate without having to materialize the
+ /// immediate into a register.
+ virtual bool isLegalICmpImmediate(int64_t) const {
+ return false;
+ }
+ /// isLegalAddressingMode - Return true if the addressing mode represented by
+ /// AM is legal for this target, for a load/store of the specified type.
+ /// The type may be VoidTy, in which case only return true if the addressing
+ /// mode is legal for a load/store of any legal type.
+ /// TODO: Handle pre/postinc as well.
+ virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const {
+ return false;
+ }
+ /// isTruncateFree - Return true if it's free to truncate a value of
+ /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in
+ /// register EAX to i16 by referencing its sub-register AX.
+ virtual bool isTruncateFree(Type * /*Ty1*/, Type * /*Ty2*/) const {
+ return false;
+ }
+ /// Is this type legal.
+ virtual bool isTypeLegal(Type *Ty) const {
+ return false;
+ }
+ /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes
+ virtual unsigned getJumpBufAlignment() const {
+ return 0;
+ }
+ /// getJumpBufSize - returns the target's jmp_buf size in bytes.
+ virtual unsigned getJumpBufSize() const {
+ return 0;
+ }
+};
+
+class VectorTargetTransformInfo {
+ // TODO: define an interface for VectorTargetTransformInfo.
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h
index 4b0c448acfc..8e63aaa4e87 100644
--- a/include/llvm/Transforms/Instrumentation.h
+++ b/include/llvm/Transforms/Instrumentation.h
@@ -34,7 +34,7 @@ ModulePass *createGCOVProfilerPass(bool EmitNotes = true, bool EmitData = true,
bool UseExtraChecksum = false);
// Insert AddressSanitizer (address sanity checking) instrumentation
-ModulePass *createAddressSanitizerPass();
+FunctionPass *createAddressSanitizerPass();
// Insert ThreadSanitizer (race detection) instrumentation
FunctionPass *createThreadSanitizerPass();
diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h
index a5d8eed7462..3b665bf4b68 100644
--- a/include/llvm/Transforms/Scalar.h
+++ b/include/llvm/Transforms/Scalar.h
@@ -119,7 +119,7 @@ Pass *createLICMPass();
// optional parameter used to consult the target machine whether certain
// transformations are profitable.
//
-Pass *createLoopStrengthReducePass(const TargetLowering *TLI = 0);
+Pass *createLoopStrengthReducePass();
Pass *createGlobalMergePass(const TargetLowering *TLI = 0);
@@ -249,9 +249,8 @@ extern char &LowerSwitchID;
// purpose "my LLVM-to-LLVM pass doesn't support the invoke instruction yet"
// lowering pass.
//
-FunctionPass *createLowerInvokePass(const TargetLowering *TLI = 0);
-FunctionPass *createLowerInvokePass(const TargetLowering *TLI,
- bool useExpensiveEHSupport);
+FunctionPass *createLowerInvokePass();
+FunctionPass *createLowerInvokePass(bool useExpensiveEHSupport);
extern char &LowerInvokePassID;
//===----------------------------------------------------------------------===//
diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h
index 21dd3fbe110..fd1b5556ef2 100644
--- a/include/llvm/Transforms/Utils/Local.h
+++ b/include/llvm/Transforms/Utils/Local.h
@@ -186,7 +186,8 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP,
bool isInBounds = cast<GEPOperator>(GEP)->isInBounds() && !NoAssumptions;
// Build a mask for high order bits.
- unsigned IntPtrWidth = TD.getPointerSizeInBits();
+ unsigned AS = cast<GEPOperator>(GEP)->getPointerAddressSpace();
+ unsigned IntPtrWidth = TD.getPointerSizeInBits(AS);
uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth);
for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e;
diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
new file mode 100644
index 00000000000..5db2d001814
--- /dev/null
+++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h
@@ -0,0 +1,43 @@
+//===- SimplifyLibCalls.h - Library call simplifier -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file exposes an interface to build some C language libcalls for
+// optimization passes that need to call the various functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
+#define LLVM_TRANSFORMS_UTILS_SIMPLIFYLIBCALLS_H
+
+namespace llvm {
+ class Value;
+ class CallInst;
+ class DataLayout;
+ class TargetLibraryInfo;
+ class LibCallSimplifierImpl;
+
+ /// LibCallSimplifier - This class implements a collection of optimizations
+ /// that replace well formed calls to library functions with a more optimal
+ /// form. For example, replacing 'printf("Hello!")' with 'puts("Hello!")'.
+ class LibCallSimplifier {
+ /// Impl - A pointer to the actual implementation of the library call
+ /// simplifier.
+ LibCallSimplifierImpl *Impl;
+ public:
+ LibCallSimplifier(const DataLayout *TD, const TargetLibraryInfo *TLI);
+ virtual ~LibCallSimplifier();
+
+ /// optimizeCall - Take the given call instruction and return a more
+ /// optimal value to replace the instruction with or 0 if a more
+ /// optimal form can't be found.
+ Value *optimizeCall(CallInst *CI);
+ };
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Type.h b/include/llvm/Type.h
index 8e66ea86094..5a867045af8 100644
--- a/include/llvm/Type.h
+++ b/include/llvm/Type.h
@@ -389,9 +389,6 @@ public:
static PointerType *getInt32PtrTy(LLVMContext &C, unsigned AS = 0);
static PointerType *getInt64PtrTy(LLVMContext &C, unsigned AS = 0);
- /// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Type *) { return true; }
-
/// getPointerTo - Return a pointer to the current type. This is equivalent
/// to PointerType::get(Foo, AddrSpace).
PointerType *getPointerTo(unsigned AddrSpace = 0);
diff --git a/include/llvm/User.h b/include/llvm/User.h
index ade3676260b..df303d0dd5f 100644
--- a/include/llvm/User.h
+++ b/include/llvm/User.h
@@ -176,7 +176,6 @@ public:
void replaceUsesOfWith(Value *From, Value *To);
// Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const User *) { return true; }
static inline bool classof(const Value *V) {
return isa<Instruction>(V) || isa<Constant>(V);
}
diff --git a/include/llvm/Value.h b/include/llvm/Value.h
index 6560a420bf6..5b19435ebaf 100644
--- a/include/llvm/Value.h
+++ b/include/llvm/Value.h
@@ -257,11 +257,6 @@ public:
/// hasValueHandle - Return true if there is a value handle associated with
/// this value.
bool hasValueHandle() const { return HasValueHandle; }
-
- // Methods for support type inquiry through isa, cast, and dyn_cast:
- static inline bool classof(const Value *) {
- return true; // Values are always values.
- }
/// stripPointerCasts - This method strips off any unneeded pointer casts and
/// all-zero GEPs from the specified value, returning the original uncasted
diff --git a/lib/Analysis/Analysis.cpp b/lib/Analysis/Analysis.cpp
index 87a75fd3b11..588206e9159 100644
--- a/lib/Analysis/Analysis.cpp
+++ b/lib/Analysis/Analysis.cpp
@@ -31,6 +31,7 @@ void llvm::initializeAnalysis(PassRegistry &Registry) {
initializeCFGOnlyViewerPass(Registry);
initializeCFGOnlyPrinterPass(Registry);
initializePrintDbgInfoPass(Registry);
+ initializeDependenceAnalysisPass(Registry);
initializeDominanceFrontierPass(Registry);
initializeDomViewerPass(Registry);
initializeDomPrinterPass(Registry);
diff --git a/lib/Analysis/BasicAliasAnalysis.cpp b/lib/Analysis/BasicAliasAnalysis.cpp
index 263bfc031fc..36903f94e25 100644
--- a/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/lib/Analysis/BasicAliasAnalysis.cpp
@@ -286,7 +286,8 @@ DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
V = GEPOp->getOperand(0);
continue;
}
-
+
+ unsigned AS = GEPOp->getPointerAddressSpace();
// Walk the indices of the GEP, accumulating them into BaseOff/VarIndices.
gep_type_iterator GTI = gep_type_begin(GEPOp);
for (User::const_op_iterator I = GEPOp->op_begin()+1,
@@ -315,7 +316,7 @@ DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
// If the integer type is smaller than the pointer size, it is implicitly
// sign extended to pointer size.
unsigned Width = cast<IntegerType>(Index->getType())->getBitWidth();
- if (TD->getPointerSizeInBits() > Width)
+ if (TD->getPointerSizeInBits(AS) > Width)
Extension = EK_SignExt;
// Use GetLinearExpression to decompose the index into a C1*V+C2 form.
@@ -344,7 +345,7 @@ DecomposeGEPExpression(const Value *V, int64_t &BaseOffs,
// Make sure that we have a scale that makes sense for this target's
// pointer size.
- if (unsigned ShiftBits = 64-TD->getPointerSizeInBits()) {
+ if (unsigned ShiftBits = 64-TD->getPointerSizeInBits(AS)) {
Scale <<= ShiftBits;
Scale = (int64_t)Scale >> ShiftBits;
}
diff --git a/lib/Analysis/CMakeLists.txt b/lib/Analysis/CMakeLists.txt
index e461848e861..3ce888fefa4 100644
--- a/lib/Analysis/CMakeLists.txt
+++ b/lib/Analysis/CMakeLists.txt
@@ -13,6 +13,7 @@ add_llvm_library(LLVMAnalysis
CodeMetrics.cpp
ConstantFolding.cpp
DbgInfoPrinter.cpp
+ DependenceAnalysis.cpp
DomPrinter.cpp
DominanceFrontier.cpp
IVUsers.cpp
diff --git a/lib/Analysis/CodeMetrics.cpp b/lib/Analysis/CodeMetrics.cpp
index 651a54be1b9..d6692684960 100644
--- a/lib/Analysis/CodeMetrics.cpp
+++ b/lib/Analysis/CodeMetrics.cpp
@@ -91,14 +91,16 @@ bool llvm::isInstructionFree(const Instruction *I, const DataLayout *TD) {
// which doesn't contain values outside the range of a pointer.
if (isa<IntToPtrInst>(CI) && TD &&
TD->isLegalInteger(Op->getType()->getScalarSizeInBits()) &&
- Op->getType()->getScalarSizeInBits() <= TD->getPointerSizeInBits())
+ Op->getType()->getScalarSizeInBits() <= TD->getPointerSizeInBits(
+ cast<IntToPtrInst>(CI)->getAddressSpace()))
return true;
// A ptrtoint cast is free so long as the result is large enough to store
// the pointer, and a legal integer type.
if (isa<PtrToIntInst>(CI) && TD &&
TD->isLegalInteger(Op->getType()->getScalarSizeInBits()) &&
- Op->getType()->getScalarSizeInBits() >= TD->getPointerSizeInBits())
+ Op->getType()->getScalarSizeInBits() >= TD->getPointerSizeInBits(
+ cast<PtrToIntInst>(CI)->getPointerAddressSpace()))
return true;
// trunc to a native type is free (assuming the target has compare and
diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp
index b7bf044a368..146897ad675 100644
--- a/lib/Analysis/ConstantFolding.cpp
+++ b/lib/Analysis/ConstantFolding.cpp
@@ -916,10 +916,11 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
if (TD && CE->getOpcode() == Instruction::IntToPtr) {
Constant *Input = CE->getOperand(0);
unsigned InWidth = Input->getType()->getScalarSizeInBits();
- if (TD->getPointerSizeInBits() < InWidth) {
+ unsigned AS = cast<PointerType>(CE->getType())->getAddressSpace();
+ if (TD->getPointerSizeInBits(AS) < InWidth) {
Constant *Mask =
ConstantInt::get(CE->getContext(), APInt::getLowBitsSet(InWidth,
- TD->getPointerSizeInBits()));
+ TD->getPointerSizeInBits(AS)));
Input = ConstantExpr::getAnd(Input, Mask);
}
// Do a zext or trunc to get to the dest size.
@@ -932,9 +933,10 @@ Constant *llvm::ConstantFoldInstOperands(unsigned Opcode, Type *DestTy,
// the int size is >= the ptr size. This requires knowing the width of a
// pointer, so it can't be done in ConstantExpr::getCast.
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ops[0]))
- if (TD &&
- TD->getPointerSizeInBits() <= CE->getType()->getScalarSizeInBits() &&
- CE->getOpcode() == Instruction::PtrToInt)
+ if (TD && CE->getOpcode() == Instruction::PtrToInt &&
+ TD->getPointerSizeInBits(
+ cast<PointerType>(CE->getOperand(0)->getType())->getAddressSpace())
+ <= CE->getType()->getScalarSizeInBits())
return FoldBitCast(CE->getOperand(0), DestTy, *TD);
return ConstantExpr::getCast(Opcode, Ops[0], DestTy);
diff --git a/lib/Analysis/DependenceAnalysis.cpp b/lib/Analysis/DependenceAnalysis.cpp
new file mode 100644
index 00000000000..016fe396e7d
--- /dev/null
+++ b/lib/Analysis/DependenceAnalysis.cpp
@@ -0,0 +1,3781 @@
+//===-- DependenceAnalysis.cpp - DA Implementation --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// DependenceAnalysis is an LLVM pass that analyses dependences between memory
+// accesses. Currently, it is an (incomplete) implementation of the approach
+// described in
+//
+// Practical Dependence Testing
+// Goff, Kennedy, Tseng
+// PLDI 1991
+//
+// There's a single entry point that analyzes the dependence between a pair
+// of memory references in a function, returning either NULL, for no dependence,
+// or a more-or-less detailed description of the dependence between them.
+//
+// Currently, the implementation cannot propagate constraints between
+// coupled RDIV subscripts and lacks a multi-subscript MIV test.
+// Both of these are conservative weaknesses;
+// that is, not a source of correctness problems.
+//
+// The implementation depends on the GEP instruction to
+// differentiate subscripts. Since Clang linearizes subscripts
+// for most arrays, we give up some precision (though the existing MIV tests
+// will help). We trust that the GEP instruction will eventually be extended.
+// In the meantime, we should explore Maslov's ideas about delinearization.
+//
+// We should pay some careful attention to the possibility of integer overflow
+// in the implementation of the various tests. This could happen with Add,
+// Subtract, or Multiply, with both APInt's and SCEV's.
+//
+// Some non-linear subscript pairs can be handled by the GCD test
+// (and perhaps other tests).
+// Should explore how often these things occur.
+//
+// Finally, it seems like certain test cases expose weaknesses in the SCEV
+// simplification, especially in the handling of sign and zero extensions.
+// It could be useful to spend time exploring these.
+//
+// Please note that this is work in progress and the interface is subject to
+// change.
+//
+//===----------------------------------------------------------------------===//
+// //
+// In memory of Ken Kennedy, 1945 - 2007 //
+// //
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "da"
+
+#include "llvm/Analysis/DependenceAnalysis.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Instructions.h"
+#include "llvm/Operator.h"
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/InstIterator.h"
+
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// statistics
+
+STATISTIC(TotalArrayPairs, "Array pairs tested");
+STATISTIC(SeparableSubscriptPairs, "Separable subscript pairs");
+STATISTIC(CoupledSubscriptPairs, "Coupled subscript pairs");
+STATISTIC(NonlinearSubscriptPairs, "Nonlinear subscript pairs");
+STATISTIC(ZIVapplications, "ZIV applications");
+STATISTIC(ZIVindependence, "ZIV independence");
+STATISTIC(StrongSIVapplications, "Strong SIV applications");
+STATISTIC(StrongSIVsuccesses, "Strong SIV successes");
+STATISTIC(StrongSIVindependence, "Strong SIV independence");
+STATISTIC(WeakCrossingSIVapplications, "Weak-Crossing SIV applications");
+STATISTIC(WeakCrossingSIVsuccesses, "Weak-Crossing SIV successes");
+STATISTIC(WeakCrossingSIVindependence, "Weak-Crossing SIV independence");
+STATISTIC(ExactSIVapplications, "Exact SIV applications");
+STATISTIC(ExactSIVsuccesses, "Exact SIV successes");
+STATISTIC(ExactSIVindependence, "Exact SIV independence");
+STATISTIC(WeakZeroSIVapplications, "Weak-Zero SIV applications");
+STATISTIC(WeakZeroSIVsuccesses, "Weak-Zero SIV successes");
+STATISTIC(WeakZeroSIVindependence, "Weak-Zero SIV independence");
+STATISTIC(ExactRDIVapplications, "Exact RDIV applications");
+STATISTIC(ExactRDIVindependence, "Exact RDIV independence");
+STATISTIC(SymbolicRDIVapplications, "Symbolic RDIV applications");
+STATISTIC(SymbolicRDIVindependence, "Symbolic RDIV independence");
+STATISTIC(DeltaApplications, "Delta applications");
+STATISTIC(DeltaSuccesses, "Delta successes");
+STATISTIC(DeltaIndependence, "Delta independence");
+STATISTIC(DeltaPropagations, "Delta propagations");
+STATISTIC(GCDapplications, "GCD applications");
+STATISTIC(GCDsuccesses, "GCD successes");
+STATISTIC(GCDindependence, "GCD independence");
+STATISTIC(BanerjeeApplications, "Banerjee applications");
+STATISTIC(BanerjeeIndependence, "Banerjee independence");
+STATISTIC(BanerjeeSuccesses, "Banerjee successes");
+
+//===----------------------------------------------------------------------===//
+// basics
+
+INITIALIZE_PASS_BEGIN(DependenceAnalysis, "da",
+ "Dependence Analysis", true, true)
+INITIALIZE_PASS_DEPENDENCY(LoopInfo)
+INITIALIZE_PASS_DEPENDENCY(ScalarEvolution)
+INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
+INITIALIZE_PASS_END(DependenceAnalysis, "da",
+ "Dependence Analysis", true, true)
+
+char DependenceAnalysis::ID = 0;
+
+
+FunctionPass *llvm::createDependenceAnalysisPass() {
+ return new DependenceAnalysis();
+}
+
+
+bool DependenceAnalysis::runOnFunction(Function &F) {
+ this->F = &F;
+ AA = &getAnalysis<AliasAnalysis>();
+ SE = &getAnalysis<ScalarEvolution>();
+ LI = &getAnalysis<LoopInfo>();
+ return false;
+}
+
+
+void DependenceAnalysis::releaseMemory() {
+}
+
+
+void DependenceAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesAll();
+ AU.addRequiredTransitive<AliasAnalysis>();
+ AU.addRequiredTransitive<ScalarEvolution>();
+ AU.addRequiredTransitive<LoopInfo>();
+}
+
+
+// Used to test the dependence analyzer.
+// Looks through the function, noting the first store instruction
+// and the first load instruction
+// (which always follows the first load in our tests).
+// Calls depends() and prints out the result.
+// Ignores all other instructions.
+static
+void dumpExampleDependence(raw_ostream &OS, Function *F,
+ DependenceAnalysis *DA) {
+ for (inst_iterator SrcI = inst_begin(F), SrcE = inst_end(F);
+ SrcI != SrcE; ++SrcI) {
+ if (const StoreInst *Src = dyn_cast<StoreInst>(&*SrcI)) {
+ for (inst_iterator DstI = SrcI, DstE = inst_end(F);
+ DstI != DstE; ++DstI) {
+ if (const LoadInst *Dst = dyn_cast<LoadInst>(&*DstI)) {
+ OS << "da analyze - ";
+ if (Dependence *D = DA->depends(Src, Dst, true)) {
+ D->dump(OS);
+ for (unsigned Level = 1; Level <= D->getLevels(); Level++) {
+ if (D->isSplitable(Level)) {
+ OS << "da analyze - split level = " << Level;
+ OS << ", iteration = " << *DA->getSplitIteration(D, Level);
+ OS << "!\n";
+ }
+ }
+ delete D;
+ }
+ else
+ OS << "none!\n";
+ return;
+ }
+ }
+ }
+ }
+}
+
+
+void DependenceAnalysis::print(raw_ostream &OS, const Module*) const {
+ dumpExampleDependence(OS, F, const_cast<DependenceAnalysis *>(this));
+}
+
+//===----------------------------------------------------------------------===//
+// Dependence methods
+
+// Returns true if this is an input dependence.
+bool Dependence::isInput() const {
+ return Src->mayReadFromMemory() && Dst->mayReadFromMemory();
+}
+
+
+// Returns true if this is an output dependence.
+bool Dependence::isOutput() const {
+ return Src->mayWriteToMemory() && Dst->mayWriteToMemory();
+}
+
+
+// Returns true if this is an flow (aka true) dependence.
+bool Dependence::isFlow() const {
+ return Src->mayWriteToMemory() && Dst->mayReadFromMemory();
+}
+
+
+// Returns true if this is an anti dependence.
+bool Dependence::isAnti() const {
+ return Src->mayReadFromMemory() && Dst->mayWriteToMemory();
+}
+
+
+// Returns true if a particular level is scalar; that is,
+// if no subscript in the source or destination mention the induction
+// variable associated with the loop at this level.
+// Leave this out of line, so it will serve as a virtual method anchor
+bool Dependence::isScalar(unsigned level) const {
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// FullDependence methods
+
+FullDependence::FullDependence(const Instruction *Source,
+ const Instruction *Destination,
+ bool PossiblyLoopIndependent,
+ unsigned CommonLevels) :
+ Dependence(Source, Destination),
+ Levels(CommonLevels),
+ LoopIndependent(PossiblyLoopIndependent) {
+ Consistent = true;
+ DV = CommonLevels ? new DVEntry[CommonLevels] : NULL;
+}
+
+// The rest are simple getters that hide the implementation.
+
+// getDirection - Returns the direction associated with a particular level.
+unsigned FullDependence::getDirection(unsigned Level) const {
+ assert(0 < Level && Level <= Levels && "Level out of range");
+ return DV[Level - 1].Direction;
+}
+
+
+// Returns the distance (or NULL) associated with a particular level.
+const SCEV *FullDependence::getDistance(unsigned Level) const {
+ assert(0 < Level && Level <= Levels && "Level out of range");
+ return DV[Level - 1].Distance;
+}
+
+
+// Returns true if a particular level is scalar; that is,
+// if no subscript in the source or destination mention the induction
+// variable associated with the loop at this level.
+bool FullDependence::isScalar(unsigned Level) const {
+ assert(0 < Level && Level <= Levels && "Level out of range");
+ return DV[Level - 1].Scalar;
+}
+
+
+// Returns true if peeling the first iteration from this loop
+// will break this dependence.
+bool FullDependence::isPeelFirst(unsigned Level) const {
+ assert(0 < Level && Level <= Levels && "Level out of range");
+ return DV[Level - 1].PeelFirst;
+}
+
+
+// Returns true if peeling the last iteration from this loop
+// will break this dependence.
+bool FullDependence::isPeelLast(unsigned Level) const {
+ assert(0 < Level && Level <= Levels && "Level out of range");
+ return DV[Level - 1].PeelLast;
+}
+
+
+// Returns true if splitting this loop will break the dependence.
+bool FullDependence::isSplitable(unsigned Level) const {
+ assert(0 < Level && Level <= Levels && "Level out of range");
+ return DV[Level - 1].Splitable;
+}
+
+
+//===----------------------------------------------------------------------===//
+// DependenceAnalysis::Constraint methods
+
+// If constraint is a point <X, Y>, returns X.
+// Otherwise assert.
+const SCEV *DependenceAnalysis::Constraint::getX() const {
+ assert(Kind == Point && "Kind should be Point");
+ return A;
+}
+
+
+// If constraint is a point <X, Y>, returns Y.
+// Otherwise assert.
+const SCEV *DependenceAnalysis::Constraint::getY() const {
+ assert(Kind == Point && "Kind should be Point");
+ return B;
+}
+
+
+// If constraint is a line AX + BY = C, returns A.
+// Otherwise assert.
+const SCEV *DependenceAnalysis::Constraint::getA() const {
+ assert((Kind == Line || Kind == Distance) &&
+ "Kind should be Line (or Distance)");
+ return A;
+}
+
+
+// If constraint is a line AX + BY = C, returns B.
+// Otherwise assert.
+const SCEV *DependenceAnalysis::Constraint::getB() const {
+ assert((Kind == Line || Kind == Distance) &&
+ "Kind should be Line (or Distance)");
+ return B;
+}
+
+
+// If constraint is a line AX + BY = C, returns C.
+// Otherwise assert.
+const SCEV *DependenceAnalysis::Constraint::getC() const {
+ assert((Kind == Line || Kind == Distance) &&
+ "Kind should be Line (or Distance)");
+ return C;
+}
+
+
+// If constraint is a distance, returns D.
+// Otherwise assert.
+const SCEV *DependenceAnalysis::Constraint::getD() const {
+ assert(Kind == Distance && "Kind should be Distance");
+ return SE->getNegativeSCEV(C);
+}
+
+
+// Returns the loop associated with this constraint.
+const Loop *DependenceAnalysis::Constraint::getAssociatedLoop() const {
+ assert((Kind == Distance || Kind == Line || Kind == Point) &&
+ "Kind should be Distance, Line, or Point");
+ return AssociatedLoop;
+}
+
+
+void DependenceAnalysis::Constraint::setPoint(const SCEV *X,
+ const SCEV *Y,
+ const Loop *CurLoop) {
+ Kind = Point;
+ A = X;
+ B = Y;
+ AssociatedLoop = CurLoop;
+}
+
+
+void DependenceAnalysis::Constraint::setLine(const SCEV *AA,
+ const SCEV *BB,
+ const SCEV *CC,
+ const Loop *CurLoop) {
+ Kind = Line;
+ A = AA;
+ B = BB;
+ C = CC;
+ AssociatedLoop = CurLoop;
+}
+
+
+void DependenceAnalysis::Constraint::setDistance(const SCEV *D,
+ const Loop *CurLoop) {
+ Kind = Distance;
+ A = SE->getConstant(D->getType(), 1);
+ B = SE->getNegativeSCEV(A);
+ C = SE->getNegativeSCEV(D);
+ AssociatedLoop = CurLoop;
+}
+
+
+void DependenceAnalysis::Constraint::setEmpty() {
+ Kind = Empty;
+}
+
+
+void DependenceAnalysis::Constraint::setAny(ScalarEvolution *NewSE) {
+ SE = NewSE;
+ Kind = Any;
+}
+
+
+// For debugging purposes. Dumps the constraint out to OS.
+void DependenceAnalysis::Constraint::dump(raw_ostream &OS) const {
+ if (isEmpty())
+ OS << " Empty\n";
+ else if (isAny())
+ OS << " Any\n";
+ else if (isPoint())
+ OS << " Point is <" << *getX() << ", " << *getY() << ">\n";
+ else if (isDistance())
+ OS << " Distance is " << *getD() <<
+ " (" << *getA() << "*X + " << *getB() << "*Y = " << *getC() << ")\n";
+ else if (isLine())
+ OS << " Line is " << *getA() << "*X + " <<
+ *getB() << "*Y = " << *getC() << "\n";
+ else
+ llvm_unreachable("unknown constraint type in Constraint::dump");
+}
+
+
+// Updates X with the intersection
+// of the Constraints X and Y. Returns true if X has changed.
+// Corresponds to Figure 4 from the paper
+//
+// Practical Dependence Testing
+// Goff, Kennedy, Tseng
+// PLDI 1991
+bool DependenceAnalysis::intersectConstraints(Constraint *X,
+ const Constraint *Y) {
+ ++DeltaApplications;
+ DEBUG(dbgs() << "\tintersect constraints\n");
+ DEBUG(dbgs() << "\t X ="; X->dump(dbgs()));
+ DEBUG(dbgs() << "\t Y ="; Y->dump(dbgs()));
+ assert(!Y->isPoint() && "Y must not be a Point");
+ if (X->isAny()) {
+ if (Y->isAny())
+ return false;
+ *X = *Y;
+ return true;
+ }
+ if (X->isEmpty())
+ return false;
+ if (Y->isEmpty()) {
+ X->setEmpty();
+ return true;
+ }
+
+ if (X->isDistance() && Y->isDistance()) {
+ DEBUG(dbgs() << "\t intersect 2 distances\n");
+ if (isKnownPredicate(CmpInst::ICMP_EQ, X->getD(), Y->getD()))
+ return false;
+ if (isKnownPredicate(CmpInst::ICMP_NE, X->getD(), Y->getD())) {
+ X->setEmpty();
+ ++DeltaSuccesses;
+ return true;
+ }
+ // Hmmm, interesting situation.
+ // I guess if either is constant, keep it and ignore the other.
+ if (isa<SCEVConstant>(Y->getD())) {
+ *X = *Y;
+ return true;
+ }
+ return false;
+ }
+
+ // At this point, the pseudo-code in Figure 4 of the paper
+ // checks if (X->isPoint() && Y->isPoint()).
+ // This case can't occur in our implementation,
+ // since a Point can only arise as the result of intersecting
+ // two Line constraints, and the right-hand value, Y, is never
+ // the result of an intersection.
+ assert(!(X->isPoint() && Y->isPoint()) &&
+ "We shouldn't ever see X->isPoint() && Y->isPoint()");
+
+ if (X->isLine() && Y->isLine()) {
+ DEBUG(dbgs() << "\t intersect 2 lines\n");
+ const SCEV *Prod1 = SE->getMulExpr(X->getA(), Y->getB());
+ const SCEV *Prod2 = SE->getMulExpr(X->getB(), Y->getA());
+ if (isKnownPredicate(CmpInst::ICMP_EQ, Prod1, Prod2)) {
+ // slopes are equal, so lines are parallel
+ DEBUG(dbgs() << "\t\tsame slope\n");
+ Prod1 = SE->getMulExpr(X->getC(), Y->getB());
+ Prod2 = SE->getMulExpr(X->getB(), Y->getC());
+ if (isKnownPredicate(CmpInst::ICMP_EQ, Prod1, Prod2))
+ return false;
+ if (isKnownPredicate(CmpInst::ICMP_NE, Prod1, Prod2)) {
+ X->setEmpty();
+ ++DeltaSuccesses;
+ return true;
+ }
+ return false;
+ }
+ if (isKnownPredicate(CmpInst::ICMP_NE, Prod1, Prod2)) {
+ // slopes differ, so lines intersect
+ DEBUG(dbgs() << "\t\tdifferent slopes\n");
+ const SCEV *C1B2 = SE->getMulExpr(X->getC(), Y->getB());
+ const SCEV *C1A2 = SE->getMulExpr(X->getC(), Y->getA());
+ const SCEV *C2B1 = SE->getMulExpr(Y->getC(), X->getB());
+ const SCEV *C2A1 = SE->getMulExpr(Y->getC(), X->getA());
+ const SCEV *A1B2 = SE->getMulExpr(X->getA(), Y->getB());
+ const SCEV *A2B1 = SE->getMulExpr(Y->getA(), X->getB());
+ const SCEVConstant *C1A2_C2A1 =
+ dyn_cast<SCEVConstant>(SE->getMinusSCEV(C1A2, C2A1));
+ const SCEVConstant *C1B2_C2B1 =
+ dyn_cast<SCEVConstant>(SE->getMinusSCEV(C1B2, C2B1));
+ const SCEVConstant *A1B2_A2B1 =
+ dyn_cast<SCEVConstant>(SE->getMinusSCEV(A1B2, A2B1));
+ const SCEVConstant *A2B1_A1B2 =
+ dyn_cast<SCEVConstant>(SE->getMinusSCEV(A2B1, A1B2));
+ if (!C1B2_C2B1 || !C1A2_C2A1 ||
+ !A1B2_A2B1 || !A2B1_A1B2)
+ return false;
+ APInt Xtop = C1B2_C2B1->getValue()->getValue();
+ APInt Xbot = A1B2_A2B1->getValue()->getValue();
+ APInt Ytop = C1A2_C2A1->getValue()->getValue();
+ APInt Ybot = A2B1_A1B2->getValue()->getValue();
+ DEBUG(dbgs() << "\t\tXtop = " << Xtop << "\n");
+ DEBUG(dbgs() << "\t\tXbot = " << Xbot << "\n");
+ DEBUG(dbgs() << "\t\tYtop = " << Ytop << "\n");
+ DEBUG(dbgs() << "\t\tYbot = " << Ybot << "\n");
+ APInt Xq = Xtop; // these need to be initialized, even
+ APInt Xr = Xtop; // though they're just going to be overwritten
+ APInt::sdivrem(Xtop, Xbot, Xq, Xr);
+ APInt Yq = Ytop;
+ APInt Yr = Ytop;;
+ APInt::sdivrem(Ytop, Ybot, Yq, Yr);
+ if (Xr != 0 || Yr != 0) {
+ X->setEmpty();
+ ++DeltaSuccesses;
+ return true;
+ }
+ DEBUG(dbgs() << "\t\tX = " << Xq << ", Y = " << Yq << "\n");
+ if (Xq.slt(0) || Yq.slt(0)) {
+ X->setEmpty();
+ ++DeltaSuccesses;
+ return true;
+ }
+ if (const SCEVConstant *CUB =
+ collectConstantUpperBound(X->getAssociatedLoop(), Prod1->getType())) {
+ APInt UpperBound = CUB->getValue()->getValue();
+ DEBUG(dbgs() << "\t\tupper bound = " << UpperBound << "\n");
+ if (Xq.sgt(UpperBound) || Yq.sgt(UpperBound)) {
+ X->setEmpty();
+ ++DeltaSuccesses;
+ return true;
+ }
+ }
+ X->setPoint(SE->getConstant(Xq),
+ SE->getConstant(Yq),
+ X->getAssociatedLoop());
+ ++DeltaSuccesses;
+ return true;
+ }
+ return false;
+ }
+
+ // if (X->isLine() && Y->isPoint()) This case can't occur.
+ assert(!(X->isLine() && Y->isPoint()) && "This case should never occur");
+
+ if (X->isPoint() && Y->isLine()) {
+ DEBUG(dbgs() << "\t intersect Point and Line\n");
+ const SCEV *A1X1 = SE->getMulExpr(Y->getA(), X->getX());
+ const SCEV *B1Y1 = SE->getMulExpr(Y->getB(), X->getY());
+ const SCEV *Sum = SE->getAddExpr(A1X1, B1Y1);
+ if (isKnownPredicate(CmpInst::ICMP_EQ, Sum, Y->getC()))
+ return false;
+ if (isKnownPredicate(CmpInst::ICMP_NE, Sum, Y->getC())) {
+ X->setEmpty();
+ ++DeltaSuccesses;
+ return true;
+ }
+ return false;
+ }
+
+ llvm_unreachable("shouldn't reach the end of Constraint intersection");
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// DependenceAnalysis methods
+
+// For debugging purposes. Dumps a dependence to OS.
+void Dependence::dump(raw_ostream &OS) const {
+ bool Splitable = false;
+ if (isConfused())
+ OS << "confused";
+ else {
+ if (isConsistent())
+ OS << "consistent ";
+ if (isFlow())
+ OS << "flow";
+ else if (isOutput())
+ OS << "output";
+ else if (isAnti())
+ OS << "anti";
+ else if (isInput())
+ OS << "input";
+ unsigned Levels = getLevels();
+ if (Levels) {
+ OS << " [";
+ for (unsigned II = 1; II <= Levels; ++II) {
+ if (isSplitable(II))
+ Splitable = true;
+ if (isPeelFirst(II))
+ OS << 'p';
+ const SCEV *Distance = getDistance(II);
+ if (Distance)
+ OS << *Distance;
+ else if (isScalar(II))
+ OS << "S";
+ else {
+ unsigned Direction = getDirection(II);
+ if (Direction == DVEntry::ALL)
+ OS << "*";
+ else {
+ if (Direction & DVEntry::LT)
+ OS << "<";
+ if (Direction & DVEntry::EQ)
+ OS << "=";
+ if (Direction & DVEntry::GT)
+ OS << ">";
+ }
+ }
+ if (isPeelLast(II))
+ OS << 'p';
+ if (II < Levels)
+ OS << " ";
+ }
+ if (isLoopIndependent())
+ OS << "|<";
+ OS << "]";
+ if (Splitable)
+ OS << " splitable";
+ }
+ }
+ OS << "!\n";
+}
+
+
+
+static
+AliasAnalysis::AliasResult underlyingObjectsAlias(AliasAnalysis *AA,
+ const Value *A,
+ const Value *B) {
+ const Value *AObj = GetUnderlyingObject(A);
+ const Value *BObj = GetUnderlyingObject(B);
+ return AA->alias(AObj, AA->getTypeStoreSize(AObj->getType()),
+ BObj, AA->getTypeStoreSize(BObj->getType()));
+}
+
+
+// Returns true if the load or store can be analyzed. Atomic and volatile
+// operations have properties which this analysis does not understand.
+static
+bool isLoadOrStore(const Instruction *I) {
+ if (const LoadInst *LI = dyn_cast<LoadInst>(I))
+ return LI->isUnordered();
+ else if (const StoreInst *SI = dyn_cast<StoreInst>(I))
+ return SI->isUnordered();
+ return false;
+}
+
+
+static
+const Value *getPointerOperand(const Instruction *I) {
+ if (const LoadInst *LI = dyn_cast<LoadInst>(I))
+ return LI->getPointerOperand();
+ if (const StoreInst *SI = dyn_cast<StoreInst>(I))
+ return SI->getPointerOperand();
+ llvm_unreachable("Value is not load or store instruction");
+ return 0;
+}
+
+
+// Examines the loop nesting of the Src and Dst
+// instructions and establishes their shared loops. Sets the variables
+// CommonLevels, SrcLevels, and MaxLevels.
+// The source and destination instructions needn't be contained in the same
+// loop. The routine establishNestingLevels finds the level of most deeply
+// nested loop that contains them both, CommonLevels. An instruction that's
+// not contained in a loop is at level = 0. MaxLevels is equal to the level
+// of the source plus the level of the destination, minus CommonLevels.
+// This lets us allocate vectors MaxLevels in length, with room for every
+// distinct loop referenced in both the source and destination subscripts.
+// The variable SrcLevels is the nesting depth of the source instruction.
+// It's used to help calculate distinct loops referenced by the destination.
+// Here's the map from loops to levels:
+// 0 - unused
+// 1 - outermost common loop
+// ... - other common loops
+// CommonLevels - innermost common loop
+// ... - loops containing Src but not Dst
+// SrcLevels - innermost loop containing Src but not Dst
+// ... - loops containing Dst but not Src
+// MaxLevels - innermost loops containing Dst but not Src
+// Consider the follow code fragment:
+// for (a = ...) {
+// for (b = ...) {
+// for (c = ...) {
+// for (d = ...) {
+// A[] = ...;
+// }
+// }
+// for (e = ...) {
+// for (f = ...) {
+// for (g = ...) {
+// ... = A[];
+// }
+// }
+// }
+// }
+// }
+// If we're looking at the possibility of a dependence between the store
+// to A (the Src) and the load from A (the Dst), we'll note that they
+// have 2 loops in common, so CommonLevels will equal 2 and the direction
+// vector for Result will have 2 entries. SrcLevels = 4 and MaxLevels = 7.
+// A map from loop names to loop numbers would look like
+// a - 1
+// b - 2 = CommonLevels
+// c - 3
+// d - 4 = SrcLevels
+// e - 5
+// f - 6
+// g - 7 = MaxLevels
+void DependenceAnalysis::establishNestingLevels(const Instruction *Src,
+ const Instruction *Dst) {
+ const BasicBlock *SrcBlock = Src->getParent();
+ const BasicBlock *DstBlock = Dst->getParent();
+ unsigned SrcLevel = LI->getLoopDepth(SrcBlock);
+ unsigned DstLevel = LI->getLoopDepth(DstBlock);
+ const Loop *SrcLoop = LI->getLoopFor(SrcBlock);
+ const Loop *DstLoop = LI->getLoopFor(DstBlock);
+ SrcLevels = SrcLevel;
+ MaxLevels = SrcLevel + DstLevel;
+ while (SrcLevel > DstLevel) {
+ SrcLoop = SrcLoop->getParentLoop();
+ SrcLevel--;
+ }
+ while (DstLevel > SrcLevel) {
+ DstLoop = DstLoop->getParentLoop();
+ DstLevel--;
+ }
+ while (SrcLoop != DstLoop) {
+ SrcLoop = SrcLoop->getParentLoop();
+ DstLoop = DstLoop->getParentLoop();
+ SrcLevel--;
+ }
+ CommonLevels = SrcLevel;
+ MaxLevels -= CommonLevels;
+}
+
+
+// Given one of the loops containing the source, return
+// its level index in our numbering scheme.
+unsigned DependenceAnalysis::mapSrcLoop(const Loop *SrcLoop) const {
+ return SrcLoop->getLoopDepth();
+}
+
+
+// Given one of the loops containing the destination,
+// return its level index in our numbering scheme.
+unsigned DependenceAnalysis::mapDstLoop(const Loop *DstLoop) const {
+ unsigned D = DstLoop->getLoopDepth();
+ if (D > CommonLevels)
+ return D - CommonLevels + SrcLevels;
+ else
+ return D;
+}
+
+
+// Returns true if Expression is loop invariant in LoopNest.
+bool DependenceAnalysis::isLoopInvariant(const SCEV *Expression,
+ const Loop *LoopNest) const {
+ if (!LoopNest)
+ return true;
+ return SE->isLoopInvariant(Expression, LoopNest) &&
+ isLoopInvariant(Expression, LoopNest->getParentLoop());
+}
+
+
+
+// Finds the set of loops from the LoopNest that
+// have a level <= CommonLevels and are referred to by the SCEV Expression.
+void DependenceAnalysis::collectCommonLoops(const SCEV *Expression,
+ const Loop *LoopNest,
+ SmallBitVector &Loops) const {
+ while (LoopNest) {
+ unsigned Level = LoopNest->getLoopDepth();
+ if (Level <= CommonLevels && !SE->isLoopInvariant(Expression, LoopNest))
+ Loops.set(Level);
+ LoopNest = LoopNest->getParentLoop();
+ }
+}
+
+
+// removeMatchingExtensions - Examines a subscript pair.
+// If the source and destination are identically sign (or zero)
+// extended, it strips off the extension in an effect to simplify
+// the actual analysis.
+void DependenceAnalysis::removeMatchingExtensions(Subscript *Pair) {
+ const SCEV *Src = Pair->Src;
+ const SCEV *Dst = Pair->Dst;
+ if ((isa<SCEVZeroExtendExpr>(Src) && isa<SCEVZeroExtendExpr>(Dst)) ||
+ (isa<SCEVSignExtendExpr>(Src) && isa<SCEVSignExtendExpr>(Dst))) {
+ const SCEVCastExpr *SrcCast = cast<SCEVCastExpr>(Src);
+ const SCEVCastExpr *DstCast = cast<SCEVCastExpr>(Dst);
+ if (SrcCast->getType() == DstCast->getType()) {
+ Pair->Src = SrcCast->getOperand();
+ Pair->Dst = DstCast->getOperand();
+ }
+ }
+}
+
+
+// Examine the scev and return true iff it's linear.
+// Collect any loops mentioned in the set of "Loops".
+bool DependenceAnalysis::checkSrcSubscript(const SCEV *Src,
+ const Loop *LoopNest,
+ SmallBitVector &Loops) {
+ const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Src);
+ if (!AddRec)
+ return isLoopInvariant(Src, LoopNest);
+ const SCEV *Start = AddRec->getStart();
+ const SCEV *Step = AddRec->getStepRecurrence(*SE);
+ if (!isLoopInvariant(Step, LoopNest))
+ return false;
+ Loops.set(mapSrcLoop(AddRec->getLoop()));
+ return checkSrcSubscript(Start, LoopNest, Loops);
+}
+
+
+
+// Examine the scev and return true iff it's linear.
+// Collect any loops mentioned in the set of "Loops".
+bool DependenceAnalysis::checkDstSubscript(const SCEV *Dst,
+ const Loop *LoopNest,
+ SmallBitVector &Loops) {
+ const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Dst);
+ if (!AddRec)
+ return isLoopInvariant(Dst, LoopNest);
+ const SCEV *Start = AddRec->getStart();
+ const SCEV *Step = AddRec->getStepRecurrence(*SE);
+ if (!isLoopInvariant(Step, LoopNest))
+ return false;
+ Loops.set(mapDstLoop(AddRec->getLoop()));
+ return checkDstSubscript(Start, LoopNest, Loops);
+}
+
+
+// Examines the subscript pair (the Src and Dst SCEVs)
+// and classifies it as either ZIV, SIV, RDIV, MIV, or Nonlinear.
+// Collects the associated loops in a set.
+DependenceAnalysis::Subscript::ClassificationKind
+DependenceAnalysis::classifyPair(const SCEV *Src, const Loop *SrcLoopNest,
+ const SCEV *Dst, const Loop *DstLoopNest,
+ SmallBitVector &Loops) {
+ SmallBitVector SrcLoops(MaxLevels + 1);
+ SmallBitVector DstLoops(MaxLevels + 1);
+ if (!checkSrcSubscript(Src, SrcLoopNest, SrcLoops))
+ return Subscript::NonLinear;
+ if (!checkDstSubscript(Dst, DstLoopNest, DstLoops))
+ return Subscript::NonLinear;
+ Loops = SrcLoops;
+ Loops |= DstLoops;
+ unsigned N = Loops.count();
+ if (N == 0)
+ return Subscript::ZIV;
+ if (N == 1)
+ return Subscript::SIV;
+ if (N == 2 && (SrcLoops.count() == 0 ||
+ DstLoops.count() == 0 ||
+ (SrcLoops.count() == 1 && DstLoops.count() == 1)))
+ return Subscript::RDIV;
+ return Subscript::MIV;
+}
+
+
+// A wrapper around SCEV::isKnownPredicate.
+// Looks for cases where we're interested in comparing for equality.
+// If both X and Y have been identically sign or zero extended,
+// it strips off the (confusing) extensions before invoking
+// SCEV::isKnownPredicate. Perhaps, someday, the ScalarEvolution package
+// will be similarly updated.
+//
+// If SCEV::isKnownPredicate can't prove the predicate,
+// we try simple subtraction, which seems to help in some cases
+// involving symbolics.
+bool DependenceAnalysis::isKnownPredicate(ICmpInst::Predicate Pred,
+ const SCEV *X,
+ const SCEV *Y) const {
+ if (Pred == CmpInst::ICMP_EQ ||
+ Pred == CmpInst::ICMP_NE) {
+ if ((isa<SCEVSignExtendExpr>(X) &&
+ isa<SCEVSignExtendExpr>(Y)) ||
+ (isa<SCEVZeroExtendExpr>(X) &&
+ isa<SCEVZeroExtendExpr>(Y))) {
+ const SCEVCastExpr *CX = cast<SCEVCastExpr>(X);
+ const SCEVCastExpr *CY = cast<SCEVCastExpr>(Y);
+ const SCEV *Xop = CX->getOperand();
+ const SCEV *Yop = CY->getOperand();
+ if (Xop->getType() == Yop->getType()) {
+ X = Xop;
+ Y = Yop;
+ }
+ }
+ }
+ if (SE->isKnownPredicate(Pred, X, Y))
+ return true;
+ // If SE->isKnownPredicate can't prove the condition,
+ // we try the brute-force approach of subtracting
+ // and testing the difference.
+ // By testing with SE->isKnownPredicate first, we avoid
+ // the possibility of overflow when the arguments are constants.
+ const SCEV *Delta = SE->getMinusSCEV(X, Y);
+ switch (Pred) {
+ case CmpInst::ICMP_EQ:
+ return Delta->isZero();
+ case CmpInst::ICMP_NE:
+ return SE->isKnownNonZero(Delta);
+ case CmpInst::ICMP_SGE:
+ return SE->isKnownNonNegative(Delta);
+ case CmpInst::ICMP_SLE:
+ return SE->isKnownNonPositive(Delta);
+ case CmpInst::ICMP_SGT:
+ return SE->isKnownPositive(Delta);
+ case CmpInst::ICMP_SLT:
+ return SE->isKnownNegative(Delta);
+ default:
+ llvm_unreachable("unexpected predicate in isKnownPredicate");
+ }
+}
+
+
+// All subscripts are all the same type.
+// Loop bound may be smaller (e.g., a char).
+// Should zero extend loop bound, since it's always >= 0.
+// This routine collects upper bound and extends if needed.
+// Return null if no bound available.
+const SCEV *DependenceAnalysis::collectUpperBound(const Loop *L,
+ Type *T) const {
+ if (SE->hasLoopInvariantBackedgeTakenCount(L)) {
+ const SCEV *UB = SE->getBackedgeTakenCount(L);
+ return SE->getNoopOrZeroExtend(UB, T);
+ }
+ return NULL;
+}
+
+
+// Calls collectUpperBound(), then attempts to cast it to SCEVConstant.
+// If the cast fails, returns NULL.
+const SCEVConstant *DependenceAnalysis::collectConstantUpperBound(const Loop *L,
+ Type *T
+ ) const {
+ if (const SCEV *UB = collectUpperBound(L, T))
+ return dyn_cast<SCEVConstant>(UB);
+ return NULL;
+}
+
+
+// testZIV -
+// When we have a pair of subscripts of the form [c1] and [c2],
+// where c1 and c2 are both loop invariant, we attack it using
+// the ZIV test. Basically, we test by comparing the two values,
+// but there are actually three possible results:
+// 1) the values are equal, so there's a dependence
+// 2) the values are different, so there's no dependence
+// 3) the values might be equal, so we have to assume a dependence.
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::testZIV(const SCEV *Src,
+ const SCEV *Dst,
+ FullDependence &Result) const {
+ DEBUG(dbgs() << " src = " << *Src << "\n");
+ DEBUG(dbgs() << " dst = " << *Dst << "\n");
+ ++ZIVapplications;
+ if (isKnownPredicate(CmpInst::ICMP_EQ, Src, Dst)) {
+ DEBUG(dbgs() << " provably dependent\n");
+ return false; // provably dependent
+ }
+ if (isKnownPredicate(CmpInst::ICMP_NE, Src, Dst)) {
+ DEBUG(dbgs() << " provably independent\n");
+ ++ZIVindependence;
+ return true; // provably independent
+ }
+ DEBUG(dbgs() << " possibly dependent\n");
+ Result.Consistent = false;
+ return false; // possibly dependent
+}
+
+
+// strongSIVtest -
+// From the paper, Practical Dependence Testing, Section 4.2.1
+//
+// When we have a pair of subscripts of the form [c1 + a*i] and [c2 + a*i],
+// where i is an induction variable, c1 and c2 are loop invariant,
+// and a is a constant, we can solve it exactly using the Strong SIV test.
+//
+// Can prove independence. Failing that, can compute distance (and direction).
+// In the presence of symbolic terms, we can sometimes make progress.
+//
+// If there's a dependence,
+//
+// c1 + a*i = c2 + a*i'
+//
+// The dependence distance is
+//
+// d = i' - i = (c1 - c2)/a
+//
+// A dependence only exists if d is an integer and abs(d) <= U, where U is the
+// loop's upper bound. If a dependence exists, the dependence direction is
+// defined as
+//
+// { < if d > 0
+// direction = { = if d = 0
+// { > if d < 0
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::strongSIVtest(const SCEV *Coeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint) const {
+ DEBUG(dbgs() << "\tStrong SIV test\n");
+ DEBUG(dbgs() << "\t Coeff = " << *Coeff);
+ DEBUG(dbgs() << ", " << *Coeff->getType() << "\n");
+ DEBUG(dbgs() << "\t SrcConst = " << *SrcConst);
+ DEBUG(dbgs() << ", " << *SrcConst->getType() << "\n");
+ DEBUG(dbgs() << "\t DstConst = " << *DstConst);
+ DEBUG(dbgs() << ", " << *DstConst->getType() << "\n");
+ ++StrongSIVapplications;
+ assert(0 < Level && Level <= CommonLevels && "level out of range");
+ Level--;
+
+ const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
+ DEBUG(dbgs() << "\t Delta = " << *Delta);
+ DEBUG(dbgs() << ", " << *Delta->getType() << "\n");
+
+ // check that |Delta| < iteration count
+ if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
+ DEBUG(dbgs() << "\t UpperBound = " << *UpperBound);
+ DEBUG(dbgs() << ", " << *UpperBound->getType() << "\n");
+ const SCEV *AbsDelta =
+ SE->isKnownNonNegative(Delta) ? Delta : SE->getNegativeSCEV(Delta);
+ const SCEV *AbsCoeff =
+ SE->isKnownNonNegative(Coeff) ? Coeff : SE->getNegativeSCEV(Coeff);
+ const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
+ if (isKnownPredicate(CmpInst::ICMP_SGT, AbsDelta, Product)) {
+ // Distance greater than trip count - no dependence
+ ++StrongSIVindependence;
+ ++StrongSIVsuccesses;
+ return true;
+ }
+ }
+
+ // Can we compute distance?
+ if (isa<SCEVConstant>(Delta) && isa<SCEVConstant>(Coeff)) {
+ APInt ConstDelta = cast<SCEVConstant>(Delta)->getValue()->getValue();
+ APInt ConstCoeff = cast<SCEVConstant>(Coeff)->getValue()->getValue();
+ APInt Distance = ConstDelta; // these need to be initialized
+ APInt Remainder = ConstDelta;
+ APInt::sdivrem(ConstDelta, ConstCoeff, Distance, Remainder);
+ DEBUG(dbgs() << "\t Distance = " << Distance << "\n");
+ DEBUG(dbgs() << "\t Remainder = " << Remainder << "\n");
+ // Make sure Coeff divides Delta exactly
+ if (Remainder != 0) {
+ // Coeff doesn't divide Distance, no dependence
+ ++StrongSIVindependence;
+ ++StrongSIVsuccesses;
+ return true;
+ }
+ Result.DV[Level].Distance = SE->getConstant(Distance);
+ NewConstraint.setDistance(SE->getConstant(Distance), CurLoop);
+ if (Distance.sgt(0))
+ Result.DV[Level].Direction &= Dependence::DVEntry::LT;
+ else if (Distance.slt(0))
+ Result.DV[Level].Direction &= Dependence::DVEntry::GT;
+ else
+ Result.DV[Level].Direction &= Dependence::DVEntry::EQ;
+ ++StrongSIVsuccesses;
+ }
+ else if (Delta->isZero()) {
+ // since 0/X == 0
+ Result.DV[Level].Distance = Delta;
+ NewConstraint.setDistance(Delta, CurLoop);
+ Result.DV[Level].Direction &= Dependence::DVEntry::EQ;
+ ++StrongSIVsuccesses;
+ }
+ else {
+ if (Coeff->isOne()) {
+ DEBUG(dbgs() << "\t Distance = " << *Delta << "\n");
+ Result.DV[Level].Distance = Delta; // since X/1 == X
+ NewConstraint.setDistance(Delta, CurLoop);
+ }
+ else {
+ Result.Consistent = false;
+ NewConstraint.setLine(Coeff,
+ SE->getNegativeSCEV(Coeff),
+ SE->getNegativeSCEV(Delta), CurLoop);
+ }
+
+ // maybe we can get a useful direction
+ bool DeltaMaybeZero = !SE->isKnownNonZero(Delta);
+ bool DeltaMaybePositive = !SE->isKnownNonPositive(Delta);
+ bool DeltaMaybeNegative = !SE->isKnownNonNegative(Delta);
+ bool CoeffMaybePositive = !SE->isKnownNonPositive(Coeff);
+ bool CoeffMaybeNegative = !SE->isKnownNonNegative(Coeff);
+ // The double negatives above are confusing.
+ // It helps to read !SE->isKnownNonZero(Delta)
+ // as "Delta might be Zero"
+ unsigned NewDirection = Dependence::DVEntry::NONE;
+ if ((DeltaMaybePositive && CoeffMaybePositive) ||
+ (DeltaMaybeNegative && CoeffMaybeNegative))
+ NewDirection = Dependence::DVEntry::LT;
+ if (DeltaMaybeZero)
+ NewDirection |= Dependence::DVEntry::EQ;
+ if ((DeltaMaybeNegative && CoeffMaybePositive) ||
+ (DeltaMaybePositive && CoeffMaybeNegative))
+ NewDirection |= Dependence::DVEntry::GT;
+ if (NewDirection < Result.DV[Level].Direction)
+ ++StrongSIVsuccesses;
+ Result.DV[Level].Direction &= NewDirection;
+ }
+ return false;
+}
+
+
+// weakCrossingSIVtest -
+// From the paper, Practical Dependence Testing, Section 4.2.2
+//
+// When we have a pair of subscripts of the form [c1 + a*i] and [c2 - a*i],
+// where i is an induction variable, c1 and c2 are loop invariant,
+// and a is a constant, we can solve it exactly using the
+// Weak-Crossing SIV test.
+//
+// Given c1 + a*i = c2 - a*i', we can look for the intersection of
+// the two lines, where i = i', yielding
+//
+// c1 + a*i = c2 - a*i
+// 2a*i = c2 - c1
+// i = (c2 - c1)/2a
+//
+// If i < 0, there is no dependence.
+// If i > upperbound, there is no dependence.
+// If i = 0 (i.e., if c1 = c2), there's a dependence with distance = 0.
+// If i = upperbound, there's a dependence with distance = 0.
+// If i is integral, there's a dependence (all directions).
+// If the non-integer part = 1/2, there's a dependence (<> directions).
+// Otherwise, there's no dependence.
+//
+// Can prove independence. Failing that,
+// can sometimes refine the directions.
+// Can determine iteration for splitting.
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::weakCrossingSIVtest(const SCEV *Coeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint,
+ const SCEV *&SplitIter) const {
+ DEBUG(dbgs() << "\tWeak-Crossing SIV test\n");
+ DEBUG(dbgs() << "\t Coeff = " << *Coeff << "\n");
+ DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
+ DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
+ ++WeakCrossingSIVapplications;
+ assert(0 < Level && Level <= CommonLevels && "Level out of range");
+ Level--;
+ Result.Consistent = false;
+ const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
+ DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
+ NewConstraint.setLine(Coeff, Coeff, Delta, CurLoop);
+ if (Delta->isZero()) {
+ Result.DV[Level].Direction &= unsigned(~Dependence::DVEntry::LT);
+ Result.DV[Level].Direction &= unsigned(~Dependence::DVEntry::GT);
+ ++WeakCrossingSIVsuccesses;
+ if (!Result.DV[Level].Direction) {
+ ++WeakCrossingSIVindependence;
+ return true;
+ }
+ Result.DV[Level].Distance = Delta; // = 0
+ return false;
+ }
+ const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(Coeff);
+ if (!ConstCoeff)
+ return false;
+
+ Result.DV[Level].Splitable = true;
+ if (SE->isKnownNegative(ConstCoeff)) {
+ ConstCoeff = dyn_cast<SCEVConstant>(SE->getNegativeSCEV(ConstCoeff));
+ assert(ConstCoeff &&
+ "dynamic cast of negative of ConstCoeff should yield constant");
+ Delta = SE->getNegativeSCEV(Delta);
+ }
+ assert(SE->isKnownPositive(ConstCoeff) && "ConstCoeff should be positive");
+
+ // compute SplitIter for use by DependenceAnalysis::getSplitIteration()
+ SplitIter =
+ SE->getUDivExpr(SE->getSMaxExpr(SE->getConstant(Delta->getType(), 0),
+ Delta),
+ SE->getMulExpr(SE->getConstant(Delta->getType(), 2),
+ ConstCoeff));
+ DEBUG(dbgs() << "\t Split iter = " << *SplitIter << "\n");
+
+ const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
+ if (!ConstDelta)
+ return false;
+
+ // We're certain that ConstCoeff > 0; therefore,
+ // if Delta < 0, then no dependence.
+ DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
+ DEBUG(dbgs() << "\t ConstCoeff = " << *ConstCoeff << "\n");
+ if (SE->isKnownNegative(Delta)) {
+ // No dependence, Delta < 0
+ ++WeakCrossingSIVindependence;
+ ++WeakCrossingSIVsuccesses;
+ return true;
+ }
+
+ // We're certain that Delta > 0 and ConstCoeff > 0.
+ // Check Delta/(2*ConstCoeff) against upper loop bound
+ if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
+ DEBUG(dbgs() << "\t UpperBound = " << *UpperBound << "\n");
+ const SCEV *ConstantTwo = SE->getConstant(UpperBound->getType(), 2);
+ const SCEV *ML = SE->getMulExpr(SE->getMulExpr(ConstCoeff, UpperBound),
+ ConstantTwo);
+ DEBUG(dbgs() << "\t ML = " << *ML << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_SGT, Delta, ML)) {
+ // Delta too big, no dependence
+ ++WeakCrossingSIVindependence;
+ ++WeakCrossingSIVsuccesses;
+ return true;
+ }
+ if (isKnownPredicate(CmpInst::ICMP_EQ, Delta, ML)) {
+ // i = i' = UB
+ Result.DV[Level].Direction &= unsigned(~Dependence::DVEntry::LT);
+ Result.DV[Level].Direction &= unsigned(~Dependence::DVEntry::GT);
+ ++WeakCrossingSIVsuccesses;
+ if (!Result.DV[Level].Direction) {
+ ++WeakCrossingSIVindependence;
+ return true;
+ }
+ Result.DV[Level].Splitable = false;
+ Result.DV[Level].Distance = SE->getConstant(Delta->getType(), 0);
+ return false;
+ }
+ }
+
+ // check that Coeff divides Delta
+ APInt APDelta = ConstDelta->getValue()->getValue();
+ APInt APCoeff = ConstCoeff->getValue()->getValue();
+ APInt Distance = APDelta; // these need to be initialzed
+ APInt Remainder = APDelta;
+ APInt::sdivrem(APDelta, APCoeff, Distance, Remainder);
+ DEBUG(dbgs() << "\t Remainder = " << Remainder << "\n");
+ if (Remainder != 0) {
+ // Coeff doesn't divide Delta, no dependence
+ ++WeakCrossingSIVindependence;
+ ++WeakCrossingSIVsuccesses;
+ return true;
+ }
+ DEBUG(dbgs() << "\t Distance = " << Distance << "\n");
+
+ // if 2*Coeff doesn't divide Delta, then the equal direction isn't possible
+ APInt Two = APInt(Distance.getBitWidth(), 2, true);
+ Remainder = Distance.srem(Two);
+ DEBUG(dbgs() << "\t Remainder = " << Remainder << "\n");
+ if (Remainder != 0) {
+ // Equal direction isn't possible
+ Result.DV[Level].Direction &= unsigned(~Dependence::DVEntry::EQ);
+ ++WeakCrossingSIVsuccesses;
+ }
+ return false;
+}
+
+
+// Kirch's algorithm, from
+//
+// Optimizing Supercompilers for Supercomputers
+// Michael Wolfe
+// MIT Press, 1989
+//
+// Program 2.1, page 29.
+// Computes the GCD of AM and BM.
+// Also finds a solution to the equation ax - by = gdc(a, b).
+// Returns true iff the gcd divides Delta.
+static
+bool findGCD(unsigned Bits, APInt AM, APInt BM, APInt Delta,
+ APInt &G, APInt &X, APInt &Y) {
+ APInt A0(Bits, 1, true), A1(Bits, 0, true);
+ APInt B0(Bits, 0, true), B1(Bits, 1, true);
+ APInt G0 = AM.abs();
+ APInt G1 = BM.abs();
+ APInt Q = G0; // these need to be initialized
+ APInt R = G0;
+ APInt::sdivrem(G0, G1, Q, R);
+ while (R != 0) {
+ APInt A2 = A0 - Q*A1; A0 = A1; A1 = A2;
+ APInt B2 = B0 - Q*B1; B0 = B1; B1 = B2;
+ G0 = G1; G1 = R;
+ APInt::sdivrem(G0, G1, Q, R);
+ }
+ G = G1;
+ DEBUG(dbgs() << "\t GCD = " << G << "\n");
+ X = AM.slt(0) ? -A1 : A1;
+ Y = BM.slt(0) ? B1 : -B1;
+
+ // make sure gcd divides Delta
+ R = Delta.srem(G);
+ if (R != 0)
+ return true; // gcd doesn't divide Delta, no dependence
+ Q = Delta.sdiv(G);
+ X *= Q;
+ Y *= Q;
+ return false;
+}
+
+
+static
+APInt floorOfQuotient(APInt A, APInt B) {
+ APInt Q = A; // these need to be initialized
+ APInt R = A;
+ APInt::sdivrem(A, B, Q, R);
+ if (R == 0)
+ return Q;
+ if ((A.sgt(0) && B.sgt(0)) ||
+ (A.slt(0) && B.slt(0)))
+ return Q;
+ else
+ return Q - 1;
+}
+
+
+static
+APInt ceilingOfQuotient(APInt A, APInt B) {
+ APInt Q = A; // these need to be initialized
+ APInt R = A;
+ APInt::sdivrem(A, B, Q, R);
+ if (R == 0)
+ return Q;
+ if ((A.sgt(0) && B.sgt(0)) ||
+ (A.slt(0) && B.slt(0)))
+ return Q + 1;
+ else
+ return Q;
+}
+
+
+static
+APInt maxAPInt(APInt A, APInt B) {
+ return A.sgt(B) ? A : B;
+}
+
+
+static
+APInt minAPInt(APInt A, APInt B) {
+ return A.slt(B) ? A : B;
+}
+
+
+// exactSIVtest -
+// When we have a pair of subscripts of the form [c1 + a1*i] and [c2 + a2*i],
+// where i is an induction variable, c1 and c2 are loop invariant, and a1
+// and a2 are constant, we can solve it exactly using an algorithm developed
+// by Banerjee and Wolfe. See Section 2.5.3 in
+//
+// Optimizing Supercompilers for Supercomputers
+// Michael Wolfe
+// MIT Press, 1989
+//
+// It's slower than the specialized tests (strong SIV, weak-zero SIV, etc),
+// so use them if possible. They're also a bit better with symbolics and,
+// in the case of the strong SIV test, can compute Distances.
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::exactSIVtest(const SCEV *SrcCoeff,
+ const SCEV *DstCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint) const {
+ DEBUG(dbgs() << "\tExact SIV test\n");
+ DEBUG(dbgs() << "\t SrcCoeff = " << *SrcCoeff << " = AM\n");
+ DEBUG(dbgs() << "\t DstCoeff = " << *DstCoeff << " = BM\n");
+ DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
+ DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
+ ++ExactSIVapplications;
+ assert(0 < Level && Level <= CommonLevels && "Level out of range");
+ Level--;
+ Result.Consistent = false;
+ const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
+ DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
+ NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff),
+ Delta, CurLoop);
+ const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
+ const SCEVConstant *ConstSrcCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
+ const SCEVConstant *ConstDstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
+ if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
+ return false;
+
+ // find gcd
+ APInt G, X, Y;
+ APInt AM = ConstSrcCoeff->getValue()->getValue();
+ APInt BM = ConstDstCoeff->getValue()->getValue();
+ unsigned Bits = AM.getBitWidth();
+ if (findGCD(Bits, AM, BM, ConstDelta->getValue()->getValue(), G, X, Y)) {
+ // gcd doesn't divide Delta, no dependence
+ ++ExactSIVindependence;
+ ++ExactSIVsuccesses;
+ return true;
+ }
+
+ DEBUG(dbgs() << "\t X = " << X << ", Y = " << Y << "\n");
+
+ // since SCEV construction normalizes, LM = 0
+ APInt UM(Bits, 1, true);
+ bool UMvalid = false;
+ // UM is perhaps unavailable, let's check
+ if (const SCEVConstant *CUB =
+ collectConstantUpperBound(CurLoop, Delta->getType())) {
+ UM = CUB->getValue()->getValue();
+ DEBUG(dbgs() << "\t UM = " << UM << "\n");
+ UMvalid = true;
+ }
+
+ APInt TU(APInt::getSignedMaxValue(Bits));
+ APInt TL(APInt::getSignedMinValue(Bits));
+
+ // test(BM/G, LM-X) and test(-BM/G, X-UM)
+ APInt TMUL = BM.sdiv(G);
+ if (TMUL.sgt(0)) {
+ TL = maxAPInt(TL, ceilingOfQuotient(-X, TMUL));
+ DEBUG(dbgs() << "\t TL = " << TL << "\n");
+ if (UMvalid) {
+ TU = minAPInt(TU, floorOfQuotient(UM - X, TMUL));
+ DEBUG(dbgs() << "\t TU = " << TU << "\n");
+ }
+ }
+ else {
+ TU = minAPInt(TU, floorOfQuotient(-X, TMUL));
+ DEBUG(dbgs() << "\t TU = " << TU << "\n");
+ if (UMvalid) {
+ TL = maxAPInt(TL, ceilingOfQuotient(UM - X, TMUL));
+ DEBUG(dbgs() << "\t TL = " << TL << "\n");
+ }
+ }
+
+ // test(AM/G, LM-Y) and test(-AM/G, Y-UM)
+ TMUL = AM.sdiv(G);
+ if (TMUL.sgt(0)) {
+ TL = maxAPInt(TL, ceilingOfQuotient(-Y, TMUL));
+ DEBUG(dbgs() << "\t TL = " << TL << "\n");
+ if (UMvalid) {
+ TU = minAPInt(TU, floorOfQuotient(UM - Y, TMUL));
+ DEBUG(dbgs() << "\t TU = " << TU << "\n");
+ }
+ }
+ else {
+ TU = minAPInt(TU, floorOfQuotient(-Y, TMUL));
+ DEBUG(dbgs() << "\t TU = " << TU << "\n");
+ if (UMvalid) {
+ TL = maxAPInt(TL, ceilingOfQuotient(UM - Y, TMUL));
+ DEBUG(dbgs() << "\t TL = " << TL << "\n");
+ }
+ }
+ if (TL.sgt(TU)) {
+ ++ExactSIVindependence;
+ ++ExactSIVsuccesses;
+ return true;
+ }
+
+ // explore directions
+ unsigned NewDirection = Dependence::DVEntry::NONE;
+
+ // less than
+ APInt SaveTU(TU); // save these
+ APInt SaveTL(TL);
+ DEBUG(dbgs() << "\t exploring LT direction\n");
+ TMUL = AM - BM;
+ if (TMUL.sgt(0)) {
+ TL = maxAPInt(TL, ceilingOfQuotient(X - Y + 1, TMUL));
+ DEBUG(dbgs() << "\t\t TL = " << TL << "\n");
+ }
+ else {
+ TU = minAPInt(TU, floorOfQuotient(X - Y + 1, TMUL));
+ DEBUG(dbgs() << "\t\t TU = " << TU << "\n");
+ }
+ if (TL.sle(TU)) {
+ NewDirection |= Dependence::DVEntry::LT;
+ ++ExactSIVsuccesses;
+ }
+
+ // equal
+ TU = SaveTU; // restore
+ TL = SaveTL;
+ DEBUG(dbgs() << "\t exploring EQ direction\n");
+ if (TMUL.sgt(0)) {
+ TL = maxAPInt(TL, ceilingOfQuotient(X - Y, TMUL));
+ DEBUG(dbgs() << "\t\t TL = " << TL << "\n");
+ }
+ else {
+ TU = minAPInt(TU, floorOfQuotient(X - Y, TMUL));
+ DEBUG(dbgs() << "\t\t TU = " << TU << "\n");
+ }
+ TMUL = BM - AM;
+ if (TMUL.sgt(0)) {
+ TL = maxAPInt(TL, ceilingOfQuotient(Y - X, TMUL));
+ DEBUG(dbgs() << "\t\t TL = " << TL << "\n");
+ }
+ else {
+ TU = minAPInt(TU, floorOfQuotient(Y - X, TMUL));
+ DEBUG(dbgs() << "\t\t TU = " << TU << "\n");
+ }
+ if (TL.sle(TU)) {
+ NewDirection |= Dependence::DVEntry::EQ;
+ ++ExactSIVsuccesses;
+ }
+
+ // greater than
+ TU = SaveTU; // restore
+ TL = SaveTL;
+ DEBUG(dbgs() << "\t exploring GT direction\n");
+ if (TMUL.sgt(0)) {
+ TL = maxAPInt(TL, ceilingOfQuotient(Y - X + 1, TMUL));
+ DEBUG(dbgs() << "\t\t TL = " << TL << "\n");
+ }
+ else {
+ TU = minAPInt(TU, floorOfQuotient(Y - X + 1, TMUL));
+ DEBUG(dbgs() << "\t\t TU = " << TU << "\n");
+ }
+ if (TL.sle(TU)) {
+ NewDirection |= Dependence::DVEntry::GT;
+ ++ExactSIVsuccesses;
+ }
+
+ // finished
+ Result.DV[Level].Direction &= NewDirection;
+ if (Result.DV[Level].Direction == Dependence::DVEntry::NONE)
+ ++ExactSIVindependence;
+ return Result.DV[Level].Direction == Dependence::DVEntry::NONE;
+}
+
+
+
+// Return true if the divisor evenly divides the dividend.
+static
+bool isRemainderZero(const SCEVConstant *Dividend,
+ const SCEVConstant *Divisor) {
+ APInt ConstDividend = Dividend->getValue()->getValue();
+ APInt ConstDivisor = Divisor->getValue()->getValue();
+ return ConstDividend.srem(ConstDivisor) == 0;
+}
+
+
+// weakZeroSrcSIVtest -
+// From the paper, Practical Dependence Testing, Section 4.2.2
+//
+// When we have a pair of subscripts of the form [c1] and [c2 + a*i],
+// where i is an induction variable, c1 and c2 are loop invariant,
+// and a is a constant, we can solve it exactly using the
+// Weak-Zero SIV test.
+//
+// Given
+//
+// c1 = c2 + a*i
+//
+// we get
+//
+// (c1 - c2)/a = i
+//
+// If i is not an integer, there's no dependence.
+// If i < 0 or > UB, there's no dependence.
+// If i = 0, the direction is <= and peeling the
+// 1st iteration will break the dependence.
+// If i = UB, the direction is >= and peeling the
+// last iteration will break the dependence.
+// Otherwise, the direction is *.
+//
+// Can prove independence. Failing that, we can sometimes refine
+// the directions. Can sometimes show that first or last
+// iteration carries all the dependences (so worth peeling).
+//
+// (see also weakZeroDstSIVtest)
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::weakZeroSrcSIVtest(const SCEV *DstCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint) const {
+ // For the WeakSIV test, it's possible the loop isn't common to
+ // the Src and Dst loops. If it isn't, then there's no need to
+ // record a direction.
+ DEBUG(dbgs() << "\tWeak-Zero (src) SIV test\n");
+ DEBUG(dbgs() << "\t DstCoeff = " << *DstCoeff << "\n");
+ DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
+ DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
+ ++WeakZeroSIVapplications;
+ assert(0 < Level && Level <= MaxLevels && "Level out of range");
+ Level--;
+ Result.Consistent = false;
+ const SCEV *Delta = SE->getMinusSCEV(SrcConst, DstConst);
+ NewConstraint.setLine(SE->getConstant(Delta->getType(), 0),
+ DstCoeff, Delta, CurLoop);
+ DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_EQ, SrcConst, DstConst)) {
+ if (Level < CommonLevels) {
+ Result.DV[Level].Direction &= Dependence::DVEntry::LE;
+ Result.DV[Level].PeelFirst = true;
+ ++WeakZeroSIVsuccesses;
+ }
+ return false; // dependences caused by first iteration
+ }
+ const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
+ if (!ConstCoeff)
+ return false;
+ const SCEV *AbsCoeff =
+ SE->isKnownNegative(ConstCoeff) ?
+ SE->getNegativeSCEV(ConstCoeff) : ConstCoeff;
+ const SCEV *NewDelta =
+ SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
+
+ // check that Delta/SrcCoeff < iteration count
+ // really check NewDelta < count*AbsCoeff
+ if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
+ DEBUG(dbgs() << "\t UpperBound = " << *UpperBound << "\n");
+ const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
+ if (isKnownPredicate(CmpInst::ICMP_SGT, NewDelta, Product)) {
+ ++WeakZeroSIVindependence;
+ ++WeakZeroSIVsuccesses;
+ return true;
+ }
+ if (isKnownPredicate(CmpInst::ICMP_EQ, NewDelta, Product)) {
+ // dependences caused by last iteration
+ if (Level < CommonLevels) {
+ Result.DV[Level].Direction &= Dependence::DVEntry::GE;
+ Result.DV[Level].PeelLast = true;
+ ++WeakZeroSIVsuccesses;
+ }
+ return false;
+ }
+ }
+
+ // check that Delta/SrcCoeff >= 0
+ // really check that NewDelta >= 0
+ if (SE->isKnownNegative(NewDelta)) {
+ // No dependence, newDelta < 0
+ ++WeakZeroSIVindependence;
+ ++WeakZeroSIVsuccesses;
+ return true;
+ }
+
+ // if SrcCoeff doesn't divide Delta, then no dependence
+ if (isa<SCEVConstant>(Delta) &&
+ !isRemainderZero(cast<SCEVConstant>(Delta), ConstCoeff)) {
+ ++WeakZeroSIVindependence;
+ ++WeakZeroSIVsuccesses;
+ return true;
+ }
+ return false;
+}
+
+
+// weakZeroDstSIVtest -
+// From the paper, Practical Dependence Testing, Section 4.2.2
+//
+// When we have a pair of subscripts of the form [c1 + a*i] and [c2],
+// where i is an induction variable, c1 and c2 are loop invariant,
+// and a is a constant, we can solve it exactly using the
+// Weak-Zero SIV test.
+//
+// Given
+//
+// c1 + a*i = c2
+//
+// we get
+//
+// i = (c2 - c1)/a
+//
+// If i is not an integer, there's no dependence.
+// If i < 0 or > UB, there's no dependence.
+// If i = 0, the direction is <= and peeling the
+// 1st iteration will break the dependence.
+// If i = UB, the direction is >= and peeling the
+// last iteration will break the dependence.
+// Otherwise, the direction is *.
+//
+// Can prove independence. Failing that, we can sometimes refine
+// the directions. Can sometimes show that first or last
+// iteration carries all the dependences (so worth peeling).
+//
+// (see also weakZeroSrcSIVtest)
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::weakZeroDstSIVtest(const SCEV *SrcCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *CurLoop,
+ unsigned Level,
+ FullDependence &Result,
+ Constraint &NewConstraint) const {
+ // For the WeakSIV test, it's possible the loop isn't common to the
+ // Src and Dst loops. If it isn't, then there's no need to record a direction.
+ DEBUG(dbgs() << "\tWeak-Zero (dst) SIV test\n");
+ DEBUG(dbgs() << "\t SrcCoeff = " << *SrcCoeff << "\n");
+ DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
+ DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
+ ++WeakZeroSIVapplications;
+ assert(0 < Level && Level <= SrcLevels && "Level out of range");
+ Level--;
+ Result.Consistent = false;
+ const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
+ NewConstraint.setLine(SrcCoeff, SE->getConstant(Delta->getType(), 0),
+ Delta, CurLoop);
+ DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_EQ, DstConst, SrcConst)) {
+ if (Level < CommonLevels) {
+ Result.DV[Level].Direction &= Dependence::DVEntry::LE;
+ Result.DV[Level].PeelFirst = true;
+ ++WeakZeroSIVsuccesses;
+ }
+ return false; // dependences caused by first iteration
+ }
+ const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
+ if (!ConstCoeff)
+ return false;
+ const SCEV *AbsCoeff =
+ SE->isKnownNegative(ConstCoeff) ?
+ SE->getNegativeSCEV(ConstCoeff) : ConstCoeff;
+ const SCEV *NewDelta =
+ SE->isKnownNegative(ConstCoeff) ? SE->getNegativeSCEV(Delta) : Delta;
+
+ // check that Delta/SrcCoeff < iteration count
+ // really check NewDelta < count*AbsCoeff
+ if (const SCEV *UpperBound = collectUpperBound(CurLoop, Delta->getType())) {
+ DEBUG(dbgs() << "\t UpperBound = " << *UpperBound << "\n");
+ const SCEV *Product = SE->getMulExpr(AbsCoeff, UpperBound);
+ if (isKnownPredicate(CmpInst::ICMP_SGT, NewDelta, Product)) {
+ ++WeakZeroSIVindependence;
+ ++WeakZeroSIVsuccesses;
+ return true;
+ }
+ if (isKnownPredicate(CmpInst::ICMP_EQ, NewDelta, Product)) {
+ // dependences caused by last iteration
+ if (Level < CommonLevels) {
+ Result.DV[Level].Direction &= Dependence::DVEntry::GE;
+ Result.DV[Level].PeelLast = true;
+ ++WeakZeroSIVsuccesses;
+ }
+ return false;
+ }
+ }
+
+ // check that Delta/SrcCoeff >= 0
+ // really check that NewDelta >= 0
+ if (SE->isKnownNegative(NewDelta)) {
+ // No dependence, newDelta < 0
+ ++WeakZeroSIVindependence;
+ ++WeakZeroSIVsuccesses;
+ return true;
+ }
+
+ // if SrcCoeff doesn't divide Delta, then no dependence
+ if (isa<SCEVConstant>(Delta) &&
+ !isRemainderZero(cast<SCEVConstant>(Delta), ConstCoeff)) {
+ ++WeakZeroSIVindependence;
+ ++WeakZeroSIVsuccesses;
+ return true;
+ }
+ return false;
+}
+
+
+// exactRDIVtest - Tests the RDIV subscript pair for dependence.
+// Things of the form [c1 + a*i] and [c2 + b*j],
+// where i and j are induction variable, c1 and c2 are loop invariant,
+// and a and b are constants.
+// Returns true if any possible dependence is disproved.
+// Marks the result as inconsistant.
+// Works in some cases that symbolicRDIVtest doesn't, and vice versa.
+bool DependenceAnalysis::exactRDIVtest(const SCEV *SrcCoeff,
+ const SCEV *DstCoeff,
+ const SCEV *SrcConst,
+ const SCEV *DstConst,
+ const Loop *SrcLoop,
+ const Loop *DstLoop,
+ FullDependence &Result) const {
+ DEBUG(dbgs() << "\tExact RDIV test\n");
+ DEBUG(dbgs() << "\t SrcCoeff = " << *SrcCoeff << " = AM\n");
+ DEBUG(dbgs() << "\t DstCoeff = " << *DstCoeff << " = BM\n");
+ DEBUG(dbgs() << "\t SrcConst = " << *SrcConst << "\n");
+ DEBUG(dbgs() << "\t DstConst = " << *DstConst << "\n");
+ ++ExactRDIVapplications;
+ Result.Consistent = false;
+ const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
+ DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
+ const SCEVConstant *ConstDelta = dyn_cast<SCEVConstant>(Delta);
+ const SCEVConstant *ConstSrcCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
+ const SCEVConstant *ConstDstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
+ if (!ConstDelta || !ConstSrcCoeff || !ConstDstCoeff)
+ return false;
+
+ // find gcd
+ APInt G, X, Y;
+ APInt AM = ConstSrcCoeff->getValue()->getValue();
+ APInt BM = ConstDstCoeff->getValue()->getValue();
+ unsigned Bits = AM.getBitWidth();
+ if (findGCD(Bits, AM, BM, ConstDelta->getValue()->getValue(), G, X, Y)) {
+ // gcd doesn't divide Delta, no dependence
+ ++ExactRDIVindependence;
+ return true;
+ }
+
+ DEBUG(dbgs() << "\t X = " << X << ", Y = " << Y << "\n");
+
+ // since SCEV construction seems to normalize, LM = 0
+ APInt SrcUM(Bits, 1, true);
+ bool SrcUMvalid = false;
+ // SrcUM is perhaps unavailable, let's check
+ if (const SCEVConstant *UpperBound =
+ collectConstantUpperBound(SrcLoop, Delta->getType())) {
+ SrcUM = UpperBound->getValue()->getValue();
+ DEBUG(dbgs() << "\t SrcUM = " << SrcUM << "\n");
+ SrcUMvalid = true;
+ }
+
+ APInt DstUM(Bits, 1, true);
+ bool DstUMvalid = false;
+ // UM is perhaps unavailable, let's check
+ if (const SCEVConstant *UpperBound =
+ collectConstantUpperBound(DstLoop, Delta->getType())) {
+ DstUM = UpperBound->getValue()->getValue();
+ DEBUG(dbgs() << "\t DstUM = " << DstUM << "\n");
+ DstUMvalid = true;
+ }
+
+ APInt TU(APInt::getSignedMaxValue(Bits));
+ APInt TL(APInt::getSignedMinValue(Bits));
+
+ // test(BM/G, LM-X) and test(-BM/G, X-UM)
+ APInt TMUL = BM.sdiv(G);
+ if (TMUL.sgt(0)) {
+ TL = maxAPInt(TL, ceilingOfQuotient(-X, TMUL));
+ DEBUG(dbgs() << "\t TL = " << TL << "\n");
+ if (SrcUMvalid) {
+ TU = minAPInt(TU, floorOfQuotient(SrcUM - X, TMUL));
+ DEBUG(dbgs() << "\t TU = " << TU << "\n");
+ }
+ }
+ else {
+ TU = minAPInt(TU, floorOfQuotient(-X, TMUL));
+ DEBUG(dbgs() << "\t TU = " << TU << "\n");
+ if (SrcUMvalid) {
+ TL = maxAPInt(TL, ceilingOfQuotient(SrcUM - X, TMUL));
+ DEBUG(dbgs() << "\t TL = " << TL << "\n");
+ }
+ }
+
+ // test(AM/G, LM-Y) and test(-AM/G, Y-UM)
+ TMUL = AM.sdiv(G);
+ if (TMUL.sgt(0)) {
+ TL = maxAPInt(TL, ceilingOfQuotient(-Y, TMUL));
+ DEBUG(dbgs() << "\t TL = " << TL << "\n");
+ if (DstUMvalid) {
+ TU = minAPInt(TU, floorOfQuotient(DstUM - Y, TMUL));
+ DEBUG(dbgs() << "\t TU = " << TU << "\n");
+ }
+ }
+ else {
+ TU = minAPInt(TU, floorOfQuotient(-Y, TMUL));
+ DEBUG(dbgs() << "\t TU = " << TU << "\n");
+ if (DstUMvalid) {
+ TL = maxAPInt(TL, ceilingOfQuotient(DstUM - Y, TMUL));
+ DEBUG(dbgs() << "\t TL = " << TL << "\n");
+ }
+ }
+ if (TL.sgt(TU))
+ ++ExactRDIVindependence;
+ return TL.sgt(TU);
+}
+
+
+// symbolicRDIVtest -
+// In Section 4.5 of the Practical Dependence Testing paper,the authors
+// introduce a special case of Banerjee's Inequalities (also called the
+// Extreme-Value Test) that can handle some of the SIV and RDIV cases,
+// particularly cases with symbolics. Since it's only able to disprove
+// dependence (not compute distances or directions), we'll use it as a
+// fall back for the other tests.
+//
+// When we have a pair of subscripts of the form [c1 + a1*i] and [c2 + a2*j]
+// where i and j are induction variables and c1 and c2 are loop invariants,
+// we can use the symbolic tests to disprove some dependences, serving as a
+// backup for the RDIV test. Note that i and j can be the same variable,
+// letting this test serve as a backup for the various SIV tests.
+//
+// For a dependence to exist, c1 + a1*i must equal c2 + a2*j for some
+// 0 <= i <= N1 and some 0 <= j <= N2, where N1 and N2 are the (normalized)
+// loop bounds for the i and j loops, respectively. So, ...
+//
+// c1 + a1*i = c2 + a2*j
+// a1*i - a2*j = c2 - c1
+//
+// To test for a dependence, we compute c2 - c1 and make sure it's in the
+// range of the maximum and minimum possible values of a1*i - a2*j.
+// Considering the signs of a1 and a2, we have 4 possible cases:
+//
+// 1) If a1 >= 0 and a2 >= 0, then
+// a1*0 - a2*N2 <= c2 - c1 <= a1*N1 - a2*0
+// -a2*N2 <= c2 - c1 <= a1*N1
+//
+// 2) If a1 >= 0 and a2 <= 0, then
+// a1*0 - a2*0 <= c2 - c1 <= a1*N1 - a2*N2
+// 0 <= c2 - c1 <= a1*N1 - a2*N2
+//
+// 3) If a1 <= 0 and a2 >= 0, then
+// a1*N1 - a2*N2 <= c2 - c1 <= a1*0 - a2*0
+// a1*N1 - a2*N2 <= c2 - c1 <= 0
+//
+// 4) If a1 <= 0 and a2 <= 0, then
+// a1*N1 - a2*0 <= c2 - c1 <= a1*0 - a2*N2
+// a1*N1 <= c2 - c1 <= -a2*N2
+//
+// return true if dependence disproved
+bool DependenceAnalysis::symbolicRDIVtest(const SCEV *A1,
+ const SCEV *A2,
+ const SCEV *C1,
+ const SCEV *C2,
+ const Loop *Loop1,
+ const Loop *Loop2) const {
+ ++SymbolicRDIVapplications;
+ DEBUG(dbgs() << "\ttry symbolic RDIV test\n");
+ DEBUG(dbgs() << "\t A1 = " << *A1);
+ DEBUG(dbgs() << ", type = " << *A1->getType() << "\n");
+ DEBUG(dbgs() << "\t A2 = " << *A2 << "\n");
+ DEBUG(dbgs() << "\t C1 = " << *C1 << "\n");
+ DEBUG(dbgs() << "\t C2 = " << *C2 << "\n");
+ const SCEV *N1 = collectUpperBound(Loop1, A1->getType());
+ const SCEV *N2 = collectUpperBound(Loop2, A1->getType());
+ DEBUG(if (N1) dbgs() << "\t N1 = " << *N1 << "\n");
+ DEBUG(if (N2) dbgs() << "\t N2 = " << *N2 << "\n");
+ const SCEV *C2_C1 = SE->getMinusSCEV(C2, C1);
+ const SCEV *C1_C2 = SE->getMinusSCEV(C1, C2);
+ DEBUG(dbgs() << "\t C2 - C1 = " << *C2_C1 << "\n");
+ DEBUG(dbgs() << "\t C1 - C2 = " << *C1_C2 << "\n");
+ if (SE->isKnownNonNegative(A1)) {
+ if (SE->isKnownNonNegative(A2)) {
+ // A1 >= 0 && A2 >= 0
+ if (N1) {
+ // make sure that c2 - c1 <= a1*N1
+ const SCEV *A1N1 = SE->getMulExpr(A1, N1);
+ DEBUG(dbgs() << "\t A1*N1 = " << *A1N1 << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_SGT, C2_C1, A1N1)) {
+ ++SymbolicRDIVindependence;
+ return true;
+ }
+ }
+ if (N2) {
+ // make sure that -a2*N2 <= c2 - c1, or a2*N2 >= c1 - c2
+ const SCEV *A2N2 = SE->getMulExpr(A2, N2);
+ DEBUG(dbgs() << "\t A2*N2 = " << *A2N2 << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_SLT, A2N2, C1_C2)) {
+ ++SymbolicRDIVindependence;
+ return true;
+ }
+ }
+ }
+ else if (SE->isKnownNonPositive(A2)) {
+ // a1 >= 0 && a2 <= 0
+ if (N1 && N2) {
+ // make sure that c2 - c1 <= a1*N1 - a2*N2
+ const SCEV *A1N1 = SE->getMulExpr(A1, N1);
+ const SCEV *A2N2 = SE->getMulExpr(A2, N2);
+ const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
+ DEBUG(dbgs() << "\t A1*N1 - A2*N2 = " << *A1N1_A2N2 << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_SGT, C2_C1, A1N1_A2N2)) {
+ ++SymbolicRDIVindependence;
+ return true;
+ }
+ }
+ // make sure that 0 <= c2 - c1
+ if (SE->isKnownNegative(C2_C1)) {
+ ++SymbolicRDIVindependence;
+ return true;
+ }
+ }
+ }
+ else if (SE->isKnownNonPositive(A1)) {
+ if (SE->isKnownNonNegative(A2)) {
+ // a1 <= 0 && a2 >= 0
+ if (N1 && N2) {
+ // make sure that a1*N1 - a2*N2 <= c2 - c1
+ const SCEV *A1N1 = SE->getMulExpr(A1, N1);
+ const SCEV *A2N2 = SE->getMulExpr(A2, N2);
+ const SCEV *A1N1_A2N2 = SE->getMinusSCEV(A1N1, A2N2);
+ DEBUG(dbgs() << "\t A1*N1 - A2*N2 = " << *A1N1_A2N2 << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_SGT, A1N1_A2N2, C2_C1)) {
+ ++SymbolicRDIVindependence;
+ return true;
+ }
+ }
+ // make sure that c2 - c1 <= 0
+ if (SE->isKnownPositive(C2_C1)) {
+ ++SymbolicRDIVindependence;
+ return true;
+ }
+ }
+ else if (SE->isKnownNonPositive(A2)) {
+ // a1 <= 0 && a2 <= 0
+ if (N1) {
+ // make sure that a1*N1 <= c2 - c1
+ const SCEV *A1N1 = SE->getMulExpr(A1, N1);
+ DEBUG(dbgs() << "\t A1*N1 = " << *A1N1 << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_SGT, A1N1, C2_C1)) {
+ ++SymbolicRDIVindependence;
+ return true;
+ }
+ }
+ if (N2) {
+ // make sure that c2 - c1 <= -a2*N2, or c1 - c2 >= a2*N2
+ const SCEV *A2N2 = SE->getMulExpr(A2, N2);
+ DEBUG(dbgs() << "\t A2*N2 = " << *A2N2 << "\n");
+ if (isKnownPredicate(CmpInst::ICMP_SLT, C1_C2, A2N2)) {
+ ++SymbolicRDIVindependence;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+// testSIV -
+// When we have a pair of subscripts of the form [c1 + a1*i] and [c2 - a2*i]
+// where i is an induction variable, c1 and c2 are loop invariant, and a1 and
+// a2 are constant, we attack it with an SIV test. While they can all be
+// solved with the Exact SIV test, it's worthwhile to use simpler tests when
+// they apply; they're cheaper and sometimes more precise.
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::testSIV(const SCEV *Src,
+ const SCEV *Dst,
+ unsigned &Level,
+ FullDependence &Result,
+ Constraint &NewConstraint,
+ const SCEV *&SplitIter) const {
+ DEBUG(dbgs() << " src = " << *Src << "\n");
+ DEBUG(dbgs() << " dst = " << *Dst << "\n");
+ const SCEVAddRecExpr *SrcAddRec = dyn_cast<SCEVAddRecExpr>(Src);
+ const SCEVAddRecExpr *DstAddRec = dyn_cast<SCEVAddRecExpr>(Dst);
+ if (SrcAddRec && DstAddRec) {
+ const SCEV *SrcConst = SrcAddRec->getStart();
+ const SCEV *DstConst = DstAddRec->getStart();
+ const SCEV *SrcCoeff = SrcAddRec->getStepRecurrence(*SE);
+ const SCEV *DstCoeff = DstAddRec->getStepRecurrence(*SE);
+ const Loop *CurLoop = SrcAddRec->getLoop();
+ assert(CurLoop == DstAddRec->getLoop() &&
+ "both loops in SIV should be same");
+ Level = mapSrcLoop(CurLoop);
+ bool disproven;
+ if (SrcCoeff == DstCoeff)
+ disproven = strongSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
+ Level, Result, NewConstraint);
+ else if (SrcCoeff == SE->getNegativeSCEV(DstCoeff))
+ disproven = weakCrossingSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
+ Level, Result, NewConstraint, SplitIter);
+ else
+ disproven = exactSIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop,
+ Level, Result, NewConstraint);
+ return disproven ||
+ gcdMIVtest(Src, Dst, Result) ||
+ symbolicRDIVtest(SrcCoeff, DstCoeff, SrcConst, DstConst, CurLoop, CurLoop);
+ }
+ if (SrcAddRec) {
+ const SCEV *SrcConst = SrcAddRec->getStart();
+ const SCEV *SrcCoeff = SrcAddRec->getStepRecurrence(*SE);
+ const SCEV *DstConst = Dst;
+ const Loop *CurLoop = SrcAddRec->getLoop();
+ Level = mapSrcLoop(CurLoop);
+ return weakZeroDstSIVtest(SrcCoeff, SrcConst, DstConst, CurLoop,
+ Level, Result, NewConstraint) ||
+ gcdMIVtest(Src, Dst, Result);
+ }
+ if (DstAddRec) {
+ const SCEV *DstConst = DstAddRec->getStart();
+ const SCEV *DstCoeff = DstAddRec->getStepRecurrence(*SE);
+ const SCEV *SrcConst = Src;
+ const Loop *CurLoop = DstAddRec->getLoop();
+ Level = mapDstLoop(CurLoop);
+ return weakZeroSrcSIVtest(DstCoeff, SrcConst, DstConst,
+ CurLoop, Level, Result, NewConstraint) ||
+ gcdMIVtest(Src, Dst, Result);
+ }
+ llvm_unreachable("SIV test expected at least one AddRec");
+ return false;
+}
+
+
+// testRDIV -
+// When we have a pair of subscripts of the form [c1 + a1*i] and [c2 + a2*j]
+// where i and j are induction variables, c1 and c2 are loop invariant,
+// and a1 and a2 are constant, we can solve it exactly with an easy adaptation
+// of the Exact SIV test, the Restricted Double Index Variable (RDIV) test.
+// It doesn't make sense to talk about distance or direction in this case,
+// so there's no point in making special versions of the Strong SIV test or
+// the Weak-crossing SIV test.
+//
+// With minor algebra, this test can also be used for things like
+// [c1 + a1*i + a2*j][c2].
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::testRDIV(const SCEV *Src,
+ const SCEV *Dst,
+ FullDependence &Result) const {
+ // we have 3 possible situations here:
+ // 1) [a*i + b] and [c*j + d]
+ // 2) [a*i + c*j + b] and [d]
+ // 3) [b] and [a*i + c*j + d]
+ // We need to find what we've got and get organized
+
+ const SCEV *SrcConst, *DstConst;
+ const SCEV *SrcCoeff, *DstCoeff;
+ const Loop *SrcLoop, *DstLoop;
+
+ DEBUG(dbgs() << " src = " << *Src << "\n");
+ DEBUG(dbgs() << " dst = " << *Dst << "\n");
+ const SCEVAddRecExpr *SrcAddRec = dyn_cast<SCEVAddRecExpr>(Src);
+ const SCEVAddRecExpr *DstAddRec = dyn_cast<SCEVAddRecExpr>(Dst);
+ if (SrcAddRec && DstAddRec) {
+ SrcConst = SrcAddRec->getStart();
+ SrcCoeff = SrcAddRec->getStepRecurrence(*SE);
+ SrcLoop = SrcAddRec->getLoop();
+ DstConst = DstAddRec->getStart();
+ DstCoeff = DstAddRec->getStepRecurrence(*SE);
+ DstLoop = DstAddRec->getLoop();
+ }
+ else if (SrcAddRec) {
+ if (const SCEVAddRecExpr *tmpAddRec =
+ dyn_cast<SCEVAddRecExpr>(SrcAddRec->getStart())) {
+ SrcConst = tmpAddRec->getStart();
+ SrcCoeff = tmpAddRec->getStepRecurrence(*SE);
+ SrcLoop = tmpAddRec->getLoop();
+ DstConst = Dst;
+ DstCoeff = SE->getNegativeSCEV(SrcAddRec->getStepRecurrence(*SE));
+ DstLoop = SrcAddRec->getLoop();
+ }
+ else
+ llvm_unreachable("RDIV reached by surprising SCEVs");
+ }
+ else if (DstAddRec) {
+ if (const SCEVAddRecExpr *tmpAddRec =
+ dyn_cast<SCEVAddRecExpr>(DstAddRec->getStart())) {
+ DstConst = tmpAddRec->getStart();
+ DstCoeff = tmpAddRec->getStepRecurrence(*SE);
+ DstLoop = tmpAddRec->getLoop();
+ SrcConst = Src;
+ SrcCoeff = SE->getNegativeSCEV(DstAddRec->getStepRecurrence(*SE));
+ SrcLoop = DstAddRec->getLoop();
+ }
+ else
+ llvm_unreachable("RDIV reached by surprising SCEVs");
+ }
+ else
+ llvm_unreachable("RDIV expected at least one AddRec");
+ return exactRDIVtest(SrcCoeff, DstCoeff,
+ SrcConst, DstConst,
+ SrcLoop, DstLoop,
+ Result) ||
+ gcdMIVtest(Src, Dst, Result) ||
+ symbolicRDIVtest(SrcCoeff, DstCoeff,
+ SrcConst, DstConst,
+ SrcLoop, DstLoop);
+}
+
+
+// Tests the single-subscript MIV pair (Src and Dst) for dependence.
+// Return true if dependence disproved.
+// Can sometimes refine direction vectors.
+bool DependenceAnalysis::testMIV(const SCEV *Src,
+ const SCEV *Dst,
+ const SmallBitVector &Loops,
+ FullDependence &Result) const {
+ DEBUG(dbgs() << " src = " << *Src << "\n");
+ DEBUG(dbgs() << " dst = " << *Dst << "\n");
+ Result.Consistent = false;
+ return gcdMIVtest(Src, Dst, Result) ||
+ banerjeeMIVtest(Src, Dst, Loops, Result);
+}
+
+
+// Given a product, e.g., 10*X*Y, returns the first constant operand,
+// in this case 10. If there is no constant part, returns NULL.
+static
+const SCEVConstant *getConstantPart(const SCEVMulExpr *Product) {
+ for (unsigned Op = 0, Ops = Product->getNumOperands(); Op < Ops; Op++) {
+ if (const SCEVConstant *Constant = dyn_cast<SCEVConstant>(Product->getOperand(Op)))
+ return Constant;
+ }
+ return NULL;
+}
+
+
+//===----------------------------------------------------------------------===//
+// gcdMIVtest -
+// Tests an MIV subscript pair for dependence.
+// Returns true if any possible dependence is disproved.
+// Marks the result as inconsistant.
+// Can sometimes disprove the equal direction for 1 or more loops,
+// as discussed in Michael Wolfe's book,
+// High Performance Compilers for Parallel Computing, page 235.
+//
+// We spend some effort (code!) to handle cases like
+// [10*i + 5*N*j + 15*M + 6], where i and j are induction variables,
+// but M and N are just loop-invariant variables.
+// This should help us handle linearized subscripts;
+// also makes this test a useful backup to the various SIV tests.
+//
+// It occurs to me that the presence of loop-invariant variables
+// changes the nature of the test from "greatest common divisor"
+// to "a common divisor!"
+bool DependenceAnalysis::gcdMIVtest(const SCEV *Src,
+ const SCEV *Dst,
+ FullDependence &Result) const {
+ DEBUG(dbgs() << "starting gcd\n");
+ ++GCDapplications;
+ unsigned BitWidth = Src->getType()->getIntegerBitWidth();
+ APInt RunningGCD = APInt::getNullValue(BitWidth);
+
+ // Examine Src coefficients.
+ // Compute running GCD and record source constant.
+ // Because we're looking for the constant at the end of the chain,
+ // we can't quit the loop just because the GCD == 1.
+ const SCEV *Coefficients = Src;
+ while (const SCEVAddRecExpr *AddRec =
+ dyn_cast<SCEVAddRecExpr>(Coefficients)) {
+ const SCEV *Coeff = AddRec->getStepRecurrence(*SE);
+ const SCEVConstant *Constant = dyn_cast<SCEVConstant>(Coeff);
+ if (const SCEVMulExpr *Product = dyn_cast<SCEVMulExpr>(Coeff))
+ // If the coefficient is the product of a constant and other stuff,
+ // we can use the constant in the GCD computation.
+ Constant = getConstantPart(Product);
+ if (!Constant)
+ return false;
+ APInt ConstCoeff = Constant->getValue()->getValue();
+ RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
+ Coefficients = AddRec->getStart();
+ }
+ const SCEV *SrcConst = Coefficients;
+
+ // Examine Dst coefficients.
+ // Compute running GCD and record destination constant.
+ // Because we're looking for the constant at the end of the chain,
+ // we can't quit the loop just because the GCD == 1.
+ Coefficients = Dst;
+ while (const SCEVAddRecExpr *AddRec =
+ dyn_cast<SCEVAddRecExpr>(Coefficients)) {
+ const SCEV *Coeff = AddRec->getStepRecurrence(*SE);
+ const SCEVConstant *Constant = dyn_cast<SCEVConstant>(Coeff);
+ if (const SCEVMulExpr *Product = dyn_cast<SCEVMulExpr>(Coeff))
+ // If the coefficient is the product of a constant and other stuff,
+ // we can use the constant in the GCD computation.
+ Constant = getConstantPart(Product);
+ if (!Constant)
+ return false;
+ APInt ConstCoeff = Constant->getValue()->getValue();
+ RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
+ Coefficients = AddRec->getStart();
+ }
+ const SCEV *DstConst = Coefficients;
+
+ APInt ExtraGCD = APInt::getNullValue(BitWidth);
+ const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
+ DEBUG(dbgs() << " Delta = " << *Delta << "\n");
+ const SCEVConstant *Constant = dyn_cast<SCEVConstant>(Delta);
+ if (const SCEVAddExpr *Sum = dyn_cast<SCEVAddExpr>(Delta)) {
+ // If Delta is a sum of products, we may be able to make further progress.
+ for (unsigned Op = 0, Ops = Sum->getNumOperands(); Op < Ops; Op++) {
+ const SCEV *Operand = Sum->getOperand(Op);
+ if (isa<SCEVConstant>(Operand)) {
+ assert(!Constant && "Surprised to find multiple constants");
+ Constant = cast<SCEVConstant>(Operand);
+ }
+ else if (isa<SCEVMulExpr>(Operand)) {
+ // Search for constant operand to participate in GCD;
+ // If none found; return false.
+ const SCEVConstant *ConstOp =
+ getConstantPart(cast<SCEVMulExpr>(Operand));
+ APInt ConstOpValue = ConstOp->getValue()->getValue();
+ ExtraGCD = APIntOps::GreatestCommonDivisor(ExtraGCD,
+ ConstOpValue.abs());
+ }
+ else
+ return false;
+ }
+ }
+ if (!Constant)
+ return false;
+ APInt ConstDelta = cast<SCEVConstant>(Constant)->getValue()->getValue();
+ DEBUG(dbgs() << " ConstDelta = " << ConstDelta << "\n");
+ if (ConstDelta == 0)
+ return false;
+ RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ExtraGCD);
+ DEBUG(dbgs() << " RunningGCD = " << RunningGCD << "\n");
+ APInt Remainder = ConstDelta.srem(RunningGCD);
+ if (Remainder != 0) {
+ ++GCDindependence;
+ return true;
+ }
+
+ // Try to disprove equal directions.
+ // For example, given a subscript pair [3*i + 2*j] and [i' + 2*j' - 1],
+ // the code above can't disprove the dependence because the GCD = 1.
+ // So we consider what happen if i = i' and what happens if j = j'.
+ // If i = i', we can simplify the subscript to [2*i + 2*j] and [2*j' - 1],
+ // which is infeasible, so we can disallow the = direction for the i level.
+ // Setting j = j' doesn't help matters, so we end up with a direction vector
+ // of [<>, *]
+ //
+ // Given A[5*i + 10*j*M + 9*M*N] and A[15*i + 20*j*M - 21*N*M + 5],
+ // we need to remember that the constant part is 5 and the RunningGCD should
+ // be initialized to ExtraGCD = 30.
+ DEBUG(dbgs() << " ExtraGCD = " << ExtraGCD << '\n');
+
+ bool Improved = false;
+ Coefficients = Src;
+ while (const SCEVAddRecExpr *AddRec =
+ dyn_cast<SCEVAddRecExpr>(Coefficients)) {
+ Coefficients = AddRec->getStart();
+ const Loop *CurLoop = AddRec->getLoop();
+ RunningGCD = ExtraGCD;
+ const SCEV *SrcCoeff = AddRec->getStepRecurrence(*SE);
+ const SCEV *DstCoeff = SE->getMinusSCEV(SrcCoeff, SrcCoeff);
+ const SCEV *Inner = Src;
+ while (RunningGCD != 1 && isa<SCEVAddRecExpr>(Inner)) {
+ AddRec = cast<SCEVAddRecExpr>(Inner);
+ const SCEV *Coeff = AddRec->getStepRecurrence(*SE);
+ if (CurLoop == AddRec->getLoop())
+ ; // SrcCoeff == Coeff
+ else {
+ if (const SCEVMulExpr *Product = dyn_cast<SCEVMulExpr>(Coeff))
+ // If the coefficient is the product of a constant and other stuff,
+ // we can use the constant in the GCD computation.
+ Constant = getConstantPart(Product);
+ else
+ Constant = cast<SCEVConstant>(Coeff);
+ APInt ConstCoeff = Constant->getValue()->getValue();
+ RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
+ }
+ Inner = AddRec->getStart();
+ }
+ Inner = Dst;
+ while (RunningGCD != 1 && isa<SCEVAddRecExpr>(Inner)) {
+ AddRec = cast<SCEVAddRecExpr>(Inner);
+ const SCEV *Coeff = AddRec->getStepRecurrence(*SE);
+ if (CurLoop == AddRec->getLoop())
+ DstCoeff = Coeff;
+ else {
+ if (const SCEVMulExpr *Product = dyn_cast<SCEVMulExpr>(Coeff))
+ // If the coefficient is the product of a constant and other stuff,
+ // we can use the constant in the GCD computation.
+ Constant = getConstantPart(Product);
+ else
+ Constant = cast<SCEVConstant>(Coeff);
+ APInt ConstCoeff = Constant->getValue()->getValue();
+ RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
+ }
+ Inner = AddRec->getStart();
+ }
+ Delta = SE->getMinusSCEV(SrcCoeff, DstCoeff);
+ if (const SCEVMulExpr *Product = dyn_cast<SCEVMulExpr>(Delta))
+ // If the coefficient is the product of a constant and other stuff,
+ // we can use the constant in the GCD computation.
+ Constant = getConstantPart(Product);
+ else if (isa<SCEVConstant>(Delta))
+ Constant = cast<SCEVConstant>(Delta);
+ else {
+ // The difference of the two coefficients might not be a product
+ // or constant, in which case we give up on this direction.
+ continue;
+ }
+ APInt ConstCoeff = Constant->getValue()->getValue();
+ RunningGCD = APIntOps::GreatestCommonDivisor(RunningGCD, ConstCoeff.abs());
+ DEBUG(dbgs() << "\tRunningGCD = " << RunningGCD << "\n");
+ if (RunningGCD != 0) {
+ Remainder = ConstDelta.srem(RunningGCD);
+ DEBUG(dbgs() << "\tRemainder = " << Remainder << "\n");
+ if (Remainder != 0) {
+ unsigned Level = mapSrcLoop(CurLoop);
+ Result.DV[Level - 1].Direction &= unsigned(~Dependence::DVEntry::EQ);
+ Improved = true;
+ }
+ }
+ }
+ if (Improved)
+ ++GCDsuccesses;
+ DEBUG(dbgs() << "all done\n");
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// banerjeeMIVtest -
+// Use Banerjee's Inequalities to test an MIV subscript pair.
+// (Wolfe, in the race-car book, calls this the Extreme Value Test.)
+// Generally follows the discussion in Section 2.5.2 of
+//
+// Optimizing Supercompilers for Supercomputers
+// Michael Wolfe
+//
+// The inequalities given on page 25 are simplified in that loops are
+// normalized so that the lower bound is always 0 and the stride is always 1.
+// For example, Wolfe gives
+//
+// LB^<_k = (A^-_k - B_k)^- (U_k - L_k - N_k) + (A_k - B_k)L_k - B_k N_k
+//
+// where A_k is the coefficient of the kth index in the source subscript,
+// B_k is the coefficient of the kth index in the destination subscript,
+// U_k is the upper bound of the kth index, L_k is the lower bound of the Kth
+// index, and N_k is the stride of the kth index. Since all loops are normalized
+// by the SCEV package, N_k = 1 and L_k = 0, allowing us to simplify the
+// equation to
+//
+// LB^<_k = (A^-_k - B_k)^- (U_k - 0 - 1) + (A_k - B_k)0 - B_k 1
+// = (A^-_k - B_k)^- (U_k - 1) - B_k
+//
+// Similar simplifications are possible for the other equations.
+//
+// When we can't determine the number of iterations for a loop,
+// we use NULL as an indicator for the worst case, infinity.
+// When computing the upper bound, NULL denotes +inf;
+// for the lower bound, NULL denotes -inf.
+//
+// Return true if dependence disproved.
+bool DependenceAnalysis::banerjeeMIVtest(const SCEV *Src,
+ const SCEV *Dst,
+ const SmallBitVector &Loops,
+ FullDependence &Result) const {
+ DEBUG(dbgs() << "starting Banerjee\n");
+ ++BanerjeeApplications;
+ DEBUG(dbgs() << " Src = " << *Src << '\n');
+ const SCEV *A0;
+ CoefficientInfo *A = collectCoeffInfo(Src, true, A0);
+ DEBUG(dbgs() << " Dst = " << *Dst << '\n');
+ const SCEV *B0;
+ CoefficientInfo *B = collectCoeffInfo(Dst, false, B0);
+ BoundInfo *Bound = new BoundInfo[MaxLevels + 1];
+ const SCEV *Delta = SE->getMinusSCEV(B0, A0);
+ DEBUG(dbgs() << "\tDelta = " << *Delta << '\n');
+
+ // Compute bounds for all the * directions.
+ DEBUG(dbgs() << "\tBounds[*]\n");
+ for (unsigned K = 1; K <= MaxLevels; ++K) {
+ Bound[K].Iterations = A[K].Iterations ? A[K].Iterations : B[K].Iterations;
+ Bound[K].Direction = Dependence::DVEntry::ALL;
+ Bound[K].DirSet = Dependence::DVEntry::NONE;
+ findBoundsALL(A, B, Bound, K);
+#ifndef NDEBUG
+ DEBUG(dbgs() << "\t " << K << '\t');
+ if (Bound[K].Lower[Dependence::DVEntry::ALL])
+ DEBUG(dbgs() << *Bound[K].Lower[Dependence::DVEntry::ALL] << '\t');
+ else
+ DEBUG(dbgs() << "-inf\t");
+ if (Bound[K].Upper[Dependence::DVEntry::ALL])
+ DEBUG(dbgs() << *Bound[K].Upper[Dependence::DVEntry::ALL] << '\n');
+ else
+ DEBUG(dbgs() << "+inf\n");
+#endif
+ }
+
+ // Test the *, *, *, ... case.
+ bool Disproved = false;
+ if (testBounds(Dependence::DVEntry::ALL, 0, Bound, Delta)) {
+ // Explore the direction vector hierarchy.
+ unsigned DepthExpanded = 0;
+ unsigned NewDeps = exploreDirections(1, A, B, Bound,
+ Loops, DepthExpanded, Delta);
+ if (NewDeps > 0) {
+ bool Improved = false;
+ for (unsigned K = 1; K <= CommonLevels; ++K) {
+ if (Loops[K]) {
+ unsigned Old = Result.DV[K - 1].Direction;
+ Result.DV[K - 1].Direction = Old & Bound[K].DirSet;
+ Improved |= Old != Result.DV[K - 1].Direction;
+ if (!Result.DV[K - 1].Direction) {
+ Improved = false;
+ Disproved = true;
+ break;
+ }
+ }
+ }
+ if (Improved)
+ ++BanerjeeSuccesses;
+ }
+ else {
+ ++BanerjeeIndependence;
+ Disproved = true;
+ }
+ }
+ else {
+ ++BanerjeeIndependence;
+ Disproved = true;
+ }
+ delete [] Bound;
+ delete [] A;
+ delete [] B;
+ return Disproved;
+}
+
+
+// Hierarchically expands the direction vector
+// search space, combining the directions of discovered dependences
+// in the DirSet field of Bound. Returns the number of distinct
+// dependences discovered. If the dependence is disproved,
+// it will return 0.
+unsigned DependenceAnalysis::exploreDirections(unsigned Level,
+ CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ const SmallBitVector &Loops,
+ unsigned &DepthExpanded,
+ const SCEV *Delta) const {
+ if (Level > CommonLevels) {
+ // record result
+ DEBUG(dbgs() << "\t[");
+ for (unsigned K = 1; K <= CommonLevels; ++K) {
+ if (Loops[K]) {
+ Bound[K].DirSet |= Bound[K].Direction;
+#ifndef NDEBUG
+ switch (Bound[K].Direction) {
+ case Dependence::DVEntry::LT:
+ DEBUG(dbgs() << " <");
+ break;
+ case Dependence::DVEntry::EQ:
+ DEBUG(dbgs() << " =");
+ break;
+ case Dependence::DVEntry::GT:
+ DEBUG(dbgs() << " >");
+ break;
+ case Dependence::DVEntry::ALL:
+ DEBUG(dbgs() << " *");
+ break;
+ default:
+ llvm_unreachable("unexpected Bound[K].Direction");
+ }
+#endif
+ }
+ }
+ DEBUG(dbgs() << " ]\n");
+ return 1;
+ }
+ if (Loops[Level]) {
+ if (Level > DepthExpanded) {
+ DepthExpanded = Level;
+ // compute bounds for <, =, > at current level
+ findBoundsLT(A, B, Bound, Level);
+ findBoundsGT(A, B, Bound, Level);
+ findBoundsEQ(A, B, Bound, Level);
+#ifndef NDEBUG
+ DEBUG(dbgs() << "\tBound for level = " << Level << '\n');
+ DEBUG(dbgs() << "\t <\t");
+ if (Bound[Level].Lower[Dependence::DVEntry::LT])
+ DEBUG(dbgs() << *Bound[Level].Lower[Dependence::DVEntry::LT] << '\t');
+ else
+ DEBUG(dbgs() << "-inf\t");
+ if (Bound[Level].Upper[Dependence::DVEntry::LT])
+ DEBUG(dbgs() << *Bound[Level].Upper[Dependence::DVEntry::LT] << '\n');
+ else
+ DEBUG(dbgs() << "+inf\n");
+ DEBUG(dbgs() << "\t =\t");
+ if (Bound[Level].Lower[Dependence::DVEntry::EQ])
+ DEBUG(dbgs() << *Bound[Level].Lower[Dependence::DVEntry::EQ] << '\t');
+ else
+ DEBUG(dbgs() << "-inf\t");
+ if (Bound[Level].Upper[Dependence::DVEntry::EQ])
+ DEBUG(dbgs() << *Bound[Level].Upper[Dependence::DVEntry::EQ] << '\n');
+ else
+ DEBUG(dbgs() << "+inf\n");
+ DEBUG(dbgs() << "\t >\t");
+ if (Bound[Level].Lower[Dependence::DVEntry::GT])
+ DEBUG(dbgs() << *Bound[Level].Lower[Dependence::DVEntry::GT] << '\t');
+ else
+ DEBUG(dbgs() << "-inf\t");
+ if (Bound[Level].Upper[Dependence::DVEntry::GT])
+ DEBUG(dbgs() << *Bound[Level].Upper[Dependence::DVEntry::GT] << '\n');
+ else
+ DEBUG(dbgs() << "+inf\n");
+#endif
+ }
+
+ unsigned NewDeps = 0;
+
+ // test bounds for <, *, *, ...
+ if (testBounds(Dependence::DVEntry::LT, Level, Bound, Delta))
+ NewDeps += exploreDirections(Level + 1, A, B, Bound,
+ Loops, DepthExpanded, Delta);
+
+ // Test bounds for =, *, *, ...
+ if (testBounds(Dependence::DVEntry::EQ, Level, Bound, Delta))
+ NewDeps += exploreDirections(Level + 1, A, B, Bound,
+ Loops, DepthExpanded, Delta);
+
+ // test bounds for >, *, *, ...
+ if (testBounds(Dependence::DVEntry::GT, Level, Bound, Delta))
+ NewDeps += exploreDirections(Level + 1, A, B, Bound,
+ Loops, DepthExpanded, Delta);
+
+ Bound[Level].Direction = Dependence::DVEntry::ALL;
+ return NewDeps;
+ }
+ else
+ return exploreDirections(Level + 1, A, B, Bound, Loops, DepthExpanded, Delta);
+}
+
+
+// Returns true iff the current bounds are plausible.
+bool DependenceAnalysis::testBounds(unsigned char DirKind,
+ unsigned Level,
+ BoundInfo *Bound,
+ const SCEV *Delta) const {
+ Bound[Level].Direction = DirKind;
+ if (const SCEV *LowerBound = getLowerBound(Bound))
+ if (isKnownPredicate(CmpInst::ICMP_SGT, LowerBound, Delta))
+ return false;
+ if (const SCEV *UpperBound = getUpperBound(Bound))
+ if (isKnownPredicate(CmpInst::ICMP_SGT, Delta, UpperBound))
+ return false;
+ return true;
+}
+
+
+// Computes the upper and lower bounds for level K
+// using the * direction. Records them in Bound.
+// Wolfe gives the equations
+//
+// LB^*_k = (A^-_k - B^+_k)(U_k - L_k) + (A_k - B_k)L_k
+// UB^*_k = (A^+_k - B^-_k)(U_k - L_k) + (A_k - B_k)L_k
+//
+// Since we normalize loops, we can simplify these equations to
+//
+// LB^*_k = (A^-_k - B^+_k)U_k
+// UB^*_k = (A^+_k - B^-_k)U_k
+//
+// We must be careful to handle the case where the upper bound is unknown.
+// Note that the lower bound is always <= 0
+// and the upper bound is always >= 0.
+void DependenceAnalysis::findBoundsALL(CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ unsigned K) const {
+ Bound[K].Lower[Dependence::DVEntry::ALL] = NULL; // Default value = -infinity.
+ Bound[K].Upper[Dependence::DVEntry::ALL] = NULL; // Default value = +infinity.
+ if (Bound[K].Iterations) {
+ Bound[K].Lower[Dependence::DVEntry::ALL] =
+ SE->getMulExpr(SE->getMinusSCEV(A[K].NegPart, B[K].PosPart),
+ Bound[K].Iterations);
+ Bound[K].Upper[Dependence::DVEntry::ALL] =
+ SE->getMulExpr(SE->getMinusSCEV(A[K].PosPart, B[K].NegPart),
+ Bound[K].Iterations);
+ }
+ else {
+ // If the difference is 0, we won't need to know the number of iterations.
+ if (isKnownPredicate(CmpInst::ICMP_EQ, A[K].NegPart, B[K].PosPart))
+ Bound[K].Lower[Dependence::DVEntry::ALL] =
+ SE->getConstant(A[K].Coeff->getType(), 0);
+ if (isKnownPredicate(CmpInst::ICMP_EQ, A[K].PosPart, B[K].NegPart))
+ Bound[K].Upper[Dependence::DVEntry::ALL] =
+ SE->getConstant(A[K].Coeff->getType(), 0);
+ }
+}
+
+
+// Computes the upper and lower bounds for level K
+// using the = direction. Records them in Bound.
+// Wolfe gives the equations
+//
+// LB^=_k = (A_k - B_k)^- (U_k - L_k) + (A_k - B_k)L_k
+// UB^=_k = (A_k - B_k)^+ (U_k - L_k) + (A_k - B_k)L_k
+//
+// Since we normalize loops, we can simplify these equations to
+//
+// LB^=_k = (A_k - B_k)^- U_k
+// UB^=_k = (A_k - B_k)^+ U_k
+//
+// We must be careful to handle the case where the upper bound is unknown.
+// Note that the lower bound is always <= 0
+// and the upper bound is always >= 0.
+void DependenceAnalysis::findBoundsEQ(CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ unsigned K) const {
+ Bound[K].Lower[Dependence::DVEntry::EQ] = NULL; // Default value = -infinity.
+ Bound[K].Upper[Dependence::DVEntry::EQ] = NULL; // Default value = +infinity.
+ if (Bound[K].Iterations) {
+ const SCEV *Delta = SE->getMinusSCEV(A[K].Coeff, B[K].Coeff);
+ const SCEV *NegativePart = getNegativePart(Delta);
+ Bound[K].Lower[Dependence::DVEntry::EQ] =
+ SE->getMulExpr(NegativePart, Bound[K].Iterations);
+ const SCEV *PositivePart = getPositivePart(Delta);
+ Bound[K].Upper[Dependence::DVEntry::EQ] =
+ SE->getMulExpr(PositivePart, Bound[K].Iterations);
+ }
+ else {
+ // If the positive/negative part of the difference is 0,
+ // we won't need to know the number of iterations.
+ const SCEV *Delta = SE->getMinusSCEV(A[K].Coeff, B[K].Coeff);
+ const SCEV *NegativePart = getNegativePart(Delta);
+ if (NegativePart->isZero())
+ Bound[K].Lower[Dependence::DVEntry::EQ] = NegativePart; // Zero
+ const SCEV *PositivePart = getPositivePart(Delta);
+ if (PositivePart->isZero())
+ Bound[K].Upper[Dependence::DVEntry::EQ] = PositivePart; // Zero
+ }
+}
+
+
+// Computes the upper and lower bounds for level K
+// using the < direction. Records them in Bound.
+// Wolfe gives the equations
+//
+// LB^<_k = (A^-_k - B_k)^- (U_k - L_k - N_k) + (A_k - B_k)L_k - B_k N_k
+// UB^<_k = (A^+_k - B_k)^+ (U_k - L_k - N_k) + (A_k - B_k)L_k - B_k N_k
+//
+// Since we normalize loops, we can simplify these equations to
+//
+// LB^<_k = (A^-_k - B_k)^- (U_k - 1) - B_k
+// UB^<_k = (A^+_k - B_k)^+ (U_k - 1) - B_k
+//
+// We must be careful to handle the case where the upper bound is unknown.
+void DependenceAnalysis::findBoundsLT(CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ unsigned K) const {
+ Bound[K].Lower[Dependence::DVEntry::LT] = NULL; // Default value = -infinity.
+ Bound[K].Upper[Dependence::DVEntry::LT] = NULL; // Default value = +infinity.
+ if (Bound[K].Iterations) {
+ const SCEV *Iter_1 =
+ SE->getMinusSCEV(Bound[K].Iterations,
+ SE->getConstant(Bound[K].Iterations->getType(), 1));
+ const SCEV *NegPart =
+ getNegativePart(SE->getMinusSCEV(A[K].NegPart, B[K].Coeff));
+ Bound[K].Lower[Dependence::DVEntry::LT] =
+ SE->getMinusSCEV(SE->getMulExpr(NegPart, Iter_1), B[K].Coeff);
+ const SCEV *PosPart =
+ getPositivePart(SE->getMinusSCEV(A[K].PosPart, B[K].Coeff));
+ Bound[K].Upper[Dependence::DVEntry::LT] =
+ SE->getMinusSCEV(SE->getMulExpr(PosPart, Iter_1), B[K].Coeff);
+ }
+ else {
+ // If the positive/negative part of the difference is 0,
+ // we won't need to know the number of iterations.
+ const SCEV *NegPart =
+ getNegativePart(SE->getMinusSCEV(A[K].NegPart, B[K].Coeff));
+ if (NegPart->isZero())
+ Bound[K].Lower[Dependence::DVEntry::LT] = SE->getNegativeSCEV(B[K].Coeff);
+ const SCEV *PosPart =
+ getPositivePart(SE->getMinusSCEV(A[K].PosPart, B[K].Coeff));
+ if (PosPart->isZero())
+ Bound[K].Upper[Dependence::DVEntry::LT] = SE->getNegativeSCEV(B[K].Coeff);
+ }
+}
+
+
+// Computes the upper and lower bounds for level K
+// using the > direction. Records them in Bound.
+// Wolfe gives the equations
+//
+// LB^>_k = (A_k - B^+_k)^- (U_k - L_k - N_k) + (A_k - B_k)L_k + A_k N_k
+// UB^>_k = (A_k - B^-_k)^+ (U_k - L_k - N_k) + (A_k - B_k)L_k + A_k N_k
+//
+// Since we normalize loops, we can simplify these equations to
+//
+// LB^>_k = (A_k - B^+_k)^- (U_k - 1) + A_k
+// UB^>_k = (A_k - B^-_k)^+ (U_k - 1) + A_k
+//
+// We must be careful to handle the case where the upper bound is unknown.
+void DependenceAnalysis::findBoundsGT(CoefficientInfo *A,
+ CoefficientInfo *B,
+ BoundInfo *Bound,
+ unsigned K) const {
+ Bound[K].Lower[Dependence::DVEntry::GT] = NULL; // Default value = -infinity.
+ Bound[K].Upper[Dependence::DVEntry::GT] = NULL; // Default value = +infinity.
+ if (Bound[K].Iterations) {
+ const SCEV *Iter_1 =
+ SE->getMinusSCEV(Bound[K].Iterations,
+ SE->getConstant(Bound[K].Iterations->getType(), 1));
+ const SCEV *NegPart =
+ getNegativePart(SE->getMinusSCEV(A[K].Coeff, B[K].PosPart));
+ Bound[K].Lower[Dependence::DVEntry::GT] =
+ SE->getAddExpr(SE->getMulExpr(NegPart, Iter_1), A[K].Coeff);
+ const SCEV *PosPart =
+ getPositivePart(SE->getMinusSCEV(A[K].Coeff, B[K].NegPart));
+ Bound[K].Upper[Dependence::DVEntry::GT] =
+ SE->getAddExpr(SE->getMulExpr(PosPart, Iter_1), A[K].Coeff);
+ }
+ else {
+ // If the positive/negative part of the difference is 0,
+ // we won't need to know the number of iterations.
+ const SCEV *NegPart = getNegativePart(SE->getMinusSCEV(A[K].Coeff, B[K].PosPart));
+ if (NegPart->isZero())
+ Bound[K].Lower[Dependence::DVEntry::GT] = A[K].Coeff;
+ const SCEV *PosPart = getPositivePart(SE->getMinusSCEV(A[K].Coeff, B[K].NegPart));
+ if (PosPart->isZero())
+ Bound[K].Upper[Dependence::DVEntry::GT] = A[K].Coeff;
+ }
+}
+
+
+// X^+ = max(X, 0)
+const SCEV *DependenceAnalysis::getPositivePart(const SCEV *X) const {
+ return SE->getSMaxExpr(X, SE->getConstant(X->getType(), 0));
+}
+
+
+// X^- = min(X, 0)
+const SCEV *DependenceAnalysis::getNegativePart(const SCEV *X) const {
+ return SE->getSMinExpr(X, SE->getConstant(X->getType(), 0));
+}
+
+
+// Walks through the subscript,
+// collecting each coefficient, the associated loop bounds,
+// and recording its positive and negative parts for later use.
+DependenceAnalysis::CoefficientInfo *
+DependenceAnalysis::collectCoeffInfo(const SCEV *Subscript,
+ bool SrcFlag,
+ const SCEV *&Constant) const {
+ const SCEV *Zero = SE->getConstant(Subscript->getType(), 0);
+ CoefficientInfo *CI = new CoefficientInfo[MaxLevels + 1];
+ for (unsigned K = 1; K <= MaxLevels; ++K) {
+ CI[K].Coeff = Zero;
+ CI[K].PosPart = Zero;
+ CI[K].NegPart = Zero;
+ CI[K].Iterations = NULL;
+ }
+ while (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Subscript)) {
+ const Loop *L = AddRec->getLoop();
+ unsigned K = SrcFlag ? mapSrcLoop(L) : mapDstLoop(L);
+ CI[K].Coeff = AddRec->getStepRecurrence(*SE);
+ CI[K].PosPart = getPositivePart(CI[K].Coeff);
+ CI[K].NegPart = getNegativePart(CI[K].Coeff);
+ CI[K].Iterations = collectUpperBound(L, Subscript->getType());
+ Subscript = AddRec->getStart();
+ }
+ Constant = Subscript;
+#ifndef NDEBUG
+ DEBUG(dbgs() << "\tCoefficient Info\n");
+ for (unsigned K = 1; K <= MaxLevels; ++K) {
+ DEBUG(dbgs() << "\t " << K << "\t" << *CI[K].Coeff);
+ DEBUG(dbgs() << "\tPos Part = ");
+ DEBUG(dbgs() << *CI[K].PosPart);
+ DEBUG(dbgs() << "\tNeg Part = ");
+ DEBUG(dbgs() << *CI[K].NegPart);
+ DEBUG(dbgs() << "\tUpper Bound = ");
+ if (CI[K].Iterations)
+ DEBUG(dbgs() << *CI[K].Iterations);
+ else
+ DEBUG(dbgs() << "+inf");
+ DEBUG(dbgs() << '\n');
+ }
+ DEBUG(dbgs() << "\t Constant = " << *Subscript << '\n');
+#endif
+ return CI;
+}
+
+
+// Looks through all the bounds info and
+// computes the lower bound given the current direction settings
+// at each level. If the lower bound for any level is -inf,
+// the result is -inf.
+const SCEV *DependenceAnalysis::getLowerBound(BoundInfo *Bound) const {
+ const SCEV *Sum = Bound[1].Lower[Bound[1].Direction];
+ for (unsigned K = 2; Sum && K <= MaxLevels; ++K) {
+ if (Bound[K].Lower[Bound[K].Direction])
+ Sum = SE->getAddExpr(Sum, Bound[K].Lower[Bound[K].Direction]);
+ else
+ Sum = NULL;
+ }
+ return Sum;
+}
+
+
+// Looks through all the bounds info and
+// computes the upper bound given the current direction settings
+// at each level. If the upper bound at any level is +inf,
+// the result is +inf.
+const SCEV *DependenceAnalysis::getUpperBound(BoundInfo *Bound) const {
+ const SCEV *Sum = Bound[1].Upper[Bound[1].Direction];
+ for (unsigned K = 2; Sum && K <= MaxLevels; ++K) {
+ if (Bound[K].Upper[Bound[K].Direction])
+ Sum = SE->getAddExpr(Sum, Bound[K].Upper[Bound[K].Direction]);
+ else
+ Sum = NULL;
+ }
+ return Sum;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Constraint manipulation for Delta test.
+
+// Given a linear SCEV,
+// return the coefficient (the step)
+// corresponding to the specified loop.
+// If there isn't one, return 0.
+// For example, given a*i + b*j + c*k, zeroing the coefficient
+// corresponding to the j loop would yield b.
+const SCEV *DependenceAnalysis::findCoefficient(const SCEV *Expr,
+ const Loop *TargetLoop) const {
+ const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Expr);
+ if (!AddRec)
+ return SE->getConstant(Expr->getType(), 0);
+ if (AddRec->getLoop() == TargetLoop)
+ return AddRec->getStepRecurrence(*SE);
+ return findCoefficient(AddRec->getStart(), TargetLoop);
+}
+
+
+// Given a linear SCEV,
+// return the SCEV given by zeroing out the coefficient
+// corresponding to the specified loop.
+// For example, given a*i + b*j + c*k, zeroing the coefficient
+// corresponding to the j loop would yield a*i + c*k.
+const SCEV *DependenceAnalysis::zeroCoefficient(const SCEV *Expr,
+ const Loop *TargetLoop) const {
+ const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Expr);
+ if (!AddRec)
+ return Expr; // ignore
+ if (AddRec->getLoop() == TargetLoop)
+ return AddRec->getStart();
+ return SE->getAddRecExpr(zeroCoefficient(AddRec->getStart(), TargetLoop),
+ AddRec->getStepRecurrence(*SE),
+ AddRec->getLoop(),
+ AddRec->getNoWrapFlags());
+}
+
+
+// Given a linear SCEV Expr,
+// return the SCEV given by adding some Value to the
+// coefficient corresponding to the specified TargetLoop.
+// For example, given a*i + b*j + c*k, adding 1 to the coefficient
+// corresponding to the j loop would yield a*i + (b+1)*j + c*k.
+const SCEV *DependenceAnalysis::addToCoefficient(const SCEV *Expr,
+ const Loop *TargetLoop,
+ const SCEV *Value) const {
+ const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(Expr);
+ if (!AddRec) // create a new addRec
+ return SE->getAddRecExpr(Expr,
+ Value,
+ TargetLoop,
+ SCEV::FlagAnyWrap); // Worst case, with no info.
+ if (AddRec->getLoop() == TargetLoop) {
+ const SCEV *Sum = SE->getAddExpr(AddRec->getStepRecurrence(*SE), Value);
+ if (Sum->isZero())
+ return AddRec->getStart();
+ return SE->getAddRecExpr(AddRec->getStart(),
+ Sum,
+ AddRec->getLoop(),
+ AddRec->getNoWrapFlags());
+ }
+ return SE->getAddRecExpr(addToCoefficient(AddRec->getStart(),
+ TargetLoop, Value),
+ AddRec->getStepRecurrence(*SE),
+ AddRec->getLoop(),
+ AddRec->getNoWrapFlags());
+}
+
+
+// Review the constraints, looking for opportunities
+// to simplify a subscript pair (Src and Dst).
+// Return true if some simplification occurs.
+// If the simplification isn't exact (that is, if it is conservative
+// in terms of dependence), set consistent to false.
+// Corresponds to Figure 5 from the paper
+//
+// Practical Dependence Testing
+// Goff, Kennedy, Tseng
+// PLDI 1991
+bool DependenceAnalysis::propagate(const SCEV *&Src,
+ const SCEV *&Dst,
+ SmallBitVector &Loops,
+ SmallVector<Constraint, 4> &Constraints,
+ bool &Consistent) {
+ bool Result = false;
+ for (int LI = Loops.find_first(); LI >= 0; LI = Loops.find_next(LI)) {
+ DEBUG(dbgs() << "\t Constraint[" << LI << "] is");
+ DEBUG(Constraints[LI].dump(dbgs()));
+ if (Constraints[LI].isDistance())
+ Result |= propagateDistance(Src, Dst, Constraints[LI], Consistent);
+ else if (Constraints[LI].isLine())
+ Result |= propagateLine(Src, Dst, Constraints[LI], Consistent);
+ else if (Constraints[LI].isPoint())
+ Result |= propagatePoint(Src, Dst, Constraints[LI]);
+ }
+ return Result;
+}
+
+
+// Attempt to propagate a distance
+// constraint into a subscript pair (Src and Dst).
+// Return true if some simplification occurs.
+// If the simplification isn't exact (that is, if it is conservative
+// in terms of dependence), set consistent to false.
+bool DependenceAnalysis::propagateDistance(const SCEV *&Src,
+ const SCEV *&Dst,
+ Constraint &CurConstraint,
+ bool &Consistent) {
+ const Loop *CurLoop = CurConstraint.getAssociatedLoop();
+ DEBUG(dbgs() << "\t\tSrc is " << *Src << "\n");
+ const SCEV *A_K = findCoefficient(Src, CurLoop);
+ if (A_K->isZero())
+ return false;
+ const SCEV *DA_K = SE->getMulExpr(A_K, CurConstraint.getD());
+ Src = SE->getMinusSCEV(Src, DA_K);
+ Src = zeroCoefficient(Src, CurLoop);
+ DEBUG(dbgs() << "\t\tnew Src is " << *Src << "\n");
+ DEBUG(dbgs() << "\t\tDst is " << *Dst << "\n");
+ Dst = addToCoefficient(Dst, CurLoop, SE->getNegativeSCEV(A_K));
+ DEBUG(dbgs() << "\t\tnew Dst is " << *Dst << "\n");
+ if (!findCoefficient(Dst, CurLoop)->isZero())
+ Consistent = false;
+ return true;
+}
+
+
+// Attempt to propagate a line
+// constraint into a subscript pair (Src and Dst).
+// Return true if some simplification occurs.
+// If the simplification isn't exact (that is, if it is conservative
+// in terms of dependence), set consistent to false.
+bool DependenceAnalysis::propagateLine(const SCEV *&Src,
+ const SCEV *&Dst,
+ Constraint &CurConstraint,
+ bool &Consistent) {
+ const Loop *CurLoop = CurConstraint.getAssociatedLoop();
+ const SCEV *A = CurConstraint.getA();
+ const SCEV *B = CurConstraint.getB();
+ const SCEV *C = CurConstraint.getC();
+ DEBUG(dbgs() << "\t\tA = " << *A << ", B = " << *B << ", C = " << *C << "\n");
+ DEBUG(dbgs() << "\t\tSrc = " << *Src << "\n");
+ DEBUG(dbgs() << "\t\tDst = " << *Dst << "\n");
+ if (A->isZero()) {
+ const SCEVConstant *Bconst = dyn_cast<SCEVConstant>(B);
+ const SCEVConstant *Cconst = dyn_cast<SCEVConstant>(C);
+ if (!Bconst || !Cconst) return false;
+ APInt Beta = Bconst->getValue()->getValue();
+ APInt Charlie = Cconst->getValue()->getValue();
+ APInt CdivB = Charlie.sdiv(Beta);
+ assert(Charlie.srem(Beta) == 0 && "C should be evenly divisible by B");
+ const SCEV *AP_K = findCoefficient(Dst, CurLoop);
+ // Src = SE->getAddExpr(Src, SE->getMulExpr(AP_K, SE->getConstant(CdivB)));
+ Src = SE->getMinusSCEV(Src, SE->getMulExpr(AP_K, SE->getConstant(CdivB)));
+ Dst = zeroCoefficient(Dst, CurLoop);
+ if (!findCoefficient(Src, CurLoop)->isZero())
+ Consistent = false;
+ }
+ else if (B->isZero()) {
+ const SCEVConstant *Aconst = dyn_cast<SCEVConstant>(A);
+ const SCEVConstant *Cconst = dyn_cast<SCEVConstant>(C);
+ if (!Aconst || !Cconst) return false;
+ APInt Alpha = Aconst->getValue()->getValue();
+ APInt Charlie = Cconst->getValue()->getValue();
+ APInt CdivA = Charlie.sdiv(Alpha);
+ assert(Charlie.srem(Alpha) == 0 && "C should be evenly divisible by A");
+ const SCEV *A_K = findCoefficient(Src, CurLoop);
+ Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
+ Src = zeroCoefficient(Src, CurLoop);
+ if (!findCoefficient(Dst, CurLoop)->isZero())
+ Consistent = false;
+ }
+ else if (isKnownPredicate(CmpInst::ICMP_EQ, A, B)) {
+ const SCEVConstant *Aconst = dyn_cast<SCEVConstant>(A);
+ const SCEVConstant *Cconst = dyn_cast<SCEVConstant>(C);
+ if (!Aconst || !Cconst) return false;
+ APInt Alpha = Aconst->getValue()->getValue();
+ APInt Charlie = Cconst->getValue()->getValue();
+ APInt CdivA = Charlie.sdiv(Alpha);
+ assert(Charlie.srem(Alpha) == 0 && "C should be evenly divisible by A");
+ const SCEV *A_K = findCoefficient(Src, CurLoop);
+ Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, SE->getConstant(CdivA)));
+ Src = zeroCoefficient(Src, CurLoop);
+ Dst = addToCoefficient(Dst, CurLoop, A_K);
+ if (!findCoefficient(Dst, CurLoop)->isZero())
+ Consistent = false;
+ }
+ else {
+ // paper is incorrect here, or perhaps just misleading
+ const SCEV *A_K = findCoefficient(Src, CurLoop);
+ Src = SE->getMulExpr(Src, A);
+ Dst = SE->getMulExpr(Dst, A);
+ Src = SE->getAddExpr(Src, SE->getMulExpr(A_K, C));
+ Src = zeroCoefficient(Src, CurLoop);
+ Dst = addToCoefficient(Dst, CurLoop, SE->getMulExpr(A_K, B));
+ if (!findCoefficient(Dst, CurLoop)->isZero())
+ Consistent = false;
+ }
+ DEBUG(dbgs() << "\t\tnew Src = " << *Src << "\n");
+ DEBUG(dbgs() << "\t\tnew Dst = " << *Dst << "\n");
+ return true;
+}
+
+
+// Attempt to propagate a point
+// constraint into a subscript pair (Src and Dst).
+// Return true if some simplification occurs.
+bool DependenceAnalysis::propagatePoint(const SCEV *&Src,
+ const SCEV *&Dst,
+ Constraint &CurConstraint) {
+ const Loop *CurLoop = CurConstraint.getAssociatedLoop();
+ const SCEV *A_K = findCoefficient(Src, CurLoop);
+ const SCEV *AP_K = findCoefficient(Dst, CurLoop);
+ const SCEV *XA_K = SE->getMulExpr(A_K, CurConstraint.getX());
+ const SCEV *YAP_K = SE->getMulExpr(AP_K, CurConstraint.getY());
+ DEBUG(dbgs() << "\t\tSrc is " << *Src << "\n");
+ Src = SE->getAddExpr(Src, SE->getMinusSCEV(XA_K, YAP_K));
+ Src = zeroCoefficient(Src, CurLoop);
+ DEBUG(dbgs() << "\t\tnew Src is " << *Src << "\n");
+ DEBUG(dbgs() << "\t\tDst is " << *Dst << "\n");
+ Dst = zeroCoefficient(Dst, CurLoop);
+ DEBUG(dbgs() << "\t\tnew Dst is " << *Dst << "\n");
+ return true;
+}
+
+
+// Update direction vector entry based on the current constraint.
+void DependenceAnalysis::updateDirection(Dependence::DVEntry &Level,
+ const Constraint &CurConstraint
+ ) const {
+ DEBUG(dbgs() << "\tUpdate direction, constraint =");
+ DEBUG(CurConstraint.dump(dbgs()));
+ if (CurConstraint.isAny())
+ ; // use defaults
+ else if (CurConstraint.isDistance()) {
+ // this one is consistent, the others aren't
+ Level.Scalar = false;
+ Level.Distance = CurConstraint.getD();
+ unsigned NewDirection = Dependence::DVEntry::NONE;
+ if (!SE->isKnownNonZero(Level.Distance)) // if may be zero
+ NewDirection = Dependence::DVEntry::EQ;
+ if (!SE->isKnownNonPositive(Level.Distance)) // if may be positive
+ NewDirection |= Dependence::DVEntry::LT;
+ if (!SE->isKnownNonNegative(Level.Distance)) // if may be negative
+ NewDirection |= Dependence::DVEntry::GT;
+ Level.Direction &= NewDirection;
+ }
+ else if (CurConstraint.isLine()) {
+ Level.Scalar = false;
+ Level.Distance = NULL;
+ // direction should be accurate
+ }
+ else if (CurConstraint.isPoint()) {
+ Level.Scalar = false;
+ Level.Distance = NULL;
+ unsigned NewDirection = Dependence::DVEntry::NONE;
+ if (!isKnownPredicate(CmpInst::ICMP_NE,
+ CurConstraint.getY(),
+ CurConstraint.getX()))
+ // if X may be = Y
+ NewDirection |= Dependence::DVEntry::EQ;
+ if (!isKnownPredicate(CmpInst::ICMP_SLE,
+ CurConstraint.getY(),
+ CurConstraint.getX()))
+ // if Y may be > X
+ NewDirection |= Dependence::DVEntry::LT;
+ if (!isKnownPredicate(CmpInst::ICMP_SGE,
+ CurConstraint.getY(),
+ CurConstraint.getX()))
+ // if Y may be < X
+ NewDirection |= Dependence::DVEntry::GT;
+ Level.Direction &= NewDirection;
+ }
+ else
+ llvm_unreachable("constraint has unexpected kind");
+}
+
+
+//===----------------------------------------------------------------------===//
+
+#ifndef NDEBUG
+// For debugging purposes, dump a small bit vector to dbgs().
+static void dumpSmallBitVector(SmallBitVector &BV) {
+ dbgs() << "{";
+ for (int VI = BV.find_first(); VI >= 0; VI = BV.find_next(VI)) {
+ dbgs() << VI;
+ if (BV.find_next(VI) >= 0)
+ dbgs() << ' ';
+ }
+ dbgs() << "}\n";
+}
+#endif
+
+
+// depends -
+// Returns NULL if there is no dependence.
+// Otherwise, return a Dependence with as many details as possible.
+// Corresponds to Section 3.1 in the paper
+//
+// Practical Dependence Testing
+// Goff, Kennedy, Tseng
+// PLDI 1991
+//
+// Care is required to keep the code below up to date w.r.t. this routine.
+Dependence *DependenceAnalysis::depends(const Instruction *Src,
+ const Instruction *Dst,
+ bool PossiblyLoopIndependent) {
+ if ((!Src->mayReadFromMemory() && !Src->mayWriteToMemory()) ||
+ (!Dst->mayReadFromMemory() && !Dst->mayWriteToMemory()))
+ // if both instructions don't reference memory, there's no dependence
+ return NULL;
+
+ if (!isLoadOrStore(Src) || !isLoadOrStore(Dst))
+ // can only analyze simple loads and stores, i.e., no calls, invokes, etc.
+ return new Dependence(Src, Dst);
+
+ const Value *SrcPtr = getPointerOperand(Src);
+ const Value *DstPtr = getPointerOperand(Dst);
+
+ switch (underlyingObjectsAlias(AA, DstPtr, SrcPtr)) {
+ case AliasAnalysis::MayAlias:
+ case AliasAnalysis::PartialAlias:
+ // cannot analyse objects if we don't understand their aliasing.
+ return new Dependence(Src, Dst);
+ case AliasAnalysis::NoAlias:
+ // If the objects noalias, they are distinct, accesses are independent.
+ return NULL;
+ case AliasAnalysis::MustAlias:
+ break; // The underlying objects alias; test accesses for dependence.
+ }
+
+ const GEPOperator *SrcGEP = dyn_cast<GEPOperator>(SrcPtr);
+ const GEPOperator *DstGEP = dyn_cast<GEPOperator>(DstPtr);
+ if (!SrcGEP || !DstGEP)
+ return new Dependence(Src, Dst); // missing GEP, assume dependence
+
+ if (SrcGEP->getPointerOperandType() != DstGEP->getPointerOperandType())
+ return new Dependence(Src, Dst); // different types, assume dependence
+
+ // establish loop nesting levels
+ establishNestingLevels(Src, Dst);
+ DEBUG(dbgs() << " common nesting levels = " << CommonLevels << "\n");
+ DEBUG(dbgs() << " maximum nesting levels = " << MaxLevels << "\n");
+
+ FullDependence Result(Src, Dst, PossiblyLoopIndependent, CommonLevels);
+ ++TotalArrayPairs;
+
+ // classify subscript pairs
+ unsigned Pairs = SrcGEP->idx_end() - SrcGEP->idx_begin();
+ SmallVector<Subscript, 4> Pair(Pairs);
+ for (unsigned SI = 0; SI < Pairs; ++SI) {
+ Pair[SI].Loops.resize(MaxLevels + 1);
+ Pair[SI].GroupLoops.resize(MaxLevels + 1);
+ Pair[SI].Group.resize(Pairs);
+ }
+ Pairs = 0;
+ for (GEPOperator::const_op_iterator SrcIdx = SrcGEP->idx_begin(),
+ SrcEnd = SrcGEP->idx_end(),
+ DstIdx = DstGEP->idx_begin(),
+ DstEnd = DstGEP->idx_end();
+ SrcIdx != SrcEnd && DstIdx != DstEnd;
+ ++SrcIdx, ++DstIdx, ++Pairs) {
+ Pair[Pairs].Src = SE->getSCEV(*SrcIdx);
+ Pair[Pairs].Dst = SE->getSCEV(*DstIdx);
+ removeMatchingExtensions(&Pair[Pairs]);
+ Pair[Pairs].Classification =
+ classifyPair(Pair[Pairs].Src, LI->getLoopFor(Src->getParent()),
+ Pair[Pairs].Dst, LI->getLoopFor(Dst->getParent()),
+ Pair[Pairs].Loops);
+ Pair[Pairs].GroupLoops = Pair[Pairs].Loops;
+ Pair[Pairs].Group.set(Pairs);
+ DEBUG(dbgs() << " subscript " << Pairs << "\n");
+ DEBUG(dbgs() << "\tsrc = " << *Pair[Pairs].Src << "\n");
+ DEBUG(dbgs() << "\tdst = " << *Pair[Pairs].Dst << "\n");
+ DEBUG(dbgs() << "\tclass = " << Pair[Pairs].Classification << "\n");
+ DEBUG(dbgs() << "\tloops = ");
+ DEBUG(dumpSmallBitVector(Pair[Pairs].Loops));
+ }
+
+ SmallBitVector Separable(Pairs);
+ SmallBitVector Coupled(Pairs);
+
+ // Partition subscripts into separable and minimally-coupled groups
+ // Algorithm in paper is algorithmically better;
+ // this may be faster in practice. Check someday.
+ //
+ // Here's an example of how it works. Consider this code:
+ //
+ // for (i = ...) {
+ // for (j = ...) {
+ // for (k = ...) {
+ // for (l = ...) {
+ // for (m = ...) {
+ // A[i][j][k][m] = ...;
+ // ... = A[0][j][l][i + j];
+ // }
+ // }
+ // }
+ // }
+ // }
+ //
+ // There are 4 subscripts here:
+ // 0 [i] and [0]
+ // 1 [j] and [j]
+ // 2 [k] and [l]
+ // 3 [m] and [i + j]
+ //
+ // We've already classified each subscript pair as ZIV, SIV, etc.,
+ // and collected all the loops mentioned by pair P in Pair[P].Loops.
+ // In addition, we've initialized Pair[P].GroupLoops to Pair[P].Loops
+ // and set Pair[P].Group = {P}.
+ //
+ // Src Dst Classification Loops GroupLoops Group
+ // 0 [i] [0] SIV {1} {1} {0}
+ // 1 [j] [j] SIV {2} {2} {1}
+ // 2 [k] [l] RDIV {3,4} {3,4} {2}
+ // 3 [m] [i + j] MIV {1,2,5} {1,2,5} {3}
+ //
+ // For each subscript SI 0 .. 3, we consider each remaining subscript, SJ.
+ // So, 0 is compared against 1, 2, and 3; 1 is compared against 2 and 3, etc.
+ //
+ // We begin by comparing 0 and 1. The intersection of the GroupLoops is empty.
+ // Next, 0 and 2. Again, the intersection of their GroupLoops is empty.
+ // Next 0 and 3. The intersection of their GroupLoop = {1}, not empty,
+ // so Pair[3].Group = {0,3} and Done = false (that is, 0 will not be added
+ // to either Separable or Coupled).
+ //
+ // Next, we consider 1 and 2. The intersection of the GroupLoops is empty.
+ // Next, 1 and 3. The intersectionof their GroupLoops = {2}, not empty,
+ // so Pair[3].Group = {0, 1, 3} and Done = false.
+ //
+ // Next, we compare 2 against 3. The intersection of the GroupLoops is empty.
+ // Since Done remains true, we add 2 to the set of Separable pairs.
+ //
+ // Finally, we consider 3. There's nothing to compare it with,
+ // so Done remains true and we add it to the Coupled set.
+ // Pair[3].Group = {0, 1, 3} and GroupLoops = {1, 2, 5}.
+ //
+ // In the end, we've got 1 separable subscript and 1 coupled group.
+ for (unsigned SI = 0; SI < Pairs; ++SI) {
+ if (Pair[SI].Classification == Subscript::NonLinear) {
+ // ignore these, but collect loops for later
+ ++NonlinearSubscriptPairs;
+ collectCommonLoops(Pair[SI].Src,
+ LI->getLoopFor(Src->getParent()),
+ Pair[SI].Loops);
+ collectCommonLoops(Pair[SI].Dst,
+ LI->getLoopFor(Dst->getParent()),
+ Pair[SI].Loops);
+ Result.Consistent = false;
+ }
+ else if (Pair[SI].Classification == Subscript::ZIV) {
+ // always separable
+ Separable.set(SI);
+ }
+ else {
+ // SIV, RDIV, or MIV, so check for coupled group
+ bool Done = true;
+ for (unsigned SJ = SI + 1; SJ < Pairs; ++SJ) {
+ SmallBitVector Intersection = Pair[SI].GroupLoops;
+ Intersection &= Pair[SJ].GroupLoops;
+ if (Intersection.any()) {
+ // accumulate set of all the loops in group
+ Pair[SJ].GroupLoops |= Pair[SI].GroupLoops;
+ // accumulate set of all subscripts in group
+ Pair[SJ].Group |= Pair[SI].Group;
+ Done = false;
+ }
+ }
+ if (Done) {
+ if (Pair[SI].Group.count() == 1) {
+ Separable.set(SI);
+ ++SeparableSubscriptPairs;
+ }
+ else {
+ Coupled.set(SI);
+ ++CoupledSubscriptPairs;
+ }
+ }
+ }
+ }
+
+ DEBUG(dbgs() << " Separable = ");
+ DEBUG(dumpSmallBitVector(Separable));
+ DEBUG(dbgs() << " Coupled = ");
+ DEBUG(dumpSmallBitVector(Coupled));
+
+ Constraint NewConstraint;
+ NewConstraint.setAny(SE);
+
+ // test separable subscripts
+ for (int SI = Separable.find_first(); SI >= 0; SI = Separable.find_next(SI)) {
+ DEBUG(dbgs() << "testing subscript " << SI);
+ switch (Pair[SI].Classification) {
+ case Subscript::ZIV:
+ DEBUG(dbgs() << ", ZIV\n");
+ if (testZIV(Pair[SI].Src, Pair[SI].Dst, Result))
+ return NULL;
+ break;
+ case Subscript::SIV: {
+ DEBUG(dbgs() << ", SIV\n");
+ unsigned Level;
+ const SCEV *SplitIter = NULL;
+ if (testSIV(Pair[SI].Src, Pair[SI].Dst, Level,
+ Result, NewConstraint, SplitIter))
+ return NULL;
+ break;
+ }
+ case Subscript::RDIV:
+ DEBUG(dbgs() << ", RDIV\n");
+ if (testRDIV(Pair[SI].Src, Pair[SI].Dst, Result))
+ return NULL;
+ break;
+ case Subscript::MIV:
+ DEBUG(dbgs() << ", MIV\n");
+ if (testMIV(Pair[SI].Src, Pair[SI].Dst, Pair[SI].Loops, Result))
+ return NULL;
+ break;
+ default:
+ llvm_unreachable("subscript has unexpected classification");
+ }
+ }
+
+ if (Coupled.count()) {
+ // test coupled subscript groups
+ DEBUG(dbgs() << "starting on coupled subscripts\n");
+ DEBUG(dbgs() << "MaxLevels + 1 = " << MaxLevels + 1 << "\n");
+ SmallVector<Constraint, 4> Constraints(MaxLevels + 1);
+ for (unsigned II = 0; II <= MaxLevels; ++II)
+ Constraints[II].setAny(SE);
+ for (int SI = Coupled.find_first(); SI >= 0; SI = Coupled.find_next(SI)) {
+ DEBUG(dbgs() << "testing subscript group " << SI << " { ");
+ SmallBitVector Group(Pair[SI].Group);
+ SmallBitVector Sivs(Pairs);
+ SmallBitVector Mivs(Pairs);
+ SmallBitVector ConstrainedLevels(MaxLevels + 1);
+ for (int SJ = Group.find_first(); SJ >= 0; SJ = Group.find_next(SJ)) {
+ DEBUG(dbgs() << SJ << " ");
+ if (Pair[SJ].Classification == Subscript::SIV)
+ Sivs.set(SJ);
+ else
+ Mivs.set(SJ);
+ }
+ DEBUG(dbgs() << "}\n");
+ while (Sivs.any()) {
+ bool Changed = false;
+ for (int SJ = Sivs.find_first(); SJ >= 0; SJ = Sivs.find_next(SJ)) {
+ DEBUG(dbgs() << "testing subscript " << SJ << ", SIV\n");
+ // SJ is an SIV subscript that's part of the current coupled group
+ unsigned Level;
+ const SCEV *SplitIter = NULL;
+ DEBUG(dbgs() << "SIV\n");
+ if (testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level,
+ Result, NewConstraint, SplitIter))
+ return NULL;
+ ConstrainedLevels.set(Level);
+ if (intersectConstraints(&Constraints[Level], &NewConstraint)) {
+ if (Constraints[Level].isEmpty()) {
+ ++DeltaIndependence;
+ return NULL;
+ }
+ Changed = true;
+ }
+ Sivs.reset(SJ);
+ }
+ if (Changed) {
+ // propagate, possibly creating new SIVs and ZIVs
+ DEBUG(dbgs() << " propagating\n");
+ DEBUG(dbgs() << "\tMivs = ");
+ DEBUG(dumpSmallBitVector(Mivs));
+ for (int SJ = Mivs.find_first(); SJ >= 0; SJ = Mivs.find_next(SJ)) {
+ // SJ is an MIV subscript that's part of the current coupled group
+ DEBUG(dbgs() << "\tSJ = " << SJ << "\n");
+ if (propagate(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].Loops,
+ Constraints, Result.Consistent)) {
+ DEBUG(dbgs() << "\t Changed\n");
+ ++DeltaPropagations;
+ Pair[SJ].Classification =
+ classifyPair(Pair[SJ].Src, LI->getLoopFor(Src->getParent()),
+ Pair[SJ].Dst, LI->getLoopFor(Dst->getParent()),
+ Pair[SJ].Loops);
+ switch (Pair[SJ].Classification) {
+ case Subscript::ZIV:
+ DEBUG(dbgs() << "ZIV\n");
+ if (testZIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
+ return NULL;
+ Mivs.reset(SJ);
+ break;
+ case Subscript::SIV:
+ Sivs.set(SJ);
+ Mivs.reset(SJ);
+ break;
+ case Subscript::RDIV:
+ case Subscript::MIV:
+ break;
+ default:
+ llvm_unreachable("bad subscript classification");
+ }
+ }
+ }
+ }
+ }
+
+ // test & propagate remaining RDIVs
+ for (int SJ = Mivs.find_first(); SJ >= 0; SJ = Mivs.find_next(SJ)) {
+ if (Pair[SJ].Classification == Subscript::RDIV) {
+ DEBUG(dbgs() << "RDIV test\n");
+ if (testRDIV(Pair[SJ].Src, Pair[SJ].Dst, Result))
+ return NULL;
+ // I don't yet understand how to propagate RDIV results
+ Mivs.reset(SJ);
+ }
+ }
+
+ // test remaining MIVs
+ // This code is temporary.
+ // Better to somehow test all remaining subscripts simultaneously.
+ for (int SJ = Mivs.find_first(); SJ >= 0; SJ = Mivs.find_next(SJ)) {
+ if (Pair[SJ].Classification == Subscript::MIV) {
+ DEBUG(dbgs() << "MIV test\n");
+ if (testMIV(Pair[SJ].Src, Pair[SJ].Dst, Pair[SJ].Loops, Result))
+ return NULL;
+ }
+ else
+ llvm_unreachable("expected only MIV subscripts at this point");
+ }
+
+ // update Result.DV from constraint vector
+ DEBUG(dbgs() << " updating\n");
+ for (int SJ = ConstrainedLevels.find_first();
+ SJ >= 0; SJ = ConstrainedLevels.find_next(SJ)) {
+ updateDirection(Result.DV[SJ - 1], Constraints[SJ]);
+ if (Result.DV[SJ - 1].Direction == Dependence::DVEntry::NONE)
+ return NULL;
+ }
+ }
+ }
+
+ // make sure Scalar flags are set correctly
+ SmallBitVector CompleteLoops(MaxLevels + 1);
+ for (unsigned SI = 0; SI < Pairs; ++SI)
+ CompleteLoops |= Pair[SI].Loops;
+ for (unsigned II = 1; II <= CommonLevels; ++II)
+ if (CompleteLoops[II])
+ Result.DV[II - 1].Scalar = false;
+
+ // make sure loopIndepent flag is set correctly
+ if (PossiblyLoopIndependent) {
+ for (unsigned II = 1; II <= CommonLevels; ++II) {
+ if (!(Result.getDirection(II) & Dependence::DVEntry::EQ)) {
+ Result.LoopIndependent = false;
+ break;
+ }
+ }
+ }
+
+ FullDependence *Final = new FullDependence(Result);
+ Result.DV = NULL;
+ return Final;
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// getSplitIteration -
+// Rather than spend rarely-used space recording the splitting iteration
+// during the Weak-Crossing SIV test, we re-compute it on demand.
+// The re-computation is basically a repeat of the entire dependence test,
+// though simplified since we know that the dependence exists.
+// It's tedious, since we must go through all propagations, etc.
+//
+// Care is required to keep this code up to date w.r.t. the code above.
+//
+// Generally, the dependence analyzer will be used to build
+// a dependence graph for a function (basically a map from instructions
+// to dependences). Looking for cycles in the graph shows us loops
+// that cannot be trivially vectorized/parallelized.
+//
+// We can try to improve the situation by examining all the dependences
+// that make up the cycle, looking for ones we can break.
+// Sometimes, peeling the first or last iteration of a loop will break
+// dependences, and we've got flags for those possibilities.
+// Sometimes, splitting a loop at some other iteration will do the trick,
+// and we've got a flag for that case. Rather than waste the space to
+// record the exact iteration (since we rarely know), we provide
+// a method that calculates the iteration. It's a drag that it must work
+// from scratch, but wonderful in that it's possible.
+//
+// Here's an example:
+//
+// for (i = 0; i < 10; i++)
+// A[i] = ...
+// ... = A[11 - i]
+//
+// There's a loop-carried flow dependence from the store to the load,
+// found by the weak-crossing SIV test. The dependence will have a flag,
+// indicating that the dependence can be broken by splitting the loop.
+// Calling getSplitIteration will return 5.
+// Splitting the loop breaks the dependence, like so:
+//
+// for (i = 0; i <= 5; i++)
+// A[i] = ...
+// ... = A[11 - i]
+// for (i = 6; i < 10; i++)
+// A[i] = ...
+// ... = A[11 - i]
+//
+// breaks the dependence and allows us to vectorize/parallelize
+// both loops.
+const SCEV *DependenceAnalysis::getSplitIteration(const Dependence *Dep,
+ unsigned SplitLevel) {
+ assert(Dep && "expected a pointer to a Dependence");
+ assert(Dep->isSplitable(SplitLevel) &&
+ "Dep should be splitable at SplitLevel");
+ const Instruction *Src = Dep->getSrc();
+ const Instruction *Dst = Dep->getDst();
+ assert(Src->mayReadFromMemory() || Src->mayWriteToMemory());
+ assert(Dst->mayReadFromMemory() || Dst->mayWriteToMemory());
+ assert(isLoadOrStore(Src));
+ assert(isLoadOrStore(Dst));
+ const Value *SrcPtr = getPointerOperand(Src);
+ const Value *DstPtr = getPointerOperand(Dst);
+ assert(underlyingObjectsAlias(AA, DstPtr, SrcPtr) ==
+ AliasAnalysis::MustAlias);
+ const GEPOperator *SrcGEP = dyn_cast<GEPOperator>(SrcPtr);
+ const GEPOperator *DstGEP = dyn_cast<GEPOperator>(DstPtr);
+ assert(SrcGEP);
+ assert(DstGEP);
+ assert(SrcGEP->getPointerOperandType() == DstGEP->getPointerOperandType());
+
+ // establish loop nesting levels
+ establishNestingLevels(Src, Dst);
+
+ FullDependence Result(Src, Dst, false, CommonLevels);
+
+ // classify subscript pairs
+ unsigned Pairs = SrcGEP->idx_end() - SrcGEP->idx_begin();
+ SmallVector<Subscript, 4> Pair(Pairs);
+ for (unsigned SI = 0; SI < Pairs; ++SI) {
+ Pair[SI].Loops.resize(MaxLevels + 1);
+ Pair[SI].GroupLoops.resize(MaxLevels + 1);
+ Pair[SI].Group.resize(Pairs);
+ }
+ Pairs = 0;
+ for (GEPOperator::const_op_iterator SrcIdx = SrcGEP->idx_begin(),
+ SrcEnd = SrcGEP->idx_end(),
+ DstIdx = DstGEP->idx_begin(),
+ DstEnd = DstGEP->idx_end();
+ SrcIdx != SrcEnd && DstIdx != DstEnd;
+ ++SrcIdx, ++DstIdx, ++Pairs) {
+ Pair[Pairs].Src = SE->getSCEV(*SrcIdx);
+ Pair[Pairs].Dst = SE->getSCEV(*DstIdx);
+ Pair[Pairs].Classification =
+ classifyPair(Pair[Pairs].Src, LI->getLoopFor(Src->getParent()),
+ Pair[Pairs].Dst, LI->getLoopFor(Dst->getParent()),
+ Pair[Pairs].Loops);
+ Pair[Pairs].GroupLoops = Pair[Pairs].Loops;
+ Pair[Pairs].Group.set(Pairs);
+ }
+
+ SmallBitVector Separable(Pairs);
+ SmallBitVector Coupled(Pairs);
+
+ // partition subscripts into separable and minimally-coupled groups
+ for (unsigned SI = 0; SI < Pairs; ++SI) {
+ if (Pair[SI].Classification == Subscript::NonLinear) {
+ // ignore these, but collect loops for later
+ collectCommonLoops(Pair[SI].Src,
+ LI->getLoopFor(Src->getParent()),
+ Pair[SI].Loops);
+ collectCommonLoops(Pair[SI].Dst,
+ LI->getLoopFor(Dst->getParent()),
+ Pair[SI].Loops);
+ Result.Consistent = false;
+ }
+ else if (Pair[SI].Classification == Subscript::ZIV)
+ Separable.set(SI);
+ else {
+ // SIV, RDIV, or MIV, so check for coupled group
+ bool Done = true;
+ for (unsigned SJ = SI + 1; SJ < Pairs; ++SJ) {
+ SmallBitVector Intersection = Pair[SI].GroupLoops;
+ Intersection &= Pair[SJ].GroupLoops;
+ if (Intersection.any()) {
+ // accumulate set of all the loops in group
+ Pair[SJ].GroupLoops |= Pair[SI].GroupLoops;
+ // accumulate set of all subscripts in group
+ Pair[SJ].Group |= Pair[SI].Group;
+ Done = false;
+ }
+ }
+ if (Done) {
+ if (Pair[SI].Group.count() == 1)
+ Separable.set(SI);
+ else
+ Coupled.set(SI);
+ }
+ }
+ }
+
+ Constraint NewConstraint;
+ NewConstraint.setAny(SE);
+
+ // test separable subscripts
+ for (int SI = Separable.find_first(); SI >= 0; SI = Separable.find_next(SI)) {
+ switch (Pair[SI].Classification) {
+ case Subscript::SIV: {
+ unsigned Level;
+ const SCEV *SplitIter = NULL;
+ (void) testSIV(Pair[SI].Src, Pair[SI].Dst, Level,
+ Result, NewConstraint, SplitIter);
+ if (Level == SplitLevel) {
+ assert(SplitIter != NULL);
+ return SplitIter;
+ }
+ break;
+ }
+ case Subscript::ZIV:
+ case Subscript::RDIV:
+ case Subscript::MIV:
+ break;
+ default:
+ llvm_unreachable("subscript has unexpected classification");
+ }
+ }
+
+ if (Coupled.count()) {
+ // test coupled subscript groups
+ SmallVector<Constraint, 4> Constraints(MaxLevels + 1);
+ for (unsigned II = 0; II <= MaxLevels; ++II)
+ Constraints[II].setAny(SE);
+ for (int SI = Coupled.find_first(); SI >= 0; SI = Coupled.find_next(SI)) {
+ SmallBitVector Group(Pair[SI].Group);
+ SmallBitVector Sivs(Pairs);
+ SmallBitVector Mivs(Pairs);
+ SmallBitVector ConstrainedLevels(MaxLevels + 1);
+ for (int SJ = Group.find_first(); SJ >= 0; SJ = Group.find_next(SJ)) {
+ if (Pair[SJ].Classification == Subscript::SIV)
+ Sivs.set(SJ);
+ else
+ Mivs.set(SJ);
+ }
+ while (Sivs.any()) {
+ bool Changed = false;
+ for (int SJ = Sivs.find_first(); SJ >= 0; SJ = Sivs.find_next(SJ)) {
+ // SJ is an SIV subscript that's part of the current coupled group
+ unsigned Level;
+ const SCEV *SplitIter = NULL;
+ (void) testSIV(Pair[SJ].Src, Pair[SJ].Dst, Level,
+ Result, NewConstraint, SplitIter);
+ if (Level == SplitLevel && SplitIter)
+ return SplitIter;
+ ConstrainedLevels.set(Level);
+ if (intersectConstraints(&Constraints[Level], &NewConstraint))
+ Changed = true;
+ Sivs.reset(SJ);
+ }
+ if (Changed) {
+ // propagate, possibly creating new SIVs and ZIVs
+ for (int SJ = Mivs.find_first(); SJ >= 0; SJ = Mivs.find_next(SJ)) {
+ // SJ is an MIV subscript that's part of the current coupled group
+ if (propagate(Pair[SJ].Src, Pair[SJ].Dst,
+ Pair[SJ].Loops, Constraints, Result.Consistent)) {
+ Pair[SJ].Classification =
+ classifyPair(Pair[SJ].Src, LI->getLoopFor(Src->getParent()),
+ Pair[SJ].Dst, LI->getLoopFor(Dst->getParent()),
+ Pair[SJ].Loops);
+ switch (Pair[SJ].Classification) {
+ case Subscript::ZIV:
+ Mivs.reset(SJ);
+ break;
+ case Subscript::SIV:
+ Sivs.set(SJ);
+ Mivs.reset(SJ);
+ break;
+ case Subscript::RDIV:
+ case Subscript::MIV:
+ break;
+ default:
+ llvm_unreachable("bad subscript classification");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ llvm_unreachable("somehow reached end of routine");
+ return NULL;
+}
diff --git a/lib/Analysis/InlineCost.cpp b/lib/Analysis/InlineCost.cpp
index 5f51f775f14..95e58022ca1 100644
--- a/lib/Analysis/InlineCost.cpp
+++ b/lib/Analysis/InlineCost.cpp
@@ -243,7 +243,8 @@ bool CallAnalyzer::accumulateGEPOffset(GEPOperator &GEP, APInt &Offset) {
if (!TD)
return false;
- unsigned IntPtrWidth = TD->getPointerSizeInBits();
+ unsigned AS = GEP.getPointerAddressSpace();
+ unsigned IntPtrWidth = TD->getPointerSizeInBits(AS);
assert(IntPtrWidth == Offset.getBitWidth());
for (gep_type_iterator GTI = gep_type_begin(GEP), GTE = gep_type_end(GEP);
@@ -391,7 +392,8 @@ bool CallAnalyzer::visitPtrToInt(PtrToIntInst &I) {
// Track base/offset pairs when converted to a plain integer provided the
// integer is large enough to represent the pointer.
unsigned IntegerSize = I.getType()->getScalarSizeInBits();
- if (TD && IntegerSize >= TD->getPointerSizeInBits()) {
+ unsigned AS = I.getPointerAddressSpace();
+ if (TD && IntegerSize >= TD->getPointerSizeInBits(AS)) {
std::pair<Value *, APInt> BaseAndOffset
= ConstantOffsetPtrs.lookup(I.getOperand(0));
if (BaseAndOffset.first)
@@ -425,7 +427,8 @@ bool CallAnalyzer::visitIntToPtr(IntToPtrInst &I) {
// modifications provided the integer is not too large.
Value *Op = I.getOperand(0);
unsigned IntegerSize = Op->getType()->getScalarSizeInBits();
- if (TD && IntegerSize <= TD->getPointerSizeInBits()) {
+ unsigned AS = I.getAddressSpace();
+ if (TD && IntegerSize <= TD->getPointerSizeInBits(AS)) {
std::pair<Value *, APInt> BaseAndOffset = ConstantOffsetPtrs.lookup(Op);
if (BaseAndOffset.first)
ConstantOffsetPtrs[&I] = BaseAndOffset;
@@ -760,7 +763,8 @@ ConstantInt *CallAnalyzer::stripAndComputeInBoundsConstantOffsets(Value *&V) {
if (!TD || !V->getType()->isPointerTy())
return 0;
- unsigned IntPtrWidth = TD->getPointerSizeInBits();
+ unsigned AS = cast<PointerType>(V->getType())->getAddressSpace();;
+ unsigned IntPtrWidth = TD->getPointerSizeInBits(AS);
APInt Offset = APInt::getNullValue(IntPtrWidth);
// Even though we don't look through PHI nodes, we could be called on an
@@ -824,7 +828,8 @@ bool CallAnalyzer::analyzeCall(CallSite CS) {
// size of the byval type by the target's pointer size.
PointerType *PTy = cast<PointerType>(CS.getArgument(I)->getType());
unsigned TypeSize = TD->getTypeSizeInBits(PTy->getElementType());
- unsigned PointerSize = TD->getPointerSizeInBits();
+ unsigned AS = PTy->getAddressSpace();
+ unsigned PointerSize = TD->getPointerSizeInBits(AS);
// Ceiling division.
unsigned NumStores = (TypeSize + PointerSize - 1) / PointerSize;
diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp
index b3d62487fc1..8e326122fa5 100644
--- a/lib/Analysis/InstructionSimplify.cpp
+++ b/lib/Analysis/InstructionSimplify.cpp
@@ -666,7 +666,8 @@ Value *llvm::SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW,
/// 'Offset' APInt must be the bitwidth of the target's pointer size.
static bool accumulateGEPOffset(const DataLayout &TD, GEPOperator *GEP,
APInt &Offset) {
- unsigned IntPtrWidth = TD.getPointerSizeInBits();
+ unsigned AS = GEP->getPointerAddressSpace();
+ unsigned IntPtrWidth = TD.getPointerSizeInBits(AS);
assert(IntPtrWidth == Offset.getBitWidth());
gep_type_iterator GTI = gep_type_begin(GEP);
@@ -696,12 +697,14 @@ static bool accumulateGEPOffset(const DataLayout &TD, GEPOperator *GEP,
/// accumulates the total constant offset applied in the returned constant. It
/// returns 0 if V is not a pointer, and returns the constant '0' if there are
/// no constant offsets applied.
+/// FIXME: This function also exists in InlineCost.cpp.
static Constant *stripAndComputeConstantOffsets(const DataLayout &TD,
Value *&V) {
if (!V->getType()->isPointerTy())
return 0;
- unsigned IntPtrWidth = TD.getPointerSizeInBits();
+ unsigned AS = cast<PointerType>(V->getType())->getAddressSpace();;
+ unsigned IntPtrWidth = TD.getPointerSizeInBits(AS);
APInt Offset = APInt::getNullValue(IntPtrWidth);
// Even though we don't look through PHI nodes, we could be called on an
@@ -1877,7 +1880,9 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
// Turn icmp (ptrtoint x), (ptrtoint/constant) into a compare of the input
// if the integer type is the same size as the pointer type.
if (MaxRecurse && Q.TD && isa<PtrToIntInst>(LI) &&
- Q.TD->getPointerSizeInBits() == DstTy->getPrimitiveSizeInBits()) {
+ Q.TD->getPointerSizeInBits(
+ cast<PtrToIntInst>(LI)->getPointerAddressSpace()) ==
+ DstTy->getPrimitiveSizeInBits()) {
if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
// Transfer the cast to the constant.
if (Value *V = SimplifyICmpInst(Pred, SrcOp,
diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp
index 5e05f4c8ca1..5c2a49e767f 100644
--- a/lib/Analysis/ScalarEvolutionExpander.cpp
+++ b/lib/Analysis/ScalarEvolutionExpander.cpp
@@ -19,8 +19,8 @@
#include "llvm/LLVMContext.h"
#include "llvm/Support/Debug.h"
#include "llvm/DataLayout.h"
-#include "llvm/Target/TargetLowering.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/TargetTransformInfo.h"
using namespace llvm;
@@ -1599,15 +1599,15 @@ static bool width_descending(Value *lhs, Value *rhs) {
/// This does not depend on any SCEVExpander state but should be used in
/// the same context that SCEVExpander is used.
unsigned SCEVExpander::replaceCongruentIVs(Loop *L, const DominatorTree *DT,
- SmallVectorImpl<WeakVH> &DeadInsts,
- const TargetLowering *TLI) {
+ SmallVectorImpl<WeakVH> &DeadInsts,
+ const ScalarTargetTransformInfo *STTI) {
// Find integer phis in order of increasing width.
SmallVector<PHINode*, 8> Phis;
for (BasicBlock::iterator I = L->getHeader()->begin();
PHINode *Phi = dyn_cast<PHINode>(I); ++I) {
Phis.push_back(Phi);
}
- if (TLI)
+ if (STTI)
std::sort(Phis.begin(), Phis.end(), width_descending);
unsigned NumElim = 0;
@@ -1624,8 +1624,8 @@ unsigned SCEVExpander::replaceCongruentIVs(Loop *L, const DominatorTree *DT,
PHINode *&OrigPhiRef = ExprToIVMap[SE.getSCEV(Phi)];
if (!OrigPhiRef) {
OrigPhiRef = Phi;
- if (Phi->getType()->isIntegerTy() && TLI
- && TLI->isTruncateFree(Phi->getType(), Phis.back()->getType())) {
+ if (Phi->getType()->isIntegerTy() && STTI &&
+ STTI->isTruncateFree(Phi->getType(), Phis.back()->getType())) {
// This phi can be freely truncated to the narrowest phi type. Map the
// truncated expression to it so it will be reused for narrow types.
const SCEV *TruncExpr =
diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp
index 951b442b874..1d7f0692cbe 100644
--- a/lib/Analysis/ValueTracking.cpp
+++ b/lib/Analysis/ValueTracking.cpp
@@ -40,7 +40,8 @@ static unsigned getBitWidth(Type *Ty, const DataLayout *TD) {
if (unsigned BitWidth = Ty->getScalarSizeInBits())
return BitWidth;
assert(isa<PointerType>(Ty) && "Expected a pointer type!");
- return TD ? TD->getPointerSizeInBits() : 0;
+ return TD ?
+ TD->getPointerSizeInBits(cast<PointerType>(Ty)->getAddressSpace()) : 0;
}
static void ComputeMaskedBitsAddSub(bool Add, Value *Op0, Value *Op1, bool NSW,
@@ -1621,7 +1622,8 @@ Value *llvm::GetPointerBaseWithConstantOffset(Value *Ptr, int64_t &Offset,
// Re-sign extend from the pointer size if needed to get overflow edge cases
// right.
- unsigned PtrSize = TD.getPointerSizeInBits();
+ unsigned AS = GEP->getPointerAddressSpace();
+ unsigned PtrSize = TD.getPointerSizeInBits(AS);
if (PtrSize < 64)
Offset = SignExtend64(Offset, PtrSize);
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 86bc7aced1e..60e1741d694 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -916,7 +916,7 @@ bool LLParser::ParseOptionalAddrSpace(unsigned &AddrSpace) {
/// ParseOptionalAttrs - Parse a potentially empty attribute list. AttrKind
/// indicates what kind of attribute list this is: 0: function arg, 1: result,
/// 2: function attr.
-bool LLParser::ParseOptionalAttrs(Attributes::Builder &B, unsigned AttrKind) {
+bool LLParser::ParseOptionalAttrs(AttrBuilder &B, unsigned AttrKind) {
LocTy AttrLoc = Lex.getLoc();
bool HaveError = false;
@@ -1435,7 +1435,7 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
// Parse the argument.
LocTy ArgLoc;
Type *ArgTy = 0;
- Attributes::Builder ArgAttrs;
+ AttrBuilder ArgAttrs;
Value *V;
if (ParseType(ArgTy, ArgLoc))
return true;
@@ -1443,7 +1443,8 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
// Otherwise, handle normal operands.
if (ParseOptionalAttrs(ArgAttrs, 0) || ParseValue(ArgTy, V, PFS))
return true;
- ArgList.push_back(ParamInfo(ArgLoc, V, Attributes::get(ArgAttrs)));
+ ArgList.push_back(ParamInfo(ArgLoc, V, Attributes::get(V->getContext(),
+ ArgAttrs)));
}
Lex.Lex(); // Lex the ')'.
@@ -1475,7 +1476,7 @@ bool LLParser::ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
} else {
LocTy TypeLoc = Lex.getLoc();
Type *ArgTy = 0;
- Attributes::Builder Attrs;
+ AttrBuilder Attrs;
std::string Name;
if (ParseType(ArgTy) ||
@@ -1492,7 +1493,9 @@ bool LLParser::ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
if (!FunctionType::isValidArgumentType(ArgTy))
return Error(TypeLoc, "invalid type for function argument");
- ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attributes::get(Attrs), Name));
+ ArgList.push_back(ArgInfo(TypeLoc, ArgTy,
+ Attributes::get(ArgTy->getContext(),
+ Attrs), Name));
while (EatIfPresent(lltok::comma)) {
// Handle ... at end of arg list.
@@ -1518,7 +1521,9 @@ bool LLParser::ParseArgumentList(SmallVectorImpl<ArgInfo> &ArgList,
if (!ArgTy->isFirstClassType())
return Error(TypeLoc, "invalid type for function argument");
- ArgList.push_back(ArgInfo(TypeLoc, ArgTy, Attributes::get(Attrs), Name));
+ ArgList.push_back(ArgInfo(TypeLoc, ArgTy,
+ Attributes::get(ArgTy->getContext(), Attrs),
+ Name));
}
}
@@ -1542,7 +1547,7 @@ bool LLParser::ParseFunctionType(Type *&Result) {
for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
if (!ArgList[i].Name.empty())
return Error(ArgList[i].Loc, "argument name invalid in function type");
- if (ArgList[i].Attrs)
+ if (ArgList[i].Attrs.hasAttributes())
return Error(ArgList[i].Loc,
"argument attributes invalid in function type");
}
@@ -2672,7 +2677,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
unsigned Linkage;
unsigned Visibility;
- Attributes::Builder RetAttrs;
+ AttrBuilder RetAttrs;
CallingConv::ID CC;
Type *RetType = 0;
LocTy RetTypeLoc = Lex.getLoc();
@@ -2736,7 +2741,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
SmallVector<ArgInfo, 8> ArgList;
bool isVarArg;
- Attributes::Builder FuncAttrs;
+ AttrBuilder FuncAttrs;
std::string Section;
unsigned Alignment;
std::string GC;
@@ -2766,7 +2771,10 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
SmallVector<AttributeWithIndex, 8> Attrs;
if (RetAttrs.hasAttributes())
- Attrs.push_back(AttributeWithIndex::get(0, Attributes::get(RetAttrs)));
+ Attrs.push_back(
+ AttributeWithIndex::get(AttrListPtr::ReturnIndex,
+ Attributes::get(RetType->getContext(),
+ RetAttrs)));
for (unsigned i = 0, e = ArgList.size(); i != e; ++i) {
ParamTypeList.push_back(ArgList[i].Ty);
@@ -2775,7 +2783,10 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
}
if (FuncAttrs.hasAttributes())
- Attrs.push_back(AttributeWithIndex::get(~0, Attributes::get(FuncAttrs)));
+ Attrs.push_back(
+ AttributeWithIndex::get(AttrListPtr::FunctionIndex,
+ Attributes::get(RetType->getContext(),
+ FuncAttrs)));
AttrListPtr PAL = AttrListPtr::get(Attrs);
@@ -2795,6 +2806,9 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
ForwardRefVals.find(FunctionName);
if (FRVI != ForwardRefVals.end()) {
Fn = M->getFunction(FunctionName);
+ if (!Fn)
+ return Error(FRVI->second.second, "invalid forward reference to "
+ "function as global value!");
if (Fn->getType() != PFT)
return Error(FRVI->second.second, "invalid forward reference to "
"function '" + FunctionName + "' with wrong type!");
@@ -3248,7 +3262,7 @@ bool LLParser::ParseIndirectBr(Instruction *&Inst, PerFunctionState &PFS) {
/// OptionalAttrs 'to' TypeAndValue 'unwind' TypeAndValue
bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
LocTy CallLoc = Lex.getLoc();
- Attributes::Builder RetAttrs, FnAttrs;
+ AttrBuilder RetAttrs, FnAttrs;
CallingConv::ID CC;
Type *RetType = 0;
LocTy RetTypeLoc;
@@ -3294,7 +3308,10 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
// Set up the Attributes for the function.
SmallVector<AttributeWithIndex, 8> Attrs;
if (RetAttrs.hasAttributes())
- Attrs.push_back(AttributeWithIndex::get(0, Attributes::get(RetAttrs)));
+ Attrs.push_back(
+ AttributeWithIndex::get(AttrListPtr::ReturnIndex,
+ Attributes::get(Callee->getContext(),
+ RetAttrs)));
SmallVector<Value*, 8> Args;
@@ -3322,7 +3339,10 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
return Error(CallLoc, "not enough parameters specified for call");
if (FnAttrs.hasAttributes())
- Attrs.push_back(AttributeWithIndex::get(~0, Attributes::get(FnAttrs)));
+ Attrs.push_back(
+ AttributeWithIndex::get(AttrListPtr::FunctionIndex,
+ Attributes::get(Callee->getContext(),
+ FnAttrs)));
// Finish off the Attributes and check them
AttrListPtr PAL = AttrListPtr::get(Attrs);
@@ -3647,7 +3667,7 @@ bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) {
/// ParameterList OptionalAttrs
bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
bool isTail) {
- Attributes::Builder RetAttrs, FnAttrs;
+ AttrBuilder RetAttrs, FnAttrs;
CallingConv::ID CC;
Type *RetType = 0;
LocTy RetTypeLoc;
@@ -3690,7 +3710,10 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
// Set up the Attributes for the function.
SmallVector<AttributeWithIndex, 8> Attrs;
if (RetAttrs.hasAttributes())
- Attrs.push_back(AttributeWithIndex::get(0, Attributes::get(RetAttrs)));
+ Attrs.push_back(
+ AttributeWithIndex::get(AttrListPtr::ReturnIndex,
+ Attributes::get(Callee->getContext(),
+ RetAttrs)));
SmallVector<Value*, 8> Args;
@@ -3718,7 +3741,10 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
return Error(CallLoc, "not enough parameters specified for call");
if (FnAttrs.hasAttributes())
- Attrs.push_back(AttributeWithIndex::get(~0, Attributes::get(FnAttrs)));
+ Attrs.push_back(
+ AttributeWithIndex::get(AttrListPtr::FunctionIndex,
+ Attributes::get(Callee->getContext(),
+ FnAttrs)));
// Finish off the Attributes and check them
AttrListPtr PAL = AttrListPtr::get(Attrs);
diff --git a/lib/AsmParser/LLParser.h b/lib/AsmParser/LLParser.h
index 671eaf64291..c6bbdb27aee 100644
--- a/lib/AsmParser/LLParser.h
+++ b/lib/AsmParser/LLParser.h
@@ -175,7 +175,7 @@ namespace llvm {
bool ParseTLSModel(GlobalVariable::ThreadLocalMode &TLM);
bool ParseOptionalThreadLocal(GlobalVariable::ThreadLocalMode &TLM);
bool ParseOptionalAddrSpace(unsigned &AddrSpace);
- bool ParseOptionalAttrs(Attributes::Builder &Attrs, unsigned AttrKind);
+ bool ParseOptionalAttrs(AttrBuilder &Attrs, unsigned AttrKind);
bool ParseOptionalLinkage(unsigned &Linkage, bool &HasLinkage);
bool ParseOptionalLinkage(unsigned &Linkage) {
bool HasLinkage; return ParseOptionalLinkage(Linkage, HasLinkage);
diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp
index 8860ef065c6..279343c48c6 100644
--- a/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -211,7 +211,6 @@ namespace {
}
/// @brief Methods to support type inquiry through isa, cast, and dyn_cast.
- //static inline bool classof(const ConstantPlaceHolder *) { return true; }
static bool classof(const Value *V) {
return isa<ConstantExpr>(V) &&
cast<ConstantExpr>(V)->getOpcode() == Instruction::UserOp1;
@@ -477,14 +476,15 @@ bool BitcodeReader::ParseAttributeBlock() {
for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
Attributes ReconstitutedAttr =
- Attributes::decodeLLVMAttributesForBitcode(Record[i+1]);
+ Attributes::decodeLLVMAttributesForBitcode(Context, Record[i+1]);
Record[i+1] = ReconstitutedAttr.Raw();
}
for (unsigned i = 0, e = Record.size(); i != e; i += 2) {
- if (Attributes(Record[i+1]).hasAttributes())
+ AttrBuilder B(Record[i+1]);
+ if (B.hasAttributes())
Attrs.push_back(AttributeWithIndex::get(Record[i],
- Attributes(Record[i+1])));
+ Attributes::get(Context, B)));
}
MAttributes.push_back(AttrListPtr::get(Attrs));
@@ -891,9 +891,9 @@ bool BitcodeReader::ParseMetadata() {
}
}
-/// DecodeSignRotatedValue - Decode a signed value stored with the sign bit in
+/// decodeSignRotatedValue - Decode a signed value stored with the sign bit in
/// the LSB for dense VBR encoding.
-static uint64_t DecodeSignRotatedValue(uint64_t V) {
+uint64_t BitcodeReader::decodeSignRotatedValue(uint64_t V) {
if ((V & 1) == 0)
return V >> 1;
if (V != 1)
@@ -943,7 +943,7 @@ bool BitcodeReader::ResolveGlobalAndAliasInits() {
static APInt ReadWideAPInt(ArrayRef<uint64_t> Vals, unsigned TypeBits) {
SmallVector<uint64_t, 8> Words(Vals.size());
std::transform(Vals.begin(), Vals.end(), Words.begin(),
- DecodeSignRotatedValue);
+ BitcodeReader::decodeSignRotatedValue);
return APInt(TypeBits, Words);
}
@@ -997,7 +997,7 @@ bool BitcodeReader::ParseConstants() {
case bitc::CST_CODE_INTEGER: // INTEGER: [intval]
if (!CurTy->isIntegerTy() || Record.empty())
return Error("Invalid CST_INTEGER record");
- V = ConstantInt::get(CurTy, DecodeSignRotatedValue(Record[0]));
+ V = ConstantInt::get(CurTy, decodeSignRotatedValue(Record[0]));
break;
case bitc::CST_CODE_WIDE_INTEGER: {// WIDE_INTEGER: [n x intval]
if (!CurTy->isIntegerTy() || Record.empty())
@@ -1524,13 +1524,22 @@ bool BitcodeReader::ParseModule(bool Resume) {
// Read a record.
switch (Stream.ReadRecord(Code, Record)) {
default: break; // Default behavior, ignore unknown content.
- case bitc::MODULE_CODE_VERSION: // VERSION: [version#]
+ case bitc::MODULE_CODE_VERSION: { // VERSION: [version#]
if (Record.size() < 1)
return Error("Malformed MODULE_CODE_VERSION");
- // Only version #0 is supported so far.
- if (Record[0] != 0)
- return Error("Unknown bitstream version!");
+ // Only version #0 and #1 are supported so far.
+ unsigned module_version = Record[0];
+ switch (module_version) {
+ default: return Error("Unknown bitstream version!");
+ case 0:
+ UseRelativeIDs = false;
+ break;
+ case 1:
+ UseRelativeIDs = true;
+ break;
+ }
break;
+ }
case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N]
std::string S;
if (ConvertToString(Record, 0, S))
@@ -1797,13 +1806,6 @@ bool BitcodeReader::ParseModuleTriple(std::string &Triple) {
// Read a record.
switch (Stream.ReadRecord(Code, Record)) {
default: break; // Default behavior, ignore unknown content.
- case bitc::MODULE_CODE_VERSION: // VERSION: [version#]
- if (Record.size() < 1)
- return Error("Malformed MODULE_CODE_VERSION");
- // Only version #0 is supported so far.
- if (Record[0] != 0)
- return Error("Unknown bitstream version!");
- break;
case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N]
std::string S;
if (ConvertToString(Record, 0, S))
@@ -2016,7 +2018,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *LHS, *RHS;
if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
- getValue(Record, OpNum, LHS->getType(), RHS) ||
+ popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS) ||
OpNum+1 > Record.size())
return Error("Invalid BINOP record");
@@ -2131,8 +2133,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *TrueVal, *FalseVal, *Cond;
if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
- getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
- getValue(Record, OpNum, Type::getInt1Ty(Context), Cond))
+ popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) ||
+ popValue(Record, OpNum, NextValueNo, Type::getInt1Ty(Context), Cond))
return Error("Invalid SELECT record");
I = SelectInst::Create(Cond, TrueVal, FalseVal);
@@ -2146,7 +2148,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *TrueVal, *FalseVal, *Cond;
if (getValueTypePair(Record, OpNum, NextValueNo, TrueVal) ||
- getValue(Record, OpNum, TrueVal->getType(), FalseVal) ||
+ popValue(Record, OpNum, NextValueNo, TrueVal->getType(), FalseVal) ||
getValueTypePair(Record, OpNum, NextValueNo, Cond))
return Error("Invalid SELECT record");
@@ -2171,7 +2173,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *Vec, *Idx;
if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
- getValue(Record, OpNum, Type::getInt32Ty(Context), Idx))
+ popValue(Record, OpNum, NextValueNo, Type::getInt32Ty(Context), Idx))
return Error("Invalid EXTRACTELT record");
I = ExtractElementInst::Create(Vec, Idx);
InstructionList.push_back(I);
@@ -2182,9 +2184,9 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *Vec, *Elt, *Idx;
if (getValueTypePair(Record, OpNum, NextValueNo, Vec) ||
- getValue(Record, OpNum,
+ popValue(Record, OpNum, NextValueNo,
cast<VectorType>(Vec->getType())->getElementType(), Elt) ||
- getValue(Record, OpNum, Type::getInt32Ty(Context), Idx))
+ popValue(Record, OpNum, NextValueNo, Type::getInt32Ty(Context), Idx))
return Error("Invalid INSERTELT record");
I = InsertElementInst::Create(Vec, Elt, Idx);
InstructionList.push_back(I);
@@ -2195,7 +2197,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *Vec1, *Vec2, *Mask;
if (getValueTypePair(Record, OpNum, NextValueNo, Vec1) ||
- getValue(Record, OpNum, Vec1->getType(), Vec2))
+ popValue(Record, OpNum, NextValueNo, Vec1->getType(), Vec2))
return Error("Invalid SHUFFLEVEC record");
if (getValueTypePair(Record, OpNum, NextValueNo, Mask))
@@ -2215,7 +2217,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *LHS, *RHS;
if (getValueTypePair(Record, OpNum, NextValueNo, LHS) ||
- getValue(Record, OpNum, LHS->getType(), RHS) ||
+ popValue(Record, OpNum, NextValueNo, LHS->getType(), RHS) ||
OpNum+1 != Record.size())
return Error("Invalid CMP record");
@@ -2260,7 +2262,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
}
else {
BasicBlock *FalseDest = getBasicBlock(Record[1]);
- Value *Cond = getFnValueByID(Record[2], Type::getInt1Ty(Context));
+ Value *Cond = getValue(Record, 2, NextValueNo,
+ Type::getInt1Ty(Context));
if (FalseDest == 0 || Cond == 0)
return Error("Invalid BR record");
I = BranchInst::Create(TrueDest, FalseDest, Cond);
@@ -2276,7 +2279,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
Type *OpTy = getTypeByID(Record[1]);
unsigned ValueBitWidth = cast<IntegerType>(OpTy)->getBitWidth();
- Value *Cond = getFnValueByID(Record[2], OpTy);
+ Value *Cond = getValue(Record, 2, NextValueNo, OpTy);
BasicBlock *Default = getBasicBlock(Record[3]);
if (OpTy == 0 || Cond == 0 || Default == 0)
return Error("Invalid SWITCH record");
@@ -2331,7 +2334,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
if (Record.size() < 3 || (Record.size() & 1) == 0)
return Error("Invalid SWITCH record");
Type *OpTy = getTypeByID(Record[0]);
- Value *Cond = getFnValueByID(Record[1], OpTy);
+ Value *Cond = getValue(Record, 1, NextValueNo, OpTy);
BasicBlock *Default = getBasicBlock(Record[2]);
if (OpTy == 0 || Cond == 0 || Default == 0)
return Error("Invalid SWITCH record");
@@ -2355,7 +2358,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
if (Record.size() < 2)
return Error("Invalid INDIRECTBR record");
Type *OpTy = getTypeByID(Record[0]);
- Value *Address = getFnValueByID(Record[1], OpTy);
+ Value *Address = getValue(Record, 1, NextValueNo, OpTy);
if (OpTy == 0 || Address == 0)
return Error("Invalid INDIRECTBR record");
unsigned NumDests = Record.size()-2;
@@ -2397,7 +2400,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
SmallVector<Value*, 16> Ops;
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i, ++OpNum) {
- Ops.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
+ Ops.push_back(getValue(Record, OpNum, NextValueNo,
+ FTy->getParamType(i)));
if (Ops.back() == 0) return Error("Invalid INVOKE record");
}
@@ -2444,7 +2448,14 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
InstructionList.push_back(PN);
for (unsigned i = 0, e = Record.size()-1; i != e; i += 2) {
- Value *V = getFnValueByID(Record[1+i], Ty);
+ Value *V;
+ // With the new function encoding, it is possible that operands have
+ // negative IDs (for forward references). Use a signed VBR
+ // representation to keep the encoding small.
+ if (UseRelativeIDs)
+ V = getValueSigned(Record, 1+i, NextValueNo, Ty);
+ else
+ V = getValue(Record, 1+i, NextValueNo, Ty);
BasicBlock *BB = getBasicBlock(Record[2+i]);
if (!V || !BB) return Error("Invalid PHI record");
PN->addIncoming(V, BB);
@@ -2542,7 +2553,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *Val, *Ptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
- getValue(Record, OpNum,
+ popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
OpNum+2 != Record.size())
return Error("Invalid STORE record");
@@ -2556,7 +2567,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *Val, *Ptr;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
- getValue(Record, OpNum,
+ popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
OpNum+4 != Record.size())
return Error("Invalid STOREATOMIC record");
@@ -2579,9 +2590,9 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *Ptr, *Cmp, *New;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
- getValue(Record, OpNum,
+ popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getElementType(), Cmp) ||
- getValue(Record, OpNum,
+ popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getElementType(), New) ||
OpNum+3 != Record.size())
return Error("Invalid CMPXCHG record");
@@ -2599,7 +2610,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
unsigned OpNum = 0;
Value *Ptr, *Val;
if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
- getValue(Record, OpNum,
+ popValue(Record, OpNum, NextValueNo,
cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
OpNum+4 != Record.size())
return Error("Invalid ATOMICRMW record");
@@ -2653,7 +2664,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
if (FTy->getParamType(i)->isLabelTy())
Args.push_back(getBasicBlock(Record[OpNum]));
else
- Args.push_back(getFnValueByID(Record[OpNum], FTy->getParamType(i)));
+ Args.push_back(getValue(Record, OpNum, NextValueNo,
+ FTy->getParamType(i)));
if (Args.back() == 0) return Error("Invalid CALL record");
}
@@ -2682,7 +2694,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) {
if (Record.size() < 3)
return Error("Invalid VAARG record");
Type *OpTy = getTypeByID(Record[0]);
- Value *Op = getFnValueByID(Record[1], OpTy);
+ Value *Op = getValue(Record, 1, NextValueNo, OpTy);
Type *ResTy = getTypeByID(Record[2]);
if (!OpTy || !Op || !ResTy)
return Error("Invalid VAARG record");
diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h
index e7c4e94f785..3d5c0eb4def 100644
--- a/lib/Bitcode/Reader/BitcodeReader.h
+++ b/lib/Bitcode/Reader/BitcodeReader.h
@@ -179,18 +179,27 @@ class BitcodeReader : public GVMaterializer {
typedef std::pair<unsigned, GlobalVariable*> BlockAddrRefTy;
DenseMap<Function*, std::vector<BlockAddrRefTy> > BlockAddrFwdRefs;
+ /// UseRelativeIDs - Indicates that we are using a new encoding for
+ /// instruction operands where most operands in the current
+ /// FUNCTION_BLOCK are encoded relative to the instruction number,
+ /// for a more compact encoding. Some instruction operands are not
+ /// relative to the instruction ID: basic block numbers, and types.
+ /// Once the old style function blocks have been phased out, we would
+ /// not need this flag.
+ bool UseRelativeIDs;
+
public:
explicit BitcodeReader(MemoryBuffer *buffer, LLVMContext &C)
: Context(C), TheModule(0), Buffer(buffer), BufferOwned(false),
LazyStreamer(0), NextUnreadBit(0), SeenValueSymbolTable(false),
ErrorString(0), ValueList(C), MDValueList(C),
- SeenFirstFunctionBody(false) {
+ SeenFirstFunctionBody(false), UseRelativeIDs(false) {
}
explicit BitcodeReader(DataStreamer *streamer, LLVMContext &C)
: Context(C), TheModule(0), Buffer(0), BufferOwned(false),
LazyStreamer(streamer), NextUnreadBit(0), SeenValueSymbolTable(false),
ErrorString(0), ValueList(C), MDValueList(C),
- SeenFirstFunctionBody(false) {
+ SeenFirstFunctionBody(false), UseRelativeIDs(false) {
}
~BitcodeReader() {
FreeState();
@@ -223,6 +232,9 @@ public:
/// @brief Cheap mechanism to just extract module triple
/// @returns true if an error occurred.
bool ParseTriple(std::string &Triple);
+
+ static uint64_t decodeSignRotatedValue(uint64_t V);
+
private:
Type *getTypeByID(unsigned ID);
Value *getFnValueByID(unsigned ID, Type *Ty) {
@@ -247,6 +259,9 @@ private:
unsigned InstNum, Value *&ResVal) {
if (Slot == Record.size()) return true;
unsigned ValNo = (unsigned)Record[Slot++];
+ // Adjust the ValNo, if it was encoded relative to the InstNum.
+ if (UseRelativeIDs)
+ ValNo = InstNum - ValNo;
if (ValNo < InstNum) {
// If this is not a forward reference, just return the value we already
// have.
@@ -255,20 +270,54 @@ private:
} else if (Slot == Record.size()) {
return true;
}
-
+
unsigned TypeNo = (unsigned)Record[Slot++];
ResVal = getFnValueByID(ValNo, getTypeByID(TypeNo));
return ResVal == 0;
}
- bool getValue(SmallVector<uint64_t, 64> &Record, unsigned &Slot,
- Type *Ty, Value *&ResVal) {
- if (Slot == Record.size()) return true;
- unsigned ValNo = (unsigned)Record[Slot++];
- ResVal = getFnValueByID(ValNo, Ty);
+
+ /// popValue - Read a value out of the specified record from slot 'Slot'.
+ /// Increment Slot past the number of slots used by the value in the record.
+ /// Return true if there is an error.
+ bool popValue(SmallVector<uint64_t, 64> &Record, unsigned &Slot,
+ unsigned InstNum, Type *Ty, Value *&ResVal) {
+ if (getValue(Record, Slot, InstNum, Ty, ResVal))
+ return true;
+ // All values currently take a single record slot.
+ ++Slot;
+ return false;
+ }
+
+ /// getValue -- Like popValue, but does not increment the Slot number.
+ bool getValue(SmallVector<uint64_t, 64> &Record, unsigned Slot,
+ unsigned InstNum, Type *Ty, Value *&ResVal) {
+ ResVal = getValue(Record, Slot, InstNum, Ty);
return ResVal == 0;
}
-
+ /// getValue -- Version of getValue that returns ResVal directly,
+ /// or 0 if there is an error.
+ Value *getValue(SmallVector<uint64_t, 64> &Record, unsigned Slot,
+ unsigned InstNum, Type *Ty) {
+ if (Slot == Record.size()) return 0;
+ unsigned ValNo = (unsigned)Record[Slot];
+ // Adjust the ValNo, if it was encoded relative to the InstNum.
+ if (UseRelativeIDs)
+ ValNo = InstNum - ValNo;
+ return getFnValueByID(ValNo, Ty);
+ }
+
+ /// getValueSigned -- Like getValue, but decodes signed VBRs.
+ Value *getValueSigned(SmallVector<uint64_t, 64> &Record, unsigned Slot,
+ unsigned InstNum, Type *Ty) {
+ if (Slot == Record.size()) return 0;
+ unsigned ValNo = (unsigned)decodeSignRotatedValue(Record[Slot]);
+ // Adjust the ValNo, if it was encoded relative to the InstNum.
+ if (UseRelativeIDs)
+ ValNo = InstNum - ValNo;
+ return getFnValueByID(ValNo, Ty);
+ }
+
bool ParseModule(bool Resume);
bool ParseAttributeBlock();
bool ParseTypeTable();
diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp
index b3f1bb13a9f..60c657ae6dd 100644
--- a/lib/Bitcode/Writer/BitcodeWriter.cpp
+++ b/lib/Bitcode/Writer/BitcodeWriter.cpp
@@ -41,8 +41,6 @@ EnablePreserveUseListOrdering("enable-bc-uselist-preserve",
/// These are manifest constants used by the bitcode writer. They do not need to
/// be kept in sync with the reader, but need to be consistent within this file.
enum {
- CurVersion = 0,
-
// VALUE_SYMTAB_BLOCK abbrev id's.
VST_ENTRY_8_ABBREV = bitc::FIRST_APPLICATION_ABBREV,
VST_ENTRY_7_ABBREV,
@@ -722,16 +720,20 @@ static void WriteModuleMetadataStore(const Module *M, BitstreamWriter &Stream) {
Stream.ExitBlock();
}
+static void emitSignedInt64(SmallVectorImpl<uint64_t> &Vals, uint64_t V) {
+ if ((int64_t)V >= 0)
+ Vals.push_back(V << 1);
+ else
+ Vals.push_back((-V << 1) | 1);
+}
+
static void EmitAPInt(SmallVectorImpl<uint64_t> &Vals,
unsigned &Code, unsigned &AbbrevToUse, const APInt &Val,
bool EmitSizeForWideNumbers = false
) {
if (Val.getBitWidth() <= 64) {
uint64_t V = Val.getSExtValue();
- if ((int64_t)V >= 0)
- Vals.push_back(V << 1);
- else
- Vals.push_back((-V << 1) | 1);
+ emitSignedInt64(Vals, V);
Code = bitc::CST_CODE_INTEGER;
AbbrevToUse = CONSTANTS_INTEGER_ABBREV;
} else {
@@ -747,11 +749,7 @@ static void EmitAPInt(SmallVectorImpl<uint64_t> &Vals,
const uint64_t *RawWords = Val.getRawData();
for (unsigned i = 0; i != NWords; ++i) {
- int64_t V = RawWords[i];
- if (V >= 0)
- Vals.push_back(V << 1);
- else
- Vals.push_back((-V << 1) | 1);
+ emitSignedInt64(Vals, RawWords[i]);
}
Code = bitc::CST_CODE_WIDE_INTEGER;
}
@@ -1025,12 +1023,13 @@ static void WriteModuleConstants(const ValueEnumerator &VE,
///
/// This function adds V's value ID to Vals. If the value ID is higher than the
/// instruction ID, then it is a forward reference, and it also includes the
-/// type ID.
+/// type ID. The value ID that is written is encoded relative to the InstID.
static bool PushValueAndType(const Value *V, unsigned InstID,
SmallVector<unsigned, 64> &Vals,
ValueEnumerator &VE) {
unsigned ValID = VE.getValueID(V);
- Vals.push_back(ValID);
+ // Make encoding relative to the InstID.
+ Vals.push_back(InstID - ValID);
if (ValID >= InstID) {
Vals.push_back(VE.getTypeID(V->getType()));
return true;
@@ -1038,6 +1037,30 @@ static bool PushValueAndType(const Value *V, unsigned InstID,
return false;
}
+/// pushValue - Like PushValueAndType, but where the type of the value is
+/// omitted (perhaps it was already encoded in an earlier operand).
+static void pushValue(const Value *V, unsigned InstID,
+ SmallVector<unsigned, 64> &Vals,
+ ValueEnumerator &VE) {
+ unsigned ValID = VE.getValueID(V);
+ Vals.push_back(InstID - ValID);
+}
+
+static void pushValue64(const Value *V, unsigned InstID,
+ SmallVector<uint64_t, 128> &Vals,
+ ValueEnumerator &VE) {
+ uint64_t ValID = VE.getValueID(V);
+ Vals.push_back(InstID - ValID);
+}
+
+static void pushValueSigned(const Value *V, unsigned InstID,
+ SmallVector<uint64_t, 128> &Vals,
+ ValueEnumerator &VE) {
+ unsigned ValID = VE.getValueID(V);
+ int64_t diff = ((int32_t)InstID - (int32_t)ValID);
+ emitSignedInt64(Vals, diff);
+}
+
/// WriteInstruction - Emit an instruction to the specified stream.
static void WriteInstruction(const Instruction &I, unsigned InstID,
ValueEnumerator &VE, BitstreamWriter &Stream,
@@ -1058,7 +1081,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Code = bitc::FUNC_CODE_INST_BINOP;
if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))
AbbrevToUse = FUNCTION_INST_BINOP_ABBREV;
- Vals.push_back(VE.getValueID(I.getOperand(1)));
+ pushValue(I.getOperand(1), InstID, Vals, VE);
Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode()));
uint64_t Flags = GetOptimizationFlags(&I);
if (Flags != 0) {
@@ -1096,32 +1119,32 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::Select:
Code = bitc::FUNC_CODE_INST_VSELECT;
PushValueAndType(I.getOperand(1), InstID, Vals, VE);
- Vals.push_back(VE.getValueID(I.getOperand(2)));
+ pushValue(I.getOperand(2), InstID, Vals, VE);
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
break;
case Instruction::ExtractElement:
Code = bitc::FUNC_CODE_INST_EXTRACTELT;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
- Vals.push_back(VE.getValueID(I.getOperand(1)));
+ pushValue(I.getOperand(1), InstID, Vals, VE);
break;
case Instruction::InsertElement:
Code = bitc::FUNC_CODE_INST_INSERTELT;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
- Vals.push_back(VE.getValueID(I.getOperand(1)));
- Vals.push_back(VE.getValueID(I.getOperand(2)));
+ pushValue(I.getOperand(1), InstID, Vals, VE);
+ pushValue(I.getOperand(2), InstID, Vals, VE);
break;
case Instruction::ShuffleVector:
Code = bitc::FUNC_CODE_INST_SHUFFLEVEC;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
- Vals.push_back(VE.getValueID(I.getOperand(1)));
- Vals.push_back(VE.getValueID(I.getOperand(2)));
+ pushValue(I.getOperand(1), InstID, Vals, VE);
+ pushValue(I.getOperand(2), InstID, Vals, VE);
break;
case Instruction::ICmp:
case Instruction::FCmp:
// compare returning Int1Ty or vector of Int1Ty
Code = bitc::FUNC_CODE_INST_CMP2;
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
- Vals.push_back(VE.getValueID(I.getOperand(1)));
+ pushValue(I.getOperand(1), InstID, Vals, VE);
Vals.push_back(cast<CmpInst>(I).getPredicate());
break;
@@ -1147,7 +1170,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Vals.push_back(VE.getValueID(II.getSuccessor(0)));
if (II.isConditional()) {
Vals.push_back(VE.getValueID(II.getSuccessor(1)));
- Vals.push_back(VE.getValueID(II.getCondition()));
+ pushValue(II.getCondition(), InstID, Vals, VE);
}
}
break;
@@ -1164,7 +1187,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
Vals64.push_back(SwitchRecordHeader);
Vals64.push_back(VE.getTypeID(SI.getCondition()->getType()));
- Vals64.push_back(VE.getValueID(SI.getCondition()));
+ pushValue64(SI.getCondition(), InstID, Vals64, VE);
Vals64.push_back(VE.getValueID(SI.getDefaultDest()));
Vals64.push_back(SI.getNumCases());
for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end();
@@ -1215,7 +1238,9 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::IndirectBr:
Code = bitc::FUNC_CODE_INST_INDIRECTBR;
Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
- for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
+ // Encode the address operand as relative, but not the basic blocks.
+ pushValue(I.getOperand(0), InstID, Vals, VE);
+ for (unsigned i = 1, e = I.getNumOperands(); i != e; ++i)
Vals.push_back(VE.getValueID(I.getOperand(i)));
break;
@@ -1234,7 +1259,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
// Emit value #'s for the fixed parameters.
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
- Vals.push_back(VE.getValueID(I.getOperand(i))); // fixed param.
+ pushValue(I.getOperand(i), InstID, Vals, VE); // fixed param.
// Emit type/value pairs for varargs params.
if (FTy->isVarArg()) {
@@ -1256,12 +1281,19 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::PHI: {
const PHINode &PN = cast<PHINode>(I);
Code = bitc::FUNC_CODE_INST_PHI;
- Vals.push_back(VE.getTypeID(PN.getType()));
+ // With the newer instruction encoding, forward references could give
+ // negative valued IDs. This is most common for PHIs, so we use
+ // signed VBRs.
+ SmallVector<uint64_t, 128> Vals64;
+ Vals64.push_back(VE.getTypeID(PN.getType()));
for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) {
- Vals.push_back(VE.getValueID(PN.getIncomingValue(i)));
- Vals.push_back(VE.getValueID(PN.getIncomingBlock(i)));
+ pushValueSigned(PN.getIncomingValue(i), InstID, Vals64, VE);
+ Vals64.push_back(VE.getValueID(PN.getIncomingBlock(i)));
}
- break;
+ // Emit a Vals64 vector and exit.
+ Stream.EmitRecord(Code, Vals64, AbbrevToUse);
+ Vals64.clear();
+ return;
}
case Instruction::LandingPad: {
@@ -1311,7 +1343,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
else
Code = bitc::FUNC_CODE_INST_STORE;
PushValueAndType(I.getOperand(1), InstID, Vals, VE); // ptrty + ptr
- Vals.push_back(VE.getValueID(I.getOperand(0))); // val.
+ pushValue(I.getOperand(0), InstID, Vals, VE); // val.
Vals.push_back(Log2_32(cast<StoreInst>(I).getAlignment())+1);
Vals.push_back(cast<StoreInst>(I).isVolatile());
if (cast<StoreInst>(I).isAtomic()) {
@@ -1322,8 +1354,8 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::AtomicCmpXchg:
Code = bitc::FUNC_CODE_INST_CMPXCHG;
PushValueAndType(I.getOperand(0), InstID, Vals, VE); // ptrty + ptr
- Vals.push_back(VE.getValueID(I.getOperand(1))); // cmp.
- Vals.push_back(VE.getValueID(I.getOperand(2))); // newval.
+ pushValue(I.getOperand(1), InstID, Vals, VE); // cmp.
+ pushValue(I.getOperand(2), InstID, Vals, VE); // newval.
Vals.push_back(cast<AtomicCmpXchgInst>(I).isVolatile());
Vals.push_back(GetEncodedOrdering(
cast<AtomicCmpXchgInst>(I).getOrdering()));
@@ -1333,7 +1365,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::AtomicRMW:
Code = bitc::FUNC_CODE_INST_ATOMICRMW;
PushValueAndType(I.getOperand(0), InstID, Vals, VE); // ptrty + ptr
- Vals.push_back(VE.getValueID(I.getOperand(1))); // val.
+ pushValue(I.getOperand(1), InstID, Vals, VE); // val.
Vals.push_back(GetEncodedRMWOperation(
cast<AtomicRMWInst>(I).getOperation()));
Vals.push_back(cast<AtomicRMWInst>(I).isVolatile());
@@ -1358,8 +1390,13 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
PushValueAndType(CI.getCalledValue(), InstID, Vals, VE); // Callee
// Emit value #'s for the fixed parameters.
- for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
- Vals.push_back(VE.getValueID(CI.getArgOperand(i))); // fixed param.
+ for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i) {
+ // Check for labels (can happen with asm labels).
+ if (FTy->getParamType(i)->isLabelTy())
+ Vals.push_back(VE.getValueID(CI.getArgOperand(i)));
+ else
+ pushValue(CI.getArgOperand(i), InstID, Vals, VE); // fixed param.
+ }
// Emit type/value pairs for varargs params.
if (FTy->isVarArg()) {
@@ -1372,7 +1409,7 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
case Instruction::VAArg:
Code = bitc::FUNC_CODE_INST_VAARG;
Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); // valistty
- Vals.push_back(VE.getValueID(I.getOperand(0))); // valist.
+ pushValue(I.getOperand(0), InstID, Vals, VE); // valist.
Vals.push_back(VE.getTypeID(I.getType())); // restype.
break;
}
@@ -1514,8 +1551,8 @@ static void WriteFunction(const Function &F, ValueEnumerator &VE,
// Emit blockinfo, which defines the standard abbreviations etc.
static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) {
// We only want to emit block info records for blocks that have multiple
- // instances: CONSTANTS_BLOCK, FUNCTION_BLOCK and VALUE_SYMTAB_BLOCK. Other
- // blocks can defined their abbrevs inline.
+ // instances: CONSTANTS_BLOCK, FUNCTION_BLOCK and VALUE_SYMTAB_BLOCK.
+ // Other blocks can define their abbrevs inline.
Stream.EnterBlockInfoBlock(2);
{ // 8-bit fixed-width VST_ENTRY/VST_BBENTRY strings.
@@ -1773,12 +1810,10 @@ static void WriteModuleUseLists(const Module *M, ValueEnumerator &VE,
static void WriteModule(const Module *M, BitstreamWriter &Stream) {
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
- // Emit the version number if it is non-zero.
- if (CurVersion) {
- SmallVector<unsigned, 1> Vals;
- Vals.push_back(CurVersion);
- Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
- }
+ SmallVector<unsigned, 1> Vals;
+ unsigned CurVersion = 1;
+ Vals.push_back(CurVersion);
+ Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
// Analyze the module, enumerating globals, functions, etc.
ValueEnumerator VE(M);
diff --git a/lib/CodeGen/AggressiveAntiDepBreaker.cpp b/lib/CodeGen/AggressiveAntiDepBreaker.cpp
index 205480a4692..7a1c049d522 100644
--- a/lib/CodeGen/AggressiveAntiDepBreaker.cpp
+++ b/lib/CodeGen/AggressiveAntiDepBreaker.cpp
@@ -635,7 +635,7 @@ bool AggressiveAntiDepBreaker::FindSuitableFreeRegisters(
--R;
const unsigned NewSuperReg = Order[R];
// Don't consider non-allocatable registers
- if (!RegClassInfo.isAllocatable(NewSuperReg)) continue;
+ if (!MRI.isAllocatable(NewSuperReg)) continue;
// Don't replace a register with itself.
if (NewSuperReg == SuperReg) continue;
@@ -818,7 +818,7 @@ unsigned AggressiveAntiDepBreaker::BreakAntiDependencies(
DEBUG(dbgs() << "\tAntidep reg: " << TRI->getName(AntiDepReg));
assert(AntiDepReg != 0 && "Anti-dependence on reg0?");
- if (!RegClassInfo.isAllocatable(AntiDepReg)) {
+ if (!MRI.isAllocatable(AntiDepReg)) {
// Don't break anti-dependencies on non-allocatable registers.
DEBUG(dbgs() << " (non-allocatable)\n");
continue;
diff --git a/lib/CodeGen/AllocationOrder.cpp b/lib/CodeGen/AllocationOrder.cpp
index 32ad34a76d6..7cde136c5ef 100644
--- a/lib/CodeGen/AllocationOrder.cpp
+++ b/lib/CodeGen/AllocationOrder.cpp
@@ -29,6 +29,7 @@ AllocationOrder::AllocationOrder(unsigned VirtReg,
const TargetRegisterClass *RC = VRM.getRegInfo().getRegClass(VirtReg);
std::pair<unsigned, unsigned> HintPair =
VRM.getRegInfo().getRegAllocationHint(VirtReg);
+ const MachineRegisterInfo &MRI = VRM.getRegInfo();
// HintPair.second is a register, phys or virt.
Hint = HintPair.second;
@@ -52,7 +53,7 @@ AllocationOrder::AllocationOrder(unsigned VirtReg,
unsigned *P = new unsigned[Order.size()];
Begin = P;
for (unsigned i = 0; i != Order.size(); ++i)
- if (!RCI.isReserved(Order[i]))
+ if (!MRI.isReserved(Order[i]))
*P++ = Order[i];
End = P;
@@ -69,7 +70,7 @@ AllocationOrder::AllocationOrder(unsigned VirtReg,
// The hint must be a valid physreg for allocation.
if (Hint && (!TargetRegisterInfo::isPhysicalRegister(Hint) ||
- !RC->contains(Hint) || RCI.isReserved(Hint)))
+ !RC->contains(Hint) || MRI.isReserved(Hint)))
Hint = 0;
}
diff --git a/lib/CodeGen/Analysis.cpp b/lib/CodeGen/Analysis.cpp
index 09e30eba579..5162ad762e7 100644
--- a/lib/CodeGen/Analysis.cpp
+++ b/lib/CodeGen/Analysis.cpp
@@ -314,8 +314,8 @@ bool llvm::isInTailCallPosition(ImmutableCallSite CS, Attributes CalleeRetAttr,
// the return. Ignore noalias because it doesn't affect the call sequence.
const Function *F = ExitBB->getParent();
Attributes CallerRetAttr = F->getAttributes().getRetAttributes();
- if (Attributes::Builder(CalleeRetAttr ^ CallerRetAttr)
- .removeAttribute(Attributes::NoAlias).hasAttributes())
+ if (AttrBuilder(CalleeRetAttr).removeAttribute(Attributes::NoAlias) !=
+ AttrBuilder(CallerRetAttr).removeAttribute(Attributes::NoAlias))
return false;
// It's not safe to eliminate the sign / zero extension of the return value.
@@ -356,7 +356,7 @@ bool llvm::isInTailCallPosition(SelectionDAG &DAG, SDNode *Node,
// Conservatively require the attributes of the call to match those of
// the return. Ignore noalias because it doesn't affect the call sequence.
Attributes CallerRetAttr = F->getAttributes().getRetAttributes();
- if (Attributes::Builder(CallerRetAttr)
+ if (AttrBuilder(CallerRetAttr)
.removeAttribute(Attributes::NoAlias).hasAttributes())
return false;
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d74a70362a2..4de98da655b 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -385,7 +385,8 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
// - __tlv_bootstrap - used to make sure support exists
// - spare pointer, used when mapped by the runtime
// - pointer to mangled symbol above with initializer
- unsigned PtrSize = TD->getPointerSizeInBits()/8;
+ unsigned AS = GV->getType()->getAddressSpace();
+ unsigned PtrSize = TD->getPointerSizeInBits(AS)/8;
OutStreamer.EmitSymbolValue(GetExternalSymbolSymbol("_tlv_bootstrap"),
PtrSize, 0);
OutStreamer.EmitIntValue(0, PtrSize, 0);
@@ -1299,7 +1300,7 @@ void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) {
// Emit the function pointers in the target-specific order
const DataLayout *TD = TM.getDataLayout();
- unsigned Align = Log2_32(TD->getPointerPrefAlignment());
+ unsigned Align = Log2_32(TD->getPointerPrefAlignment(0));
std::stable_sort(Structors.begin(), Structors.end(), priority_order);
for (unsigned i = 0, e = Structors.size(); i != e; ++i) {
const MCSection *OutputSection =
@@ -1480,8 +1481,9 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) {
if (Offset == 0)
return Base;
+ unsigned AS = cast<PointerType>(CE->getType())->getAddressSpace();
// Truncate/sext the offset to the pointer size.
- unsigned Width = TD.getPointerSizeInBits();
+ unsigned Width = TD.getPointerSizeInBits(AS);
if (Width < 64)
Offset = SignExtend64(Offset, Width);
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index d94e1fe61bf..6c17af2e8c8 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -112,7 +112,7 @@ unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
switch (Encoding & 0x07) {
default: llvm_unreachable("Invalid encoded value.");
- case dwarf::DW_EH_PE_absptr: return TM.getDataLayout()->getPointerSize();
+ case dwarf::DW_EH_PE_absptr: return TM.getDataLayout()->getPointerSize(0);
case dwarf::DW_EH_PE_udata2: return 2;
case dwarf::DW_EH_PE_udata4: return 4;
case dwarf::DW_EH_PE_udata8: return 8;
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index 4d73b3c2226..73e18cd817b 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -200,7 +200,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const {
case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return;
case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return;
case dwarf::DW_FORM_addr:
- Size = Asm->getDataLayout().getPointerSize(); break;
+ Size = Asm->getDataLayout().getPointerSize(0); break;
default: llvm_unreachable("DIE Value form not supported yet");
}
Asm->OutStreamer.EmitIntValue(Integer, Size, 0/*addrspace*/);
@@ -222,7 +222,7 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const {
case dwarf::DW_FORM_data8: return sizeof(int64_t);
case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer);
case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer);
- case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize();
+ case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize(0);
default: llvm_unreachable("DIE Value form not supported yet");
}
}
@@ -249,7 +249,7 @@ void DIELabel::EmitValue(AsmPrinter *AP, unsigned Form) const {
unsigned DIELabel::SizeOf(AsmPrinter *AP, unsigned Form) const {
if (Form == dwarf::DW_FORM_data4) return 4;
if (Form == dwarf::DW_FORM_strp) return 4;
- return AP->getDataLayout().getPointerSize();
+ return AP->getDataLayout().getPointerSize(0);
}
#ifndef NDEBUG
@@ -273,7 +273,7 @@ void DIEDelta::EmitValue(AsmPrinter *AP, unsigned Form) const {
unsigned DIEDelta::SizeOf(AsmPrinter *AP, unsigned Form) const {
if (Form == dwarf::DW_FORM_data4) return 4;
if (Form == dwarf::DW_FORM_strp) return 4;
- return AP->getDataLayout().getPointerSize();
+ return AP->getDataLayout().getPointerSize(0);
}
#ifndef NDEBUG
diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h
index f93ea1b045b..28a96f3b2b6 100644
--- a/lib/CodeGen/AsmPrinter/DIE.h
+++ b/lib/CodeGen/AsmPrinter/DIE.h
@@ -214,9 +214,6 @@ namespace llvm {
///
virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const = 0;
- // Implement isa/cast/dyncast.
- static bool classof(const DIEValue *) { return true; }
-
#ifndef NDEBUG
virtual void print(raw_ostream &O) = 0;
void dump();
@@ -257,7 +254,6 @@ namespace llvm {
virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const;
// Implement isa/cast/dyncast.
- static bool classof(const DIEInteger *) { return true; }
static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
#ifndef NDEBUG
@@ -286,7 +282,6 @@ namespace llvm {
virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const;
// Implement isa/cast/dyncast.
- static bool classof(const DIELabel *) { return true; }
static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
#ifndef NDEBUG
@@ -313,7 +308,6 @@ namespace llvm {
virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const;
// Implement isa/cast/dyncast.
- static bool classof(const DIEDelta *) { return true; }
static bool classof(const DIEValue *D) { return D->getType() == isDelta; }
#ifndef NDEBUG
@@ -343,7 +337,6 @@ namespace llvm {
}
// Implement isa/cast/dyncast.
- static bool classof(const DIEEntry *) { return true; }
static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
#ifndef NDEBUG
@@ -383,7 +376,6 @@ namespace llvm {
virtual unsigned SizeOf(AsmPrinter *AP, unsigned Form) const;
// Implement isa/cast/dyncast.
- static bool classof(const DIEBlock *) { return true; }
static bool classof(const DIEValue *E) { return E->getType() == isBlock; }
#ifndef NDEBUG
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 6acf19ee8c4..df162e07a88 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -384,7 +384,7 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
// DW_AT_ranges appropriately.
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
DebugRangeSymbols.size()
- * Asm->getDataLayout().getPointerSize());
+ * Asm->getDataLayout().getPointerSize(0));
for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
RE = Ranges.end(); RI != RE; ++RI) {
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
@@ -450,7 +450,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
// DW_AT_ranges appropriately.
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
DebugRangeSymbols.size()
- * Asm->getDataLayout().getPointerSize());
+ * Asm->getDataLayout().getPointerSize(0));
for (SmallVector<InsnRange, 4>::const_iterator RI = Ranges.begin(),
RE = Ranges.end(); RI != RE; ++RI) {
DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
@@ -1765,7 +1765,7 @@ void DwarfDebug::emitDebugInfo() {
Asm->EmitSectionOffset(Asm->GetTempSymbol("abbrev_begin"),
DwarfAbbrevSectionSym);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
- Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
+ Asm->EmitInt8(Asm->getDataLayout().getPointerSize(0));
emitDIE(Die);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", TheCU->getID()));
@@ -1811,14 +1811,14 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
Asm->EmitInt8(0);
Asm->OutStreamer.AddComment("Op size");
- Asm->EmitInt8(Asm->getDataLayout().getPointerSize() + 1);
+ Asm->EmitInt8(Asm->getDataLayout().getPointerSize(0) + 1);
Asm->OutStreamer.AddComment("DW_LNE_set_address");
Asm->EmitInt8(dwarf::DW_LNE_set_address);
Asm->OutStreamer.AddComment("Section end label");
Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd),
- Asm->getDataLayout().getPointerSize(),
+ Asm->getDataLayout().getPointerSize(0),
0/*AddrSpace*/);
// Mark end of matrix.
@@ -2047,7 +2047,7 @@ void DwarfDebug::emitDebugLoc() {
// Start the dwarf loc section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfLocSection());
- unsigned char Size = Asm->getDataLayout().getPointerSize();
+ unsigned char Size = Asm->getDataLayout().getPointerSize(0);
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
unsigned index = 1;
for (SmallVector<DotDebugLocEntry, 4>::iterator
@@ -2144,7 +2144,7 @@ void DwarfDebug::emitDebugRanges() {
// Start the dwarf ranges section.
Asm->OutStreamer.SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
- unsigned char Size = Asm->getDataLayout().getPointerSize();
+ unsigned char Size = Asm->getDataLayout().getPointerSize(0);
for (SmallVector<const MCSymbol *, 8>::iterator
I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end();
I != E; ++I) {
@@ -2202,7 +2202,7 @@ void DwarfDebug::emitDebugInlineInfo() {
Asm->OutStreamer.AddComment("Dwarf Version");
Asm->EmitInt16(dwarf::DWARF_VERSION);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
- Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
+ Asm->EmitInt8(Asm->getDataLayout().getPointerSize(0));
for (SmallVector<const MDNode *, 4>::iterator I = InlinedSPNodes.begin(),
E = InlinedSPNodes.end(); I != E; ++I) {
@@ -2233,7 +2233,7 @@ void DwarfDebug::emitDebugInlineInfo() {
if (Asm->isVerbose()) Asm->OutStreamer.AddComment("low_pc");
Asm->OutStreamer.EmitSymbolValue(LI->first,
- Asm->getDataLayout().getPointerSize(),0);
+ Asm->getDataLayout().getPointerSize(0),0);
}
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index 08fb6b3f52c..31d07141a1d 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -417,7 +417,7 @@ void DwarfException::EmitExceptionTable() {
// that we're omitting that bit.
TTypeEncoding = dwarf::DW_EH_PE_omit;
// dwarf::DW_EH_PE_absptr
- TypeFormatSize = Asm->getDataLayout().getPointerSize();
+ TypeFormatSize = Asm->getDataLayout().getPointerSize(0);
} else {
// Okay, we have actual filters or typeinfos to emit. As such, we need to
// pick a type encoding for them. We're about to emit a list of pointers to
diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
index f7c011968c2..d0e27d1d04d 100644
--- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
@@ -91,7 +91,7 @@ void OcamlGCMetadataPrinter::beginAssembly(AsmPrinter &AP) {
/// either condition is detected in a function which uses the GC.
///
void OcamlGCMetadataPrinter::finishAssembly(AsmPrinter &AP) {
- unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize();
+ unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize(0);
AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection());
EmitCamlGlobal(getModule(), AP, "code_end");
diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp
index bc5258ef7d8..dee339a4586 100644
--- a/lib/CodeGen/CalcSpillWeights.cpp
+++ b/lib/CodeGen/CalcSpillWeights.cpp
@@ -164,7 +164,7 @@ void VirtRegAuxInfo::CalculateWeightAndHint(LiveInterval &li) {
continue;
float hweight = Hint[hint] += weight;
if (TargetRegisterInfo::isPhysicalRegister(hint)) {
- if (hweight > bestPhys && LIS.isAllocatable(hint))
+ if (hweight > bestPhys && mri.isAllocatable(hint))
bestPhys = hweight, hintPhys = hint;
} else {
if (hweight > bestVirt)
diff --git a/lib/CodeGen/CallingConvLower.cpp b/lib/CodeGen/CallingConvLower.cpp
index cdae33c2441..22b91409240 100644
--- a/lib/CodeGen/CallingConvLower.cpp
+++ b/lib/CodeGen/CallingConvLower.cpp
@@ -50,7 +50,7 @@ void CCState::HandleByVal(unsigned ValNo, MVT ValVT,
if (MinAlign > (int)Align)
Align = MinAlign;
MF.getFrameInfo()->ensureMaxAlignment(Align);
- TM.getTargetLowering()->HandleByVal(this, Size);
+ TM.getTargetLowering()->HandleByVal(this, Size, Align);
unsigned Offset = AllocateStack(Size, Align);
addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
}
diff --git a/lib/CodeGen/CriticalAntiDepBreaker.cpp b/lib/CodeGen/CriticalAntiDepBreaker.cpp
index a9de1c7490f..377b4712bea 100644