From nicholas at mxc.ca Mon Apr 11 01:11:22 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Sun, 10 Apr 2011 23:11:22 -0700 Subject: [llvm-commits] [llvm] r129128 - in /llvm/trunk/lib: CodeGen/ELFWriter.cpp ExecutionEngine/ExecutionEngine.cpp Transforms/IPO/GlobalOpt.cpp VMCore/Verifier.cpp In-Reply-To: References: <20110408073021.495BF2A6C12E@llvm.org> Message-ID: <4DA29B8A.4030609@mxc.ca> Eli Friedman wrote: > On Fri, Apr 8, 2011 at 12:30 AM, Nick Lewycky wrote: >> Author: nicholas >> Date: Fri Apr 8 02:30:21 2011 >> New Revision: 129128 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=129128&view=rev >> Log: >> llvm.global_[cd]tor is defined to be either external, or appending with an array >> of { i32, void ()* }. Teach the verifier to verify that, deleting copies of >> checks strewn about. > > Please take another look at this... see r129207. (I only looked at > GlobalOpt because it made buildbot turn red.) Thanks Eli! Sorry for the mess, I'll look more closely at this tomorrow. Nick > > -Eli > >> Modified: >> llvm/trunk/lib/CodeGen/ELFWriter.cpp >> llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp >> llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp >> llvm/trunk/lib/VMCore/Verifier.cpp >> >> Modified: llvm/trunk/lib/CodeGen/ELFWriter.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ELFWriter.cpp?rev=129128&r1=129127&r2=129128&view=diff >> ============================================================================== >> --- llvm/trunk/lib/CodeGen/ELFWriter.cpp (original) >> +++ llvm/trunk/lib/CodeGen/ELFWriter.cpp Fri Apr 8 02:30:21 2011 >> @@ -660,19 +660,17 @@ >> /// EmitXXStructorList - Emit the ctor or dtor list. This just emits out the >> /// function pointers, ignoring the init priority. >> void ELFWriter::EmitXXStructorList(Constant *List, ELFSection&Xtor) { >> - // Should be an array of '{ int, void ()* }' structs. The first value is the >> + // Should be an array of '{ i32, void ()* }' structs. The first value is the >> // init priority, which we ignore. >> - if (!isa(List)) return; >> ConstantArray *InitList = cast(List); >> - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) >> - if (ConstantStruct *CS = dyn_cast(InitList->getOperand(i))){ >> - if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. >> - >> - if (CS->getOperand(1)->isNullValue()) >> - return; // Found a null terminator, exit printing. >> - // Emit the function pointer. >> - EmitGlobalConstant(CS->getOperand(1), Xtor); >> - } >> + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { >> + ConstantStruct *CS = cast(InitList->getOperand(i)); >> + >> + if (CS->getOperand(1)->isNullValue()) >> + return; // Found a null terminator, exit printing. >> + // Emit the function pointer. >> + EmitGlobalConstant(CS->getOperand(1), Xtor); >> + } >> } >> >> bool ELFWriter::runOnMachineFunction(MachineFunction&MF) { >> >> Modified: llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp?rev=129128&r1=129127&r2=129128&view=diff >> ============================================================================== >> --- llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp (original) >> +++ llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp Fri Apr 8 02:30:21 2011 >> @@ -313,13 +313,9 @@ >> >> // Should be an array of '{ i32, void ()* }' structs. The first value is >> // the init priority, which we ignore. >> - ConstantArray *InitList = dyn_cast(GV->getInitializer()); >> - if (!InitList) return; >> + ConstantArray *InitList = cast(GV->getInitializer()); >> for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { >> - ConstantStruct *CS = >> - dyn_cast(InitList->getOperand(i)); >> - if (!CS) continue; >> - if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. >> + ConstantStruct *CS = cast(InitList->getOperand(i)); >> >> Constant *FP = CS->getOperand(1); >> if (FP->isNullValue()) >> >> Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=129128&r1=129127&r2=129128&view=diff >> ============================================================================== >> --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original) >> +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Fri Apr 8 02:30:21 2011 >> @@ -1944,35 +1944,20 @@ >> return Changed; >> } >> >> -/// FindGlobalCtors - Find the llvm.globalctors list, verifying that all >> +/// FindGlobalCtors - Find the llvm.global_ctors list, verifying that all >> /// initializers have an init priority of 65535. >> GlobalVariable *GlobalOpt::FindGlobalCtors(Module&M) { >> GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors"); >> if (GV == 0) return 0; >> >> - // Found it, verify it's an array of { int, void()* }. >> - const ArrayType *ATy =dyn_cast(GV->getType()->getElementType()); >> - if (!ATy) return 0; >> - const StructType *STy = dyn_cast(ATy->getElementType()); >> - if (!STy || STy->getNumElements() != 2 || >> - !STy->getElementType(0)->isIntegerTy(32)) return 0; >> - const PointerType *PFTy = dyn_cast(STy->getElementType(1)); >> - if (!PFTy) return 0; >> - const FunctionType *FTy = dyn_cast(PFTy->getElementType()); >> - if (!FTy || !FTy->getReturnType()->isVoidTy() || >> - FTy->isVarArg() || FTy->getNumParams() != 0) >> - return 0; >> - >> // Verify that the initializer is simple enough for us to handle. We are >> // only allowed to optimize the initializer if it is unique. >> if (!GV->hasUniqueInitializer()) return 0; >> >> - ConstantArray *CA = dyn_cast(GV->getInitializer()); >> - if (!CA) return 0; >> + ConstantArray *CA = cast(GV->getInitializer()); >> >> for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) { >> - ConstantStruct *CS = dyn_cast(*i); >> - if (CS == 0) return 0; >> + ConstantStruct *CS = cast(*i); >> >> if (isa(CS->getOperand(1))) >> continue; >> @@ -1982,8 +1967,8 @@ >> return 0; >> >> // Init priority must be standard. >> - ConstantInt *CI = dyn_cast(CS->getOperand(0)); >> - if (!CI || CI->getZExtValue() != 65535) >> + ConstantInt *CI = cast(CS->getOperand(0)); >> + if (CI->getZExtValue() != 65535) >> return 0; >> } >> >> >> Modified: llvm/trunk/lib/VMCore/Verifier.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=129128&r1=129127&r2=129128&view=diff >> ============================================================================== >> --- llvm/trunk/lib/VMCore/Verifier.cpp (original) >> +++ llvm/trunk/lib/VMCore/Verifier.cpp Fri Apr 8 02:30:21 2011 >> @@ -471,6 +471,23 @@ >> "invalid linkage type for global declaration",&GV); >> } >> >> + if (GV.hasName()&& (GV.getName() == "llvm.global_ctors" || >> + GV.getName() == "llvm.global_dtors")) { >> + Assert1(!GV.hasInitializer() || GV.hasAppendingLinkage(), >> + "invalid linkage for intrinsic global variable",&GV); >> + // Don't worry about emitting an error for it not being an array, >> + // visitGlobalValue will complain on appending non-array. >> + if (const ArrayType *ATy = dyn_cast(GV.getType())) { >> + const StructType *STy = dyn_cast(ATy->getElementType()); >> + const PointerType *FuncPtrTy = >> + FunctionType::get(Type::getVoidTy(*Context), false)->getPointerTo(); >> + Assert1(STy&& STy->getNumElements() == 2&& >> + STy->getTypeAtIndex(0u)->isIntegerTy(32)&& >> + STy->getTypeAtIndex(1) == FuncPtrTy, >> + "wrong type for intrinsic global variable",&GV); >> + } >> + } >> + >> visitGlobalValue(GV); >> } >> >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> > From jay.foad at gmail.com Mon Apr 11 04:25:51 2011 From: jay.foad at gmail.com (Jay Foad) Date: Mon, 11 Apr 2011 09:25:51 -0000 Subject: [llvm-commits] [llvm] r129270 - /llvm/trunk/lib/VMCore/Instructions.cpp Message-ID: <20110411092551.62A4F2A6C12E@llvm.org> Author: foad Date: Mon Apr 11 04:25:51 2011 New Revision: 129270 URL: http://llvm.org/viewvc/llvm-project?rev=129270&view=rev Log: Phi nodes always use an even number of operands, so don't ever allocate an odd number. Modified: llvm/trunk/lib/VMCore/Instructions.cpp Modified: llvm/trunk/lib/VMCore/Instructions.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=129270&r1=129269&r2=129270&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Instructions.cpp (original) +++ llvm/trunk/lib/VMCore/Instructions.cpp Mon Apr 11 04:25:51 2011 @@ -137,7 +137,8 @@ /// void PHINode::growOperands() { unsigned e = getNumOperands(); - unsigned NumOps = e*3/2; + // Multiply by 1.5 and round down so the result is still even. + unsigned NumOps = e + e / 4 * 2; if (NumOps < 4) NumOps = 4; // 4 op PHI nodes are VERY common. ReservedSpace = NumOps; From geek4civic at gmail.com Mon Apr 11 04:33:43 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Mon, 11 Apr 2011 18:33:43 +0900 Subject: [llvm-commits] [PATCH] TableGen: Keep the order of DECL_CONTEXT() for DeclNodes.td. RecordVector may be used instead of RecordSet. Message-ID: --- utils/TableGen/ClangASTNodesEmitter.cpp | 12 ++++++++---- 1 files changed, 8 insertions(+), 4 deletions(-) --- The result of DeclNodes.inc was unstable on msys, Windows 7 x64. ...Takumi -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-TableGen-Keep-the-order-of-DECL_CONTEXT-for-Decl.patch.txt Type: text/x-patch Size: 895 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110411/8636715d/attachment.bin From jay.foad at gmail.com Mon Apr 11 04:35:34 2011 From: jay.foad at gmail.com (Jay Foad) Date: Mon, 11 Apr 2011 09:35:34 -0000 Subject: [llvm-commits] [llvm] r129271 - in /llvm/trunk: include/llvm/ include/llvm/Analysis/ lib/Analysis/ lib/CodeGen/SelectionDAG/ lib/Target/ARM/ lib/Target/X86/ lib/Transforms/IPO/ lib/Transforms/InstCombine/ lib/Transforms/Instrumentation/ lib/Transforms/Scalar/ lib/Transforms/Utils/ lib/VMCore/ tools/llvm-diff/ unittests/Transforms/Utils/ unittests/VMCore/ Message-ID: <20110411093534.9B1892A6C12D@llvm.org> Author: foad Date: Mon Apr 11 04:35:34 2011 New Revision: 129271 URL: http://llvm.org/viewvc/llvm-project?rev=129271&view=rev Log: Don't include Operator.h from InstrTypes.h. Modified: llvm/trunk/include/llvm/Analysis/CFGPrinter.h llvm/trunk/include/llvm/Analysis/ScalarEvolution.h llvm/trunk/include/llvm/InstrTypes.h llvm/trunk/lib/Analysis/CaptureTracking.cpp llvm/trunk/lib/Analysis/ConstantFolding.cpp llvm/trunk/lib/Analysis/InstructionSimplify.cpp llvm/trunk/lib/Analysis/Loads.cpp llvm/trunk/lib/Analysis/PHITransAddr.cpp llvm/trunk/lib/Analysis/TypeBasedAliasAnalysis.cpp llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp llvm/trunk/lib/Target/ARM/ARMFastISel.cpp llvm/trunk/lib/Target/X86/X86FastISel.cpp llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp llvm/trunk/lib/Transforms/InstCombine/InstCombine.h llvm/trunk/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp llvm/trunk/lib/Transforms/Utils/Local.cpp llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp llvm/trunk/lib/VMCore/ConstantFold.cpp llvm/trunk/tools/llvm-diff/DifferenceEngine.cpp llvm/trunk/unittests/Transforms/Utils/Cloning.cpp llvm/trunk/unittests/VMCore/InstructionsTest.cpp llvm/trunk/unittests/VMCore/ValueMapTest.cpp Modified: llvm/trunk/include/llvm/Analysis/CFGPrinter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CFGPrinter.h?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/CFGPrinter.h (original) +++ llvm/trunk/include/llvm/Analysis/CFGPrinter.h Mon Apr 11 04:35:34 2011 @@ -15,6 +15,7 @@ #ifndef LLVM_ANALYSIS_CFGPRINTER_H #define LLVM_ANALYSIS_CFGPRINTER_H +#include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Assembly/Writer.h" Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original) +++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Mon Apr 11 04:35:34 2011 @@ -24,6 +24,7 @@ #include "llvm/Pass.h" #include "llvm/Instructions.h" #include "llvm/Function.h" +#include "llvm/Operator.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ValueHandle.h" #include "llvm/Support/Allocator.h" Modified: llvm/trunk/include/llvm/InstrTypes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InstrTypes.h?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/include/llvm/InstrTypes.h (original) +++ llvm/trunk/include/llvm/InstrTypes.h Mon Apr 11 04:35:34 2011 @@ -18,7 +18,6 @@ #include "llvm/Instruction.h" #include "llvm/OperandTraits.h" -#include "llvm/Operator.h" #include "llvm/DerivedTypes.h" #include "llvm/ADT/Twine.h" Modified: llvm/trunk/lib/Analysis/CaptureTracking.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CaptureTracking.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/CaptureTracking.cpp (original) +++ llvm/trunk/lib/Analysis/CaptureTracking.cpp Mon Apr 11 04:35:34 2011 @@ -17,6 +17,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/Value.h" #include "llvm/Analysis/AliasAnalysis.h" Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original) +++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Mon Apr 11 04:35:34 2011 @@ -23,6 +23,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" +#include "llvm/Operator.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Target/TargetData.h" #include "llvm/ADT/SmallVector.h" Modified: llvm/trunk/lib/Analysis/InstructionSimplify.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/InstructionSimplify.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp (original) +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp Mon Apr 11 04:35:34 2011 @@ -18,6 +18,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "instsimplify" +#include "llvm/Operator.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/ConstantFolding.h" Modified: llvm/trunk/lib/Analysis/Loads.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/Loads.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/Loads.cpp (original) +++ llvm/trunk/lib/Analysis/Loads.cpp Mon Apr 11 04:35:34 2011 @@ -17,6 +17,7 @@ #include "llvm/GlobalAlias.h" #include "llvm/GlobalVariable.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" using namespace llvm; /// AreEquivalentAddressValues - Test if A and B will obviously have the same Modified: llvm/trunk/lib/Analysis/PHITransAddr.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/PHITransAddr.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/PHITransAddr.cpp (original) +++ llvm/trunk/lib/Analysis/PHITransAddr.cpp Mon Apr 11 04:35:34 2011 @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/PHITransAddr.h" +#include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/InstructionSimplify.h" Modified: llvm/trunk/lib/Analysis/TypeBasedAliasAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/TypeBasedAliasAnalysis.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/TypeBasedAliasAnalysis.cpp (original) +++ llvm/trunk/lib/Analysis/TypeBasedAliasAnalysis.cpp Mon Apr 11 04:35:34 2011 @@ -59,6 +59,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/Passes.h" +#include "llvm/Constants.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Metadata.h" Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Mon Apr 11 04:35:34 2011 @@ -43,6 +43,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" Modified: llvm/trunk/lib/Target/ARM/ARMFastISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMFastISel.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMFastISel.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMFastISel.cpp Mon Apr 11 04:35:34 2011 @@ -26,6 +26,7 @@ #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" Modified: llvm/trunk/lib/Target/X86/X86FastISel.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FastISel.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86FastISel.cpp (original) +++ llvm/trunk/lib/Target/X86/X86FastISel.cpp Mon Apr 11 04:35:34 2011 @@ -23,6 +23,7 @@ #include "llvm/GlobalVariable.h" #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/FastISel.h" #include "llvm/CodeGen/FunctionLoweringInfo.h" Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Mon Apr 11 04:35:34 2011 @@ -21,6 +21,7 @@ #include "llvm/Instructions.h" #include "llvm/IntrinsicInst.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/Pass.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/MemoryBuiltins.h" Modified: llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp Mon Apr 11 04:35:34 2011 @@ -55,6 +55,7 @@ #include "llvm/Instructions.h" #include "llvm/LLVMContext.h" #include "llvm/Module.h" +#include "llvm/Operator.h" #include "llvm/Pass.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/Debug.h" Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombine.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombine.h?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombine.h (original) +++ llvm/trunk/lib/Transforms/InstCombine/InstCombine.h Mon Apr 11 04:35:34 2011 @@ -11,6 +11,7 @@ #define INSTCOMBINE_INSTCOMBINE_H #include "InstCombineWorklist.h" +#include "llvm/Operator.h" #include "llvm/Pass.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Support/IRBuilder.h" Modified: llvm/trunk/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp (original) +++ llvm/trunk/lib/Transforms/Instrumentation/OptimalEdgeProfiling.cpp Mon Apr 11 04:35:34 2011 @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "insert-optimal-edge-profiling" #include "ProfilingUtils.h" +#include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Analysis/Passes.h" Modified: llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp Mon Apr 11 04:35:34 2011 @@ -13,6 +13,7 @@ #define DEBUG_TYPE "correlated-value-propagation" #include "llvm/Transforms/Scalar.h" +#include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Pass.h" Modified: llvm/trunk/lib/Transforms/Utils/Local.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/Local.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/Local.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/Local.cpp Mon Apr 11 04:35:34 2011 @@ -20,6 +20,7 @@ #include "llvm/Instructions.h" #include "llvm/Intrinsics.h" #include "llvm/IntrinsicInst.h" +#include "llvm/Operator.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/DebugInfo.h" Modified: llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/SSAUpdater.cpp Mon Apr 11 04:35:34 2011 @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "ssaupdater" +#include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Analysis/InstructionSimplify.h" Modified: llvm/trunk/lib/VMCore/ConstantFold.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/ConstantFold.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/ConstantFold.cpp (original) +++ llvm/trunk/lib/VMCore/ConstantFold.cpp Mon Apr 11 04:35:34 2011 @@ -24,6 +24,7 @@ #include "llvm/Function.h" #include "llvm/GlobalAlias.h" #include "llvm/GlobalVariable.h" +#include "llvm/Operator.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" Modified: llvm/trunk/tools/llvm-diff/DifferenceEngine.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-diff/DifferenceEngine.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/tools/llvm-diff/DifferenceEngine.cpp (original) +++ llvm/trunk/tools/llvm-diff/DifferenceEngine.cpp Mon Apr 11 04:35:34 2011 @@ -14,6 +14,7 @@ #include "DifferenceEngine.h" +#include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Instructions.h" #include "llvm/Module.h" Modified: llvm/trunk/unittests/Transforms/Utils/Cloning.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Transforms/Utils/Cloning.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/unittests/Transforms/Utils/Cloning.cpp (original) +++ llvm/trunk/unittests/Transforms/Utils/Cloning.cpp Mon Apr 11 04:35:34 2011 @@ -9,6 +9,7 @@ #include "gtest/gtest.h" #include "llvm/Argument.h" +#include "llvm/Constant.h" #include "llvm/Instructions.h" #include "llvm/LLVMContext.h" #include "llvm/ADT/SmallPtrSet.h" Modified: llvm/trunk/unittests/VMCore/InstructionsTest.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/VMCore/InstructionsTest.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/unittests/VMCore/InstructionsTest.cpp (original) +++ llvm/trunk/unittests/VMCore/InstructionsTest.cpp Mon Apr 11 04:35:34 2011 @@ -9,6 +9,7 @@ #include "llvm/Instructions.h" #include "llvm/BasicBlock.h" +#include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/LLVMContext.h" #include "llvm/ADT/STLExtras.h" Modified: llvm/trunk/unittests/VMCore/ValueMapTest.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/VMCore/ValueMapTest.cpp?rev=129271&r1=129270&r2=129271&view=diff ============================================================================== --- llvm/trunk/unittests/VMCore/ValueMapTest.cpp (original) +++ llvm/trunk/unittests/VMCore/ValueMapTest.cpp Mon Apr 11 04:35:34 2011 @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/ValueMap.h" +#include "llvm/Constants.h" #include "llvm/Instructions.h" #include "llvm/LLVMContext.h" #include "llvm/ADT/OwningPtr.h" From jay.foad at gmail.com Mon Apr 11 04:48:56 2011 From: jay.foad at gmail.com (Jay Foad) Date: Mon, 11 Apr 2011 09:48:56 -0000 Subject: [llvm-commits] [llvm] r129272 - in /llvm/trunk: include/llvm/Constant.h lib/Bitcode/Writer/ValueEnumerator.cpp Message-ID: <20110411094856.12FC42A6C12D@llvm.org> Author: foad Date: Mon Apr 11 04:48:55 2011 New Revision: 129272 URL: http://llvm.org/viewvc/llvm-project?rev=129272&view=rev Log: Fix or remove code which seemed to think that the operand of a Constant was always a User. Modified: llvm/trunk/include/llvm/Constant.h llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp Modified: llvm/trunk/include/llvm/Constant.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constant.h?rev=129272&r1=129271&r2=129272&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constant.h (original) +++ llvm/trunk/include/llvm/Constant.h Mon Apr 11 04:48:55 2011 @@ -47,10 +47,6 @@ : User(ty, vty, Ops, NumOps) {} void destroyConstantImpl(); - - void setOperand(unsigned i, Value *V) { - User::setOperand(i, V); - } public: /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. @@ -90,15 +86,6 @@ /// FIXME: This really should not be in VMCore. PossibleRelocationsTy getRelocationInfo() const; - // Specialize get/setOperand for Users as their operands are always - // constants or BasicBlocks as well. - User *getOperand(unsigned i) { - return static_cast(User::getOperand(i)); - } - const User *getOperand(unsigned i) const { - return static_cast(User::getOperand(i)); - } - /// getVectorElements - This method, which is only valid on constant of vector /// type, returns the elements of the vector in the specified smallvector. /// This handles breaking down a vector undef into undef elements, etc. For Modified: llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp?rev=129272&r1=129271&r2=129272&view=diff ============================================================================== --- llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp (original) +++ llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp Mon Apr 11 04:48:55 2011 @@ -423,7 +423,7 @@ // This constant may have operands, make sure to enumerate the types in // them. for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { - const User *Op = C->getOperand(i); + const Value *Op = C->getOperand(i); // Don't enumerate basic blocks here, this happens as operands to // blockaddress. From nadav.rotem at intel.com Mon Apr 11 08:40:51 2011 From: nadav.rotem at intel.com (Rotem, Nadav) Date: Mon, 11 Apr 2011 16:40:51 +0300 Subject: [llvm-commits] [PATCH] - endless loop in instcombine and a small constant folding optimization on vectors Message-ID: <6594DDFF12B03D4E89690887C2486994027889605C@hasmsx504.ger.corp.intel.com> Hi, Please review the attached patch: 1. Fix an endless loop in instcombine. VisitAnd changes the instruction, and VisitXor fixes it in an endless loop. 2. A small constant folding patch vector select with a splat condition. Thanks, Nadav --------------------------------------------------------------------- Intel Israel (74) Limited This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). Any review or distribution by others is strictly prohibited. If you are not the intended recipient, please contact the sender and delete all copies. -------------- next part -------------- A non-text attachment was scrubbed... Name: vec_xor_loop.diff Type: application/octet-stream Size: 5957 bytes Desc: vec_xor_loop.diff Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110411/a994b8d0/attachment.obj From ofv at wanadoo.es Mon Apr 11 09:52:39 2011 From: ofv at wanadoo.es (Oscar Fuentes) Date: Mon, 11 Apr 2011 14:52:39 -0000 Subject: [llvm-commits] [llvm] r129274 - in /llvm/trunk/cmake/modules: CMakeLists.txt LLVMConfig.cmake.in Message-ID: <20110411145239.8A1382A6C12D@llvm.org> Author: ofv Date: Mon Apr 11 09:52:39 2011 New Revision: 129274 URL: http://llvm.org/viewvc/llvm-project?rev=129274&view=rev Log: CMake: remove some unnecesary code and ToDos. Patch by arrowdodger! Modified: llvm/trunk/cmake/modules/CMakeLists.txt llvm/trunk/cmake/modules/LLVMConfig.cmake.in Modified: llvm/trunk/cmake/modules/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/CMakeLists.txt?rev=129274&r1=129273&r2=129274&view=diff ============================================================================== --- llvm/trunk/cmake/modules/CMakeLists.txt (original) +++ llvm/trunk/cmake/modules/CMakeLists.txt Mon Apr 11 09:52:39 2011 @@ -32,11 +32,3 @@ PATTERN GetTargetTriple.cmake EXCLUDE PATTERN VersionFromVCS.cmake EXCLUDE PATTERN CheckAtomic.cmake EXCLUDE) - -#remove this? -install(FILES - ${llvm_cmake_builddir}/LLVMConfig.cmake - ${llvm_cmake_builddir}/LLVMConfigVersion.cmake - LLVM-Config.cmake - LLVMLibDeps.cmake - DESTINATION share/llvm/cmake) Modified: llvm/trunk/cmake/modules/LLVMConfig.cmake.in URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/LLVMConfig.cmake.in?rev=129274&r1=129273&r2=129274&view=diff ============================================================================== --- llvm/trunk/cmake/modules/LLVMConfig.cmake.in (original) +++ llvm/trunk/cmake/modules/LLVMConfig.cmake.in Mon Apr 11 09:52:39 2011 @@ -1,6 +1,6 @@ # This file provides information and services to the final user. -set(LLVM_PACKAGE_VERSION @PACKAGE_VERSION@) #remove this? +set(LLVM_PACKAGE_VERSION @PACKAGE_VERSION@) set(LLVM_COMMON_DEPENDS @LLVM_COMMON_DEPENDS@) From stoklund at 2pi.dk Mon Apr 11 10:00:39 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 15:00:39 -0000 Subject: [llvm-commits] [llvm] r129275 - /llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp Message-ID: <20110411150040.075AA2A6C12D@llvm.org> Author: stoklund Date: Mon Apr 11 10:00:39 2011 New Revision: 129275 URL: http://llvm.org/viewvc/llvm-project?rev=129275&view=rev Log: Don't shrink live ranges after dead code elimination unless it is going to help. In particular, don't repeatedly recompute the PIC base live range after rematerialization. Modified: llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp Modified: llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp?rev=129275&r1=129274&r2=129275&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp Mon Apr 11 10:00:39 2011 @@ -203,6 +203,7 @@ SetVector, SmallPtrSet > ToShrink; + MachineRegisterInfo &MRI = VRM.getRegInfo(); for (;;) { // Erase all dead defs. @@ -236,8 +237,13 @@ continue; LiveInterval &LI = LIS.getInterval(Reg); - // Shrink read registers. - if (MI->readsVirtualRegister(Reg)) + // Shrink read registers, unless it is likely to be expensive and + // unlikely to change anything. We typically don't want to shrink the + // PIC base register that has lots of uses everywhere. + // Always shrink COPY uses that probably come from live range splitting. + if (MI->readsVirtualRegister(Reg) && + (MI->isCopy() || MOI->isDef() || MRI.hasOneNonDBGUse(Reg) || + LI.killedAt(Idx))) ToShrink.insert(&LI); // Remove defined value. @@ -266,7 +272,7 @@ // Shrink just one live interval. Then delete new dead defs. LiveInterval *LI = ToShrink.back(); ToShrink.pop_back(); - if (foldAsLoad(LI, Dead, VRM.getRegInfo(), LIS, TII)) + if (foldAsLoad(LI, Dead, MRI, LIS, TII)) continue; if (delegate_) delegate_->LRE_WillShrinkVirtReg(LI->reg); @@ -286,7 +292,7 @@ if (delegate_) delegate_->LRE_DidCloneVirtReg(Dups.back()->reg, LI->reg); } - ConEQ.Distribute(&Dups[0], VRM.getRegInfo()); + ConEQ.Distribute(&Dups[0], MRI); } } From stoklund at 2pi.dk Mon Apr 11 10:00:42 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 15:00:42 -0000 Subject: [llvm-commits] [llvm] r129276 - /llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Message-ID: <20110411150042.5DE4F2A6C12E@llvm.org> Author: stoklund Date: Mon Apr 11 10:00:42 2011 New Revision: 129276 URL: http://llvm.org/viewvc/llvm-project?rev=129276&view=rev Log: Time the initial seeding of live registers Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocBasic.cpp?rev=129276&r1=129275&r2=129276&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocBasic.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Mon Apr 11 10:00:42 2011 @@ -258,6 +258,7 @@ // register, unify them with the corresponding LiveIntervalUnion, otherwise push // them on the priority queue for later assignment. void RegAllocBase::seedLiveRegs() { + NamedRegionTimer T("Seed Live Regs", TimerGroupName, TimePassesIsEnabled); for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I) { unsigned RegNum = I->first; LiveInterval &VirtReg = *I->second; From stoklund at 2pi.dk Mon Apr 11 10:00:44 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 15:00:44 -0000 Subject: [llvm-commits] [llvm] r129277 - /llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp Message-ID: <20110411150044.9F0D72A6C12F@llvm.org> Author: stoklund Date: Mon Apr 11 10:00:44 2011 New Revision: 129277 URL: http://llvm.org/viewvc/llvm-project?rev=129277&view=rev Log: Speed up LiveIntervalUnion::unify by handling end insertion specially. This particularly helps with the initial transfer of fixed intervals. Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp?rev=129277&r1=129276&r2=129277&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp Mon Apr 11 10:00:44 2011 @@ -35,12 +35,20 @@ LiveInterval::iterator RegEnd = VirtReg.end(); SegmentIter SegPos = Segments.find(RegPos->start); - for (;;) { + while (SegPos.valid()) { SegPos.insert(RegPos->start, RegPos->end, &VirtReg); if (++RegPos == RegEnd) return; SegPos.advanceTo(RegPos->start); } + + // We have reached the end of Segments, so it is no longer necessary to search + // for the insertion position. + // It is faster to insert the end first. + --RegEnd; + SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg); + for (; RegPos != RegEnd; ++RegPos, ++SegPos) + SegPos.insert(RegPos->start, RegPos->end, &VirtReg); } // Remove a live virtual register's segments from this union. From baldrick at free.fr Mon Apr 11 10:48:03 2011 From: baldrick at free.fr (Duncan Sands) Date: Mon, 11 Apr 2011 17:48:03 +0200 Subject: [llvm-commits] [llvm] r129235 - in /llvm/trunk: include/llvm/BasicBlock.h include/llvm/Bitcode/LLVMBitCodes.h lib/AsmParser/LLLexer.cpp lib/AsmParser/LLParser.cpp lib/AsmParser/LLToken.h lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/BitcodeWriter.cpp lib/VMCore/AsmWriter.cpp lib/VMCore/BasicBlock.cpp test/Feature/bb_attrs.ll In-Reply-To: References: <20110410000427.D81CC2A6C12E@llvm.org> <3E68CF50-8E76-4868-9CA8-E492A1F29841@apple.com> <4DA15D33.6090406@free.fr> Message-ID: <4DA322B3.5040605@free.fr> Hi Bill, >>>> This sounds very interesting. Do you have a description of what you're angling for? I'd really like to understand and digest the model before you write too much code. >> >> since Bill's proposal seemed way too complicated to me, I sent in an >> alternative proposal shortly afterwards, here: >> >> http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-December/036731.html >> >> In particular it has a fairly detailed analysis of some of the existing >> problems with LLVM exception handling. >> > I didn't comment too much on your idea because I think of the problem differently. To me the problem is systemic and not cosmetic. Your solution is cosmetic in nature, and still has the major problems of the current implementation. > > For instance in order to generate good EH tables (this is not to say that the EH code has to be DWARF-specific, but it does need to be rich enough to handling DWARF EH stuff), we need to know at two points in the code all of the information about the call that may throw: (1) at the point where the call is made, and (2) at the point where the decision to execute a catch or cleanup is made. I disagree with the way you describe the issue in (2), though maybe I'm just nit picking. There is an issue, but I would say that the issue is in getting the right exception value / selector value at the point where decisions about branching to catch clauses is made, and not one of knowing "all of the information about the call". As you explain, at the moment when an exception results in control branching to a landing pad there is a value for the exception and selector (passed in registers), but the point where you make decisions about which catch to execute etc can be far away, with all kinds of other exceptions being thrown and caught before you get there. This means that you are obliged to stash the exception/selector values away somewhere so that you can get hold of them again later. I didn't discuss this point much in my proposal since it can be solved using intrinsics (ie with no IR changes). I agree that the intrinsics approach is rather ugly and something of a hack, but since it would solve the problem I find it hard to get excited about it: point (1) seems much more serious to me. In short, I would say that my proposal has all the minor problems of the current implementation, but not the major problem :) I think the best way to proceed is not to discuss solutions/proposals etc for the moment, but instead to clearly define what is wrong with the current eh scheme. In the next day or so I plan to post an email describing and analysing all the problems with the current scheme (this may take me a while since there are a lot of them!). Ciao, Duncan. From baldrick at free.fr Mon Apr 11 10:49:07 2011 From: baldrick at free.fr (Duncan Sands) Date: Mon, 11 Apr 2011 15:49:07 -0000 Subject: [llvm-commits] [dragonegg] r129278 - /dragonegg/trunk/Constants.cpp Message-ID: <20110411154907.603272A6C12D@llvm.org> Author: baldrick Date: Mon Apr 11 10:49:07 2011 New Revision: 129278 URL: http://llvm.org/viewvc/llvm-project?rev=129278&view=rev Log: Rework handling of CONSTRUCTOR nodes with array type. The changes solve two problems: (1) in Fortran it is possible for the value given for some array element to be too small, in which case it needs to be padded to the right size [see gcc testcase char_component_initializer_1.f90, modified to have three array elements rather than two]; (2) if the user forced a small alignment on the array, then a packed struct needs to be used in order to not break the invariant that the converted value is not more aligned than the GCC type. Modified: dragonegg/trunk/Constants.cpp Modified: dragonegg/trunk/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Constants.cpp?rev=129278&r1=129277&r2=129278&view=diff ============================================================================== --- dragonegg/trunk/Constants.cpp (original) +++ dragonegg/trunk/Constants.cpp Mon Apr 11 10:49:07 2011 @@ -606,133 +606,148 @@ return AddressOf(TREE_OPERAND(exp, 0)); } +/// ConvertArrayCONSTRUCTOR - Convert a CONSTRUCTOR with array or vector type. static Constant *ConvertArrayCONSTRUCTOR(tree exp) { - // Vectors are like arrays, but the domain is stored via an array - // type indirectly. + const TargetData &TD = getTargetData(); - // If we have a lower bound for the range of the type, get it. tree init_type = TREE_TYPE(exp); + const Type *InitTy = ConvertType(init_type); + tree elt_type = TREE_TYPE(init_type); + const Type *EltTy = ConvertType(elt_type); - tree min_element = size_zero_node; - std::vector ResultElts; + // Check that the element type has a known, constant size. + assert(isSequentialCompatible(init_type) && "Variable sized array element!"); + uint64_t EltSize = TD.getTypeAllocSizeInBits(EltTy); - if (TREE_CODE(init_type) == VECTOR_TYPE) { - ResultElts.resize(TYPE_VECTOR_SUBPARTS(init_type)); - } else { - assert(TREE_CODE(init_type) == ARRAY_TYPE && "Unknown type for init"); - tree Domain = TYPE_DOMAIN(init_type); - if (Domain && TYPE_MIN_VALUE(Domain)) - min_element = fold_convert(sizetype, TYPE_MIN_VALUE(Domain)); - - if (Domain && TYPE_MAX_VALUE(Domain)) { - tree max_element = fold_convert(sizetype, TYPE_MAX_VALUE(Domain)); - tree size = size_binop (MINUS_EXPR, max_element, min_element); - size = size_binop (PLUS_EXPR, size, size_one_node); + /// Elts - The initial values to use for the array elements. A null entry + /// means that the corresponding array element should be default initialized. + std::vector Elts; - if (host_integerp(size, 1)) - ResultElts.resize(tree_low_cst(size, 1)); - } - } + // Resize to the number of array elements if known. This ensures that every + // element will be at least default initialized even if no initial value is + // given for it. + uint64_t TypeElts = TREE_CODE(init_type) == ARRAY_TYPE ? + ArrayLengthOf(init_type) : TYPE_VECTOR_SUBPARTS(init_type); + if (TypeElts != ~0ULL) + Elts.resize(TypeElts); + + // If GCC indices into the array need adjusting to make them zero indexed then + // record here the value to subtract off. + tree lower_bnd = NULL_TREE; + if (TREE_CODE(init_type) == ARRAY_TYPE && TYPE_DOMAIN(init_type) && + !integer_zerop(TYPE_MIN_VALUE(TYPE_DOMAIN(init_type)))) + lower_bnd = TYPE_MIN_VALUE(TYPE_DOMAIN(init_type)); - unsigned NextFieldToFill = 0; + unsigned NextIndex = 0; unsigned HOST_WIDE_INT ix; tree elt_index, elt_value; - Constant *SomeVal = 0; - FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), ix, elt_index, elt_value) { + FOR_EACH_CONSTRUCTOR_ELT(CONSTRUCTOR_ELTS(exp), ix, elt_index, elt_value) { // Find and decode the constructor's value. Constant *Val = ConvertInitializerWithCast(elt_value, elt_type); - SomeVal = Val; + uint64_t ValSize = TD.getTypeAllocSizeInBits(Val->getType()); + assert(ValSize <= EltSize && "Element initial value too big!"); + + // If the initial value is smaller than the element size then pad it out. + if (ValSize < EltSize) { + unsigned PadBits = EltSize - ValSize; + assert(PadBits % BITS_PER_UNIT == 0 && "Non-unit type size?"); + unsigned Units = PadBits / BITS_PER_UNIT; + Constant *Padding = UndefValue::get(GetUnitType(Context, Units)); + Val = ConstantStruct::get(Context, false, Val, Padding, NULL); + } // Get the index position of the element within the array. Note that this // can be NULL_TREE, which means that it belongs in the next available slot. tree index = elt_index; - // The first and last field to fill in, inclusive. - unsigned FieldOffset, FieldLastOffset; - if (index && TREE_CODE(index) == RANGE_EXPR) { - tree first = fold_convert (sizetype, TREE_OPERAND(index, 0)); - tree last = fold_convert (sizetype, TREE_OPERAND(index, 1)); - - first = size_binop (MINUS_EXPR, first, min_element); - last = size_binop (MINUS_EXPR, last, min_element); + // The first and last elements to fill in, inclusive. + unsigned FirstIndex, LastIndex; + if (!index) { + LastIndex = FirstIndex = NextIndex; + } else if (TREE_CODE(index) == RANGE_EXPR) { + tree first = TREE_OPERAND(index, 0); + tree last = TREE_OPERAND(index, 1); + + // Subtract off the lower bound if any to ensure indices start from zero. + if (lower_bnd != NULL_TREE) { + first = fold_build2(MINUS_EXPR, TREE_TYPE(first), first, lower_bnd); + last = fold_build2(MINUS_EXPR, TREE_TYPE(last), last, lower_bnd); + } assert(host_integerp(first, 1) && host_integerp(last, 1) && "Unknown range_expr!"); - FieldOffset = tree_low_cst(first, 1); - FieldLastOffset = tree_low_cst(last, 1); - } else if (index) { - index = size_binop (MINUS_EXPR, fold_convert (sizetype, index), - min_element); - assert(host_integerp(index, 1)); - FieldOffset = tree_low_cst(index, 1); - FieldLastOffset = FieldOffset; + FirstIndex = tree_low_cst(first, 1); + LastIndex = tree_low_cst(last, 1); } else { - FieldOffset = NextFieldToFill; - FieldLastOffset = FieldOffset; + // Subtract off the lower bound if any to ensure indices start from zero. + if (lower_bnd != NULL_TREE) + index = fold_build2(MINUS_EXPR, TREE_TYPE(index), index, lower_bnd); + assert(host_integerp(index, 1)); + FirstIndex = tree_low_cst(index, 1); + LastIndex = FirstIndex; } // Process all of the elements in the range. - for (--FieldOffset; FieldOffset != FieldLastOffset; ) { - ++FieldOffset; - if (FieldOffset == ResultElts.size()) - ResultElts.push_back(Val); - else { - if (FieldOffset >= ResultElts.size()) - ResultElts.resize(FieldOffset+1); - ResultElts[FieldOffset] = Val; - } + if (LastIndex >= Elts.size()) + Elts.resize(LastIndex + 1); + for (; FirstIndex <= LastIndex; ++FirstIndex) + Elts[FirstIndex] = Val; - NextFieldToFill = FieldOffset+1; - } + NextIndex = FirstIndex; } + unsigned NumElts = Elts.size(); + // Zero length array. - if (ResultElts.empty()) - return getDefaultValue(ConvertType(TREE_TYPE(exp))); - assert(SomeVal && "If we had some initializer, we should have some value!"); + if (!NumElts) + return getDefaultValue(InitTy); + + // Default initialize any elements that had no initial value specified. + Constant *DefaultElt = getDefaultValue(EltTy); + for (unsigned i = 0; i != NumElts; ++i) + if (!Elts[i]) + Elts[i] = DefaultElt; + + // Check whether any of the elements have different types. If so we need to + // return a struct instead of an array. This can occur in cases where we have + // an array of unions, and the various unions had different parts initialized. + // While there, compute the maximum element alignment. + bool UseStruct = false; + const Type *ActualEltTy = Elts[0]->getType(); + unsigned MaxAlign = TD.getABITypeAlignment(ActualEltTy); + for (unsigned i = 1; i != NumElts; ++i) + if (Elts[i]->getType() != ActualEltTy) { + MaxAlign = std::max(TD.getABITypeAlignment(Elts[i]->getType()), MaxAlign); + UseStruct = true; + } + + // If any elements are more aligned than the GCC type then we need to return a + // packed struct. This can happen if the user forced a small alignment on the + // array type. + bool Pack = MaxAlign * 8 > TYPE_ALIGN(TREE_TYPE(exp)); - // Do a post-pass over all of the elements. We're taking care of two things - // here: - // #1. If any elements did not have initializers specified, provide them - // with a null init. - // #2. If any of the elements have different types, return a struct instead - // of an array. This can occur in cases where we have an array of - // unions, and the various unions had different pieces init'd. - const Type *ElTy = SomeVal->getType(); - Constant *Filler = Constant::getNullValue(ElTy); - bool AllEltsSameType = true; - for (unsigned i = 0, e = ResultElts.size(); i != e; ++i) { - if (ResultElts[i] == 0) - ResultElts[i] = Filler; - else if (ResultElts[i]->getType() != ElTy) - AllEltsSameType = false; - } - - if (TREE_CODE(init_type) == VECTOR_TYPE) { - assert(AllEltsSameType && "Vector of heterogeneous element types?"); - return ConstantVector::get(ResultElts); - } - - Constant *Res = AllEltsSameType ? - ConstantArray::get(ArrayType::get(ElTy, ResultElts.size()), ResultElts) : - ConstantStruct::get(Context, ResultElts, false); - - // If the array does not require extra padding, return it. - const Type *InitType = ConvertType(init_type); - uint64_t ExpectedBits = getTargetData().getTypeAllocSizeInBits(InitType); - uint64_t FoundBits = getTargetData().getTypeAllocSizeInBits(Res->getType()); - // The initializer may be bigger than the type if init_type is variable sized - // or has no size (in which case the size is determined by the initial value). - if (ExpectedBits <= FoundBits) - return Res; - - // Wrap the array in a struct with padding at the end. - Constant *PadElts[2]; - PadElts[0] = Res; - PadElts[1] = UndefValue::get(ArrayType::get(Type::getInt8Ty(Context), - (ExpectedBits - FoundBits) / 8)); - return ConstantStruct::get(Context, PadElts, 2, false); + // We guarantee that initializers are always at least as big as the LLVM type + // for the initializer. If needed, append padding to ensure this. + uint64_t TypeSize = TD.getTypeAllocSizeInBits(InitTy); + if (NumElts * EltSize < TypeSize) { + unsigned PadBits = TypeSize - NumElts * EltSize; + assert(PadBits % BITS_PER_UNIT == 0 && "Non-unit type size?"); + unsigned Units = PadBits / BITS_PER_UNIT; + Elts.push_back(UndefValue::get(GetUnitType(Context, Units))); + UseStruct = true; + } + + // Return as a struct if the contents are not homogeneous. + if (UseStruct || Pack) + return ConstantStruct::get(Context, Elts, Pack); + + // Make the IR more pleasant by returning as a vector if the GCC type was a + // vector. However this is only correct if the initial values had the same + // type as the vector element type, rather than some random other type. + return ActualEltTy == EltTy && TREE_CODE(init_type) == VECTOR_TYPE ? + ConstantVector::get(Elts) : + ConstantArray::get(ArrayType::get(ActualEltTy, Elts.size()), Elts); } /// FieldContents - A constant restricted to a range of bits. Any part of the @@ -903,10 +918,10 @@ // For each field for which an initial value was specified, set the bits // occupied by the field to that value. - unsigned HOST_WIDE_INT idx; + unsigned HOST_WIDE_INT ix; tree field, next_field, value; next_field = TYPE_FIELDS(TREE_TYPE(exp)); - FOR_EACH_CONSTRUCTOR_ELT(CONSTRUCTOR_ELTS(exp), idx, field, value) { + FOR_EACH_CONSTRUCTOR_ELT(CONSTRUCTOR_ELTS(exp), ix, field, value) { if (!field) { // Move on to the next FIELD_DECL, skipping contained methods, types etc. field = next_field; @@ -1009,9 +1024,9 @@ } static Constant *ConvertCONSTRUCTOR(tree exp) { - // If the constructor is empty then default initialize all components. It is - // safe to use the LLVM type here as it covers every part of the GCC type that - // can be default initialized. + // If the constructor is empty then default initialize all of the components. + // It is safe to use the LLVM type here as it covers every part of the GCC + // type that can possibly be default initialized. if (CONSTRUCTOR_NELTS(exp) == 0) return getDefaultValue(ConvertType(TREE_TYPE(exp))); From aggarwa4 at illinois.edu Mon Apr 11 11:20:58 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Mon, 11 Apr 2011 16:20:58 -0000 Subject: [llvm-commits] [poolalloc] r129280 - in /poolalloc/trunk: lib/AssistDS/CMakeLists.txt lib/AssistDS/SimplifyExtractValue.cpp lib/AssistDS/SimplifyInsertValue.cpp lib/AssistDS/SimplifyMRV.cpp test/TEST.types.Makefile test/TEST.types.report Message-ID: <20110411162058.8DE912A6C12D@llvm.org> Author: aggarwa4 Date: Mon Apr 11 11:20:58 2011 New Revision: 129280 URL: http://llvm.org/viewvc/llvm-project?rev=129280&view=rev Log: Merge all the extract value simplifications, into a single file. Removed: poolalloc/trunk/lib/AssistDS/SimplifyMRV.cpp Modified: poolalloc/trunk/lib/AssistDS/CMakeLists.txt poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp poolalloc/trunk/test/TEST.types.Makefile poolalloc/trunk/test/TEST.types.report Modified: poolalloc/trunk/lib/AssistDS/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/CMakeLists.txt?rev=129280&r1=129279&r2=129280&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/CMakeLists.txt (original) +++ poolalloc/trunk/lib/AssistDS/CMakeLists.txt Mon Apr 11 11:20:58 2011 @@ -8,7 +8,8 @@ MergeArrayIndexGEP.cpp SVADevirt.cpp SimplifyGEP.cpp - SimplifyMRV.cpp + SimplifyEV.cpp + SimplifyIV.cpp TestGEP.cpp TypeAnalysis.cpp VarArgsFunc.cpp Modified: poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp?rev=129280&r1=129279&r2=129280&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp (original) +++ poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp Mon Apr 11 11:20:58 2011 @@ -7,10 +7,12 @@ // //===----------------------------------------------------------------------===// // -// Replace extract value by loads where possible +// Simplify extractvalue +// +// Derived from InstCombine // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "simplify-ev" +#define DEBUG_TYPE "simplifyev" #include "llvm/Instructions.h" #include "llvm/Module.h" @@ -40,7 +42,7 @@ // Method: runOnModule() // // Description: - // Entry point for this LLVM pass. Search for extractvalue instructions + // Entry point for this LLVM pass. Search for insert/extractvalue instructions // that can be simplified. // // Inputs: @@ -65,27 +67,176 @@ if(!EV) continue; Value *Agg = EV->getAggregateOperand(); - LoadInst *LI = dyn_cast(Agg); - if(!LI) + if (!EV->hasIndices()) { + EV->replaceAllUsesWith(Agg); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + changed = true; continue; - // check that it is in same basic block - SmallVector Indices; - const Type *Int32Ty = Type::getInt32Ty(M.getContext()); - Indices.push_back(Constant::getNullValue(Int32Ty)); - for (ExtractValueInst::idx_iterator I = EV->idx_begin(), E = EV->idx_end(); - I != E; ++I) { - Indices.push_back(ConstantInt::get(Int32Ty, *I)); } + if (Constant *C = dyn_cast(Agg)) { + if (isa(C)) { + EV->replaceAllUsesWith(UndefValue::get(EV->getType())); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + changed = true; + continue; + } + if (isa(C)) { + EV->replaceAllUsesWith(Constant::getNullValue(EV->getType())); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + changed = true; + continue; + } + if (isa(C) || isa(C)) { + // Extract the element indexed by the first index out of the constant + Value *V = C->getOperand(*EV->idx_begin()); + if (EV->getNumIndices() > 1) { + // Extract the remaining indices out of the constant indexed by the + // first index + ExtractValueInst *EV_new = ExtractValueInst::Create(V, + EV->idx_begin() + 1, + EV->idx_end(), "", EV); + EV->replaceAllUsesWith(EV_new); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + changed = true; + continue; + } else { + EV->replaceAllUsesWith(V); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + changed = true; + continue; + } + } + continue; + } + if (LoadInst * LI = dyn_cast(Agg)) { + SmallVector Indices; + const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + Indices.push_back(Constant::getNullValue(Int32Ty)); + for (ExtractValueInst::idx_iterator I = EV->idx_begin(), E = EV->idx_end(); + I != E; ++I) { + Indices.push_back(ConstantInt::get(Int32Ty, *I)); + } + + GetElementPtrInst *GEP = GetElementPtrInst::CreateInBounds(LI->getOperand(0), Indices.begin(), + Indices.end(), LI->getName(), LI) ; + LoadInst *LINew = new LoadInst(GEP, "", LI); + EV->replaceAllUsesWith(LINew); + EV->eraseFromParent(); + changed = true; + numErased++; + continue; - GetElementPtrInst *GEP = GetElementPtrInst::CreateInBounds(LI->getOperand(0), Indices.begin(), - Indices.end(), LI->getName(), LI) ; - LoadInst *LINew = new LoadInst(GEP, "", LI); - EV->replaceAllUsesWith(LINew); - EV->eraseFromParent(); - changed = true; - numErased++; - - + } + if (InsertValueInst *IV = dyn_cast(Agg)) { + bool done = false; + // We're extracting from an insertvalue instruction, compare the indices + const unsigned *exti, *exte, *insi, *inse; + for (exti = EV->idx_begin(), insi = IV->idx_begin(), + exte = EV->idx_end(), inse = IV->idx_end(); + exti != exte && insi != inse; + ++exti, ++insi) { + if (*insi != *exti) { + // The insert and extract both reference distinctly different elements. + // This means the extract is not influenced by the insert, and we can + // replace the aggregate operand of the extract with the aggregate + // operand of the insert. i.e., replace + // %I = insertvalue { i32, { i32 } } %A, { i32 } { i32 42 }, 1 + // %E = extractvalue { i32, { i32 } } %I, 0 + // with + // %E = extractvalue { i32, { i32 } } %A, 0 + ExtractValueInst *EV_new = ExtractValueInst::Create(IV->getAggregateOperand(), + EV->idx_begin(), EV->idx_end(),"", EV); + EV->replaceAllUsesWith(EV_new); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + done = true; + changed = true; + break; + } + } + if(done) + continue; + if (exti == exte && insi == inse) { + // Both iterators are at the end: Index lists are identical. Replace + // %B = insertvalue { i32, { i32 } } %A, i32 42, 1, 0 + // %C = extractvalue { i32, { i32 } } %B, 1, 0 + // with "i32 42" + EV->replaceAllUsesWith(IV->getInsertedValueOperand()); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + changed = true; + continue; + + } + if (exti == exte) { + // The extract list is a prefix of the insert list. i.e. replace + // %I = insertvalue { i32, { i32 } } %A, i32 42, 1, 0 + // %E = extractvalue { i32, { i32 } } %I, 1 + // with + // %X = extractvalue { i32, { i32 } } %A, 1 + // %E = insertvalue { i32 } %X, i32 42, 0 + // by switching the order of the insert and extract (though the + // insertvalue should be left in, since it may have other uses). + Value *NewEV = ExtractValueInst::Create(IV->getAggregateOperand(), + EV->idx_begin(), EV->idx_end(), "", EV); + Value *NewIV = InsertValueInst::Create(NewEV, IV->getInsertedValueOperand(), + insi, inse, "", EV); + EV->replaceAllUsesWith(NewIV); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + changed = true; + continue; + } + if (insi == inse) { + // The insert list is a prefix of the extract list + // We can simply remove the common indices from the extract and make it + // operate on the inserted value instead of the insertvalue result. + // i.e., replace + // %I = insertvalue { i32, { i32 } } %A, { i32 } { i32 42 }, 1 + // %E = extractvalue { i32, { i32 } } %I, 1, 0 + // with + // %E extractvalue { i32 } { i32 42 }, 0 + ExtractValueInst *EV_new = ExtractValueInst::Create(IV->getInsertedValueOperand(), + exti, exte,"", EV); + EV->replaceAllUsesWith(EV_new); + DEBUG(errs() << "EV:"); + DEBUG(errs() << "ERASE:"); + DEBUG(EV->dump()); + EV->eraseFromParent(); + numErased++; + changed = true; + continue; + } + } } } } @@ -100,4 +251,4 @@ // Register the pass static RegisterPass -X("simplify-ev", "Simplify extract value"); +X("simplify-ev", "Simplify extract/insert value insts"); Modified: poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp?rev=129280&r1=129279&r2=129280&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp (original) +++ poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp Mon Apr 11 11:20:58 2011 @@ -7,7 +7,8 @@ // //===----------------------------------------------------------------------===// // -// Replace insert value by storess where possible +// Simplify insertvalue +// Replace insertvalue by storess where possible // //===----------------------------------------------------------------------===// #define DEBUG_TYPE "simplify-iv" Removed: poolalloc/trunk/lib/AssistDS/SimplifyMRV.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/SimplifyMRV.cpp?rev=129279&view=auto ============================================================================== --- poolalloc/trunk/lib/AssistDS/SimplifyMRV.cpp (original) +++ poolalloc/trunk/lib/AssistDS/SimplifyMRV.cpp (removed) @@ -1,237 +0,0 @@ -//===-- SimplifyMRV.cpp - Remove extraneous insert/extractvalue insts------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Remove unnecessary insertvalue/extractvalue pairs -// The name of the pass indicates that such pairs are mostly seen when -// mrv(s) occur. -// -// Derived from InstCombine -// -//===----------------------------------------------------------------------===// -#define DEBUG_TYPE "simplifymrv" - -#include "llvm/Instructions.h" -#include "llvm/Module.h" -#include "llvm/Pass.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/PatternMatch.h" -#include "llvm/Target/TargetData.h" - -#include -#include -#include - -using namespace llvm; - -// Pass statistic -STATISTIC(numErased, "Number of Instructions Deleted"); - -namespace { - class SimplifyMRV : public ModulePass { - public: - static char ID; - SimplifyMRV() : ModulePass(&ID) {} - // - // Method: runOnModule() - // - // Description: - // Entry point for this LLVM pass. Search for insert/extractvalue instructions - // that can be simplified. - // - // Inputs: - // M - A reference to the LLVM module to transform. - // - // Outputs: - // M - The transformed LLVM module. - // - // Return value: - // true - The module was modified. - // false - The module was not modified. - // - bool runOnModule(Module& M) { - // Repeat till no change - bool changed; - do { - changed = false; - for (Module::iterator F = M.begin(); F != M.end(); ++F) { - for (Function::iterator B = F->begin(), FE = F->end(); B != FE; ++B) { - for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { - ExtractValueInst *EV = dyn_cast(I++); - if(!EV) - continue; - Value *Agg = EV->getAggregateOperand(); - if (!EV->hasIndices()) { - EV->replaceAllUsesWith(Agg); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - changed = true; - continue; - } - if (Constant *C = dyn_cast(Agg)) { - if (isa(C)) { - EV->replaceAllUsesWith(UndefValue::get(EV->getType())); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - changed = true; - continue; - } - if (isa(C)) { - EV->replaceAllUsesWith(Constant::getNullValue(EV->getType())); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - changed = true; - continue; - } - if (isa(C) || isa(C)) { - // Extract the element indexed by the first index out of the constant - Value *V = C->getOperand(*EV->idx_begin()); - if (EV->getNumIndices() > 1) { - // Extract the remaining indices out of the constant indexed by the - // first index - ExtractValueInst *EV_new = ExtractValueInst::Create(V, - EV->idx_begin() + 1, - EV->idx_end(), "", EV); - EV->replaceAllUsesWith(EV_new); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - changed = true; - continue; - } else { - EV->replaceAllUsesWith(V); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - changed = true; - continue; - } - } - continue; - } - if (InsertValueInst *IV = dyn_cast(Agg)) { - bool done = false; - // We're extracting from an insertvalue instruction, compare the indices - const unsigned *exti, *exte, *insi, *inse; - for (exti = EV->idx_begin(), insi = IV->idx_begin(), - exte = EV->idx_end(), inse = IV->idx_end(); - exti != exte && insi != inse; - ++exti, ++insi) { - if (*insi != *exti) { - // The insert and extract both reference distinctly different elements. - // This means the extract is not influenced by the insert, and we can - // replace the aggregate operand of the extract with the aggregate - // operand of the insert. i.e., replace - // %I = insertvalue { i32, { i32 } } %A, { i32 } { i32 42 }, 1 - // %E = extractvalue { i32, { i32 } } %I, 0 - // with - // %E = extractvalue { i32, { i32 } } %A, 0 - ExtractValueInst *EV_new = ExtractValueInst::Create(IV->getAggregateOperand(), - EV->idx_begin(), EV->idx_end(),"", EV); - EV->replaceAllUsesWith(EV_new); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - done = true; - changed = true; - break; - } - } - if(done) - continue; - if (exti == exte && insi == inse) { - // Both iterators are at the end: Index lists are identical. Replace - // %B = insertvalue { i32, { i32 } } %A, i32 42, 1, 0 - // %C = extractvalue { i32, { i32 } } %B, 1, 0 - // with "i32 42" - EV->replaceAllUsesWith(IV->getInsertedValueOperand()); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - changed = true; - continue; - - } - if (exti == exte) { - // The extract list is a prefix of the insert list. i.e. replace - // %I = insertvalue { i32, { i32 } } %A, i32 42, 1, 0 - // %E = extractvalue { i32, { i32 } } %I, 1 - // with - // %X = extractvalue { i32, { i32 } } %A, 1 - // %E = insertvalue { i32 } %X, i32 42, 0 - // by switching the order of the insert and extract (though the - // insertvalue should be left in, since it may have other uses). - Value *NewEV = ExtractValueInst::Create(IV->getAggregateOperand(), - EV->idx_begin(), EV->idx_end(), "", EV); - Value *NewIV = InsertValueInst::Create(NewEV, IV->getInsertedValueOperand(), - insi, inse, "", EV); - EV->replaceAllUsesWith(NewIV); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - changed = true; - continue; - } - if (insi == inse) { - // The insert list is a prefix of the extract list - // We can simply remove the common indices from the extract and make it - // operate on the inserted value instead of the insertvalue result. - // i.e., replace - // %I = insertvalue { i32, { i32 } } %A, { i32 } { i32 42 }, 1 - // %E = extractvalue { i32, { i32 } } %I, 1, 0 - // with - // %E extractvalue { i32 } { i32 42 }, 0 - ExtractValueInst *EV_new = ExtractValueInst::Create(IV->getInsertedValueOperand(), - exti, exte,"", EV); - EV->replaceAllUsesWith(EV_new); - DEBUG(errs() << "MRV:"); - DEBUG(errs() << "ERASE:"); - DEBUG(EV->dump()); - EV->eraseFromParent(); - numErased++; - changed = true; - continue; - } - } - } - } - } - } while(changed); - return (numErased > 0); - } - }; -} - -// Pass ID variable -char SimplifyMRV::ID = 0; - -// Register the pass -static RegisterPass -X("simplify-mrv", "Simplify extract/insert value insts"); Modified: poolalloc/trunk/test/TEST.types.Makefile URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/test/TEST.types.Makefile?rev=129280&r1=129279&r2=129280&view=diff ============================================================================== --- poolalloc/trunk/test/TEST.types.Makefile (original) +++ poolalloc/trunk/test/TEST.types.Makefile Mon Apr 11 11:20:58 2011 @@ -49,7 +49,7 @@ $(PROGRAMS_TO_TEST:%=Output/%.opt.bc): \ Output/%.opt.bc: Output/%.llvm1.bc $(LOPT) $(ASSIST_SO) - -$(RUNOPT) -load $(ASSIST_SO) -disable-opt -info-output-file=$(CURDIR)/$@.info -instnamer -internalize -mem2reg -dce -simplify-mrv -basiccg -inline -dce -simplify-mrv -dce -varargsfunc -indclone -funcspec -ipsccp -deadargelim -simplify-gep -die -die -mergearrgep -die -globaldce -simplifycfg -deadargelim -arg-simplify -die -varargsfunc -die -simplifycfg -globaldce -indclone -funcspec -deadargelim -globaldce -die -simplifycfg -gep-args -deadargelim -die -mergefunc -die -die -mergearrgep -die -globaldce -int2ptrcmp -die -dce -simplify-mrv -dce -inline -mem2reg -dce -arg-cast -dce -type-analysis -stats -time-passes $< -f -o $@ + -$(RUNOPT) -load $(ASSIST_SO) -disable-opt -info-output-file=$(CURDIR)/$@.info -instnamer -internalize -mem2reg -dce -basiccg -inline -dce -dce -varargsfunc -indclone -funcspec -ipsccp -deadargelim -simplify-gep -die -die -mergearrgep -die -globaldce -simplifycfg -deadargelim -arg-simplify -die -varargsfunc -die -simplifycfg -globaldce -indclone -funcspec -deadargelim -globaldce -die -simplifycfg -gep-args -deadargelim -die -mergefunc -die -die -mergearrgep -die -globaldce -int2ptrcmp -die -dce -dce -inline -mem2reg -dce -arg-cast -dce -stats -time-passes -struct-arg -simplify-ev -simplify-iv -dce $< -f -o $@ $(PROGRAMS_TO_TEST:%=Output/%.temp2.bc): \ Output/%.temp2.bc: Output/%.temp1.bc $(LOPT) $(ASSIST_SO) @@ -214,7 +214,7 @@ @/bin/echo -n "ARG_SMPL: " >> $@ - at grep 'Number of Args changeable' $<.info >> $@ @echo >> $@ - @/bin/echo -n "MRV: " >> $@ + @/bin/echo -n "EV: " >> $@ - at grep 'Number of Instructions Deleted' $<.info >> $@ @echo >> $@ @/bin/echo -n "ALLOC: " >> $@ Modified: poolalloc/trunk/test/TEST.types.report URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/test/TEST.types.report?rev=129280&r1=129279&r2=129280&view=diff ============================================================================== --- poolalloc/trunk/test/TEST.types.report (original) +++ poolalloc/trunk/test/TEST.types.report Mon Apr 11 11:20:58 2011 @@ -169,7 +169,7 @@ ["StdLibFold", "STD_LIB_FOLD: *([0-9]+)"], ["I2PB", "I2PB: *([0-9]+)"], ["I2PS", "I2PS: *([0-9]+)"], - ["MRV", "MRV: *([0-9]+)"], + ["EV", "EV: *([0-9]+)"], ["AL", "ALLOC: *([0-9]+)"], ["DE", "DEALLOC: *([0-9]+)"], ["CAST", "CAST: *([0-9]+)"], From aggarwa4 at illinois.edu Mon Apr 11 11:30:36 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Mon, 11 Apr 2011 16:30:36 -0000 Subject: [llvm-commits] [poolalloc] r129281 - /poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp Message-ID: <20110411163036.DD4A42A6C12D@llvm.org> Author: aggarwa4 Date: Mon Apr 11 11:30:36 2011 New Revision: 129281 URL: http://llvm.org/viewvc/llvm-project?rev=129281&view=rev Log: For functions that return structs, return a pointer instead. Added: poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp Added: poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp?rev=129281&view=auto ============================================================================== --- poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp (added) +++ poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp Mon Apr 11 11:30:36 2011 @@ -0,0 +1,140 @@ +//===-------- StructReturnToPointer.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#define DEBUG_TYPE "struct-ret" + +#include "llvm/Instructions.h" +#include "llvm/Attributes.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Debug.h" + +#include +#include +#include + +using namespace llvm; + + +namespace { + + class StructArg : public ModulePass { + public: + static char ID; + StructArg() : ModulePass(&ID) {} + + // + // Method: runOnModule() + // + // Description: + // Entry point for this LLVM pass. + // If a function returns a struct, make it return + // a pointer to the struct. + // + // Inputs: + // M - A reference to the LLVM module to transform + // + // Outputs: + // M - The transformed LLVM module. + // + // Return value: + // true - The module was modified. + // false - The module was not modified. + // + bool runOnModule(Module& M) { + + std::vector worklistR; + for (Module::iterator I = M.begin(); I != M.end(); ++I) + if (!I->isDeclaration() && !I->mayBeOverridden()) { + if(I->hasAddressTaken()) + continue; + if(I->getReturnType()->isStructTy()) { + worklistR.push_back(I); + } + } + + while(!worklistR.empty()) { + Function *F = worklistR.back(); + worklistR.pop_back(); + const Type *NewReturnType = F->getReturnType()->getPointerTo(); + + // Construct the new Type + std::vectorTP; + for (Function::arg_iterator ii = F->arg_begin(), ee = F->arg_end(); + ii != ee; ++ii) { + TP.push_back(ii->getType()); + } + + const FunctionType *NFTy = FunctionType::get(NewReturnType, TP, false); + + // Create the new function body and insert it into the module. + Function *NF = Function::Create(NFTy, F->getLinkage(), F->getName(), &M); + NF->copyAttributesFrom(F); + Function::arg_iterator NI = NF->arg_begin(); + for (Function::arg_iterator II = F->arg_begin(); II != F->arg_end(); ++II, ++NI) { + II->replaceAllUsesWith(NI); + NI->setName(II->getName()); + } + NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); + Instruction *InsertPoint; + for (BasicBlock::iterator insrt = NF->front().begin(); isa(InsertPoint = insrt); ++insrt) {;} + + Function* MallocF = M.getFunction ("malloc"); + const Type* IntPtrT = Type::getInt64Ty(M.getContext()); + + const Type *BPTy = Type::getInt8PtrTy(M.getContext()); + Value *MallocFunc = MallocF; + Constant *Size; + if (!MallocFunc) { + // prototype malloc as "void *malloc(size_t)" + Size = ConstantInt::get (IntPtrT, 123, true); + MallocFunc = M.getOrInsertFunction("malloc", BPTy, IntPtrT, NULL); + } else { + Size = ConstantInt::get (MallocF->arg_begin()->getType(), 123, true); + } + CallInst *MCall = CallInst::Create(MallocFunc,Size, "ret_ptr", InsertPoint); + Instruction *Result = new BitCastInst(MCall, NewReturnType, "", InsertPoint); + for (Function::iterator B = NF->begin(), FE = NF->end(); B != FE; ++B) { + for (BasicBlock::iterator I = B->begin(), BE = B->end(); I != BE;) { + ReturnInst * RI = dyn_cast(I++); + if(!RI) + continue; + new StoreInst(RI->getOperand(0), Result, RI); + ReturnInst::Create(M.getContext(), Result, RI); + RI->eraseFromParent(); + } + } + + for(Value::use_iterator ui = F->use_begin(), ue = F->use_end(); + ui != ue; ) { + CallInst *CI = dyn_cast(ui++); + SmallVector Args; + for(unsigned j =1;jgetNumOperands();j++) { + Args.push_back(CI->getOperand(j)); + } + CallInst *CINew = CallInst::Create(NF, Args.begin(), Args.end(), "", CI); + LoadInst *LI = new LoadInst(CINew, "", CI); + CI->replaceAllUsesWith(LI); + CI->eraseFromParent(); + } + F->eraseFromParent(); + } + return true; + } + }; +} + +// Pass ID variable +char StructArg::ID = 0; + +// Register the pass +static RegisterPass +X("struct-ret", "Find struct arguments"); From aggarwa4 at illinois.edu Mon Apr 11 11:33:48 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Mon, 11 Apr 2011 16:33:48 -0000 Subject: [llvm-commits] [poolalloc] r129282 - /poolalloc/trunk/test/TEST.types.Makefile Message-ID: <20110411163348.1C20D2A6C12D@llvm.org> Author: aggarwa4 Date: Mon Apr 11 11:33:47 2011 New Revision: 129282 URL: http://llvm.org/viewvc/llvm-project?rev=129282&view=rev Log: Use the new -struct-ret pass. Modified: poolalloc/trunk/test/TEST.types.Makefile Modified: poolalloc/trunk/test/TEST.types.Makefile URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/test/TEST.types.Makefile?rev=129282&r1=129281&r2=129282&view=diff ============================================================================== --- poolalloc/trunk/test/TEST.types.Makefile (original) +++ poolalloc/trunk/test/TEST.types.Makefile Mon Apr 11 11:33:47 2011 @@ -49,7 +49,7 @@ $(PROGRAMS_TO_TEST:%=Output/%.opt.bc): \ Output/%.opt.bc: Output/%.llvm1.bc $(LOPT) $(ASSIST_SO) - -$(RUNOPT) -load $(ASSIST_SO) -disable-opt -info-output-file=$(CURDIR)/$@.info -instnamer -internalize -mem2reg -dce -basiccg -inline -dce -dce -varargsfunc -indclone -funcspec -ipsccp -deadargelim -simplify-gep -die -die -mergearrgep -die -globaldce -simplifycfg -deadargelim -arg-simplify -die -varargsfunc -die -simplifycfg -globaldce -indclone -funcspec -deadargelim -globaldce -die -simplifycfg -gep-args -deadargelim -die -mergefunc -die -die -mergearrgep -die -globaldce -int2ptrcmp -die -dce -dce -inline -mem2reg -dce -arg-cast -dce -stats -time-passes -struct-arg -simplify-ev -simplify-iv -dce $< -f -o $@ + -$(RUNOPT) -load $(ASSIST_SO) -disable-opt -info-output-file=$(CURDIR)/$@.info -instnamer -internalize -mem2reg -dce -basiccg -inline -dce -dce -varargsfunc -indclone -funcspec -ipsccp -deadargelim -simplify-gep -die -die -mergearrgep -die -globaldce -simplifycfg -deadargelim -arg-simplify -die -varargsfunc -die -simplifycfg -globaldce -indclone -funcspec -deadargelim -globaldce -die -simplifycfg -gep-args -deadargelim -die -mergefunc -die -die -mergearrgep -die -globaldce -int2ptrcmp -die -dce -dce -inline -mem2reg -dce -arg-cast -dce -struct-ret -simplify-ev -simplify-iv -dce -stats -time-passes $< -f -o $@ $(PROGRAMS_TO_TEST:%=Output/%.temp2.bc): \ Output/%.temp2.bc: Output/%.temp1.bc $(LOPT) $(ASSIST_SO) From jay.foad at gmail.com Mon Apr 11 13:08:17 2011 From: jay.foad at gmail.com (Jay Foad) Date: Mon, 11 Apr 2011 19:08:17 +0100 Subject: [llvm-commits] [llvm] r129235 - in /llvm/trunk: include/llvm/BasicBlock.h include/llvm/Bitcode/LLVMBitCodes.h lib/AsmParser/LLLexer.cpp lib/AsmParser/LLParser.cpp lib/AsmParser/LLToken.h lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/Bit Message-ID: > There is an issue, but I would say that the issue is in getting > the right exception value / selector value at the point where decisions about > branching to catch clauses is made, I've been wondering for a while if these things could be represented as new kinds of Value: class ExceptionPointer : public User { ... } // or "ExceptionValue" in your terminology class ExceptionIndex : public User { ... } // or "SelectorValue" which have a single operand which is a BasicBlock, and represent the exception/selector value from when that basic block was (last) jumped to as a landing pad. I think this would codegen quite straightforwardly. Jay. From stoklund at 2pi.dk Mon Apr 11 13:08:10 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 18:08:10 -0000 Subject: [llvm-commits] [llvm] r129283 - in /llvm/trunk/lib/CodeGen: LiveIntervalAnalysis.cpp SimpleRegisterCoalescing.cpp Message-ID: <20110411180810.4A4502A6C12D@llvm.org> Author: stoklund Date: Mon Apr 11 13:08:10 2011 New Revision: 129283 URL: http://llvm.org/viewvc/llvm-project?rev=129283&view=rev Log: Don't add live ranges for sub-registers when clobbering a physical register. Both coalescing and register allocation already check aliases for interference, so these extra segments are only slowing us down. This speeds up both linear scan and the greedy register allocator. Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp?rev=129283&r1=129282&r2=129283&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp Mon Apr 11 13:08:10 2011 @@ -578,13 +578,6 @@ CopyMI = MI; handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, getOrCreateInterval(MO.getReg()), CopyMI); - // Def of a register also defines its sub-registers. - for (const unsigned* AS = tri_->getSubRegisters(MO.getReg()); *AS; ++AS) - // If MI also modifies the sub-register explicitly, avoid processing it - // more than once. Do not pass in TRI here so it checks for exact match. - if (!MI->definesRegister(*AS)) - handlePhysicalRegisterDef(MBB, MI, MIIdx, MO, - getOrCreateInterval(*AS), 0); } } Modified: llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp?rev=129283&r1=129282&r2=129283&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp (original) +++ llvm/trunk/lib/CodeGen/SimpleRegisterCoalescing.cpp Mon Apr 11 13:08:10 2011 @@ -208,15 +208,14 @@ if (ValLR+1 != BLR) return false; // If a live interval is a physical register, conservatively check if any - // of its sub-registers is overlapping the live interval of the virtual - // register. If so, do not coalesce. - if (TargetRegisterInfo::isPhysicalRegister(IntB.reg) && - *tri_->getSubRegisters(IntB.reg)) { - for (const unsigned* SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) - if (li_->hasInterval(*SR) && IntA.overlaps(li_->getInterval(*SR))) { + // of its aliases is overlapping the live interval of the virtual register. + // If so, do not coalesce. + if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { + for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) + if (li_->hasInterval(*AS) && IntA.overlaps(li_->getInterval(*AS))) { DEBUG({ - dbgs() << "\t\tInterfere with sub-register "; - li_->getInterval(*SR).print(dbgs(), tri_); + dbgs() << "\t\tInterfere with alias "; + li_->getInterval(*AS).print(dbgs(), tri_); }); return false; } From enderby at apple.com Mon Apr 11 13:08:50 2011 From: enderby at apple.com (Kevin Enderby) Date: Mon, 11 Apr 2011 18:08:50 -0000 Subject: [llvm-commits] [llvm] r129284 - in /llvm/trunk: include/llvm-c/Disassembler.h include/llvm/MC/MCDisassembler.h lib/MC/MCDisassembler/Disassembler.cpp lib/MC/MCDisassembler/Disassembler.h lib/Target/ARM/Disassembler/ARMDisassembler.cpp lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp lib/Target/ARM/Disassembler/ARMDisassemblerCore.h lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Message-ID: <20110411180850.4C3B92A6C12D@llvm.org> Author: enderby Date: Mon Apr 11 13:08:50 2011 New Revision: 129284 URL: http://llvm.org/viewvc/llvm-project?rev=129284&view=rev Log: Adding support for printing operands symbolically to llvm's public 'C' disassembler API. Hooked this up to the ARM target so such tools as Darwin's otool(1) can now print things like branch targets for example this: blx _puts instead of this: blx #-36 And even print the expression encoded in the Mach-O relocation entried for things like this: movt r0, :upper16:((_foo-_bar)+1234) Modified: llvm/trunk/include/llvm-c/Disassembler.h llvm/trunk/include/llvm/MC/MCDisassembler.h llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp llvm/trunk/lib/MC/MCDisassembler/Disassembler.h llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Modified: llvm/trunk/include/llvm-c/Disassembler.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Disassembler.h?rev=129284&r1=129283&r2=129284&view=diff ============================================================================== --- llvm/trunk/include/llvm-c/Disassembler.h (original) +++ llvm/trunk/include/llvm-c/Disassembler.h Mon Apr 11 13:08:50 2011 @@ -48,6 +48,49 @@ void *TagBuf); /** + * The initial support in LLVM MC for the most general form of a relocatable + * expression is "AddSymbol - SubtractSymbol + Offset". For some Darwin targets + * this full form is encoded in the relocation information so that AddSymbol and + * SubtractSymbol can be link edited independent of each other. Many other + * platforms only allow a relocatable expression of the form AddSymbol + Offset + * to be encoded. + * + * The LLVMOpInfoCallback() for the TagType value of 1 uses the struct + * LLVMOpInfo1. The value of the relocatable expression for the operand, + * including any PC adjustment, is passed in to the call back in the Value + * field. The symbolic information about the operand is returned using all + * the fields of the structure with the Offset of the relocatable expression + * returned in the Value field. It is possible that some symbols in the + * relocatable expression were assembly temporary symbols, for example + * "Ldata - LpicBase + constant", and only the Values of the symbols without + * symbol names are present in the relocation information. The VariantKind + * type is one of the Target specific #defines below and is used to print + * operands like "_foo at GOT", ":lower16:_foo", etc. + */ +struct LLVMOpInfoSymbol1 { + uint64_t Present; /* 1 if this symbol is present */ + char *Name; /* symbol name if not NULL */ + uint64_t Value; /* symbol value if name is NULL */ +}; +struct LLVMOpInfo1 { + struct LLVMOpInfoSymbol1 AddSymbol; + struct LLVMOpInfoSymbol1 SubtractSymbol; + uint64_t Value; + uint64_t VariantKind; +}; + +/** + * The operand VariantKinds for symbolic disassembly. + */ +#define LLVMDisassembler_VariantKind_None 0 /* all targets */ + +/** + * The ARM target VariantKinds. + */ +#define LLVMDisassembler_VariantKind_ARM_HI16 1 /* :upper16: */ +#define LLVMDisassembler_VariantKind_ARM_LO16 2 /* :lower16: */ + +/** * The type for the symbol lookup function. This may be called by the * disassembler for such things like adding a comment for a PC plus a constant * offset load instruction to use a symbol name instead of a load address value. Modified: llvm/trunk/include/llvm/MC/MCDisassembler.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCDisassembler.h?rev=129284&r1=129283&r2=129284&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCDisassembler.h (original) +++ llvm/trunk/include/llvm/MC/MCDisassembler.h Mon Apr 11 13:08:50 2011 @@ -10,12 +10,14 @@ #define MCDISASSEMBLER_H #include "llvm/Support/DataTypes.h" +#include "llvm-c/Disassembler.h" namespace llvm { class MCInst; class MemoryObject; class raw_ostream; +class MCContext; struct EDInstInfo; @@ -24,7 +26,7 @@ class MCDisassembler { public: /// Constructor - Performs initial setup for the disassembler. - MCDisassembler() {} + MCDisassembler() : GetOpInfo(0), DisInfo(0), Ctx(0) {} virtual ~MCDisassembler(); @@ -53,6 +55,30 @@ /// each MCInst opcode this disassembler returns. /// NULL if there is no info for this target. virtual EDInstInfo *getEDInfo() const { return (EDInstInfo*)0; } + +private: + // + // Hooks for symbolic disassembly via the public 'C' interface. + // + // The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + // The pointer to the block of symbolic information for above call back. + void *DisInfo; + // The assembly context for creating symbols and MCExprs in place of + // immediate operands when there is symbolic information. + MCContext *Ctx; + +public: + void setupForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo, + void *disInfo, + MCContext *ctx) { + GetOpInfo = getOpInfo; + DisInfo = disInfo; + Ctx = ctx; + } + LLVMOpInfoCallback getLLVMOpInfoCallback() const { return GetOpInfo; } + void *getDisInfoBlock() const { return DisInfo; } + MCContext *getMCContext() const { return Ctx; } }; } // namespace llvm Modified: llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp?rev=129284&r1=129283&r2=129284&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp (original) +++ llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp Mon Apr 11 13:08:50 2011 @@ -77,8 +77,9 @@ assert(Ctx && "Unable to create MCContext!"); // Set up disassembler. - const MCDisassembler *DisAsm = TheTarget->createMCDisassembler(); + MCDisassembler *DisAsm = TheTarget->createMCDisassembler(); assert(DisAsm && "Unable to create disassembler!"); + DisAsm->setupForSymbolicDisassembly(GetOpInfo, DisInfo, Ctx); // Set up the instruction printer. int AsmPrinterVariant = MAI->getAssemblerDialect(); Modified: llvm/trunk/lib/MC/MCDisassembler/Disassembler.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDisassembler/Disassembler.h?rev=129284&r1=129283&r2=129284&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCDisassembler/Disassembler.h (original) +++ llvm/trunk/lib/MC/MCDisassembler/Disassembler.h Mon Apr 11 13:08:50 2011 @@ -69,7 +69,7 @@ public: LLVMDisasmContext(std::string tripleName, void *disInfo, int tagType, - LLVMOpInfoCallback getOpInfo, + LLVMOpInfoCallback getOpInfo, LLVMSymbolLookupCallback symbolLookUp, const Target *theTarget, const MCAsmInfo *mAI, llvm::TargetMachine *tM, const TargetAsmInfo *tai, Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp?rev=129284&r1=129283&r2=129284&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Mon Apr 11 13:08:50 2011 @@ -422,6 +422,10 @@ if (!Builder) return false; + Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(), + getDisInfoBlock(), getMCContext(), + Address); + if (!Builder->Build(MI, insn)) return false; @@ -504,6 +508,10 @@ Builder->SetSession(const_cast(&SO)); + Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(), + getDisInfoBlock(), getMCContext(), + Address); + if (!Builder->Build(MI, insn)) return false; Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=129284&r1=129283&r2=129284&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Mon Apr 11 13:08:50 2011 @@ -17,6 +17,7 @@ #include "ARMDisassemblerCore.h" #include "ARMAddressingModes.h" +#include "ARMMCExpr.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -1066,7 +1067,8 @@ // We have an imm16 = imm4:imm12 (imm4=Inst{19:16}, imm12 = Inst{11:0}). assert(getIBit(insn) == 1 && "I_Bit != '1' reg/imm form"); unsigned Imm16 = slice(insn, 19, 16) << 12 | slice(insn, 11, 0); - MI.addOperand(MCOperand::CreateImm(Imm16)); + if (!B->tryAddingSymbolicOperand(Imm16, 4, MI)) + MI.addOperand(MCOperand::CreateImm(Imm16)); ++OpIdx; } else { // We have a reg/imm form. @@ -3628,3 +3630,80 @@ return new ARMBasicMCBuilder(Opcode, Format, ARMInsts[Opcode].getNumOperands()); } + +/// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic +/// operand in place of the immediate Value in the MCInst. The immediate +/// Value has had any PC adjustment made by the caller. If the getOpInfo() +/// function was set as part of the setupBuilderForSymbolicDisassembly() call +/// then that function is called to get any symbolic information at the +/// builder's Address for this instrution. If that returns non-zero then the +/// symbolic information is returns is used to create an MCExpr and that is +/// added as an operand to the MCInst. This function returns true if it adds +/// an operand to the MCInst and false otherwise. +bool ARMBasicMCBuilder::tryAddingSymbolicOperand(uint64_t Value, + uint64_t InstSize, + MCInst &MI) { + if (!GetOpInfo) + return false; + + struct LLVMOpInfo1 SymbolicOp; + SymbolicOp.Value = Value; + if (!GetOpInfo(DisInfo, Address, 0 /* Offset */, InstSize, 1, &SymbolicOp)) + return false; + + const MCExpr *Add = NULL; + if (SymbolicOp.AddSymbol.Present) { + if (SymbolicOp.AddSymbol.Name) { + StringRef Name(SymbolicOp.AddSymbol.Name); + MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name); + Add = MCSymbolRefExpr::Create(Sym, *Ctx); + } else { + Add = MCConstantExpr::Create(SymbolicOp.AddSymbol.Value, *Ctx); + } + } + + const MCExpr *Sub = NULL; + if (SymbolicOp.SubtractSymbol.Present) { + if (SymbolicOp.SubtractSymbol.Name) { + StringRef Name(SymbolicOp.SubtractSymbol.Name); + MCSymbol *Sym = Ctx->GetOrCreateSymbol(Name); + Sub = MCSymbolRefExpr::Create(Sym, *Ctx); + } else { + Sub = MCConstantExpr::Create(SymbolicOp.SubtractSymbol.Value, *Ctx); + } + } + + const MCExpr *Off = NULL; + if (SymbolicOp.Value != 0) + Off = MCConstantExpr::Create(SymbolicOp.Value, *Ctx); + + const MCExpr *Expr; + if (Sub) { + const MCExpr *LHS; + if (Add) + LHS = MCBinaryExpr::CreateSub(Add, Sub, *Ctx); + else + LHS = MCUnaryExpr::CreateMinus(Sub, *Ctx); + if (Off != 0) + Expr = MCBinaryExpr::CreateAdd(LHS, Off, *Ctx); + else + Expr = LHS; + } else if (Add) { + if (Off != 0) + Expr = MCBinaryExpr::CreateAdd(Add, Off, *Ctx); + else + Expr = Add; + } else + Expr = Off; + + if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_HI16) + MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateUpper16(Expr, *Ctx))); + else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_ARM_LO16) + MI.addOperand(MCOperand::CreateExpr(ARMMCExpr::CreateLower16(Expr, *Ctx))); + else if (SymbolicOp.VariantKind == LLVMDisassembler_VariantKind_None) + MI.addOperand(MCOperand::CreateExpr(Expr)); + else + assert("bad SymbolicOp.VariantKind"); + + return true; +} Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h?rev=129284&r1=129283&r2=129284&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h Mon Apr 11 13:08:50 2011 @@ -22,12 +22,17 @@ #define ARMDISASSEMBLERCORE_H #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCContext.h" #include "llvm/Target/TargetInstrInfo.h" +#include "llvm-c/Disassembler.h" #include "ARMBaseInstrInfo.h" #include "ARMRegisterInfo.h" #include "ARMDisassembler.h" namespace llvm { +class MCContext; class ARMUtils { public: @@ -202,7 +207,7 @@ public: ARMBasicMCBuilder(ARMBasicMCBuilder &B) : Opcode(B.Opcode), Format(B.Format), NumOps(B.NumOps), Disasm(B.Disasm), - SP(B.SP) { + SP(B.SP), GetOpInfo(0), DisInfo(0), Ctx(0) { Err = 0; } @@ -261,6 +266,44 @@ assert(SP); return slice(SP->ITState, 7, 4); } + +private: + // + // Hooks for symbolic disassembly via the public 'C' interface. + // + // The function to get the symbolic information for operands. + LLVMOpInfoCallback GetOpInfo; + // The pointer to the block of symbolic information for above call back. + void *DisInfo; + // The assembly context for creating symbols and MCExprs in place of + // immediate operands when there is symbolic information. + MCContext *Ctx; + // The address of the instruction being disassembled. + uint64_t Address; + +public: + void setupBuilderForSymbolicDisassembly(LLVMOpInfoCallback getOpInfo, + void *disInfo, MCContext *ctx, + uint64_t address) { + GetOpInfo = getOpInfo; + DisInfo = disInfo; + Ctx = ctx; + Address = address; + } + + uint64_t getBuilderAddress() const { return Address; } + + /// tryAddingSymbolicOperand - tryAddingSymbolicOperand trys to add a symbolic + /// operand in place of the immediate Value in the MCInst. The immediate + /// Value has had any PC adjustment made by the caller. If the getOpInfo() + /// function was set as part of the setupBuilderForSymbolicDisassembly() call + /// then that function is called to get any symbolic information at the + /// builder's Address for this instrution. If that returns non-zero then the + /// symbolic information is returns is used to create an MCExpr and that is + /// added as an operand to the MCInst. This function returns true if it adds + /// an operand to the MCInst and false otherwise. + bool tryAddingSymbolicOperand(uint64_t Value, uint64_t InstSize, MCInst &MI); + }; } // namespace llvm Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129284&r1=129283&r2=129284&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Mon Apr 11 13:08:50 2011 @@ -1570,9 +1570,10 @@ if (Opcode == ARM::t2ADDri12 || Opcode == ARM::t2SUBri12 || Opcode == ARM::t2LEApcrel) MI.addOperand(MCOperand::CreateImm(getIImm3Imm8(insn))); - else if (Opcode == ARM::t2MOVi16 || Opcode == ARM::t2MOVTi16) - MI.addOperand(MCOperand::CreateImm(getImm16(insn))); - else if (Opcode == ARM::t2BFC || Opcode == ARM::t2BFI) { + else if (Opcode == ARM::t2MOVi16 || Opcode == ARM::t2MOVTi16) { + if (!B->tryAddingSymbolicOperand(getImm16(insn), 4, MI)) + MI.addOperand(MCOperand::CreateImm(getImm16(insn))); + } else if (Opcode == ARM::t2BFC || Opcode == ARM::t2BFI) { uint32_t mask = 0; if (getBitfieldInvMask(insn, mask)) MI.addOperand(MCOperand::CreateImm(mask)); @@ -1756,7 +1757,9 @@ Offset = decodeImm32_BLX(insn); break; } - MI.addOperand(MCOperand::CreateImm(Offset)); + + if (!B->tryAddingSymbolicOperand(Offset + B->getBuilderAddress() + 4, 4, MI)) + MI.addOperand(MCOperand::CreateImm(Offset)); // This is an increment as some predicate operands may have been added first. NumOpsAdded += 1; From baldrick at free.fr Mon Apr 11 13:34:49 2011 From: baldrick at free.fr (Duncan Sands) Date: Mon, 11 Apr 2011 20:34:49 +0200 Subject: [llvm-commits] [llvm] r129235 - in /llvm/trunk: include/llvm/BasicBlock.h include/llvm/Bitcode/LLVMBitCodes.h lib/AsmParser/LLLexer.cpp lib/AsmParser/LLParser.cpp lib/AsmParser/LLToken.h lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/Bit In-Reply-To: References: Message-ID: <4DA349C9.8090401@free.fr> Hi Jay, >> There is an issue, but I would say that the issue is in getting >> the right exception value / selector value at the point where decisions about >> branching to catch clauses is made, > > I've been wondering for a while if these things could be represented > as new kinds of Value: > > class ExceptionPointer : public User { ... } // or "ExceptionValue" in > your terminology > class ExceptionIndex : public User { ... } // or "SelectorValue" > > which have a single operand which is a BasicBlock, and represent the > exception/selector value from when that basic block was (last) jumped > to as a landing pad. I think this would codegen quite > straightforwardly. having an intrinsic or instruction that takes a basic block as an argument is indeed one of the possible solutions. Ciao, Duncan. From johnny.chen at apple.com Mon Apr 11 13:34:13 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Apr 2011 18:34:13 -0000 Subject: [llvm-commits] [llvm] r129286 - in /llvm/trunk: lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt Message-ID: <20110411183413.1C1102A6C12D@llvm.org> Author: johnny Date: Mon Apr 11 13:34:12 2011 New Revision: 129286 URL: http://llvm.org/viewvc/llvm-project?rev=129286&view=rev Log: Check invalid register encodings for LdFrm/StFrm ARM instructions and flag them as invalid instructions. Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=129286&r1=129285&r2=129286&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Mon Apr 11 13:34:12 2011 @@ -1175,6 +1175,71 @@ return true; } +static bool BadRegsLdStFrm(unsigned Opcode, uint32_t insn, bool Store, bool WBack, + bool Imm) { + const StringRef Name = ARMInsts[Opcode].Name; + unsigned Rt = decodeRd(insn); + unsigned Rn = decodeRn(insn); + unsigned Rm = decodeRm(insn); + unsigned P = getPBit(insn); + unsigned W = getWBit(insn); + + if (Store) { + // Only STR (immediate, register) allows PC as the source. + if (Name.startswith("STRB") && Rt == 15) { + DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n"); + return true; + } + if (WBack && (Rn == 15 || Rn == Rt)) { + DEBUG(errs() << "if wback && (n == 15 || n == t) then UNPREDICTABLE\n"); + return true; + } + if (!Imm && Rm == 15) { + DEBUG(errs() << "if m == 15 then UNPREDICTABLE\n"); + return true; + } + } else { + // Only LDR (immediate, register) allows PC as the destination. + if (Name.startswith("LDRB") && Rt == 15) { + DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n"); + return true; + } + if (Imm) { + // Immediate + if (Rn == 15) { + // The literal form must be in offset mode; it's an encoding error + // otherwise. + if (!(P == 1 && W == 0)) { + DEBUG(errs() << "Ld literal form with !(P == 1 && W == 0)\n"); + return true; + } + // LDRB (literal) does not allow PC as the destination. + if (Opcode != ARM::LDRi12 && Rt == 15) { + DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n"); + return true; + } + } else { + // Write back while Rn == Rt does not make sense. + if (WBack && (Rn == Rt)) { + DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n"); + return true; + } + } + } else { + // Register + if (Rm == 15) { + DEBUG(errs() << "if m == 15 then UNPREDICTABLE\n"); + return true; + } + if (WBack && (Rn == 15 || Rn == Rt)) { + DEBUG(errs() << "if wback && (n == 15 || n == t) then UNPREDICTABLE\n"); + return true; + } + } + } + return false; +} + static bool DisassembleLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) { @@ -1237,6 +1302,9 @@ if (OpIdx + 1 >= NumOps) return false; + if (BadRegsLdStFrm(Opcode, insn, isStore, isPrePost, getIBit(insn)==0)) + return false; + ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; unsigned IndexMode = (TID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt?rev=129286&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt Mon Apr 11 13:34:12 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=140 Name=LDRB_POST Format=ARM_FORMAT_LDFRM(6) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 0| 0: 1: 1: 0| 1: 1: 0: 1| 0: 1: 1: 1| 0: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 1: 0: 1| +# ------------------------------------------------------------------------------------------------- +# +# if wback && (n == 15 || n == t) then UNPREDICTABLE +0x05 0x70 0xd7 0xe6 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt?rev=129286&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt Mon Apr 11 13:34:12 2011 @@ -0,0 +1,4 @@ +# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} + +# LDR_PRE/POST has encoding Inst{4} = 0. +0xde 0x69 0x18 0x46 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt?rev=129286&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt Mon Apr 11 13:34:12 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=165 Name=LDR_PRE Format=ARM_FORMAT_LDFRM(6) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 0| 0: 1: 1: 1| 1: 0: 1: 1| 0: 1: 1: 1| 0: 1: 1: 0| 0: 0: 0: 0| 1: 0: 0: 0| 1: 1: 1: 1| +# ------------------------------------------------------------------------------------------------- +# +# if m == 15 then UNPREDICTABLE +0x8f 0x60 0xb7 0xe7 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt?rev=129286&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt Mon Apr 11 13:34:12 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=355 Name=STRBrs Format=ARM_FORMAT_STFRM(7) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 0| 0: 1: 1: 1| 1: 1: 0: 0| 1: 1: 1: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| +# ------------------------------------------------------------------------------------------------- +# +# if t == 15 then UNPREDICTABLE +0x00 0xf0 0xcf 0xe7 From evan.cheng at apple.com Mon Apr 11 13:47:20 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 11 Apr 2011 18:47:20 -0000 Subject: [llvm-commits] [llvm] r129287 - in /llvm/trunk/lib/CodeGen: MachineCSE.cpp MachineSink.cpp Message-ID: <20110411184720.7D9212A6C12D@llvm.org> Author: evancheng Date: Mon Apr 11 13:47:20 2011 New Revision: 129287 URL: http://llvm.org/viewvc/llvm-project?rev=129287&view=rev Log: Fix a couple of places where changes are made but not tracked. Modified: llvm/trunk/lib/CodeGen/MachineCSE.cpp llvm/trunk/lib/CodeGen/MachineSink.cpp Modified: llvm/trunk/lib/CodeGen/MachineCSE.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineCSE.cpp?rev=129287&r1=129286&r2=129287&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineCSE.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineCSE.cpp Mon Apr 11 13:47:20 2011 @@ -365,6 +365,8 @@ if (!FoundCSE) { // Look for trivial copy coalescing opportunities. if (PerformTrivialCoalescing(MI, MBB)) { + Changed = true; + // After coalescing MI itself may become a copy. if (MI->isCopyLike()) continue; @@ -379,10 +381,11 @@ if (NewMI) { Commuted = true; FoundCSE = VNT.count(NewMI); - if (NewMI != MI) + if (NewMI != MI) { // New instruction. It doesn't need to be kept. NewMI->eraseFromParent(); - else if (!FoundCSE) + Changed = true; + } else if (!FoundCSE) // MI was changed but it didn't help, commute it back! (void)TII->commuteInstruction(MI); } @@ -450,6 +453,7 @@ ++NumPhysCSEs; if (Commuted) ++NumCommutes; + Changed = true; } else { DEBUG(dbgs() << "*** Not profitable, avoid CSE!\n"); VNT.insert(MI, CurrVN++); Modified: llvm/trunk/lib/CodeGen/MachineSink.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineSink.cpp?rev=129287&r1=129286&r2=129287&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineSink.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineSink.cpp Mon Apr 11 13:47:20 2011 @@ -265,8 +265,11 @@ if (MI->isDebugValue()) continue; - if (PerformTrivialForwardCoalescing(MI, &MBB)) + bool Joined = PerformTrivialForwardCoalescing(MI, &MBB); + if (Joined) { + MadeChange = true; continue; + } if (SinkInstruction(MI, SawStore)) ++NumSunk, MadeChange = true; From johnny.chen at apple.com Mon Apr 11 13:51:50 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Apr 2011 18:51:50 -0000 Subject: [llvm-commits] [llvm] r129288 - in /llvm/trunk/lib/Target/ARM/Disassembler: ARMDisassemblerCore.cpp ARMDisassemblerCore.h Message-ID: <20110411185150.7D9FD2A6C12D@llvm.org> Author: johnny Date: Mon Apr 11 13:51:50 2011 New Revision: 129288 URL: http://llvm.org/viewvc/llvm-project?rev=129288&view=rev Log: Trivial comment fix. Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=129288&r1=129287&r2=129288&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Mon Apr 11 13:51:50 2011 @@ -3705,7 +3705,7 @@ /// function was set as part of the setupBuilderForSymbolicDisassembly() call /// then that function is called to get any symbolic information at the /// builder's Address for this instrution. If that returns non-zero then the -/// symbolic information is returns is used to create an MCExpr and that is +/// symbolic information it returns is used to create an MCExpr and that is /// added as an operand to the MCInst. This function returns true if it adds /// an operand to the MCInst and false otherwise. bool ARMBasicMCBuilder::tryAddingSymbolicOperand(uint64_t Value, Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h?rev=129288&r1=129287&r2=129288&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h Mon Apr 11 13:51:50 2011 @@ -299,7 +299,7 @@ /// function was set as part of the setupBuilderForSymbolicDisassembly() call /// then that function is called to get any symbolic information at the /// builder's Address for this instrution. If that returns non-zero then the - /// symbolic information is returns is used to create an MCExpr and that is + /// symbolic information it returns is used to create an MCExpr and that is /// added as an operand to the MCInst. This function returns true if it adds /// an operand to the MCInst and false otherwise. bool tryAddingSymbolicOperand(uint64_t Value, uint64_t InstSize, MCInst &MI); From grosbach at apple.com Mon Apr 11 13:57:22 2011 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 11 Apr 2011 11:57:22 -0700 Subject: [llvm-commits] [llvm] r128940 - in /llvm/trunk/lib/Target/ARM: ARMExpandPseudoInsts.cpp ARMISelLowering.cpp ARMInstrInfo.td In-Reply-To: <20110405214858.1EC0F2A6C12D@llvm.org> References: <20110405214858.1EC0F2A6C12D@llvm.org> Message-ID: <2FA3BB07-8D35-424E-A908-D7C0D27E343F@apple.com> Hi Owen, Sorry for the late response. This needs the same ARMPseudoInst treatment you gave RSB/RSC in r128965. Otherwise, we're defining a pseudo-instruction with real instruction patterns, which isn't good, plus we run into the same instruction composition errors (duplicate operands and such), resulting in an assertion error when building ClamAV. -Jim On Apr 5, 2011, at 2:48 PM, Owen Anderson wrote: > Author: resistor > Date: Tue Apr 5 16:48:57 2011 > New Revision: 128940 > > URL: http://llvm.org/viewvc/llvm-project?rev=128940&view=rev > Log: > Fix bugs in the pseuo-ization of ADCS/SBCS pointed out by Jim, as well as doing the expansion earlier (using a custom inserter) to allow for the chance of predicating these instructions. > > Modified: > llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp > llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp > llvm/trunk/lib/Target/ARM/ARMInstrInfo.td > > Modified: llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp?rev=128940&r1=128939&r2=128940&view=diff > ============================================================================== > --- llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp (original) > +++ llvm/trunk/lib/Target/ARM/ARMExpandPseudoInsts.cpp Tue Apr 5 16:48:57 2011 > @@ -55,7 +55,6 @@ > void ExpandVLD(MachineBasicBlock::iterator &MBBI); > void ExpandVST(MachineBasicBlock::iterator &MBBI); > void ExpandLaneOp(MachineBasicBlock::iterator &MBBI); > - void ExpandSBitOp(MachineBasicBlock::iterator &MBBI); > void ExpandVTBL(MachineBasicBlock::iterator &MBBI, > unsigned Opc, bool IsExt, unsigned NumRegs); > void ExpandMOV32BitImm(MachineBasicBlock &MBB, > @@ -630,43 +629,6 @@ > MI.eraseFromParent(); > } > > -void ARMExpandPseudo::ExpandSBitOp(MachineBasicBlock::iterator &MBBI) { > - MachineInstr &MI = *MBBI; > - MachineBasicBlock &MBB = *MI.getParent(); > - unsigned OldOpc = MI.getOpcode(); > - unsigned Opc = 0; > - switch (OldOpc) { > - case ARM::ADCSSrr: > - Opc = ARM::ADCrr; > - break; > - case ARM::ADCSSri: > - Opc = ARM::ADCri; > - break; > - case ARM::ADCSSrs: > - Opc = ARM::ADCrs; > - break; > - case ARM::SBCSSrr: > - Opc = ARM::SBCrr; > - break; > - case ARM::SBCSSri: > - Opc = ARM::SBCri; > - break; > - case ARM::SBCSSrs: > - Opc = ARM::SBCrs; > - break; > - default: > - llvm_unreachable("Unknown opcode?"); > - } > - > - MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc)); > - MIB.addOperand(MachineOperand::CreateImm(0)); // Predicate > - MIB.addOperand(MachineOperand::CreateImm(0)); // S bit > - for (unsigned i = 0; i < MI.getNumOperands(); ++i) > - MIB.addOperand(MI.getOperand(i)); > - TransferImpOps(MI, MIB, MIB); > - MI.eraseFromParent(); > -} > - > void ARMExpandPseudo::ExpandMOV32BitImm(MachineBasicBlock &MBB, > MachineBasicBlock::iterator &MBBI) { > MachineInstr &MI = *MBBI; > @@ -979,15 +941,6 @@ > ExpandMOV32BitImm(MBB, MBBI); > return true; > > - case ARM::ADCSSri: > - case ARM::ADCSSrr: > - case ARM::ADCSSrs: > - case ARM::SBCSSri: > - case ARM::SBCSSrr: > - case ARM::SBCSSrs: > - ExpandSBitOp(MBBI); > - return true; > - > case ARM::VMOVQQ: { > unsigned DstReg = MI.getOperand(0).getReg(); > bool DstIsDead = MI.getOperand(0).isDead(); > > Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=128940&r1=128939&r2=128940&view=diff > ============================================================================== > --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) > +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Tue Apr 5 16:48:57 2011 > @@ -2390,7 +2390,7 @@ > assert(VA.getValVT() != MVT::i64 && "i64 should already be lowered"); > > int index = ArgLocs[i].getValNo(); > - > + > // Some Ins[] entries become multiple ArgLoc[] entries. > // Process them only once. > if (index != lastInsIndex) > @@ -2966,7 +2966,7 @@ > AllOnes = DAG.getNode(ARMISD::VMOVIMM, dl, MVT::v8i8, AllOnes); > SDValue MaskNot = DAG.getNode(ISD::XOR, dl, OpVT, Mask, > DAG.getNode(ISD::BITCAST, dl, OpVT, AllOnes)); > - > + > SDValue Res = DAG.getNode(ISD::OR, dl, OpVT, > DAG.getNode(ISD::AND, dl, OpVT, Tmp1, Mask), > DAG.getNode(ISD::AND, dl, OpVT, Tmp0, MaskNot)); > @@ -4147,7 +4147,7 @@ > DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v8i8, > &VTBLMask[0], 8)); > > - return DAG.getNode(ARMISD::VTBL2, DL, MVT::v8i8, V1, V2, > + return DAG.getNode(ARMISD::VTBL2, DL, MVT::v8i8, V1, V2, > DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v8i8, > &VTBLMask[0], 8)); > } > @@ -4520,7 +4520,7 @@ > DAG.getNode(ISD::BITCAST, DL, Op1VT, N01), Op1)); > } > > -static SDValue > +static SDValue > LowerSDIV_v4i8(SDValue X, SDValue Y, DebugLoc dl, SelectionDAG &DAG) { > // Convert to float > // float4 xf = vcvt_f32_s32(vmovl_s16(a.lo)); > @@ -4531,7 +4531,7 @@ > Y = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, Y); > // Get reciprocal estimate. > // float4 recip = vrecpeq_f32(yf); > - Y = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > + Y = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), Y); > // Because char has a smaller range than uchar, we can actually get away > // without any newton steps. This requires that we use a weird bias > @@ -4549,7 +4549,7 @@ > return X; > } > > -static SDValue > +static SDValue > LowerSDIV_v4i16(SDValue N0, SDValue N1, DebugLoc dl, SelectionDAG &DAG) { > SDValue N2; > // Convert to float. > @@ -4559,13 +4559,13 @@ > N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v4i32, N1); > N0 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, N0); > N1 = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, N1); > - > + > // Use reciprocal estimate and one refinement step. > // float4 recip = vrecpeq_f32(yf); > // recip *= vrecpsq_f32(yf, recip); > - N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > + N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), N1); > - N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), > N1, N2); > N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); > @@ -4595,15 +4595,15 @@ > SDValue N0 = Op.getOperand(0); > SDValue N1 = Op.getOperand(1); > SDValue N2, N3; > - > + > if (VT == MVT::v8i8) { > N0 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v8i16, N0); > N1 = DAG.getNode(ISD::SIGN_EXTEND, dl, MVT::v8i16, N1); > - > + > N2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, > DAG.getIntPtrConstant(4)); > N3 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, > - DAG.getIntPtrConstant(4)); > + DAG.getIntPtrConstant(4)); > N0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, > DAG.getIntPtrConstant(0)); > N1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, > @@ -4614,7 +4614,7 @@ > > N0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v8i16, N0, N2); > N0 = LowerCONCAT_VECTORS(N0, DAG); > - > + > N0 = DAG.getNode(ISD::TRUNCATE, dl, MVT::v8i8, N0); > return N0; > } > @@ -4630,32 +4630,32 @@ > SDValue N0 = Op.getOperand(0); > SDValue N1 = Op.getOperand(1); > SDValue N2, N3; > - > + > if (VT == MVT::v8i8) { > N0 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v8i16, N0); > N1 = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::v8i16, N1); > - > + > N2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, > DAG.getIntPtrConstant(4)); > N3 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, > - DAG.getIntPtrConstant(4)); > + DAG.getIntPtrConstant(4)); > N0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N0, > DAG.getIntPtrConstant(0)); > N1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, MVT::v4i16, N1, > DAG.getIntPtrConstant(0)); > - > + > N0 = LowerSDIV_v4i16(N0, N1, dl, DAG); // v4i16 > N2 = LowerSDIV_v4i16(N2, N3, dl, DAG); // v4i16 > - > + > N0 = DAG.getNode(ISD::CONCAT_VECTORS, dl, MVT::v8i16, N0, N2); > N0 = LowerCONCAT_VECTORS(N0, DAG); > - > - N0 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v8i8, > + > + N0 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v8i8, > DAG.getConstant(Intrinsic::arm_neon_vqmovnsu, MVT::i32), > N0); > return N0; > } > - > + > // v4i16 sdiv ... Convert to float. > // float4 yf = vcvt_f32_s32(vmovl_u16(y)); > // float4 xf = vcvt_f32_s32(vmovl_u16(x)); > @@ -4668,13 +4668,13 @@ > // float4 recip = vrecpeq_f32(yf); > // recip *= vrecpsq_f32(yf, recip); > // recip *= vrecpsq_f32(yf, recip); > - N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > + N2 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > DAG.getConstant(Intrinsic::arm_neon_vrecpe, MVT::i32), N1); > - N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), > N1, N2); > N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); > - N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > + N1 = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, MVT::v4f32, > DAG.getConstant(Intrinsic::arm_neon_vrecps, MVT::i32), > N1, N2); > N2 = DAG.getNode(ISD::FMUL, dl, MVT::v4f32, N1, N2); > @@ -5024,6 +5024,48 @@ > case ARM::ATOMIC_CMP_SWAP_I16: return EmitAtomicCmpSwap(MI, BB, 2); > case ARM::ATOMIC_CMP_SWAP_I32: return EmitAtomicCmpSwap(MI, BB, 4); > > + case ARM::ADCSSri: > + case ARM::ADCSSrr: > + case ARM::ADCSSrs: > + case ARM::SBCSSri: > + case ARM::SBCSSrr: > + case ARM::SBCSSrs: { > + unsigned OldOpc = MI->getOpcode(); > + unsigned Opc = 0; > + switch (OldOpc) { > + case ARM::ADCSSrr: > + Opc = ARM::ADCrr; > + break; > + case ARM::ADCSSri: > + Opc = ARM::ADCri; > + break; > + case ARM::ADCSSrs: > + Opc = ARM::ADCrs; > + break; > + case ARM::SBCSSrr: > + Opc = ARM::SBCrr; > + break; > + case ARM::SBCSSri: > + Opc = ARM::SBCri; > + break; > + case ARM::SBCSSrs: > + Opc = ARM::SBCrs; > + break; > + default: > + llvm_unreachable("Unknown opcode?"); > + } > + > + MachineInstrBuilder MIB = > + BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(Opc)); > + for (unsigned i = 0; i < MI->getNumOperands(); ++i) > + MIB.addOperand(MI->getOperand(i)); > + AddDefaultPred(MIB); > + MIB.addReg(ARM::CPSR, RegState::Define); // S bit > + MI->eraseFromParent(); > + return BB; > + } > + > + > case ARM::tMOVCCr_pseudo: { > // To "insert" a SELECT_CC instruction, we actually have to insert the > // diamond control-flow pattern. The incoming instruction knows the > @@ -5326,7 +5368,7 @@ > > static SDValue PerformANDCombine(SDNode *N, > TargetLowering::DAGCombinerInfo &DCI) { > - > + > // Attempt to use immediate-form VBIC > BuildVectorSDNode *BVN = dyn_cast(N->getOperand(1)); > DebugLoc dl = N->getDebugLoc(); > @@ -5851,7 +5893,7 @@ > EVT VecTy; > if (isLoad) > VecTy = N->getValueType(0); > - else > + else > VecTy = N->getOperand(AddrOpIdx+1).getValueType(); > unsigned NumBytes = NumVecs * VecTy.getSizeInBits() / 8; > if (isLaneOp) > @@ -5901,7 +5943,7 @@ > DCI.CombineTo(User, SDValue(UpdN.getNode(), NumResultVecs)); > > break; > - } > + } > return SDValue(); > } > > > Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=128940&r1=128939&r2=128940&view=diff > ============================================================================== > --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) > +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Apr 5 16:48:57 2011 > @@ -936,8 +936,7 @@ > } > // Carry setting variants > let isCodeGenOnly = 1, Defs = [CPSR] in { > -multiclass AI1_adde_sube_s_irs opcod, string opc, PatFrag opnode, > - bit Commutable = 0> { > +multiclass AI1_adde_sube_s_irs { > def Sri : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), > Size4Bytes, IIC_iALUi, > [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>, > @@ -2197,10 +2196,12 @@ > BinOpFrag<(sube_dead_carry node:$LHS, node:$RHS)>>; > > // ADC and SUBC with 's' bit set. > -defm ADCS : AI1_adde_sube_s_irs<0b0101, "adcs", > - BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; > -defm SBCS : AI1_adde_sube_s_irs<0b0110, "sbcs", > - BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>; > +let usesCustomInserter = 1 in { > +defm ADCS : AI1_adde_sube_s_irs< > + BinOpFrag<(adde_live_carry node:$LHS, node:$RHS)>, 1>; > +defm SBCS : AI1_adde_sube_s_irs< > + BinOpFrag<(sube_live_carry node:$LHS, node:$RHS) >>; > +} > > def RSBri : AsI1<0b0011, (outs GPR:$Rd), (ins GPR:$Rn, so_imm:$imm), DPFrm, > IIC_iALUi, "rsb", "\t$Rd, $Rn, $imm", > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From gvenn.cfe.dev at gmail.com Mon Apr 11 14:52:49 2011 From: gvenn.cfe.dev at gmail.com (Garrison Venn) Date: Mon, 11 Apr 2011 19:52:49 -0000 Subject: [llvm-commits] [llvm] r129291 - /llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Message-ID: <20110411195249.42FEC2A6C12D@llvm.org> Author: gvenn Date: Mon Apr 11 14:52:49 2011 New Revision: 129291 URL: http://llvm.org/viewvc/llvm-project?rev=129291&view=rev Log: Because some systems have reported that this example would not build the header file cstdio was added as an include. Modified: llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Modified: llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp?rev=129291&r1=129290&r2=129291&view=diff ============================================================================== --- llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp (original) +++ llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Mon Apr 11 14:52:49 2011 @@ -62,6 +62,11 @@ #include "llvm/Support/IRBuilder.h" #include "llvm/Support/Dwarf.h" +// Note: Some systems seem to have a problem finding +// the symbols like stderr, and fprintf when this +// header file is not included +#include + #include #include From stoklund at 2pi.dk Mon Apr 11 15:01:42 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 20:01:42 -0000 Subject: [llvm-commits] [llvm] r129292 - /llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Message-ID: <20110411200142.239592A6C12D@llvm.org> Author: stoklund Date: Mon Apr 11 15:01:41 2011 New Revision: 129292 URL: http://llvm.org/viewvc/llvm-project?rev=129292&view=rev Log: Use a faster algorithm for computing MBB live-in registers after register allocation. LiveIntervals::findLiveInMBBs has to do a full binary search for each segment. Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocBasic.cpp?rev=129292&r1=129291&r2=129292&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocBasic.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Mon Apr 11 15:01:41 2011 @@ -405,29 +405,31 @@ // Add newly allocated physical registers to the MBB live in sets. void RegAllocBase::addMBBLiveIns(MachineFunction *MF) { NamedRegionTimer T("MBB Live Ins", TimerGroupName, TimePassesIsEnabled); - typedef SmallVector MBBVec; - MBBVec liveInMBBs; - MachineBasicBlock &entryMBB = *MF->begin(); + SlotIndexes *Indexes = LIS->getSlotIndexes(); + if (MF->size() <= 1) + return; + LiveIntervalUnion::SegmentIter SI; for (unsigned PhysReg = 0; PhysReg < PhysReg2LiveUnion.numRegs(); ++PhysReg) { LiveIntervalUnion &LiveUnion = PhysReg2LiveUnion[PhysReg]; if (LiveUnion.empty()) continue; - for (LiveIntervalUnion::SegmentIter SI = LiveUnion.begin(); SI.valid(); - ++SI) { - - // Find the set of basic blocks which this range is live into... - liveInMBBs.clear(); - if (!LIS->findLiveInMBBs(SI.start(), SI.stop(), liveInMBBs)) continue; - - // And add the physreg for this interval to their live-in sets. - for (MBBVec::iterator I = liveInMBBs.begin(), E = liveInMBBs.end(); - I != E; ++I) { - MachineBasicBlock *MBB = *I; - if (MBB == &entryMBB) continue; - if (MBB->isLiveIn(PhysReg)) continue; - MBB->addLiveIn(PhysReg); - } + MachineFunction::iterator MBB = llvm::next(MF->begin()); + MachineFunction::iterator MFE = MF->end(); + SlotIndex Start, Stop; + tie(Start, Stop) = Indexes->getMBBRange(MBB); + SI.setMap(LiveUnion.getMap()); + SI.find(Start); + while (SI.valid()) { + if (SI.start() <= Start) { + if (!MBB->isLiveIn(PhysReg)) + MBB->addLiveIn(PhysReg); + } else if (SI.start() > Stop) + MBB = Indexes->getMBBFromIndex(SI.start()); + if (++MBB == MFE) + break; + tie(Start, Stop) = Indexes->getMBBRange(MBB); + SI.advanceTo(Start); } } } From stoklund at 2pi.dk Mon Apr 11 15:01:44 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 20:01:44 -0000 Subject: [llvm-commits] [llvm] r129293 - /llvm/trunk/include/llvm/CodeGen/SlotIndexes.h Message-ID: <20110411200144.A9B2C2A6C12E@llvm.org> Author: stoklund Date: Mon Apr 11 15:01:44 2011 New Revision: 129293 URL: http://llvm.org/viewvc/llvm-project?rev=129293&view=rev Log: Skip a binary search when possible. Modified: llvm/trunk/include/llvm/CodeGen/SlotIndexes.h Modified: llvm/trunk/include/llvm/CodeGen/SlotIndexes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SlotIndexes.h?rev=129293&r1=129292&r2=129293&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SlotIndexes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SlotIndexes.h Mon Apr 11 15:01:44 2011 @@ -545,6 +545,8 @@ /// Returns the basic block which the given index falls in. MachineBasicBlock* getMBBFromIndex(SlotIndex index) const { + if (MachineInstr *MI = getInstructionFromIndex(index)) + return MI->getParent(); SmallVectorImpl::const_iterator I = std::lower_bound(idx2MBBMap.begin(), idx2MBBMap.end(), index); // Take the pair containing the index From resistor at mac.com Mon Apr 11 15:12:19 2011 From: resistor at mac.com (Owen Anderson) Date: Mon, 11 Apr 2011 20:12:19 -0000 Subject: [llvm-commits] [llvm] r129294 - /llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Message-ID: <20110411201219.F08362A6C12D@llvm.org> Author: resistor Date: Mon Apr 11 15:12:19 2011 New Revision: 129294 URL: http://llvm.org/viewvc/llvm-project?rev=129294&view=rev Log: Fix another using-CPSR-twice bug in my ADCS/SBCS cleanups, and make proper use of the Commutable bit. Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=129294&r1=129293&r2=129294&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Apr 11 15:12:19 2011 @@ -934,6 +934,8 @@ let Inst{19-16} = Rn; } } +} + // Carry setting variants // NOTE: CPSR def omitted because it will be handled by the custom inserter. let usesCustomInserter = 1 in { @@ -943,13 +945,14 @@ [(set GPR:$Rd, (opnode GPR:$Rn, so_imm:$imm))]>; def Srr : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), Size4Bytes, IIC_iALUr, - [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]>; + [(set GPR:$Rd, (opnode GPR:$Rn, GPR:$Rm))]> { + let isCommutable = Commutable; + } def Srs : ARMPseudoInst<(outs GPR:$Rd), (ins GPR:$Rn, so_reg:$shift), Size4Bytes, IIC_iALUsr, [(set GPR:$Rd, (opnode GPR:$Rn, so_reg:$shift))]>; } } -} let canFoldAsLoad = 1, isReMaterializable = 1 in { multiclass AI_ldr1 Author: efriedma Date: Mon Apr 11 15:16:05 2011 New Revision: 129295 URL: http://llvm.org/viewvc/llvm-project?rev=129295&view=rev Log: Get rid of useless comment; if a file uses functions from a given header, it is obvious that it should be included. Modified: llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Modified: llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp?rev=129295&r1=129294&r2=129295&view=diff ============================================================================== --- llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp (original) +++ llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Mon Apr 11 15:16:05 2011 @@ -62,11 +62,7 @@ #include "llvm/Support/IRBuilder.h" #include "llvm/Support/Dwarf.h" -// Note: Some systems seem to have a problem finding -// the symbols like stderr, and fprintf when this -// header file is not included #include - #include #include From rafael.espindola at gmail.com Mon Apr 11 15:29:16 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Mon, 11 Apr 2011 20:29:16 -0000 Subject: [llvm-commits] [llvm] r129296 - /llvm/trunk/lib/MC/MCParser/AsmParser.cpp Message-ID: <20110411202916.5191D2A6C12D@llvm.org> Author: rafael Date: Mon Apr 11 15:29:16 2011 New Revision: 129296 URL: http://llvm.org/viewvc/llvm-project?rev=129296&view=rev Log: implement .cfi_adjust_cfa_offset. Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=129296&r1=129295&r2=129296&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Mon Apr 11 15:29:16 2011 @@ -80,6 +80,7 @@ SourceMgr &SrcMgr; MCAsmParserExtension *GenericParser; MCAsmParserExtension *PlatformParser; + int64_t LastOffset; /// This is the current buffer index we're lexing from as managed by the /// SourceMgr object. @@ -140,6 +141,14 @@ /// } + int64_t adjustLastOffset(int64_t Adjustment) { + LastOffset += Adjustment; + return LastOffset; + } + void setLastOffset(int64_t Offset) { + LastOffset = Offset; + } + private: void CheckForValidSection(); @@ -251,6 +260,8 @@ ".cfi_def_cfa"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaOffset>( ".cfi_def_cfa_offset"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset>( + ".cfi_adjust_cfa_offset"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIDefCfaRegister>( ".cfi_def_cfa_register"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIOffset>( @@ -287,6 +298,7 @@ bool ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfa(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaOffset(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIAdjustCfaOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); @@ -315,7 +327,7 @@ AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), - GenericParser(new GenericAsmParser), PlatformParser(0), + GenericParser(new GenericAsmParser), PlatformParser(0), LastOffset(0), CurBuffer(0), MacrosEnabled(true) { Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); @@ -2309,6 +2321,21 @@ if (getParser().ParseAbsoluteExpression(Offset)) return true; + getParser().setLastOffset(Offset); + + return getStreamer().EmitCFIDefCfaOffset(Offset); +} + +/// ParseDirectiveCFIAdjustCfaOffset +/// ::= .cfi_adjust_cfa_offset adjustment +bool GenericAsmParser::ParseDirectiveCFIAdjustCfaOffset(StringRef, + SMLoc DirectiveLoc) { + int64_t Adjustment = 0; + if (getParser().ParseAbsoluteExpression(Adjustment)) + return true; + + int64_t Offset = getParser().adjustLastOffset(Adjustment); + return getStreamer().EmitCFIDefCfaOffset(Offset); } From jgu222 at gmail.com Mon Apr 11 15:44:14 2011 From: jgu222 at gmail.com (Junjie Gu) Date: Mon, 11 Apr 2011 13:44:14 -0700 Subject: [llvm-commits] Minor change to LoopUnroll's ctor In-Reply-To: References: Message-ID: Hello, Is this change okay ? Thanks Junjie On Mon, Apr 4, 2011 at 1:47 PM, Junjie Gu wrote: > I'd like to change the loop unroll so that the > threshold/count/allowpartial can be passed as parameters to > LoopUnroll's ctor. The reason for doing so is that static options > (-unroll-threshold, -unroll-count, -unroll-allow-partial) are not good > for an environment (OpenCL) in which multiple llvm context may be > present at the same time. And each llvm context may have its own > optimization options, and thus options cannot be shared. > > With this patch, a user can create a loop unroll by the following: > > ? ? ? ? ?createLoopUnrollPass(Threshold, Count, AllowPartial); > > And the previous API > ? ? ? ? ?createLoopUnrollPass() > will work as before. > > Please review it. I do have commit access so I can check in by myself > after reviewing. > > Thanks > Junjie > From wendling at apple.com Mon Apr 11 15:50:36 2011 From: wendling at apple.com (Bill Wendling) Date: Mon, 11 Apr 2011 13:50:36 -0700 Subject: [llvm-commits] [llvm] r129235 - in /llvm/trunk: include/llvm/BasicBlock.h include/llvm/Bitcode/LLVMBitCodes.h lib/AsmParser/LLLexer.cpp lib/AsmParser/LLParser.cpp lib/AsmParser/LLToken.h lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/BitcodeWriter.cpp lib/VMCore/AsmWriter.cpp lib/VMCore/BasicBlock.cpp test/Feature/bb_attrs.ll In-Reply-To: <4DA322B3.5040605@free.fr> References: <20110410000427.D81CC2A6C12E@llvm.org> <3E68CF50-8E76-4868-9CA8-E492A1F29841@apple.com> <4DA15D33.6090406@free.fr> <4DA322B3.5040605@free.fr> Message-ID: <514A9C8F-BDA5-4769-8981-D2555E94B6AC@apple.com> On Apr 11, 2011, at 8:48 AM, Duncan Sands wrote: > I disagree with the way you describe the issue in (2), though maybe I'm just > nit picking. There is an issue, but I would say that the issue is in getting > the right exception value / selector value at the point where decisions about > branching to catch clauses is made, and not one of knowing "all of the > information about the call". As you explain, at the moment when an exception > results in control branching to a landing pad there is a value for the > exception and selector (passed in registers), but the point where you make > decisions about which catch to execute etc can be far away, with all kinds of > other exceptions being thrown and caught before you get there. This means that > you are obliged to stash the exception/selector values away somewhere so that > you can get hold of them again later. I didn't discuss this point much in my > proposal since it can be solved using intrinsics (ie with no IR changes). I > agree that the intrinsics approach is rather ugly and something of a hack, but > since it would solve the problem I find it hard to get excited about it: point > (1) seems much more serious to me. > > In short, I would say that my proposal has all the minor problems of the current > implementation, but not the major problem :) > > I think the best way to proceed is not to discuss solutions/proposals etc for > the moment, but instead to clearly define what is wrong with the current eh > scheme. In the next day or so I plan to post an email describing and > analysing all the problems with the current scheme (this may take me a while > since there are a lot of them!). > Hi Duncan, Fair enough, I'll write up what I think are the problems with the current implementation. To be honest, This topic has been debated a lot in the past few years. There may not be a whole lot of information left to squeeze from the proverbial turnip. :-) I'm highly motivated to fix/rewrite exception handling because of the number of problems (reported both internally and externally) that crop up due to our current implementation. -bw From evan.cheng at apple.com Mon Apr 11 16:09:19 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Mon, 11 Apr 2011 21:09:19 -0000 Subject: [llvm-commits] [llvm] r129297 - in /llvm/trunk: lib/CodeGen/MachineLICM.cpp test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll Message-ID: <20110411210919.2D7CC2A6C12D@llvm.org> Author: evancheng Date: Mon Apr 11 16:09:18 2011 New Revision: 129297 URL: http://llvm.org/viewvc/llvm-project?rev=129297&view=rev Log: Look pass copies when determining whether hoisting would end up inserting more copies. rdar://9266679 Added: llvm/trunk/test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll Modified: llvm/trunk/lib/CodeGen/MachineLICM.cpp Modified: llvm/trunk/lib/CodeGen/MachineLICM.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineLICM.cpp?rev=129297&r1=129296&r2=129297&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineLICM.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineLICM.cpp Mon Apr 11 16:09:18 2011 @@ -39,7 +39,6 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" - using namespace llvm; STATISTIC(NumHoisted, @@ -169,6 +168,10 @@ /// bool IsLoopInvariantInst(MachineInstr &I); + /// HasAnyPHIUse - Return true if the specified register is used by any + /// phi node. + bool HasAnyPHIUse(unsigned Reg) const; + /// HasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. @@ -758,18 +761,25 @@ } -/// HasPHIUses - Return true if the specified register has any PHI use. -static bool HasPHIUses(unsigned Reg, MachineRegisterInfo *MRI) { +/// HasAnyPHIUse - Return true if the specified register is used by any +/// phi node. +bool MachineLICM::HasAnyPHIUse(unsigned Reg) const { for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(Reg), UE = MRI->use_end(); UI != UE; ++UI) { MachineInstr *UseMI = &*UI; if (UseMI->isPHI()) return true; + // Look pass copies as well. + if (UseMI->isCopy()) { + unsigned Def = UseMI->getOperand(0).getReg(); + if (TargetRegisterInfo::isVirtualRegister(Def) && + HasAnyPHIUse(Def)) + return true; + } } return false; } - /// HasHighOperandLatency - Compute operand latency between a def of 'Reg' /// and an use in the current loop, return true if the target considered /// it 'high'. @@ -976,14 +986,13 @@ return false; } - // If result(s) of this instruction is used by PHIs, then don't hoist it. - // The presence of joins makes it difficult for current register allocator - // implementation to perform remat. + // If result(s) of this instruction is used by PHIs outside of the loop, then + // don't hoist it if the instruction because it will introduce an extra copy. for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI.getOperand(i); if (!MO.isReg() || !MO.isDef()) continue; - if (HasPHIUses(MO.getReg(), MRI)) + if (HasAnyPHIUse(MO.getReg())) return false; } Added: llvm/trunk/test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll?rev=129297&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll (added) +++ llvm/trunk/test/CodeGen/ARM/2011-04-11-MachineLICMBug.ll Mon Apr 11 16:09:18 2011 @@ -0,0 +1,34 @@ +; RUN: llc < %s -mtriple=thumbv7-apple-darwin -mcpu=cortex-a8 | FileCheck %s + +; Overly aggressive LICM simply adds copies of constants +; rdar://9266679 + +define zeroext i1 @t(i32* nocapture %A, i32 %size, i32 %value) nounwind readonly ssp { +; CHECK: t: +entry: + br label %for.cond + +for.cond: + %0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] + %cmp = icmp ult i32 %0, %size + br i1 %cmp, label %for.body, label %return + +for.body: +; CHECK: %for.body +; CHECK: movs r{{[0-9]+}}, #1 + %arrayidx = getelementptr i32* %A, i32 %0 + %tmp4 = load i32* %arrayidx, align 4 + %cmp6 = icmp eq i32 %tmp4, %value + br i1 %cmp6, label %return, label %for.inc + +; CHECK: %for.cond +; CHECK: movs r{{[0-9]+}}, #0 + +for.inc: + %inc = add i32 %0, 1 + br label %for.cond + +return: + %retval.0 = phi i1 [ true, %for.body ], [ false, %for.cond ] + ret i1 %retval.0 +} From johnny.chen at apple.com Mon Apr 11 16:14:35 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Apr 2011 21:14:35 -0000 Subject: [llvm-commits] [llvm] r129298 - in /llvm/trunk: lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110411211435.543EE2A6C12D@llvm.org> Author: johnny Date: Mon Apr 11 16:14:35 2011 New Revision: 129298 URL: http://llvm.org/viewvc/llvm-project?rev=129298&view=rev Log: Fix the bug where the immediate shift amount for Thumb logical shift instructions are incorrectly disassembled. rdar://problem/9266265 Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129298&r1=129297&r2=129298&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Mon Apr 11 16:14:35 2011 @@ -398,9 +398,17 @@ assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef() && "Pure imm operand expected"); - MI.addOperand(MCOperand::CreateImm(UseRt ? getT1Imm8(insn) - : (Imm3 ? getT1Imm3(insn) - : getT1Imm5(insn)))); + unsigned Imm = 0; + if (UseRt) + Imm = getT1Imm8(insn); + else if (Imm3) + Imm = getT1Imm3(insn); + else { + Imm = getT1Imm5(insn); + ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 12, 11)); + getImmShiftSE(ShOp, Imm); + } + MI.addOperand(MCOperand::CreateImm(Imm)); } ++OpIdx; @@ -1385,9 +1393,12 @@ if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - if (Thumb2ShiftOpcode(Opcode)) - MI.addOperand(MCOperand::CreateImm(getShiftAmtBits(insn))); - else { + if (Thumb2ShiftOpcode(Opcode)) { + unsigned Imm = getShiftAmtBits(insn); + ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 5, 4)); + getImmShiftSE(ShOp, Imm); + MI.addOperand(MCOperand::CreateImm(Imm)); + } else { // Build the constant shift specifier operand. unsigned bits2 = getShiftTypeBits(insn); unsigned imm5 = getShiftAmtBits(insn); Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129298&r1=129297&r2=129298&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Mon Apr 11 16:14:35 2011 @@ -208,3 +208,9 @@ # CHECK: isb 0xbf 0xf3 0x6f 0x8f + +# CHECK: asrs r1, r0, #32 +0x1 0x10 + +# CHECK: lsr.w r10, r0, #32 +0x4f 0xea 0x10 0x0a From johnny.chen at apple.com Mon Apr 11 16:27:13 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Apr 2011 14:27:13 -0700 Subject: [llvm-commits] Source register same as write-back base In-Reply-To: <88D727341410A44C9E34E8E3EF37D8ED04213C3E@be25.exg3.exghost.com> References: <88D727341410A44C9E34E8E3EF37D8ED04213C3E@be25.exg3.exghost.com> Message-ID: <12BD8D01-BDE4-4E21-8608-A24EFF90A48C@apple.com> Hi Joe, I've CCed llvm-commit. Hopefully the backend folks can help you out! Thanks. On Apr 11, 2011, at 2:20 PM, Joe Abbey wrote: > Johnny, > > I saw your changelist which adds a check to the disassembly of ARM instructions. > > I?m currently trying to debug how the register allocation works to produce: > > str r3, [r3], #4 > > My assembler is complaining that: > > libtest-libstl.so.bc:46025: Warning: source register same as write-back base > > And it should because as you (and ARM) note, this is UNPREDICTABLE. > > Any thoughts on who to ask or where to start digging in LLVM to debug? > > Thanks! > > Joe Abbey > Software Architect > Arxan Technologies, Inc. > 1305 Cumberland Ave, Ste 215 > West Lafayette, IN 47906 > W: 765-889-4756 x2 > C: 765-464-9893 > jabbey at arxan.com > www.arxan.com > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110411/9ed3fdc0/attachment.html From isanbard at gmail.com Mon Apr 11 16:32:34 2011 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 11 Apr 2011 21:32:34 -0000 Subject: [llvm-commits] [llvm] r129302 - /llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp Message-ID: <20110411213234.6400A2A6C12D@llvm.org> Author: void Date: Mon Apr 11 16:32:34 2011 New Revision: 129302 URL: http://llvm.org/viewvc/llvm-project?rev=129302&view=rev Log: The default of the dispatch switch statement was to branch to a BB that executed the 'unwind' instruction. However, later on that instruction was converted into a jump to the basic block it was located in, causing an infinite loop when we get there. It turns out, we get there if the _Unwind_Resume_or_Rethrow call returns (which it's not supposed to do). It returns if it cannot find a place to unwind to. Thus we would get what appears to be a "hang" when in reality it's just that the EH couldn't be propagated further along. Instead of infinitely looping (or calling `unwind', which none of our back-ends support (it's lowered into nothing...)), call the @llvm.trap() intrinsic instead. This may not conform to specific rules of a particular language, but it's rather better than infinitely looping. Modified: llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp Modified: llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp?rev=129302&r1=129301&r2=129302&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp (original) +++ llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp Mon Apr 11 16:32:34 2011 @@ -443,16 +443,17 @@ BasicBlock::Create(F.getContext(), "eh.sjlj.setjmp.catch", &F); // Insert a load of the callsite in the dispatch block, and a switch on its - // value. By default, we go to a block that just does an unwind (which is the - // correct action for a standard call). - BasicBlock *UnwindBlock = - BasicBlock::Create(F.getContext(), "unwindbb", &F); - Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBlock)); + // value. By default, we issue a trap statement. + BasicBlock *TrapBlock = + BasicBlock::Create(F.getContext(), "trapbb", &F); + CallInst::Create(Intrinsic::getDeclaration(F.getParent(), Intrinsic::trap), + "", TrapBlock); + new UnreachableInst(F.getContext(), TrapBlock); Value *DispatchLoad = new LoadInst(CallSite, "invoke.num", true, DispatchBlock); SwitchInst *DispatchSwitch = - SwitchInst::Create(DispatchLoad, UnwindBlock, Invokes.size(), + SwitchInst::Create(DispatchLoad, TrapBlock, Invokes.size(), DispatchBlock); // Split the entry block to insert the conditional branch for the setjmp. BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(), @@ -561,7 +562,7 @@ // Replace all unwinds with a branch to the unwind handler. // ??? Should this ever happen with sjlj exceptions? for (unsigned i = 0, e = Unwinds.size(); i != e; ++i) { - BranchInst::Create(UnwindBlock, Unwinds[i]); + BranchInst::Create(TrapBlock, Unwinds[i]); Unwinds[i]->eraseFromParent(); } From peckw at wesleypeck.com Mon Apr 11 16:35:21 2011 From: peckw at wesleypeck.com (Wesley Peck) Date: Mon, 11 Apr 2011 21:35:21 -0000 Subject: [llvm-commits] [llvm] r129303 - in /llvm/trunk/lib/Target/MBlaze: Disassembler/MBlazeDisassembler.cpp MBlazeRegisterInfo.cpp MBlazeRegisterInfo.h Message-ID: <20110411213521.433F82A6C12D@llvm.org> Author: peckw Date: Mon Apr 11 16:35:21 2011 New Revision: 129303 URL: http://llvm.org/viewvc/llvm-project?rev=129303&view=rev Log: Don't crash on invalid instructions when disassembling MBlaze code. This fixes http://llvm.org/bugs/show_bug.cgi?id=9653 Modified: llvm/trunk/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.cpp llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.h Modified: llvm/trunk/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp?rev=129303&r1=129302&r2=129303&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp (original) +++ llvm/trunk/lib/Target/MBlaze/Disassembler/MBlazeDisassembler.cpp Mon Apr 11 16:35:21 2011 @@ -57,18 +57,26 @@ }; static unsigned getRD(uint32_t insn) { + if (!MBlazeRegisterInfo::isRegister((insn>>21)&0x1F)) + return UNSUPPORTED; return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>21)&0x1F); } static unsigned getRA(uint32_t insn) { + if (!MBlazeRegisterInfo::getRegisterFromNumbering((insn>>16)&0x1F)) + return UNSUPPORTED; return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>16)&0x1F); } static unsigned getRB(uint32_t insn) { + if (!MBlazeRegisterInfo::getRegisterFromNumbering((insn>>11)&0x1F)) + return UNSUPPORTED; return MBlazeRegisterInfo::getRegisterFromNumbering((insn>>11)&0x1F); } static int64_t getRS(uint32_t insn) { + if (!MBlazeRegisterInfo::isSpecialRegister(insn&0x3FFF)) + return UNSUPPORTED; return MBlazeRegisterInfo::getSpecialRegisterFromNumbering(insn&0x3FFF); } @@ -489,13 +497,14 @@ raw_ostream &vStream) const { // The machine instruction. uint32_t insn; + uint64_t read; uint8_t bytes[4]; - // We always consume 4 bytes of data - size = 4; + // By default we consume 1 byte on failure + size = 1; // We want to read exactly 4 bytes of data. - if (region.readBytes(address, 4, (uint8_t*)bytes, NULL) == -1) + if (region.readBytes(address, 4, (uint8_t*)bytes, &read) == -1 || read < 4) return false; // Encoded as a big-endian 32-bit word in the stream. @@ -509,44 +518,63 @@ instr.setOpcode(opcode); + unsigned RD = getRD(insn); + unsigned RA = getRA(insn); + unsigned RB = getRB(insn); + unsigned RS = getRS(insn); + uint64_t tsFlags = MBlazeInsts[opcode].TSFlags; switch ((tsFlags & MBlazeII::FormMask)) { - default: llvm_unreachable("unknown instruction encoding"); + default: + return false; case MBlazeII::FRRRR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRB(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RB)); + instr.addOperand(MCOperand::CreateReg(RA)); break; case MBlazeII::FRRR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED || RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RA)); + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FRI: switch (opcode) { - default: llvm_unreachable("unknown instruction encoding"); + default: + return false; case MBlaze::MFS: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(insn&0x3FFF)); break; case MBlaze::MTS: + if (RA == UNSUPPORTED) + return false; instr.addOperand(MCOperand::CreateImm(insn&0x3FFF)); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateReg(RA)); break; case MBlaze::MSRSET: case MBlaze::MSRCLR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(insn&0x7FFF)); break; } break; case MBlazeII::FRRI: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RA)); switch (opcode) { default: instr.addOperand(MCOperand::CreateImm(getIMM(insn))); @@ -560,27 +588,37 @@ break; case MBlazeII::FCRR: - instr.addOperand(MCOperand::CreateReg(getRA(insn))); - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RA == UNSUPPORTED || RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RA)); + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FCRI: - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RA)); instr.addOperand(MCOperand::CreateImm(getIMM(insn))); break; case MBlazeII::FRCR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RD == UNSUPPORTED || RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FRCI: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(getIMM(insn))); break; case MBlazeII::FCCR: - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FCCI: @@ -588,33 +626,45 @@ break; case MBlazeII::FRRCI: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RA)); instr.addOperand(MCOperand::CreateImm(getSHT(insn))); break; case MBlazeII::FRRC: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RA)); break; case MBlazeII::FRCX: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(getFSL(insn))); break; case MBlazeII::FRCS: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); - instr.addOperand(MCOperand::CreateReg(getRS(insn))); + if (RD == UNSUPPORTED || RS == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); + instr.addOperand(MCOperand::CreateReg(RS)); break; case MBlazeII::FCRCS: - instr.addOperand(MCOperand::CreateReg(getRS(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RS == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RS)); + instr.addOperand(MCOperand::CreateReg(RA)); break; case MBlazeII::FCRCX: - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + if (RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RA)); instr.addOperand(MCOperand::CreateImm(getFSL(insn))); break; @@ -623,16 +673,23 @@ break; case MBlazeII::FCR: - instr.addOperand(MCOperand::CreateReg(getRB(insn))); + if (RB == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RB)); break; case MBlazeII::FRIR: - instr.addOperand(MCOperand::CreateReg(getRD(insn))); + if (RD == UNSUPPORTED || RA == UNSUPPORTED) + return false; + instr.addOperand(MCOperand::CreateReg(RD)); instr.addOperand(MCOperand::CreateImm(getIMM(insn))); - instr.addOperand(MCOperand::CreateReg(getRA(insn))); + instr.addOperand(MCOperand::CreateReg(RA)); break; } + // We always consume 4 bytes of data on success + size = 4; + return true; } Modified: llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.cpp?rev=129303&r1=129302&r2=129303&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.cpp (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.cpp Mon Apr 11 16:35:21 2011 @@ -181,6 +181,26 @@ return 0; // Not reached } +bool MBlazeRegisterInfo::isRegister(unsigned Reg) { + return Reg <= 31; +} + +bool MBlazeRegisterInfo::isSpecialRegister(unsigned Reg) { + switch (Reg) { + case 0x0000 : case 0x0001 : case 0x0003 : case 0x0005 : + case 0x0007 : case 0x000B : case 0x000D : case 0x1000 : + case 0x1001 : case 0x1002 : case 0x1003 : case 0x1004 : + case 0x2000 : case 0x2001 : case 0x2002 : case 0x2003 : + case 0x2004 : case 0x2005 : case 0x2006 : case 0x2007 : + case 0x2008 : case 0x2009 : case 0x200A : case 0x200B : + return true; + + default: + return false; + } + return false; // Not reached +} + unsigned MBlazeRegisterInfo::getPICCallReg() { return MBlaze::R20; } Modified: llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.h?rev=129303&r1=129302&r2=129303&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.h (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.h Mon Apr 11 16:35:21 2011 @@ -45,6 +45,8 @@ static unsigned getRegisterNumbering(unsigned RegEnum); static unsigned getRegisterFromNumbering(unsigned RegEnum); static unsigned getSpecialRegisterFromNumbering(unsigned RegEnum); + static bool isRegister(unsigned RegEnum); + static bool isSpecialRegister(unsigned RegEnum); /// Get PIC indirect call register static unsigned getPICCallReg(); From rafael.espindola at gmail.com Mon Apr 11 16:41:34 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Mon, 11 Apr 2011 21:41:34 -0000 Subject: [llvm-commits] [llvm] r129304 - /llvm/trunk/test/MC/ELF/cfi-adjust-cfa-offset.s Message-ID: <20110411214134.2AD012A6C12D@llvm.org> Author: rafael Date: Mon Apr 11 16:41:34 2011 New Revision: 129304 URL: http://llvm.org/viewvc/llvm-project?rev=129304&view=rev Log: Add test for previous commit. Added: llvm/trunk/test/MC/ELF/cfi-adjust-cfa-offset.s Added: llvm/trunk/test/MC/ELF/cfi-adjust-cfa-offset.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/cfi-adjust-cfa-offset.s?rev=129304&view=auto ============================================================================== --- llvm/trunk/test/MC/ELF/cfi-adjust-cfa-offset.s (added) +++ llvm/trunk/test/MC/ELF/cfi-adjust-cfa-offset.s Mon Apr 11 16:41:34 2011 @@ -0,0 +1,46 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +f: + .cfi_startproc + subq $8, %rsp + .cfi_def_cfa_offset 16 + nop + .cfi_adjust_cfa_offset 4 + addq $8, %rsp + .cfi_def_cfa_offset 8 + ret + .cfi_endproc + +// CHECK: # Section 0x00000004 +// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000001) +// CHECK-NEXT: ('sh_flags', 0x00000002) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000050) +// CHECK-NEXT: ('sh_size', 0x00000038) +// CHECK-NEXT: ('sh_link', 0x00000000) +// CHECK-NEXT: ('sh_info', 0x00000000) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000000) +// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 1c000000 1c000000 00000000 0a000000 00440e10 410e1444 0e080000 00000000') +// CHECK-NEXT: ), +// CHECK-NEXT: # Section 0x00000005 +// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000004) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x000003a0) +// CHECK-NEXT: ('sh_size', 0x00000018) +// CHECK-NEXT: ('sh_link', 0x00000007) +// CHECK-NEXT: ('sh_info', 0x00000004) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000018) +// CHECK-NEXT: ('_relocations', [ +// CHECK-NEXT: # Relocation 0x00000000 +// CHECK-NEXT: (('r_offset', 0x00000020) +// CHECK-NEXT: ('r_sym', 0x00000002) +// CHECK-NEXT: ('r_type', 0x00000002) +// CHECK-NEXT: ('r_addend', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) +// CHECK-NEXT: ), From stoklund at 2pi.dk Mon Apr 11 16:47:01 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 21:47:01 -0000 Subject: [llvm-commits] [llvm] r129305 - in /llvm/trunk/lib/CodeGen: LiveIntervalUnion.cpp LiveIntervalUnion.h RegAllocGreedy.cpp Message-ID: <20110411214701.5CE512A6C12D@llvm.org> Author: stoklund Date: Mon Apr 11 16:47:01 2011 New Revision: 129305 URL: http://llvm.org/viewvc/llvm-project?rev=129305&view=rev Log: Speed up eviction by stopping collectInterferingVRegs as soon as the spill weight limit has been exceeded. Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp llvm/trunk/lib/CodeGen/LiveIntervalUnion.h llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp?rev=129305&r1=129304&r2=129305&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalUnion.cpp Mon Apr 11 16:47:01 2011 @@ -176,6 +176,7 @@ return FirstInterference; CheckedFirstInterference = true; InterferenceResult &IR = FirstInterference; + IR.LiveUnionI.setMap(LiveUnion->getMap()); // Quickly skip interference check for empty sets. if (VirtReg->empty() || LiveUnion->empty()) { @@ -184,10 +185,10 @@ // VirtReg starts first, perform double binary search. IR.VirtRegI = VirtReg->find(LiveUnion->startIndex()); if (IR.VirtRegI != VirtReg->end()) - IR.LiveUnionI = LiveUnion->find(IR.VirtRegI->start); + IR.LiveUnionI.find(IR.VirtRegI->start); } else { // LiveUnion starts first, perform double binary search. - IR.LiveUnionI = LiveUnion->find(VirtReg->beginIndex()); + IR.LiveUnionI.find(VirtReg->beginIndex()); if (IR.LiveUnionI.valid()) IR.VirtRegI = VirtReg->find(IR.LiveUnionI.start()); else @@ -243,7 +244,7 @@ // // For comments on how to speed it up, see Query::findIntersection(). unsigned LiveIntervalUnion::Query:: -collectInterferingVRegs(unsigned MaxInterferingRegs) { +collectInterferingVRegs(unsigned MaxInterferingRegs, float MaxWeight) { InterferenceResult IR = firstInterference(); LiveInterval::iterator VirtRegEnd = VirtReg->end(); LiveInterval *RecentInterferingVReg = NULL; @@ -285,6 +286,11 @@ // Cache the most recent interfering vreg to bypass isSeenInterference. RecentInterferingVReg = IR.LiveUnionI.value(); ++IR.LiveUnionI; + + // Stop collecting when the max weight is exceeded. + if (RecentInterferingVReg->weight >= MaxWeight) + return InterferingVRegs.size(); + continue; } // VirtRegI may have advanced far beyond LiveUnionI, Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalUnion.h?rev=129305&r1=129304&r2=129305&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalUnion.h (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalUnion.h Mon Apr 11 16:47:01 2011 @@ -226,7 +226,8 @@ // Count the virtual registers in this union that interfere with this // query's live virtual register, up to maxInterferingRegs. - unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX); + unsigned collectInterferingVRegs(unsigned MaxInterferingRegs = UINT_MAX, + float MaxWeight = HUGE_VALF); // Was this virtual register visited during collectInterferingVRegs? bool isSeenInterference(LiveInterval *VReg) const; Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp?rev=129305&r1=129304&r2=129305&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Mon Apr 11 16:47:01 2011 @@ -336,22 +336,24 @@ //===----------------------------------------------------------------------===// /// canEvict - Return true if all interferences between VirtReg and PhysReg can -/// be evicted. Set maxWeight to the maximal spill weight of an interference. +/// be evicted. +/// Return false if any interference is heavier than MaxWeight. +/// On return, set MaxWeight to the maximal spill weight of an interference. bool RAGreedy::canEvictInterference(LiveInterval &VirtReg, unsigned PhysReg, float &MaxWeight) { float Weight = 0; for (const unsigned *AliasI = TRI->getOverlaps(PhysReg); *AliasI; ++AliasI) { LiveIntervalUnion::Query &Q = query(VirtReg, *AliasI); - // If there is 10 or more interferences, chances are one is smaller. - if (Q.collectInterferingVRegs(10) >= 10) + // If there is 10 or more interferences, chances are one is heavier. + if (Q.collectInterferingVRegs(10, MaxWeight) >= 10) return false; - // Check if any interfering live range is heavier than VirtReg. - for (unsigned i = 0, e = Q.interferingVRegs().size(); i != e; ++i) { - LiveInterval *Intf = Q.interferingVRegs()[i]; + // Check if any interfering live range is heavier than MaxWeight. + for (unsigned i = Q.interferingVRegs().size(); i; --i) { + LiveInterval *Intf = Q.interferingVRegs()[i - 1]; if (TargetRegisterInfo::isPhysicalRegister(Intf->reg)) return false; - if (Intf->weight >= VirtReg.weight) + if (Intf->weight >= MaxWeight) return false; Weight = std::max(Weight, Intf->weight); } @@ -370,17 +372,17 @@ NamedRegionTimer T("Evict", TimerGroupName, TimePassesIsEnabled); // Keep track of the lightest single interference seen so far. - float BestWeight = 0; + float BestWeight = VirtReg.weight; unsigned BestPhys = 0; Order.rewind(); while (unsigned PhysReg = Order.next()) { - float Weight = 0; + float Weight = BestWeight; if (!canEvictInterference(VirtReg, PhysReg, Weight)) continue; // This is an eviction candidate. - DEBUG(dbgs() << "max " << PrintReg(PhysReg, TRI) << " interference = " + DEBUG(dbgs() << PrintReg(PhysReg, TRI) << " interference = " << Weight << '\n'); if (BestPhys && Weight >= BestWeight) continue; From rafael.espindola at gmail.com Mon Apr 11 16:49:50 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Mon, 11 Apr 2011 21:49:50 -0000 Subject: [llvm-commits] [llvm] r129306 - in /llvm/trunk: lib/MC/MCParser/AsmParser.cpp test/MC/ELF/cfi-rel-offset.s Message-ID: <20110411214950.58DF32A6C12D@llvm.org> Author: rafael Date: Mon Apr 11 16:49:50 2011 New Revision: 129306 URL: http://llvm.org/viewvc/llvm-project?rev=129306&view=rev Log: Implement cfi_rel_offset Added: llvm/trunk/test/MC/ELF/cfi-rel-offset.s Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=129306&r1=129305&r2=129306&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Mon Apr 11 16:49:50 2011 @@ -80,6 +80,10 @@ SourceMgr &SrcMgr; MCAsmParserExtension *GenericParser; MCAsmParserExtension *PlatformParser; + + // FIXME: This is not the best place to store this. To handle a (for example) + // .cfi_rel_offset before a .cfi_def_cfa_offset we need to know the initial + // frame state. int64_t LastOffset; /// This is the current buffer index we're lexing from as managed by the @@ -145,6 +149,9 @@ LastOffset += Adjustment; return LastOffset; } + int64_t getLastOffset() { + return LastOffset; + } void setLastOffset(int64_t Offset) { LastOffset = Offset; } @@ -266,6 +273,8 @@ ".cfi_def_cfa_register"); AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIOffset>( ".cfi_offset"); + AddDirectiveHandler<&GenericAsmParser::ParseDirectiveCFIRelOffset>( + ".cfi_rel_offset"); AddDirectiveHandler< &GenericAsmParser::ParseDirectiveCFIPersonalityOrLsda>(".cfi_personality"); AddDirectiveHandler< @@ -301,6 +310,7 @@ bool ParseDirectiveCFIAdjustCfaOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIDefCfaRegister(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFIRelOffset(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc); @@ -2351,7 +2361,7 @@ } /// ParseDirectiveCFIOffset -/// ::= .cfi_off register, offset +/// ::= .cfi_offset register, offset bool GenericAsmParser::ParseDirectiveCFIOffset(StringRef, SMLoc DirectiveLoc) { int64_t Register = 0; int64_t Offset = 0; @@ -2369,6 +2379,28 @@ return getStreamer().EmitCFIOffset(Register, Offset); } +/// ParseDirectiveCFIRelOffset +/// ::= .cfi_rel_offset register, offset +bool GenericAsmParser::ParseDirectiveCFIRelOffset(StringRef, + SMLoc DirectiveLoc) { + int64_t Register = 0; + + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + if (getLexer().isNot(AsmToken::Comma)) + return TokError("unexpected token in directive"); + Lex(); + + int64_t Offset = 0; + if (getParser().ParseAbsoluteExpression(Offset)) + return true; + + Offset -= getParser().getLastOffset(); + + return getStreamer().EmitCFIOffset(Register, Offset); +} + static bool isValidEncoding(int64_t Encoding) { if (Encoding & ~0xff) return false; Added: llvm/trunk/test/MC/ELF/cfi-rel-offset.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/cfi-rel-offset.s?rev=129306&view=auto ============================================================================== --- llvm/trunk/test/MC/ELF/cfi-rel-offset.s (added) +++ llvm/trunk/test/MC/ELF/cfi-rel-offset.s Mon Apr 11 16:49:50 2011 @@ -0,0 +1,49 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +f: + .cfi_startproc + nop + .cfi_def_cfa_offset 8 + nop + .cfi_def_cfa_register 6 + nop + .cfi_rel_offset 6,16 + nop + .cfi_def_cfa_offset 16 + nop + .cfi_rel_offset 6,0 + .cfi_endproc + +// CHECK: # Section 0x00000004 +// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000001) +// CHECK-NEXT: ('sh_flags', 0x00000002) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000048) +// CHECK-NEXT: ('sh_size', 0x00000040) +// CHECK-NEXT: ('sh_link', 0x00000000) +// CHECK-NEXT: ('sh_info', 0x00000000) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000000) +// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 24000000 1c000000 00000000 05000000 00410e08 410d0641 11067f41 0e104186 02000000 00000000') +// CHECK-NEXT: ), +// CHECK-NEXT: # Section 0x00000005 +// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000004) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x000003a0) +// CHECK-NEXT: ('sh_size', 0x00000018) +// CHECK-NEXT: ('sh_link', 0x00000007) +// CHECK-NEXT: ('sh_info', 0x00000004) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000018) +// CHECK-NEXT: ('_relocations', [ +// CHECK-NEXT: # Relocation 0x00000000 +// CHECK-NEXT: (('r_offset', 0x00000020) +// CHECK-NEXT: ('r_sym', 0x00000002) +// CHECK-NEXT: ('r_type', 0x00000002) +// CHECK-NEXT: ('r_addend', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) +// CHECK-NEXT: ), From nicholas at mxc.ca Mon Apr 11 17:11:20 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Mon, 11 Apr 2011 22:11:20 -0000 Subject: [llvm-commits] [llvm] r129307 - in /llvm/trunk/lib: CodeGen/ELFWriter.cpp ExecutionEngine/ExecutionEngine.cpp Transforms/IPO/GlobalOpt.cpp Message-ID: <20110411221120.5481B2A6C12D@llvm.org> Author: nicholas Date: Mon Apr 11 17:11:20 2011 New Revision: 129307 URL: http://llvm.org/viewvc/llvm-project?rev=129307&view=rev Log: Just because a GlobalVariable's initializer is [N x { i32, void ()* }] doesn't mean that it has to be ConstantArray of ConstantStruct. We might have ConstantAggregateZero, at either level, so don't crash on that. Also, semi-deprecate the sentinal value. The linker isn't aware of sentinals so we end up with the two lists appended, each with their "sentinals" on them. Different parts of LLVM treated sentinals differently, so make them all just ignore the single entry and continue on with the rest of the list. Modified: llvm/trunk/lib/CodeGen/ELFWriter.cpp llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Modified: llvm/trunk/lib/CodeGen/ELFWriter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ELFWriter.cpp?rev=129307&r1=129306&r2=129307&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/ELFWriter.cpp (original) +++ llvm/trunk/lib/CodeGen/ELFWriter.cpp Mon Apr 11 17:11:20 2011 @@ -662,12 +662,16 @@ void ELFWriter::EmitXXStructorList(Constant *List, ELFSection &Xtor) { // Should be an array of '{ i32, void ()* }' structs. The first value is the // init priority, which we ignore. + if (List->isNullValue()) return; ConstantArray *InitList = cast(List); for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + if (InitList->getOperand(i)->isNullValue()) + continue; ConstantStruct *CS = cast(InitList->getOperand(i)); if (CS->getOperand(1)->isNullValue()) - return; // Found a null terminator, exit printing. + continue; + // Emit the function pointer. EmitGlobalConstant(CS->getOperand(1), Xtor); } Modified: llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp?rev=129307&r1=129306&r2=129307&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/ExecutionEngine.cpp Mon Apr 11 17:11:20 2011 @@ -313,13 +313,17 @@ // Should be an array of '{ i32, void ()* }' structs. The first value is // the init priority, which we ignore. + if (isa(GV->getInitializer())) + return; ConstantArray *InitList = cast(GV->getInitializer()); for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + if (isa(InitList->getOperand(i))) + continue; ConstantStruct *CS = cast(InitList->getOperand(i)); Constant *FP = CS->getOperand(1); if (FP->isNullValue()) - break; // Found a null terminator, exit. + continue; // Found a sentinal value, ignore. // Strip off constant expression casts. if (ConstantExpr *CE = dyn_cast(FP)) Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=129307&r1=129306&r2=129307&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Mon Apr 11 17:11:20 2011 @@ -1954,14 +1954,15 @@ // Verify that the initializer is simple enough for us to handle. We are // only allowed to optimize the initializer if it is unique. if (!GV->hasUniqueInitializer()) return 0; - - ConstantArray *CA = dyn_cast(GV->getInitializer()); - if (!CA) return 0; - for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) { - ConstantStruct *CS = dyn_cast(*i); - if (!CS) return 0; + if (isa(GV->getInitializer())) + return GV; + ConstantArray *CA = cast(GV->getInitializer()); + for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) { + if (isa(*i)) + continue; + ConstantStruct *CS = cast(*i); if (isa(CS->getOperand(1))) continue; @@ -1981,6 +1982,8 @@ /// ParseGlobalCtors - Given a llvm.global_ctors list that we can understand, /// return a list of the functions and null terminator as a vector. static std::vector ParseGlobalCtors(GlobalVariable *GV) { + if (GV->getInitializer()->isNullValue()) + return std::vector(); ConstantArray *CA = cast(GV->getInitializer()); std::vector Result; Result.reserve(CA->getNumOperands()); @@ -2011,7 +2014,7 @@ const PointerType *PFTy = PointerType::getUnqual(FTy); CSVals[1] = Constant::getNullValue(PFTy); CSVals[0] = ConstantInt::get(Type::getInt32Ty(GCL->getContext()), - 2147483647); + 0x7fffffff); } CAList.push_back(ConstantStruct::get(GCL->getContext(), CSVals, false)); } From echristo at apple.com Mon Apr 11 17:24:56 2011 From: echristo at apple.com (Eric Christopher) Date: Mon, 11 Apr 2011 22:24:56 -0000 Subject: [llvm-commits] [llvm] r129309 - /llvm/trunk/lib/MC/MCParser/AsmLexer.cpp Message-ID: <20110411222456.E1F922A6C12D@llvm.org> Author: echristo Date: Mon Apr 11 17:24:56 2011 New Revision: 129309 URL: http://llvm.org/viewvc/llvm-project?rev=129309&view=rev Log: Lex, and then fail on invalid constants. Testcase forthcoming. rdar://8490596 Modified: llvm/trunk/lib/MC/MCParser/AsmLexer.cpp Modified: llvm/trunk/lib/MC/MCParser/AsmLexer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmLexer.cpp?rev=129309&r1=129308&r2=129309&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmLexer.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmLexer.cpp Mon Apr 11 17:24:56 2011 @@ -251,7 +251,7 @@ } // Must be an octal number, it starts with 0. - while (*CurPtr >= '0' && *CurPtr <= '7') + while (*CurPtr >= '0' && *CurPtr <= '9') ++CurPtr; StringRef Result(TokStart, CurPtr - TokStart); From peckw at wesleypeck.com Mon Apr 11 17:31:52 2011 From: peckw at wesleypeck.com (Wesley Peck) Date: Mon, 11 Apr 2011 22:31:52 -0000 Subject: [llvm-commits] [llvm] r129311 - in /llvm/trunk: lib/Target/MBlaze/ test/CodeGen/MBlaze/ Message-ID: <20110411223153.08ECC2A6C12D@llvm.org> Author: peckw Date: Mon Apr 11 17:31:52 2011 New Revision: 129311 URL: http://llvm.org/viewvc/llvm-project?rev=129311&view=rev Log: Add scheduling information for the MBlaze backend. Added: llvm/trunk/lib/Target/MBlaze/MBlazeSchedule3.td llvm/trunk/lib/Target/MBlaze/MBlazeSchedule5.td Modified: llvm/trunk/lib/Target/MBlaze/MBlaze.td llvm/trunk/lib/Target/MBlaze/MBlazeInstrFPU.td llvm/trunk/lib/Target/MBlaze/MBlazeInstrFSL.td llvm/trunk/lib/Target/MBlaze/MBlazeInstrFormats.td llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.cpp llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.h llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.td llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.td llvm/trunk/lib/Target/MBlaze/MBlazeSchedule.td llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.cpp llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.h llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.cpp llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.h llvm/trunk/lib/Target/MBlaze/TODO llvm/trunk/test/CodeGen/MBlaze/fsl.ll llvm/trunk/test/CodeGen/MBlaze/loop.ll Modified: llvm/trunk/lib/Target/MBlaze/MBlaze.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlaze.td?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlaze.td (original) +++ llvm/trunk/lib/Target/MBlaze/MBlaze.td Mon Apr 11 17:31:52 2011 @@ -31,49 +31,28 @@ // Microblaze Subtarget features // //===----------------------------------------------------------------------===// -def FeaturePipe3 : SubtargetFeature<"pipe3", "HasPipe3", "true", - "Implements 3-stage pipeline">; def FeatureBarrel : SubtargetFeature<"barrel", "HasBarrel", "true", "Implements barrel shifter">; def FeatureDiv : SubtargetFeature<"div", "HasDiv", "true", "Implements hardware divider">; def FeatureMul : SubtargetFeature<"mul", "HasMul", "true", "Implements hardware multiplier">; -def FeatureFSL : SubtargetFeature<"fsl", "HasFSL", "true", - "Implements FSL instructions">; -def FeatureEFSL : SubtargetFeature<"efsl", "HasEFSL", "true", - "Implements extended FSL instructions">; -def FeatureMSRSet : SubtargetFeature<"msrset", "HasMSRSet", "true", - "Implements MSR register set and clear">; -def FeatureException : SubtargetFeature<"exception", "HasException", "true", - "Implements hardware exception support">; def FeaturePatCmp : SubtargetFeature<"patcmp", "HasPatCmp", "true", "Implements pattern compare instruction">; def FeatureFPU : SubtargetFeature<"fpu", "HasFPU", "true", "Implements floating point unit">; -def FeatureESR : SubtargetFeature<"esr", "HasESR", "true", - "Implements ESR and EAR registers">; -def FeaturePVR : SubtargetFeature<"pvr", "HasPVR", "true", - "Implements processor version register">; def FeatureMul64 : SubtargetFeature<"mul64", "HasMul64", "true", "Implements multiplier with 64-bit result">; def FeatureSqrt : SubtargetFeature<"sqrt", "HasSqrt", "true", "Implements sqrt and floating point convert">; -def FeatureMMU : SubtargetFeature<"mmu", "HasMMU", "true", - "Implements memory management unit">; //===----------------------------------------------------------------------===// // MBlaze processors supported. //===----------------------------------------------------------------------===// -class Proc Features> - : Processor; - -def : Proc<"v400", []>; -def : Proc<"v500", []>; -def : Proc<"v600", []>; -def : Proc<"v700", []>; -def : Proc<"v710", []>; +def : Processor<"mblaze", MBlazeGenericItineraries, []>; +def : Processor<"mblaze3", MBlazePipe3Itineraries, []>; +def : Processor<"mblaze5", MBlazePipe5Itineraries, []>; //===----------------------------------------------------------------------===// // Instruction Descriptions Modified: llvm/trunk/lib/Target/MBlaze/MBlazeInstrFPU.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeInstrFPU.td?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeInstrFPU.td (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeInstrFPU.td Mon Apr 11 17:31:52 2011 @@ -21,22 +21,22 @@ class LoadFM op, string instr_asm, PatFrag OpNode> : TA; + [(set (f32 GPR:$dst), (OpNode xaddr:$addr))], IIC_MEMl>; class LoadFMI op, string instr_asm, PatFrag OpNode> : TB; + [(set (f32 GPR:$dst), (OpNode iaddr:$addr))], IIC_MEMl>; class StoreFM op, string instr_asm, PatFrag OpNode> : TA; + [(OpNode (f32 GPR:$dst), xaddr:$addr)], IIC_MEMs>; class StoreFMI op, string instr_asm, PatFrag OpNode> : TB; + [(OpNode (f32 GPR:$dst), iaddr:$addr)], IIC_MEMs>; class ArithF op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : @@ -56,15 +56,10 @@ !strconcat(instr_asm, " $dst, $c, $b"), [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], itin>; -class LogicF op, string instr_asm> : - TB; - class LogicFI op, string instr_asm> : TB; + [], IIC_ALU>; let rb=0 in { class ArithF2 op, bits<11> flags, string instr_asm, @@ -95,10 +90,10 @@ //===----------------------------------------------------------------------===// let Predicates=[HasFPU] in { def FORI : LogicFI<0x28, "ori ">; - def FADD : ArithF<0x16, 0x000, "fadd ", fadd, IIAlu>; - def FRSUB : ArithFR<0x16, 0x080, "frsub ", fsub, IIAlu>; - def FMUL : ArithF<0x16, 0x100, "fmul ", fmul, IIAlu>; - def FDIV : ArithF<0x16, 0x180, "fdiv ", fdiv, IIAlu>; + def FADD : ArithF<0x16, 0x000, "fadd ", fadd, IIC_FPU>; + def FRSUB : ArithFR<0x16, 0x080, "frsub ", fsub, IIC_FPU>; + def FMUL : ArithF<0x16, 0x100, "fmul ", fmul, IIC_FPU>; + def FDIV : ArithF<0x16, 0x180, "fdiv ", fdiv, IIC_FPUd>; } let Predicates=[HasFPU], isCodeGenOnly=1 in { @@ -110,19 +105,19 @@ } let Predicates=[HasFPU,HasSqrt] in { - def FLT : ArithIF<0x16, 0x280, "flt ", IIAlu>; - def FINT : ArithFI<0x16, 0x300, "fint ", IIAlu>; - def FSQRT : ArithF2<0x16, 0x380, "fsqrt ", IIAlu>; + def FLT : ArithIF<0x16, 0x280, "flt ", IIC_FPUf>; + def FINT : ArithFI<0x16, 0x300, "fint ", IIC_FPUi>; + def FSQRT : ArithF2<0x16, 0x380, "fsqrt ", IIC_FPUs>; } let isAsCheapAsAMove = 1 in { - def FCMP_UN : CmpFN<0x16, 0x200, "fcmp.un", IIAlu>; - def FCMP_LT : CmpFN<0x16, 0x210, "fcmp.lt", IIAlu>; - def FCMP_EQ : CmpFN<0x16, 0x220, "fcmp.eq", IIAlu>; - def FCMP_LE : CmpFN<0x16, 0x230, "fcmp.le", IIAlu>; - def FCMP_GT : CmpFN<0x16, 0x240, "fcmp.gt", IIAlu>; - def FCMP_NE : CmpFN<0x16, 0x250, "fcmp.ne", IIAlu>; - def FCMP_GE : CmpFN<0x16, 0x260, "fcmp.ge", IIAlu>; + def FCMP_UN : CmpFN<0x16, 0x200, "fcmp.un", IIC_FPUc>; + def FCMP_LT : CmpFN<0x16, 0x210, "fcmp.lt", IIC_FPUc>; + def FCMP_EQ : CmpFN<0x16, 0x220, "fcmp.eq", IIC_FPUc>; + def FCMP_LE : CmpFN<0x16, 0x230, "fcmp.le", IIC_FPUc>; + def FCMP_GT : CmpFN<0x16, 0x240, "fcmp.gt", IIC_FPUc>; + def FCMP_NE : CmpFN<0x16, 0x250, "fcmp.ne", IIC_FPUc>; + def FCMP_GE : CmpFN<0x16, 0x260, "fcmp.ge", IIC_FPUc>; } Modified: llvm/trunk/lib/Target/MBlaze/MBlazeInstrFSL.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeInstrFSL.td?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeInstrFSL.td (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeInstrFSL.td Mon Apr 11 17:31:52 2011 @@ -13,7 +13,7 @@ class FSLGet op, bits<5> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(set GPR:$dst, (OpNode immZExt4:$b))],IIC_FSLg> { bits<5> rd; bits<4> fslno; @@ -29,7 +29,7 @@ class FSLGetD op, bits<5> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(set GPR:$dst, (OpNode GPR:$b))], IIC_FSLg> { bits<5> rd; bits<5> rb; @@ -45,7 +45,7 @@ class FSLPut op, bits<4> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(OpNode GPR:$v, immZExt4:$b)], IIC_FSLp> { bits<5> ra; bits<4> fslno; @@ -61,7 +61,7 @@ class FSLPutD op, bits<4> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(OpNode GPR:$v, GPR:$b)], IIC_FSLp> { bits<5> ra; bits<5> rb; @@ -77,7 +77,7 @@ class FSLPutT op, bits<4> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(OpNode immZExt4:$b)], IIC_FSLp> { bits<4> fslno; @@ -92,7 +92,7 @@ class FSLPutTD op, bits<4> flags, string instr_asm, Intrinsic OpNode> : MBlazeInst + [(OpNode GPR:$b)], IIC_FSLp> { bits<5> rb; Modified: llvm/trunk/lib/Target/MBlaze/MBlazeInstrFormats.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeInstrFormats.td?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeInstrFormats.td (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeInstrFormats.td Mon Apr 11 17:31:52 2011 @@ -81,7 +81,7 @@ // Pseudo instruction class //===----------------------------------------------------------------------===// class MBlazePseudo pattern>: - MBlazeInst<0x0, FPseudo, outs, ins, asmstr, pattern, IIPseudo>; + MBlazeInst<0x0, FPseudo, outs, ins, asmstr, pattern, IIC_Pseudo>; //===----------------------------------------------------------------------===// // Type A instruction class in MBlaze : <|opcode|rd|ra|rb|flags|> Modified: llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.cpp?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.cpp (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.cpp Mon Apr 11 17:31:52 2011 @@ -17,6 +17,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScoreboardHazardRecognizer.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "MBlazeGenInstrInfo.inc" Modified: llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.h?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.h (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.h Mon Apr 11 17:31:52 2011 @@ -261,7 +261,6 @@ virtual bool ReverseBranchCondition(SmallVectorImpl &Cond) const; - virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, Modified: llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.td?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.td (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeInstrInfo.td Mon Apr 11 17:31:52 2011 @@ -47,22 +47,22 @@ //===----------------------------------------------------------------------===// // MBlaze Instruction Predicate Definitions. //===----------------------------------------------------------------------===// -def HasPipe3 : Predicate<"Subtarget.hasPipe3()">; +// def HasPipe3 : Predicate<"Subtarget.hasPipe3()">; def HasBarrel : Predicate<"Subtarget.hasBarrel()">; -def NoBarrel : Predicate<"!Subtarget.hasBarrel()">; +// def NoBarrel : Predicate<"!Subtarget.hasBarrel()">; def HasDiv : Predicate<"Subtarget.hasDiv()">; def HasMul : Predicate<"Subtarget.hasMul()">; -def HasFSL : Predicate<"Subtarget.hasFSL()">; -def HasEFSL : Predicate<"Subtarget.hasEFSL()">; -def HasMSRSet : Predicate<"Subtarget.hasMSRSet()">; -def HasException : Predicate<"Subtarget.hasException()">; +// def HasFSL : Predicate<"Subtarget.hasFSL()">; +// def HasEFSL : Predicate<"Subtarget.hasEFSL()">; +// def HasMSRSet : Predicate<"Subtarget.hasMSRSet()">; +// def HasException : Predicate<"Subtarget.hasException()">; def HasPatCmp : Predicate<"Subtarget.hasPatCmp()">; def HasFPU : Predicate<"Subtarget.hasFPU()">; -def HasESR : Predicate<"Subtarget.hasESR()">; -def HasPVR : Predicate<"Subtarget.hasPVR()">; +// def HasESR : Predicate<"Subtarget.hasESR()">; +// def HasPVR : Predicate<"Subtarget.hasPVR()">; def HasMul64 : Predicate<"Subtarget.hasMul64()">; def HasSqrt : Predicate<"Subtarget.hasSqrt()">; -def HasMMU : Predicate<"Subtarget.hasMMU()">; +// def HasMMU : Predicate<"Subtarget.hasMMU()">; //===----------------------------------------------------------------------===// // MBlaze Operand, Complex Patterns and Transformations Definitions. @@ -170,18 +170,18 @@ Operand Od, PatLeaf imm_type> : TB; + [(set GPR:$dst, (OpNode GPR:$b, imm_type:$c))], IIC_ALU>; class ArithI32 op, string instr_asm,Operand Od, PatLeaf imm_type> : TB; + [], IIC_ALU>; class ShiftI op, bits<2> flags, string instr_asm, SDNode OpNode, Operand Od, PatLeaf imm_type> : SHT; + [(set GPR:$dst, (OpNode GPR:$b, imm_type:$c))], IIC_SHT>; class ArithR op, bits<11> flags, string instr_asm, SDNode OpNode, InstrItinClass itin> : @@ -193,7 +193,7 @@ Operand Od, PatLeaf imm_type> : TBR; + [(set GPR:$dst, (OpNode imm_type:$b, GPR:$c))], IIC_ALU>; class ArithN op, bits<11> flags, string instr_asm, InstrItinClass itin> : @@ -204,7 +204,7 @@ class ArithNI op, string instr_asm,Operand Od, PatLeaf imm_type> : TB; + [], IIC_ALU>; class ArithRN op, bits<11> flags, string instr_asm, InstrItinClass itin> : @@ -215,7 +215,7 @@ class ArithRNI op, string instr_asm,Operand Od, PatLeaf imm_type> : TBR; + [], IIC_ALU>; //===----------------------------------------------------------------------===// // Misc Arithmetic Instructions @@ -224,23 +224,23 @@ class Logic op, bits<11> flags, string instr_asm, SDNode OpNode> : TA; + [(set GPR:$dst, (OpNode GPR:$b, GPR:$c))], IIC_ALU>; class LogicI op, string instr_asm, SDNode OpNode> : TB; + IIC_ALU>; class LogicI32 op, string instr_asm> : TB; + [], IIC_ALU>; class PatCmp op, bits<11> flags, string instr_asm> : TA; + [], IIC_ALU>; //===----------------------------------------------------------------------===// // Memory Access Instructions @@ -248,22 +248,22 @@ class LoadM op, bits<11> flags, string instr_asm> : TA; + [], IIC_MEMl>; class LoadMI op, string instr_asm, PatFrag OpNode> : TB; + [(set (i32 GPR:$dst), (OpNode iaddr:$addr))], IIC_MEMl>; class StoreM op, bits<11> flags, string instr_asm> : TA; + [], IIC_MEMs>; class StoreMI op, string instr_asm, PatFrag OpNode> : TB; + [(OpNode (i32 GPR:$dst), iaddr:$addr)], IIC_MEMs>; //===----------------------------------------------------------------------===// // Branch Instructions @@ -271,7 +271,7 @@ class Branch op, bits<5> br, bits<11> flags, string instr_asm> : TA { + [], IIC_BR> { let rd = 0x0; let ra = br; let Form = FCCR; @@ -280,7 +280,7 @@ class BranchI op, bits<5> br, string instr_asm> : TB { + [], IIC_BR> { let rd = 0; let ra = br; let Form = FCCI; @@ -292,7 +292,7 @@ class BranchL op, bits<5> br, bits<11> flags, string instr_asm> : TA { + [], IIC_BRl> { let ra = br; let Form = FRCR; } @@ -300,7 +300,7 @@ class BranchLI op, bits<5> br, string instr_asm> : TB { + [], IIC_BRl> { let ra = br; let Form = FRCI; } @@ -312,7 +312,7 @@ TA { + [], IIC_BRc> { let rd = br; let Form = FCRR; } @@ -320,7 +320,7 @@ class BranchCI op, bits<5> br, string instr_asm> : TB { + [], IIC_BRc> { let rd = br; let Form = FCRI; } @@ -330,71 +330,74 @@ //===----------------------------------------------------------------------===// let isCommutable = 1, isAsCheapAsAMove = 1 in { - def ADDK : Arith<0x04, 0x000, "addk ", add, IIAlu>; + def ADDK : Arith<0x04, 0x000, "addk ", add, IIC_ALU>; def AND : Logic<0x21, 0x000, "and ", and>; def OR : Logic<0x20, 0x000, "or ", or>; def XOR : Logic<0x22, 0x000, "xor ", xor>; - def PCMPBF : PatCmp<0x20, 0x400, "pcmpbf ">; - def PCMPEQ : PatCmp<0x22, 0x400, "pcmpeq ">; - def PCMPNE : PatCmp<0x23, 0x400, "pcmpne ">; + + let Predicates=[HasPatCmp] in { + def PCMPBF : PatCmp<0x20, 0x400, "pcmpbf ">; + def PCMPEQ : PatCmp<0x22, 0x400, "pcmpeq ">; + def PCMPNE : PatCmp<0x23, 0x400, "pcmpne ">; + } let Defs = [CARRY] in { - def ADD : Arith<0x00, 0x000, "add ", addc, IIAlu>; + def ADD : Arith<0x00, 0x000, "add ", addc, IIC_ALU>; let Uses = [CARRY] in { - def ADDC : Arith<0x02, 0x000, "addc ", adde, IIAlu>; + def ADDC : Arith<0x02, 0x000, "addc ", adde, IIC_ALU>; } } let Uses = [CARRY] in { - def ADDKC : ArithN<0x06, 0x000, "addkc ", IIAlu>; + def ADDKC : ArithN<0x06, 0x000, "addkc ", IIC_ALU>; } } let isAsCheapAsAMove = 1 in { - def ANDN : ArithN<0x23, 0x000, "andn ", IIAlu>; - def CMP : ArithN<0x05, 0x001, "cmp ", IIAlu>; - def CMPU : ArithN<0x05, 0x003, "cmpu ", IIAlu>; - def RSUBK : ArithR<0x05, 0x000, "rsubk ", sub, IIAlu>; + def ANDN : ArithN<0x23, 0x000, "andn ", IIC_ALU>; + def CMP : ArithN<0x05, 0x001, "cmp ", IIC_ALU>; + def CMPU : ArithN<0x05, 0x003, "cmpu ", IIC_ALU>; + def RSUBK : ArithR<0x05, 0x000, "rsubk ", sub, IIC_ALU>; let Defs = [CARRY] in { - def RSUB : ArithR<0x01, 0x000, "rsub ", subc, IIAlu>; + def RSUB : ArithR<0x01, 0x000, "rsub ", subc, IIC_ALU>; let Uses = [CARRY] in { - def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIAlu>; + def RSUBC : ArithR<0x03, 0x000, "rsubc ", sube, IIC_ALU>; } } let Uses = [CARRY] in { - def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIAlu>; + def RSUBKC : ArithRN<0x07, 0x000, "rsubkc ", IIC_ALU>; } } let isCommutable = 1, Predicates=[HasMul] in { - def MUL : Arith<0x10, 0x000, "mul ", mul, IIAlu>; + def MUL : Arith<0x10, 0x000, "mul ", mul, IIC_ALUm>; } let isCommutable = 1, Predicates=[HasMul,HasMul64] in { - def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIAlu>; - def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIAlu>; + def MULH : Arith<0x10, 0x001, "mulh ", mulhs, IIC_ALUm>; + def MULHU : Arith<0x10, 0x003, "mulhu ", mulhu, IIC_ALUm>; } let Predicates=[HasMul,HasMul64] in { - def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIAlu>; + def MULHSU : ArithN<0x10, 0x002, "mulhsu ", IIC_ALUm>; } let Predicates=[HasBarrel] in { - def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIAlu>; - def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIAlu>; - def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIAlu>; + def BSRL : Arith<0x11, 0x000, "bsrl ", srl, IIC_SHT>; + def BSRA : Arith<0x11, 0x200, "bsra ", sra, IIC_SHT>; + def BSLL : Arith<0x11, 0x400, "bsll ", shl, IIC_SHT>; def BSRLI : ShiftI<0x19, 0x0, "bsrli ", srl, uimm5, immZExt5>; def BSRAI : ShiftI<0x19, 0x1, "bsrai ", sra, uimm5, immZExt5>; def BSLLI : ShiftI<0x19, 0x2, "bslli ", shl, uimm5, immZExt5>; } let Predicates=[HasDiv] in { - def IDIV : ArithR<0x12, 0x000, "idiv ", sdiv, IIAlu>; - def IDIVU : ArithR<0x12, 0x002, "idivu ", udiv, IIAlu>; + def IDIV : ArithR<0x12, 0x000, "idiv ", sdiv, IIC_ALUd>; + def IDIVU : ArithR<0x12, 0x002, "idivu ", udiv, IIC_ALUd>; } //===----------------------------------------------------------------------===// @@ -552,7 +555,7 @@ def RTSD : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtsd $target, $imm", [], - IIBranch>; + IIC_BR>; } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, @@ -560,7 +563,7 @@ def RTID : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtid $target, $imm", [], - IIBranch>; + IIC_BR>; } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, @@ -568,7 +571,7 @@ def RTBD : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rtbd $target, $imm", [], - IIBranch>; + IIC_BR>; } let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, @@ -576,7 +579,7 @@ def RTED : TB<0x2D, (outs), (ins GPR:$target, simm16:$imm), "rted $target, $imm", [], - IIBranch>; + IIC_BR>; } //===----------------------------------------------------------------------===// @@ -584,7 +587,7 @@ //===----------------------------------------------------------------------===// let neverHasSideEffects = 1 in { - def NOP : MBlazeInst< 0x20, FC, (outs), (ins), "nop ", [], IIAlu>; + def NOP : MBlazeInst< 0x20, FC, (outs), (ins), "nop ", [], IIC_ALU>; } let usesCustomInserter = 1 in { @@ -611,17 +614,17 @@ let rb = 0 in { def SEXT16 : TA<0x24, 0x061, (outs GPR:$dst), (ins GPR:$src), - "sext16 $dst, $src", [], IIAlu>; + "sext16 $dst, $src", [], IIC_ALU>; def SEXT8 : TA<0x24, 0x060, (outs GPR:$dst), (ins GPR:$src), - "sext8 $dst, $src", [], IIAlu>; + "sext8 $dst, $src", [], IIC_ALU>; let Defs = [CARRY] in { def SRL : TA<0x24, 0x041, (outs GPR:$dst), (ins GPR:$src), - "srl $dst, $src", [], IIAlu>; + "srl $dst, $src", [], IIC_ALU>; def SRA : TA<0x24, 0x001, (outs GPR:$dst), (ins GPR:$src), - "sra $dst, $src", [], IIAlu>; + "sra $dst, $src", [], IIC_ALU>; let Uses = [CARRY] in { def SRC : TA<0x24, 0x021, (outs GPR:$dst), (ins GPR:$src), - "src $dst, $src", [], IIAlu>; + "src $dst, $src", [], IIC_ALU>; } } } @@ -637,36 +640,36 @@ //===----------------------------------------------------------------------===// let Form=FRCS in { def MFS : SPC<0x25, 0x2, (outs GPR:$dst), (ins SPR:$src), - "mfs $dst, $src", [], IIAlu>; + "mfs $dst, $src", [], IIC_ALU>; } let Form=FCRCS in { def MTS : SPC<0x25, 0x3, (outs SPR:$dst), (ins GPR:$src), - "mts $dst, $src", [], IIAlu>; + "mts $dst, $src", [], IIC_ALU>; } def MSRSET : MSR<0x25, 0x20, (outs GPR:$dst), (ins uimm15:$set), - "msrset $dst, $set", [], IIAlu>; + "msrset $dst, $set", [], IIC_ALU>; def MSRCLR : MSR<0x25, 0x22, (outs GPR:$dst), (ins uimm15:$clr), - "msrclr $dst, $clr", [], IIAlu>; + "msrclr $dst, $clr", [], IIC_ALU>; let rd=0x0, Form=FCRR in { def WDC : TA<0x24, 0x64, (outs), (ins GPR:$a, GPR:$b), - "wdc $a, $b", [], IIAlu>; + "wdc $a, $b", [], IIC_WDC>; def WDCF : TA<0x24, 0x74, (outs), (ins GPR:$a, GPR:$b), - "wdc.flush $a, $b", [], IIAlu>; + "wdc.flush $a, $b", [], IIC_WDC>; def WDCC : TA<0x24, 0x66, (outs), (ins GPR:$a, GPR:$b), - "wdc.clear $a, $b", [], IIAlu>; + "wdc.clear $a, $b", [], IIC_WDC>; def WIC : TA<0x24, 0x68, (outs), (ins GPR:$a, GPR:$b), - "wic $a, $b", [], IIAlu>; + "wic $a, $b", [], IIC_WDC>; } def BRK : BranchL<0x26, 0x0C, 0x000, "brk ">; def BRKI : BranchLI<0x2E, 0x0C, "brki ">; def IMM : MBlazeInst<0x2C, FCCI, (outs), (ins simm16:$imm), - "imm $imm", [], IIAlu>; + "imm $imm", [], IIC_ALU>; //===----------------------------------------------------------------------===// // Pseudo instructions for atomic operations @@ -848,11 +851,6 @@ // Misc instructions def : Pat<(and (i32 GPR:$lh), (not (i32 GPR:$rh))),(ANDN GPR:$lh, GPR:$rh)>; -// Arithmetic with immediates -def : Pat<(add (i32 GPR:$in), imm:$imm),(ADDIK GPR:$in, imm:$imm)>; -def : Pat<(or (i32 GPR:$in), imm:$imm),(ORI GPR:$in, imm:$imm)>; -def : Pat<(xor (i32 GPR:$in), imm:$imm),(XORI GPR:$in, imm:$imm)>; - // Convert any extend loads into zero extend loads def : Pat<(extloadi8 iaddr:$src), (i32 (LBUI iaddr:$src))>; def : Pat<(extloadi16 iaddr:$src), (i32 (LHUI iaddr:$src))>; Modified: llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.td?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.td (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeRegisterInfo.td Mon Apr 11 17:31:52 2011 @@ -85,18 +85,19 @@ def RTLBX : MBlazeSPRReg<0x1002, "rtlbx">, DwarfRegNum<[41]>; def RTLBLO : MBlazeSPRReg<0x1003, "rtlblo">, DwarfRegNum<[42]>; def RTLBHI : MBlazeSPRReg<0x1004, "rtlbhi">, DwarfRegNum<[43]>; - def RPVR0 : MBlazeSPRReg<0x2000, "rpvr0">, DwarfRegNum<[44]>; - def RPVR1 : MBlazeSPRReg<0x2001, "rpvr1">, DwarfRegNum<[45]>; - def RPVR2 : MBlazeSPRReg<0x2002, "rpvr2">, DwarfRegNum<[46]>; - def RPVR3 : MBlazeSPRReg<0x2003, "rpvr3">, DwarfRegNum<[47]>; - def RPVR4 : MBlazeSPRReg<0x2004, "rpvr4">, DwarfRegNum<[48]>; - def RPVR5 : MBlazeSPRReg<0x2005, "rpvr5">, DwarfRegNum<[49]>; - def RPVR6 : MBlazeSPRReg<0x2006, "rpvr6">, DwarfRegNum<[50]>; - def RPVR7 : MBlazeSPRReg<0x2007, "rpvr7">, DwarfRegNum<[51]>; - def RPVR8 : MBlazeSPRReg<0x2008, "rpvr8">, DwarfRegNum<[52]>; - def RPVR9 : MBlazeSPRReg<0x2009, "rpvr9">, DwarfRegNum<[53]>; - def RPVR10 : MBlazeSPRReg<0x200A, "rpvr10">, DwarfRegNum<[54]>; - def RPVR11 : MBlazeSPRReg<0x200B, "rpvr11">, DwarfRegNum<[55]>; + def RTLBSX : MBlazeSPRReg<0x1004, "rtlbsx">, DwarfRegNum<[44]>; + def RPVR0 : MBlazeSPRReg<0x2000, "rpvr0">, DwarfRegNum<[45]>; + def RPVR1 : MBlazeSPRReg<0x2001, "rpvr1">, DwarfRegNum<[46]>; + def RPVR2 : MBlazeSPRReg<0x2002, "rpvr2">, DwarfRegNum<[47]>; + def RPVR3 : MBlazeSPRReg<0x2003, "rpvr3">, DwarfRegNum<[48]>; + def RPVR4 : MBlazeSPRReg<0x2004, "rpvr4">, DwarfRegNum<[49]>; + def RPVR5 : MBlazeSPRReg<0x2005, "rpvr5">, DwarfRegNum<[50]>; + def RPVR6 : MBlazeSPRReg<0x2006, "rpvr6">, DwarfRegNum<[51]>; + def RPVR7 : MBlazeSPRReg<0x2007, "rpvr7">, DwarfRegNum<[52]>; + def RPVR8 : MBlazeSPRReg<0x2008, "rpvr8">, DwarfRegNum<[53]>; + def RPVR9 : MBlazeSPRReg<0x2009, "rpvr9">, DwarfRegNum<[54]>; + def RPVR10 : MBlazeSPRReg<0x200A, "rpvr10">, DwarfRegNum<[55]>; + def RPVR11 : MBlazeSPRReg<0x200B, "rpvr11">, DwarfRegNum<[56]>; // The carry bit. In the Microblaze this is really bit 29 of the // MSR register but this is the only bit of that register that we Modified: llvm/trunk/lib/Target/MBlaze/MBlazeSchedule.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeSchedule.td?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeSchedule.td (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeSchedule.td Mon Apr 11 17:31:52 2011 @@ -8,57 +8,48 @@ //===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// -// Functional units across MBlaze chips sets. Based on GCC/MBlaze backend files. +// MBlaze functional units. //===----------------------------------------------------------------------===// -def ALU : FuncUnit; -def IMULDIV : FuncUnit; +def IF : FuncUnit; +def ID : FuncUnit; +def EX : FuncUnit; +def MA : FuncUnit; +def WB : FuncUnit; //===----------------------------------------------------------------------===// // Instruction Itinerary classes used for MBlaze //===----------------------------------------------------------------------===// -def IIAlu : InstrItinClass; -def IILoad : InstrItinClass; -def IIStore : InstrItinClass; -def IIXfer : InstrItinClass; -def IIBranch : InstrItinClass; -def IIHiLo : InstrItinClass; -def IIImul : InstrItinClass; -def IIIdiv : InstrItinClass; -def IIFcvt : InstrItinClass; -def IIFmove : InstrItinClass; -def IIFcmp : InstrItinClass; -def IIFadd : InstrItinClass; -def IIFmulSingle : InstrItinClass; -def IIFmulDouble : InstrItinClass; -def IIFdivSingle : InstrItinClass; -def IIFdivDouble : InstrItinClass; -def IIFsqrtSingle : InstrItinClass; -def IIFsqrtDouble : InstrItinClass; -def IIFrecipFsqrtStep : InstrItinClass; -def IIPseudo : InstrItinClass; +def IIC_ALU : InstrItinClass; +def IIC_ALUm : InstrItinClass; +def IIC_ALUd : InstrItinClass; +def IIC_SHT : InstrItinClass; +def IIC_FSLg : InstrItinClass; +def IIC_FSLp : InstrItinClass; +def IIC_MEMs : InstrItinClass; +def IIC_MEMl : InstrItinClass; +def IIC_FPU : InstrItinClass; +def IIC_FPUd : InstrItinClass; +def IIC_FPUf : InstrItinClass; +def IIC_FPUi : InstrItinClass; +def IIC_FPUs : InstrItinClass; +def IIC_FPUc : InstrItinClass; +def IIC_BR : InstrItinClass; +def IIC_BRc : InstrItinClass; +def IIC_BRl : InstrItinClass; +def IIC_WDC : InstrItinClass; +def IIC_Pseudo : InstrItinClass; //===----------------------------------------------------------------------===// -// MBlaze Generic instruction itineraries. +// MBlaze generic instruction itineraries. //===----------------------------------------------------------------------===// -def MBlazeGenericItineraries : ProcessorItineraries< - [ALU, IMULDIV], [], [ - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]>, - InstrItinData]> -]>; +def MBlazeGenericItineraries : ProcessorItineraries<[], [], []>; + +//===----------------------------------------------------------------------===// +// MBlaze instruction itineraries for three stage pipeline. +//===----------------------------------------------------------------------===// +include "MBlazeSchedule3.td" + +//===----------------------------------------------------------------------===// +// MBlaze instruction itineraries for five stage pipeline. +//===----------------------------------------------------------------------===// +include "MBlazeSchedule5.td" Added: llvm/trunk/lib/Target/MBlaze/MBlazeSchedule3.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeSchedule3.td?rev=129311&view=auto ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeSchedule3.td (added) +++ llvm/trunk/lib/Target/MBlaze/MBlazeSchedule3.td Mon Apr 11 17:31:52 2011 @@ -0,0 +1,236 @@ +//===- MBlazeSchedule3.td - MBlaze Scheduling Definitions --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MBlaze instruction itineraries for the threee stage pipeline. +//===----------------------------------------------------------------------===// +def MBlazePipe3Itineraries : ProcessorItineraries< + [IF,ID,EX], [], [ + + // ALU instruction with one destination register and either two register + // source operands or one register source operand and one immediate operand. + // The instruction takes one cycle to execute in each of the stages. The + // two source operands are read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_ALU, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]>], // one cycle in execute stage + [ 2 // result ready after two cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // ALU multiply instruction with one destination register and either two + // register source operands or one register source operand and one immediate + // operand. The instruction takes one cycle to execute in each of the + // pipeline stages except the execute stage, which takes three cycles. The + // two source operands are read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_ALUm, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<3,[EX]>], // three cycles in execute stage + [ 4 // result ready after four cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // ALU divide instruction with one destination register two register source + // operands. The instruction takes one cycle to execute in each the pipeline + // stages except the execute stage, which takes 34 cycles. The two + // source operands are read during the decode stage and the result is ready + // after the execute stage. + InstrItinData< IIC_ALUd, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<34,[EX]>], // 34 cycles in execute stage + [ 35 // result ready after 35 cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Shift instruction with one destination register and either two register + // source operands or one register source operand and one immediate operand. + // The instruction takes one cycle to execute in each of the pipeline stages + // except the execute stage, which takes two cycles. The two source operands + // are read during the decode stage and the result is ready after the execute + // stage. + InstrItinData< IIC_SHT, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 3 // result ready after three cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Branch instruction with one source operand register. The instruction takes + // one cycle to execute in each of the pipeline stages. The source operand is + // read during the decode stage. + InstrItinData< IIC_BR, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]>], // one cycle in execute stage + [ 1 ]>, // first operand read after one cycle + + // Conditional branch instruction with two source operand registers. The + // instruction takes one cycle to execute in each of the pipeline stages. The + // two source operands are read during the decode stage. + InstrItinData< IIC_BRc, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]>], // one cycle in execute stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Branch and link instruction with one destination register and one source + // operand register. The instruction takes one cycle to execute in each of + // the pipeline stages. The source operand is read during the decode stage + // and the destination register is ready after the execute stage. + InstrItinData< IIC_BRl, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]>], // one cycle in execute stage + [ 2 // result ready after two cycles + , 1 ]>, // first operand read after one cycle + + // Cache control instruction with two source operand registers. The + // instruction takes one cycle to execute in each of the pipeline stages + // except the memory access stage, which takes two cycles. The source + // operands are read during the decode stage. + InstrItinData< IIC_WDC, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Floating point instruction with one destination register and two source + // operand registers. The instruction takes one cycle to execute in each of + // the pipeline stages except the execute stage, which takes six cycles. The + // source operands are read during the decode stage and the results are ready + // after the execute stage. + InstrItinData< IIC_FPU, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<6,[EX]>], // six cycles in execute stage + [ 7 // result ready after seven cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Floating point divide instruction with one destination register and two + // source operand registers. The instruction takes one cycle to execute in + // each of the pipeline stages except the execute stage, which takes 30 + // cycles. The source operands are read during the decode stage and the + // results are ready after the execute stage. + InstrItinData< IIC_FPUd, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<30,[EX]>], // one cycle in execute stage + [ 31 // result ready after 31 cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Convert floating point to integer instruction with one destination + // register and one source operand register. The instruction takes one cycle + // to execute in each of the pipeline stages except the execute stage, + // which takes seven cycles. The source operands are read during the decode + // stage and the results are ready after the execute stage. + InstrItinData< IIC_FPUi, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<7,[EX]>], // seven cycles in execute stage + [ 8 // result ready after eight cycles + , 1 ]>, // first operand read after one cycle + + // Convert integer to floating point instruction with one destination + // register and one source operand register. The instruction takes one cycle + // to execute in each of the pipeline stages except the execute stage, + // which takes six cycles. The source operands are read during the decode + // stage and the results are ready after the execute stage. + InstrItinData< IIC_FPUf, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<6,[EX]>], // six cycles in execute stage + [ 7 // result ready after seven cycles + , 1 ]>, // first operand read after one cycle + + // Floating point square root instruction with one destination register and + // one source operand register. The instruction takes one cycle to execute in + // each of the pipeline stages except the execute stage, which takes 29 + // cycles. The source operands are read during the decode stage and the + // results are ready after the execute stage. + InstrItinData< IIC_FPUs, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<29,[EX]>], // 29 cycles in execute stage + [ 30 // result ready after 30 cycles + , 1 ]>, // first operand read after one cycle + + // Floating point comparison instruction with one destination register and + // two source operand registers. The instruction takes one cycle to execute + // in each of the pipeline stages except the execute stage, which takes three + // cycles. The source operands are read during the decode stage and the + // results are ready after the execute stage. + InstrItinData< IIC_FPUc, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<3,[EX]>], // three cycles in execute stage + [ 4 // result ready after four cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // FSL get instruction with one register or immediate source operand and one + // destination register. The instruction takes one cycle to execute in each + // of the pipeline stages except the execute stage, which takes two cycles. + // The one source operand is read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_FSLg, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 3 // result ready after two cycles + , 1 ]>, // first operand read after one cycle + + // FSL put instruction with either two register source operands or one + // register source operand and one immediate operand. There is no result + // produced by the instruction. The instruction takes one cycle to execute in + // each of the pipeline stages except the execute stage, which takes two + // cycles. The two source operands are read during the decode stage. + InstrItinData< IIC_FSLp, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Memory store instruction with either three register source operands or two + // register source operands and one immediate operand. There is no result + // produced by the instruction. The instruction takes one cycle to execute in + // each of the pipeline stages except the execute stage, which takes two + // cycles. All of the source operands are read during the decode stage. + InstrItinData< IIC_MEMs, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 1 // first operand read after one cycle + , 1 // second operand read after one cycle + , 1 ]>, // third operand read after one cycle + + // Memory load instruction with one destination register and either two + // register source operands or one register source operand and one immediate + // operand. The instruction takes one cycle to execute in each of the + // pipeline stages except the execute stage, which takes two cycles. All of + // the source operands are read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_MEMl, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<2,[EX]>], // two cycles in execute stage + [ 3 // result ready after four cycles + , 1 // second operand read after one cycle + , 1 ]> // third operand read after one cycle +]>; Added: llvm/trunk/lib/Target/MBlaze/MBlazeSchedule5.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeSchedule5.td?rev=129311&view=auto ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeSchedule5.td (added) +++ llvm/trunk/lib/Target/MBlaze/MBlazeSchedule5.td Mon Apr 11 17:31:52 2011 @@ -0,0 +1,267 @@ +//===- MBlazeSchedule5.td - MBlaze Scheduling Definitions --*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// MBlaze instruction itineraries for the five stage pipeline. +//===----------------------------------------------------------------------===// +def MBlazePipe5Itineraries : ProcessorItineraries< + [IF,ID,EX,MA,WB], [], [ + + // ALU instruction with one destination register and either two register + // source operands or one register source operand and one immediate operand. + // The instruction takes one cycle to execute in each of the stages. The + // two source operands are read during the decode stage and the result is + // ready after the execute stage. + InstrItinData< IIC_ALU, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 2 // result ready after two cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // ALU multiply instruction with one destination register and either two + // register source operands or one register source operand and one immediate + // operand. The instruction takes one cycle to execute in each of the + // pipeline stages. The two source operands are read during the decode stage + // and the result is ready after the execute stage. + InstrItinData< IIC_ALUm, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 2 // result ready after two cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // ALU divide instruction with one destination register two register source + // operands. The instruction takes one cycle to execute in each the pipeline + // stages except the memory access stage, which takes 31 cycles. The two + // source operands are read during the decode stage and the result is ready + // after the memory access stage. + InstrItinData< IIC_ALUd, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<31,[MA]> // 31 cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 33 // result ready after 33 cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Shift instruction with one destination register and either two register + // source operands or one register source operand and one immediate operand. + // The instruction takes one cycle to execute in each of the pipeline stages. + // The two source operands are read during the decode stage and the result is + // ready after the memory access stage. + InstrItinData< IIC_SHT, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 3 // result ready after three cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Branch instruction with one source operand register. The instruction takes + // one cycle to execute in each of the pipeline stages. The source operand is + // read during the decode stage. + InstrItinData< IIC_BR, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 ]>, // first operand read after one cycle + + // Conditional branch instruction with two source operand registers. The + // instruction takes one cycle to execute in each of the pipeline stages. The + // two source operands are read during the decode stage. + InstrItinData< IIC_BRc, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Branch and link instruction with one destination register and one source + // operand register. The instruction takes one cycle to execute in each of + // the pipeline stages. The source operand is read during the decode stage + // and the destination register is ready after the writeback stage. + InstrItinData< IIC_BRl, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 4 // result ready after four cycles + , 1 ]>, // first operand read after one cycle + + // Cache control instruction with two source operand registers. The + // instruction takes one cycle to execute in each of the pipeline stages + // except the memory access stage, which takes two cycles. The source + // operands are read during the decode stage. + InstrItinData< IIC_WDC, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<2,[MA]> // two cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Floating point instruction with one destination register and two source + // operand registers. The instruction takes one cycle to execute in each of + // the pipeline stages except the memory access stage, which takes two + // cycles. The source operands are read during the decode stage and the + // results are ready after the writeback stage. + InstrItinData< IIC_FPU, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<2,[MA]> // two cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 5 // result ready after five cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Floating point divide instruction with one destination register and two + // source operand registers. The instruction takes one cycle to execute in + // each of the pipeline stages except the memory access stage, which takes 26 + // cycles. The source operands are read during the decode stage and the + // results are ready after the writeback stage. + InstrItinData< IIC_FPUd, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<26,[MA]> // 26 cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 29 // result ready after 29 cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Convert floating point to integer instruction with one destination + // register and one source operand register. The instruction takes one cycle + // to execute in each of the pipeline stages except the memory access stage, + // which takes three cycles. The source operands are read during the decode + // stage and the results are ready after the writeback stage. + InstrItinData< IIC_FPUi, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<3,[MA]> // three cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 6 // result ready after six cycles + , 1 ]>, // first operand read after one cycle + + // Convert integer to floating point instruction with one destination + // register and one source operand register. The instruction takes one cycle + // to execute in each of the pipeline stages except the memory access stage, + // which takes two cycles. The source operands are read during the decode + // stage and the results are ready after the writeback stage. + InstrItinData< IIC_FPUf, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<2,[MA]> // two cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 5 // result ready after five cycles + , 1 ]>, // first operand read after one cycle + + // Floating point square root instruction with one destination register and + // one source operand register. The instruction takes one cycle to execute in + // each of the pipeline stages except the memory access stage, which takes 25 + // cycles. The source operands are read during the decode stage and the + // results are ready after the writeback stage. + InstrItinData< IIC_FPUs, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<25,[MA]> // 25 cycles in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 28 // result ready after 28 cycles + , 1 ]>, // first operand read after one cycle + + // Floating point comparison instruction with one destination register and + // two source operand registers. The instruction takes one cycle to execute + // in each of the pipeline stages. The source operands are read during the + // decode stage and the results are ready after the execute stage. + InstrItinData< IIC_FPUc, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 2 // result ready after two cycles + , 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // FSL get instruction with one register or immediate source operand and one + // destination register. The instruction takes one cycle to execute in each + // of the pipeline stages. The one source operand is read during the decode + // stage and the result is ready after the execute stage. + InstrItinData< IIC_FSLg, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 2 // result ready after two cycles + , 1 ]>, // first operand read after one cycle + + // FSL put instruction with either two register source operands or one + // register source operand and one immediate operand. There is no result + // produced by the instruction. The instruction takes one cycle to execute in + // each of the pipeline stages. The two source operands are read during the + // decode stage. + InstrItinData< IIC_FSLp, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 // first operand read after one cycle + , 1 ]>, // second operand read after one cycle + + // Memory store instruction with either three register source operands or two + // register source operands and one immediate operand. There is no result + // produced by the instruction. The instruction takes one cycle to execute in + // each of the pipeline stages. All of the source operands are read during + // the decode stage. + InstrItinData< IIC_MEMs, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 1 // first operand read after one cycle + , 1 // second operand read after one cycle + , 1 ]>, // third operand read after one cycle + + // Memory load instruction with one destination register and either two + // register source operands or one register source operand and one immediate + // operand. The instruction takes one cycle to execute in each of the + // pipeline stages. All of the source operands are read during the decode + // stage and the result is ready after the writeback stage. + InstrItinData< IIC_MEMl, + [ InstrStage<1,[IF]> // one cycle in fetch stage + , InstrStage<1,[ID]> // one cycle in decode stage + , InstrStage<1,[EX]> // one cycle in execute stage + , InstrStage<1,[MA]> // one cycle in memory access stage + , InstrStage<1,[WB]>], // one cycle in write back stage + [ 4 // result ready after four cycles + , 1 // second operand read after one cycle + , 1 ]> // third operand read after one cycle +]>; Modified: llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.cpp?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.cpp (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.cpp Mon Apr 11 17:31:52 2011 @@ -13,19 +13,39 @@ #include "MBlazeSubtarget.h" #include "MBlaze.h" +#include "MBlazeRegisterInfo.h" #include "MBlazeGenSubtarget.inc" #include "llvm/Support/CommandLine.h" using namespace llvm; MBlazeSubtarget::MBlazeSubtarget(const std::string &TT, const std::string &FS): - HasPipe3(false), HasBarrel(false), HasDiv(false), HasMul(false), - HasFSL(false), HasEFSL(false), HasMSRSet(false), HasException(false), - HasPatCmp(false), HasFPU(false), HasESR(false), HasPVR(false), - HasMul64(false), HasSqrt(false), HasMMU(false) + HasBarrel(false), HasDiv(false), HasMul(false), HasPatCmp(false), + HasFPU(false), HasMul64(false), HasSqrt(false) { - std::string CPU = "v400"; - MBlazeArchVersion = V400; - // Parse features string. - ParseSubtargetFeatures(FS, CPU); + std::string CPU = "mblaze"; + CPU = ParseSubtargetFeatures(FS, CPU); + + // Only use instruction scheduling if the selected CPU has an instruction + // itinerary (the default CPU is the only one that doesn't). + HasItin = CPU != "mblaze"; + DEBUG(dbgs() << "CPU " << CPU << "(" << HasItin << ")\n"); + + // Compute the issue width of the MBlaze itineraries + computeIssueWidth(); +} + +void MBlazeSubtarget::computeIssueWidth() { + InstrItins.IssueWidth = 1; +} + +bool MBlazeSubtarget:: +enablePostRAScheduler(CodeGenOpt::Level OptLevel, + TargetSubtarget::AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const { + Mode = TargetSubtarget::ANTIDEP_CRITICAL; + CriticalPathRCs.clear(); + CriticalPathRCs.push_back(&MBlaze::GPRRegClass); + return HasItin && OptLevel >= CodeGenOpt::Default; } + Modified: llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.h?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.h (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeSubtarget.h Mon Apr 11 17:31:52 2011 @@ -24,29 +24,14 @@ class MBlazeSubtarget : public TargetSubtarget { protected: - - enum MBlazeArchEnum { - V400, V500, V600, V700, V710 - }; - - // MBlaze architecture version - MBlazeArchEnum MBlazeArchVersion; - - bool HasPipe3; bool HasBarrel; bool HasDiv; bool HasMul; - bool HasFSL; - bool HasEFSL; - bool HasMSRSet; - bool HasException; bool HasPatCmp; bool HasFPU; - bool HasESR; - bool HasPVR; bool HasMul64; bool HasSqrt; - bool HasMMU; + bool HasItin; InstrItineraryData InstrItins; @@ -61,18 +46,26 @@ std::string ParseSubtargetFeatures(const std::string &FS, const std::string &CPU); + /// Compute the number of maximum number of issues per cycle for the + /// MBlaze scheduling itineraries. + void computeIssueWidth(); + + /// enablePostRAScheduler - True at 'More' optimization. + bool enablePostRAScheduler(CodeGenOpt::Level OptLevel, + TargetSubtarget::AntiDepBreakMode& Mode, + RegClassVector& CriticalPathRCs) const; + + /// getInstrItins - Return the instruction itineraies based on subtarget. + const InstrItineraryData &getInstrItineraryData() const { return InstrItins; } + + bool hasItin() const { return HasItin; } + bool hasPCMP() const { return HasPatCmp; } bool hasFPU() const { return HasFPU; } bool hasSqrt() const { return HasSqrt; } bool hasMul() const { return HasMul; } bool hasMul64() const { return HasMul64; } bool hasDiv() const { return HasDiv; } bool hasBarrel() const { return HasBarrel; } - - bool isV400() const { return MBlazeArchVersion == V400; } - bool isV500() const { return MBlazeArchVersion == V500; } - bool isV600() const { return MBlazeArchVersion == V600; } - bool isV700() const { return MBlazeArchVersion == V700; } - bool isV710() const { return MBlazeArchVersion == V710; } }; } // End llvm namespace Modified: llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.cpp?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.cpp (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.cpp Mon Apr 11 17:31:52 2011 @@ -87,7 +87,8 @@ DataLayout("E-p:32:32:32-i8:8:8-i16:16:16"), InstrInfo(*this), FrameLowering(Subtarget), - TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this) { + TLInfo(*this), TSInfo(*this), ELFWriterInfo(*this), + InstrItins(Subtarget.getInstrItineraryData()) { if (getRelocationModel() == Reloc::Default) { setRelocationModel(Reloc::Static); } Modified: llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.h?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.h (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeTargetMachine.h Mon Apr 11 17:31:52 2011 @@ -38,13 +38,18 @@ MBlazeSelectionDAGInfo TSInfo; MBlazeIntrinsicInfo IntrinsicInfo; MBlazeELFWriterInfo ELFWriterInfo; + InstrItineraryData InstrItins; + public: MBlazeTargetMachine(const Target &T, const std::string &TT, - const std::string &FS); + const std::string &FS); virtual const MBlazeInstrInfo *getInstrInfo() const { return &InstrInfo; } + virtual const InstrItineraryData *getInstrItineraryData() const + { return &InstrItins; } + virtual const TargetFrameLowering *getFrameLowering() const { return &FrameLowering; } Modified: llvm/trunk/lib/Target/MBlaze/TODO URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/TODO?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/TODO (original) +++ llvm/trunk/lib/Target/MBlaze/TODO Mon Apr 11 17:31:52 2011 @@ -9,8 +9,6 @@ needs to be examined more closely: - The stack layout needs to be examined to make sure it meets the standard, especially in regards to var arg functions. - - The processor itineraries are copied from a different backend - and need to be updated to model the MicroBlaze correctly. - Look at the MBlazeGenFastISel.inc stuff and make use of it if appropriate. @@ -18,9 +16,6 @@ There are a few things that need to be looked at: - There are some instructions that are not generated by the backend and have not been tested as far as the parser is concerned. - - The assembly parser does not use any MicroBlaze specific directives. + - The assembly parser does not use many MicroBlaze specific directives. I should investigate if there are MicroBlaze specific directive and, if there are, add them. - - The instruction MFS and MTS use special names for some of the - special registers that can be accessed. These special register - names should be parsed by the assembly parser. Modified: llvm/trunk/test/CodeGen/MBlaze/fsl.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MBlaze/fsl.ll?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/MBlaze/fsl.ll (original) +++ llvm/trunk/test/CodeGen/MBlaze/fsl.ll Mon Apr 11 17:31:52 2011 @@ -3,7 +3,7 @@ ; dynamic version of the instructions and that constant values use the ; constant version of the instructions. ; -; RUN: llc < %s -march=mblaze | FileCheck %s +; RUN: llc -O3 < %s -march=mblaze | FileCheck %s declare i32 @llvm.mblaze.fsl.get(i32 %port) declare i32 @llvm.mblaze.fsl.aget(i32 %port) @@ -55,8 +55,7 @@ declare void @llvm.mblaze.fsl.tncput(i32 %port) declare void @llvm.mblaze.fsl.tncaput(i32 %port) -define i32 @fsl_get(i32 %port) -{ +define void @fsl_get(i32 %port) { ; CHECK: fsl_get: %v0 = call i32 @llvm.mblaze.fsl.get(i32 %port) ; CHECK: getd @@ -122,12 +121,11 @@ ; CHECK-NEXT: tnecgetd %v31 = call i32 @llvm.mblaze.fsl.tnecaget(i32 %port) ; CHECK-NEXT: tnecagetd - ret i32 1 + ret void ; CHECK: rtsd } -define i32 @fslc_get() -{ +define void @fslc_get() { ; CHECK: fslc_get: %v0 = call i32 @llvm.mblaze.fsl.get(i32 1) ; CHECK: get @@ -224,12 +222,11 @@ %v31 = call i32 @llvm.mblaze.fsl.tnecaget(i32 1) ; CHECK-NOT: tnecagetd ; CHECK: tnecaget - ret i32 1 + ret void ; CHECK: rtsd } -define void @putfsl(i32 %value, i32 %port) -{ +define void @putfsl(i32 %value, i32 %port) { ; CHECK: putfsl: call void @llvm.mblaze.fsl.put(i32 %value, i32 %port) ; CHECK: putd @@ -267,8 +264,7 @@ ; CHECK: rtsd } -define void @putfsl_const(i32 %value) -{ +define void @putfsl_const(i32 %value) { ; CHECK: putfsl_const: call void @llvm.mblaze.fsl.put(i32 %value, i32 1) ; CHECK-NOT: putd Modified: llvm/trunk/test/CodeGen/MBlaze/loop.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/MBlaze/loop.ll?rev=129311&r1=129310&r2=129311&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/MBlaze/loop.ll (original) +++ llvm/trunk/test/CodeGen/MBlaze/loop.ll Mon Apr 11 17:31:52 2011 @@ -29,14 +29,12 @@ %inner.5 = add i32 %inner.2, 1 call i32 (i8*,...)* @printf( i8* getelementptr([19 x i8]* @MSG,i32 0,i32 0), i32 %inner.0, i32 %inner.1, i32 %inner.2 ) - ; CHECK: brlid - ; CHECK: addik {{.*, 1}} %inner.6 = icmp eq i32 %inner.5, 100 - ; CHECK: cmp + ; CHECK: cmp [[REG:r[0-9]*]] br i1 %inner.6, label %loop_inner, label %loop_outer_finish - ; CHECK: {{beq|bne}} + ; CHECK: {{beqid|bneid}} [[REG]] loop_outer_finish: %outer.1 = add i32 %outer.0, 1 From daniel at zuster.org Mon Apr 11 17:37:39 2011 From: daniel at zuster.org (Daniel Dunbar) Date: Mon, 11 Apr 2011 22:37:39 -0000 Subject: [llvm-commits] [llvm] r129312 - in /llvm/trunk: Makefile Makefile.rules utils/show-diagnostics Message-ID: <20110411223739.4C9492A6C12D@llvm.org> Author: ddunbar Date: Mon Apr 11 17:37:39 2011 New Revision: 129312 URL: http://llvm.org/viewvc/llvm-project?rev=129312&view=rev Log: build: Add support for a SHOW_DIAGNOSTICS build variable. If enabled, this will attempt to use the CC_LOG_DIAGNOSTICS feature I dropped into Clang to print a log of all the diagnostics generated during an individual build (from the top-level). Not sure if this will actually be useful, but for now it is handy for testing the option. Added: llvm/trunk/utils/show-diagnostics (with props) Modified: llvm/trunk/Makefile llvm/trunk/Makefile.rules Modified: llvm/trunk/Makefile URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/Makefile?rev=129312&r1=129311&r2=129312&view=diff ============================================================================== --- llvm/trunk/Makefile (original) +++ llvm/trunk/Makefile Mon Apr 11 17:37:39 2011 @@ -168,6 +168,15 @@ install-clang-c: install install-libs: install +# If SHOW_DIAGNOSTICS is enabled, clear the diagnostics file first. +ifeq ($(SHOW_DIAGNOSTICS),1) +clean-diagnostics: + $(Verb) rm -f $(LLVM_OBJ_ROOT)/$(BuildMode)/diags +.PHONY: clean-diagnostics + +all-local:: clean-diagnostics +endif + #------------------------------------------------------------------------ # Make sure the generated headers are up-to-date. This must be kept in # sync with the AC_CONFIG_HEADER invocations in autoconf/configure.ac @@ -198,6 +207,12 @@ $(Echo) '*****' optimized build. Use 'make ENABLE_OPTIMIZED=1' to $(Echo) '*****' make an optimized build. Alternatively you can $(Echo) '*****' configure with --enable-optimized. +ifeq ($(SHOW_DIAGNOSTICS),1) + $(Verb) if test -s $(LLVM_OBJ_ROOT)/$(BuildMode)/diags; then \ + $(LLVM_SRC_ROOT)/utils/show-diagnostics \ + $(LLVM_OBJ_ROOT)/$(BuildMode)/diags; \ + fi +endif endif endif Modified: llvm/trunk/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/Makefile.rules?rev=129312&r1=129311&r2=129312&view=diff ============================================================================== --- llvm/trunk/Makefile.rules (original) +++ llvm/trunk/Makefile.rules Mon Apr 11 17:37:39 2011 @@ -646,25 +646,41 @@ $(LLVM_OBJ_ROOT) $(LLVM_SRC_ROOT))) \ $(CPP.BaseFlags) +# SHOW_DIAGNOSTICS support. +ifeq ($(SHOW_DIAGNOSTICS),1) + Compile.Wrapper := env CC_LOG_DIAGNOSTICS=1 \ + CC_LOG_DIAGNOSTICS_FILE="$(LLVM_OBJ_ROOT)/$(BuildMode)/diags" +else + Compile.Wrapper := +endif + ifeq ($(BUILD_COMPONENT), 1) - Compile.C = $(BUILD_CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + Compile.C = $(Compile.Wrapper) \ + $(BUILD_CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) -c - Compile.CXX = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ + Compile.CXX = $(Compile.Wrapper) \ + $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ $(CPPFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) -c - Preprocess.CXX= $(BUILD_CXX) $(CPP.Flags) $(CPPFLAGS) $(TargetCommonOpts) \ + Preprocess.CXX= $(Compile.Wrapper) \ + $(BUILD_CXX) $(CPP.Flags) $(CPPFLAGS) $(TargetCommonOpts) \ $(CompileCommonOpts) $(CXX.Flags) -E - Link = $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ + Link = $(Compile.Wrapper) \ + $(BUILD_CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) \ $(LD.Flags) $(LDFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) $(Strip) else - Compile.C = $(CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ + Compile.C = $(Compile.Wrapper) \ + $(CC) $(CPP.Flags) $(C.Flags) $(CFLAGS) $(CPPFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) -c - Compile.CXX = $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ + Compile.CXX = $(Compile.Wrapper) \ + $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(CPPFLAGS) \ $(TargetCommonOpts) $(CompileCommonOpts) -c - Preprocess.CXX= $(CXX) $(CPP.Flags) $(TargetCommonOpts) $(CPPFLAGS) \ + Preprocess.CXX= $(Compile.Wrapper) \ + $(CXX) $(CPP.Flags) $(TargetCommonOpts) $(CPPFLAGS) \ $(CompileCommonOpts) $(CXX.Flags) -E - Link = $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(LD.Flags) \ + Link = $(Compile.Wrapper) \ + $(CXX) $(CPP.Flags) $(CXX.Flags) $(CXXFLAGS) $(LD.Flags) \ $(LDFLAGS) $(TargetCommonOpts) $(CompileCommonOpts) $(Strip) endif Added: llvm/trunk/utils/show-diagnostics URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/show-diagnostics?rev=129312&view=auto ============================================================================== --- llvm/trunk/utils/show-diagnostics (added) +++ llvm/trunk/utils/show-diagnostics Mon Apr 11 17:37:39 2011 @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +import plistlib + +def main(): + from optparse import OptionParser, OptionGroup + parser = OptionParser("""\ +usage: %prog [options] + +Utility for dumping Clang-style logged diagnostics.\ +""") + (opts, args) = parser.parse_args() + + if len(args) != 1: + parser.error("invalid number of arguments") + + path, = args + + # Read the diagnostics log. + f = open(path) + try: + data = f.read() + finally: + f.close() + + # Complete the plist (the log itself is just the chunks). + data = """\ + + + + +%s + +""" % data + + # Load the diagnostics. + diags = plistlib.readPlistFromString(data) + + # Print out the diagnostics. + print + print "**** BUILD DIAGNOSTICS ****" + for i, file_diags in enumerate(diags): + file = file_diags.get('main-file') + print "*** %s ***" % file + for d in file_diags.get('diagnostics', ()): + print "%s:%s:%s: %s: %s" % ( + d.get('filename'), d.get('line'), d.get('column'), + d.get('level'), d.get('message')) + +if __name__ == "__main__": + main() Propchange: llvm/trunk/utils/show-diagnostics ------------------------------------------------------------------------------ svn:executable = * From peckw at wesleypeck.com Mon Apr 11 17:45:02 2011 From: peckw at wesleypeck.com (Wesley Peck) Date: Mon, 11 Apr 2011 22:45:02 -0000 Subject: [llvm-commits] [llvm] r129313 - /llvm/trunk/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp Message-ID: <20110411224502.9FFF72A6C12D@llvm.org> Author: peckw Date: Mon Apr 11 17:45:02 2011 New Revision: 129313 URL: http://llvm.org/viewvc/llvm-project?rev=129313&view=rev Log: Fix an error in the MBlaze delay slot filler. Modified: llvm/trunk/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp Modified: llvm/trunk/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp?rev=129313&r1=129312&r2=129313&view=diff ============================================================================== --- llvm/trunk/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp (original) +++ llvm/trunk/lib/Target/MBlaze/MBlazeDelaySlotFiller.cpp Mon Apr 11 17:45:02 2011 @@ -77,7 +77,7 @@ // We must assume that unknown immediate values require more than // 16-bits to represent. - if (mop.isGlobal() || mop.isSymbol()) + if (mop.isGlobal() || mop.isSymbol() || mop.isJTI() || mop.isCPI()) return true; // FIXME: we could probably check to see if the FP value happens From sabre at nondot.org Mon Apr 11 18:09:44 2011 From: sabre at nondot.org (Chris Lattner) Date: Mon, 11 Apr 2011 23:09:44 -0000 Subject: [llvm-commits] [llvm] r129314 - in /llvm/trunk: include/llvm/InitializePasses.h include/llvm/LinkAllPasses.h include/llvm/Transforms/IPO.h lib/Transforms/IPO/CMakeLists.txt lib/Transforms/IPO/IPO.cpp lib/Transforms/IPO/StructRetPromotion.cpp test/Transforms/SRETPromotion/ Message-ID: <20110411230944.9D0252A6C12D@llvm.org> Author: lattner Date: Mon Apr 11 18:09:44 2011 New Revision: 129314 URL: http://llvm.org/viewvc/llvm-project?rev=129314&view=rev Log: remove the StructRetPromotion pass. It is unused, not maintained and has some bugs. If this is interesting functionality, it should be reimplemented in the argpromotion pass. Removed: llvm/trunk/lib/Transforms/IPO/StructRetPromotion.cpp llvm/trunk/test/Transforms/SRETPromotion/ Modified: llvm/trunk/include/llvm/InitializePasses.h llvm/trunk/include/llvm/LinkAllPasses.h llvm/trunk/include/llvm/Transforms/IPO.h llvm/trunk/lib/Transforms/IPO/CMakeLists.txt llvm/trunk/lib/Transforms/IPO/IPO.cpp Modified: llvm/trunk/include/llvm/InitializePasses.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=129314&r1=129313&r2=129314&view=diff ============================================================================== --- llvm/trunk/include/llvm/InitializePasses.h (original) +++ llvm/trunk/include/llvm/InitializePasses.h Mon Apr 11 18:09:44 2011 @@ -193,7 +193,6 @@ void initializeRegisterCoalescerAnalysisGroup(PassRegistry&); void initializeRenderMachineFunctionPass(PassRegistry&); void initializeSCCPPass(PassRegistry&); -void initializeSRETPromotionPass(PassRegistry&); void initializeSROA_DTPass(PassRegistry&); void initializeSROA_SSAUpPass(PassRegistry&); void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); Modified: llvm/trunk/include/llvm/LinkAllPasses.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=129314&r1=129313&r2=129314&view=diff ============================================================================== --- llvm/trunk/include/llvm/LinkAllPasses.h (original) +++ llvm/trunk/include/llvm/LinkAllPasses.h Mon Apr 11 18:09:44 2011 @@ -49,7 +49,6 @@ (void) llvm::createAliasAnalysisCounterPass(); (void) llvm::createAliasDebugger(); (void) llvm::createArgumentPromotionPass(); - (void) llvm::createStructRetPromotionPass(); (void) llvm::createBasicAliasAnalysisPass(); (void) llvm::createLibCallAliasAnalysisPass(0); (void) llvm::createScalarEvolutionAliasAnalysisPass(); Modified: llvm/trunk/include/llvm/Transforms/IPO.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/IPO.h?rev=129314&r1=129313&r2=129314&view=diff ============================================================================== --- llvm/trunk/include/llvm/Transforms/IPO.h (original) +++ llvm/trunk/include/llvm/Transforms/IPO.h Mon Apr 11 18:09:44 2011 @@ -152,7 +152,6 @@ /// equal to maxElements (maxElements == 0 means always promote). /// Pass *createArgumentPromotionPass(unsigned maxElements = 3); -Pass *createStructRetPromotionPass(); //===----------------------------------------------------------------------===// /// createIPConstantPropagationPass - This pass propagates constants from call Modified: llvm/trunk/lib/Transforms/IPO/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/CMakeLists.txt?rev=129314&r1=129313&r2=129314&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/CMakeLists.txt (original) +++ llvm/trunk/lib/Transforms/IPO/CMakeLists.txt Mon Apr 11 18:09:44 2011 @@ -20,5 +20,4 @@ PruneEH.cpp StripDeadPrototypes.cpp StripSymbols.cpp - StructRetPromotion.cpp ) Modified: llvm/trunk/lib/Transforms/IPO/IPO.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/IPO.cpp?rev=129314&r1=129313&r2=129314&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/IPO.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/IPO.cpp Mon Apr 11 18:09:44 2011 @@ -45,7 +45,6 @@ initializeStripDebugDeclarePass(Registry); initializeStripDeadDebugInfoPass(Registry); initializeStripNonDebugSymbolsPass(Registry); - initializeSRETPromotionPass(Registry); } void LLVMInitializeIPO(LLVMPassRegistryRef R) { Removed: llvm/trunk/lib/Transforms/IPO/StructRetPromotion.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/StructRetPromotion.cpp?rev=129313&view=auto ============================================================================== --- llvm/trunk/lib/Transforms/IPO/StructRetPromotion.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/StructRetPromotion.cpp (removed) @@ -1,357 +0,0 @@ -//===-- StructRetPromotion.cpp - Promote sret arguments -------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass finds functions that return a struct (using a pointer to the struct -// as the first argument of the function, marked with the 'sret' attribute) and -// replaces them with a new function that simply returns each of the elements of -// that struct (using multiple return values). -// -// This pass works under a number of conditions: -// 1. The returned struct must not contain other structs -// 2. The returned struct must only be used to load values from -// 3. The placeholder struct passed in is the result of an alloca -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "sretpromotion" -#include "llvm/Transforms/IPO.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/CallGraphSCCPass.h" -#include "llvm/Instructions.h" -#include "llvm/Analysis/CallGraph.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/CFG.h" -#include "llvm/Support/Debug.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/Support/raw_ostream.h" -using namespace llvm; - -STATISTIC(NumRejectedSRETUses , "Number of sret rejected due to unexpected uses"); -STATISTIC(NumSRET , "Number of sret promoted"); -namespace { - /// SRETPromotion - This pass removes sret parameter and updates - /// function to use multiple return value. - /// - struct SRETPromotion : public CallGraphSCCPass { - virtual void getAnalysisUsage(AnalysisUsage &AU) const { - CallGraphSCCPass::getAnalysisUsage(AU); - } - - virtual bool runOnSCC(CallGraphSCC &SCC); - static char ID; // Pass identification, replacement for typeid - SRETPromotion() : CallGraphSCCPass(ID) { - initializeSRETPromotionPass(*PassRegistry::getPassRegistry()); - } - - private: - CallGraphNode *PromoteReturn(CallGraphNode *CGN); - bool isSafeToUpdateAllCallers(Function *F); - Function *cloneFunctionBody(Function *F, const StructType *STy); - CallGraphNode *updateCallSites(Function *F, Function *NF); - }; -} - -char SRETPromotion::ID = 0; -INITIALIZE_PASS_BEGIN(SRETPromotion, "sretpromotion", - "Promote sret arguments to multiple ret values", false, false) -INITIALIZE_AG_DEPENDENCY(CallGraph) -INITIALIZE_PASS_END(SRETPromotion, "sretpromotion", - "Promote sret arguments to multiple ret values", false, false) - -Pass *llvm::createStructRetPromotionPass() { - return new SRETPromotion(); -} - -bool SRETPromotion::runOnSCC(CallGraphSCC &SCC) { - bool Changed = false; - - for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) - if (CallGraphNode *NewNode = PromoteReturn(*I)) { - SCC.ReplaceNode(*I, NewNode); - Changed = true; - } - - return Changed; -} - -/// PromoteReturn - This method promotes function that uses StructRet paramater -/// into a function that uses multiple return values. -CallGraphNode *SRETPromotion::PromoteReturn(CallGraphNode *CGN) { - Function *F = CGN->getFunction(); - - if (!F || F->isDeclaration() || !F->hasLocalLinkage()) - return 0; - - // Make sure that function returns struct. - if (F->arg_size() == 0 || !F->hasStructRetAttr() || F->doesNotReturn()) - return 0; - - DEBUG(dbgs() << "SretPromotion: Looking at sret function " - << F->getName() << "\n"); - - assert(F->getReturnType()->isVoidTy() && "Invalid function return type"); - Function::arg_iterator AI = F->arg_begin(); - const llvm::PointerType *FArgType = dyn_cast(AI->getType()); - assert(FArgType && "Invalid sret parameter type"); - const llvm::StructType *STy = - dyn_cast(FArgType->getElementType()); - assert(STy && "Invalid sret parameter element type"); - - // Check if it is ok to perform this promotion. - if (isSafeToUpdateAllCallers(F) == false) { - DEBUG(dbgs() << "SretPromotion: Not all callers can be updated\n"); - ++NumRejectedSRETUses; - return 0; - } - - DEBUG(dbgs() << "SretPromotion: sret argument will be promoted\n"); - ++NumSRET; - // [1] Replace use of sret parameter - AllocaInst *TheAlloca = new AllocaInst(STy, NULL, "mrv", - F->getEntryBlock().begin()); - Value *NFirstArg = F->arg_begin(); - NFirstArg->replaceAllUsesWith(TheAlloca); - - // [2] Find and replace ret instructions - for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) - for(BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) { - Instruction *I = BI; - ++BI; - if (isa(I)) { - Value *NV = new LoadInst(TheAlloca, "mrv.ld", I); - ReturnInst *NR = ReturnInst::Create(F->getContext(), NV, I); - I->replaceAllUsesWith(NR); - I->eraseFromParent(); - } - } - - // [3] Create the new function body and insert it into the module. - Function *NF = cloneFunctionBody(F, STy); - - // [4] Update all call sites to use new function - CallGraphNode *NF_CFN = updateCallSites(F, NF); - - CallGraph &CG = getAnalysis(); - NF_CFN->stealCalledFunctionsFrom(CG[F]); - - delete CG.removeFunctionFromModule(F); - return NF_CFN; -} - -// Check if it is ok to perform this promotion. -bool SRETPromotion::isSafeToUpdateAllCallers(Function *F) { - - if (F->use_empty()) - // No users. OK to modify signature. - return true; - - for (Value::use_iterator FnUseI = F->use_begin(), FnUseE = F->use_end(); - FnUseI != FnUseE; ++FnUseI) { - // The function is passed in as an argument to (possibly) another function, - // we can't change it! - CallSite CS(*FnUseI); - Instruction *Call = CS.getInstruction(); - // The function is used by something else than a call or invoke instruction, - // we can't change it! - if (!Call || !CS.isCallee(FnUseI)) - return false; - CallSite::arg_iterator AI = CS.arg_begin(); - Value *FirstArg = *AI; - - if (!isa(FirstArg)) - return false; - - // Check FirstArg's users. - for (Value::use_iterator ArgI = FirstArg->use_begin(), - ArgE = FirstArg->use_end(); ArgI != ArgE; ++ArgI) { - User *U = *ArgI; - // If FirstArg user is a CallInst that does not correspond to current - // call site then this function F is not suitable for sret promotion. - if (CallInst *CI = dyn_cast(U)) { - if (CI != Call) - return false; - } - // If FirstArg user is a GEP whose all users are not LoadInst then - // this function F is not suitable for sret promotion. - else if (GetElementPtrInst *GEP = dyn_cast(U)) { - // TODO : Use dom info and insert PHINodes to collect get results - // from multiple call sites for this GEP. - if (GEP->getParent() != Call->getParent()) - return false; - for (Value::use_iterator GEPI = GEP->use_begin(), GEPE = GEP->use_end(); - GEPI != GEPE; ++GEPI) - if (!isa(*GEPI)) - return false; - } - // Any other FirstArg users make this function unsuitable for sret - // promotion. - else - return false; - } - } - - return true; -} - -/// cloneFunctionBody - Create a new function based on F and -/// insert it into module. Remove first argument. Use STy as -/// the return type for new function. -Function *SRETPromotion::cloneFunctionBody(Function *F, - const StructType *STy) { - - const FunctionType *FTy = F->getFunctionType(); - std::vector Params; - - // Attributes - Keep track of the parameter attributes for the arguments. - SmallVector AttributesVec; - const AttrListPtr &PAL = F->getAttributes(); - - // Add any return attributes. - if (Attributes attrs = PAL.getRetAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); - - // Skip first argument. - Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); - ++I; - // 0th parameter attribute is reserved for return type. - // 1th parameter attribute is for first 1st sret argument. - unsigned ParamIndex = 2; - while (I != E) { - Params.push_back(I->getType()); - if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) - AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); - ++I; - ++ParamIndex; - } - - // Add any fn attributes. - if (Attributes attrs = PAL.getFnAttributes()) - AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); - - - FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg()); - Function *NF = Function::Create(NFTy, F->getLinkage()); - NF->takeName(F); - NF->copyAttributesFrom(F); - NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); - F->getParent()->getFunctionList().insert(F, NF); - NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); - - // Replace arguments - I = F->arg_begin(); - E = F->arg_end(); - Function::arg_iterator NI = NF->arg_begin(); - ++I; - while (I != E) { - I->replaceAllUsesWith(NI); - NI->takeName(I); - ++I; - ++NI; - } - - return NF; -} - -/// updateCallSites - Update all sites that call F to use NF. -CallGraphNode *SRETPromotion::updateCallSites(Function *F, Function *NF) { - CallGraph &CG = getAnalysis(); - SmallVector Args; - - // Attributes - Keep track of the parameter attributes for the arguments. - SmallVector ArgAttrsVec; - - // Get a new callgraph node for NF. - CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF); - - while (!F->use_empty()) { - CallSite CS(*F->use_begin()); - Instruction *Call = CS.getInstruction(); - - const AttrListPtr &PAL = F->getAttributes(); - // Add any return attributes. - if (Attributes attrs = PAL.getRetAttributes()) - ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs)); - - // Copy arguments, however skip first one. - CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); - Value *FirstCArg = *AI; - ++AI; - // 0th parameter attribute is reserved for return type. - // 1th parameter attribute is for first 1st sret argument. - unsigned ParamIndex = 2; - while (AI != AE) { - Args.push_back(*AI); - if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) - ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); - ++ParamIndex; - ++AI; - } - - // Add any function attributes. - if (Attributes attrs = PAL.getFnAttributes()) - ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs)); - - AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end()); - - // Build new call instruction. - Instruction *New; - if (InvokeInst *II = dyn_cast(Call)) { - New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), - Args.begin(), Args.end(), "", Call); - cast(New)->setCallingConv(CS.getCallingConv()); - cast(New)->setAttributes(NewPAL); - } else { - New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); - cast(New)->setCallingConv(CS.getCallingConv()); - cast(New)->setAttributes(NewPAL); - if (cast(Call)->isTailCall()) - cast(New)->setTailCall(); - } - Args.clear(); - ArgAttrsVec.clear(); - New->takeName(Call); - - // Update the callgraph to know that the callsite has been transformed. - CallGraphNode *CalleeNode = CG[Call->getParent()->getParent()]; - CalleeNode->removeCallEdgeFor(Call); - CalleeNode->addCalledFunction(New, NF_CGN); - - // Update all users of sret parameter to extract value using extractvalue. - for (Value::use_iterator UI = FirstCArg->use_begin(), - UE = FirstCArg->use_end(); UI != UE; ) { - User *U2 = *UI++; - CallInst *C2 = dyn_cast(U2); - if (C2 && (C2 == Call)) - continue; - - GetElementPtrInst *UGEP = cast(U2); - ConstantInt *Idx = cast(UGEP->getOperand(2)); - Value *GR = ExtractValueInst::Create(New, Idx->getZExtValue(), - "evi", UGEP); - while(!UGEP->use_empty()) { - // isSafeToUpdateAllCallers has checked that all GEP uses are - // LoadInsts - LoadInst *L = cast(*UGEP->use_begin()); - L->replaceAllUsesWith(GR); - L->eraseFromParent(); - } - UGEP->eraseFromParent(); - continue; - } - Call->eraseFromParent(); - } - - return NF_CGN; -} - From geek4civic at gmail.com Mon Apr 11 18:20:28 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Mon, 11 Apr 2011 23:20:28 -0000 Subject: [llvm-commits] [llvm] r129317 - /llvm/trunk/utils/TableGen/ClangASTNodesEmitter.cpp Message-ID: <20110411232028.95CCB2A6C12D@llvm.org> Author: chapuni Date: Mon Apr 11 18:20:28 2011 New Revision: 129317 URL: http://llvm.org/viewvc/llvm-project?rev=129317&view=rev Log: TableGen: Keep the order of DECL_CONTEXT() for DeclNodes.td. RecordVector may be used instead of RecordSet. The result of DeclNodes.inc was unstable on msys, Windows 7 x64. Modified: llvm/trunk/utils/TableGen/ClangASTNodesEmitter.cpp Modified: llvm/trunk/utils/TableGen/ClangASTNodesEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/ClangASTNodesEmitter.cpp?rev=129317&r1=129316&r2=129317&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/ClangASTNodesEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/ClangASTNodesEmitter.cpp Mon Apr 11 18:20:28 2011 @@ -155,10 +155,13 @@ } } - for (RecordSet::iterator i = DeclContexts.begin(), e = DeclContexts.end(); - i != e; ++i) { - OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; - } + // To keep identical order, RecordVector may be used + // instead of RecordSet. + for (RecordVector::iterator + i = DeclContextsVector.begin(), e = DeclContextsVector.end(); + i != e; ++i) + if (DeclContexts.find(*i) != DeclContexts.end()) + OS << "DECL_CONTEXT(" << (*i)->getName() << ")\n"; OS << "#undef DECL_CONTEXT\n"; OS << "#undef DECL_CONTEXT_BASE\n"; From geek4civic at gmail.com Mon Apr 11 18:26:04 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Tue, 12 Apr 2011 08:26:04 +0900 Subject: [llvm-commits] [cfe-commits] [PATCH] TableGen: Keep the order of DECL_CONTEXT() for DeclNodes.td. RecordVector may be used instead of RecordSet. In-Reply-To: <53FC1430-3871-4A0B-9570-87064C1227C7@apple.com> References: <53FC1430-3871-4A0B-9570-87064C1227C7@apple.com> Message-ID: Committed in r129317 with a small reformat, thank you! ...Takumi On Tue, Apr 12, 2011 at 1:19 AM, Chris Lattner wrote: > > On Apr 11, 2011, at 2:33 AM, NAKAMURA Takumi wrote: > >> --- >> utils/TableGen/ClangASTNodesEmitter.cpp | ? 12 ++++++++---- >> 1 files changed, 8 insertions(+), 4 deletions(-) >> >> --- >> The result of DeclNodes.inc was unstable on msys, Windows 7 x64. > > Nice catch. ?Please apply, but put as much of the "for ()" on a single line as will fit, instead of breaking it over several lines. ?Thanks! > > -Chris From sabre at nondot.org Mon Apr 11 18:24:57 2011 From: sabre at nondot.org (Chris Lattner) Date: Mon, 11 Apr 2011 23:24:57 -0000 Subject: [llvm-commits] [llvm] r129319 - /llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Message-ID: <20110411232457.3FB1E2A6C12D@llvm.org> Author: lattner Date: Mon Apr 11 18:24:57 2011 New Revision: 129319 URL: http://llvm.org/viewvc/llvm-project?rev=129319&view=rev Log: comment cleanup, use moveBefore instead of removeFromParent+insertBefore. Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=129319&r1=129318&r2=129319&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Mon Apr 11 18:24:57 2011 @@ -1401,10 +1401,9 @@ return true; } -/// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch, -/// and if a predecessor branches to us and one of our successors, fold the -/// setcc into the predecessor and use logical operations to pick the right -/// destination. +/// FoldBranchToCommonDest - If this basic block is simple enough, and if a +/// predecessor branches to us and one of our successors, fold the block into +/// the predecessor and use logical operations to pick the right destination. bool llvm::FoldBranchToCommonDest(BranchInst *BI) { BasicBlock *BB = BI->getParent(); Instruction *Cond = dyn_cast(BI->getCondition()); @@ -1588,11 +1587,8 @@ // Move dbg value intrinsics in PredBlock. for (SmallVector::iterator DBI = DbgValues.begin(), - DBE = DbgValues.end(); DBI != DBE; ++DBI) { - DbgInfoIntrinsic *DB = *DBI; - DB->removeFromParent(); - DB->insertBefore(PBI); - } + DBE = DbgValues.end(); DBI != DBE; ++DBI) + (*DBI)->moveBefore(PBI); return true; } return false; From johnny.chen at apple.com Mon Apr 11 18:33:30 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Mon, 11 Apr 2011 23:33:30 -0000 Subject: [llvm-commits] [llvm] r129320 - in /llvm/trunk: lib/Target/ARM/ARMInstrThumb.td lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/thumb-tests.txt utils/TableGen/ARMDecoderEmitter.cpp Message-ID: <20110411233330.DA6D92A6C12D@llvm.org> Author: johnny Date: Mon Apr 11 18:33:30 2011 New Revision: 129320 URL: http://llvm.org/viewvc/llvm-project?rev=129320&view=rev Log: Thumb disassembler was erroneously rejecting "blx sp" instruction. rdar://problem/9267838 Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt llvm/trunk/utils/TableGen/ARMDecoderEmitter.cpp Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=129320&r1=129319&r2=129320&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Mon Apr 11 18:33:30 2011 @@ -369,6 +369,15 @@ let Inst{2-0} = 0b000; } + def tBX_Rm : TI<(outs), (ins pred:$p, GPR:$Rm), IIC_Br, "bx${p}\t$Rm", + [/* for disassembly only */]>, + T1Special<{1,1,0,?}> { + // A6.2.3 & A8.6.25 + bits<4> Rm; + let Inst{6-3} = Rm; + let Inst{2-0} = 0b000; + } + // Alternative return instruction used by vararg functions. def tBX_RET_vararg : TI<(outs), (ins tGPR:$Rm), IIC_Br, "bx\t$Rm", Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129320&r1=129319&r2=129320&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Mon Apr 11 18:33:30 2011 @@ -485,10 +485,13 @@ return true; // BX/BLX has 1 reg operand: Rm. - if (NumOps == 1) { + if (Opcode == ARM::tBLXr_r9 || Opcode == ARM::tBX_Rm) { + // Handling the two predicate operands before the reg operand. + if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps)) + return false; MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, getT1Rm(insn)))); - NumOpsAdded = 1; + NumOpsAdded = 3; return true; } Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129320&r1=129319&r2=129320&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Mon Apr 11 18:33:30 2011 @@ -214,3 +214,12 @@ # CHECK: lsr.w r10, r0, #32 0x4f 0xea 0x10 0x0a + +# CHECK: blx sp +0xe8 0x47 + +# CHECK: bx lr +0x70 0x47 + +# CHECK: bx pc +0x78 0x47 Modified: llvm/trunk/utils/TableGen/ARMDecoderEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/ARMDecoderEmitter.cpp?rev=129320&r1=129319&r2=129320&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/ARMDecoderEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/ARMDecoderEmitter.cpp Mon Apr 11 18:33:30 2011 @@ -1624,6 +1624,10 @@ if (Name == "tBL" || Name == "tBLXi" || Name == "tBLXr") return false; + // A8.6.25 BX. Use the generic tBX_Rm, ignore tBX_RET and tBX_RET_vararg. + if (Name == "tBX_RET" || Name == "tBX_RET_vararg") + return false; + // Ignore the TPsoft (TLS) instructions, which conflict with tBLr9. if (Name == "tTPsoft" || Name == "t2TPsoft") return false; From stoklund at 2pi.dk Mon Apr 11 18:44:14 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 16:44:14 -0700 Subject: [llvm-commits] Source register same as write-back base In-Reply-To: <12BD8D01-BDE4-4E21-8608-A24EFF90A48C@apple.com> References: <88D727341410A44C9E34E8E3EF37D8ED04213C3E@be25.exg3.exghost.com> <12BD8D01-BDE4-4E21-8608-A24EFF90A48C@apple.com> Message-ID: On Apr 11, 2011, at 2:27 PM, Johnny Chen wrote: > Hi Joe, > > I've CCed llvm-commit. Hopefully the backend folks can help you out! > Thanks. > > On Apr 11, 2011, at 2:20 PM, Joe Abbey wrote: > >> Johnny, >> >> I saw your changelist which adds a check to the disassembly of ARM instructions. >> >> I?m currently trying to debug how the register allocation works to produce: >> >> str r3, [r3], #4 >> >> My assembler is complaining that: >> >> libtest-libstl.so.bc:46025: Warning: source register same as write-back base >> >> And it should because as you (and ARM) note, this is UNPREDICTABLE. Is this the same situation as the armV5 MUL instructions where the documents say it is unpredictable, but all existing hardware implementations behave correctly? Which architecture revisions have this constraint? /jakob From stoklund at 2pi.dk Mon Apr 11 18:57:14 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 11 Apr 2011 23:57:14 -0000 Subject: [llvm-commits] [llvm] r129321 - in /llvm/trunk/lib/CodeGen: LiveIntervalUnion.h RegAllocBasic.cpp Message-ID: <20110411235714.DD3332A6C12D@llvm.org> Author: stoklund Date: Mon Apr 11 18:57:14 2011 New Revision: 129321 URL: http://llvm.org/viewvc/llvm-project?rev=129321&view=rev Log: Reuse live interval union between functions. This saves a bit of compile time when compiling many small functions. Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.h llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Modified: llvm/trunk/lib/CodeGen/LiveIntervalUnion.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveIntervalUnion.h?rev=129321&r1=129320&r2=129321&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveIntervalUnion.h (original) +++ llvm/trunk/lib/CodeGen/LiveIntervalUnion.h Mon Apr 11 18:57:14 2011 @@ -95,6 +95,9 @@ // Remove a live virtual register's segments from this union. void extract(LiveInterval &VirtReg); + // Remove all inserted virtual registers. + void clear() { Segments.clear(); ++Tag; } + // Print union, using TRI to translate register names void print(raw_ostream &OS, const TargetRegisterInfo *TRI) const; Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocBasic.cpp?rev=129321&r1=129320&r2=129321&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocBasic.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Mon Apr 11 18:57:14 2011 @@ -235,9 +235,12 @@ MRI = &vrm.getRegInfo(); VRM = &vrm; LIS = &lis; - PhysReg2LiveUnion.init(UnionAllocator, TRI->getNumRegs()); - // Cache an interferece query for each physical reg - Queries.reset(new LiveIntervalUnion::Query[PhysReg2LiveUnion.numRegs()]); + const unsigned NumRegs = TRI->getNumRegs(); + if (NumRegs != PhysReg2LiveUnion.numRegs()) { + PhysReg2LiveUnion.init(UnionAllocator, NumRegs); + // Cache an interferece query for each physical reg + Queries.reset(new LiveIntervalUnion::Query[PhysReg2LiveUnion.numRegs()]); + } } void RegAllocBase::LiveUnionArray::clear() { @@ -251,7 +254,8 @@ } void RegAllocBase::releaseMemory() { - PhysReg2LiveUnion.clear(); + for (unsigned r = 0, e = PhysReg2LiveUnion.numRegs(); r != e; ++r) + PhysReg2LiveUnion[r].clear(); } // Visit all the live registers. If they are already assigned to a physical From echristo at apple.com Mon Apr 11 19:03:14 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 12 Apr 2011 00:03:14 -0000 Subject: [llvm-commits] [llvm] r129322 - /llvm/trunk/lib/MC/MCParser/AsmParser.cpp Message-ID: <20110412000314.104072A6C12D@llvm.org> Author: echristo Date: Mon Apr 11 19:03:13 2011 New Revision: 129322 URL: http://llvm.org/viewvc/llvm-project?rev=129322&view=rev Log: To avoid printing out multiple error messages for cases like: .long 80+08 go ahead and assume that if we've got an Error token that we handled it already. Otherwise if it's a token we can't handle then go ahead and return the default error. Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=129322&r1=129321&r2=129322&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Mon Apr 11 19:03:13 2011 @@ -539,6 +539,9 @@ switch (Lexer.getKind()) { default: return TokError("unknown token in expression"); + // If we have an error assume that we've already handled it. + case AsmToken::Error: + return true; case AsmToken::Exclaim: Lex(); // Eat the operator. if (ParsePrimaryExpr(Res, EndLoc)) From echristo at apple.com Mon Apr 11 19:03:38 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 12 Apr 2011 00:03:38 -0000 Subject: [llvm-commits] [llvm] r129323 - /llvm/trunk/test/MC/AsmParser/exprs-invalid.s Message-ID: <20110412000338.434BE2A6C12D@llvm.org> Author: echristo Date: Mon Apr 11 19:03:38 2011 New Revision: 129323 URL: http://llvm.org/viewvc/llvm-project?rev=129323&view=rev Log: Test for invalid constant expr addition - bad octal constant. Modified: llvm/trunk/test/MC/AsmParser/exprs-invalid.s Modified: llvm/trunk/test/MC/AsmParser/exprs-invalid.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/exprs-invalid.s?rev=129323&r1=129322&r2=129323&view=diff ============================================================================== --- llvm/trunk/test/MC/AsmParser/exprs-invalid.s (original) +++ llvm/trunk/test/MC/AsmParser/exprs-invalid.s Mon Apr 11 19:03:38 2011 @@ -1,13 +1,5 @@ -// RUN: not llvm-mc -triple i386-unknown-unknown %s 2> %t -// RUN: FileCheck -input-file %t %s - -// Currently XFAIL'ed, since the front-end isn't validating this. Figure out the -// right resolution. -// -// XFAIL: * - - .text -a: - .data -// CHECK: expected relocatable expression - .long -(0 + a) +// RUN: not llvm-mc -triple x86_64-apple-darwin10 %s 2> %t.err | FileCheck %s +// RUN: FileCheck --check-prefix=CHECK-ERRORS %s < %t.err +// CHECK: .section __TEXT,__text,regular,pure_instructions +// CHECK-ERRORS: error: Invalid octal number +.long 80+08 From gohman at apple.com Mon Apr 11 19:11:56 2011 From: gohman at apple.com (Dan Gohman) Date: Tue, 12 Apr 2011 00:11:56 -0000 Subject: [llvm-commits] [llvm] r129324 - in /llvm/trunk: lib/Transforms/Scalar/Reassociate.cpp test/Transforms/Reassociate/secondary.ll Message-ID: <20110412001156.AFE7D2A6C12D@llvm.org> Author: djg Date: Mon Apr 11 19:11:56 2011 New Revision: 129324 URL: http://llvm.org/viewvc/llvm-project?rev=129324&view=rev Log: Fix reassociate to use a worklist instead of recursing when new reassociation opportunities are exposed. This fixes a bug where the nested reassociation expects to be the IR to be consistent, but it isn't, because the outer reassociation has disconnected some of the operands. rdar://9167457 Added: llvm/trunk/test/Transforms/Reassociate/secondary.ll Modified: llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp Modified: llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp?rev=129324&r1=129323&r2=129324&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/Reassociate.cpp Mon Apr 11 19:11:56 2011 @@ -75,6 +75,7 @@ class Reassociate : public FunctionPass { DenseMap RankMap; DenseMap, unsigned> ValueRankMap; + SmallVector RedoInsts; SmallVector DeadInsts; bool MadeChange; public: @@ -100,7 +101,7 @@ void LinearizeExprTree(BinaryOperator *I, SmallVectorImpl &Ops); void LinearizeExpr(BinaryOperator *I); Value *RemoveFactorFromExpression(Value *V, Value *Factor); - void ReassociateBB(BasicBlock *BB); + void ReassociateInst(BasicBlock::iterator &BBI); void RemoveDeadBinaryOp(Value *V); }; @@ -734,7 +735,7 @@ // Now that we have inserted a multiply, optimize it. This allows us to // handle cases that require multiple factoring steps, such as this: // (X*2) + (X*2) + (X*2) -> (X*2)*3 -> X*6 - Mul = ReassociateExpression(cast(Mul)); + RedoInsts.push_back(Mul); // If every add operand was a duplicate, return the multiply. if (Ops.empty()) @@ -962,71 +963,69 @@ } -/// ReassociateBB - Inspect all of the instructions in this basic block, -/// reassociating them as we go. -void Reassociate::ReassociateBB(BasicBlock *BB) { - for (BasicBlock::iterator BBI = BB->begin(); BBI != BB->end(); ) { - Instruction *BI = BBI++; - if (BI->getOpcode() == Instruction::Shl && - isa(BI->getOperand(1))) - if (Instruction *NI = ConvertShiftToMul(BI, ValueRankMap)) { - MadeChange = true; - BI = NI; - } +/// ReassociateInst - Inspect and reassociate the instruction at the +/// given position, post-incrementing the position. +void Reassociate::ReassociateInst(BasicBlock::iterator &BBI) { + Instruction *BI = BBI++; + if (BI->getOpcode() == Instruction::Shl && + isa(BI->getOperand(1))) + if (Instruction *NI = ConvertShiftToMul(BI, ValueRankMap)) { + MadeChange = true; + BI = NI; + } - // Reject cases where it is pointless to do this. - if (!isa(BI) || BI->getType()->isFloatingPointTy() || - BI->getType()->isVectorTy()) - continue; // Floating point ops are not associative. - - // Do not reassociate boolean (i1) expressions. We want to preserve the - // original order of evaluation for short-circuited comparisons that - // SimplifyCFG has folded to AND/OR expressions. If the expression - // is not further optimized, it is likely to be transformed back to a - // short-circuited form for code gen, and the source order may have been - // optimized for the most likely conditions. - if (BI->getType()->isIntegerTy(1)) - continue; + // Reject cases where it is pointless to do this. + if (!isa(BI) || BI->getType()->isFloatingPointTy() || + BI->getType()->isVectorTy()) + return; // Floating point ops are not associative. + + // Do not reassociate boolean (i1) expressions. We want to preserve the + // original order of evaluation for short-circuited comparisons that + // SimplifyCFG has folded to AND/OR expressions. If the expression + // is not further optimized, it is likely to be transformed back to a + // short-circuited form for code gen, and the source order may have been + // optimized for the most likely conditions. + if (BI->getType()->isIntegerTy(1)) + return; - // If this is a subtract instruction which is not already in negate form, - // see if we can convert it to X+-Y. - if (BI->getOpcode() == Instruction::Sub) { - if (ShouldBreakUpSubtract(BI)) { - BI = BreakUpSubtract(BI, ValueRankMap); - // Reset the BBI iterator in case BreakUpSubtract changed the - // instruction it points to. - BBI = BI; - ++BBI; + // If this is a subtract instruction which is not already in negate form, + // see if we can convert it to X+-Y. + if (BI->getOpcode() == Instruction::Sub) { + if (ShouldBreakUpSubtract(BI)) { + BI = BreakUpSubtract(BI, ValueRankMap); + // Reset the BBI iterator in case BreakUpSubtract changed the + // instruction it points to. + BBI = BI; + ++BBI; + MadeChange = true; + } else if (BinaryOperator::isNeg(BI)) { + // Otherwise, this is a negation. See if the operand is a multiply tree + // and if this is not an inner node of a multiply tree. + if (isReassociableOp(BI->getOperand(1), Instruction::Mul) && + (!BI->hasOneUse() || + !isReassociableOp(BI->use_back(), Instruction::Mul))) { + BI = LowerNegateToMultiply(BI, ValueRankMap); MadeChange = true; - } else if (BinaryOperator::isNeg(BI)) { - // Otherwise, this is a negation. See if the operand is a multiply tree - // and if this is not an inner node of a multiply tree. - if (isReassociableOp(BI->getOperand(1), Instruction::Mul) && - (!BI->hasOneUse() || - !isReassociableOp(BI->use_back(), Instruction::Mul))) { - BI = LowerNegateToMultiply(BI, ValueRankMap); - MadeChange = true; - } } } + } - // If this instruction is a commutative binary operator, process it. - if (!BI->isAssociative()) continue; - BinaryOperator *I = cast(BI); - - // If this is an interior node of a reassociable tree, ignore it until we - // get to the root of the tree, to avoid N^2 analysis. - if (I->hasOneUse() && isReassociableOp(I->use_back(), I->getOpcode())) - continue; + // If this instruction is a commutative binary operator, process it. + if (!BI->isAssociative()) return; + BinaryOperator *I = cast(BI); + + // If this is an interior node of a reassociable tree, ignore it until we + // get to the root of the tree, to avoid N^2 analysis. + if (I->hasOneUse() && isReassociableOp(I->use_back(), I->getOpcode())) + return; - // If this is an add tree that is used by a sub instruction, ignore it - // until we process the subtract. - if (I->hasOneUse() && I->getOpcode() == Instruction::Add && - cast(I->use_back())->getOpcode() == Instruction::Sub) - continue; + // If this is an add tree that is used by a sub instruction, ignore it + // until we process the subtract. + if (I->hasOneUse() && I->getOpcode() == Instruction::Add && + cast(I->use_back())->getOpcode() == Instruction::Sub) + return; - ReassociateExpression(I); - } + ReassociateExpression(I); } Value *Reassociate::ReassociateExpression(BinaryOperator *I) { @@ -1093,7 +1092,16 @@ MadeChange = false; for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) - ReassociateBB(FI); + for (BasicBlock::iterator BBI = FI->begin(); BBI != FI->end(); ) + ReassociateInst(BBI); + + // Now that we're done, revisit any instructions which are likely to + // have secondary reassociation opportunities. + while (!RedoInsts.empty()) + if (Value *V = RedoInsts.pop_back_val()) { + BasicBlock::iterator BBI = cast(V); + ReassociateInst(BBI); + } // Now that we're done, delete any instructions which are no longer used. while (!DeadInsts.empty()) Added: llvm/trunk/test/Transforms/Reassociate/secondary.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/secondary.ll?rev=129324&view=auto ============================================================================== --- llvm/trunk/test/Transforms/Reassociate/secondary.ll (added) +++ llvm/trunk/test/Transforms/Reassociate/secondary.ll Mon Apr 11 19:11:56 2011 @@ -0,0 +1,24 @@ +; RUN: opt -S -reassociate < %s | FileCheck %s +; rdar://9167457 + +; Reassociate shouldn't break this testcase involving a secondary +; reassociation. + +; CHECK: define +; CHECK-NOT: undef +; CHECK: %factor = mul i32 %tmp3, -2 +; CHECK-NOT: undef +; CHECK: } + +define void @x0f2f640ab6718391b59ce96d9fdeda54(i32 %arg, i32 %arg1, i32 %arg2, i32* %.out) nounwind { +_: + %tmp = sub i32 %arg, %arg1 + %tmp3 = mul i32 %tmp, -1268345047 + %tmp4 = add i32 %tmp3, 2014710503 + %tmp5 = add i32 %tmp3, -1048397418 + %tmp6 = sub i32 %tmp4, %tmp5 + %tmp7 = sub i32 -2014710503, %tmp3 + %tmp8 = add i32 %tmp6, %tmp7 + store i32 %tmp8, i32* %.out + ret void +} From johnny.chen at apple.com Mon Apr 11 19:14:49 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Apr 2011 00:14:49 -0000 Subject: [llvm-commits] [llvm] r129325 - in /llvm/trunk: lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt Message-ID: <20110412001449.510FF2A6C12D@llvm.org> Author: johnny Date: Mon Apr 11 19:14:49 2011 New Revision: 129325 URL: http://llvm.org/viewvc/llvm-project?rev=129325&view=rev Log: A8.6.16 B Encoding T1 (tBcc) if cond == '1110' then UNDEFINED; rdar://problem/9268681 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129325&r1=129324&r2=129325&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Mon Apr 11 19:14:49 2011 @@ -951,6 +951,11 @@ : (int)Imm8)); // Predicate operands by ARMBasicMCBuilder::TryPredicateAndSBitModifier(). + // But note that for tBcc, if cond = '1110' then UNDEFINED. + if (Opcode == ARM::tBcc && slice(insn, 11, 8) == 14) { + DEBUG(errs() << "if cond = '1110' then UNDEFINED\n"); + return false; + } NumOpsAdded = 1; return true; Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt?rev=129325&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt Mon Apr 11 19:14:49 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=2249 Name=tBcc Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 1: 0: 1| 1: 1: 1: 0| 0: 1: 1: 0| 1: 1: 1: 1| +# ------------------------------------------------------------------------------------------------- +# +# if cond = '1110' then UNDEFINED +0x6f 0xde From echristo at apple.com Mon Apr 11 19:18:03 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 12 Apr 2011 00:18:03 -0000 Subject: [llvm-commits] [llvm] r129326 - in /llvm/trunk: lib/MC/MCParser/AsmLexer.cpp test/MC/AsmParser/exprs-invalid.s Message-ID: <20110412001804.00F962A6C12D@llvm.org> Author: echristo Date: Mon Apr 11 19:18:03 2011 New Revision: 129326 URL: http://llvm.org/viewvc/llvm-project?rev=129326&view=rev Log: Match case for invalid constant error messages and add a new test for invalid hexadecimals. Modified: llvm/trunk/lib/MC/MCParser/AsmLexer.cpp llvm/trunk/test/MC/AsmParser/exprs-invalid.s Modified: llvm/trunk/lib/MC/MCParser/AsmLexer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmLexer.cpp?rev=129326&r1=129325&r2=129326&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmLexer.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmLexer.cpp Mon Apr 11 19:18:03 2011 @@ -213,13 +213,13 @@ // Requires at least one binary digit. if (CurPtr == NumStart) - return ReturnError(TokStart, "Invalid binary number"); + return ReturnError(TokStart, "invalid binary number"); StringRef Result(TokStart, CurPtr - TokStart); long long Value; if (Result.substr(2).getAsInteger(2, Value)) - return ReturnError(TokStart, "Invalid binary number"); + return ReturnError(TokStart, "invalid binary number"); // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL // suffixes on integer literals. @@ -236,11 +236,11 @@ // Requires at least one hex digit. if (CurPtr == NumStart) - return ReturnError(CurPtr-2, "Invalid hexadecimal number"); + return ReturnError(CurPtr-2, "invalid hexadecimal number"); unsigned long long Result; if (StringRef(TokStart, CurPtr - TokStart).getAsInteger(0, Result)) - return ReturnError(TokStart, "Invalid hexadecimal number"); + return ReturnError(TokStart, "invalid hexadecimal number"); // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL // suffixes on integer literals. @@ -257,7 +257,7 @@ StringRef Result(TokStart, CurPtr - TokStart); long long Value; if (Result.getAsInteger(8, Value)) - return ReturnError(TokStart, "Invalid octal number"); + return ReturnError(TokStart, "invalid octal number"); // The darwin/x86 (and x86-64) assembler accepts and ignores ULL and LL // suffixes on integer literals. Modified: llvm/trunk/test/MC/AsmParser/exprs-invalid.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/exprs-invalid.s?rev=129326&r1=129325&r2=129326&view=diff ============================================================================== --- llvm/trunk/test/MC/AsmParser/exprs-invalid.s (original) +++ llvm/trunk/test/MC/AsmParser/exprs-invalid.s Mon Apr 11 19:18:03 2011 @@ -1,5 +1,8 @@ // RUN: not llvm-mc -triple x86_64-apple-darwin10 %s 2> %t.err | FileCheck %s // RUN: FileCheck --check-prefix=CHECK-ERRORS %s < %t.err // CHECK: .section __TEXT,__text,regular,pure_instructions -// CHECK-ERRORS: error: Invalid octal number +// CHECK-ERRORS: error: invalid octal number .long 80+08 + +// CHECK-ERRORS: error: invalid hexadecimal number +.long 80+0xzz From johnny.chen at apple.com Mon Apr 11 19:21:48 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Apr 2011 00:21:48 -0000 Subject: [llvm-commits] [llvm] r129327 - /llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110412002148.94B612A6C12D@llvm.org> Author: johnny Date: Mon Apr 11 19:21:48 2011 New Revision: 129327 URL: http://llvm.org/viewvc/llvm-project?rev=129327&view=rev Log: Add one test case (svc). Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129327&r1=129326&r2=129327&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Mon Apr 11 19:21:48 2011 @@ -223,3 +223,6 @@ # CHECK: bx pc 0x78 0x47 + +# CHECK: svc #230 +0xe6 0xdf From grosbach at apple.com Mon Apr 11 19:23:32 2011 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 12 Apr 2011 00:23:32 -0000 Subject: [llvm-commits] [llvm] r129328 - in /llvm/trunk: include/llvm/ExecutionEngine/RuntimeDyld.h lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp tools/llvm-rtdyld/llvm-rtdyld.cpp Message-ID: <20110412002332.6079F2A6C12D@llvm.org> Author: grosbach Date: Mon Apr 11 19:23:32 2011 New Revision: 129328 URL: http://llvm.org/viewvc/llvm-project?rev=129328&view=rev Log: Tidy up a bit now that we're using the MemoryManager interface. Modified: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Modified: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h?rev=129328&r1=129327&r2=129328&view=diff ============================================================================== --- llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h (original) +++ llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h Mon Apr 11 19:23:32 2011 @@ -63,9 +63,6 @@ // and resolve relocatons based on where they put it). void *getSymbolAddress(StringRef Name); void reassignSymbolAddress(StringRef Name, uint64_t Addr); - // FIXME: Should be parameterized to get the memory block associated with - // a particular loaded object. - sys::MemoryBlock getMemoryBlock(); StringRef getErrorString(); }; Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=129328&r1=129327&r2=129328&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Mon Apr 11 19:23:32 2011 @@ -51,7 +51,7 @@ // FIXME: Should have multiple data blocks, one for each loaded chunk of // compiled code. - sys::MemoryBlock Data; +// sys::MemoryBlock Data; bool HasError; std::string ErrorStr; @@ -91,8 +91,6 @@ return Functions.lookup(Name).base(); } - sys::MemoryBlock getMemoryBlock() { return Data; } - // Is the linker in an error state? bool hasError() { return HasError; } @@ -528,10 +526,6 @@ return Dyld->getSymbolAddress(Name); } -sys::MemoryBlock RuntimeDyld::getMemoryBlock() { - return Dyld->getMemoryBlock(); -} - StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); } Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp?rev=129328&r1=129327&r2=129328&view=diff ============================================================================== --- llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp (original) +++ llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Mon Apr 11 19:23:32 2011 @@ -44,9 +44,11 @@ // support library allocation routines directly. class TrivialMemoryManager : public RTDyldMemoryManager { public: + SmallVector FunctionMemory; + uint8_t *startFunctionBody(const char *Name, uintptr_t &Size); void endFunctionBody(const char *Name, uint8_t *FunctionStart, - uint8_t *FunctionEnd) {} + uint8_t *FunctionEnd); }; uint8_t *TrivialMemoryManager::startFunctionBody(const char *Name, @@ -54,6 +56,13 @@ return (uint8_t*)sys::Memory::AllocateRWX(Size, 0, 0).base(); } +void TrivialMemoryManager::endFunctionBody(const char *Name, + uint8_t *FunctionStart, + uint8_t *FunctionEnd) { + uintptr_t Size = FunctionEnd - FunctionStart + 1; + FunctionMemory.push_back(sys::MemoryBlock(FunctionStart, Size)); +} + static const char *ProgramName; static void Message(const char *Type, const Twine &Msg) { @@ -74,7 +83,8 @@ return Error("unable to read input: '" + ec.message() + "'"); // Instantiate a dynamic linker. - RuntimeDyld Dyld(new TrivialMemoryManager); + TrivialMemoryManager *MemMgr = new TrivialMemoryManager; + RuntimeDyld Dyld(MemMgr); // Load the object file into it. if (Dyld.loadObject(InputBuffer.take())) { @@ -86,14 +96,16 @@ if (MainAddress == 0) return Error("no definition for '_main'"); - // Invalidate the instruction cache. - sys::MemoryBlock Data = Dyld.getMemoryBlock(); - sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); - - // Make sure the memory is executable. - std::string ErrorStr; - if (!sys::Memory::setExecutable(Data, &ErrorStr)) - return Error("unable to mark function executable: '" + ErrorStr + "'"); + // Invalidate the instruction cache for each loaded function. + for (unsigned i = 0, e = MemMgr->FunctionMemory.size(); i != e; ++i) { + sys::MemoryBlock &Data = MemMgr->FunctionMemory[i]; + // Make sure the memory is executable. + std::string ErrorStr; + sys::Memory::InvalidateInstructionCache(Data.base(), Data.size()); + if (!sys::Memory::setExecutable(Data, &ErrorStr)) + return Error("unable to mark function executable: '" + ErrorStr + "'"); + } + // Dispatch to _main(). errs() << "loaded '_main' at: " << (void*)MainAddress << "\n"; From nicholas at mxc.ca Mon Apr 11 19:29:07 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 12 Apr 2011 00:29:07 -0000 Subject: [llvm-commits] [llvm] r129330 - in /llvm/trunk: include/llvm/Support/IRBuilder.h lib/VMCore/IRBuilder.cpp Message-ID: <20110412002907.E811F2A6C12D@llvm.org> Author: nicholas Date: Mon Apr 11 19:29:07 2011 New Revision: 129330 URL: http://llvm.org/viewvc/llvm-project?rev=129330&view=rev Log: Make IRBuilder support StringRef for building strings. Also document that the global variables produced are mergable. Modified: llvm/trunk/include/llvm/Support/IRBuilder.h llvm/trunk/lib/VMCore/IRBuilder.cpp Modified: llvm/trunk/include/llvm/Support/IRBuilder.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/IRBuilder.h?rev=129330&r1=129329&r2=129330&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/IRBuilder.h (original) +++ llvm/trunk/include/llvm/Support/IRBuilder.h Mon Apr 11 19:29:07 2011 @@ -18,6 +18,7 @@ #include "llvm/Instructions.h" #include "llvm/BasicBlock.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/ConstantFolder.h" @@ -153,9 +154,10 @@ /// CreateGlobalString - Make a new global variable with an initializer that /// has array of i8 type filled in with the nul terminated string value - /// specified. If Name is specified, it is the name of the global variable - /// created. - Value *CreateGlobalString(const char *Str = "", const Twine &Name = ""); + /// specified. The new global variable will be marked mergable with any + /// others of the same contents. If Name is specified, it is the name of the + /// global variable created. + Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); /// getInt1 - Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { @@ -862,7 +864,7 @@ /// CreateGlobalStringPtr - Same as CreateGlobalString, but return a pointer /// with "i8*" type instead of a pointer to array of i8. - Value *CreateGlobalStringPtr(const char *Str = "", const Twine &Name = "") { + Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { Value *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; Modified: llvm/trunk/lib/VMCore/IRBuilder.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/IRBuilder.cpp?rev=129330&r1=129329&r2=129330&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/IRBuilder.cpp (original) +++ llvm/trunk/lib/VMCore/IRBuilder.cpp Mon Apr 11 19:29:07 2011 @@ -23,7 +23,7 @@ /// has array of i8 type filled in with the nul terminated string value /// specified. If Name is specified, it is the name of the global variable /// created. -Value *IRBuilderBase::CreateGlobalString(const char *Str, const Twine &Name) { +Value *IRBuilderBase::CreateGlobalString(StringRef Str, const Twine &Name) { Constant *StrConstant = ConstantArray::get(Context, Str, true); Module &M = *BB->getParent()->getParent(); GlobalVariable *GV = new GlobalVariable(M, StrConstant->getType(), From echristo at apple.com Mon Apr 11 19:48:08 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 12 Apr 2011 00:48:08 -0000 Subject: [llvm-commits] [llvm] r129334 - /llvm/trunk/lib/CodeGen/RegAllocFast.cpp Message-ID: <20110412004808.8D7012A6C12D@llvm.org> Author: echristo Date: Mon Apr 11 19:48:08 2011 New Revision: 129334 URL: http://llvm.org/viewvc/llvm-project?rev=129334&view=rev Log: Fix typo. Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocFast.cpp?rev=129334&r1=129333&r2=129334&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocFast.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocFast.cpp Mon Apr 11 19:48:08 2011 @@ -433,7 +433,7 @@ return LiveVirtRegs.lookup(VirtReg).Dirty ? spillDirty : spillClean; } - // This is a disabled register, add up const of aliases. + // This is a disabled register, add up cost of aliases. unsigned Cost = 0; for (const unsigned *AS = TRI->getAliasSet(PhysReg); unsigned Alias = *AS; ++AS) { From nicholas at mxc.ca Mon Apr 11 20:02:45 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 12 Apr 2011 01:02:45 -0000 Subject: [llvm-commits] [llvm] r129338 - /llvm/trunk/lib/Transforms/Instrumentation/ProfilingUtils.cpp Message-ID: <20110412010245.9D1942A6C12E@llvm.org> Author: nicholas Date: Mon Apr 11 20:02:45 2011 New Revision: 129338 URL: http://llvm.org/viewvc/llvm-project?rev=129338&view=rev Log: Consider ConstantAggregateZero as well as ConstantArray/Struct. Modified: llvm/trunk/lib/Transforms/Instrumentation/ProfilingUtils.cpp Modified: llvm/trunk/lib/Transforms/Instrumentation/ProfilingUtils.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/ProfilingUtils.cpp?rev=129338&r1=129337&r2=129338&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/ProfilingUtils.cpp (original) +++ llvm/trunk/lib/Transforms/Instrumentation/ProfilingUtils.cpp Mon Apr 11 20:02:45 2011 @@ -110,7 +110,7 @@ GlobalValue *CounterArray, bool beginning) { // Insert the increment after any alloca or PHI instructions... BasicBlock::iterator InsertPos = beginning ? BB->getFirstNonPHI() : - BB->getTerminator(); + BB->getTerminator(); while (isa(InsertPos)) ++InsertPos; @@ -151,10 +151,12 @@ // delete it, to replace it with one that has a larger array type. std::vector dtors; if (GlobalVariable *GlobalDtors = Mod->getNamedGlobal("llvm.global_dtors")) { - ConstantArray *InitList = - cast(GlobalDtors->getInitializer()); - for (unsigned i = 0, e = InitList->getType()->getNumElements(); i != e; ++i) - dtors.push_back(cast(InitList->getOperand(i))); + if (ConstantArray *InitList = + dyn_cast(GlobalDtors->getInitializer())) { + for (unsigned i = 0, e = InitList->getType()->getNumElements(); + i != e; ++i) + dtors.push_back(cast(InitList->getOperand(i))); + } GlobalDtors->eraseFromParent(); } From nicholas at mxc.ca Mon Apr 11 20:06:09 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 12 Apr 2011 01:06:09 -0000 Subject: [llvm-commits] [llvm] r129340 - in /llvm/trunk: include/llvm/InitializePasses.h include/llvm/LinkAllPasses.h include/llvm/Transforms/Instrumentation.h lib/Transforms/Instrumentation/Instrumentation.cpp lib/Transforms/Instrumentation/LineProfiling.cpp runtime/libprofile/LineProfiling.c runtime/libprofile/libprofile.exports Message-ID: <20110412010609.B39542A6C12D@llvm.org> Author: nicholas Date: Mon Apr 11 20:06:09 2011 New Revision: 129340 URL: http://llvm.org/viewvc/llvm-project?rev=129340&view=rev Log: Add support for line profiling. Very work-in-progress. Use debug info in the IR to find the directory/file:line:col. Each time that location changes, bump a counter. Unlike the existing profiling system, we don't try to look at argv[], and thusly don't require main() to be present in the IR. This matches GCC's technique where you specify the profiling flag when producing each .o file. The runtime library is minimal, currently just calling printf at program shutdown time. The API is designed to make it possible to emit GCOV data later on. Added: llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp llvm/trunk/runtime/libprofile/LineProfiling.c Modified: llvm/trunk/include/llvm/InitializePasses.h llvm/trunk/include/llvm/LinkAllPasses.h llvm/trunk/include/llvm/Transforms/Instrumentation.h llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp llvm/trunk/runtime/libprofile/libprofile.exports Modified: llvm/trunk/include/llvm/InitializePasses.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=129340&r1=129339&r2=129340&view=diff ============================================================================== --- llvm/trunk/include/llvm/InitializePasses.h (original) +++ llvm/trunk/include/llvm/InitializePasses.h Mon Apr 11 20:06:09 2011 @@ -94,6 +94,7 @@ void initializeEdgeBundlesPass(PassRegistry&); void initializeEdgeProfilerPass(PassRegistry&); void initializePathProfilerPass(PassRegistry&); +void initializeLineProfilerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); void initializeFindUsedTypesPass(PassRegistry&); Modified: llvm/trunk/include/llvm/LinkAllPasses.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=129340&r1=129339&r2=129340&view=diff ============================================================================== --- llvm/trunk/include/llvm/LinkAllPasses.h (original) +++ llvm/trunk/include/llvm/LinkAllPasses.h Mon Apr 11 20:06:09 2011 @@ -70,6 +70,7 @@ (void) llvm::createEdgeProfilerPass(); (void) llvm::createOptimalEdgeProfilerPass(); (void) llvm::createPathProfilerPass(); + (void) llvm::createLineProfilerPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); Modified: llvm/trunk/include/llvm/Transforms/Instrumentation.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=129340&r1=129339&r2=129340&view=diff ============================================================================== --- llvm/trunk/include/llvm/Transforms/Instrumentation.h (original) +++ llvm/trunk/include/llvm/Transforms/Instrumentation.h Mon Apr 11 20:06:09 2011 @@ -17,7 +17,6 @@ namespace llvm { class ModulePass; -class FunctionPass; // Insert edge profiling instrumentation ModulePass *createEdgeProfilerPass(); @@ -28,6 +27,9 @@ // Insert path profiling instrumentation ModulePass *createPathProfilerPass(); +// Insert line profiling instrumentation +ModulePass *createLineProfilerPass(); + } // End llvm namespace #endif Modified: llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp?rev=129340&r1=129339&r2=129340&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp (original) +++ llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp Mon Apr 11 20:06:09 2011 @@ -23,6 +23,7 @@ initializeEdgeProfilerPass(Registry); initializeOptimalEdgeProfilerPass(Registry); initializePathProfilerPass(Registry); + initializeLineProfilerPass(Registry); } /// LLVMInitializeInstrumentation - C binding for Added: llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp?rev=129340&view=auto ============================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp (added) +++ llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp Mon Apr 11 20:06:09 2011 @@ -0,0 +1,217 @@ +//===- LineProfiling.cpp - Insert counters for line profiling -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass creates counters for the number of times that the original source +// lines of code were executed. +// +// The lines are found from existing debug info in the LLVM IR. Iterating +// through LLVM instructions, every time the debug location changes we insert a +// new counter and instructions to increment the counter there. A global +// destructor runs to dump the counters out to a file. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "insert-line-profiling" + +#include "ProfilingUtils.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Module.h" +#include "llvm/Pass.h" +#include "llvm/Instructions.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/InstIterator.h" +#include "llvm/Support/IRBuilder.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include +#include +using namespace llvm; + +STATISTIC(NumUpdatesInserted, "The # of counter increments inserted."); + +namespace { + class LineProfiler : public ModulePass { + bool runOnModule(Module &M); + public: + static char ID; + LineProfiler() : ModulePass(ID) { + initializeLineProfilerPass(*PassRegistry::getPassRegistry()); + } + virtual const char *getPassName() const { + return "Line Profiler"; + } + + private: + // Get pointers to the functions in the runtime library. + Constant *getStartFileFunc(); + Constant *getCounterFunc(); + Constant *getEndFileFunc(); + + // Insert an increment of the counter before instruction I. + void InsertCounterUpdateBefore(Instruction *I); + + // Add the function to write out all our counters to the global destructor + // list. + void InsertCounterWriteout(); + + // Mapping from the source location to the counter tracking that location. + DenseMap counters; + + Module *Mod; + LLVMContext *Ctx; + }; +} + +char LineProfiler::ID = 0; +INITIALIZE_PASS(LineProfiler, "insert-line-profiling", + "Insert instrumentation for line profiling", false, false) + +ModulePass *llvm::createLineProfilerPass() { return new LineProfiler(); } + +bool LineProfiler::runOnModule(Module &M) { + Mod = &M; + Ctx = &M.getContext(); + + DebugLoc last_line; // initializes to unknown + bool Changed = false; + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { + for (inst_iterator II = inst_begin(F), IE = inst_end(F); II != IE; ++II) { + const DebugLoc &loc = II->getDebugLoc(); + if (loc.isUnknown()) continue; + if (loc == last_line) continue; + last_line = loc; + + InsertCounterUpdateBefore(&*II); + ++NumUpdatesInserted; + Changed = true; + } + } + + if (Changed) { + InsertCounterWriteout(); + } + + return Changed; +} + +void LineProfiler::InsertCounterUpdateBefore(Instruction *I) { + const DebugLoc &loc = I->getDebugLoc(); + GlobalVariable *&counter = counters[loc]; + const Type *Int64Ty = Type::getInt64Ty(*Ctx); + if (!counter) { + counter = new GlobalVariable(*Mod, Int64Ty, false, + GlobalValue::InternalLinkage, + Constant::getNullValue(Int64Ty), + "__llvm_prof_linecov_ctr", 0, false, 0); + counter->setVisibility(GlobalVariable::HiddenVisibility); + counter->setUnnamedAddr(true); + } + + if (isa(I)) { + // We may not error out or crash in this case, because a module could put + // changing line numbers on phi nodes and still pass the verifier. + dbgs() << "Refusing to insert code before phi: " << *I << "\n"; + I = I->getParent()->getFirstNonPHI(); + } + + IRBuilder<> builder(I); + Value *ctr = builder.CreateLoad(counter); + ctr = builder.CreateAdd(ctr, ConstantInt::get(Int64Ty, 1)); + builder.CreateStore(ctr, counter); +} + +static DISubprogram FindSubprogram(DIScope scope) { + while (!scope.isSubprogram()) { + assert(scope.isLexicalBlock() && + "Debug location not lexical block or subprogram"); + scope = DILexicalBlock(scope).getContext(); + } + return DISubprogram(scope); +} + +Constant *LineProfiler::getStartFileFunc() { + const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) }; + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), + Args, false); + return Mod->getOrInsertFunction("llvm_prof_linectr_start_file", FTy); +} + +Constant *LineProfiler::getCounterFunc() { + const Type *Args[] = { + Type::getInt8PtrTy(*Ctx), // const char *dir + Type::getInt8PtrTy(*Ctx), // const char *file + Type::getInt32Ty(*Ctx), // uint32_t line + Type::getInt32Ty(*Ctx), // uint32_t column + Type::getInt64PtrTy(*Ctx), // int64_t *counter + }; + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), + Args, false); + return Mod->getOrInsertFunction("llvm_prof_linectr_emit_counter", FTy); +} + +Constant *LineProfiler::getEndFileFunc() { + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); + return Mod->getOrInsertFunction("llvm_prof_linectr_end_file", FTy); +} + +void LineProfiler::InsertCounterWriteout() { + std::set compile_units; + for (DenseMap::iterator I = counters.begin(), + E = counters.end(); I != E; ++I) { + const DebugLoc &loc = I->first; + DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx)))); + compile_units.insert(subprogram.getCompileUnit().getFilename().str()); + } + + const FunctionType *WriteoutFTy = + FunctionType::get(Type::getVoidTy(*Ctx), false); + Function *WriteoutF = Function::Create(WriteoutFTy, + GlobalValue::InternalLinkage, + "__llvm_prof_linecov_dtor", + Mod); + WriteoutF->setUnnamedAddr(true); + BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF); + IRBuilder<> builder(BB); + + Constant *StartFile = getStartFileFunc(); + Constant *EmitCounter = getCounterFunc(); + Constant *EndFile = getEndFileFunc(); + + for (std::set::const_iterator CUI = compile_units.begin(), + CUE = compile_units.end(); CUI != CUE; ++CUI) { + builder.CreateCall(StartFile, + builder.CreateGlobalStringPtr(*CUI)); + for (DenseMap::iterator I = counters.begin(), + E = counters.end(); I != E; ++I) { + const DebugLoc &loc = I->first; + DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx)))); + DICompileUnit compileunit(subprogram.getCompileUnit()); + + if (compileunit.getFilename() != *CUI) + continue; + + Value *Args[] = { + builder.CreateGlobalStringPtr(subprogram.getDirectory()), + builder.CreateGlobalStringPtr(subprogram.getFilename()), + ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getLine()), + ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getCol()), + I->second + }; + builder.CreateCall(EmitCounter, Args); + } + builder.CreateCall(EndFile); + } + builder.CreateRetVoid(); + + InsertProfilingShutdownCall(WriteoutF, Mod); +} Added: llvm/trunk/runtime/libprofile/LineProfiling.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129340&view=auto ============================================================================== --- llvm/trunk/runtime/libprofile/LineProfiling.c (added) +++ llvm/trunk/runtime/libprofile/LineProfiling.c Mon Apr 11 20:06:09 2011 @@ -0,0 +1,37 @@ +/*===- LineProfiling.c - Support library for line profiling ---------------===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file is distributed under the University of Illinois Open Source +|* License. See LICENSE.TXT for details. +|* +|*===----------------------------------------------------------------------===*| +|* +|* This file implements the call back routines for the line profiling +|* instrumentation pass. Link against this library when running code through +|* the -insert-line-profiling LLVM pass. +|* +\*===----------------------------------------------------------------------===*/ + +#include +#include +#include + +/* A file in this case is a translation unit. Each .o file built with line + * profiling enabled will emit to a different file. Only one file may be + * started at a time. + */ +void llvm_prof_linectr_start_file(const char *orig_filename) { + printf("[%s]\n", orig_filename); +} + +/* Emit data about a counter to the data file. */ +void llvm_prof_linectr_emit_counter(const char *dir, const char *file, + uint32_t line, uint32_t column, + int64_t *counter) { + printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); +} + +void llvm_prof_linectr_end_file() { + printf("-----\n"); +} Modified: llvm/trunk/runtime/libprofile/libprofile.exports URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/libprofile.exports?rev=129340&r1=129339&r2=129340&view=diff ============================================================================== --- llvm/trunk/runtime/libprofile/libprofile.exports (original) +++ llvm/trunk/runtime/libprofile/libprofile.exports Mon Apr 11 20:06:09 2011 @@ -5,3 +5,6 @@ llvm_trace_basic_block llvm_increment_path_count llvm_decrement_path_count +llvm_prof_linectr_start_file +llvm_prof_linectr_emit_counter +llvm_prof_linectr_end_file From geek4civic at gmail.com Mon Apr 11 20:54:41 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Tue, 12 Apr 2011 01:54:41 -0000 Subject: [llvm-commits] [llvm] r129343 - /llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt Message-ID: <20110412015441.141632A6C12D@llvm.org> Author: chapuni Date: Mon Apr 11 20:54:40 2011 New Revision: 129343 URL: http://llvm.org/viewvc/llvm-project?rev=129343&view=rev Log: lib/Transforms/Instrumentation/CMakeLists.txt: Add LineProfiling.cpp to fix up r129340. Modified: llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt Modified: llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt?rev=129343&r1=129342&r2=129343&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt (original) +++ llvm/trunk/lib/Transforms/Instrumentation/CMakeLists.txt Mon Apr 11 20:54:40 2011 @@ -1,6 +1,7 @@ add_llvm_library(LLVMInstrumentation EdgeProfiling.cpp Instrumentation.cpp + LineProfiling.cpp OptimalEdgeProfiling.cpp PathProfiling.cpp ProfilingUtils.cpp From evan.cheng at apple.com Mon Apr 11 21:17:41 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 12 Apr 2011 02:17:41 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r129344 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Message-ID: <20110412021741.C5BB52A6C12D@llvm.org> Author: evancheng Date: Mon Apr 11 21:17:41 2011 New Revision: 129344 URL: http://llvm.org/viewvc/llvm-project?rev=129344&view=rev Log: Disable loop idiom recognition if -fno-builtin-* options are specified. rdar://9268471 Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=129344&r1=129343&r2=129344&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Mon Apr 11 21:17:41 2011 @@ -37,6 +37,7 @@ #include "llvm/CodeGen/RegAllocRegistry.h" #include "llvm/Target/SubtargetFeature.h" #include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegistry.h" @@ -70,6 +71,7 @@ #include "langhooks.h" #include "cgraph.h" #include "params.h" +#include "c-common.h" } // Non-zero if bytecode from PCH is successfully read. @@ -670,6 +672,19 @@ new FunctionPassManager(TheModule); PerFunctionPasses->add(new TargetData(*TheTarget->getTargetData())); + // Disable (partially) loop idiom pass with -fno-builtin*. + TargetLibraryInfo *TLI = + new TargetLibraryInfo(Triple(TheModule->getTargetTriple())); + if (flag_no_builtin) + TLI->disableAllFunctions(); + else { + if (builtin_function_disabled_p("__builtin_memset")) + TLI->setUnavailable(LibFunc::memset); + if (builtin_function_disabled_p("__builtin_memcpy")) + TLI->setUnavailable(LibFunc::memcpy); + } + PerFunctionPasses->add(TLI); + // In -O0 if checking is disabled, we don't even have per-function passes. bool HasPerFunctionPasses = false; #ifdef ENABLE_CHECKING @@ -740,8 +755,21 @@ // FIXME: AT -O0/O1, we should stream out functions at a time. PerModulePasses = new PassManager(); PerModulePasses->add(new TargetData(*TheTarget->getTargetData())); - bool HasPerModulePasses = false; + // Disable (partially) loop idiom pass with -fno-builtin*. + TargetLibraryInfo *TLI = + new TargetLibraryInfo(Triple(TheModule->getTargetTriple())); + if (flag_no_builtin) + TLI->disableAllFunctions(); + else { + if (builtin_function_disabled_p("__builtin_memset")) + TLI->setUnavailable(LibFunc::memset); + if (builtin_function_disabled_p("__builtin_memcpy")) + TLI->setUnavailable(LibFunc::memcpy); + } + PerModulePasses->add(TLI); + + bool HasPerModulePasses = false; if (!DisableLLVMOptimizations) { bool NeedAlwaysInliner = false; llvm::Pass *InliningPass = 0; From zwarich at apple.com Mon Apr 11 21:24:17 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Tue, 12 Apr 2011 02:24:17 -0000 Subject: [llvm-commits] [llvm] r129345 - in /llvm/trunk: lib/Target/ARM/ARMISelLowering.cpp test/CodeGen/ARM/fp-arg-shuffle.ll Message-ID: <20110412022418.0D0652A6C12D@llvm.org> Author: zwarich Date: Mon Apr 11 21:24:17 2011 New Revision: 129345 URL: http://llvm.org/viewvc/llvm-project?rev=129345&view=rev Log: Split a store of a VMOVDRR into two integer stores to avoid mixing NEON and ARM stores of arguments in the same cache line. This fixes the second half of . Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp llvm/trunk/test/CodeGen/ARM/fp-arg-shuffle.ll Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=129345&r1=129344&r2=129345&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Apr 11 21:24:17 2011 @@ -5684,8 +5684,28 @@ // Otherwise, the i64 value will be legalized to a pair of i32 values. StoreSDNode *St = cast(N); SDValue StVal = St->getValue(); - if (!ISD::isNormalStore(St) || St->isVolatile() || - StVal.getValueType() != MVT::i64 || + if (!ISD::isNormalStore(St) || St->isVolatile()) + return SDValue(); + + if (StVal.getNode()->getOpcode() == ARMISD::VMOVDRR && + StVal.getNode()->hasOneUse() && !St->isVolatile()) { + SelectionDAG &DAG = DCI.DAG; + DebugLoc DL = St->getDebugLoc(); + SDValue BasePtr = St->getBasePtr(); + SDValue NewST1 = DAG.getStore(St->getChain(), DL, + StVal.getNode()->getOperand(0), BasePtr, + St->getPointerInfo(), St->isVolatile(), + St->isNonTemporal(), St->getAlignment()); + + SDValue OffsetPtr = DAG.getNode(ISD::ADD, DL, MVT::i32, BasePtr, + DAG.getConstant(4, MVT::i32)); + return DAG.getStore(NewST1.getValue(0), DL, StVal.getNode()->getOperand(1), + OffsetPtr, St->getPointerInfo(), St->isVolatile(), + St->isNonTemporal(), + std::min(4U, St->getAlignment() / 2)); + } + + if (StVal.getValueType() != MVT::i64 || StVal.getNode()->getOpcode() != ISD::EXTRACT_VECTOR_ELT) return SDValue(); Modified: llvm/trunk/test/CodeGen/ARM/fp-arg-shuffle.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/fp-arg-shuffle.ll?rev=129345&r1=129344&r2=129345&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/fp-arg-shuffle.ll (original) +++ llvm/trunk/test/CodeGen/ARM/fp-arg-shuffle.ll Mon Apr 11 21:24:17 2011 @@ -1,7 +1,7 @@ ; RUN: llc < %s -march=arm -mattr=+neon -float-abi=soft | FileCheck %s ; CHECK: function1 -; CHECK-NOT: vmov r +; CHECK-NOT: vmov define double @function1(double %a, double %b, double %c, double %d, double %e, double %f) nounwind noinline ssp { entry: %call = tail call double @function2(double %f, double %e, double %d, double %c, double %b, double %a) nounwind From evan.cheng at apple.com Mon Apr 11 22:12:58 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 12 Apr 2011 03:12:58 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r129347 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Message-ID: <20110412031258.788A82A6C12D@llvm.org> Author: evancheng Date: Mon Apr 11 22:12:58 2011 New Revision: 129347 URL: http://llvm.org/viewvc/llvm-project?rev=129347&view=rev Log: Fix detection of -fno-builtin-memset and -fno-builtin-memcpy. rdar://9268471. Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=129347&r1=129346&r2=129347&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Mon Apr 11 22:12:58 2011 @@ -678,9 +678,9 @@ if (flag_no_builtin) TLI->disableAllFunctions(); else { - if (builtin_function_disabled_p("__builtin_memset")) + if (builtin_function_disabled_p("memset")) TLI->setUnavailable(LibFunc::memset); - if (builtin_function_disabled_p("__builtin_memcpy")) + if (builtin_function_disabled_p("memcpy")) TLI->setUnavailable(LibFunc::memcpy); } PerFunctionPasses->add(TLI); @@ -762,9 +762,9 @@ if (flag_no_builtin) TLI->disableAllFunctions(); else { - if (builtin_function_disabled_p("__builtin_memset")) + if (builtin_function_disabled_p("memset")) TLI->setUnavailable(LibFunc::memset); - if (builtin_function_disabled_p("__builtin_memcpy")) + if (builtin_function_disabled_p("memcpy")) TLI->setUnavailable(LibFunc::memcpy); } PerModulePasses->add(TLI); From baldrick at free.fr Tue Apr 12 00:39:27 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 05:39:27 -0000 Subject: [llvm-commits] [dragonegg] r129350 - /dragonegg/trunk/Constants.cpp Message-ID: <20110412053927.94FEA2A6C12D@llvm.org> Author: baldrick Date: Tue Apr 12 00:39:27 2011 New Revision: 129350 URL: http://llvm.org/viewvc/llvm-project?rev=129350&view=rev Log: Now that array constructors take care not to be too aligned, so if we can self-host build with this check turned on. Modified: dragonegg/trunk/Constants.cpp Modified: dragonegg/trunk/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Constants.cpp?rev=129350&r1=129349&r2=129350&view=diff ============================================================================== --- dragonegg/trunk/Constants.cpp (original) +++ dragonegg/trunk/Constants.cpp Tue Apr 12 00:39:27 2011 @@ -1148,10 +1148,9 @@ if (isInt64(TREE_TYPE(exp), true) && InitSize != TypeSize) DieAbjectly("Constant too big for type!", exp); } -// FIXME: This check fails when building libdecnumber (self-host build). -// if (getTargetData().getABITypeAlignment(Init->getType()) * 8 > -// TYPE_ALIGN(TREE_TYPE(exp))) -// DieAbjectly("Constant over aligned!", exp); + if (getTargetData().getABITypeAlignment(Init->getType()) * 8 > + TYPE_ALIGN(TREE_TYPE(exp))) + DieAbjectly("Constant over aligned!", exp); #endif return Init; From baldrick at free.fr Tue Apr 12 01:11:50 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 08:11:50 +0200 Subject: [llvm-commits] [llvm] r129302 - /llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp In-Reply-To: <20110411213234.6400A2A6C12D@llvm.org> References: <20110411213234.6400A2A6C12D@llvm.org> Message-ID: <4DA3ED26.6020804@free.fr> Hi Bill, > It turns out, we get there if the _Unwind_Resume_or_Rethrow call returns (which > it's not supposed to do). IIRC it will return if there are only cleanups all the way up the stack. Then you can use _Unwind_ForcedUnwind to unwind anyway IIRC (Ada uses this because it always runs cleanups [*], unlike C++ which for some reason thinks that cleanups don't matter if there is nothing else to do). I might be remembering wrong though. Ciao, Duncan. [*] For example a cleanup that shuts down the reactor. From nicholas at mxc.ca Tue Apr 12 01:23:49 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Mon, 11 Apr 2011 23:23:49 -0700 Subject: [llvm-commits] [PATCH] - endless loop in instcombine and a small constant folding optimization on vectors In-Reply-To: <6594DDFF12B03D4E89690887C2486994027889605C@hasmsx504.ger.corp.intel.com> References: <6594DDFF12B03D4E89690887C2486994027889605C@hasmsx504.ger.corp.intel.com> Message-ID: <4DA3EFF5.3050507@mxc.ca> Rotem, Nadav wrote: > Hi, > > Please review the attached patch: > > 1. Fix an endless loop in instcombine. VisitAnd changes the instruction, and VisitXor fixes it in an endless loop. Hrmm. Neither visitAnd nor visitXor should be swapping operands for funsies, there should be one canonical form of the expression and instcombine should produce it. I tried to analyze this, but I found that in your testcase, my breakpoint in visitXor never fired, there was only a look on visitAnd... > 2. A small constant folding patch vector select with a splat condition. + // Handles cases where the condition is splat vector. + // select , X, Y -> Y + // select , X, Y -> X + if (isa(CondVal)) return FalseVal; + if (ConstantVector *CP = dyn_cast(CondVal)) { + if (CP->isAllOnesValue()) return TrueVal; if (CP->isNullValue()) return FalseVal; ? Nick + } + > Thanks, > Nadav > --------------------------------------------------------------------- > Intel Israel (74) Limited > > This e-mail and any attachments may contain confidential material for > the sole use of the intended recipient(s). Any review or distribution > by others is strictly prohibited. If you are not the intended > recipient, please contact the sender and delete all copies. > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From baldrick at free.fr Tue Apr 12 02:39:05 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 09:39:05 +0200 Subject: [llvm-commits] [llvm-gcc-4.2] r129344 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp In-Reply-To: <20110412021741.C5BB52A6C12D@llvm.org> References: <20110412021741.C5BB52A6C12D@llvm.org> Message-ID: <4DA40199.4050302@free.fr> Hi Evan, > Disable loop idiom recognition if -fno-builtin-* options are specified. rdar://9268471 from http://google1.osuosl.org:8011/builders/llvm-x86_64-linux-checks /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/./prev-gcc/xgcc -B/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/./prev-gcc/ -B/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.install/x86_64-pc-linux-gnu/bin/ -c -g -O2 -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -Wold-style-definition -Wmissing-format-attribute -DHAVE_CONFIG_H -I. -I. -I../../llvm-gcc.src/gcc -I../../llvm-gcc.src/gcc/. -I../../llvm-gcc.src/gcc/../include -I../../llvm-gcc.src/gcc/../libcpp/include -I/opt/cfarm/gmp/include -I/opt/cfarm/mpfr/include -I../../llvm-gcc.src/gcc/../libdecnumber -I../libdecnumber -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.obj/include -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.src/include -DENABLE_LLVM -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.src/include -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.obj/include -D_DEBUG -D_GLIBCXX_DEBUG -DXDEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS cc1-checksum.c -o cc1-checksum.o libbackend.a(llvm-backend.o): In function `createPerFunctionOptimizationPasses': /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:678: undefined reference to `flag_no_builtin' /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:681: undefined reference to `builtin_function_disabled_p' /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:683: undefined reference to `builtin_function_disabled_p' libbackend.a(llvm-backend.o): In function `createPerModuleOptimizationPasses': /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:762: undefined reference to `flag_no_builtin' /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:765: undefined reference to `builtin_function_disabled_p' /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:767: undefined reference to `builtin_function_disabled_p' collect2: ld returned 1 exit status From wendling at apple.com Tue Apr 12 02:49:55 2011 From: wendling at apple.com (Bill Wendling) Date: Tue, 12 Apr 2011 00:49:55 -0700 Subject: [llvm-commits] [llvm] r129302 - /llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp In-Reply-To: <4DA3ED26.6020804@free.fr> References: <20110411213234.6400A2A6C12D@llvm.org> <4DA3ED26.6020804@free.fr> Message-ID: On Apr 11, 2011, at 11:11 PM, Duncan Sands wrote: > Hi Bill, > >> It turns out, we get there if the _Unwind_Resume_or_Rethrow call returns (which >> it's not supposed to do). > > IIRC it will return if there are only cleanups all the way up the stack. Then > you can use _Unwind_ForcedUnwind to unwind anyway IIRC (Ada uses this because > it always runs cleanups [*], unlike C++ which for some reason thinks that > cleanups don't matter if there is nothing else to do). I might be remembering > wrong though. > That's correct. And it's probably meant to use _Unwind_ForceUnwind afterwards. But at the point where this is happening, we no longer have such information (unfortunately). > [*] For example a cleanup that shuts down the reactor. Which is why Ada is used in such situations. :-) Though I would hate to have these systems using exceptions... -bw From baldrick at free.fr Tue Apr 12 02:54:38 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 09:54:38 +0200 Subject: [llvm-commits] [llvm] r129302 - /llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp In-Reply-To: References: <20110411213234.6400A2A6C12D@llvm.org> <4DA3ED26.6020804@free.fr> Message-ID: <4DA4053E.5010805@free.fr> Hi Bill, >> [*] For example a cleanup that shuts down the reactor. > > Which is why Ada is used in such situations. :-) Though I would hate to have these systems using exceptions... if you knew that the software on the plane you are flying in was compiled using LLVM, would you reach for a parachute? :) Ciao, Duncan. PS: As far as I know safety critical systems typically make no use of exceptions (or anything else that makes static analysis hard). From wendling at apple.com Tue Apr 12 02:58:15 2011 From: wendling at apple.com (Bill Wendling) Date: Tue, 12 Apr 2011 00:58:15 -0700 Subject: [llvm-commits] [llvm] r129302 - /llvm/trunk/lib/CodeGen/SjLjEHPrepare.cpp In-Reply-To: <4DA4053E.5010805@free.fr> References: <20110411213234.6400A2A6C12D@llvm.org> <4DA3ED26.6020804@free.fr> <4DA4053E.5010805@free.fr> Message-ID: <96F7D486-8D50-4F98-8359-AA4CDBEBE296@apple.com> On Apr 12, 2011, at 12:54 AM, Duncan Sands wrote: > Hi Bill, > >>> [*] For example a cleanup that shuts down the reactor. >> >> Which is why Ada is used in such situations. :-) Though I would hate to have these systems using exceptions... > > if you knew that the software on the plane you are flying in was compiled using > LLVM, would you reach for a parachute? :) No comment. ;-) > PS: As far as I know safety critical systems typically make no use of exceptions > (or anything else that makes static analysis hard). Yeah. I got a small peek into this when I worked at The MathWorks. The software that Matlab and Simulink generated had to be as "optimized" as possible, because they typically didn't use optimizations when generating their code. And the qualification process for getting software into these systems was intense. -bw From baldrick at free.fr Tue Apr 12 04:15:29 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 09:15:29 -0000 Subject: [llvm-commits] [dragonegg] r129352 - in /dragonegg/trunk: Backend.cpp Constants.cpp Convert.cpp Debug.cpp DefaultABI.cpp Makefile Trees.cpp Types.cpp bits_and_bobs.cpp cache.c extras/do_self_strap src/ src/Backend.cpp src/Constants.cpp src/Convert.cpp src/Debug.cpp src/DefaultABI.cpp src/Trees.cpp src/Types.cpp src/bits_and_bobs.cpp src/cache.c Message-ID: <20110412091529.BCFF72A6C12D@llvm.org> Author: baldrick Date: Tue Apr 12 04:15:29 2011 New Revision: 129352 URL: http://llvm.org/viewvc/llvm-project?rev=129352&view=rev Log: Move most source files to the src subdirectory. Added: dragonegg/trunk/src/ dragonegg/trunk/src/Backend.cpp - copied unchanged from r129217, dragonegg/trunk/Backend.cpp dragonegg/trunk/src/Constants.cpp - copied unchanged from r129350, dragonegg/trunk/Constants.cpp dragonegg/trunk/src/Convert.cpp - copied unchanged from r129217, dragonegg/trunk/Convert.cpp dragonegg/trunk/src/Debug.cpp - copied unchanged from r129217, dragonegg/trunk/Debug.cpp dragonegg/trunk/src/DefaultABI.cpp - copied unchanged from r129217, dragonegg/trunk/DefaultABI.cpp dragonegg/trunk/src/Trees.cpp - copied unchanged from r129217, dragonegg/trunk/Trees.cpp dragonegg/trunk/src/Types.cpp - copied unchanged from r129244, dragonegg/trunk/Types.cpp dragonegg/trunk/src/bits_and_bobs.cpp - copied unchanged from r129217, dragonegg/trunk/bits_and_bobs.cpp dragonegg/trunk/src/cache.c - copied unchanged from r129217, dragonegg/trunk/cache.c Removed: dragonegg/trunk/Backend.cpp dragonegg/trunk/Constants.cpp dragonegg/trunk/Convert.cpp dragonegg/trunk/Debug.cpp dragonegg/trunk/DefaultABI.cpp dragonegg/trunk/Trees.cpp dragonegg/trunk/Types.cpp dragonegg/trunk/bits_and_bobs.cpp dragonegg/trunk/cache.c Modified: dragonegg/trunk/Makefile dragonegg/trunk/extras/do_self_strap Removed: dragonegg/trunk/Backend.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Backend.cpp?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/Backend.cpp (original) +++ dragonegg/trunk/Backend.cpp (removed) @@ -1,2746 +0,0 @@ -//===----------- Backend.cpp - High-level LLVM backend interface ----------===// -// -// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Chris Lattner, -// Duncan Sands et al. -// -// This file is part of DragonEgg. -// -// DragonEgg is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free Software -// Foundation; either version 2, or (at your option) any later version. -// -// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -// A PARTICULAR PURPOSE. See the GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along with -// DragonEgg; see the file COPYING. If not, write to the Free Software -// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. -// -//===----------------------------------------------------------------------===// -// This file defines the high-level LLVM backend interface. -//===----------------------------------------------------------------------===// - -// Plugin headers -extern "C" { -#include "dragonegg/cache.h" -} -#include "dragonegg/Constants.h" -#include "dragonegg/Debug.h" -#include "dragonegg/OS.h" -#include "dragonegg/Target.h" - -// LLVM headers -#define DEBUG_TYPE "plugin" -#include "llvm/LLVMContext.h" -#include "llvm/Module.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Assembly/PrintModulePass.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/CodeGen/RegAllocRegistry.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/StandardPasses.h" -#include "llvm/Target/SubtargetFeature.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Target/TargetLibraryInfo.h" -#include "llvm/Target/TargetRegistry.h" - -// System headers -#include - -// GCC headers -extern "C" { -#include "config.h" -// Stop GCC declaring 'getopt' as it can clash with the system's declaration. -#undef HAVE_DECL_GETOPT -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" - -#include "debug.h" -#include "diagnostic.h" -#include "flags.h" -#include "gcc-plugin.h" -#include "intl.h" -#include "langhooks.h" -#include "output.h" -#include "params.h" -#include "plugin-version.h" -#include "toplev.h" -#include "tree-flow.h" -#include "tree-pass.h" -#include "version.h" -} - -#if (GCC_MAJOR != 4) -#error Unsupported GCC major version -#endif - -// Non-zero if bytecode from PCH is successfully read. -int flag_llvm_pch_read; - -// Non-zero if libcalls should not be simplified. -int flag_no_simplify_libcalls; - -// Non-zero if red-zone is disabled. -//TODOstatic int flag_disable_red_zone = 0; - -// Non-zero if implicit floating point instructions are disabled. -//TODOstatic int flag_no_implicit_float = 0; - -/// llvm_asm_file_name - Name of file to use for assembly code output. -static const char *llvm_asm_file_name; - -// Global state for the LLVM backend. -Module *TheModule = 0; -DebugInfo *TheDebugInfo = 0; -TargetMachine *TheTarget = 0; -TargetFolder *TheFolder = 0; -TypeConverter *TheTypeConverter = 0; -raw_ostream *OutStream = 0; // Stream to write assembly code to. -formatted_raw_ostream FormattedOutStream; - -static bool DebugPassArguments; -static bool DebugPassStructure; -static bool DisableLLVMOptimizations; -static bool EnableGCCOptimizations; -static bool EmitIR; -static bool SaveGCCOutput; - -std::vector > StaticCtors, StaticDtors; -SmallSetVector AttributeUsedGlobals; -SmallSetVector AttributeCompilerUsedGlobals; -std::vector AttributeAnnotateGlobals; - -/// PerFunctionPasses - This is the list of cleanup passes run per-function -/// as each is compiled. In cases where we are not doing IPO, it includes the -/// code generator. -static FunctionPassManager *PerFunctionPasses = 0; -static PassManager *PerModulePasses = 0; -static FunctionPassManager *CodeGenPasses = 0; - -static void createPerFunctionOptimizationPasses(); -static void createPerModuleOptimizationPasses(); -//TODOstatic void destroyOptimizationPasses(); - - -//===----------------------------------------------------------------------===// -// Matching LLVM Values with GCC DECL trees -//===----------------------------------------------------------------------===// - -/// set_decl_llvm - Remember the LLVM value for a GCC declaration. -Value *set_decl_llvm (tree t, Value *V) { - assert(HAS_RTL_P(t) && "Expected a declaration with RTL!"); - return (Value *)llvm_set_cached(t, V); -} - -/// get_decl_llvm - Retrieve the LLVM value for a GCC declaration, or NULL. -Value *get_decl_llvm(tree t) { - assert(HAS_RTL_P(t) && "Expected a declaration with RTL!"); - return (Value *)llvm_get_cached(t); -} - -/// set_decl_index - Associate a non-negative number with the given GCC -/// declaration. -int set_decl_index(tree t, int i) { - assert(!HAS_RTL_P(t) && "Expected a declaration without RTL!"); - assert(i >= 0 && "Negative indices not allowed!"); - // In order to use zero as a special value (see get_decl_index) map the range - // 0 .. INT_MAX to -1 .. INT_MIN. - llvm_set_cached(t, (void *)(intptr_t)(-i - 1)); - return i; -} - -/// get_decl_index - Get the non-negative number associated with the given GCC -/// declaration. Returns a negative value if no such association has been made. -int get_decl_index(tree t) { - assert(!HAS_RTL_P(t) && "Expected a declaration without RTL!"); - // Map the range -1 .. INT_MIN back to 0 .. INT_MAX (see set_decl_index) and - // send 0 (aka void) to -1. - return -(1 + (int)(intptr_t)llvm_get_cached(t)); -} - -/// changeLLVMConstant - Replace Old with New everywhere, updating all maps -/// (except for AttributeAnnotateGlobals, which is a different kind of animal). -/// At this point we know that New is not in any of these maps. -void changeLLVMConstant(Constant *Old, Constant *New) { - assert(Old->use_empty() && "Old value has uses!"); - - if (AttributeUsedGlobals.count(Old)) { - AttributeUsedGlobals.remove(Old); - AttributeUsedGlobals.insert(New); - } - - if (AttributeCompilerUsedGlobals.count(Old)) { - AttributeCompilerUsedGlobals.remove(Old); - AttributeCompilerUsedGlobals.insert(New); - } - - for (unsigned i = 0, e = StaticCtors.size(); i != e; ++i) { - if (StaticCtors[i].first == Old) - StaticCtors[i].first = New; - } - - for (unsigned i = 0, e = StaticDtors.size(); i != e; ++i) { - if (StaticDtors[i].first == Old) - StaticDtors[i].first = New; - } - - llvm_replace_cached(Old, New); -} - -//TODO/// readLLVMValues - Read LLVM Types string table -//TODOvoid readLLVMValues() { -//TODO GlobalValue *V = TheModule->getNamedGlobal("llvm.pch.values"); -//TODO if (!V) -//TODO return; -//TODO -//TODO GlobalVariable *GV = cast(V); -//TODO ConstantStruct *ValuesFromPCH = cast(GV->getOperand(0)); -//TODO -//TODO for (unsigned i = 0; i < ValuesFromPCH->getNumOperands(); ++i) { -//TODO Value *Va = ValuesFromPCH->getOperand(i); -//TODO -//TODO if (!Va) { -//TODO // If V is empty then insert NULL to represent empty entries. -//TODO LLVMValues.push_back(Va); -//TODO continue; -//TODO } -//TODO if (ConstantArray *CA = dyn_cast(Va)) { -//TODO std::string Str = CA->getAsString(); -//TODO Va = TheModule->getValueSymbolTable().lookup(Str); -//TODO } -//TODO assert (Va != NULL && "Invalid Value in LLVMValues string table"); -//TODO LLVMValues.push_back(Va); -//TODO } -//TODO -//TODO // Now, llvm.pch.values is not required so remove it from the symbol table. -//TODO GV->eraseFromParent(); -//TODO} -//TODO -//TODO/// writeLLVMValues - GCC tree's uses LLVMValues vector's index to reach LLVM -//TODO/// Values. Create a string table to hold these LLVM Values' names. This string -//TODO/// table will be used to recreate LTypes vector after loading PCH. -//TODOvoid writeLLVMValues() { -//TODO if (LLVMValues.empty()) -//TODO return; -//TODO -//TODO LLVMContext &Context = getGlobalContext(); -//TODO -//TODO std::vector ValuesForPCH; -//TODO for (std::vector::iterator I = LLVMValues.begin(), -//TODO E = LLVMValues.end(); I != E; ++I) { -//TODO if (Constant *C = dyn_cast_or_null(*I)) -//TODO ValuesForPCH.push_back(C); -//TODO else -//TODO // Non constant values, e.g. arguments, are not at global scope. -//TODO // When PCH is read, only global scope values are used. -//TODO ValuesForPCH.push_back(Constant::getNullValue(Type::getInt32Ty(Context))); -//TODO } -//TODO -//TODO // Create string table. -//TODO Constant *LLVMValuesTable = ConstantStruct::get(Context, ValuesForPCH, false); -//TODO -//TODO // Create variable to hold this string table. -//TODO new GlobalVariable(*TheModule, LLVMValuesTable->getType(), true, -//TODO GlobalValue::ExternalLinkage, -//TODO LLVMValuesTable, -//TODO "llvm.pch.values"); -//TODO} - -/// handleVisibility - Forward decl visibility style to global. -void handleVisibility(tree decl, GlobalValue *GV) { - // If decl has visibility specified explicitely (via attribute) - honour - // it. Otherwise (e.g. visibility specified via -fvisibility=hidden) honour - // only if symbol is local. - if (TREE_PUBLIC(decl) && - (DECL_VISIBILITY_SPECIFIED(decl) || !DECL_EXTERNAL(decl))) { - if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN) - GV->setVisibility(GlobalValue::HiddenVisibility); - else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED) - GV->setVisibility(GlobalValue::ProtectedVisibility); - else if (DECL_VISIBILITY(decl) == VISIBILITY_DEFAULT) - GV->setVisibility(Function::DefaultVisibility); - } -} - -// GuessAtInliningThreshold - Figure out a reasonable threshold to pass llvm's -// inliner. gcc has many options that control inlining, but we have decided -// not to support anything like that for llvm-gcc. -static unsigned GuessAtInliningThreshold() { - if (optimize_size) - // Reduce inline limit. - return 75; - - if (optimize >= 3) - return 275; - return 225; -} - -// SizeOfGlobalMatchesDecl - Whether the size of the given global value is the -// same as that of the given GCC declaration. Conservatively returns 'true' if -// the answer is unclear. -static LLVM_ATTRIBUTE_UNUSED // Only called from asserts. -bool SizeOfGlobalMatchesDecl(GlobalValue *GV, tree decl) { - // If the GCC declaration has no size then nothing useful can be said here. - if (!DECL_SIZE(decl)) - return true; - assert(isInt64(DECL_SIZE(decl), true) && "Global decl with variable size!"); - - const Type *Ty = GV->getType()->getElementType(); - // If the LLVM type has no size then a useful comparison cannot be made. - if (!Ty->isSized()) - return true; - - // DECL_SIZE need not be a multiple of the alignment, while the LLVM size - // always is. Correct for this. - // TODO: Change getTypeSizeInBits for aggregate types so it is no longer - // rounded up to the alignment. - uint64_t gcc_size = getInt64(DECL_SIZE(decl), true); - const TargetData *TD = TheTarget->getTargetData(); - unsigned Align = 8 * TD->getABITypeAlignment(Ty); - return TheTarget->getTargetData()->getTypeAllocSizeInBits(Ty) == - ((gcc_size + Align - 1) / Align) * Align; -} - -#ifndef LLVM_TARGET_NAME -#error LLVM_TARGET_NAME macro not specified -#endif - -namespace llvm { -#define Declare2(TARG, MOD) extern "C" void LLVMInitialize ## TARG ## MOD() -#define Declare(T, M) Declare2(T, M) - Declare(LLVM_TARGET_NAME, TargetInfo); - Declare(LLVM_TARGET_NAME, Target); - Declare(LLVM_TARGET_NAME, AsmPrinter); -#undef Declare -#undef Declare2 -} - -/// ConfigureLLVM - Initialized and configure LLVM. -static void ConfigureLLVM(void) { - // Initialize the LLVM backend. -#define DoInit2(TARG, MOD) LLVMInitialize ## TARG ## MOD() -#define DoInit(T, M) DoInit2(T, M) - DoInit(LLVM_TARGET_NAME, TargetInfo); - DoInit(LLVM_TARGET_NAME, Target); - DoInit(LLVM_TARGET_NAME, AsmPrinter); -#undef DoInit -#undef DoInit2 - - // Initialize LLVM command line options. - std::vector Args; - Args.push_back(progname); // program name - -//TODO // Allow targets to specify PIC options and other stuff to the corresponding -//TODO // LLVM backends. -//TODO#ifdef LLVM_SET_RED_ZONE_FLAG -//TODO LLVM_SET_RED_ZONE_FLAG(flag_disable_red_zone) -//TODO#endif -#ifdef LLVM_SET_TARGET_OPTIONS - LLVM_SET_TARGET_OPTIONS(Args); -#endif -#ifdef LLVM_SET_MACHINE_OPTIONS - LLVM_SET_MACHINE_OPTIONS(Args); -#endif -//TODO#ifdef LLVM_SET_IMPLICIT_FLOAT -//TODO LLVM_SET_IMPLICIT_FLOAT(flag_no_implicit_float) -//TODO#endif - - if (time_report || !quiet_flag || flag_detailed_statistics) - Args.push_back("--time-passes"); - if (!quiet_flag || flag_detailed_statistics) - Args.push_back("--stats"); - if (fast_math_flags_set_p()) - Args.push_back("--enable-unsafe-fp-math"); - if (flag_finite_math_only) { - Args.push_back("--enable-no-nans-fp-math"); - Args.push_back("--enable-no-infs-fp-math"); - } - if (!flag_omit_frame_pointer) - Args.push_back("--disable-fp-elim"); - if (!flag_zero_initialized_in_bss) - Args.push_back("--nozero-initialized-in-bss"); - if (flag_verbose_asm) - Args.push_back("--asm-verbose"); - if (DebugPassStructure) - Args.push_back("--debug-pass=Structure"); - if (DebugPassArguments) - Args.push_back("--debug-pass=Arguments"); - if (flag_unwind_tables) - Args.push_back("--unwind-tables"); - if (!flag_schedule_insns) - Args.push_back("--pre-RA-sched=source"); - if (flag_function_sections) - Args.push_back("--ffunction-sections"); - if (flag_data_sections) - Args.push_back("--fdata-sections"); - - // If there are options that should be passed through to the LLVM backend - // directly from the command line, do so now. This is mainly for debugging - // purposes, and shouldn't really be for general use. - std::vector ArgStrings; - - unsigned threshold = GuessAtInliningThreshold(); - std::string Arg("--inline-threshold="+utostr(threshold)); - ArgStrings.push_back(Arg); - -//TODO if (flag_limited_precision > 0) { -//TODO std::string Arg("--limit-float-precision="+utostr(flag_limited_precision)); -//TODO ArgStrings.push_back(Arg); -//TODO } - - if (flag_stack_protect > 0) { - std::string Arg("--stack-protector-buffer-size=" + - utostr(PARAM_VALUE(PARAM_SSP_BUFFER_SIZE))); - ArgStrings.push_back(Arg); - } - - for (unsigned i = 0, e = ArgStrings.size(); i != e; ++i) - Args.push_back(ArgStrings[i].c_str()); - -//TODO std::vector LLVM_Optns; // Avoid deallocation before opts parsed! -//TODO if (llvm_optns) { -//TODO llvm::SmallVector Buf; -//TODO SplitString(llvm_optns, Buf); -//TODO for(unsigned i = 0, e = Buf.size(); i != e; ++i) { -//TODO LLVM_Optns.push_back(Buf[i]); -//TODO Args.push_back(LLVM_Optns.back().c_str()); -//TODO } -//TODO } - - Args.push_back(0); // Null terminator. - int pseudo_argc = Args.size()-1; - llvm::cl::ParseCommandLineOptions(pseudo_argc, const_cast(&Args[0])); -} - -/// ComputeTargetTriple - Determine the target triple to use. -static std::string ComputeTargetTriple() { - // If the target wants to override the architecture, e.g. turning - // powerpc-darwin-... into powerpc64-darwin-... when -m64 is enabled, do so - // now. - std::string TargetTriple = TARGET_NAME; -#ifdef LLVM_OVERRIDE_TARGET_ARCH - std::string Arch = LLVM_OVERRIDE_TARGET_ARCH(); - if (!Arch.empty()) { - std::string::size_type DashPos = TargetTriple.find('-'); - if (DashPos != std::string::npos)// If we have a sane t-t, replace the arch. - TargetTriple = Arch + TargetTriple.substr(DashPos); - } -#endif -#ifdef LLVM_OVERRIDE_TARGET_VERSION - char *NewTriple; - bool OverRidden = LLVM_OVERRIDE_TARGET_VERSION(TargetTriple.c_str(), - &NewTriple); - if (OverRidden) - TargetTriple = std::string(NewTriple); -#endif - return TargetTriple; -} - -/// CreateTargetMachine - Create the TargetMachine we will generate code with. -static void CreateTargetMachine(const std::string &TargetTriple) { - // FIXME: Figure out how to select the target and pass down subtarget info. - std::string Err; - const Target *TME = - TargetRegistry::lookupTarget(TargetTriple, Err); - if (!TME) - report_fatal_error(Err); - - // Figure out the subtarget feature string we pass to the target. - std::string FeatureStr; - // The target can set LLVM_SET_SUBTARGET_FEATURES to configure the LLVM - // backend. -#ifdef LLVM_SET_SUBTARGET_FEATURES - SubtargetFeatures Features; - LLVM_SET_SUBTARGET_FEATURES(Features); - FeatureStr = Features.getString(); -#endif - TheTarget = TME->createTargetMachine(TargetTriple, FeatureStr); - assert(TheTarget->getTargetData()->isBigEndian() == BYTES_BIG_ENDIAN); -} - -/// CreateModule - Create and initialize a module to output LLVM IR to. -static void CreateModule(const std::string &TargetTriple) { - // Create the module itself. - StringRef ModuleID = main_input_filename ? main_input_filename : ""; - TheModule = new Module(ModuleID, getGlobalContext()); - - // Insert a special .ident directive to identify the version of the plugin - // which compiled this code. The format of the .ident string is patterned - // after the ones produced by GCC. -#ifdef IDENT_ASM_OP - if (!flag_no_ident) { - const char *pkg_version = "(GNU) "; - - if (strcmp ("(GCC) ", pkgversion_string)) - pkg_version = pkgversion_string; - - std::string IdentString = IDENT_ASM_OP; - IdentString += "\"GCC: "; - IdentString += pkg_version; - IdentString += version_string; - IdentString += " LLVM: "; - IdentString += REVISION; - IdentString += "\""; - TheModule->setModuleInlineAsm(IdentString); - } -#endif - - // Install information about the target triple and data layout into the module - // for optimizer use. - TheModule->setTargetTriple(TargetTriple); - TheModule->setDataLayout(TheTarget->getTargetData()-> - getStringRepresentation()); -} - -/// flag_default_initialize_globals - Whether global variables with no explicit -/// initial value should be zero initialized. -bool flag_default_initialize_globals = true; // GCC always initializes to zero - -/// flag_odr - Whether the language being compiled obeys the One Definition Rule -/// (i.e. if the same function is defined in multiple compilation units, all the -/// definitions are equivalent). -bool flag_odr; - -/// flag_vararg_requires_arguments - Do not consider functions with no arguments -/// to take a variable number of arguments (...). If set then a function like -/// "T foo() {}" will be treated like "T foo(void) {}" and not "T foo(...) {}". -bool flag_vararg_requires_arguments; - -/// flag_force_vararg_prototypes - Force prototypes to take a variable number of -/// arguments (...). This is helpful if the language front-end sometimes emits -/// calls where the call arguments do not match the callee function declaration. -bool flag_force_vararg_prototypes; - -/// InstallLanguageSettings - Do any language-specific back-end configuration. -static void InstallLanguageSettings() { - // The principal here is that not doing any language-specific configuration - // should still result in correct code. The language-specific settings are - // only for obtaining better code, by exploiting language-specific features. - StringRef LanguageName = lang_hooks.name; - - if (LanguageName == "GNU Ada") { - flag_default_initialize_globals = false; // Uninitialized means what it says - flag_odr = true; // Ada obeys the one-definition-rule - } else if (LanguageName == "GNU C") { - flag_vararg_requires_arguments = true; // "T foo() {}" -> "T foo(void) {}" - } else if (LanguageName == "GNU C++") { - flag_odr = true; // C++ obeys the one-definition-rule - } else if (LanguageName == "GNU Fortran") { - flag_force_vararg_prototypes = true; - } else if (LanguageName == "GNU GIMPLE") { // LTO gold plugin - } else if (LanguageName == "GNU Java") { - } else if (LanguageName == "GNU Objective-C") { - flag_vararg_requires_arguments = true; // "T foo() {}" -> "T foo(void) {}" - } else if (LanguageName == "GNU Objective-C++") { - flag_odr = true; // Objective C++ obeys the one-definition-rule - } -} - -/// InitializeBackend - Initialize the GCC to LLVM conversion machinery. -/// Can safely be called multiple times. -static void InitializeBackend(void) { - static bool Initialized = false; - if (Initialized) - return; - - // Initialize and configure LLVM. - ConfigureLLVM(); - - // Create the target machine to generate code for. - const std::string TargetTriple = ComputeTargetTriple(); - CreateTargetMachine(TargetTriple); - - // Create a module to hold the generated LLVM IR. - CreateModule(TargetTriple); - - TheTypeConverter = new TypeConverter(); - TheFolder = new TargetFolder(TheTarget->getTargetData()); - - if (debug_info_level > DINFO_LEVEL_NONE) - TheDebugInfo = new DebugInfo(TheModule); - if (TheDebugInfo) - TheDebugInfo->Initialize(); - - // Perform language specific configuration. - InstallLanguageSettings(); - - Initialized = true; -} - -/// InitializeOutputStreams - Initialize the assembly code output streams. -static void InitializeOutputStreams(bool Binary) { - assert(!OutStream && "Output stream already initialized!"); - std::string Error; - - OutStream = new raw_fd_ostream(llvm_asm_file_name, Error, - Binary ? raw_fd_ostream::F_Binary : 0); - - if (!Error.empty()) - report_fatal_error(Error); - - FormattedOutStream.setStream(*OutStream, - formatted_raw_ostream::PRESERVE_STREAM); -} - -//TODOoFILEstream *AsmIntermediateOutStream = 0; -//TODO -//TODO/// llvm_pch_read - Read bytecode from PCH file. Initialize TheModule and setup -//TODO/// LTypes vector. -//TODOvoid llvm_pch_read(const unsigned char *Buffer, unsigned Size) { -//TODO std::string ModuleName = TheModule->getModuleIdentifier(); -//TODO -//TODO delete TheModule; -//TODO delete TheDebugInfo; -//TODO -//TODO clearTargetBuiltinCache(); -//TODO -//TODO MemoryBuffer *MB = MemoryBuffer::getNewMemBuffer(Size, ModuleName.c_str()); -//TODO memcpy((char*)MB->getBufferStart(), Buffer, Size); -//TODO -//TODO std::string ErrMsg; -//TODO TheModule = ParseBitcodeFile(MB, getGlobalContext(), &ErrMsg); -//TODO delete MB; -//TODO -//TODO // FIXME - Do not disable debug info while writing pch. -//TODO if (!flag_pch_file && debug_info_level > DINFO_LEVEL_NONE) { -//TODO TheDebugInfo = new DebugInfo(TheModule); -//TODO TheDebugInfo->Initialize(); -//TODO } -//TODO -//TODO if (!TheModule) { -//TODO errs() << "Error reading bytecodes from PCH file\n"; -//TODO errs() << ErrMsg << "\n"; -//TODO exit(1); -//TODO } -//TODO -//TODO if (PerFunctionPasses || PerModulePasses) { -//TODO destroyOptimizationPasses(); -//TODO -//TODO // Don't run codegen, when we should output PCH -//TODO if (flag_pch_file) -//TODO llvm_pch_write_init(); -//TODO } -//TODO -//TODO // Read LLVM Types string table -//TODO readLLVMTypesStringTable(); -//TODO readLLVMValues(); -//TODO -//TODO flag_llvm_pch_read = 1; -//TODO} -//TODO -//TODO/// llvm_pch_write_init - Initialize PCH writing. -//TODOvoid llvm_pch_write_init(void) { -//TODO timevar_push(TV_LLVM_INIT); -//TODO AsmOutStream = new oFILEstream(asm_out_file); -//TODO // FIXME: disentangle ostream madness here. Kill off ostream and FILE. -//TODO AsmOutRawStream = -//TODO new formatted_raw_ostream(*new raw_os_ostream(*AsmOutStream), -//TODO formatted_raw_ostream::DELETE_STREAM); -//TODO -//TODO PerModulePasses = new PassManager(); -//TODO PerModulePasses->add(new TargetData(*TheTarget->getTargetData())); -//TODO -//TODO // If writing to stdout, set binary mode. -//TODO if (asm_out_file == stdout) -//TODO sys::Program::ChangeStdoutToBinary(); -//TODO -//TODO // Emit an LLVM .bc file to the output. This is used when passed -//TODO // -emit-llvm -c to the GCC driver. -//TODO PerModulePasses->add(createBitcodeWriterPass(*AsmOutStream)); -//TODO -//TODO // Disable emission of .ident into the output file... which is completely -//TODO // wrong for llvm/.bc emission cases. -//TODO flag_no_ident = 1; -//TODO -//TODO flag_llvm_pch_read = 0; -//TODO -//TODO timevar_pop(TV_LLVM_INIT); -//TODO} - -//TODOstatic void destroyOptimizationPasses() { -//TODO delete PerFunctionPasses; -//TODO delete PerModulePasses; -//TODO delete CodeGenPasses; -//TODO -//TODO PerFunctionPasses = 0; -//TODO PerModulePasses = 0; -//TODO CodeGenPasses = 0; -//TODO} - -static void createPerFunctionOptimizationPasses() { - if (PerFunctionPasses) - return; - - // Create and set up the per-function pass manager. - // FIXME: Move the code generator to be function-at-a-time. - PerFunctionPasses = - new FunctionPassManager(TheModule); - PerFunctionPasses->add(new TargetData(*TheTarget->getTargetData())); - - // In -O0 if checking is disabled, we don't even have per-function passes. - bool HasPerFunctionPasses = false; -#ifdef ENABLE_CHECKING - PerFunctionPasses->add(createVerifierPass()); - HasPerFunctionPasses = true; -#endif - - if (optimize > 0 && !DisableLLVMOptimizations) { - HasPerFunctionPasses = true; - - TargetLibraryInfo *TLI = - new TargetLibraryInfo(Triple(TheModule->getTargetTriple())); - if (flag_no_simplify_libcalls) - TLI->disableAllFunctions(); - PerFunctionPasses->add(TLI); - - PerFunctionPasses->add(createCFGSimplificationPass()); - if (optimize == 1) - PerFunctionPasses->add(createPromoteMemoryToRegisterPass()); - else - PerFunctionPasses->add(createScalarReplAggregatesPass()); - PerFunctionPasses->add(createInstructionCombiningPass()); - } - - // If there are no module-level passes that have to be run, we codegen as - // each function is parsed. - // FIXME: We can't figure this out until we know there are no always-inline - // functions. - // FIXME: This is disabled right now until bugs can be worked out. Reenable - // this for fast -O0 compiles! - if (!EmitIR && 0) { - FunctionPassManager *PM = PerFunctionPasses; - HasPerFunctionPasses = true; - - CodeGenOpt::Level OptLevel = CodeGenOpt::Default; // -O2, -Os, and -Oz - if (optimize == 0) - OptLevel = CodeGenOpt::None; - else if (optimize == 1) - OptLevel = CodeGenOpt::Less; - else if (optimize == 3) - // -O3 and above. - OptLevel = CodeGenOpt::Aggressive; - - // Request that addPassesToEmitFile run the Verifier after running - // passes which modify the IR. -#ifndef NDEBUG - bool DisableVerify = false; -#else - bool DisableVerify = true; -#endif - - // Normal mode, emit a .s file by running the code generator. - // Note, this also adds codegenerator level optimization passes. - InitializeOutputStreams(false); - if (TheTarget->addPassesToEmitFile(*PM, FormattedOutStream, - TargetMachine::CGFT_AssemblyFile, - OptLevel, DisableVerify)) - DieAbjectly("Error interfacing to target machine!"); - } - - if (HasPerFunctionPasses) { - PerFunctionPasses->doInitialization(); - } else { - delete PerFunctionPasses; - PerFunctionPasses = 0; - } -} - -static void createPerModuleOptimizationPasses() { - if (PerModulePasses) - // llvm_pch_write_init has already created the per module passes. - return; - - // FIXME: AT -O0/O1, we should stream out functions at a time. - PerModulePasses = new PassManager(); - PerModulePasses->add(new TargetData(*TheTarget->getTargetData())); - bool HasPerModulePasses = false; - - if (!DisableLLVMOptimizations) { - TargetLibraryInfo *TLI = - new TargetLibraryInfo(Triple(TheModule->getTargetTriple())); - if (flag_no_simplify_libcalls) - TLI->disableAllFunctions(); - PerModulePasses->add(TLI); - - bool NeedAlwaysInliner = false; - llvm::Pass *InliningPass = 0; - if (flag_inline_small_functions && !flag_no_inline) { - InliningPass = createFunctionInliningPass(); // Inline small functions - } else { - // If full inliner is not run, check if always-inline is needed to handle - // functions that are marked as always_inline. - // TODO: Consider letting the GCC inliner do this. - for (Module::iterator I = TheModule->begin(), E = TheModule->end(); - I != E; ++I) - if (I->hasFnAttr(Attribute::AlwaysInline)) { - NeedAlwaysInliner = true; - break; - } - - if (NeedAlwaysInliner) - InliningPass = createAlwaysInlinerPass(); // Inline always_inline funcs - } - - HasPerModulePasses = true; - createStandardModulePasses(PerModulePasses, optimize, - optimize_size, - flag_unit_at_a_time, flag_unroll_loops, - !flag_no_simplify_libcalls, flag_exceptions, - InliningPass); - } - - if (EmitIR && 0) { - // Emit an LLVM .bc file to the output. This is used when passed - // -emit-llvm -c to the GCC driver. - InitializeOutputStreams(true); - PerModulePasses->add(createBitcodeWriterPass(*OutStream)); - HasPerModulePasses = true; - } else if (EmitIR) { - // Emit an LLVM .ll file to the output. This is used when passed - // -emit-llvm -S to the GCC driver. - InitializeOutputStreams(false); - PerModulePasses->add(createPrintModulePass(OutStream)); - HasPerModulePasses = true; - } else { - // If there are passes we have to run on the entire module, we do codegen - // as a separate "pass" after that happens. - // However if there are no module-level passes that have to be run, we - // codegen as each function is parsed. - // FIXME: This is disabled right now until bugs can be worked out. Reenable - // this for fast -O0 compiles! - if (PerModulePasses || 1) { - FunctionPassManager *PM = CodeGenPasses = - new FunctionPassManager(TheModule); - PM->add(new TargetData(*TheTarget->getTargetData())); - - CodeGenOpt::Level OptLevel = CodeGenOpt::Default; - - switch (optimize) { - default: break; - case 0: OptLevel = CodeGenOpt::None; break; - case 3: OptLevel = CodeGenOpt::Aggressive; break; - } - - // Request that addPassesToEmitFile run the Verifier after running - // passes which modify the IR. -#ifndef NDEBUG - bool DisableVerify = false; -#else - bool DisableVerify = true; -#endif - - // Normal mode, emit a .s file by running the code generator. - // Note, this also adds codegenerator level optimization passes. - InitializeOutputStreams(false); - if (TheTarget->addPassesToEmitFile(*PM, FormattedOutStream, - TargetMachine::CGFT_AssemblyFile, - OptLevel, DisableVerify)) - DieAbjectly("Error interfacing to target machine!"); - } - } - - if (!HasPerModulePasses) { - delete PerModulePasses; - PerModulePasses = 0; - } -} - -//TODO/// llvm_asm_file_start - Start the .s file. -//TODOvoid llvm_asm_file_start(void) { -//TODO timevar_push(TV_LLVM_INIT); -//TODO AsmOutStream = new oFILEstream(asm_out_file); -//TODO // FIXME: disentangle ostream madness here. Kill off ostream and FILE. -//TODO AsmOutRawStream = -//TODO new formatted_raw_ostream(*new raw_os_ostream(*AsmOutStream), -//TODO formatted_raw_ostream::DELETE_STREAM); -//TODO -//TODO flag_llvm_pch_read = 0; -//TODO -//TODO if (EmitIR) -//TODO // Disable emission of .ident into the output file... which is completely -//TODO // wrong for llvm/.bc emission cases. -//TODO flag_no_ident = 1; -//TODO -//TODO // If writing to stdout, set binary mode. -//TODO if (asm_out_file == stdout) -//TODO sys::Program::ChangeStdoutToBinary(); -//TODO -//TODO AttributeUsedGlobals.clear(); -//TODO AttributeCompilerUsedGlobals.clear(); -//TODO timevar_pop(TV_LLVM_INIT); -//TODO} - -/// ConvertStructorsList - Convert a list of static ctors/dtors to an -/// initializer suitable for the llvm.global_[cd]tors globals. -static void CreateStructorsList(std::vector > &Tors, - const char *Name) { - std::vector InitList; - std::vector StructInit; - StructInit.resize(2); - - LLVMContext &Context = getGlobalContext(); - - const Type *FPTy = - FunctionType::get(Type::getVoidTy(Context), - std::vector(), false); - FPTy = FPTy->getPointerTo(); - - for (unsigned i = 0, e = Tors.size(); i != e; ++i) { - StructInit[0] = ConstantInt::get(Type::getInt32Ty(Context), Tors[i].second); - - // __attribute__(constructor) can be on a function with any type. Make sure - // the pointer is void()*. - StructInit[1] = TheFolder->CreateBitCast(Tors[i].first, FPTy); - InitList.push_back(ConstantStruct::get(Context, StructInit, false)); - } - Constant *Array = ConstantArray::get( - ArrayType::get(InitList[0]->getType(), InitList.size()), InitList); - new GlobalVariable(*TheModule, Array->getType(), false, - GlobalValue::AppendingLinkage, - Array, Name); -} - -/// ConvertMetadataStringToGV - Convert string to global value. Use existing -/// global if possible. -Constant* ConvertMetadataStringToGV(const char *str) { - - Constant *Init = ConstantArray::get(getGlobalContext(), std::string(str)); - - // Use cached string if it exists. - static std::map StringCSTCache; - GlobalVariable *&Slot = StringCSTCache[Init]; - if (Slot) return Slot; - - // Create a new string global. - GlobalVariable *GV = new GlobalVariable(*TheModule, Init->getType(), true, - GlobalVariable::PrivateLinkage, - Init, ".str"); - GV->setSection("llvm.metadata"); - Slot = GV; - return GV; - -} - -/// AddAnnotateAttrsToGlobal - Adds decls that have a annotate attribute to a -/// vector to be emitted later. -void AddAnnotateAttrsToGlobal(GlobalValue *GV, tree decl) { - LLVMContext &Context = getGlobalContext(); - - // Handle annotate attribute on global. - tree annotateAttr = lookup_attribute("annotate", DECL_ATTRIBUTES (decl)); - if (annotateAttr == 0) - return; - - // Get file and line number - Constant *lineNo = ConstantInt::get(Type::getInt32Ty(Context), - DECL_SOURCE_LINE(decl)); - Constant *file = ConvertMetadataStringToGV(DECL_SOURCE_FILE(decl)); - const Type *SBP = Type::getInt8PtrTy(Context); - file = TheFolder->CreateBitCast(file, SBP); - - // There may be multiple annotate attributes. Pass return of lookup_attr - // to successive lookups. - while (annotateAttr) { - - // Each annotate attribute is a tree list. - // Get value of list which is our linked list of args. - tree args = TREE_VALUE(annotateAttr); - - // Each annotate attribute may have multiple args. - // Treat each arg as if it were a separate annotate attribute. - for (tree a = args; a; a = TREE_CHAIN(a)) { - // Each element of the arg list is a tree list, so get value - tree val = TREE_VALUE(a); - - // Assert its a string, and then get that string. - assert(TREE_CODE(val) == STRING_CST && - "Annotate attribute arg should always be a string"); - Constant *strGV = AddressOf(val); - Constant *Element[4] = { - TheFolder->CreateBitCast(GV,SBP), - TheFolder->CreateBitCast(strGV,SBP), - file, - lineNo - }; - - AttributeAnnotateGlobals.push_back( - ConstantStruct::get(Context, Element, 4, false)); - } - - // Get next annotate attribute. - annotateAttr = TREE_CHAIN(annotateAttr); - if (annotateAttr) - annotateAttr = lookup_attribute("annotate", annotateAttr); - } -} - -/// emit_global - Emit the specified VAR_DECL or aggregate CONST_DECL to LLVM as -/// a global variable. This function implements the end of assemble_variable. -static void emit_global(tree decl) { - // FIXME: Support alignment on globals: DECL_ALIGN. - // FIXME: DECL_PRESERVE_P indicates the var is marked with attribute 'used'. - - // Global register variables don't turn into LLVM GlobalVariables. - if (TREE_CODE(decl) == VAR_DECL && DECL_REGISTER(decl)) - return; - - // If we encounter a forward declaration then do not emit the global yet. - if (!TYPE_SIZE(TREE_TYPE(decl))) - return; - -//TODO timevar_push(TV_LLVM_GLOBALS); - - // Get or create the global variable now. - GlobalVariable *GV = cast(DECL_LLVM(decl)); - - // Convert the initializer over. - Constant *Init; - if (DECL_INITIAL(decl) == 0 || DECL_INITIAL(decl) == error_mark_node) { - // Reconvert the type in case the forward def of the global and the real def - // differ in type (e.g. declared as 'int A[]', and defined as 'int A[100]'). - const Type *Ty = ConvertType(TREE_TYPE(decl)); - Init = getDefaultValue(Ty); - } else { - // Temporarily set an initializer for the global, so we don't infinitely - // recurse. If we don't do this, we can hit cases where we see "oh a global - // with an initializer hasn't been initialized yet, call emit_global on it". - // When constructing the initializer it might refer to itself. - // This can happen for things like void *G = &G; - GV->setInitializer(UndefValue::get(GV->getType()->getElementType())); - Init = ConvertInitializer(DECL_INITIAL(decl)); - } - - // If we had a forward definition that has a type that disagrees with our - // initializer, insert a cast now. This sort of thing occurs when we have a - // global union, and the LLVM type followed a union initializer that is - // different from the union element used for the type. - if (GV->getType()->getElementType() != Init->getType()) { - GV->removeFromParent(); - GlobalVariable *NGV = new GlobalVariable(*TheModule, Init->getType(), - GV->isConstant(), - GlobalValue::ExternalLinkage, 0, - GV->getName()); - GV->replaceAllUsesWith(TheFolder->CreateBitCast(NGV, GV->getType())); - changeLLVMConstant(GV, NGV); - delete GV; - SET_DECL_LLVM(decl, NGV); - GV = NGV; - } - - // Set the initializer. - GV->setInitializer(Init); - - // Set thread local (TLS) - if (TREE_CODE(decl) == VAR_DECL && DECL_THREAD_LOCAL_P(decl)) - GV->setThreadLocal(true); - - // Set the linkage. - GlobalValue::LinkageTypes Linkage; - - if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS) - && false) {// FIXME DECL_LLVM_PRIVATE(decl)) { - Linkage = GlobalValue::PrivateLinkage; - } else if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS) - && false) {//FIXME DECL_LLVM_LINKER_PRIVATE(decl)) { - Linkage = GlobalValue::LinkerPrivateLinkage; - } else if (!TREE_PUBLIC(decl)) { - Linkage = GlobalValue::InternalLinkage; - } else if (DECL_WEAK(decl)) { - // The user may have explicitly asked for weak linkage - ignore flag_odr. - Linkage = GlobalValue::WeakAnyLinkage; - } else if (DECL_ONE_ONLY(decl)) { - Linkage = GlobalValue::getWeakLinkage(flag_odr); - } else if (DECL_COMMON(decl) && // DECL_COMMON is only meaningful if no init - (!DECL_INITIAL(decl) || DECL_INITIAL(decl) == error_mark_node)) { - // llvm-gcc also includes DECL_VIRTUAL_P here. - Linkage = GlobalValue::CommonLinkage; - } else if (DECL_COMDAT(decl)) { - Linkage = GlobalValue::getLinkOnceLinkage(flag_odr); - } else { - Linkage = GV->getLinkage(); - } - - // Allow loads from constants to be folded even if the constant has weak - // linkage. Do this by giving the constant weak_odr linkage rather than - // weak linkage. It is not clear whether this optimization is valid (see - // gcc bug 36685), but mainline gcc chooses to do it, and fold may already - // have done it, so we might as well join in with gusto. - if (GV->isConstant()) { - if (Linkage == GlobalValue::WeakAnyLinkage) - Linkage = GlobalValue::WeakODRLinkage; - else if (Linkage == GlobalValue::LinkOnceAnyLinkage) - Linkage = GlobalValue::LinkOnceODRLinkage; - } - GV->setLinkage(Linkage); - -#ifdef TARGET_ADJUST_LLVM_LINKAGE - TARGET_ADJUST_LLVM_LINKAGE(GV, decl); -#endif /* TARGET_ADJUST_LLVM_LINKAGE */ - - handleVisibility(decl, GV); - - // Set the section for the global. - if (TREE_CODE(decl) == VAR_DECL) { - if (DECL_SECTION_NAME(decl)) { - GV->setSection(TREE_STRING_POINTER(DECL_SECTION_NAME(decl))); -#ifdef LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION - } else if (const char *Section = - LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION(decl)) { - GV->setSection(Section); -#endif - } - - // Set the alignment for the global if one of the following condition is met - // 1) DECL_ALIGN is better than the alignment as per ABI specification - // 2) DECL_ALIGN is set by user. - if (DECL_ALIGN(decl)) { - unsigned TargetAlign = - getTargetData().getABITypeAlignment(GV->getType()->getElementType()); - if (DECL_USER_ALIGN(decl) || - 8 * TargetAlign < (unsigned)DECL_ALIGN(decl)) { - GV->setAlignment(DECL_ALIGN(decl) / 8); - } -#ifdef TARGET_ADJUST_CSTRING_ALIGN - else if (DECL_INITIAL(decl) != error_mark_node && // uninitialized? - DECL_INITIAL(decl) && - TREE_CODE(DECL_INITIAL(decl)) == STRING_CST) { - TARGET_ADJUST_CSTRING_ALIGN(GV); - } -#endif - } - - // Handle used decls - if (DECL_PRESERVE_P (decl)) { - if (false)//FIXME DECL_LLVM_LINKER_PRIVATE (decl)) - AttributeCompilerUsedGlobals.insert(GV); - else - AttributeUsedGlobals.insert(GV); - } - - // Add annotate attributes for globals - if (DECL_ATTRIBUTES(decl)) - AddAnnotateAttrsToGlobal(GV, decl); - -#ifdef LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION - } else if (TREE_CODE(decl) == CONST_DECL) { - if (const char *Section = - LLVM_IMPLICIT_TARGET_GLOBAL_VAR_SECTION(decl)) { - GV->setSection(Section); - - /* LLVM LOCAL - begin radar 6389998 */ -#ifdef TARGET_ADJUST_CFSTRING_NAME - TARGET_ADJUST_CFSTRING_NAME(GV, Section); -#endif - /* LLVM LOCAL - end radar 6389998 */ - } -#endif - } - - if (TheDebugInfo) - TheDebugInfo->EmitGlobalVariable(GV, decl); - - // Sanity check that the LLVM global has the right size. - assert(SizeOfGlobalMatchesDecl(GV, decl) && "Global has wrong size!"); - - // Mark the global as written so gcc doesn't waste time outputting it. - TREE_ASM_WRITTEN(decl) = 1; - -//TODO timevar_pop(TV_LLVM_GLOBALS); -} - - -/// ValidateRegisterVariable - Check that a static "asm" variable is -/// well-formed. If not, emit error messages and return true. If so, return -/// false. -bool ValidateRegisterVariable(tree decl) { - int RegNumber = decode_reg_name(extractRegisterName(decl)); - - if (errorcount || sorrycount) - return true; // Do not process broken code. - - /* Detect errors in declaring global registers. */ - if (RegNumber == -1) - error("register name not specified for %q+D", decl); - else if (RegNumber < 0) - error("invalid register name for %q+D", decl); - else if (TYPE_MODE(TREE_TYPE(decl)) == BLKmode) - error("data type of %q+D isn%'t suitable for a register", decl); -#if 0 // FIXME: enable this. - else if (!HARD_REGNO_MODE_OK(RegNumber, TYPE_MODE(TREE_TYPE(decl)))) - error("register specified for %q+D isn%'t suitable for data type", - decl); -#endif - else if (DECL_INITIAL(decl) != 0 && TREE_STATIC(decl)) - error("global register variable has initial value"); - else if (AGGREGATE_TYPE_P(TREE_TYPE(decl))) - sorry("LLVM cannot handle register variable %q+D, report a bug", - decl); - else { - if (TREE_THIS_VOLATILE(decl)) - warning(0, "volatile register variables don%'t work as you might wish"); - - return false; // Everything ok. - } - - return true; -} - - -/// make_decl_llvm - Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL -/// should have static storage duration. In other words, it should not be an -/// automatic variable, including PARM_DECLs. -/// -/// There is, however, one exception: this function handles variables explicitly -/// placed in a particular register by the user. -/// -/// This function corresponds to make_decl_rtl in varasm.c, and is implicitly -/// called by DECL_LLVM if a decl doesn't have an LLVM set. -Value *make_decl_llvm(tree decl) { - // If we already made the LLVM, then return it. - if (Value *V = get_decl_llvm(decl)) - return V; - -#ifdef ENABLE_CHECKING - // Check that we are not being given an automatic variable or a type or label. - // A weak alias has TREE_PUBLIC set but not the other bits. - if (TREE_CODE(decl) == PARM_DECL || TREE_CODE(decl) == RESULT_DECL || - TREE_CODE(decl) == TYPE_DECL || TREE_CODE(decl) == LABEL_DECL || - (TREE_CODE(decl) == VAR_DECL && !TREE_STATIC(decl) && - !TREE_PUBLIC(decl) && !DECL_EXTERNAL(decl) && !DECL_REGISTER(decl))) - DieAbjectly("Cannot make a global for this kind of declaration!", decl); -#endif - - if (errorcount || sorrycount) - return NULL; // Do not process broken code. - - LLVMContext &Context = getGlobalContext(); - - // Global register variable with asm name, e.g.: - // register unsigned long esp __asm__("ebp"); - if (TREE_CODE(decl) != FUNCTION_DECL && DECL_REGISTER(decl)) { - // This just verifies that the variable is ok. The actual "load/store" - // code paths handle accesses to the variable. - ValidateRegisterVariable(decl); - return NULL; - } - -//TODO timevar_push(TV_LLVM_GLOBALS); - - std::string Name; - if (TREE_CODE(decl) != CONST_DECL) // CONST_DECLs do not have assembler names. - Name = getLLVMAssemblerName(decl).str(); - - // Now handle ordinary static variables and functions (in memory). - // Also handle vars declared register invalidly. - if (!Name.empty() && Name[0] == 1) { -#ifdef REGISTER_PREFIX - if (strlen (REGISTER_PREFIX) != 0) { - int reg_number = decode_reg_name(Name); - if (reg_number >= 0 || reg_number == -3) - error("register name given for non-register variable %q+D", decl); - } -#endif - } - - // Specifying a section attribute on a variable forces it into a - // non-.bss section, and thus it cannot be common. - if (TREE_CODE(decl) == VAR_DECL && DECL_SECTION_NAME(decl) != NULL_TREE && - DECL_INITIAL(decl) == NULL_TREE && DECL_COMMON(decl)) - DECL_COMMON(decl) = 0; - - // Variables can't be both common and weak. - if (TREE_CODE(decl) == VAR_DECL && DECL_WEAK(decl)) - DECL_COMMON(decl) = 0; - - // Okay, now we need to create an LLVM global variable or function for this - // object. Note that this is quite possibly a forward reference to the - // object, so its type may change later. - if (TREE_CODE(decl) == FUNCTION_DECL) { - assert(!Name.empty() && "Function with empty name!"); - // If this function has already been created, reuse the decl. This happens - // when we have something like __builtin_memset and memset in the same file. - Function *FnEntry = TheModule->getFunction(Name); - if (FnEntry == 0) { - CallingConv::ID CC; - AttrListPtr PAL; - const FunctionType *Ty = - TheTypeConverter->ConvertFunctionType(TREE_TYPE(decl), decl, NULL, - CC, PAL); - FnEntry = Function::Create(Ty, Function::ExternalLinkage, Name, TheModule); - FnEntry->setCallingConv(CC); - FnEntry->setAttributes(PAL); - - // Check for external weak linkage. - if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) - FnEntry->setLinkage(Function::ExternalWeakLinkage); - -#ifdef TARGET_ADJUST_LLVM_LINKAGE - TARGET_ADJUST_LLVM_LINKAGE(FnEntry,decl); -#endif /* TARGET_ADJUST_LLVM_LINKAGE */ - - handleVisibility(decl, FnEntry); - - // If FnEntry got renamed, then there is already an object with this name - // in the symbol table. If this happens, the old one must be a forward - // decl, just replace it with a cast of the new one. - if (FnEntry->getName() != Name) { - GlobalVariable *G = TheModule->getGlobalVariable(Name, true); - assert(G && G->isDeclaration() && "A global turned into a function?"); - - // Replace any uses of "G" with uses of FnEntry. - Constant *GInNewType = TheFolder->CreateBitCast(FnEntry, G->getType()); - G->replaceAllUsesWith(GInNewType); - - // Update the decl that points to G. - changeLLVMConstant(G, GInNewType); - - // Now we can give GV the proper name. - FnEntry->takeName(G); - - // G is now dead, nuke it. - G->eraseFromParent(); - } - } - return SET_DECL_LLVM(decl, FnEntry); - } else { - assert((TREE_CODE(decl) == VAR_DECL || - TREE_CODE(decl) == CONST_DECL) && "Not a function or var decl?"); - const Type *Ty = ConvertType(TREE_TYPE(decl)); - GlobalVariable *GV ; - - // If we have "extern void foo", make the global have type {} instead of - // type void. - if (Ty->isVoidTy()) - Ty = StructType::get(Context); - - if (Name.empty()) { // Global has no name. - GV = new GlobalVariable(*TheModule, Ty, false, - GlobalValue::ExternalLinkage, 0, ""); - - // Check for external weak linkage. - if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) - GV->setLinkage(GlobalValue::ExternalWeakLinkage); - -#ifdef TARGET_ADJUST_LLVM_LINKAGE - TARGET_ADJUST_LLVM_LINKAGE(GV,decl); -#endif /* TARGET_ADJUST_LLVM_LINKAGE */ - - handleVisibility(decl, GV); - } else { - // If the global has a name, prevent multiple vars with the same name from - // being created. - GlobalVariable *GVE = TheModule->getGlobalVariable(Name, true); - - if (GVE == 0) { - GV = new GlobalVariable(*TheModule, Ty, false, - GlobalValue::ExternalLinkage, 0, Name); - - // Check for external weak linkage. - if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) - GV->setLinkage(GlobalValue::ExternalWeakLinkage); - -#ifdef TARGET_ADJUST_LLVM_LINKAGE - TARGET_ADJUST_LLVM_LINKAGE(GV,decl); -#endif /* TARGET_ADJUST_LLVM_LINKAGE */ - - handleVisibility(decl, GV); - - // If GV got renamed, then there is already an object with this name in - // the symbol table. If this happens, the old one must be a forward - // decl, just replace it with a cast of the new one. - if (GV->getName() != Name) { - Function *F = TheModule->getFunction(Name); - assert(F && F->isDeclaration() && "A function turned into a global?"); - - // Replace any uses of "F" with uses of GV. - Constant *FInNewType = TheFolder->CreateBitCast(GV, F->getType()); - F->replaceAllUsesWith(FInNewType); - - // Update the decl that points to F. - changeLLVMConstant(F, FInNewType); - - // Now we can give GV the proper name. - GV->takeName(F); - - // F is now dead, nuke it. - F->eraseFromParent(); - } - - } else { - GV = GVE; // Global already created, reuse it. - } - } - - if ((TREE_READONLY(decl) && !TREE_SIDE_EFFECTS(decl)) || - TREE_CODE(decl) == CONST_DECL) { - if (DECL_EXTERNAL(decl)) { - // Mark external globals constant even though they could be marked - // non-constant in the defining translation unit. The definition of the - // global determines whether the global is ultimately constant or not, - // marking this constant will allow us to do some extra (legal) - // optimizations that we would otherwise not be able to do. (In C++, - // any global that is 'C++ const' may not be readonly: it could have a - // dynamic initializer. - // - GV->setConstant(true); - } else { - // Mark readonly globals with constant initializers constant. - if (DECL_INITIAL(decl) != error_mark_node && // uninitialized? - DECL_INITIAL(decl) && - (TREE_CONSTANT(DECL_INITIAL(decl)) || - TREE_CODE(DECL_INITIAL(decl)) == STRING_CST)) - GV->setConstant(true); - } - } - - // Set thread local (TLS) - if (TREE_CODE(decl) == VAR_DECL && DECL_THREAD_LOCAL_P(decl)) - GV->setThreadLocal(true); - - assert((GV->isDeclaration() || SizeOfGlobalMatchesDecl(GV, decl)) && - "Global has unexpected initializer!"); - - return SET_DECL_LLVM(decl, GV); - } -//TODO timevar_pop(TV_LLVM_GLOBALS); -} - -/// make_definition_llvm - Ensures that the body or initial value of the given -/// GCC global will be output, and returns a declaration for it. -Value *make_definition_llvm(tree decl) { - // Only need to do something special for global variables. - if (TREE_CODE(decl) != CONST_DECL && TREE_CODE(decl) != VAR_DECL) - return DECL_LLVM(decl); - // Do not allocate storage for external references (eg: a "weakref" alias). - if (DECL_EXTERNAL(decl)) - return DECL_LLVM(decl); - // Can only assign initial values to global variables in static storage. - if (!TREE_STATIC(decl)) { - assert(!DECL_INITIAL(decl) && "Non-static global has initial value!"); - return DECL_LLVM(decl); - } - GlobalValue *GV = cast(DECL_LLVM(decl)); - // If we already output a definition for this declaration, then reuse it. - if (!GV->isDeclaration()) - return GV; - emit_global(decl); - return DECL_LLVM(decl); // Decl could have changed if it changed type. -} - -/// register_ctor_dtor - Called to register static ctors/dtors with LLVM. -/// Fn is a 'void()' ctor/dtor function to be run, initprio is the init -/// priority, and isCtor indicates whether this is a ctor or dtor. -void register_ctor_dtor(Function *Fn, int InitPrio, bool isCtor) { - (isCtor ? &StaticCtors:&StaticDtors)->push_back(std::make_pair(Fn, InitPrio)); -} - -//FIXME/// print_llvm - Print the specified LLVM chunk like an operand, called by -//FIXME/// print-tree.c for tree dumps. -//FIXMEvoid print_llvm(FILE *file, void *LLVM) { -//FIXME oFILEstream FS(file); -//FIXME FS << "LLVM: "; -//FIXME WriteAsOperand(FS, (Value*)LLVM, true, TheModule); -//FIXME} -//FIXME -//FIXME/// print_llvm_type - Print the specified LLVM type symbolically, called by -//FIXME/// print-tree.c for tree dumps. -//FIXMEvoid print_llvm_type(FILE *file, void *LLVM) { -//FIXME oFILEstream FS(file); -//FIXME FS << "LLVM: "; -//FIXME -//FIXME // FIXME: oFILEstream can probably be removed in favor of a new raw_ostream -//FIXME // adaptor which would be simpler and more efficient. In the meantime, just -//FIXME // adapt the adaptor. -//FIXME raw_os_ostream RO(FS); -//FIXME WriteTypeSymbolic(RO, (const Type*)LLVM, TheModule); -//FIXME} - -/// extractRegisterName - Get a register name given its decl. In 4.2 unlike 4.0 -/// these names have been run through set_user_assembler_name which means they -/// may have a leading star at this point; compensate. -const char* extractRegisterName(tree decl) { - const char* Name = IDENTIFIER_POINTER(DECL_ASSEMBLER_NAME(decl)); - return (*Name == '*') ? Name + 1 : Name; -} - -/// getLLVMAssemblerName - Get the assembler name (DECL_ASSEMBLER_NAME) for the -/// declaration, with any leading star replaced by '\1'. -Twine getLLVMAssemblerName(union tree_node *decl) { - tree Ident = DECL_ASSEMBLER_NAME(decl); - if (!Ident) - return ""; - - const char *Name = IDENTIFIER_POINTER(Ident); - if (*Name != '*') - return Name; - - return "\1" + Twine(Name + 1); -} - -/// FinalizePlugin - Shutdown the plugin. -static void FinalizePlugin(void) { - static bool Finalized = false; - if (Finalized) - return; - -#ifndef NDEBUG - delete PerModulePasses; - delete PerFunctionPasses; - delete CodeGenPasses; - delete TheModule; - llvm_shutdown(); -#endif - - Finalized = true; -} - -/// TakeoverAsmOutput - Obtain exclusive use of the assembly code output file. -/// Any GCC output will be thrown away. -static void TakeoverAsmOutput(void) { - // Calculate the output file name as in init_asm_output (toplev.c). - if (!dump_base_name && main_input_filename) - dump_base_name = main_input_filename[0] ? main_input_filename : "gccdump"; - - if (!main_input_filename && !asm_file_name) { - llvm_asm_file_name = "-"; - } else if (!asm_file_name) { - int len = strlen(dump_base_name); - char *dumpname = XNEWVEC(char, len + 6); - - memcpy(dumpname, dump_base_name, len + 1); - strip_off_ending(dumpname, len); - strcat(dumpname, ".s"); - llvm_asm_file_name = dumpname; - } else { - llvm_asm_file_name = asm_file_name; - } - - if (!SaveGCCOutput) { - // Redirect any GCC output to /dev/null. - asm_file_name = HOST_BIT_BUCKET; - } else { - // Save GCC output to a special file. Good for seeing how much pointless - // output gcc is producing. - int len = strlen(llvm_asm_file_name); - char *name = XNEWVEC(char, len + 5); - memcpy(name, llvm_asm_file_name, len + 1); - asm_file_name = strcat(name, ".gcc"); - } -} - - -//===----------------------------------------------------------------------===// -// Plugin interface -//===----------------------------------------------------------------------===// - -// This plugin's code is licensed under the GPLv2 or later. The LLVM libraries -// use the GPL compatible University of Illinois/NCSA Open Source License. The -// plugin is GPL compatible. -int plugin_is_GPL_compatible __attribute__ ((visibility("default"))); - - -/// llvm_start_unit - Perform late initialization. This is called by GCC just -/// before processing the compilation unit. -/// NOTE: called even when only doing syntax checking, so do not initialize the -/// module etc here. -static void llvm_start_unit(void * /*gcc_data*/, void * /*user_data*/) { - if (!quiet_flag) - errs() << "Starting compilation unit\n"; - -#ifdef ENABLE_LTO - // Output LLVM IR if the user requested generation of lto data. - EmitIR |= flag_generate_lto != 0; - // We have the same needs as GCC's LTO. Always claim to be doing LTO. - flag_lto = 1; - flag_whopr = 0; - flag_generate_lto = 1; - flag_whole_program = 0; -#else -# error "LTO support required but not enabled in GCC" -#endif - - // Stop GCC outputting serious amounts of debug info. - debug_hooks = &do_nothing_debug_hooks; -} - - -/// gate_emission - Whether to turn gimple into LLVM IR. -static bool gate_emission(void) { - // Don't bother doing anything if the program has errors. - return !errorcount && !sorrycount; // Do not process broken code. -} - -/// emit_current_function - Turn the current gimple function into LLVM IR. This -/// is called once for each function in the compilation unit. -static void emit_current_function() { - if (!quiet_flag && DECL_NAME(current_function_decl)) - errs() << IDENTIFIER_POINTER(DECL_NAME(current_function_decl)); - - // Convert the AST to raw/ugly LLVM code. - Function *Fn; - { - TreeToLLVM Emitter(current_function_decl); - Fn = Emitter.EmitFunction(); - } - - if (!errorcount && !sorrycount) { // Do not process broken code. - createPerFunctionOptimizationPasses(); - - if (PerFunctionPasses) - PerFunctionPasses->run(*Fn); - - // TODO: Nuke the .ll code for the function at -O[01] if we don't want to - // inline it or something else. - } -} - -/// emit_function - Turn a gimple function into LLVM IR. This is called once -/// for each function in the compilation unit if GCC optimizations are disabled. -static void emit_function(struct cgraph_node *node) { - if (errorcount || sorrycount) - return; // Do not process broken code. - - tree function = node->decl; - struct function *fn = DECL_STRUCT_FUNCTION(function); - - // Set the current function to this one. - // TODO: Make it so we don't need to do this. - assert(current_function_decl == NULL_TREE && cfun == NULL && - "Current function already set!"); - current_function_decl = function; - push_cfun (fn); - - // Convert the function. - emit_current_function(); - - // Done with this function. - current_function_decl = NULL; - pop_cfun (); -} - -/// GetLinkageForAlias - The given GCC declaration is an alias or thunk. Return -/// the appropriate LLVM linkage type for it. -static GlobalValue::LinkageTypes GetLinkageForAlias(tree decl) { - if (DECL_COMDAT(decl)) - // Need not be put out unless needed in this translation unit. - return GlobalValue::InternalLinkage; - - if (DECL_ONE_ONLY(decl)) - // Copies of this DECL in multiple translation units should be merged. - return GlobalValue::getWeakLinkage(flag_odr); - - if (DECL_WEAK(decl)) - // The user may have explicitly asked for weak linkage - ignore flag_odr. - return GlobalValue::WeakAnyLinkage; - - if (!TREE_PUBLIC(decl)) - // Not accessible from outside this translation unit. - return GlobalValue::InternalLinkage; - - if (DECL_EXTERNAL(decl)) - // Do not allocate storage, and refer to a definition elsewhere. - return GlobalValue::InternalLinkage; - - return GlobalValue::ExternalLinkage; -} - -/// ApplyVirtualOffset - Adjust 'this' by a virtual offset. -static Value *ApplyVirtualOffset(Value *This, HOST_WIDE_INT virtual_value, - LLVMBuilder &Builder) { - LLVMContext &Context = getGlobalContext(); - const Type *BytePtrTy = Type::getInt8PtrTy(Context); // i8* - const Type *HandleTy = BytePtrTy->getPointerTo(); // i8** - const Type *IntPtrTy = TheTarget->getTargetData()->getIntPtrType(Context); - - // The vptr is always at offset zero in the object. - Value *VPtr = Builder.CreateBitCast(This, HandleTy->getPointerTo()); // i8*** - - // Form the vtable address. - Value *VTableAddr = Builder.CreateLoad(VPtr); // i8** - - // Find the entry with the vcall offset. - Value *VOffset = ConstantInt::get(IntPtrTy, virtual_value); - VTableAddr = Builder.CreateBitCast(VTableAddr, BytePtrTy); - VTableAddr = Builder.CreateInBoundsGEP(VTableAddr, VOffset); - VTableAddr = Builder.CreateBitCast(VTableAddr, HandleTy); // i8** - - // Get the offset itself. - Value *VCallOffset = Builder.CreateLoad(VTableAddr); // i8* - VCallOffset = Builder.CreatePtrToInt(VCallOffset, IntPtrTy); - - // Adjust the 'this' pointer. - Value *Adjusted = Builder.CreateBitCast(This, BytePtrTy); - Adjusted = Builder.CreateInBoundsGEP(Adjusted, VCallOffset); - return Builder.CreateBitCast(Adjusted, This->getType()); -} - -/// emit_thunk - Turn a thunk into LLVM IR. -static void emit_thunk(struct cgraph_node *node) { - if (errorcount || sorrycount) - return; // Do not process broken code. - - Function *Thunk = cast(DECL_LLVM(node->decl)); - if (Thunk->isVarArg()) { - sorry("thunks to varargs functions not supported"); - return; - } - - // Mark the thunk as written so gcc doesn't waste time outputting it. - TREE_ASM_WRITTEN(node->decl) = 1; - - // Set the linkage and visibility. - Thunk->setLinkage(GetLinkageForAlias(node->decl)); - handleVisibility(node->decl, Thunk); - - // Whether the thunk adjusts 'this' before calling the thunk alias (otherwise - // it is the value returned by the alias that is adjusted). - bool ThisAdjusting = node->thunk.this_adjusting; - - LLVMContext &Context = getGlobalContext(); - const Type *BytePtrTy = Type::getInt8Ty(Context)->getPointerTo(); - const Type *IntPtrTy = TheTarget->getTargetData()->getIntPtrType(Context); - LLVMBuilder Builder(Context, *TheFolder); - Builder.SetInsertPoint(BasicBlock::Create(Context, "entry", Thunk)); - - // Whether we found 'this' yet. When not 'this adjusting', setting this to - // 'true' means all parameters (including 'this') are passed through as is. - bool FoundThis = !ThisAdjusting; - - SmallVector Arguments; - for (Function::arg_iterator AI = Thunk->arg_begin(), AE = Thunk->arg_end(); - AI != AE; ++AI) { - // While 'this' is always the first GCC argument, we may have introduced - // additional artificial arguments for doing struct return or passing a - // nested function static chain. Look for 'this' while passing through - // all arguments except for 'this' unchanged. - if (FoundThis || AI->hasStructRetAttr() || AI->hasNestAttr()) { - Arguments.push_back(AI); - continue; - } - - FoundThis = true; // The current argument is 'this'. - assert(AI->getType()->isPointerTy() && "Wrong type for 'this'!"); - Value *This = AI; - - // Adjust 'this' according to the thunk offsets. First, the fixed offset. - if (node->thunk.fixed_offset) { - Value *Offset = ConstantInt::get(IntPtrTy, node->thunk.fixed_offset); - This = Builder.CreateBitCast(This, BytePtrTy); - This = Builder.CreateInBoundsGEP(This, Offset); - This = Builder.CreateBitCast(This, AI->getType()); - } - - // Then by the virtual offset, if any. - if (node->thunk.virtual_offset_p) - This = ApplyVirtualOffset(This, node->thunk.virtual_value, Builder); - - Arguments.push_back(This); - } - - CallInst *Call = Builder.CreateCall(DECL_LLVM(node->thunk.alias), - Arguments.begin(), Arguments.end()); - Call->setCallingConv(Thunk->getCallingConv()); - Call->setAttributes(Thunk->getAttributes()); - // All parameters except 'this' are passed on unchanged - this is a tail call. - Call->setTailCall(); - - if (ThisAdjusting) { - // Return the value unchanged. - if (Thunk->getReturnType()->isVoidTy()) - Builder.CreateRetVoid(); - else - Builder.CreateRet(Call); - return; - } - - // Covariant return thunk - adjust the returned value by the thunk offsets. - assert(Call->getType()->isPointerTy() && "Only know how to adjust pointers!"); - Value *RetVal = Call; - - // First check if the returned value is NULL. - Value *Zero = Constant::getNullValue(RetVal->getType()); - Value *isNull = Builder.CreateICmpEQ(RetVal, Zero); - - BasicBlock *isNullBB = BasicBlock::Create(Context, "isNull", Thunk); - BasicBlock *isNotNullBB = BasicBlock::Create(Context, "isNotNull", Thunk); - Builder.CreateCondBr(isNull, isNullBB, isNotNullBB); - - // If it is NULL, return it without any adjustment. - Builder.SetInsertPoint(isNullBB); - Builder.CreateRet(Zero); - - // Otherwise, first adjust by the virtual offset, if any. - Builder.SetInsertPoint(isNotNullBB); - if (node->thunk.virtual_offset_p) - RetVal = ApplyVirtualOffset(RetVal, node->thunk.virtual_value, Builder); - - // Then move 'this' by the fixed offset. - if (node->thunk.fixed_offset) { - Value *Offset = ConstantInt::get(IntPtrTy, node->thunk.fixed_offset); - RetVal = Builder.CreateBitCast(RetVal, BytePtrTy); - RetVal = Builder.CreateInBoundsGEP(RetVal, Offset); - RetVal = Builder.CreateBitCast(RetVal, Thunk->getReturnType()); - } - - // Return the adjusted value. - Builder.CreateRet(RetVal); -} - -/// emit_alias - Given decl and target emit alias to target. -static void emit_alias(tree decl, tree target) { - if (errorcount || sorrycount) - return; // Do not process broken code. - - // Get or create LLVM global for our alias. - GlobalValue *V = cast(DECL_LLVM(decl)); - - bool weakref = lookup_attribute("weakref", DECL_ATTRIBUTES(decl)); - if (weakref) - while (IDENTIFIER_TRANSPARENT_ALIAS(target)) - target = TREE_CHAIN(target); - - if (TREE_CODE(target) == IDENTIFIER_NODE) { - if (struct cgraph_node *fnode = cgraph_node_for_asm(target)) - target = fnode->decl; - else if (struct varpool_node *vnode = varpool_node_for_asm(target)) - target = vnode->decl; - } - - GlobalValue *Aliasee = 0; - if (TREE_CODE(target) == IDENTIFIER_NODE) { - if (!weakref) { - error("%q+D aliased to undefined symbol %qs", decl, - IDENTIFIER_POINTER(target)); - return; - } - - // weakref to external symbol. - if (GlobalVariable *GV = dyn_cast(V)) - Aliasee = new GlobalVariable(*TheModule, GV->getType(), - GV->isConstant(), - GlobalVariable::ExternalWeakLinkage, NULL, - IDENTIFIER_POINTER(target)); - else if (Function *F = dyn_cast(V)) - Aliasee = Function::Create(F->getFunctionType(), - Function::ExternalWeakLinkage, - IDENTIFIER_POINTER(target), - TheModule); - else - assert(0 && "Unsuported global value"); - } else { - Aliasee = cast(DEFINITION_LLVM(target)); - } - - GlobalValue::LinkageTypes Linkage = GetLinkageForAlias(decl); - - if (Linkage != GlobalValue::InternalLinkage) { - // Create the LLVM alias. - GlobalAlias* GA = new GlobalAlias(Aliasee->getType(), Linkage, "", - Aliasee, TheModule); - handleVisibility(decl, GA); - - // Associate it with decl instead of V. - V->replaceAllUsesWith(ConstantExpr::getBitCast(GA, V->getType())); - changeLLVMConstant(V, GA); - GA->takeName(V); - } else { - // Make all users of the alias directly use the aliasee instead. - V->replaceAllUsesWith(ConstantExpr::getBitCast(Aliasee, V->getType())); - changeLLVMConstant(V, Aliasee); - } - - V->eraseFromParent(); - - // Mark the alias as written so gcc doesn't waste time outputting it. - TREE_ASM_WRITTEN(decl) = 1; -} - -/// emit_same_body_alias - Turn a same-body alias into LLVM IR. -static void emit_same_body_alias(struct cgraph_node *alias, - struct cgraph_node * /*target*/) { - if (errorcount || sorrycount) - return; // Do not process broken code. - - // If the target is not "extern inline" then output an ordinary alias. - tree target = alias->thunk.alias; - if (!DECL_EXTERNAL(target)) { - emit_alias(alias->decl, target); - return; - } - - // Same body aliases have the property that if the body of the aliasee is not - // output then neither are the aliases. To arrange this for "extern inline" - // functions, which have AvailableExternally linkage in LLVM, make all users - // of the alias directly use the aliasee instead. - GlobalValue *Alias = cast(DECL_LLVM(alias->decl)); - GlobalValue *Aliasee = cast(DEFINITION_LLVM(target)); - Alias->replaceAllUsesWith(ConstantExpr::getBitCast(Aliasee,Alias->getType())); - changeLLVMConstant(Alias, Aliasee); - Alias->eraseFromParent(); - - // Mark the alias as written so gcc doesn't waste time outputting it. - TREE_ASM_WRITTEN(alias->decl) = 1; -} - -/// emit_file_scope_asm - Emit the specified string as a file-scope inline -/// asm block. -static void emit_file_scope_asm(tree string) { - if (errorcount || sorrycount) - return; // Do not process broken code. - - if (TREE_CODE(string) == ADDR_EXPR) - string = TREE_OPERAND(string, 0); - TheModule->appendModuleInlineAsm(TREE_STRING_POINTER (string)); -} - -/// emit_functions - Turn all functions in the compilation unit into LLVM IR. -static void emit_functions(cgraph_node_set set -#if (GCC_MINOR > 5) - , varpool_node_set /*vset*/ -#endif - ) { - if (errorcount || sorrycount) - return; // Do not process broken code. - - InitializeBackend(); - - // Visit each function with a body, outputting it only once (the same function - // can appear in multiple cgraph nodes due to cloning). - SmallPtrSet Visited; - for (cgraph_node_set_iterator csi = csi_start(set); !csi_end_p(csi); - csi_next(&csi)) { - struct cgraph_node *node = csi_node(csi); - if (node->analyzed && Visited.insert(node->decl)) - // If GCC optimizations are enabled then functions are output later, in - // place of gimple to RTL conversion. - if (!EnableGCCOptimizations) - emit_function(node); - - // Output any same-body aliases or thunks in the order they were created. - struct cgraph_node *alias, *next; - for (alias = node->same_body; alias && alias->next; alias = alias->next) ; - for (; alias; alias = next) { - next = alias->previous; - if (alias->thunk.thunk_p) - emit_thunk(alias); - else - emit_same_body_alias(alias, node); - } - } - - // Emit any file-scope asms. - for (struct cgraph_asm_node *can = cgraph_asm_nodes; can; can = can->next) - emit_file_scope_asm(can->asm_str); - - // Remove the asms so gcc doesn't waste time outputting them. - cgraph_asm_nodes = NULL; -} - -/// pass_emit_functions - IPA pass that turns gimple functions into LLVM IR. -static struct ipa_opt_pass_d pass_emit_functions = { - { - IPA_PASS, - "emit_functions", /* name */ - gate_emission, /* gate */ - NULL, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - }, - NULL, /* generate_summary */ - emit_functions, /* write_summary */ - NULL, /* read_summary */ -#if (GCC_MINOR > 5) - NULL, /* write_optimization_summary */ - NULL, /* read_optimization_summary */ -#else - NULL, /* function_read_summary */ -#endif - NULL, /* stmt_fixup */ - 0, /* function_transform_todo_flags_start */ - NULL, /* function_transform */ - NULL /* variable_transform */ -}; - -/// emit_variables - Output GCC global variables to the LLVM IR. -static void emit_variables(cgraph_node_set /*set*/ -#if (GCC_MINOR > 5) - , varpool_node_set /*vset*/ -#endif - ) { - if (errorcount || sorrycount) - return; // Do not process broken code. - - InitializeBackend(); - - // Output all externally visible global variables, whether they are used in - // this compilation unit or not, as well as any internal variables explicitly - // marked with the 'used' attribute. All other internal variables are output - // when their user is, or discarded if unused. - struct varpool_node *vnode; - FOR_EACH_STATIC_VARIABLE (vnode) { - tree var = vnode->decl; - if (TREE_CODE(var) == VAR_DECL && - (TREE_PUBLIC(var) || DECL_PRESERVE_P(var))) - emit_global(var); - } - - // Emit any aliases. - alias_pair *p; - for (unsigned i = 0; VEC_iterate(alias_pair, alias_pairs, i, p); i++) - emit_alias(p->decl, p->target); -} - -/// pass_emit_variables - IPA pass that turns GCC variables into LLVM IR. -static struct ipa_opt_pass_d pass_emit_variables = { - { - IPA_PASS, - "emit_variables", /* name */ - gate_emission, /* gate */ - NULL, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - }, - NULL, /* generate_summary */ - emit_variables, /* write_summary */ - NULL, /* read_summary */ -#if (GCC_MINOR > 5) - NULL, /* write_optimization_summary */ - NULL, /* read_optimization_summary */ -#else - NULL, /* function_read_summary */ -#endif - NULL, /* stmt_fixup */ - 0, /* function_transform_todo_flags_start */ - NULL, /* function_transform */ - NULL /* variable_transform */ -}; - -/// disable_rtl - Mark the current function as having been written to assembly. -static unsigned int disable_rtl(void) { - // Free any data structures. - execute_free_datastructures(); - - // Mark the function as written. - TREE_ASM_WRITTEN(current_function_decl) = 1; - - // That's all folks! - return 0; -} - -/// pass_disable_rtl - RTL pass that pretends to codegen functions, but actually -/// only does hoop jumping required by GCC. -static struct rtl_opt_pass pass_disable_rtl = -{ - { - RTL_PASS, - "disable_rtl", /* name */ - NULL, /* gate */ - disable_rtl, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - PROP_ssa | PROP_trees, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } -}; - -/// rtl_emit_function - Turn a gimple function into LLVM IR. This is called -/// once for each function in the compilation unit if GCC optimizations are -/// enabled. -static unsigned int rtl_emit_function (void) { - InitializeBackend(); - - // Convert the function. - emit_current_function(); - - // Free any data structures. - execute_free_datastructures(); - - // Finally, we have written out this function! - TREE_ASM_WRITTEN(current_function_decl) = 1; - return 0; -} - -/// pass_rtl_emit_function - RTL pass that converts a function to LLVM IR. -static struct rtl_opt_pass pass_rtl_emit_function = -{ - { - RTL_PASS, - "rtl_emit_function", /* name */ - gate_emission, /* gate */ - rtl_emit_function, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - PROP_ssa | PROP_gimple_leh | PROP_gimple_lomp - | PROP_cfg, /* properties_required */ - 0, /* properties_provided */ - PROP_ssa | PROP_trees, /* properties_destroyed */ - TODO_verify_ssa | TODO_verify_flow - | TODO_verify_stmts, /* todo_flags_start */ - TODO_ggc_collect /* todo_flags_finish */ - } -}; - - -/// llvm_finish - Run shutdown code when GCC exits. -static void llvm_finish(void * /*gcc_data*/, void * /*user_data*/) { - FinalizePlugin(); -} - -/// llvm_finish_unit - Finish the .s file. This is called by GCC once the -/// compilation unit has been completely processed. -static void llvm_finish_unit(void * /*gcc_data*/, void * /*user_data*/) { - if (errorcount || sorrycount) - return; // Do not process broken code. - - if (!quiet_flag) - errs() << "Finishing compilation unit\n"; - - InitializeBackend(); - -//TODO timevar_push(TV_LLVM_PERFILE); - LLVMContext &Context = getGlobalContext(); - - createPerFunctionOptimizationPasses(); -//TODO -//TODO if (flag_pch_file) { -//TODO writeLLVMTypesStringTable(); -//TODO writeLLVMValues(); -//TODO } - -//TODO for (Module::iterator I = TheModule->begin(), E = TheModule->end(); -//TODO I != E; ++I) -//TODO if (!I->isDeclaration()) { -//TODO if (flag_disable_red_zone) -//TODO I->addFnAttr(Attribute::NoRedZone); -//TODO if (flag_no_implicit_float) -//TODO I->addFnAttr(Attribute::NoImplicitFloat); -//TODO } - - // Add an llvm.global_ctors global if needed. - if (!StaticCtors.empty()) - CreateStructorsList(StaticCtors, "llvm.global_ctors"); - // Add an llvm.global_dtors global if needed. - if (!StaticDtors.empty()) - CreateStructorsList(StaticDtors, "llvm.global_dtors"); - - if (!AttributeUsedGlobals.empty()) { - std::vector AUGs; - const Type *SBP = Type::getInt8PtrTy(Context); - for (SmallSetVector::iterator - AI = AttributeUsedGlobals.begin(), - AE = AttributeUsedGlobals.end(); AI != AE; ++AI) { - Constant *C = *AI; - AUGs.push_back(TheFolder->CreateBitCast(C, SBP)); - } - - ArrayType *AT = ArrayType::get(SBP, AUGs.size()); - Constant *Init = ConstantArray::get(AT, AUGs); - GlobalValue *gv = new GlobalVariable(*TheModule, AT, false, - GlobalValue::AppendingLinkage, Init, - "llvm.used"); - gv->setSection("llvm.metadata"); - AttributeUsedGlobals.clear(); - } - - if (!AttributeCompilerUsedGlobals.empty()) { - std::vector ACUGs; - const Type *SBP = Type::getInt8PtrTy(Context); - for (SmallSetVector::iterator - AI = AttributeCompilerUsedGlobals.begin(), - AE = AttributeCompilerUsedGlobals.end(); AI != AE; ++AI) { - Constant *C = *AI; - ACUGs.push_back(TheFolder->CreateBitCast(C, SBP)); - } - - ArrayType *AT = ArrayType::get(SBP, ACUGs.size()); - Constant *Init = ConstantArray::get(AT, ACUGs); - GlobalValue *gv = new GlobalVariable(*TheModule, AT, false, - GlobalValue::AppendingLinkage, Init, - "llvm.compiler.used"); - gv->setSection("llvm.metadata"); - AttributeCompilerUsedGlobals.clear(); - } - - // Add llvm.global.annotations - if (!AttributeAnnotateGlobals.empty()) { - Constant *Array = ConstantArray::get( - ArrayType::get(AttributeAnnotateGlobals[0]->getType(), - AttributeAnnotateGlobals.size()), - AttributeAnnotateGlobals); - GlobalValue *gv = new GlobalVariable(*TheModule, Array->getType(), false, - GlobalValue::AppendingLinkage, Array, - "llvm.global.annotations"); - gv->setSection("llvm.metadata"); - AttributeAnnotateGlobals.clear(); - } - - // Finish off the per-function pass. - if (PerFunctionPasses) - PerFunctionPasses->doFinalization(); - -//TODO // Emit intermediate file before module level optimization passes are run. -//TODO if (flag_debug_llvm_module_opt) { -//TODO -//TODO static PassManager *IntermediatePM = new PassManager(); -//TODO IntermediatePM->add(new TargetData(*TheTarget->getTargetData())); -//TODO -//TODO char asm_intermediate_out_filename[MAXPATHLEN]; -//TODO strcpy(&asm_intermediate_out_filename[0], llvm_asm_file_name); -//TODO strcat(&asm_intermediate_out_filename[0],".0"); -//TODO FILE *asm_intermediate_out_file = fopen(asm_intermediate_out_filename, "w+b"); -//TODO AsmIntermediateOutStream = new oFILEstream(asm_intermediate_out_file); -//TODO raw_ostream *AsmIntermediateRawOutStream = -//TODO new raw_os_ostream(*AsmIntermediateOutStream); -//TODO if (EmitIR && 0) -//TODO IntermediatePM->add(createBitcodeWriterPass(*AsmIntermediateOutStream)); -//TODO if (EmitIR) -//TODO IntermediatePM->add(createPrintModulePass(AsmIntermediateRawOutStream)); -//TODO IntermediatePM->run(*TheModule); -//TODO AsmIntermediateRawOutStream->flush(); -//TODO delete AsmIntermediateRawOutStream; -//TODO AsmIntermediateRawOutStream = 0; -//TODO AsmIntermediateOutStream->flush(); -//TODO fflush(asm_intermediate_out_file); -//TODO delete AsmIntermediateOutStream; -//TODO AsmIntermediateOutStream = 0; -//TODO } - - // Run module-level optimizers, if any are present. - createPerModuleOptimizationPasses(); - if (PerModulePasses) - PerModulePasses->run(*TheModule); - - // Run the code generator, if present. - if (CodeGenPasses) { - CodeGenPasses->doInitialization(); - for (Module::iterator I = TheModule->begin(), E = TheModule->end(); - I != E; ++I) - if (!I->isDeclaration()) - CodeGenPasses->run(*I); - CodeGenPasses->doFinalization(); - } - - FormattedOutStream.flush(); - OutStream->flush(); -//TODO delete AsmOutRawStream; -//TODO AsmOutRawStream = 0; -//TODO delete AsmOutStream; -//TODO AsmOutStream = 0; -//TODO timevar_pop(TV_LLVM_PERFILE); - - // We have finished - shutdown the plugin. Doing this here ensures that timer - // info and other statistics are not intermingled with those produced by GCC. - FinalizePlugin(); -} - - -/// gate_null - Gate method for a pass that does nothing. -static bool gate_null (void) { - return false; -} - -/// pass_gimple_null - Gimple pass that does nothing. -static struct gimple_opt_pass pass_gimple_null = -{ - { - GIMPLE_PASS, - "*gimple_null", /* name */ - gate_null, /* gate */ - NULL, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } -}; - -/// execute_correct_state - Correct the cgraph state to ensure that newly -/// inserted functions are processed before being converted to LLVM IR. -static unsigned int execute_correct_state (void) { - if (cgraph_state < CGRAPH_STATE_IPA_SSA) - cgraph_state = CGRAPH_STATE_IPA_SSA; - return 0; -} - -/// gate_correct_state - Gate method for pass_gimple_correct_state. -static bool gate_correct_state (void) { - return true; -} - -/// pass_gimple_correct_state - Gimple pass that corrects the cgraph state so -/// newly inserted functions are processed before being converted to LLVM IR. -static struct gimple_opt_pass pass_gimple_correct_state = -{ - { - GIMPLE_PASS, - "*gimple_correct_state", /* name */ - gate_correct_state, /* gate */ - execute_correct_state, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } -}; - -/// pass_ipa_null - IPA pass that does nothing. -static struct ipa_opt_pass_d pass_ipa_null = { - { - IPA_PASS, - "*ipa_null", /* name */ - gate_null, /* gate */ - NULL, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - }, - NULL, /* generate_summary */ - NULL, /* write_summary */ - NULL, /* read_summary */ - NULL, /* function_read_summary */ - NULL, /* stmt_fixup */ - 0, /* TODOs */ - NULL, /* function_transform */ - NULL /* variable_transform */ -}; - -/// pass_rtl_null - RTL pass that does nothing. -static struct rtl_opt_pass pass_rtl_null = -{ - { - RTL_PASS, - "*rtl_null", /* name */ - gate_null, /* gate */ - NULL, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } -}; - -/// pass_simple_ipa_null - Simple IPA pass that does nothing. -static struct simple_ipa_opt_pass pass_simple_ipa_null = -{ - { - SIMPLE_IPA_PASS, - "*simple_ipa_null", /* name */ - gate_null, /* gate */ - NULL, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } -}; - - -// Garbage collector roots. -extern const struct ggc_cache_tab gt_ggc_rc__gt_llvm_cache_h[]; - - -/// PluginFlags - Flag arguments for the plugin. - -struct FlagDescriptor { - const char *Key; // The plugin argument is -fplugin-arg-llvm-KEY. - bool *Flag; // Set to true if the flag is seen. -}; - -static FlagDescriptor PluginFlags[] = { - { "debug-pass-structure", &DebugPassStructure}, - { "debug-pass-arguments", &DebugPassArguments}, - { "disable-llvm-optzns", &DisableLLVMOptimizations }, - { "enable-gcc-optzns", &EnableGCCOptimizations }, - { "emit-ir", &EmitIR }, - { "save-gcc-output", &SaveGCCOutput }, - { NULL, NULL } // Terminator. -}; - - -/// llvm_plugin_info - Information about this plugin. Users can access this -/// using "gcc --help -v". -static struct plugin_info llvm_plugin_info = { - REVISION, // version - // TODO provide something useful here - NULL // help -}; - -static bool version_check(struct plugin_gcc_version *gcc_version, - struct plugin_gcc_version *plugin_version) { - // Make it possible to turn off the version check - useful for testing gcc - // bootstrap. - if (getenv("dragonegg_disable_version_check")) - return true; - - // Check that the running gcc has exactly the same version as the gcc we were - // built against. This strict check seems wise when developing against a fast - // moving gcc tree. TODO: Use a milder check if doing a "release build". - return plugin_default_version_check (gcc_version, plugin_version); -} - - -/// plugin_init - Plugin initialization routine, called by GCC. This is the -/// first code executed in the plugin (except for constructors). Configure -/// the plugin and setup GCC, taking over optimization and code generation. -int __attribute__ ((visibility("default"))) -plugin_init(struct plugin_name_args *plugin_info, - struct plugin_gcc_version *version) { - const char *plugin_name = plugin_info->base_name; - struct register_pass_info pass_info; - - // Check that the plugin is compatible with the running gcc. - if (!version_check (&gcc_version, version)) { - errs() << "Incompatible plugin version\n"; - return 1; - } - - // Provide GCC with our version and help information. - register_callback (plugin_name, PLUGIN_INFO, NULL, &llvm_plugin_info); - - // Process any plugin arguments. - { - struct plugin_argument *argv = plugin_info->argv; - int argc = plugin_info->argc; - - for (int i = 0; i < argc; ++i) { - bool Found = false; - - // Look for a matching flag. - for (FlagDescriptor *F = PluginFlags; F->Key; ++F) { - if (strcmp (argv[i].key, F->Key)) - continue; - - if (argv[i].value) - warning (0, G_("option '-fplugin-arg-%s-%s=%s' ignored" - " (superfluous '=%s')"), - plugin_name, argv[i].key, argv[i].value, argv[i].value); - else - *F->Flag = true; - - Found = true; - break; - } - - if (!Found) - warning (0, G_("plugin %qs: unrecognized argument %qs ignored"), - plugin_name, argv[i].key); - } - } - - // Obtain exclusive use of the assembly code output file. This stops GCC from - // writing anything at all to the assembly file - only we get to write to it. - TakeoverAsmOutput(); - - // Register our garbage collector roots. - register_callback (plugin_name, PLUGIN_REGISTER_GGC_CACHES, NULL, - (void *)gt_ggc_rc__gt_llvm_cache_h); - - // Perform late initialization just before processing the compilation unit. - register_callback (plugin_name, PLUGIN_START_UNIT, llvm_start_unit, NULL); - - // Turn off all gcc optimization passes. - if (!EnableGCCOptimizations) { - // TODO: figure out a good way of turning off ipa optimization passes. - // Could just set optimize to zero (after taking a copy), but this would - // also impact front-end optimizations. - - // Leave pass_inline_parameters. Otherwise our vector lowering fails since - // immediates have not been propagated into builtin callsites. - - // Leave pass_ipa_function_and_variable_visibility. Needed for correctness. - - // Turn off pass_ipa_early_inline. - pass_info.pass = &pass_simple_ipa_null.pass; - pass_info.reference_pass_name = "einline_ipa"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Leave pass_ipa_free_lang_data. - - // Leave pass pass_early_local_passes::pass_fixup_cfg. ??? - - // Leave pass pass_early_local_passes::pass_tree_profile. - - // Leave pass_early_local_passes::pass_cleanup_cfg. ??? - - // Leave pass_early_local_passes::pass_init_datastructures. ??? - - // Leave pass_early_local_passes::pass_expand_omp. - - // Leave pass_early_local_passes::pass_referenced_vars. ??? - - // Leave pass_early_local_passes::pass_build_ssa. - - // Leave pass_early_local_passes::pass_early_warn_uninitialized. - - // Leave pass_early_local_passes::pass_rebuild_cgraph_edges. ??? - - // Leave pass_early_local_passes::pass_early_inline. Otherwise our vector - // lowering fails since immediates have not been propagated into builtin - // callsites. - - // Insert a pass that ensures that any newly inserted functions, for example - // those generated by OMP expansion, are processed before being converted to - // LLVM IR. - pass_info.pass = &pass_gimple_correct_state.pass; - pass_info.reference_pass_name = "early_optimizations"; - pass_info.ref_pass_instance_number = 1; - pass_info.pos_op = PASS_POS_INSERT_BEFORE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Turn off pass_early_local_passes::pass_all_early_optimizations. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "early_optimizations"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Leave pass_early_local_passes::pass_release_ssa_names. ??? - - // Leave pass_early_local_passes::pass_rebuild_cgraph_edges. ??? - - // Leave pass_inline_parameters. Otherwise our vector lowering fails since - // immediates have not been propagated into builtin callsites. - - // Turn off pass_ipa_increase_alignment. - pass_info.pass = &pass_simple_ipa_null.pass; - pass_info.reference_pass_name = "increase_alignment"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Turn off pass_ipa_matrix_reorg. - pass_info.pass = &pass_simple_ipa_null.pass; - pass_info.reference_pass_name = "matrix-reorg"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Leave pass_ipa_whole_program_visibility. ??? - - // Turn off pass_ipa_cp. - pass_info.pass = &pass_ipa_null.pass; - pass_info.reference_pass_name = "cp"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Turn off pass_ipa_inline. - pass_info.pass = &pass_ipa_null.pass; - pass_info.reference_pass_name = "inline"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Turn off pass_ipa_reference. - pass_info.pass = &pass_ipa_null.pass; - pass_info.reference_pass_name = "static-var"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Turn off pass_ipa_pure_const. - pass_info.pass = &pass_ipa_null.pass; - pass_info.reference_pass_name = "pure-const"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Turn off pass_ipa_type_escape. - pass_info.pass = &pass_simple_ipa_null.pass; - pass_info.reference_pass_name = "type-escape-var"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Turn off pass_ipa_pta. - pass_info.pass = &pass_simple_ipa_null.pass; - pass_info.reference_pass_name = "pta"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Turn off pass_ipa_struct_reorg. - pass_info.pass = &pass_simple_ipa_null.pass; - pass_info.reference_pass_name = "ipa_struct_reorg"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - } - - // Replace the LTO gimple pass. If GCC optimizations are disabled then this - // is where functions are converted to LLVM IR. When GCC optimizations are - // enabled then only aliases and thunks are output here, with functions being - // converted later after all tree optimizers have run. - pass_info.pass = &pass_emit_functions.pass; - pass_info.reference_pass_name = "lto_gimple_out"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Replace the LTO decls pass with conversion of global variables to LLVM IR. - pass_info.pass = &pass_emit_variables.pass; - pass_info.reference_pass_name = "lto_decls_out"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - -#if (GCC_MINOR < 6) - // Disable any other LTO passes. - pass_info.pass = &pass_ipa_null.pass; - pass_info.reference_pass_name = "lto_wpa_fixup"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); -#endif - - if (!EnableGCCOptimizations) { - // Disable pass_lower_eh_dispatch, which runs after LLVM conversion. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "ehdisp"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Disable pass_all_optimizations, which runs after LLVM conversion. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "*all_optimizations"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Disable pass_lower_complex_O0, which runs after LLVM conversion. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "cplxlower0"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Disable pass_cleanup_eh, which runs after LLVM conversion. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "ehcleanup"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Disable pass_lower_resx, which runs after LLVM conversion. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "resx"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Disable pass_nrv, which runs after LLVM conversion. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "nrv"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Disable pass_mudflap_2, which runs after LLVM conversion. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "mudflap2"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Disable pass_cleanup_cfg_post_optimizing, which runs after LLVM conversion. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "optimized"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // TODO: Disable pass_warn_function_noreturn? - } - - // Replace rtl expansion. - if (!EnableGCCOptimizations) { - // Replace rtl expansion with a pass that pretends to codegen functions, but - // actually only does the hoop jumping that GCC requires at this point. - pass_info.pass = &pass_disable_rtl.pass; - pass_info.reference_pass_name = "expand"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - } else { - // Replace rtl expansion with a pass that converts functions to LLVM IR. - pass_info.pass = &pass_rtl_emit_function.pass; - pass_info.reference_pass_name = "expand"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - } - - // Turn off all other rtl passes. - pass_info.pass = &pass_gimple_null.pass; - pass_info.reference_pass_name = "*rest_of_compilation"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - pass_info.pass = &pass_rtl_null.pass; - pass_info.reference_pass_name = "*clean_state"; - pass_info.ref_pass_instance_number = 0; - pass_info.pos_op = PASS_POS_REPLACE; - register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); - - // Finish the .s file once the compilation unit has been completely processed. - register_callback (plugin_name, PLUGIN_FINISH_UNIT, llvm_finish_unit, NULL); - - // Run shutdown code when GCC exits. - register_callback (plugin_name, PLUGIN_FINISH, llvm_finish, NULL); - - return 0; -} Removed: dragonegg/trunk/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Constants.cpp?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/Constants.cpp (original) +++ dragonegg/trunk/Constants.cpp (removed) @@ -1,1354 +0,0 @@ -//===------- Constants.cpp - Converting and working with constants --------===// -// -// Copyright (C) 2011 Duncan Sands -// -// This file is part of DragonEgg. -// -// DragonEgg is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free Software -// Foundation; either version 2, or (at your option) any later version. -// -// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -// A PARTICULAR PURPOSE. See the GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along with -// DragonEgg; see the file COPYING. If not, write to the Free Software -// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. -// -//===----------------------------------------------------------------------===// -// This is the code that converts GCC constants to LLVM. -//===----------------------------------------------------------------------===// - -// Plugin headers -#include "dragonegg/Constants.h" -#include "dragonegg/Internals.h" -#include "dragonegg/Trees.h" -#include "dragonegg/ADT/IntervalList.h" -#include "dragonegg/ADT/Range.h" - -// LLVM headers -#include "llvm/GlobalVariable.h" -#include "llvm/LLVMContext.h" -#include "llvm/Support/Host.h" -#include "llvm/Target/TargetData.h" - -// System headers -#include - -// GCC headers -extern "C" { -#include "config.h" -// Stop GCC declaring 'getopt' as it can clash with the system's declaration. -#undef HAVE_DECL_GETOPT -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" - -#include "flags.h" -#include "tm_p.h" -} - -static LLVMContext &Context = getGlobalContext(); - -//===----------------------------------------------------------------------===// -// ... InterpretAsType ... -//===----------------------------------------------------------------------===// - -typedef Range SignedRange; - -/// BitSlice - A contiguous range of bits held in memory. -class BitSlice { - SignedRange R; - Constant *Contents; // Null if and only if the range is empty. - - bool contentsValid() const { - if (empty()) - return !Contents; - return Contents && isa(Contents->getType()) && - getBitWidth() == Contents->getType()->getPrimitiveSizeInBits(); - } - -public: - /// BitSlice - Default constructor: empty bit range. - BitSlice() : R(), Contents(0) {} - - /// BitSlice - Constructor for the given range of bits. The bits themselves - /// are supplied in 'contents' as a constant of integer type (if the range is - /// empty then 'contents' must be null). On little-endian machines the least - /// significant bit of 'contents' corresponds to the first bit of the range - /// (aka "First"), while on big-endian machines it corresponds to the last bit - /// of the range (aka "Last-1"). - BitSlice(SignedRange r, Constant *contents) : R(r), Contents(contents) { - assert(contentsValid() && "Contents do not match range"); - } - - /// BitSlice - Constructor for the range of bits ['first', 'last'). - BitSlice(int first, int last, Constant *contents) - : R(first, last), Contents(contents) { - assert(contentsValid() && "Contents do not match range"); - } - - /// empty - Return whether the bit range is empty. - bool empty() const { - return R.empty(); - } - - /// getBitWidth - Return the number of bits in the range. - unsigned getBitWidth() const { - return R.getWidth(); - } - - /// getFirst - Return the position of the first bit in the range. - unsigned getFirst() const { - return R.getFirst(); - } - - /// getLast - Return the position of the last bit defining the range. - unsigned getLast() const { - return R.getLast(); - } - - /// getRange - Return the range of bits in this slice. - SignedRange getRange() const { - return R; - } - - /// Displace - Return the result of sliding all bits by the given offset. - BitSlice Displace(int Offset) const { - return BitSlice(R.Displace(Offset), Contents); - } - - /// getBits - Return the bits in the given range. The supplied range need not - /// be contained in the range of the slice, but if not then the bits outside - /// the slice get an undefined value. The bits are returned as a constant of - /// integer type. On little-endian machine the least significant bit of the - /// returned value corresponds to the first bit of the range (aka "First"), - /// while on big-endian machines it corresponds to the last bit of the range - /// (aka "Last-1"). - Constant *getBits(SignedRange r) const; - - /// ExtendRange - Extend the slice to a wider range. The value of the added - /// bits is undefined. - BitSlice ExtendRange(SignedRange r) const; - - /// ReduceRange - Reduce the slice to a smaller range discarding any bits that - /// do not belong to the new range. - BitSlice ReduceRange(SignedRange r) const; - - /// Merge - Join the slice with another (which must be disjoint), forming the - /// convex hull of the ranges. The bits in the range of one of the slices are - /// those of that slice. Any other bits have an undefined value. - void Merge(const BitSlice &other); -}; - -/// ExtendRange - Extend the slice to a wider range. The value of the added -/// bits is undefined. -BitSlice BitSlice::ExtendRange(SignedRange r) const { - assert(r.contains(R) && "Not an extension!"); - // Quick exit if the range did not actually increase. - if (R == r) - return *this; - assert(!r.empty() && "Empty ranges did not evaluate as equal?"); - const Type *ExtTy = IntegerType::get(Context, r.getWidth()); - // If the slice contains no bits then every bit of the extension is undefined. - if (empty()) - return BitSlice(r, UndefValue::get(ExtTy)); - // Extend the contents to the new type. - Constant *C = TheFolder->CreateZExtOrBitCast(Contents, ExtTy); - // Position the old contents correctly inside the new contents. - unsigned deltaFirst = R.getFirst() - r.getFirst(); - unsigned deltaLast = r.getLast() - R.getLast(); - if (BYTES_BIG_ENDIAN && deltaLast) { - Constant *ShiftAmt = ConstantInt::get(C->getType(), deltaLast); - C = TheFolder->CreateShl(C, ShiftAmt); - } else if (!BYTES_BIG_ENDIAN && deltaFirst) { - Constant *ShiftAmt = ConstantInt::get(C->getType(), deltaFirst); - C = TheFolder->CreateShl(C, ShiftAmt); - } - return BitSlice(r, C); -} - -/// getBits - Return the bits in the given range. The supplied range need not -/// be contained in the range of the slice, but if not then the bits outside -/// the slice get an undefined value. The bits are returned as a constant of -/// integer type. On little-endian machine the least significant bit of the -/// returned value corresponds to the first bit of the range (aka "First"), -/// while on big-endian machines it corresponds to the last bit of the range -/// (aka "Last-1"). -Constant *BitSlice::getBits(SignedRange r) const { - assert(!r.empty() && "Bit range is empty!"); - // Quick exit if the desired range matches that of the slice. - if (R == r) - return Contents; - const Type *RetTy = IntegerType::get(Context, r.getWidth()); - // If the slice contains no bits then every returned bit is undefined. - if (empty()) - return UndefValue::get(RetTy); - // Extend to the convex hull of the two ranges. - BitSlice Slice = ExtendRange(R.Join(r)); - // Chop the slice down to the requested range. - Slice = Slice.ReduceRange(r); - // Now we can just return the bits contained in the slice. - return Slice.Contents; -} - -/// Merge - Join the slice with another (which must be disjoint), forming the -/// convex hull of the ranges. The bits in the range of one of the slices are -/// those of that slice. Any other bits have an undefined value. -void BitSlice::Merge(const BitSlice &other) { - // If the other slice is empty, the result is this slice. - if (other.empty()) - return; - // If this slice is empty, the result is the other slice. - if (empty()) { - *this = other; - return; - } - assert(!R.intersects(other.getRange()) && "Slices overlap!"); - - // Extend each slice to the convex hull of the ranges. - SignedRange Hull = R.Join(other.getRange()); - BitSlice ExtThis = ExtendRange(Hull); - BitSlice ExtOther = other.ExtendRange(Hull); - - // The extra bits added when extending a slice may contain anything. In each - // extended slice clear the bits corresponding to the other slice. - int HullFirst = Hull.getFirst(), HullLast = Hull.getLast(); - unsigned HullWidth = Hull.getWidth(); - // Compute masks with the bits for each slice set to 1. - APInt ThisBits, OtherBits; - if (BYTES_BIG_ENDIAN) { - ThisBits = APInt::getBitsSet(HullWidth, HullLast - getLast(), - HullLast - getFirst()); - OtherBits = APInt::getBitsSet(HullWidth, HullLast - other.getLast(), - HullLast - other.getFirst()); - } else { - ThisBits = APInt::getBitsSet(HullWidth, getFirst() - HullFirst, - getLast() - HullFirst); - OtherBits = APInt::getBitsSet(HullWidth, other.getFirst() - HullFirst, - other.getLast() - HullFirst); - } - // Clear bits which correspond to the other slice. - ConstantInt *ClearThis = ConstantInt::get(Context, ~ThisBits); - ConstantInt *ClearOther = ConstantInt::get(Context, ~OtherBits); - Constant *ThisPart = TheFolder->CreateAnd(ExtThis.Contents, ClearOther); - Constant *OtherPart = TheFolder->CreateAnd(ExtOther.Contents, ClearThis); - - // The slices can now be joined via a simple 'or'. - *this = BitSlice(Hull, TheFolder->CreateOr(ThisPart, OtherPart)); -} - -/// ReduceRange - Reduce the slice to a smaller range discarding any bits that -/// do not belong to the new range. -BitSlice BitSlice::ReduceRange(SignedRange r) const { - assert(R.contains(r) && "Not a reduction!"); - // Quick exit if the range did not actually decrease. - if (R == r) - return *this; - // The trivial case of reducing to an empty range. - if (r.empty()) - return BitSlice(); - assert(!R.empty() && "Empty ranges did not evaluate as equal?"); - // Move the least-significant bit to the correct position. - Constant *C = Contents; - unsigned deltaFirst = r.getFirst() - R.getFirst(); - unsigned deltaLast = R.getLast() - r.getLast(); - if (BYTES_BIG_ENDIAN && deltaLast) { - Constant *ShiftAmt = ConstantInt::get(C->getType(), deltaLast); - C = TheFolder->CreateLShr(C, ShiftAmt); - } else if (!BYTES_BIG_ENDIAN && deltaFirst) { - Constant *ShiftAmt = ConstantInt::get(C->getType(), deltaFirst); - C = TheFolder->CreateLShr(C, ShiftAmt); - } - // Truncate to the new type. - const Type *RedTy = IntegerType::get(Context, r.getWidth()); - C = TheFolder->CreateTruncOrBitCast(C, RedTy); - return BitSlice(r, C); -} - -/// ViewAsBits - View the given constant as a bunch of bits, i.e. as one big -/// integer. Only the bits in the given range are needed, so there is no need -/// to supply bits outside this range though it is harmless to do so. There is -/// also no need to supply undefined bits inside the range. -static BitSlice ViewAsBits(Constant *C, SignedRange R) { - if (R.empty()) - return BitSlice(); - - // Sanitize the range to make life easier in what follows. - const Type *Ty = C->getType(); - int StoreSize = getTargetData().getTypeStoreSizeInBits(Ty); - R = R.Meet(SignedRange(0, StoreSize)); - - // Quick exit if it is clear that there are no bits in the range. - if (R.empty()) - return BitSlice(); - assert(StoreSize > 0 && "Empty range not eliminated?"); - - switch (Ty->getTypeID()) { - default: - DieAbjectly("Unsupported type!"); - case Type::PointerTyID: { - // Cast to an integer with the same number of bits and return that. - const IntegerType *IntTy = getTargetData().getIntPtrType(Context); - return BitSlice(0, StoreSize, TheFolder->CreatePtrToInt(C, IntTy)); - } - case Type::DoubleTyID: - case Type::FloatTyID: - case Type::FP128TyID: - case Type::IntegerTyID: - case Type::PPC_FP128TyID: - case Type::X86_FP80TyID: - case Type::X86_MMXTyID: { - // Bitcast to an integer with the same number of bits and return that. - unsigned BitWidth = Ty->getPrimitiveSizeInBits(); - const IntegerType *IntTy = IntegerType::get(Context, BitWidth); - C = TheFolder->CreateBitCast(C, IntTy); - // Be careful about where the bits are placed in case this is a funky type - // like i1. If the width is a multiple of the address unit then there is - // nothing to worry about: the bits occupy the range [0, StoreSize). But - // if not then endianness matters: on big-endian machines there are padding - // bits at the start, while on little-endian machines they are at the end. - return BYTES_BIG_ENDIAN ? - BitSlice(StoreSize - BitWidth, StoreSize, C) : BitSlice(0, BitWidth, C); - } - - case Type::ArrayTyID: { - const ArrayType *ATy = cast(Ty); - const Type *EltTy = ATy->getElementType(); - const unsigned NumElts = ATy->getNumElements(); - const unsigned Stride = getTargetData().getTypeAllocSizeInBits(EltTy); - assert(Stride > 0 && "Store size smaller than alloc size?"); - // Elements with indices in [FirstElt, LastElt) overlap the range. - unsigned FirstElt = R.getFirst() / Stride; - unsigned LastElt = (R.getLast() + Stride - 1) / Stride; - assert(LastElt <= NumElts && "Store size bigger than array?"); - // Visit all elements that overlap the requested range, accumulating their - // bits in Bits. - BitSlice Bits; - SignedRange StrideRange(0, Stride); - for (unsigned i = FirstElt; i < LastElt; ++i) { - // Extract the element. - Constant *Elt = TheFolder->CreateExtractValue(C, &i, 1); - // View it as a bunch of bits. - BitSlice EltBits = ViewAsBits(Elt, StrideRange); - // Add to the already known bits. - Bits.Merge(EltBits.Displace(i * Stride)); - } - return Bits; - } - - case Type::StructTyID: { - const StructType *STy = cast(Ty); - const StructLayout *SL = getTargetData().getStructLayout(STy); - // Fields with indices in [FirstIdx, LastIdx) overlap the range. - unsigned FirstIdx = SL->getElementContainingOffset((R.getFirst()+7)/8); - unsigned LastIdx = 1 + SL->getElementContainingOffset((R.getLast()+6)/8); - // Visit all fields that overlap the requested range, accumulating their - // bits in Bits. - BitSlice Bits; - for (unsigned i = FirstIdx; i < LastIdx; ++i) { - // Extract the field. - Constant *Field = TheFolder->CreateExtractValue(C, &i, 1); - // View it as a bunch of bits. - const Type *FieldTy = Field->getType(); - unsigned FieldStoreSize = getTargetData().getTypeStoreSizeInBits(FieldTy); - BitSlice FieldBits = ViewAsBits(Field, SignedRange(0, FieldStoreSize)); - // Add to the already known bits. - Bits.Merge(FieldBits.Displace(SL->getElementOffset(i)*8)); - } - return Bits; - } - - case Type::VectorTyID: { - const VectorType *VTy = cast(Ty); - const Type *EltTy = VTy->getElementType(); - const unsigned NumElts = VTy->getNumElements(); - const unsigned Stride = getTargetData().getTypeAllocSizeInBits(EltTy); - assert(Stride > 0 && "Store size smaller than alloc size?"); - // Elements with indices in [FirstElt, LastElt) overlap the range. - unsigned FirstElt = R.getFirst() / Stride; - unsigned LastElt = (R.getLast() + Stride - 1) / Stride; - assert(LastElt <= NumElts && "Store size bigger than vector?"); - // Visit all elements that overlap the requested range, accumulating their - // bits in Bits. - BitSlice Bits; - SignedRange StrideRange(0, Stride); - for (unsigned i = FirstElt; i < LastElt; ++i) { - // Extract the element. - ConstantInt *Idx = ConstantInt::get(Type::getInt32Ty(Context), i); - Constant *Elt = TheFolder->CreateExtractElement(C, Idx); - // View it as a bunch of bits. - BitSlice EltBits = ViewAsBits(Elt, StrideRange); - // Add to the already known bits. - Bits.Merge(EltBits.Displace(i * Stride)); - } - return Bits; - } - } -} - -/// InterpretAsType - Interpret the bits of the given constant (starting from -/// StartingBit) as representing a constant of type 'Ty'. This results in the -/// same constant as you would get by storing the bits of 'C' to memory (with -/// the first bit stored being 'StartingBit') and then loading out a (constant) -/// value of type 'Ty' from the stored to memory location. -Constant *InterpretAsType(Constant *C, const Type* Ty, int StartingBit) { - if (C->getType() == Ty) - return C; - - switch (Ty->getTypeID()) { - default: - DieAbjectly("Unsupported type!"); - case Type::IntegerTyID: { - unsigned BitWidth = Ty->getPrimitiveSizeInBits(); - unsigned StoreSize = getTargetData().getTypeStoreSizeInBits(Ty); - // Convert the constant into a bunch of bits. Only the bits to be "loaded" - // out are needed, so rather than converting the entire constant this only - // converts enough to get all of the required bits. - BitSlice Bits = ViewAsBits(C, SignedRange(StartingBit, - StartingBit + StoreSize)); - // Extract the bits used by the integer. If the integer width is a multiple - // of the address unit then the endianness of the target doesn't matter. If - // not then the padding bits come at the start on big-endian machines and at - // the end on little-endian machines. - Bits = Bits.Displace(-StartingBit); - return BYTES_BIG_ENDIAN ? - Bits.getBits(SignedRange(StoreSize - BitWidth, StoreSize)) : - Bits.getBits(SignedRange(0, BitWidth)); - } - - case Type::PointerTyID: { - // Interpret as an integer with the same number of bits then cast back to - // the original type. - const IntegerType *IntTy = getTargetData().getIntPtrType(Context); - C = InterpretAsType(C, IntTy, StartingBit); - return TheFolder->CreateIntToPtr(C, Ty); - } - case Type::DoubleTyID: - case Type::FloatTyID: - case Type::FP128TyID: - case Type::PPC_FP128TyID: - case Type::X86_FP80TyID: - case Type::X86_MMXTyID: { - // Interpret as an integer with the same number of bits then cast back to - // the original type. - unsigned BitWidth = Ty->getPrimitiveSizeInBits(); - const IntegerType *IntTy = IntegerType::get(Context, BitWidth); - return TheFolder->CreateBitCast(InterpretAsType(C, IntTy, StartingBit), Ty); - } - - case Type::ArrayTyID: { - // Interpret each array element in turn. - const ArrayType *ATy = cast(Ty); - const Type *EltTy = ATy->getElementType(); - const unsigned Stride = getTargetData().getTypeAllocSizeInBits(EltTy); - const unsigned NumElts = ATy->getNumElements(); - std::vector Vals(NumElts); - for (unsigned i = 0; i != NumElts; ++i) - Vals[i] = InterpretAsType(C, EltTy, StartingBit + i*Stride); - return ConstantArray::get(ATy, Vals); // TODO: Use ArrayRef constructor. - } - - case Type::StructTyID: { - // Interpret each struct field in turn. - const StructType *STy = cast(Ty); - const StructLayout *SL = getTargetData().getStructLayout(STy); - unsigned NumElts = STy->getNumElements(); - std::vector Vals(NumElts); - for (unsigned i = 0; i != NumElts; ++i) - Vals[i] = InterpretAsType(C, STy->getElementType(i), - StartingBit + SL->getElementOffsetInBits(i)); - return ConstantStruct::get(STy, Vals); // TODO: Use ArrayRef constructor. - } - - case Type::VectorTyID: { - // Interpret each vector element in turn. - const VectorType *VTy = cast(Ty); - const Type *EltTy = VTy->getElementType(); - const unsigned Stride = getTargetData().getTypeAllocSizeInBits(EltTy); - const unsigned NumElts = VTy->getNumElements(); - SmallVector Vals(NumElts); - for (unsigned i = 0; i != NumElts; ++i) - Vals[i] = InterpretAsType(C, EltTy, StartingBit + i*Stride); - return ConstantVector::get(Vals); - } - } -} - - -//===----------------------------------------------------------------------===// -// ... ConvertInitializer ... -//===----------------------------------------------------------------------===// - -/// ConvertInitializerWithCast - Convert the initial value for a global variable -/// to an equivalent LLVM constant then cast to the given type if both the type -/// and the initializer are scalar. This is convenient for making explicit the -/// implicit scalar casts that GCC allows in "assignments" such as initializing -/// a record field. -static Constant *ConvertInitializerWithCast(tree exp, tree type) { - // Convert the initializer. - Constant *C = ConvertInitializer(exp); - - // If no cast is needed, or it would not be a scalar cast, then just return - // the initializer as is. - if (type == TREE_TYPE(exp) || AGGREGATE_TYPE_P(TREE_TYPE(exp)) || - AGGREGATE_TYPE_P(type)) - return C; - const Type *SrcTy = ConvertType(TREE_TYPE(exp)); - const Type *DestTy = ConvertType(type); - // LLVM types are often the same even when the GCC types differ. - if (SrcTy == DestTy) - return C; - - // First ensure that the initializer has a sensible type. Note that it would - // be wrong to interpret the constant as being of type DestTy here since that - // would not perform a value extension (adding extra zeros or sign bits when - // casting to a larger integer type for example): any extra bits would get an - // undefined value instead. - C = InterpretAsType(C, SrcTy, 0); - // Now cast to the desired type. - bool SrcIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp)); - bool DestIsSigned = !TYPE_UNSIGNED(type); - Instruction::CastOps opcode = CastInst::getCastOpcode(C, SrcIsSigned, DestTy, - DestIsSigned); - return TheFolder->CreateCast(opcode, C, DestTy); -} - -/// ConvertCST - Return the given simple constant as an array of bytes. For the -/// moment only INTEGER_CST, REAL_CST, COMPLEX_CST and VECTOR_CST are supported. -static Constant *ConvertCST(tree exp) { - const tree type = TREE_TYPE(exp); - unsigned SizeInChars = (TREE_INT_CST_LOW(TYPE_SIZE(type)) + CHAR_BIT - 1) / - CHAR_BIT; - // Encode the constant in Buffer in target format. - std::vector Buffer(SizeInChars); - unsigned CharsWritten = native_encode_expr(exp, &Buffer[0], SizeInChars); - assert(CharsWritten == SizeInChars && "Failed to fully encode expression!"); - // Turn it into an LLVM byte array. - return ConstantArray::get(Context, StringRef((char *)&Buffer[0], SizeInChars), - /*AddNull*/false); -} - -static Constant *ConvertSTRING_CST(tree exp) { - const ArrayType *StrTy = cast(ConvertType(TREE_TYPE(exp))); - const Type *ElTy = StrTy->getElementType(); - - unsigned Len = (unsigned)TREE_STRING_LENGTH(exp); - - std::vector Elts; - if (ElTy->isIntegerTy(8)) { - const unsigned char *InStr =(const unsigned char *)TREE_STRING_POINTER(exp); - for (unsigned i = 0; i != Len; ++i) - Elts.push_back(ConstantInt::get(Type::getInt8Ty(Context), InStr[i])); - } else if (ElTy->isIntegerTy(16)) { - assert((Len&1) == 0 && - "Length in bytes should be a multiple of element size"); - const uint16_t *InStr = - (const unsigned short *)TREE_STRING_POINTER(exp); - for (unsigned i = 0; i != Len/2; ++i) { - // gcc has constructed the initializer elements in the target endianness, - // but we're going to treat them as ordinary shorts from here, with - // host endianness. Adjust if necessary. - if (llvm::sys::isBigEndianHost() == BYTES_BIG_ENDIAN) - Elts.push_back(ConstantInt::get(Type::getInt16Ty(Context), InStr[i])); - else - Elts.push_back(ConstantInt::get(Type::getInt16Ty(Context), - ByteSwap_16(InStr[i]))); - } - } else if (ElTy->isIntegerTy(32)) { - assert((Len&3) == 0 && - "Length in bytes should be a multiple of element size"); - const uint32_t *InStr = (const uint32_t *)TREE_STRING_POINTER(exp); - for (unsigned i = 0; i != Len/4; ++i) { - // gcc has constructed the initializer elements in the target endianness, - // but we're going to treat them as ordinary ints from here, with - // host endianness. Adjust if necessary. - if (llvm::sys::isBigEndianHost() == BYTES_BIG_ENDIAN) - Elts.push_back(ConstantInt::get(Type::getInt32Ty(Context), InStr[i])); - else - Elts.push_back(ConstantInt::get(Type::getInt32Ty(Context), - ByteSwap_32(InStr[i]))); - } - } else { - assert(0 && "Unknown character type!"); - } - - unsigned LenInElts = Len / - TREE_INT_CST_LOW(TYPE_SIZE_UNIT(TREE_TYPE(TREE_TYPE(exp)))); - unsigned ConstantSize = StrTy->getNumElements(); - - if (LenInElts != ConstantSize) { - // If this is a variable sized array type, set the length to LenInElts. - if (ConstantSize == 0) { - tree Domain = TYPE_DOMAIN(TREE_TYPE(exp)); - if (!Domain || !TYPE_MAX_VALUE(Domain)) { - ConstantSize = LenInElts; - StrTy = ArrayType::get(ElTy, LenInElts); - } - } - - if (ConstantSize < LenInElts) { - // Only some chars are being used, truncate the string: char X[2] = "foo"; - Elts.resize(ConstantSize); - } else { - // Fill the end of the string with nulls. - Constant *C = Constant::getNullValue(ElTy); - for (; LenInElts != ConstantSize; ++LenInElts) - Elts.push_back(C); - } - } - return ConstantArray::get(StrTy, Elts); -} - -static Constant *ConvertADDR_EXPR(tree exp) { - return AddressOf(TREE_OPERAND(exp, 0)); -} - -/// ConvertArrayCONSTRUCTOR - Convert a CONSTRUCTOR with array or vector type. -static Constant *ConvertArrayCONSTRUCTOR(tree exp) { - const TargetData &TD = getTargetData(); - - tree init_type = TREE_TYPE(exp); - const Type *InitTy = ConvertType(init_type); - - tree elt_type = TREE_TYPE(init_type); - const Type *EltTy = ConvertType(elt_type); - - // Check that the element type has a known, constant size. - assert(isSequentialCompatible(init_type) && "Variable sized array element!"); - uint64_t EltSize = TD.getTypeAllocSizeInBits(EltTy); - - /// Elts - The initial values to use for the array elements. A null entry - /// means that the corresponding array element should be default initialized. - std::vector Elts; - - // Resize to the number of array elements if known. This ensures that every - // element will be at least default initialized even if no initial value is - // given for it. - uint64_t TypeElts = TREE_CODE(init_type) == ARRAY_TYPE ? - ArrayLengthOf(init_type) : TYPE_VECTOR_SUBPARTS(init_type); - if (TypeElts != ~0ULL) - Elts.resize(TypeElts); - - // If GCC indices into the array need adjusting to make them zero indexed then - // record here the value to subtract off. - tree lower_bnd = NULL_TREE; - if (TREE_CODE(init_type) == ARRAY_TYPE && TYPE_DOMAIN(init_type) && - !integer_zerop(TYPE_MIN_VALUE(TYPE_DOMAIN(init_type)))) - lower_bnd = TYPE_MIN_VALUE(TYPE_DOMAIN(init_type)); - - unsigned NextIndex = 0; - unsigned HOST_WIDE_INT ix; - tree elt_index, elt_value; - FOR_EACH_CONSTRUCTOR_ELT(CONSTRUCTOR_ELTS(exp), ix, elt_index, elt_value) { - // Find and decode the constructor's value. - Constant *Val = ConvertInitializerWithCast(elt_value, elt_type); - uint64_t ValSize = TD.getTypeAllocSizeInBits(Val->getType()); - assert(ValSize <= EltSize && "Element initial value too big!"); - - // If the initial value is smaller than the element size then pad it out. - if (ValSize < EltSize) { - unsigned PadBits = EltSize - ValSize; - assert(PadBits % BITS_PER_UNIT == 0 && "Non-unit type size?"); - unsigned Units = PadBits / BITS_PER_UNIT; - Constant *Padding = UndefValue::get(GetUnitType(Context, Units)); - Val = ConstantStruct::get(Context, false, Val, Padding, NULL); - } - - // Get the index position of the element within the array. Note that this - // can be NULL_TREE, which means that it belongs in the next available slot. - tree index = elt_index; - - // The first and last elements to fill in, inclusive. - unsigned FirstIndex, LastIndex; - if (!index) { - LastIndex = FirstIndex = NextIndex; - } else if (TREE_CODE(index) == RANGE_EXPR) { - tree first = TREE_OPERAND(index, 0); - tree last = TREE_OPERAND(index, 1); - - // Subtract off the lower bound if any to ensure indices start from zero. - if (lower_bnd != NULL_TREE) { - first = fold_build2(MINUS_EXPR, TREE_TYPE(first), first, lower_bnd); - last = fold_build2(MINUS_EXPR, TREE_TYPE(last), last, lower_bnd); - } - - assert(host_integerp(first, 1) && host_integerp(last, 1) && - "Unknown range_expr!"); - FirstIndex = tree_low_cst(first, 1); - LastIndex = tree_low_cst(last, 1); - } else { - // Subtract off the lower bound if any to ensure indices start from zero. - if (lower_bnd != NULL_TREE) - index = fold_build2(MINUS_EXPR, TREE_TYPE(index), index, lower_bnd); - assert(host_integerp(index, 1)); - FirstIndex = tree_low_cst(index, 1); - LastIndex = FirstIndex; - } - - // Process all of the elements in the range. - if (LastIndex >= Elts.size()) - Elts.resize(LastIndex + 1); - for (; FirstIndex <= LastIndex; ++FirstIndex) - Elts[FirstIndex] = Val; - - NextIndex = FirstIndex; - } - - unsigned NumElts = Elts.size(); - - // Zero length array. - if (!NumElts) - return getDefaultValue(InitTy); - - // Default initialize any elements that had no initial value specified. - Constant *DefaultElt = getDefaultValue(EltTy); - for (unsigned i = 0; i != NumElts; ++i) - if (!Elts[i]) - Elts[i] = DefaultElt; - - // Check whether any of the elements have different types. If so we need to - // return a struct instead of an array. This can occur in cases where we have - // an array of unions, and the various unions had different parts initialized. - // While there, compute the maximum element alignment. - bool UseStruct = false; - const Type *ActualEltTy = Elts[0]->getType(); - unsigned MaxAlign = TD.getABITypeAlignment(ActualEltTy); - for (unsigned i = 1; i != NumElts; ++i) - if (Elts[i]->getType() != ActualEltTy) { - MaxAlign = std::max(TD.getABITypeAlignment(Elts[i]->getType()), MaxAlign); - UseStruct = true; - } - - // If any elements are more aligned than the GCC type then we need to return a - // packed struct. This can happen if the user forced a small alignment on the - // array type. - bool Pack = MaxAlign * 8 > TYPE_ALIGN(TREE_TYPE(exp)); - - // We guarantee that initializers are always at least as big as the LLVM type - // for the initializer. If needed, append padding to ensure this. - uint64_t TypeSize = TD.getTypeAllocSizeInBits(InitTy); - if (NumElts * EltSize < TypeSize) { - unsigned PadBits = TypeSize - NumElts * EltSize; - assert(PadBits % BITS_PER_UNIT == 0 && "Non-unit type size?"); - unsigned Units = PadBits / BITS_PER_UNIT; - Elts.push_back(UndefValue::get(GetUnitType(Context, Units))); - UseStruct = true; - } - - // Return as a struct if the contents are not homogeneous. - if (UseStruct || Pack) - return ConstantStruct::get(Context, Elts, Pack); - - // Make the IR more pleasant by returning as a vector if the GCC type was a - // vector. However this is only correct if the initial values had the same - // type as the vector element type, rather than some random other type. - return ActualEltTy == EltTy && TREE_CODE(init_type) == VECTOR_TYPE ? - ConstantVector::get(Elts) : - ConstantArray::get(ArrayType::get(ActualEltTy, Elts.size()), Elts); -} - -/// FieldContents - A constant restricted to a range of bits. Any part of the -/// constant outside of the range is discarded. The range may be bigger than -/// the constant in which case any extra bits have an undefined value. -class FieldContents { - SignedRange R; // The range of bits occupied by the constant. - Constant *C; // The constant. May be null if the range is empty. - int Starts; // The first bit of the constant is positioned at this offset. - - FieldContents(SignedRange r, Constant *c, int starts) - : R(r), C(c), Starts(starts) { - assert((R.empty() || C) && "Need constant when range not empty!"); - } - - /// getAsBits - Return the bits in the range as an integer (or null if the - /// range is empty). - Constant *getAsBits() const { - if (R.empty()) - return 0; - const Type *IntTy = IntegerType::get(Context, R.getWidth()); - return InterpretAsType(C, IntTy, R.getFirst() - Starts); - } - - /// isSafeToReturnContentsDirectly - Return whether the current value for the - /// constant properly represents the bits in the range and so can be handed to - /// the user as is. - bool isSafeToReturnContentsDirectly(const TargetData &TD) const { - // If there is no constant (allowed when the range is empty) then one needs - // to be created. - if (!C) - return false; - // If the first bit of the constant is not the first bit of the range then - // it needs to be displaced before being passed to the user. - if (!R.empty() && R.getFirst() != Starts) - return false; - // If the constant is wider than the range then it needs to be truncated - // before being passed to the user. - const Type *Ty = C->getType(); - unsigned AllocBits = TD.getTypeAllocSizeInBits(Ty); - return AllocBits <= (unsigned)R.getWidth(); - } - -public: - /// FieldContents - Default constructor: empty bit range. - FieldContents() : R(), C(0), Starts(0) {} - - /// get - Fill the range [first, last) with the given constant. - static FieldContents get(int first, int last, Constant *c) { - return FieldContents(SignedRange(first, last), c, first); - } - - /// getRange - Return the range occupied by this field. - SignedRange getRange() const { return R; } - - /// ChangeRangeTo - Change the range occupied by this field. - void ChangeRangeTo(SignedRange r) { R = r; } - - /// JoinWith - Form the union of this field with another field (which must be - /// disjoint from this one). After this the range will be the convex hull of - /// the ranges of the two fields. - void JoinWith(const FieldContents &S); - - /// extractContents - Return the contained bits as a constant which contains - /// every defined bit in the range, yet is guaranteed to have alloc size no - /// larger than the width of the range. Unlike the other methods for this - /// class, this one requires that the width of the range be a multiple of an - /// address unit, which usually means a multiple of 8. - Constant *extractContents(const TargetData &TD) { - /// If the current value for the constant can be used to represent the bits - /// in the range then just return it. - if (isSafeToReturnContentsDirectly(TD)) - return C; - // If the range is empty then return a constant with zero size. - if (R.empty()) { - // Return an empty array. Remember the returned value as an optimization - // in case we are called again. - C = UndefValue::get(GetUnitType(Context, 0)); - assert(isSafeToReturnContentsDirectly(TD) && "Unit over aligned?"); - return C; - } - assert(R.getWidth() % BITS_PER_UNIT == 0 && "Boundaries not aligned?"); - unsigned Units = R.getWidth() / BITS_PER_UNIT; - // Turn the contents into a bunch of bits. Remember the returned value as - // an optimization in case we are called again. - // TODO: If the contents only need to be truncated and have struct or array - // type then we could try to do the truncation by dropping or modifying the - // last elements of the constant, maybe yielding something less horrible. - C = getAsBits(); - Starts = R.getFirst(); - if (isSafeToReturnContentsDirectly(TD)) - return C; - // The integer type used to hold the bits was too big (for example an i24 - // typically occupies 32 bits so is too big for a range of 24 bits). Turn - // it into an array of bytes instead. - C = InterpretAsType(C, GetUnitType(Context, Units), 0); - assert(isSafeToReturnContentsDirectly(TD) && "Unit over aligned?"); - return C; - } -}; - -/// JoinWith - Form the union of this field with another field (which must be -/// disjoint from this one). After this the range will be the convex hull of -/// the ranges of the two fields. -void FieldContents::JoinWith(const FieldContents &S) { - // Consider the contents of the fields to be bunches of bits and paste them - // together. This can result in a nasty integer constant expression, but as - // we only get here for bitfields that's mostly harmless. - BitSlice Bits(R, getAsBits()); - Bits.Merge (BitSlice(S.R, S.getAsBits())); - R = Bits.getRange(); - C = Bits.getBits(R); - Starts = R.empty() ? 0 : R.getFirst(); -} - -static Constant *ConvertRecordCONSTRUCTOR(tree exp) { - // FIXME: This new logic, especially the handling of bitfields, is untested - // and probably wrong on big-endian machines. - IntervalList Layout; - const TargetData &TD = getTargetData(); - uint64_t TypeSize = TD.getTypeAllocSizeInBits(ConvertType(TREE_TYPE(exp))); - - // Ensure that fields without an initial value are default initialized by - // explicitly setting the starting value for all fields to be zero. If an - // initial value is supplied for a field then the value will overwrite and - // replace the zero starting value later. - if (flag_default_initialize_globals) { - for (tree field = TYPE_FIELDS(TREE_TYPE(exp)); field; - field = TREE_CHAIN(field)) { - // Skip contained methods, types etc. - if (TREE_CODE(field) != FIELD_DECL) - continue; - // If the field has variable or unknown position then it cannot be default - // initialized - skip it. - if (!OffsetIsLLVMCompatible(field)) - continue; - uint64_t FirstBit = getFieldOffsetInBits(field); - assert(FirstBit <= TypeSize && "Field off end of type!"); - // Determine the width of the field. - uint64_t BitWidth; - const Type *FieldTy = ConvertType(TREE_TYPE(field)); - if (isInt64(DECL_SIZE(field), true)) { - // The field has a size and it is a constant, so use it. Note that - // this size may be smaller than the type size. For example, if the - // next field starts inside alignment padding at the end of this one - // then DECL_SIZE will be the size with the padding used by the next - // field not included. - BitWidth = getInt64(DECL_SIZE(field), true); - } else { - // If the field has variable or unknown size then use the size of the - // LLVM type instead as it gives the minimum size the field may have. - if (!FieldTy->isSized()) - // An incomplete type - this field cannot be default initialized. - continue; - BitWidth = TD.getTypeAllocSizeInBits(FieldTy); - if (FirstBit + BitWidth > TypeSize) - BitWidth = TypeSize - FirstBit; - } - uint64_t LastBit = FirstBit + BitWidth; - - // Zero the bits occupied by the field. It is safe to use FieldTy here as - // it is guaranteed to cover all parts of the GCC type that can be default - // initialized. This makes for nicer IR than just using a bunch of bytes. - Constant *Zero = Constant::getNullValue(FieldTy); - Layout.AddInterval(FieldContents::get(FirstBit, LastBit, Zero)); - } - } - - // For each field for which an initial value was specified, set the bits - // occupied by the field to that value. - unsigned HOST_WIDE_INT ix; - tree field, next_field, value; - next_field = TYPE_FIELDS(TREE_TYPE(exp)); - FOR_EACH_CONSTRUCTOR_ELT(CONSTRUCTOR_ELTS(exp), ix, field, value) { - if (!field) { - // Move on to the next FIELD_DECL, skipping contained methods, types etc. - field = next_field; - while (1) { - assert(field && "Fell off end of record!"); - if (TREE_CODE(field) == FIELD_DECL) break; - field = TREE_CHAIN(field); - } - } - next_field = TREE_CHAIN(field); - - assert(TREE_CODE(field) == FIELD_DECL && "Initial value not for a field!"); - assert(OffsetIsLLVMCompatible(field) && "Field position not known!"); - // Turn the initial value for this field into an LLVM constant. - Constant *Init = ConvertInitializerWithCast(value, TREE_TYPE(field)); - // Work out the range of bits occupied by the field. - uint64_t FirstBit = getFieldOffsetInBits(field); - assert(FirstBit <= TypeSize && "Field off end of type!"); - // If a size was specified for the field then use it. Otherwise take the - // size from the initial value. - uint64_t BitWidth = isInt64(DECL_SIZE(field), true) ? - getInt64(DECL_SIZE(field), true) : - TD.getTypeAllocSizeInBits(Init->getType()); - uint64_t LastBit = FirstBit + BitWidth; - - // Set the bits occupied by the field to the initial value. - Layout.AddInterval(FieldContents::get(FirstBit, LastBit, Init)); - } - - // Force all fields to begin and end on a byte boundary. This automagically - // takes care of bitfields. - Layout.AlignBoundaries(BITS_PER_UNIT); - - // Determine whether to return a packed struct. If returning an ordinary - // struct would result in an initializer that is more aligned than its GCC - // type then return a packed struct instead. If a field's alignment would - // make it start after its desired position then also use a packed struct. - bool Pack = false; - unsigned MaxAlign = TYPE_ALIGN(TREE_TYPE(exp)); - for (unsigned i = 0, e = Layout.getNumIntervals(); i != e; ++i) { - FieldContents F = Layout.getInterval(i); - unsigned First = F.getRange().getFirst(); - Constant *Val = F.extractContents(TD); - unsigned Alignment = TD.getABITypeAlignment(Val->getType()) * 8; - if (Alignment > MaxAlign || First % Alignment) { - Pack = true; - break; - } - } - - // Create the elements that will make up the struct. As well as the fields - // themselves there may also be padding elements. - std::vector Elts; - Elts.reserve(Layout.getNumIntervals()); - unsigned EndOfPrevious = 0; // Offset of first bit after previous element. - for (unsigned i = 0, e = Layout.getNumIntervals(); i != e; ++i) { - FieldContents F = Layout.getInterval(i); - unsigned First = F.getRange().getFirst(); - Constant *Val = F.extractContents(TD); - assert(EndOfPrevious <= First && "Previous field too big!"); - - // If there is a gap then we may need to fill it with padding. - if (First > EndOfPrevious) { - // There is a gap between the end of the previous field and the start of - // this one. The alignment of the field contents may mean that it will - // start at the right offset anyway, but if not then insert padding. - bool NeedPadding = true; - if (!Pack) { - // If the field's alignment will take care of the gap then there is no - // need for padding. - unsigned Alignment = TD.getABITypeAlignment(Val->getType()) * 8; - if (First == (EndOfPrevious + Alignment - 1) / Alignment * Alignment) - NeedPadding = false; - } - if (NeedPadding) { - // Fill the gap with undefined bytes. - assert((First - EndOfPrevious) % BITS_PER_UNIT == 0 && - "Non-unit field boundaries!"); - unsigned Units = (First - EndOfPrevious) / BITS_PER_UNIT; - Elts.push_back(UndefValue::get(GetUnitType(Context, Units))); - } - } - - // Append the field. - Elts.push_back(Val); - EndOfPrevious = First + TD.getTypeAllocSizeInBits(Val->getType()); - } - - // We guarantee that initializers are always at least as big as the LLVM type - // for the initializer. If needed, append padding to ensure this. - if (EndOfPrevious < TypeSize) { - assert((TypeSize - EndOfPrevious) % BITS_PER_UNIT == 0 && - "Non-unit type size?"); - unsigned Units = (TypeSize - EndOfPrevious) / BITS_PER_UNIT; - Elts.push_back(UndefValue::get(GetUnitType(Context, Units))); - } - - // Okay, we're done, return the computed elements. - return ConstantStruct::get(Context, Elts, Pack); -} - -static Constant *ConvertCONSTRUCTOR(tree exp) { - // If the constructor is empty then default initialize all of the components. - // It is safe to use the LLVM type here as it covers every part of the GCC - // type that can possibly be default initialized. - if (CONSTRUCTOR_NELTS(exp) == 0) - return getDefaultValue(ConvertType(TREE_TYPE(exp))); - - switch (TREE_CODE(TREE_TYPE(exp))) { - default: - DieAbjectly("Unknown constructor!", exp); - case VECTOR_TYPE: - case ARRAY_TYPE: return ConvertArrayCONSTRUCTOR(exp); - case QUAL_UNION_TYPE: - case RECORD_TYPE: - case UNION_TYPE: return ConvertRecordCONSTRUCTOR(exp); - } -} - -static Constant *ConvertBinOp_CST(tree exp) { - Constant *LHS = ConvertInitializer(TREE_OPERAND(exp, 0)); - bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp,0))); - Constant *RHS = ConvertInitializer(TREE_OPERAND(exp, 1)); - bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp,1))); - Instruction::CastOps opcode; - if (LHS->getType()->isPointerTy()) { - const Type *IntPtrTy = getTargetData().getIntPtrType(Context); - opcode = CastInst::getCastOpcode(LHS, LHSIsSigned, IntPtrTy, false); - LHS = TheFolder->CreateCast(opcode, LHS, IntPtrTy); - opcode = CastInst::getCastOpcode(RHS, RHSIsSigned, IntPtrTy, false); - RHS = TheFolder->CreateCast(opcode, RHS, IntPtrTy); - } - - Constant *Result; - switch (TREE_CODE(exp)) { - default: assert(0 && "Unexpected case!"); - case PLUS_EXPR: Result = TheFolder->CreateAdd(LHS, RHS); break; - case MINUS_EXPR: Result = TheFolder->CreateSub(LHS, RHS); break; - } - - const Type *Ty = ConvertType(TREE_TYPE(exp)); - bool TyIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp)); - opcode = CastInst::getCastOpcode(Result, LHSIsSigned, Ty, TyIsSigned); - return TheFolder->CreateCast(opcode, Result, Ty); -} - -static Constant *ConvertPOINTER_PLUS_EXPR(tree exp) { - Constant *Ptr = ConvertInitializer(TREE_OPERAND(exp, 0)); // The pointer. - Constant *Idx = ConvertInitializer(TREE_OPERAND(exp, 1)); // Offset in units. - - // Convert the pointer into an i8* and add the offset to it. - Ptr = TheFolder->CreateBitCast(Ptr, GetUnitPointerType(Context)); - Constant *GEP = POINTER_TYPE_OVERFLOW_UNDEFINED ? - TheFolder->CreateInBoundsGetElementPtr(Ptr, &Idx, 1) : - TheFolder->CreateGetElementPtr(Ptr, &Idx, 1); - - // The result may be of a different pointer type. - return TheFolder->CreateBitCast(GEP, ConvertType(TREE_TYPE(exp))); -} - -static Constant *ConvertVIEW_CONVERT_EXPR(tree exp) { - // Does not change the bits, only the type they are considered to be. - return ConvertInitializer(TREE_OPERAND(exp, 0)); -} - -/// ConvertInitializer - Convert the initial value for a global variable to an -/// equivalent LLVM constant. Also handles constant constructors. The type of -/// the returned value may be pretty much anything. All that is guaranteed is -/// that its alloc size is equal to the size of the initial value and that its -/// alignment is less than or equal to the initial value's GCC type alignment. -/// Note that the GCC type may have variable size or no size, in which case the -/// size is determined by the initial value. When this happens the size of the -/// initial value may exceed the alloc size of the LLVM memory type generated -/// for the GCC type (see ConvertType); it is never smaller than the alloc size. -Constant *ConvertInitializer(tree exp) { - Constant *Init; - switch (TREE_CODE(exp)) { - default: - DieAbjectly("Unknown constant to convert!", exp); - case COMPLEX_CST: - case INTEGER_CST: - case REAL_CST: - case VECTOR_CST: - // Make the IR easier to read by converting the bunch of bytes returned by - // ConvertCST into a less surprising type. - Init = InterpretAsType(ConvertCST(exp), ConvertType(TREE_TYPE(exp)), 0); - break; - case STRING_CST: - Init = ConvertSTRING_CST(exp); - break; - case ADDR_EXPR: - Init = ConvertADDR_EXPR(exp); - break; - case CONSTRUCTOR: - Init = ConvertCONSTRUCTOR(exp); - break; - case CONVERT_EXPR: - case NOP_EXPR: - Init = ConvertInitializerWithCast(TREE_OPERAND(exp, 0), TREE_TYPE(exp)); - break; - case MINUS_EXPR: - case PLUS_EXPR: - Init = ConvertBinOp_CST(exp); - break; - case POINTER_PLUS_EXPR: - Init = ConvertPOINTER_PLUS_EXPR(exp); - break; - case VIEW_CONVERT_EXPR: - Init = ConvertVIEW_CONVERT_EXPR(exp); - break; - } - -#ifndef NDEBUG - // Check that the guarantees we make about the returned value actually hold. - // The initializer should always be at least as big as the constructor's type, - // and except in the cases of incomplete types or types with variable size the - // sizes should be the same. - const Type *Ty = ConvertType(TREE_TYPE(exp)); - if (Ty->isSized()) { - uint64_t InitSize = getTargetData().getTypeAllocSizeInBits(Init->getType()); - uint64_t TypeSize = getTargetData().getTypeAllocSizeInBits(Ty); - if (InitSize < TypeSize) - DieAbjectly("Constant too small for type!", exp); - if (isInt64(TREE_TYPE(exp), true) && InitSize != TypeSize) - DieAbjectly("Constant too big for type!", exp); - } - if (getTargetData().getABITypeAlignment(Init->getType()) * 8 > - TYPE_ALIGN(TREE_TYPE(exp))) - DieAbjectly("Constant over aligned!", exp); -#endif - - return Init; -} - - -//===----------------------------------------------------------------------===// -// ... AddressOf ... -//===----------------------------------------------------------------------===// - -/// getAsInteger - Given a constant of integer type, return its value as an LLVM -/// integer constant. -static Constant *getAsInteger(tree exp) { - tree type = TREE_TYPE(exp); - assert(INTEGRAL_TYPE_P(type) && "Constant does not have integer type!"); - Constant *C = ConvertInitializer(exp); - const Type *IntTy = IntegerType::get(Context, TYPE_PRECISION(type)); - return InterpretAsType(C, IntTy, 0); -} - -/// AddressOfCST - Return the address of a simple constant, eg a of number. -static Constant *AddressOfCST(tree exp) { - Constant *Init = ConvertInitializer(exp); - - // Cache the constants to avoid making obvious duplicates that have to be - // folded by the optimizer. - static DenseMap CSTCache; - GlobalVariable *&Slot = CSTCache[Init]; - if (Slot) - return Slot; - - // Create a new global variable. - Slot = new GlobalVariable(*TheModule, Init->getType(), true, - GlobalVariable::PrivateLinkage, Init, ".cst"); - unsigned align = TYPE_ALIGN (TREE_TYPE (exp)); -#ifdef CONSTANT_ALIGNMENT - align = CONSTANT_ALIGNMENT (exp, align); -#endif - Slot->setAlignment(align); - - return Slot; -} - -/// AddressOfARRAY_REF - Return the address of an array element or slice. -static Constant *AddressOfARRAY_REF(tree exp) { - tree array = TREE_OPERAND(exp, 0); - tree index = TREE_OPERAND(exp, 1); - tree index_type = TREE_TYPE(index); - assert(TREE_CODE(TREE_TYPE(array)) == ARRAY_TYPE && "Unknown ARRAY_REF!"); - - // Check for variable sized reference. - assert(isSequentialCompatible(TREE_TYPE(array)) && - "Global with variable size?"); - - // Get the index into the array as an LLVM integer constant. - Constant *IndexVal = getAsInteger(index); - - // Subtract off the lower bound, if any. - tree lower_bound = array_ref_low_bound(exp); - if (!integer_zerop(lower_bound)) { - // Get the lower bound as an LLVM integer constant. - Constant *LowerBoundVal = getAsInteger(lower_bound); - IndexVal = TheFolder->CreateSub(IndexVal, LowerBoundVal, hasNUW(index_type), - hasNSW(index_type)); - } - - // Avoid any assumptions about how the array type is represented in LLVM by - // doing the GEP on a pointer to the first array element. - Constant *ArrayAddr = AddressOf(array); - const Type *EltTy = ConvertType(TREE_TYPE(TREE_TYPE(array))); - ArrayAddr = TheFolder->CreateBitCast(ArrayAddr, EltTy->getPointerTo()); - - return POINTER_TYPE_OVERFLOW_UNDEFINED ? - TheFolder->CreateInBoundsGetElementPtr(ArrayAddr, &IndexVal, 1) : - TheFolder->CreateGetElementPtr(ArrayAddr, &IndexVal, 1); -} - -/// AddressOfCOMPONENT_REF - Return the address of a field in a record. -static Constant *AddressOfCOMPONENT_REF(tree exp) { - tree field_decl = TREE_OPERAND(exp, 1); - - // Compute the field offset in units from the start of the record. - Constant *Offset; - if (TREE_OPERAND(exp, 2)) { - Offset = getAsInteger(TREE_OPERAND(exp, 2)); - // At this point the offset is measured in units divided by (exactly) - // (DECL_OFFSET_ALIGN / BITS_PER_UNIT). Convert to units. - unsigned factor = DECL_OFFSET_ALIGN(field_decl) / BITS_PER_UNIT; - if (factor != 1) - Offset = TheFolder->CreateMul(Offset, - ConstantInt::get(Offset->getType(), - factor)); - } else { - assert(DECL_FIELD_OFFSET(field_decl) && "Field offset not available!"); - Offset = getAsInteger(DECL_FIELD_OFFSET(field_decl)); - } - - // Here BitStart gives the offset of the field in bits from Offset. - uint64_t BitStart = getInt64(DECL_FIELD_BIT_OFFSET(field_decl), true); - // Incorporate as much of it as possible into the pointer computation. - uint64_t Units = BitStart / BITS_PER_UNIT; - if (Units > 0) { - Offset = TheFolder->CreateAdd(Offset, - ConstantInt::get(Offset->getType(), - Units)); - BitStart -= Units * BITS_PER_UNIT; - } - assert(BitStart == 0 && - "It's a bitfield reference or we didn't get to the field!"); - - const Type *UnitPtrTy = GetUnitPointerType(Context); - Constant *StructAddr = AddressOf(TREE_OPERAND(exp, 0)); - Constant *FieldPtr = TheFolder->CreateBitCast(StructAddr, UnitPtrTy); - FieldPtr = TheFolder->CreateInBoundsGetElementPtr(FieldPtr, &Offset, 1); - - return FieldPtr; -} - -/// AddressOfDecl - Return the address of a global. -static Constant *AddressOfDecl(tree exp) { - return cast(DEFINITION_LLVM(exp)); -} - -/// AddressOfINDIRECT_REF - Return the address of a dereference. -static Constant *AddressOfINDIRECT_REF(tree exp) { - // The address is just the dereferenced operand. Get it as an LLVM constant. - Constant *C = ConvertInitializer(TREE_OPERAND(exp, 0)); - // Make no assumptions about the type of the constant. - return InterpretAsType(C, ConvertType(TREE_TYPE(TREE_OPERAND(exp, 0))), 0); -} - -/// AddressOfLABEL_DECL - Return the address of a label. -static Constant *AddressOfLABEL_DECL(tree exp) { - extern TreeToLLVM *TheTreeToLLVM; - - assert(TheTreeToLLVM && - "taking the address of a label while not compiling the function!"); - - // Figure out which function this is for, verify it's the one we're compiling. - if (DECL_CONTEXT(exp)) { - assert(TREE_CODE(DECL_CONTEXT(exp)) == FUNCTION_DECL && - "Address of label in nested function?"); - assert(TheTreeToLLVM->getFUNCTION_DECL() == DECL_CONTEXT(exp) && - "Taking the address of a label that isn't in the current fn!?"); - } - - return TheTreeToLLVM->AddressOfLABEL_DECL(exp); -} - -/// AddressOf - Given an expression with a constant address such as a constant, -/// a global variable or a label, returns the address. The type of the returned -/// is always a pointer type and, as long as 'exp' does not have void type, the -/// type of the pointee is the memory type that corresponds to the type of exp -/// (see ConvertType). -Constant *AddressOf(tree exp) { - Constant *Addr; - - switch (TREE_CODE(exp)) { - default: - DieAbjectly("Unknown constant to take the address of!", exp); - case COMPLEX_CST: - case FIXED_CST: - case INTEGER_CST: - case REAL_CST: - case STRING_CST: - case VECTOR_CST: - Addr = AddressOfCST(exp); - break; - case ARRAY_RANGE_REF: - case ARRAY_REF: - Addr = AddressOfARRAY_REF(exp); - break; - case COMPONENT_REF: - Addr = AddressOfCOMPONENT_REF(exp); - break; - case COMPOUND_LITERAL_EXPR: // FIXME: not gimple - defined by C front-end - Addr = AddressOf(DECL_EXPR_DECL (TREE_OPERAND (exp, 0))); - break; - case CONST_DECL: - case FUNCTION_DECL: - case VAR_DECL: - Addr = AddressOfDecl(exp); - break; - case INDIRECT_REF: - Addr = AddressOfINDIRECT_REF(exp); - break; - case LABEL_DECL: - Addr = AddressOfLABEL_DECL(exp); - break; - } - - // Ensure that the address has the expected type. It is simpler to do this - // once here rather than in every AddressOf helper. - const Type *Ty; - if (VOID_TYPE_P(TREE_TYPE(exp))) - Ty = GetUnitPointerType(Context); // void* -> i8*. - else - Ty = ConvertType(TREE_TYPE(exp))->getPointerTo(); - - return TheFolder->CreateBitCast(Addr, Ty); -} Removed: dragonegg/trunk/Convert.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Convert.cpp?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/Convert.cpp (original) +++ dragonegg/trunk/Convert.cpp (removed) @@ -1,8047 +0,0 @@ -//===------------- Convert.cpp - Converting gimple to LLVM IR -------------===// -// -// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Chris Lattner, -// Duncan Sands et al. -// -// This file is part of DragonEgg. -// -// DragonEgg is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free Software -// Foundation; either version 2, or (at your option) any later version. -// -// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -// A PARTICULAR PURPOSE. See the GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along with -// DragonEgg; see the file COPYING. If not, write to the Free Software -// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. -// -//===----------------------------------------------------------------------===// -// This is the code that converts GCC AST nodes into LLVM code. -//===----------------------------------------------------------------------===// - -// Plugin headers -#include "dragonegg/ABI.h" -#include "dragonegg/Constants.h" -#include "dragonegg/Debug.h" -#include "dragonegg/Trees.h" - -// LLVM headers -#include "llvm/Module.h" -#include "llvm/Support/CFG.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Host.h" -#include "llvm/Target/TargetLowering.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/StringExtras.h" - -// System headers -#include - -// GCC headers -extern "C" { -#include "config.h" -// Stop GCC declaring 'getopt' as it can clash with the system's declaration. -#undef HAVE_DECL_GETOPT -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" - -#include "diagnostic.h" -#include "except.h" -#include "flags.h" -#include "langhooks.h" -#include "output.h" -#include "rtl.h" -#include "tm_p.h" -#include "toplev.h" -#include "tree-flow.h" -#include "tree-pass.h" - -extern int get_pointer_alignment (tree exp, unsigned int max_align); -extern enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER]; -} - -static LLVMContext &Context = getGlobalContext(); - -STATISTIC(NumBasicBlocks, "Number of basic blocks converted"); -STATISTIC(NumStatements, "Number of gimple statements converted"); - -/// getINTEGER_CSTVal - Return the specified INTEGER_CST value as a uint64_t. -/// -uint64_t getINTEGER_CSTVal(tree exp) { - unsigned HOST_WIDE_INT HI = (unsigned HOST_WIDE_INT)TREE_INT_CST_HIGH(exp); - unsigned HOST_WIDE_INT LO = (unsigned HOST_WIDE_INT)TREE_INT_CST_LOW(exp); - if (HOST_BITS_PER_WIDE_INT == 64) { - return (uint64_t)LO; - } else { - assert(HOST_BITS_PER_WIDE_INT == 32 && - "Only 32- and 64-bit hosts supported!"); - return ((uint64_t)HI << 32) | (uint64_t)LO; - } -} - -/// isInt64 - Return true if t is an INTEGER_CST that fits in a 64 bit integer. -/// If Unsigned is false, returns whether it fits in a int64_t. If Unsigned is -/// true, returns whether the value is non-negative and fits in a uint64_t. -/// Always returns false for overflowed constants. -bool isInt64(tree t, bool Unsigned) { - if (!t) - return false; - if (HOST_BITS_PER_WIDE_INT == 64) - return host_integerp(t, Unsigned) && !TREE_OVERFLOW (t); - assert(HOST_BITS_PER_WIDE_INT == 32 && - "Only 32- and 64-bit hosts supported!"); - return - (TREE_CODE (t) == INTEGER_CST && !TREE_OVERFLOW (t)) - && ((TYPE_UNSIGNED(TREE_TYPE(t)) == Unsigned) || - // If the constant is signed and we want an unsigned result, check - // that the value is non-negative. If the constant is unsigned and - // we want a signed result, check it fits in 63 bits. - (HOST_WIDE_INT)TREE_INT_CST_HIGH(t) >= 0); -} - -/// getInt64 - Extract the value of an INTEGER_CST as a 64 bit integer. If -/// Unsigned is false, the value must fit in a int64_t. If Unsigned is true, -/// the value must be non-negative and fit in a uint64_t. Must not be used on -/// overflowed constants. These conditions can be checked by calling isInt64. -uint64_t getInt64(tree t, bool Unsigned) { - assert(isInt64(t, Unsigned) && "invalid constant!"); - (void)Unsigned; // Otherwise unused if asserts off - avoid compiler warning. - return getINTEGER_CSTVal(t); -} - -/// getPointerAlignment - Return the alignment in bytes of exp, a pointer valued -/// expression, or 1 if the alignment is not known. -static unsigned int getPointerAlignment(tree exp) { - assert(POINTER_TYPE_P (TREE_TYPE (exp)) && "Expected a pointer type!"); - unsigned int align = get_pointer_alignment(exp, BIGGEST_ALIGNMENT) / 8; - return align ? align : 1; -} - -/// getSSAPlaceholder - A fake value associated with an SSA name when the name -/// is used before being defined (this can occur because basic blocks are not -/// output in dominator order). Replaced with the correct value when the SSA -/// name's definition is encountered. -static Value *GetSSAPlaceholder(const Type *Ty) { - // Cannot use a constant, since there is no way to distinguish a fake value - // from a real value. So use an instruction with no parent. This needs to - // be an instruction that can return a struct type, since the SSA name might - // be a complex number. It could be a PHINode, except that the GCC phi node - // conversion logic also constructs phi nodes with no parent. A SelectInst - // would work, but a LoadInst seemed neater. - return new LoadInst(UndefValue::get(Ty->getPointerTo()), NULL); -} - -/// isSSAPlaceholder - Whether this is a fake value being used as a placeholder -/// for the definition of an SSA name. -static bool isSSAPlaceholder(Value *V) { - LoadInst *LI = dyn_cast(V); - return LI && !LI->getParent(); -} - -/// NameValue - Try to name the given value after the given GCC tree node. If -/// the GCC tree node has no sensible name then it does nothing. If the value -/// already has a name then it is not changed. -static void NameValue(Value *V, tree t) { - if (!V->hasName()) { - const std::string &Name = getDescriptiveName(t); - if (!Name.empty()) - V->setName(Name); - } -} - -/// SelectFPName - Helper for choosing a name depending on whether a floating -/// point type is float, double or long double. -static StringRef SelectFPName(tree type, StringRef FloatName, - StringRef DoubleName, StringRef LongDoubleName) { - assert(SCALAR_FLOAT_TYPE_P(type) && "Expected a floating point type!"); - if (TYPE_MODE(type) == TYPE_MODE(float_type_node)) - return FloatName; - if (TYPE_MODE(type) == TYPE_MODE(double_type_node)) - return DoubleName; - assert(TYPE_MODE(type) == TYPE_MODE(long_double_type_node) && - "Unknown floating point type!"); - return LongDoubleName; -} - - -//===----------------------------------------------------------------------===// -// ... High-Level Methods ... -//===----------------------------------------------------------------------===// - -/// TheTreeToLLVM - Keep track of the current function being compiled. -TreeToLLVM *TheTreeToLLVM = 0; - -const TargetData &getTargetData() { - return *TheTarget->getTargetData(); -} - -/// EmitDebugInfo - Return true if debug info is to be emitted for current -/// function. -bool TreeToLLVM::EmitDebugInfo() { - if (TheDebugInfo && !DECL_IGNORED_P(getFUNCTION_DECL())) - return true; - return false; -} - -TreeToLLVM::TreeToLLVM(tree fndecl) : - TD(getTargetData()), Builder(Context, *TheFolder) { - FnDecl = fndecl; - AllocaInsertionPoint = 0; - Fn = 0; - ReturnBB = 0; - ReturnOffset = 0; - RewindBB = 0; - RewindTmp = 0; - - if (EmitDebugInfo()) { - expanded_location Location = expand_location(DECL_SOURCE_LOCATION (fndecl)); - - if (Location.file) { - TheDebugInfo->setLocationFile(Location.file); - TheDebugInfo->setLocationLine(Location.line); - } else { - TheDebugInfo->setLocationFile(""); - TheDebugInfo->setLocationLine(0); - } - } - - assert(TheTreeToLLVM == 0 && "Reentering function creation?"); - TheTreeToLLVM = this; -} - -TreeToLLVM::~TreeToLLVM() { - TheTreeToLLVM = 0; -} - -//===----------------------------------------------------------------------===// -// ... Local declarations ... -//===----------------------------------------------------------------------===// - -/// isLocalDecl - Whether this declaration is local to the current function. -static bool isLocalDecl(tree decl) { - assert(HAS_RTL_P(decl) && "Expected a declaration with RTL!"); - return DECL_CONTEXT(decl) == current_function_decl && - !TREE_STATIC(decl) && // Static variables not considered local. - TREE_CODE(decl) != FUNCTION_DECL; // Nested functions not considered local. -} - -/// set_decl_local - Remember the LLVM value for a GCC declaration. -Value *TreeToLLVM::set_decl_local(tree decl, Value *V) { - if (!isLocalDecl(decl)) - return set_decl_llvm(decl, V); - if (V != NULL) - return LocalDecls[decl] = V; - LocalDecls.erase(decl); - return NULL; -} - -/// get_decl_local - Retrieve the LLVM value for a GCC declaration, or NULL. -Value *TreeToLLVM::get_decl_local(tree decl) { - if (!isLocalDecl(decl)) - return get_decl_llvm(decl); - DenseMap >::iterator I = LocalDecls.find(decl); - if (I != LocalDecls.end()) - return I->second; - return NULL; -} - -/// make_decl_local - Return the LLVM value for a GCC declaration if it exists. -/// Otherwise creates and returns an appropriate value. -Value *TreeToLLVM::make_decl_local(tree decl) { - if (!isLocalDecl(decl)) - return make_decl_llvm(decl); - - DenseMap >::iterator I = LocalDecls.find(decl); - if (I != LocalDecls.end()) - return I->second; - - switch (TREE_CODE(decl)) { - default: - DieAbjectly("Unhandled local declaration!", decl); - - case RESULT_DECL: - case VAR_DECL: - EmitAutomaticVariableDecl(decl); - I = LocalDecls.find(decl); - assert(I != LocalDecls.end() && "Not a local variable?"); - return I->second; - } -} - -/// make_definition_local - Ensure that the body or initial value of the given -/// GCC declaration will be output, and return a declaration for it. -Value *TreeToLLVM::make_definition_local(tree decl) { - if (!isLocalDecl(decl)) - return make_definition_llvm(decl); - return make_decl_local(decl); -} - -/// llvm_store_scalar_argument - Store scalar argument ARGVAL of type -/// LLVMTY at location LOC. -static void llvm_store_scalar_argument(Value *Loc, Value *ArgVal, - const llvm::Type *LLVMTy, - unsigned RealSize, - LLVMBuilder &Builder) { - if (RealSize) { - // Not clear what this is supposed to do on big endian machines... - assert(!BYTES_BIG_ENDIAN && "Unsupported case - please report"); - // Do byte wise store because actual argument type does not match LLVMTy. - assert(ArgVal->getType()->isIntegerTy() && "Expected an integer value!"); - const Type *StoreType = IntegerType::get(Context, RealSize * 8); - Loc = Builder.CreateBitCast(Loc, StoreType->getPointerTo()); - if (ArgVal->getType()->getPrimitiveSizeInBits() >= - StoreType->getPrimitiveSizeInBits()) - ArgVal = Builder.CreateTrunc(ArgVal, StoreType); - else - ArgVal = Builder.CreateZExt(ArgVal, StoreType); - Builder.CreateStore(ArgVal, Loc); - } else { - // This cast only involves pointers, therefore BitCast. - Loc = Builder.CreateBitCast(Loc, LLVMTy->getPointerTo()); - Builder.CreateStore(ArgVal, Loc); - } -} - -#ifndef LLVM_STORE_SCALAR_ARGUMENT -#define LLVM_STORE_SCALAR_ARGUMENT(LOC,ARG,TYPE,SIZE,BUILDER) \ - llvm_store_scalar_argument((LOC),(ARG),(TYPE),(SIZE),(BUILDER)) -#endif - -// This is true for types whose alignment when passed on the stack is less -// than the alignment of the type. -#define LLVM_BYVAL_ALIGNMENT_TOO_SMALL(T) \ - (LLVM_BYVAL_ALIGNMENT(T) && LLVM_BYVAL_ALIGNMENT(T) < TYPE_ALIGN_UNIT(T)) - -namespace { - /// FunctionPrologArgumentConversion - This helper class is driven by the ABI - /// definition for this target to figure out how to retrieve arguments from - /// the stack/regs coming into a function and store them into an appropriate - /// alloca for the argument. - struct FunctionPrologArgumentConversion : public DefaultABIClient { - tree FunctionDecl; - Function::arg_iterator &AI; - LLVMBuilder Builder; - std::vector LocStack; - std::vector NameStack; - unsigned Offset; - CallingConv::ID &CallingConv; - bool isShadowRet; - FunctionPrologArgumentConversion(tree FnDecl, - Function::arg_iterator &ai, - const LLVMBuilder &B, CallingConv::ID &CC) - : FunctionDecl(FnDecl), AI(ai), Builder(B), Offset(0), CallingConv(CC), - isShadowRet(false) {} - - /// getCallingConv - This provides the desired CallingConv for the function. - CallingConv::ID& getCallingConv(void) { return CallingConv; } - - void HandlePad(const llvm::Type * /*LLVMTy*/) { - ++AI; - } - - bool isShadowReturn() const { - return isShadowRet; - } - void setName(const std::string &Name) { - NameStack.push_back(Name); - } - void setLocation(Value *Loc) { - LocStack.push_back(Loc); - } - void clear() { - assert(NameStack.size() == 1 && LocStack.size() == 1 && "Imbalance!"); - NameStack.clear(); - LocStack.clear(); - } - - void HandleAggregateShadowResult(const PointerType * /*PtrArgTy*/, - bool /*RetPtr*/) { - // If the function returns a structure by value, we transform the function - // to take a pointer to the result as the first argument of the function - // instead. - assert(AI != Builder.GetInsertBlock()->getParent()->arg_end() && - "No explicit return value?"); - AI->setName("agg.result"); - - isShadowRet = true; - tree ResultDecl = DECL_RESULT(FunctionDecl); - tree RetTy = TREE_TYPE(TREE_TYPE(FunctionDecl)); - if (TREE_CODE(RetTy) == TREE_CODE(TREE_TYPE(ResultDecl))) { - TheTreeToLLVM->set_decl_local(ResultDecl, AI); - ++AI; - return; - } - - // Otherwise, this must be something returned with NRVO. - assert(TREE_CODE(TREE_TYPE(ResultDecl)) == REFERENCE_TYPE && - "Not type match and not passing by reference?"); - // Create an alloca for the ResultDecl. - Value *Tmp = TheTreeToLLVM->CreateTemporary(AI->getType()); - Builder.CreateStore(AI, Tmp); - - TheTreeToLLVM->set_decl_local(ResultDecl, Tmp); - if (TheDebugInfo && !DECL_IGNORED_P(FunctionDecl)) { - TheDebugInfo->EmitDeclare(ResultDecl, - dwarf::DW_TAG_return_variable, - "agg.result", RetTy, Tmp, - Builder); - } - ++AI; - } - - void HandleScalarShadowResult(const PointerType * /*PtrArgTy*/, - bool /*RetPtr*/) { - assert(AI != Builder.GetInsertBlock()->getParent()->arg_end() && - "No explicit return value?"); - AI->setName("scalar.result"); - isShadowRet = true; - TheTreeToLLVM->set_decl_local(DECL_RESULT(FunctionDecl), AI); - ++AI; - } - - void HandleScalarArgument(const llvm::Type *LLVMTy, tree /*type*/, - unsigned RealSize = 0) { - Value *ArgVal = AI; - if (ArgVal->getType() != LLVMTy) { - if (ArgVal->getType()->isPointerTy() && LLVMTy->isPointerTy()) { - // If this is GCC being sloppy about pointer types, insert a bitcast. - // See PR1083 for an example. - ArgVal = Builder.CreateBitCast(ArgVal, LLVMTy); - } else if (ArgVal->getType()->isDoubleTy()) { - // If this is a K&R float parameter, it got promoted to double. Insert - // the truncation to float now. - ArgVal = Builder.CreateFPTrunc(ArgVal, LLVMTy, - NameStack.back().c_str()); - } else { - // If this is just a mismatch between integer types, this is due - // to K&R prototypes, where the forward proto defines the arg as int - // and the actual impls is a short or char. - assert(ArgVal->getType()->isIntegerTy(32) && LLVMTy->isIntegerTy() && - "Lowerings don't match?"); - ArgVal = Builder.CreateTrunc(ArgVal, LLVMTy,NameStack.back().c_str()); - } - } - assert(!LocStack.empty()); - Value *Loc = LocStack.back(); - LLVM_STORE_SCALAR_ARGUMENT(Loc,ArgVal,LLVMTy,RealSize,Builder); - AI->setName(NameStack.back()); - ++AI; - } - - void HandleByValArgument(const llvm::Type * /*LLVMTy*/, tree type) { - if (LLVM_BYVAL_ALIGNMENT_TOO_SMALL(type)) { - // Incoming object on stack is insufficiently aligned for the type. - // Make a correctly aligned copy. - assert(!LocStack.empty()); - Value *Loc = LocStack.back(); - // We cannot use field-by-field copy here; x86 long double is 16 - // bytes, but only 10 are copied. If the object is really a union - // we might need the other bytes. We must also be careful to use - // the smaller alignment. - const Type *SBP = Type::getInt8PtrTy(Context); - const Type *IntPtr = getTargetData().getIntPtrType(Context); - Value *Ops[5] = { - Builder.CreateCast(Instruction::BitCast, Loc, SBP), - Builder.CreateCast(Instruction::BitCast, AI, SBP), - ConstantInt::get(IntPtr, - TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type))), - ConstantInt::get(Type::getInt32Ty(Context), - LLVM_BYVAL_ALIGNMENT(type)), - ConstantInt::get(Type::getInt1Ty(Context), false) - }; - const Type *ArgTypes[3] = {SBP, SBP, IntPtr }; - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::memcpy, - ArgTypes, 3), Ops, Ops+5); - - AI->setName(NameStack.back()); - } - ++AI; - } - - void HandleFCAArgument(const llvm::Type * /*LLVMTy*/, tree /*type*/) { - // Store the FCA argument into alloca. - assert(!LocStack.empty()); - Value *Loc = LocStack.back(); - Builder.CreateStore(AI, Loc); - AI->setName(NameStack.back()); - ++AI; - } - - void HandleAggregateResultAsScalar(const Type * /*ScalarTy*/, - unsigned Offset = 0) { - this->Offset = Offset; - } - - void EnterField(unsigned FieldNo, const llvm::Type *StructTy) { - NameStack.push_back(NameStack.back()+"."+utostr(FieldNo)); - - Value *Loc = LocStack.back(); - // This cast only involves pointers, therefore BitCast. - Loc = Builder.CreateBitCast(Loc, StructTy->getPointerTo()); - - Loc = Builder.CreateStructGEP(Loc, FieldNo); - LocStack.push_back(Loc); - } - void ExitField() { - NameStack.pop_back(); - LocStack.pop_back(); - } - }; -} - -// isPassedByVal - Return true if an aggregate of the specified type will be -// passed in memory byval. -static bool isPassedByVal(tree type, const Type *Ty, - std::vector &ScalarArgs, - bool isShadowRet, CallingConv::ID &/*CC*/) { - if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) - return true; - - std::vector Args; - if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty, CC, Args) && - LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Args, ScalarArgs, isShadowRet, - CC)) - // We want to pass the whole aggregate in registers but only some of the - // registers are available. - return true; - return false; -} - -void TreeToLLVM::StartFunctionBody() { - std::string Name = getLLVMAssemblerName(FnDecl).str(); - // TODO: Add support for dropping the leading '\1' in order to support - // unsigned bswap(unsigned) __asm__("llvm.bswap"); - // This would also require adjustments in make_decl_llvm. - - // Determine the FunctionType and calling convention for this function. - tree static_chain = cfun->static_chain_decl; - const FunctionType *FTy; - CallingConv::ID CallingConv; - AttrListPtr PAL; - - bool getFunctionTypeFromArgList = false; - - // If the function has no arguments and is varargs (...), turn it into a - // non-varargs function by scanning the param list for the function. This - // allows C functions declared as "T foo() {}" to be treated like - // "T foo(void) {}" and allows us to handle functions with K&R-style - // definitions correctly. - // - // Note that we only do this in C/Objective-C. Doing this in C++ for - // functions explicitly declared as taking (...) is bad. - if (TYPE_ARG_TYPES(TREE_TYPE(FnDecl)) == 0 && flag_vararg_requires_arguments) - getFunctionTypeFromArgList = true; - - // When forcing vararg prototypes ensure that the function only gets a varargs - // part if it was originally declared varargs. - if (flag_force_vararg_prototypes) { - tree Args = TYPE_ARG_TYPES(TREE_TYPE(FnDecl)); - while (Args && TREE_VALUE(Args) != void_type_node) - Args = TREE_CHAIN(Args); - if (Args != 0) - getFunctionTypeFromArgList = true; - } - - if (getFunctionTypeFromArgList) - FTy = TheTypeConverter->ConvertArgListToFnType(TREE_TYPE(FnDecl), - DECL_ARGUMENTS(FnDecl), - static_chain, - CallingConv, PAL); - else - // Otherwise, just get the type from the function itself. - FTy = TheTypeConverter->ConvertFunctionType(TREE_TYPE(FnDecl), - FnDecl, - static_chain, - CallingConv, PAL); - - // If we've already seen this function and created a prototype, and if the - // proto has the right LLVM type, just use it. - if (DECL_LOCAL_SET_P(FnDecl) && - cast(DECL_LOCAL(FnDecl)->getType())->getElementType()==FTy) { - Fn = cast(DECL_LOCAL(FnDecl)); - assert(Fn->getCallingConv() == CallingConv && - "Calling convention disagreement between prototype and impl!"); - // The visibility can be changed from the last time we've seen this - // function. Set to current. - handleVisibility(FnDecl, Fn); - } else { - Function *FnEntry = TheModule->getFunction(Name); - if (FnEntry) { - assert(FnEntry->getName() == Name && "Same entry, different name?"); - assert((FnEntry->isDeclaration() || - FnEntry->getLinkage() == Function::AvailableExternallyLinkage) && - "Multiple fns with same name and neither are external!"); - FnEntry->setName(""); // Clear name to avoid conflicts. - assert(FnEntry->getCallingConv() == CallingConv && - "Calling convention disagreement between prototype and impl!"); - } - - // Otherwise, either it exists with the wrong type or it doesn't exist. In - // either case create a new function. - Fn = Function::Create(FTy, Function::ExternalLinkage, Name, TheModule); - assert(Fn->getName() == Name && "Preexisting fn with the same name!"); - Fn->setCallingConv(CallingConv); - Fn->setAttributes(PAL); - - // If a previous proto existed with the wrong type, replace any uses of it - // with the actual function and delete the proto. - if (FnEntry) { - FnEntry->replaceAllUsesWith - (TheFolder->CreateBitCast(Fn, FnEntry->getType())); - changeLLVMConstant(FnEntry, Fn); - FnEntry->eraseFromParent(); - } - SET_DECL_LOCAL(FnDecl, Fn); - } - - // The function should not already have a body. - assert(Fn->empty() && "Function expanded multiple times!"); - - // Compute the linkage that the function should get. - if (false) {//FIXME DECL_LLVM_PRIVATE(FnDecl)) { - Fn->setLinkage(Function::PrivateLinkage); - } else if (false) {//FIXME DECL_LLVM_LINKER_PRIVATE(FnDecl)) { - Fn->setLinkage(Function::LinkerPrivateLinkage); - } else if (!TREE_PUBLIC(FnDecl) /*|| lang_hooks.llvm_is_in_anon(subr)*/) { - Fn->setLinkage(Function::InternalLinkage); - } else if (DECL_COMDAT(FnDecl)) { - Fn->setLinkage(Function::getLinkOnceLinkage(flag_odr)); - } else if (DECL_WEAK(FnDecl)) { - // The user may have explicitly asked for weak linkage - ignore flag_odr. - Fn->setLinkage(Function::WeakAnyLinkage); - } else if (DECL_ONE_ONLY(FnDecl)) { - Fn->setLinkage(Function::getWeakLinkage(flag_odr)); - } else if (DECL_EXTERNAL(FnDecl)) { - Fn->setLinkage(Function::AvailableExternallyLinkage); - } - -#ifdef TARGET_ADJUST_LLVM_LINKAGE - TARGET_ADJUST_LLVM_LINKAGE(Fn,FnDecl); -#endif /* TARGET_ADJUST_LLVM_LINKAGE */ - - // Handle visibility style - handleVisibility(FnDecl, Fn); - - // Register constructors and destructors. - if (DECL_STATIC_CONSTRUCTOR(FnDecl)) - register_ctor_dtor(Fn, DECL_INIT_PRIORITY(FnDecl), true); - if (DECL_STATIC_DESTRUCTOR(FnDecl)) - register_ctor_dtor(Fn, DECL_FINI_PRIORITY(FnDecl), false); - - // Handle attribute "aligned". - if (DECL_ALIGN (FnDecl) != FUNCTION_BOUNDARY) - Fn->setAlignment(DECL_ALIGN (FnDecl) / 8); - - // Handle functions in specified sections. - if (DECL_SECTION_NAME(FnDecl)) - Fn->setSection(TREE_STRING_POINTER(DECL_SECTION_NAME(FnDecl))); - - // Handle used Functions - if (lookup_attribute ("used", DECL_ATTRIBUTES (FnDecl))) - AttributeUsedGlobals.insert(Fn); - - // Handle noinline Functions - if (lookup_attribute ("noinline", DECL_ATTRIBUTES (FnDecl))) - Fn->addFnAttr(Attribute::NoInline); - - // Handle always_inline attribute - if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (FnDecl))) - Fn->addFnAttr(Attribute::AlwaysInline); - - // Pass inline keyword to optimizer. - if (DECL_DECLARED_INLINE_P(FnDecl)) - Fn->addFnAttr(Attribute::InlineHint); - - if (optimize_size) - Fn->addFnAttr(Attribute::OptimizeForSize); - - // Handle stack smashing protection. - if (flag_stack_protect == 1) - Fn->addFnAttr(Attribute::StackProtect); - else if (flag_stack_protect == 2) - Fn->addFnAttr(Attribute::StackProtectReq); - - // Handle naked attribute - if (lookup_attribute ("naked", DECL_ATTRIBUTES (FnDecl))) - Fn->addFnAttr(Attribute::Naked); - - // Handle annotate attributes - if (DECL_ATTRIBUTES(FnDecl)) - AddAnnotateAttrsToGlobal(Fn, FnDecl); - - // Mark the function "nounwind" if not doing exception handling. - if (!flag_exceptions) - Fn->setDoesNotThrow(); - - // Create a new basic block for the function. - BasicBlock *EntryBlock = BasicBlock::Create(Context, "entry", Fn); - BasicBlocks[ENTRY_BLOCK_PTR] = EntryBlock; - Builder.SetInsertPoint(EntryBlock); - - if (EmitDebugInfo()) - TheDebugInfo->EmitFunctionStart(FnDecl, Fn); - - // Loop over all of the arguments to the function, setting Argument names and - // creating argument alloca's for the PARM_DECLs in case their address is - // exposed. - Function::arg_iterator AI = Fn->arg_begin(); - - // Rename and alloca'ify real arguments. - FunctionPrologArgumentConversion Client(FnDecl, AI, Builder, CallingConv); - DefaultABI ABIConverter(Client); - - // Handle the DECL_RESULT. - ABIConverter.HandleReturnType(TREE_TYPE(TREE_TYPE(FnDecl)), FnDecl, - DECL_BUILT_IN(FnDecl)); - // Remember this for use by FinishFunctionBody. - TheTreeToLLVM->ReturnOffset = Client.Offset; - - // Prepend the static chain (if any) to the list of arguments. - tree Args = static_chain ? static_chain : DECL_ARGUMENTS(FnDecl); - - // Scalar arguments processed so far. - std::vector ScalarArgs; - while (Args) { - const char *Name = "unnamed_arg"; - if (DECL_NAME(Args)) Name = IDENTIFIER_POINTER(DECL_NAME(Args)); - - const Type *ArgTy = ConvertType(TREE_TYPE(Args)); - bool isInvRef = isPassedByInvisibleReference(TREE_TYPE(Args)); - if (isInvRef || - (ArgTy->isVectorTy() && - LLVM_SHOULD_PASS_VECTOR_USING_BYVAL_ATTR(TREE_TYPE(Args)) && - !LLVM_BYVAL_ALIGNMENT_TOO_SMALL(TREE_TYPE(Args))) || - (!ArgTy->isSingleValueType() && - isPassedByVal(TREE_TYPE(Args), ArgTy, ScalarArgs, - Client.isShadowReturn(), CallingConv) && - !LLVM_BYVAL_ALIGNMENT_TOO_SMALL(TREE_TYPE(Args)))) { - // If the value is passed by 'invisible reference' or 'byval reference', - // the l-value for the argument IS the argument itself. But for byval - // arguments whose alignment as an argument is less than the normal - // alignment of the type (examples are x86-32 aggregates containing long - // double and large x86-64 vectors), we need to make the copy. - AI->setName(Name); - SET_DECL_LOCAL(Args, AI); - if (!isInvRef && EmitDebugInfo()) - TheDebugInfo->EmitDeclare(Args, dwarf::DW_TAG_arg_variable, - Name, TREE_TYPE(Args), - AI, Builder); - ABIConverter.HandleArgument(TREE_TYPE(Args), ScalarArgs); - } else { - // Otherwise, we create an alloca to hold the argument value and provide - // an l-value. On entry to the function, we copy formal argument values - // into the alloca. - Value *Tmp = CreateTemporary(ArgTy, TYPE_ALIGN_UNIT(TREE_TYPE(Args))); - Tmp->setName(std::string(Name)+"_addr"); - SET_DECL_LOCAL(Args, Tmp); - if (EmitDebugInfo()) { - TheDebugInfo->EmitDeclare(Args, dwarf::DW_TAG_arg_variable, - Name, TREE_TYPE(Args), Tmp, - Builder); - } - - // Emit annotate intrinsic if arg has annotate attr - if (DECL_ATTRIBUTES(Args)) - EmitAnnotateIntrinsic(Tmp, Args); - - // Emit gcroot intrinsic if arg has attribute - if (POINTER_TYPE_P(TREE_TYPE(Args)) - && lookup_attribute ("gcroot", TYPE_ATTRIBUTES(TREE_TYPE(Args)))) - EmitTypeGcroot(Tmp); - - Client.setName(Name); - Client.setLocation(Tmp); - ABIConverter.HandleArgument(TREE_TYPE(Args), ScalarArgs); - Client.clear(); - } - - Args = Args == static_chain ? DECL_ARGUMENTS(FnDecl) : TREE_CHAIN(Args); - } - - // Loading the value of a PARM_DECL at this point yields its initial value. - // Remember this for use when materializing the reads implied by SSA default - // definitions. - SSAInsertionPoint = Builder.Insert(CastInst::Create(Instruction::BitCast, - Constant::getNullValue(Type::getInt32Ty(Context)), - Type::getInt32Ty(Context)), "ssa point"); - - // If this function has nested functions, we should handle a potential - // nonlocal_goto_save_area. - if (cfun->nonlocal_goto_save_area) { - // Not supported yet. - } - - if (EmitDebugInfo()) - TheDebugInfo->EmitStopPoint(Builder.GetInsertBlock(), Builder); - - // Create a new block for the return node, but don't insert it yet. - ReturnBB = BasicBlock::Create(Context, "return"); -} - -/// DefineSSAName - Use the given value as the definition of the given SSA name. -/// Returns the provided value as a convenience. -Value *TreeToLLVM::DefineSSAName(tree reg, Value *Val) { - assert(TREE_CODE(reg) == SSA_NAME && "Not an SSA name!"); - if (Value *ExistingValue = SSANames[reg]) { - if (Val != ExistingValue) { - assert(isSSAPlaceholder(ExistingValue) && "Multiply defined SSA name!"); - // Replace the placeholder with the value everywhere. This also updates - // the map entry, because it is a TrackingVH. - ExistingValue->replaceAllUsesWith(Val); - delete ExistingValue; - } - return Val; - } - return SSANames[reg] = Val; -} - -typedef SmallVector, 8> PredVector; -typedef SmallVector, 8> TreeVector; -typedef SmallVector, 8> ValueVector; - -/// PopulatePhiNodes - Populate generated phi nodes with their operands. -void TreeToLLVM::PopulatePhiNodes() { - PredVector Predecessors; - TreeVector IncomingValues; - ValueVector PhiArguments; - - for (unsigned i = 0, e = PendingPhis.size(); i < e; ++i) { - // The phi node to process. - PhiRecord &P = PendingPhis[i]; - - // Extract the incoming value for each predecessor from the GCC phi node. - for (size_t i = 0, e = gimple_phi_num_args(P.gcc_phi); i != e; ++i) { - // The incoming GCC basic block. - basic_block bb = gimple_phi_arg_edge(P.gcc_phi, i)->src; - - // The corresponding LLVM basic block. - DenseMap::iterator BI = BasicBlocks.find(bb); - assert(BI != BasicBlocks.end() && "GCC basic block not output?"); - - // The incoming GCC expression. - tree val = gimple_phi_arg(P.gcc_phi, i)->def; - - // Associate it with the LLVM basic block. - IncomingValues.push_back(std::make_pair(BI->second, val)); - - // Several LLVM basic blocks may be generated when emitting one GCC basic - // block. The additional blocks always occur immediately after the main - // basic block, and can be identified by the fact that they are nameless. - // Associate the incoming expression with all of them, since any of them - // may occur as a predecessor of the LLVM basic block containing the phi. - Function::iterator FI(BI->second), FE = Fn->end(); - for (++FI; FI != FE && !FI->hasName(); ++FI) { - assert(FI->getSinglePredecessor() == IncomingValues.back().first && - "Anonymous block does not continue predecessor!"); - IncomingValues.push_back(std::make_pair(FI, val)); - } - } - - // Sort the incoming values by basic block to help speed up queries. - std::sort(IncomingValues.begin(), IncomingValues.end()); - - // Get the LLVM predecessors for the basic block containing the phi node, - // and remember their positions in the list of predecessors (this is used - // to avoid adding phi operands in a non-deterministic order). - Predecessors.reserve(gimple_phi_num_args(P.gcc_phi)); // At least this many. - BasicBlock *PhiBB = P.PHI->getParent(); - unsigned Index = 0; - for (pred_iterator PI = pred_begin(PhiBB), PE = pred_end(PhiBB); PI != PE; - ++PI, ++Index) - Predecessors.push_back(std::make_pair(*PI, Index)); - - if (Predecessors.empty()) { - // FIXME: If this happens then GCC has a control flow edge where LLVM has - // none - something has gone wrong. For the moment be laid back about it - // because the fact we don't yet wire up exception handling code means it - // happens all the time in Ada and C++. - P.PHI->replaceAllUsesWith(UndefValue::get(P.PHI->getType())); - P.PHI->eraseFromParent(); - IncomingValues.clear(); - continue; - } - - // Sort the predecessors by basic block. In GCC, each predecessor occurs - // exactly once. However in LLVM a predecessor can occur several times, - // and then every copy of the predecessor must be associated with exactly - // the same incoming value in the phi node. Sorting the predecessors groups - // multiple occurrences together, making this easy to handle. - std::sort(Predecessors.begin(), Predecessors.end()); - - // Now iterate over the predecessors, setting phi operands as we go. - TreeVector::iterator VI = IncomingValues.begin(), VE = IncomingValues.end(); - PredVector::iterator PI = Predecessors.begin(), PE = Predecessors.end(); - PhiArguments.resize(Predecessors.size()); - while (PI != PE) { - // The predecessor basic block. - BasicBlock *BB = PI->first; - - // Find the incoming value for this predecessor. - while (VI != VE && VI->first != BB) ++VI; - assert(VI != VE && "No value for predecessor!"); - Value *Val = EmitRegister(VI->second); - - // Need to bitcast to the right type (useless_type_conversion_p). Place - // the bitcast at the end of the predecessor, before the terminator. - if (Val->getType() != P.PHI->getType()) - Val = new BitCastInst(Val, P.PHI->getType(), "", BB->getTerminator()); - - // Add the phi node arguments for all occurrences of this predecessor. - do { - // Place the argument at the position given by PI->second, which is the - // original position before sorting of the predecessor in the pred list. - // Since the predecessors were sorted non-deterministically (by pointer - // value), this ensures that the same bitcode is produced on any run. - PhiArguments[PI++->second] = std::make_pair(BB, Val); - } while (PI != PE && PI->first == BB); - } - - // Add the operands to the phi node. - for (ValueVector::iterator I = PhiArguments.begin(), E = PhiArguments.end(); - I != E; ++I) - P.PHI->addIncoming(I->second, I->first); - - IncomingValues.clear(); - PhiArguments.clear(); - Predecessors.clear(); - } - - PendingPhis.clear(); -} - -Function *TreeToLLVM::FinishFunctionBody() { - // Insert the return block at the end of the function. - BeginBlock(ReturnBB); - - SmallVector RetVals; - - // If the function returns a value, get it into a register and return it now. - if (!Fn->getReturnType()->isVoidTy()) { - tree TreeRetVal = DECL_RESULT(FnDecl); - if (!AGGREGATE_TYPE_P(TREE_TYPE(TreeRetVal)) && - TREE_CODE(TREE_TYPE(TreeRetVal)) != COMPLEX_TYPE) { - // If the DECL_RESULT is a scalar type, just load out the return value - // and return it. - Value *RetVal = Builder.CreateLoad(DECL_LOCAL(TreeRetVal), "retval"); - RetVal = Builder.CreateBitCast(RetVal, Fn->getReturnType()); - RetVals.push_back(RetVal); - } else { - Value *RetVal = DECL_LOCAL(TreeRetVal); - if (const StructType *STy = dyn_cast(Fn->getReturnType())) { - Value *R1 = Builder.CreateBitCast(RetVal, STy->getPointerTo()); - - llvm::Value *Idxs[2]; - Idxs[0] = ConstantInt::get(llvm::Type::getInt32Ty(Context), 0); - for (unsigned ri = 0; ri < STy->getNumElements(); ++ri) { - Idxs[1] = ConstantInt::get(llvm::Type::getInt32Ty(Context), ri); - Value *GEP = Builder.CreateGEP(R1, Idxs, Idxs+2, "mrv_gep"); - Value *E = Builder.CreateLoad(GEP, "mrv"); - RetVals.push_back(E); - } - // If the return type specifies an empty struct then return one. - if (RetVals.empty()) - RetVals.push_back(UndefValue::get(Fn->getReturnType())); - } else { - // Otherwise, this aggregate result must be something that is returned - // in a scalar register for this target. We must bit convert the - // aggregate to the specified scalar type, which we do by casting the - // pointer and loading. The load does not necessarily start at the - // beginning of the aggregate (x86-64). - if (ReturnOffset) { - RetVal = Builder.CreateBitCast(RetVal, Type::getInt8PtrTy(Context)); - RetVal = Builder.CreateGEP(RetVal, - ConstantInt::get(TD.getIntPtrType(Context), ReturnOffset)); - } - RetVal = Builder.CreateBitCast(RetVal, - Fn->getReturnType()->getPointerTo()); - RetVal = Builder.CreateLoad(RetVal, "retval"); - RetVals.push_back(RetVal); - } - } - } - if (RetVals.empty()) - Builder.CreateRetVoid(); - else if (RetVals.size() == 1 && RetVals[0]->getType() == Fn->getReturnType()){ - Builder.CreateRet(RetVals[0]); - } else { - assert(Fn->getReturnType()->isAggregateType() && "Return type mismatch!"); - Builder.CreateAggregateRet(RetVals.data(), RetVals.size()); - } - - // Populate phi nodes with their operands now that all ssa names have been - // defined and all basic blocks output. - PopulatePhiNodes(); - - // Now that phi nodes have been output, emit pending exception handling code. - EmitLandingPads(); - EmitFailureBlocks(); - EmitRewindBlock(); - - if (EmitDebugInfo()) { - // FIXME: This should be output just before the return call generated above. - // But because EmitFunctionEnd pops the region stack, that means that if the - // call to PopulatePhiNodes (for example) generates complicated debug info, - // then the debug info logic barfs. Testcases showing this are 20011126-2.c - // or pr42221.c from the gcc testsuite compiled with -g -O3. - TheDebugInfo->EmitStopPoint(ReturnBB, Builder); - TheDebugInfo->EmitFunctionEnd(true); - } - -#ifdef NDEBUG - // When processing broken code it can be awkward to ensure that every SSA name - // that was used has a definition. So in this case we play it cool and create - // an artificial definition for such SSA names. The choice of definition does - // not matter because the compiler is going to exit with an error anyway. - if (errorcount || sorrycount) -#else - // When checks are enabled, complain if an SSA name was used but not defined. -#endif - for (DenseMap >::const_iterator I = SSANames.begin(), - E = SSANames.end(); I != E; ++I) { - Value *NameDef = I->second; - // If this is not a placeholder then the SSA name was defined. - if (!isSSAPlaceholder(NameDef)) - continue; - - // If an error occurred then replace the placeholder with undef. Thanks - // to this we can just bail out on errors, without having to worry about - // whether we defined every SSA name. - if (errorcount || sorrycount) { - NameDef->replaceAllUsesWith(UndefValue::get(NameDef->getType())); - delete NameDef; - } else { - DieAbjectly("SSA name never defined!", I->first); - } - } - - return Fn; -} - -/// getBasicBlock - Find or create the LLVM basic block corresponding to BB. -BasicBlock *TreeToLLVM::getBasicBlock(basic_block bb) { - // If we already associated an LLVM basic block with BB, then return it. - DenseMap::iterator I = BasicBlocks.find(bb); - if (I != BasicBlocks.end()) - return I->second; - - // Otherwise, create a new LLVM basic block. - BasicBlock *BB = BasicBlock::Create(Context); - - // All basic blocks that directly correspond to GCC basic blocks (those - // created here) must have a name. All artificial basic blocks produced - // while generating code must be nameless. That way, artificial blocks - // can be easily identified. - - // Give the basic block a name. If the user specified -fverbose-asm then - // use the same naming scheme as GCC. - if (flag_verbose_asm) { - // If BB contains labels, name the LLVM basic block after the first label. - gimple stmt = first_stmt(bb); - if (stmt && gimple_code(stmt) == GIMPLE_LABEL) { - tree label = gimple_label_label(stmt); - const std::string &LabelName = getDescriptiveName(label); - if (!LabelName.empty()) - BB->setName("<" + LabelName + ">"); - } else { - // When there is no label, use the same name scheme as the GCC tree dumps. - Twine Index(bb->index); - BB->setName(""); - } - } else { - Twine Index(bb->index); - BB->setName(Index); - } - - return BasicBlocks[bb] = BB; -} - -/// getLabelDeclBlock - Lazily get and create a basic block for the specified -/// label. -BasicBlock *TreeToLLVM::getLabelDeclBlock(tree LabelDecl) { - assert(TREE_CODE(LabelDecl) == LABEL_DECL && "Isn't a label!?"); - if (DECL_LOCAL_SET_P(LabelDecl)) - return cast(DECL_LOCAL(LabelDecl)); - - basic_block bb = label_to_block(LabelDecl); - if (!bb) { - sorry("address of a non-local label"); - bb = ENTRY_BLOCK_PTR; // Do not crash. - } - - BasicBlock *BB = getBasicBlock(bb); - SET_DECL_LOCAL(LabelDecl, BB); - return BB; -} - -void TreeToLLVM::EmitBasicBlock(basic_block bb) { - ++NumBasicBlocks; - - // Avoid outputting a pointless branch at the end of the entry block. - if (bb != ENTRY_BLOCK_PTR) - BeginBlock(getBasicBlock(bb)); - - // Create an LLVM phi node for each GCC phi and define the associated ssa name - // using it. Do not populate with operands at this point since some ssa names - // the phi uses may not have been defined yet - phis are special this way. - for (gimple_stmt_iterator gsi = gsi_start_phis(bb); !gsi_end_p(gsi); - gsi_next(&gsi)) { - gimple gcc_phi = gsi_stmt(gsi); - // Skip virtual operands. - if (!is_gimple_reg(gimple_phi_result(gcc_phi))) - continue; - - // Create the LLVM phi node. - const Type *Ty = GetRegType(TREE_TYPE(gimple_phi_result(gcc_phi))); - PHINode *PHI = Builder.CreatePHI(Ty, gimple_phi_num_args(gcc_phi)); - - // The phi defines the associated ssa name. - tree name = gimple_phi_result(gcc_phi); - assert(TREE_CODE(name) == SSA_NAME && "PHI result not an SSA name!"); - if (flag_verbose_asm) - NameValue(PHI, name); - DefineSSAName(name, PHI); - - // The phi operands will be populated later - remember the phi node. - PhiRecord P = { gcc_phi, PHI }; - PendingPhis.push_back(P); - } - - // Render statements. - for (gimple_stmt_iterator gsi = gsi_start_bb(bb); !gsi_end_p(gsi); - gsi_next(&gsi)) { - gimple stmt = gsi_stmt(gsi); - ++NumStatements; - - if (EmitDebugInfo()) { - if (gimple_has_location(stmt)) { - TheDebugInfo->setLocationFile(gimple_filename(stmt)); - TheDebugInfo->setLocationLine(gimple_lineno(stmt)); - } else { - TheDebugInfo->setLocationFile(""); - TheDebugInfo->setLocationLine(0); - } - TheDebugInfo->EmitStopPoint(Builder.GetInsertBlock(), Builder); - } - - switch (gimple_code(stmt)) { - default: - DieAbjectly("Unhandled GIMPLE statement during LLVM emission!", stmt); - - case GIMPLE_ASM: - RenderGIMPLE_ASM(stmt); - break; - - case GIMPLE_ASSIGN: - RenderGIMPLE_ASSIGN(stmt); - break; - - case GIMPLE_CALL: - RenderGIMPLE_CALL(stmt); - break; - - case GIMPLE_COND: - RenderGIMPLE_COND(stmt); - break; - - case GIMPLE_DEBUG: - // TODO: Output debug info rather than just discarding it. - break; - - case GIMPLE_EH_DISPATCH: - RenderGIMPLE_EH_DISPATCH(stmt); - break; - - case GIMPLE_GOTO: - RenderGIMPLE_GOTO(stmt); - break; - - case GIMPLE_LABEL: - case GIMPLE_NOP: - case GIMPLE_PREDICT: - break; - - case GIMPLE_RESX: - RenderGIMPLE_RESX(stmt); - break; - - case GIMPLE_RETURN: - RenderGIMPLE_RETURN(stmt); - break; - - case GIMPLE_SWITCH: - RenderGIMPLE_SWITCH(stmt); - break; - } - } - - if (EmitDebugInfo()) { - TheDebugInfo->setLocationFile(""); - TheDebugInfo->setLocationLine(0); - TheDebugInfo->EmitStopPoint(Builder.GetInsertBlock(), Builder); - } - - // Add a branch to the fallthru block. - edge e; - edge_iterator ei; - FOR_EACH_EDGE (e, ei, bb->succs) - if (e->flags & EDGE_FALLTHRU) { - Builder.CreateBr(getBasicBlock(e->dest)); - break; - } -} - -Function *TreeToLLVM::EmitFunction() { - // Set up parameters and prepare for return, for the function. - StartFunctionBody(); - - // Output the basic blocks. - basic_block bb; - FOR_EACH_BB(bb) - EmitBasicBlock(bb); - - // Wrap things up. - return FinishFunctionBody(); -} - -/// EmitAggregate - Store the specified tree node into the location given by -/// DestLoc. -void TreeToLLVM::EmitAggregate(tree exp, const MemRef &DestLoc) { - assert(AGGREGATE_TYPE_P(TREE_TYPE(exp)) && "Expected an aggregate type!"); - if (TREE_CODE(exp) == CONSTRUCTOR) { - EmitCONSTRUCTOR(exp, &DestLoc); - return; - } - LValue LV = EmitLV(exp); - assert(!LV.isBitfield() && "Bitfields containing aggregates not supported!"); - EmitAggregateCopy(DestLoc, MemRef(LV.Ptr, LV.getAlignment(), - TREE_THIS_VOLATILE(exp)), TREE_TYPE(exp)); -} - -/// get_constant_alignment - Return the alignment of constant EXP in bits. -/// -static unsigned int -get_constant_alignment (tree exp) -{ - unsigned int align = TYPE_ALIGN (TREE_TYPE (exp)); -#ifdef CONSTANT_ALIGNMENT - align = CONSTANT_ALIGNMENT (exp, align); -#endif - return align; -} - -/// EmitLV - Convert the specified l-value tree node to LLVM code, returning -/// the address of the result. -LValue TreeToLLVM::EmitLV(tree exp) { - LValue LV; - - switch (TREE_CODE(exp)) { - default: - DieAbjectly("Unhandled lvalue expression!", exp); - - case PARM_DECL: - case VAR_DECL: - case FUNCTION_DECL: - case CONST_DECL: - case RESULT_DECL: - LV = EmitLV_DECL(exp); - break; - case ARRAY_RANGE_REF: - case ARRAY_REF: - LV = EmitLV_ARRAY_REF(exp); - break; - case COMPONENT_REF: - LV = EmitLV_COMPONENT_REF(exp); - break; - case BIT_FIELD_REF: - LV = EmitLV_BIT_FIELD_REF(exp); - break; - case REALPART_EXPR: - LV = EmitLV_XXXXPART_EXPR(exp, 0); - break; - case IMAGPART_EXPR: - LV = EmitLV_XXXXPART_EXPR(exp, 1); - break; - case SSA_NAME: - LV = EmitLV_SSA_NAME(exp); - break; - case TARGET_MEM_REF: - LV = EmitLV_TARGET_MEM_REF(exp); - break; - - // Constants. - case LABEL_DECL: { - LV = LValue(AddressOfLABEL_DECL(exp), 1); - break; - } - case COMPLEX_CST: - case REAL_CST: - case STRING_CST: { - Value *Ptr = AddressOf(exp); - LV = LValue(Ptr, get_constant_alignment(exp) / 8); - break; - } - - // Type Conversion. - case VIEW_CONVERT_EXPR: - LV = EmitLV_VIEW_CONVERT_EXPR(exp); - break; - - // Trivial Cases. - case WITH_SIZE_EXPR: - LV = EmitLV_WITH_SIZE_EXPR(exp); - break; - case INDIRECT_REF: - LV = EmitLV_INDIRECT_REF(exp); - break; - } - - // Check that the type of the lvalue is indeed that of a pointer to the tree - // node. This may not hold for bitfields because the type of a bitfield need - // not match the type of the value being loaded out of it. Since LLVM has no - // void* type, don't insist that void* be converted to a specific LLVM type. - assert((LV.isBitfield() || VOID_TYPE_P(TREE_TYPE(exp)) || - LV.Ptr->getType() == ConvertType(TREE_TYPE(exp))->getPointerTo()) && - "LValue has wrong type!"); - - return LV; -} - -//===----------------------------------------------------------------------===// -// ... Utility Functions ... -//===----------------------------------------------------------------------===// - -/// CastToAnyType - Cast the specified value to the specified type making no -/// assumptions about the types of the arguments. This creates an inferred cast. -Value *TreeToLLVM::CastToAnyType(Value *V, bool VisSigned, - const Type* DestTy, bool DestIsSigned) { - const Type *SrcTy = V->getType(); - - // Eliminate useless casts of a type to itself. - if (SrcTy == DestTy) - return V; - - // Check whether the cast needs to be done in two steps, for example a pointer - // to float cast requires converting the pointer to an integer before casting - // to the float. - if (!CastInst::isCastable(SrcTy, DestTy)) { - unsigned SrcBits = SrcTy->getScalarSizeInBits(); - unsigned DestBits = DestTy->getScalarSizeInBits(); - if (SrcBits && !isa(SrcTy)) { - const Type *IntTy = IntegerType::get(Context, SrcBits); - V = Builder.CreateBitCast(V, IntTy); - return CastToAnyType(V, VisSigned, DestTy, DestIsSigned); - } - if (DestBits && !isa(DestTy)) { - const Type *IntTy = IntegerType::get(Context, DestBits); - V = CastToAnyType(V, VisSigned, IntTy, DestIsSigned); - return Builder.CreateBitCast(V, DestTy); - } - assert(false && "Unable to cast between these types!"); - } - - // The types are different so we must cast. Use getCastOpcode to create an - // inferred cast opcode. - Instruction::CastOps opc = - CastInst::getCastOpcode(V, VisSigned, DestTy, DestIsSigned); - - // Generate the cast and return it. - return Builder.CreateCast(opc, V, DestTy); -} - -/// CastToFPType - Cast the specified value to the specified type assuming -/// that the value and type are floating point. -Value *TreeToLLVM::CastToFPType(Value *V, const Type* Ty) { - unsigned SrcBits = V->getType()->getPrimitiveSizeInBits(); - unsigned DstBits = Ty->getPrimitiveSizeInBits(); - if (SrcBits == DstBits) - return V; - Instruction::CastOps opcode = (SrcBits > DstBits ? - Instruction::FPTrunc : Instruction::FPExt); - return Builder.CreateCast(opcode, V, Ty); -} - -/// CreateAnyAdd - Add two LLVM scalar values with the given GCC type. Does not -/// support complex numbers. The type is used to set overflow flags. -Value *TreeToLLVM::CreateAnyAdd(Value *LHS, Value *RHS, tree type) { - if (FLOAT_TYPE_P(type)) - return Builder.CreateFAdd(LHS, RHS); - return Builder.CreateAdd(LHS, RHS, "", hasNUW(type), hasNSW(type)); -} - -/// CreateAnyMul - Multiply two LLVM scalar values with the given GCC type. -/// Does not support complex numbers. The type is used to set overflow flags. -Value *TreeToLLVM::CreateAnyMul(Value *LHS, Value *RHS, tree type) { - if (FLOAT_TYPE_P(type)) - return Builder.CreateFMul(LHS, RHS); - return Builder.CreateMul(LHS, RHS, "", hasNUW(type), hasNSW(type)); -} - -/// CreateAnyNeg - Negate an LLVM scalar value with the given GCC type. Does -/// not support complex numbers. The type is used to set overflow flags. -Value *TreeToLLVM::CreateAnyNeg(Value *V, tree type) { - if (FLOAT_TYPE_P(type)) - return Builder.CreateFNeg(V); - return Builder.CreateNeg(V, "", hasNUW(type), hasNSW(type)); -} - -/// CreateAnySub - Subtract two LLVM scalar values with the given GCC type. -/// Does not support complex numbers. The type is used to set overflow flags. -Value *TreeToLLVM::CreateAnySub(Value *LHS, Value *RHS, tree type) { - if (FLOAT_TYPE_P(type)) - return Builder.CreateFSub(LHS, RHS); - return Builder.CreateSub(LHS, RHS, "", hasNUW(type), hasNSW(type)); -} - -/// CreateTemporary - Create a new alloca instruction of the specified type, -/// inserting it into the entry block and returning it. The resulting -/// instruction's type is a pointer to the specified type. -AllocaInst *TreeToLLVM::CreateTemporary(const Type *Ty, unsigned align) { - if (AllocaInsertionPoint == 0) { - // Create a dummy instruction in the entry block as a marker to insert new - // alloc instructions before. It doesn't matter what this instruction is, - // it is dead. This allows us to insert allocas in order without having to - // scan for an insertion point. Use BitCast for int -> int - AllocaInsertionPoint = CastInst::Create(Instruction::BitCast, - Constant::getNullValue(Type::getInt32Ty(Context)), - Type::getInt32Ty(Context), "alloca point"); - // Insert it as the first instruction in the entry block. - Fn->begin()->getInstList().insert(Fn->begin()->begin(), - AllocaInsertionPoint); - } - return new AllocaInst(Ty, 0, align, "memtmp", AllocaInsertionPoint); -} - -/// CreateTempLoc - Like CreateTemporary, but returns a MemRef. -MemRef TreeToLLVM::CreateTempLoc(const Type *Ty) { - AllocaInst *AI = CreateTemporary(Ty); - // MemRefs do not allow alignment 0. - if (!AI->getAlignment()) - AI->setAlignment(TD.getPrefTypeAlignment(Ty)); - return MemRef(AI, AI->getAlignment(), false); -} - -/// BeginBlock - Add the specified basic block to the end of the function. If -/// the previous block falls through into it, add an explicit branch. -void TreeToLLVM::BeginBlock(BasicBlock *BB) { - BasicBlock *CurBB = Builder.GetInsertBlock(); - // If the previous block falls through to BB, add an explicit branch. - if (CurBB->getTerminator() == 0) { - // If the previous block has no label and is empty, remove it: it is a - // post-terminator block. - if (CurBB->getName().empty() && CurBB->begin() == CurBB->end()) - CurBB->eraseFromParent(); - else - // Otherwise, fall through to this block. - Builder.CreateBr(BB); - } - - // Add this block. - Fn->getBasicBlockList().push_back(BB); - Builder.SetInsertPoint(BB); // It is now the current block. -} - -/// CopyAggregate - Recursively traverse the potientially aggregate src/dest -/// ptrs, copying all of the elements. -static void CopyAggregate(MemRef DestLoc, MemRef SrcLoc, - LLVMBuilder &Builder, tree gccType) { - assert(DestLoc.Ptr->getType() == SrcLoc.Ptr->getType() && - "Cannot copy between two pointers of different type!"); - const Type *ElTy = - cast(DestLoc.Ptr->getType())->getElementType(); - - unsigned Alignment = std::min(DestLoc.getAlignment(), SrcLoc.getAlignment()); - - if (ElTy->isSingleValueType()) { - LoadInst *V = Builder.CreateLoad(SrcLoc.Ptr, SrcLoc.Volatile); - StoreInst *S = Builder.CreateStore(V, DestLoc.Ptr, DestLoc.Volatile); - V->setAlignment(Alignment); - S->setAlignment(Alignment); - } else if (const StructType *STy = dyn_cast(ElTy)) { - const StructLayout *SL = getTargetData().getStructLayout(STy); - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - if (gccType && isPaddingElement(gccType, i)) - continue; - Value *DElPtr = Builder.CreateStructGEP(DestLoc.Ptr, i); - Value *SElPtr = Builder.CreateStructGEP(SrcLoc.Ptr, i); - unsigned Align = MinAlign(Alignment, SL->getElementOffset(i)); - CopyAggregate(MemRef(DElPtr, Align, DestLoc.Volatile), - MemRef(SElPtr, Align, SrcLoc.Volatile), - Builder, 0); - } - } else { - const ArrayType *ATy = cast(ElTy); - unsigned EltSize = getTargetData().getTypeAllocSize(ATy->getElementType()); - for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { - Value *DElPtr = Builder.CreateStructGEP(DestLoc.Ptr, i); - Value *SElPtr = Builder.CreateStructGEP(SrcLoc.Ptr, i); - unsigned Align = MinAlign(Alignment, i * EltSize); - CopyAggregate(MemRef(DElPtr, Align, DestLoc.Volatile), - MemRef(SElPtr, Align, SrcLoc.Volatile), - Builder, 0); - } - } -} - -/// CountAggregateElements - Return the number of elements in the specified type -/// that will need to be loaded/stored if we copy this by explicit accesses. -static unsigned CountAggregateElements(const Type *Ty) { - if (Ty->isSingleValueType()) return 1; - - if (const StructType *STy = dyn_cast(Ty)) { - unsigned NumElts = 0; - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) - NumElts += CountAggregateElements(STy->getElementType(i)); - return NumElts; - } else { - const ArrayType *ATy = cast(Ty); - return ATy->getNumElements()*CountAggregateElements(ATy->getElementType()); - } -} - -/// containsFPField - indicates whether the given LLVM type -/// contains any floating point elements. - -static bool containsFPField(const Type *LLVMTy) { - if (LLVMTy->isFloatingPointTy()) - return true; - const StructType* STy = dyn_cast(LLVMTy); - if (STy) { - for (StructType::element_iterator I = STy->element_begin(), - E = STy->element_end(); I != E; I++) { - const Type *Ty = *I; - if (Ty->isFloatingPointTy()) - return true; - if (Ty->isStructTy() && containsFPField(Ty)) - return true; - const ArrayType *ATy = dyn_cast(Ty); - if (ATy && containsFPField(ATy->getElementType())) - return true; - const VectorType *VTy = dyn_cast(Ty); - if (VTy && containsFPField(VTy->getElementType())) - return true; - } - } - return false; -} - -#ifndef TARGET_LLVM_MIN_BYTES_COPY_BY_MEMCPY -#define TARGET_LLVM_MIN_BYTES_COPY_BY_MEMCPY 64 -#endif - -/// EmitAggregateCopy - Copy the elements from SrcLoc to DestLoc, using the -/// GCC type specified by GCCType to know which elements to copy. -void TreeToLLVM::EmitAggregateCopy(MemRef DestLoc, MemRef SrcLoc, tree type) { - if (DestLoc.Ptr == SrcLoc.Ptr && !DestLoc.Volatile && !SrcLoc.Volatile) - return; // noop copy. - - // If the type is small, copy the elements instead of using a block copy. - const Type *LLVMTy = ConvertType(type); - unsigned NumElts = CountAggregateElements(LLVMTy); - if (TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST && - (NumElts == 1 || - TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) < - TARGET_LLVM_MIN_BYTES_COPY_BY_MEMCPY)) { - - // Some targets (x87) cannot pass non-floating-point values using FP - // instructions. The LLVM type for a union may include FP elements, - // even if some of the union fields do not; it is unsafe to pass such - // converted types element by element. PR 2680. - - // If the GCC type is not fully covered by the LLVM type, use memcpy. This - // can occur with unions etc. - if ((TREE_CODE(type) != UNION_TYPE || !containsFPField(LLVMTy)) && - !TheTypeConverter->GCCTypeOverlapsWithLLVMTypePadding(type, LLVMTy) && - // Don't copy tons of tiny elements. - NumElts <= 8) { - DestLoc.Ptr = Builder.CreateBitCast(DestLoc.Ptr, LLVMTy->getPointerTo()); - SrcLoc.Ptr = Builder.CreateBitCast(SrcLoc.Ptr, LLVMTy->getPointerTo()); - CopyAggregate(DestLoc, SrcLoc, Builder, type); - return; - } - } - - Value *TypeSize = EmitRegister(TYPE_SIZE_UNIT(type)); - EmitMemCpy(DestLoc.Ptr, SrcLoc.Ptr, TypeSize, - std::min(DestLoc.getAlignment(), SrcLoc.getAlignment())); -} - -/// ZeroAggregate - Recursively traverse the potentially aggregate DestLoc, -/// zero'ing all of the elements. -static void ZeroAggregate(MemRef DestLoc, LLVMBuilder &Builder) { - const Type *ElTy = - cast(DestLoc.Ptr->getType())->getElementType(); - if (ElTy->isSingleValueType()) { - StoreInst *St = Builder.CreateStore(Constant::getNullValue(ElTy), - DestLoc.Ptr, DestLoc.Volatile); - St->setAlignment(DestLoc.getAlignment()); - } else if (const StructType *STy = dyn_cast(ElTy)) { - const StructLayout *SL = getTargetData().getStructLayout(STy); - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - Value *Ptr = Builder.CreateStructGEP(DestLoc.Ptr, i); - unsigned Alignment = MinAlign(DestLoc.getAlignment(), - SL->getElementOffset(i)); - ZeroAggregate(MemRef(Ptr, Alignment, DestLoc.Volatile), Builder); - } - } else { - const ArrayType *ATy = cast(ElTy); - unsigned EltSize = getTargetData().getTypeAllocSize(ATy->getElementType()); - for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { - Value *Ptr = Builder.CreateStructGEP(DestLoc.Ptr, i); - unsigned Alignment = MinAlign(DestLoc.getAlignment(), i * EltSize); - ZeroAggregate(MemRef(Ptr, Alignment, DestLoc.Volatile), Builder); - } - } -} - -/// EmitAggregateZero - Zero the elements of DestLoc. -void TreeToLLVM::EmitAggregateZero(MemRef DestLoc, tree type) { - // If the type is small, copy the elements instead of using a block copy. - if (TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST && - TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) < 128) { - const Type *LLVMTy = ConvertType(type); - - // If the GCC type is not fully covered by the LLVM type, use memset. This - // can occur with unions etc. - if (!TheTypeConverter->GCCTypeOverlapsWithLLVMTypePadding(type, LLVMTy) && - // Don't zero tons of tiny elements. - CountAggregateElements(LLVMTy) <= 8) { - DestLoc.Ptr = Builder.CreateBitCast(DestLoc.Ptr, LLVMTy->getPointerTo()); - ZeroAggregate(DestLoc, Builder); - return; - } - } - - EmitMemSet(DestLoc.Ptr, ConstantInt::get(Type::getInt8Ty(Context), 0), - EmitRegister(TYPE_SIZE_UNIT(type)), DestLoc.getAlignment()); -} - -Value *TreeToLLVM::EmitMemCpy(Value *DestPtr, Value *SrcPtr, Value *Size, - unsigned Align) { - const Type *SBP = Type::getInt8PtrTy(Context); - const Type *IntPtr = TD.getIntPtrType(Context); - Value *Ops[5] = { - Builder.CreateBitCast(DestPtr, SBP), - Builder.CreateBitCast(SrcPtr, SBP), - Builder.CreateIntCast(Size, IntPtr, /*isSigned*/true), - ConstantInt::get(Type::getInt32Ty(Context), Align), - ConstantInt::get(Type::getInt1Ty(Context), false) - }; - const Type *ArgTypes[3] = { SBP, SBP, IntPtr }; - - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::memcpy, - ArgTypes, 3), Ops, Ops+5); - return Ops[0]; -} - -Value *TreeToLLVM::EmitMemMove(Value *DestPtr, Value *SrcPtr, Value *Size, - unsigned Align) { - const Type *SBP = Type::getInt8PtrTy(Context); - const Type *IntPtr = TD.getIntPtrType(Context); - Value *Ops[5] = { - Builder.CreateBitCast(DestPtr, SBP), - Builder.CreateBitCast(SrcPtr, SBP), - Builder.CreateIntCast(Size, IntPtr, /*isSigned*/true), - ConstantInt::get(Type::getInt32Ty(Context), Align), - ConstantInt::get(Type::getInt1Ty(Context), false) - }; - const Type *ArgTypes[3] = { SBP, SBP, IntPtr }; - - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::memmove, - ArgTypes, 3), Ops, Ops+5); - return Ops[0]; -} - -Value *TreeToLLVM::EmitMemSet(Value *DestPtr, Value *SrcVal, Value *Size, - unsigned Align) { - const Type *SBP = Type::getInt8PtrTy(Context); - const Type *IntPtr = TD.getIntPtrType(Context); - Value *Ops[5] = { - Builder.CreateBitCast(DestPtr, SBP), - Builder.CreateIntCast(SrcVal, Type::getInt8Ty(Context), /*isSigned*/true), - Builder.CreateIntCast(Size, IntPtr, /*isSigned*/true), - ConstantInt::get(Type::getInt32Ty(Context), Align), - ConstantInt::get(Type::getInt1Ty(Context), false) - }; - const Type *ArgTypes[2] = { SBP, IntPtr }; - - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::memset, - ArgTypes, 2), Ops, Ops+5); - return Ops[0]; -} - - -// Emits code to do something for a type attribute -void TreeToLLVM::EmitTypeGcroot(Value *V) { - // GC intrinsics can only be used in functions which specify a collector. - Fn->setGC("shadow-stack"); - - Function *gcrootFun = Intrinsic::getDeclaration(TheModule, - Intrinsic::gcroot); - - // The idea is that it's a pointer to type "Value" - // which is opaque* but the routine expects i8** and i8*. - const PointerType *Ty = Type::getInt8PtrTy(Context); - V = Builder.CreateBitCast(V, Ty->getPointerTo()); - - Value *Ops[2] = { - V, - ConstantPointerNull::get(Ty) - }; - - Builder.CreateCall(gcrootFun, Ops, Ops+2); -} - -// Emits annotate intrinsic if the decl has the annotate attribute set. -void TreeToLLVM::EmitAnnotateIntrinsic(Value *V, tree decl) { - - // Handle annotate attribute on global. - tree annotateAttr = lookup_attribute("annotate", DECL_ATTRIBUTES (decl)); - - if (!annotateAttr) - return; - - Function *annotateFun = Intrinsic::getDeclaration(TheModule, - Intrinsic::var_annotation); - - // Get file and line number - Constant *lineNo = - ConstantInt::get(Type::getInt32Ty(Context), DECL_SOURCE_LINE(decl)); - Constant *file = ConvertMetadataStringToGV(DECL_SOURCE_FILE(decl)); - const Type *SBP = Type::getInt8PtrTy(Context); - file = TheFolder->CreateBitCast(file, SBP); - - // There may be multiple annotate attributes. Pass return of lookup_attr - // to successive lookups. - while (annotateAttr) { - - // Each annotate attribute is a tree list. - // Get value of list which is our linked list of args. - tree args = TREE_VALUE(annotateAttr); - - // Each annotate attribute may have multiple args. - // Treat each arg as if it were a separate annotate attribute. - for (tree a = args; a; a = TREE_CHAIN(a)) { - // Each element of the arg list is a tree list, so get value - tree val = TREE_VALUE(a); - - // Assert its a string, and then get that string. - assert(TREE_CODE(val) == STRING_CST && - "Annotate attribute arg should always be a string"); - const Type *SBP = Type::getInt8PtrTy(Context); - Constant *strGV = AddressOf(val); - Value *Ops[4] = { - Builder.CreateBitCast(V, SBP), - Builder.CreateBitCast(strGV, SBP), - file, - lineNo - }; - - Builder.CreateCall(annotateFun, Ops, Ops+4); - } - - // Get next annotate attribute. - annotateAttr = TREE_CHAIN(annotateAttr); - if (annotateAttr) - annotateAttr = lookup_attribute("annotate", annotateAttr); - } -} - -//===----------------------------------------------------------------------===// -// ... Basic Lists and Binding Scopes ... -//===----------------------------------------------------------------------===// - -/// EmitAutomaticVariableDecl - Emit the function-local decl to the current -/// function and set DECL_LOCAL for the decl to the right pointer. -void TreeToLLVM::EmitAutomaticVariableDecl(tree decl) { - // If this is just the rotten husk of a variable that the gimplifier - // eliminated all uses of, but is preserving for debug info, ignore it. - if (TREE_CODE(decl) == VAR_DECL && DECL_VALUE_EXPR(decl)) - return; - - tree type = TREE_TYPE(decl); - const Type *Ty; // Type to allocate - Value *Size = 0; // Amount to alloca (null for 1) - - if (DECL_SIZE(decl) == 0) { // Variable with incomplete type. - if (DECL_INITIAL(decl) == 0) - return; // Error message was already done; now avoid a crash. - else - DieAbjectly("Initializer will decide the size of this array?", decl); - } else if (TREE_CODE(DECL_SIZE_UNIT(decl)) == INTEGER_CST) { - // Variable of fixed size that goes on the stack. - Ty = ConvertType(type); - } else { - // Compute the variable's size in bytes. - Size = EmitRegister(DECL_SIZE_UNIT(decl)); - Ty = Type::getInt8Ty(Context); - } - - unsigned Alignment = 0; // Alignment in bytes. - - // Set the alignment for the local if one of the following condition is met - // 1) DECL_ALIGN is better than the alignment as per ABI specification - // 2) DECL_ALIGN is set by user. - if (DECL_ALIGN(decl)) { - unsigned TargetAlign = getTargetData().getABITypeAlignment(Ty); - if (DECL_USER_ALIGN(decl) || 8 * TargetAlign < (unsigned)DECL_ALIGN(decl)) - Alignment = DECL_ALIGN(decl) / 8; - } - - // Insert an alloca for this variable. - AllocaInst *AI; - if (!Size) { // Fixed size alloca -> entry block. - AI = CreateTemporary(Ty); - } else { - AI = Builder.CreateAlloca(Ty, Size); - } - NameValue(AI, decl); - - AI->setAlignment(Alignment); - - SET_DECL_LOCAL(decl, AI); - - // Handle annotate attributes - if (DECL_ATTRIBUTES(decl)) - EmitAnnotateIntrinsic(AI, decl); - - // Handle gcroot attribute - if (POINTER_TYPE_P(TREE_TYPE (decl)) - && lookup_attribute("gcroot", TYPE_ATTRIBUTES(TREE_TYPE (decl)))) - { - // We should null out local variables so that a stack crawl - // before initialization doesn't get garbage results to follow. - const Type *T = cast(AI->getType())->getElementType(); - EmitTypeGcroot(AI); - Builder.CreateStore(Constant::getNullValue(T), AI); - } - - if (EmitDebugInfo()) { - if (DECL_NAME(decl)) { - TheDebugInfo->EmitDeclare(decl, dwarf::DW_TAG_auto_variable, - AI->getNameStr().c_str(), TREE_TYPE(decl), AI, - Builder); - } else if (TREE_CODE(decl) == RESULT_DECL) { - TheDebugInfo->EmitDeclare(decl, dwarf::DW_TAG_return_variable, - AI->getNameStr().c_str(), TREE_TYPE(decl), AI, - Builder); - } - } -} - - -//===----------------------------------------------------------------------===// -// ... Control Flow ... -//===----------------------------------------------------------------------===// - -/// ConvertTypeInfo - Convert an exception handling type info into a pointer to -/// the associated runtime type info object. -static Constant *ConvertTypeInfo(tree type) { - // TODO: Once pass_ipa_free_lang is made a default pass, remove the call to - // lookup_type_for_runtime below. - if (TYPE_P (type)) - type = lookup_type_for_runtime (type); - STRIP_NOPS(type); - if (TREE_CODE(type) == ADDR_EXPR) - type = TREE_OPERAND(type, 0); - return AddressOf(type); -} - -/// getExceptionPtr - Return the local holding the exception pointer for the -/// given exception handling region, creating it if necessary. -AllocaInst *TreeToLLVM::getExceptionPtr(unsigned RegionNo) { - if (RegionNo >= ExceptionPtrs.size()) - ExceptionPtrs.resize(RegionNo + 1, 0); - - AllocaInst *&ExceptionPtr = ExceptionPtrs[RegionNo]; - - if (!ExceptionPtr) { - ExceptionPtr = CreateTemporary(Type::getInt8PtrTy(Context)); - ExceptionPtr->setName("exc_tmp"); - } - - return ExceptionPtr; -} - -/// getExceptionFilter - Return the local holding the filter value for the -/// given exception handling region, creating it if necessary. -AllocaInst *TreeToLLVM::getExceptionFilter(unsigned RegionNo) { - if (RegionNo >= ExceptionFilters.size()) - ExceptionFilters.resize(RegionNo + 1, 0); - - AllocaInst *&ExceptionFilter = ExceptionFilters[RegionNo]; - - if (!ExceptionFilter) { - ExceptionFilter = CreateTemporary(Type::getInt32Ty(Context)); - ExceptionFilter->setName("filt_tmp"); - } - - return ExceptionFilter; -} - -/// getFailureBlock - Return the basic block containing the failure code for -/// the given exception handling region, creating it if necessary. -BasicBlock *TreeToLLVM::getFailureBlock(unsigned RegionNo) { - if (RegionNo >= FailureBlocks.size()) - FailureBlocks.resize(RegionNo + 1, 0); - - BasicBlock *&FailureBlock = FailureBlocks[RegionNo]; - - if (!FailureBlock) - FailureBlock = BasicBlock::Create(Context, "fail"); - - return FailureBlock; -} - -/// EmitLandingPads - Emit EH landing pads. -void TreeToLLVM::EmitLandingPads() { - // If there are no invokes then there is nothing to do. - if (NormalInvokes.empty()) - return; - - // If a GCC post landing pad is shared by several exception handling regions, - // or if there is a normal edge to it, then create LLVM landing pads for each - // eh region. Calls to eh.exception and eh.selector will then go in the LLVM - // landing pad, which branches to the GCC post landing pad. - for (unsigned LPadNo = 1; LPadNo < NormalInvokes.size(); ++LPadNo) { - // Get the list of invokes for this GCC landing pad. - SmallVector &InvokesForPad = NormalInvokes[LPadNo]; - - if (InvokesForPad.empty()) - continue; - - // All of the invokes unwind to the GCC post landing pad. - BasicBlock *PostPad = InvokesForPad[0]->getUnwindDest(); - - // If the number of invokes is equal to the number of predecessors of the - // post landing pad then it follows that no other GCC landing pad has any - // invokes that unwind to this post landing pad, and also that no normal - // edges land at this post pad. In this case there is no need to create - // an LLVM specific landing pad. - if ((unsigned)std::distance(pred_begin(PostPad), pred_end(PostPad)) == - InvokesForPad.size()) - continue; - - // Create the LLVM landing pad right before the GCC post landing pad. - BasicBlock *LPad = BasicBlock::Create(Context, "lpad", Fn, PostPad); - - // Redirect invoke unwind edges from the GCC post landing pad to LPad. - for (unsigned i = 0, e = InvokesForPad.size(); i < e; ++i) - InvokesForPad[i]->setSuccessor(1, LPad); - - // If there are any PHI nodes in PostPad, we need to update them to merge - // incoming values from LPad instead. - pred_iterator PB = pred_begin(LPad), PE = pred_end(LPad); - for (BasicBlock::iterator II = PostPad->begin(); isa(II);) { - PHINode *PN = cast(II++); - - // Check to see if all of the values coming in via invoke unwind edges are - // the same. If so, we don't need to create a new PHI node. - Value *InVal = PN->getIncomingValueForBlock(*PB); - for (pred_iterator PI = PB; PI != PE; ++PI) { - if (PI != PB && InVal != PN->getIncomingValueForBlock(*PI)) { - InVal = 0; - break; - } - } - - if (InVal == 0) { - // Different unwind edges have different values. Create a new PHI node - // in LPad. - PHINode *NewPN = PHINode::Create(PN->getType(), std::distance(PB, PE), - PN->getName()+".lpad", LPad); - // Add an entry for each unwind edge, using the value from the old PHI. - for (pred_iterator PI = PB; PI != PE; ++PI) - NewPN->addIncoming(PN->getIncomingValueForBlock(*PI), *PI); - - // Now use this new PHI as the common incoming value for LPad in PN. - InVal = NewPN; - } - - // Revector exactly one entry in the PHI node to come from LPad and - // delete the entries that came from the invoke unwind edges. - for (pred_iterator PI = PB; PI != PE; ++PI) - PN->removeIncomingValue(*PI); - PN->addIncoming(InVal, LPad); - } - - // Add a fallthrough from LPad to the original landing pad. - BranchInst::Create(PostPad, LPad); - } - - // Initialize the exception pointer and selector value for each exception - // handling region at the start of the corresponding landing pad. At this - // point each exception handling region has its own landing pad, which is - // only reachable via the unwind edges of the region's invokes. - std::vector Args; - Function *ExcIntr = Intrinsic::getDeclaration(TheModule, - Intrinsic::eh_exception); - Function *SlctrIntr = Intrinsic::getDeclaration(TheModule, - Intrinsic::eh_selector); - for (unsigned LPadNo = 1; LPadNo < NormalInvokes.size(); ++LPadNo) { - // Get the list of invokes for this GCC landing pad. - SmallVector &InvokesForPad = NormalInvokes[LPadNo]; - - if (InvokesForPad.empty()) - continue; - - // All of the invokes unwind to the the landing pad. - BasicBlock *LPad = InvokesForPad[0]->getUnwindDest(); - - // The exception handling region this landing pad is for. - eh_region region = get_eh_region_from_lp_number(LPadNo); - assert(region->index > 0 && "Invalid landing pad region!"); - unsigned RegionNo = region->index; - - // Insert instructions at the start of the landing pad, but after any phis. - Builder.SetInsertPoint(LPad, LPad->getFirstNonPHI()); - - // Fetch the exception pointer. - Value *ExcPtr = Builder.CreateCall(ExcIntr, "exc_ptr"); - - // Store it if made use of elsewhere. - if (RegionNo < ExceptionPtrs.size() && ExceptionPtrs[RegionNo]) - Builder.CreateStore(ExcPtr, ExceptionPtrs[RegionNo]); - - // Get the exception selector. The first argument is the exception pointer. - Args.push_back(ExcPtr); - - // It is followed by the personality function. - tree personality = DECL_FUNCTION_PERSONALITY(FnDecl); - if (!personality) { - assert(function_needs_eh_personality(cfun) == eh_personality_any && - "No exception handling personality!"); - personality = lang_hooks.eh_personality(); - } - Args.push_back(Builder.CreateBitCast(DECL_LLVM(personality), - Type::getInt8PtrTy(Context))); - - Constant *CatchAll = TheModule->getGlobalVariable("llvm.eh.catch.all.value"); - if (!CatchAll) { - // The representation of a catch-all is language specific. - // TODO: Remove this hack. - Constant *Init = 0; - StringRef LanguageName = lang_hooks.name; - if (LanguageName == "GNU Ada") { - StringRef Name = "__gnat_all_others_value"; - Init = TheModule->getGlobalVariable(Name); - if (!Init) - Init = new GlobalVariable(*TheModule, ConvertType(integer_type_node), - /*isConstant*/true, - GlobalValue::ExternalLinkage, - /*Initializer*/NULL, Name); - } else { - // Other languages use a null pointer. - Init = Constant::getNullValue(Type::getInt8PtrTy(Context)); - } - CatchAll = new GlobalVariable(*TheModule, Init->getType(), true, - GlobalVariable::LinkOnceAnyLinkage, - Init, "llvm.eh.catch.all.value"); - cast(CatchAll)->setSection("llvm.metadata"); - AttributeUsedGlobals.insert(CatchAll); - } - - bool AllCaught = false; // Did we saw a catch-all or no-throw? - bool HasCleanup = false; // Did we see a cleanup? - SmallSet AlreadyCaught; // Typeinfos known caught already. - for (; region && !AllCaught; region = region->outer) - switch (region->type) { - case ERT_ALLOWED_EXCEPTIONS: { - // Filter. - - // Push a fake placeholder value for the length. The real length is - // computed below, once we know which typeinfos we are going to use. - unsigned LengthIndex = Args.size(); - Args.push_back(NULL); // Fake length value. - - // Add the type infos. - AllCaught = true; - for (tree type = region->u.allowed.type_list; type; - type = TREE_CHAIN(type)) { - Constant *TypeInfo = ConvertTypeInfo(TREE_VALUE(type)); - // No point in permitting a typeinfo to be thrown if we know it can - // never reach the filter. - if (AlreadyCaught.count(TypeInfo)) - continue; - Args.push_back(TypeInfo); - AllCaught = false; - } - - // The length is one more than the number of typeinfos. - Args[LengthIndex] = ConstantInt::get(Type::getInt32Ty(Context), - Args.size() - LengthIndex); - break; - } - case ERT_CLEANUP: - HasCleanup = true; - break; - case ERT_MUST_NOT_THROW: - // Same as a zero-length filter. - AllCaught = true; - Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), 1)); - break; - case ERT_TRY: - // Catches. - for (eh_catch c = region->u.eh_try.first_catch; c ; c = c->next_catch) - if (!c->type_list) { - // Catch-all - push a null pointer. - AllCaught = true; - Args.push_back(Constant::getNullValue(Type::getInt8PtrTy(Context))); - } else { - // Add the type infos. - for (tree type = c->type_list; type; type = TREE_CHAIN(type)) { - Constant *TypeInfo = ConvertTypeInfo(TREE_VALUE(type)); - // No point in trying to catch a typeinfo that was already caught. - if (!AlreadyCaught.insert(TypeInfo)) - continue; - Args.push_back(TypeInfo); - AllCaught = TypeInfo == CatchAll; - if (AllCaught) - break; - } - } - break; - } - - if (HasCleanup) { - if (Args.size() == 2) - // Insert a sentinel indicating that this is a cleanup-only selector. - Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), 0)); - else if (!AllCaught) - // Some exceptions from this region may not be caught by any handler. - // Since invokes are required to branch to the unwind label no matter - // what exception is being unwound, append a catch-all. I have a plan - // that will make all such horrible hacks unnecessary, but unfortunately - // this comment is too short to explain it. - Args.push_back(CatchAll); - } - - // Emit the selector call. - Value *Filter = Builder.CreateCall(SlctrIntr, Args.begin(), Args.end(), - "filter"); - - // Store it if made use of elsewhere. - if (RegionNo < ExceptionFilters.size() && ExceptionFilters[RegionNo]) - Builder.CreateStore(Filter, ExceptionFilters[RegionNo]); - - Args.clear(); - } - - NormalInvokes.clear(); -} - -/// EmitFailureBlocks - Emit the blocks containing failure code executed when -/// an exception is thrown in a must-not-throw region. -void TreeToLLVM::EmitFailureBlocks() { - for (unsigned RegionNo = 1; RegionNo < FailureBlocks.size(); ++RegionNo) { - BasicBlock *FailureBlock = FailureBlocks[RegionNo]; - - if (!FailureBlock) - continue; - - eh_region region = get_eh_region_from_number(RegionNo); - assert(region->type == ERT_MUST_NOT_THROW && "Unexpected region type!"); - - // Check whether all predecessors are invokes or not. Nothing exotic can - // occur here, only direct branches and unwinding via an invoke. - bool hasBranchPred = false; - bool hasInvokePred = false; - for (pred_iterator I = pred_begin(FailureBlock), E = pred_end(FailureBlock); - I != E && (!hasInvokePred || !hasBranchPred); ++I) { - TerminatorInst *T = (*I)->getTerminator(); - if (isa(T)) { - assert(FailureBlock != T->getSuccessor(0) && "Expected unwind target!"); - hasInvokePred = true; - } else { - assert(isa(T) && "Wrong kind of failure predecessor!"); - hasBranchPred = true; - } - } - assert((hasBranchPred || hasInvokePred) && "No predecessors!"); - - // Determine the landing pad that invokes will unwind to. If there are no - // invokes, then there is no landing pad. - BasicBlock *LandingPad = NULL; - if (hasInvokePred) { - // If all predecessors are invokes, then the failure block can be used as - // the landing pad. Otherwise, create a landing pad. - if (hasBranchPred) - LandingPad = BasicBlock::Create(Context, "pad"); - else - LandingPad = FailureBlock; - } - - if (LandingPad) { - BeginBlock(LandingPad); - - // Generate an empty (i.e. catch-all) filter in the landing pad. - Function *ExcIntr = Intrinsic::getDeclaration(TheModule, - Intrinsic::eh_exception); - Function *SlctrIntr = Intrinsic::getDeclaration(TheModule, - Intrinsic::eh_selector); - Value *Args[3]; - // The exception pointer. - Args[0] = Builder.CreateCall(ExcIntr, "exc_ptr"); - // The personality function. - tree personality = DECL_FUNCTION_PERSONALITY(FnDecl); - assert(personality && "No-throw region but no personality function!"); - Args[1] = Builder.CreateBitCast(DECL_LLVM(personality), - Type::getInt8PtrTy(Context)); - // One more than the filter length. - Args[2] = ConstantInt::get(Type::getInt32Ty(Context), 1); - // Create the selector call. - Builder.CreateCall(SlctrIntr, Args, Args + 3, "filter"); - - if (LandingPad != FailureBlock) { - // Make sure all invokes unwind to the new landing pad. - for (pred_iterator I = pred_begin(FailureBlock), - E = pred_end(FailureBlock); I != E; ) { - TerminatorInst *T = (*I++)->getTerminator(); - if (isa(T)) - T->setSuccessor(1, LandingPad); - } - - // Branch to the failure block at the end of the landing pad. - Builder.CreateBr(FailureBlock); - } - } - - if (LandingPad != FailureBlock) - BeginBlock(FailureBlock); - - // Determine the failure function to call. - Value *FailFunc = DECL_LLVM(region->u.must_not_throw.failure_decl); - - // Make sure it has the right type. - FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), false); - FailFunc = Builder.CreateBitCast(FailFunc, FTy->getPointerTo()); - - // Spank the user for being naughty. - // TODO: Set the correct debug location. - CallInst *FailCall = Builder.CreateCall(FailFunc); - - // This is always fatal. - FailCall->setDoesNotReturn(); - FailCall->setDoesNotThrow(); - Builder.CreateUnreachable(); - } -} - -/// EmitRewindBlock - Emit the block containing code to continue unwinding an -/// exception. -void TreeToLLVM::EmitRewindBlock() { - if (!RewindBB) - return; - - BeginBlock (RewindBB); - - // The exception pointer to continue unwinding. - assert(RewindTmp && "Rewind block but nothing to unwind?"); - Value *ExcPtr = Builder.CreateLoad(RewindTmp); - - // Generate an explicit call to _Unwind_Resume_or_Rethrow. - // FIXME: On ARM this should be a call to __cxa_end_cleanup with no arguments. - std::vector Params(1, Type::getInt8PtrTy(Context)); - FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Params, - false); - Constant *RewindFn = - TheModule->getOrInsertFunction("_Unwind_Resume_or_Rethrow", FTy); - - // Pass it to _Unwind_Resume_or_Rethrow. - CallInst *Rewind = Builder.CreateCall(RewindFn, ExcPtr); - - // This call does not return. - Rewind->setDoesNotReturn(); - Builder.CreateUnreachable(); -} - - -//===----------------------------------------------------------------------===// -// ... Expressions ... -//===----------------------------------------------------------------------===// - -static bool canEmitRegisterVariable(tree exp) { - // Only variables can be marked as 'register'. - if (TREE_CODE(exp) != VAR_DECL || !DECL_REGISTER(exp)) - return false; - - // We can emit inline assembler for access to global register variables. - if (TREE_STATIC(exp) || DECL_EXTERNAL(exp) || TREE_PUBLIC(exp)) - return true; - - // Emit inline asm if this is local variable with assembler name on it. - if (DECL_ASSEMBLER_NAME_SET_P(exp)) - return true; - - // Otherwise - it's normal automatic variable. - return false; -} - -/// EmitLoadOfLValue - When an l-value expression is used in a context that -/// requires an r-value, this method emits the lvalue computation, then loads -/// the result. -Value *TreeToLLVM::EmitLoadOfLValue(tree exp) { - if (canEmitRegisterVariable(exp)) - // If this is a register variable, EmitLV can't handle it (there is no - // l-value of a register variable). Emit an inline asm node that copies the - // value out of the specified register. - return EmitReadOfRegisterVariable(exp); - - LValue LV = EmitLV(exp); - LV.Volatile = TREE_THIS_VOLATILE(exp); - // TODO: Arrange for Volatile to already be set in the LValue. - const Type *Ty = ConvertType(TREE_TYPE(exp)); - unsigned Alignment = LV.getAlignment(); - - if (!LV.isBitfield()) { - // Scalar value: emit a load. - return LoadRegisterFromMemory(LV, TREE_TYPE(exp), Builder); - } else { - // This is a bitfield reference. - if (!LV.BitSize) - return Constant::getNullValue(Ty); - - const Type *ValTy = cast(LV.Ptr->getType())->getElementType(); - unsigned ValSizeInBits = ValTy->getPrimitiveSizeInBits(); - - // The number of loads needed to read the entire bitfield. - unsigned Strides = 1 + (LV.BitStart + LV.BitSize - 1) / ValSizeInBits; - - assert(ValTy->isIntegerTy() && "Invalid bitfield lvalue!"); - assert(ValSizeInBits > LV.BitStart && "Bad bitfield lvalue!"); - assert(ValSizeInBits >= LV.BitSize && "Bad bitfield lvalue!"); - assert(2*ValSizeInBits > LV.BitSize+LV.BitStart && "Bad bitfield lvalue!"); - - Value *Result = NULL; - - for (unsigned I = 0; I < Strides; I++) { - unsigned Index = BYTES_BIG_ENDIAN ? I : Strides - I - 1; // MSB first - unsigned ThisFirstBit = Index * ValSizeInBits; - unsigned ThisLastBitPlusOne = ThisFirstBit + ValSizeInBits; - if (ThisFirstBit < LV.BitStart) - ThisFirstBit = LV.BitStart; - if (ThisLastBitPlusOne > LV.BitStart+LV.BitSize) - ThisLastBitPlusOne = LV.BitStart+LV.BitSize; - - Value *Ptr = Index ? - Builder.CreateGEP(LV.Ptr, - ConstantInt::get(Type::getInt32Ty(Context), Index)) : - LV.Ptr; - LoadInst *LI = Builder.CreateLoad(Ptr, LV.Volatile); - LI->setAlignment(Alignment); - Value *Val = LI; - - unsigned BitsInVal = ThisLastBitPlusOne - ThisFirstBit; - unsigned FirstBitInVal = ThisFirstBit % ValSizeInBits; - - if (BYTES_BIG_ENDIAN) - FirstBitInVal = ValSizeInBits-FirstBitInVal-BitsInVal; - - // Mask the bits out by shifting left first, then shifting right. The - // LLVM optimizer will turn this into an AND if this is an unsigned - // expression. - - if (FirstBitInVal+BitsInVal != ValSizeInBits) { - Value *ShAmt = ConstantInt::get(ValTy, ValSizeInBits - - (FirstBitInVal+BitsInVal)); - Val = Builder.CreateShl(Val, ShAmt); - } - - // Shift right required? - if (ValSizeInBits != BitsInVal) { - bool AddSignBits = !TYPE_UNSIGNED(TREE_TYPE(exp)) && !Result; - Value *ShAmt = ConstantInt::get(ValTy, ValSizeInBits-BitsInVal); - Val = AddSignBits ? - Builder.CreateAShr(Val, ShAmt) : Builder.CreateLShr(Val, ShAmt); - } - - if (Result) { - Value *ShAmt = ConstantInt::get(ValTy, BitsInVal); - Result = Builder.CreateShl(Result, ShAmt); - Result = Builder.CreateOr(Result, Val); - } else { - Result = Val; - } - } - - return Builder.CreateIntCast(Result, GetRegType(TREE_TYPE(exp)), - /*isSigned*/!TYPE_UNSIGNED(TREE_TYPE(exp))); - } -} - -Value *TreeToLLVM::EmitADDR_EXPR(tree exp) { - LValue LV = EmitLV(TREE_OPERAND(exp, 0)); - assert((!LV.isBitfield() || LV.BitStart == 0) && - "It is illegal to take the address of a bitfield!"); - // Perform a cast here if necessary. For example, GCC sometimes forms an - // ADDR_EXPR where the operand is an array, and the ADDR_EXPR type is a - // pointer to the first element. - return Builder.CreateBitCast(LV.Ptr, ConvertType(TREE_TYPE(exp))); -} - -Value *TreeToLLVM::EmitOBJ_TYPE_REF(tree exp) { - return Builder.CreateBitCast(EmitRegister(OBJ_TYPE_REF_EXPR(exp)), - ConvertType(TREE_TYPE(exp))); -} - -/// EmitCONSTRUCTOR - emit the constructor into the location specified by -/// DestLoc. -Value *TreeToLLVM::EmitCONSTRUCTOR(tree exp, const MemRef *DestLoc) { - tree type = TREE_TYPE(exp); - const Type *Ty = ConvertType(type); - if (const VectorType *VTy = dyn_cast(Ty)) { - assert(DestLoc == 0 && "Dest location for vector value?"); - std::vector BuildVecOps; - BuildVecOps.reserve(VTy->getNumElements()); - - // Insert all of the elements here. - unsigned HOST_WIDE_INT idx; - tree value; - FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value) { - Value *Elt = EmitMemory(value); - - if (const VectorType *EltTy = dyn_cast(Elt->getType())) { - // GCC allows vectors to be built up from vectors. Extract all of the - // vector elements and add them to the list of build vector operands. - for (unsigned i = 0, e = EltTy->getNumElements(); i != e; ++i) { - Value *Index = ConstantInt::get(llvm::Type::getInt32Ty(Context), i); - BuildVecOps.push_back(Builder.CreateExtractElement(Elt, Index)); - } - } else { - assert(Elt->getType() == VTy->getElementType() && - "Unexpected type for vector constructor!"); - BuildVecOps.push_back(Elt); - } - } - - // Insert zero for any unspecified values. - while (BuildVecOps.size() < VTy->getNumElements()) - BuildVecOps.push_back(Constant::getNullValue(VTy->getElementType())); - assert(BuildVecOps.size() == VTy->getNumElements() && - "Vector constructor specified too many values!"); - - return BuildVector(BuildVecOps); - } - - assert(AGGREGATE_TYPE_P(type) && "Constructor for scalar type??"); - - // Start out with the value zero'd out. - EmitAggregateZero(*DestLoc, type); - - VEC(constructor_elt, gc) *elt = CONSTRUCTOR_ELTS(exp); - switch (TREE_CODE(TREE_TYPE(exp))) { - case ARRAY_TYPE: - case RECORD_TYPE: - default: - if (elt && VEC_length(constructor_elt, elt)) - DieAbjectly("We don't handle elements yet!", exp); - return 0; - case QUAL_UNION_TYPE: - case UNION_TYPE: - // Store each element of the constructor into the corresponding field of - // DEST. - if (!elt || VEC_empty(constructor_elt, elt)) return 0; // no elements - assert(VEC_length(constructor_elt, elt) == 1 - && "Union CONSTRUCTOR should have one element!"); - tree tree_purpose = VEC_index(constructor_elt, elt, 0)->index; - tree tree_value = VEC_index(constructor_elt, elt, 0)->value; - if (!tree_purpose) - return 0; // Not actually initialized? - - if (AGGREGATE_TYPE_P(TREE_TYPE(tree_purpose))) { - EmitAggregate(tree_value, *DestLoc); - } else { - // Scalar value. Evaluate to a register, then do the store. - Value *V = EmitRegister(tree_value); - StoreRegisterToMemory(V, *DestLoc, TREE_TYPE(tree_purpose), Builder); - } - break; - } - return 0; -} - -/// llvm_load_scalar_argument - Load value located at LOC. -static Value *llvm_load_scalar_argument(Value *L, - const llvm::Type *LLVMTy, - unsigned RealSize, - LLVMBuilder &Builder) { - if (!RealSize) - return UndefValue::get(LLVMTy); - - // Not clear what this is supposed to do on big endian machines... - assert(!BYTES_BIG_ENDIAN && "Unsupported case - please report"); - assert(LLVMTy->isIntegerTy() && "Expected an integer value!"); - const Type *LoadType = IntegerType::get(Context, RealSize * 8); - L = Builder.CreateBitCast(L, LoadType->getPointerTo()); - Value *Val = Builder.CreateLoad(L); - if (LoadType->getPrimitiveSizeInBits() >= LLVMTy->getPrimitiveSizeInBits()) - Val = Builder.CreateTrunc(Val, LLVMTy); - else - Val = Builder.CreateZExt(Val, LLVMTy); - return Val; -} - -#ifndef LLVM_LOAD_SCALAR_ARGUMENT -#define LLVM_LOAD_SCALAR_ARGUMENT(LOC,TY,SIZE,BUILDER) \ - llvm_load_scalar_argument((LOC),(TY),(SIZE),(BUILDER)) -#endif - -namespace { - /// FunctionCallArgumentConversion - This helper class is driven by the ABI - /// definition for this target to figure out how to pass arguments into the - /// stack/regs for a function call. - struct FunctionCallArgumentConversion : public DefaultABIClient { - SmallVector &CallOperands; - SmallVector LocStack; - const FunctionType *FTy; - const MemRef *DestLoc; - bool useReturnSlot; - LLVMBuilder &Builder; - Value *TheValue; - MemRef RetBuf; - CallingConv::ID &CallingConv; - bool isShadowRet; - bool isAggrRet; - unsigned Offset; - - FunctionCallArgumentConversion(SmallVector &ops, - const FunctionType *FnTy, - const MemRef *destloc, - bool ReturnSlotOpt, - LLVMBuilder &b, - CallingConv::ID &CC) - : CallOperands(ops), FTy(FnTy), DestLoc(destloc), - useReturnSlot(ReturnSlotOpt), Builder(b), CallingConv(CC), - isShadowRet(false), isAggrRet(false), Offset(0) { } - - /// getCallingConv - This provides the desired CallingConv for the function. - CallingConv::ID& getCallingConv(void) { return CallingConv; } - - // Push the address of an argument. - void pushAddress(Value *Loc) { - assert(Loc && "Invalid location!"); - LocStack.push_back(Loc); - } - - // Push the value of an argument. - void pushValue(Value *V) { - assert(LocStack.empty() && "Value only allowed at top level!"); - LocStack.push_back(NULL); - TheValue = V; - } - - // Get the address of the current location. - Value *getAddress(void) { - assert(!LocStack.empty()); - Value *&Loc = LocStack.back(); - if (!Loc) { - // A value. Store to a temporary, and return the temporary's address. - // Any future access to this argument will reuse the same address. - Loc = TheTreeToLLVM->CreateTemporary(TheValue->getType()); - Builder.CreateStore(TheValue, Loc); - } - return Loc; - } - - // Get the value of the current location (of type Ty). - Value *getValue(const Type *Ty) { - assert(!LocStack.empty()); - Value *Loc = LocStack.back(); - if (Loc) { - // An address. Convert to the right type and load the value out. - Loc = Builder.CreateBitCast(Loc, Ty->getPointerTo()); - return Builder.CreateLoad(Loc, "val"); - } else { - // A value - just return it. - assert(TheValue->getType() == Ty && "Value not of expected type!"); - return TheValue; - } - } - - void clear() { - assert(LocStack.size() == 1 && "Imbalance!"); - LocStack.clear(); - } - - bool isShadowReturn() const { return isShadowRet; } - bool isAggrReturn() { return isAggrRet; } - - // EmitShadowResult - If the return result was redirected to a buffer, - // emit it now. - Value *EmitShadowResult(tree type, const MemRef *DestLoc) { - if (!RetBuf.Ptr) - return 0; - - if (DestLoc) { - // Copy out the aggregate return value now. - assert(ConvertType(type) == - cast(RetBuf.Ptr->getType())->getElementType() && - "Inconsistent result types!"); - TheTreeToLLVM->EmitAggregateCopy(*DestLoc, RetBuf, type); - return 0; - } else { - // Read out the scalar return value now. - return Builder.CreateLoad(RetBuf.Ptr, "result"); - } - } - - /// HandleScalarResult - This callback is invoked if the function returns a - /// simple scalar result value. - void HandleScalarResult(const Type * /*RetTy*/) { - // There is nothing to do here if we return a scalar or void. - assert(DestLoc == 0 && - "Call returns a scalar but caller expects aggregate!"); - } - - /// HandleAggregateResultAsScalar - This callback is invoked if the function - /// returns an aggregate value by bit converting it to the specified scalar - /// type and returning that. - void HandleAggregateResultAsScalar(const Type * /*ScalarTy*/, - unsigned Offset = 0) { - this->Offset = Offset; - } - - /// HandleAggregateResultAsAggregate - This callback is invoked if the - /// function returns an aggregate value using multiple return values. - void HandleAggregateResultAsAggregate(const Type * /*AggrTy*/) { - // There is nothing to do here. - isAggrRet = true; - } - - /// HandleAggregateShadowResult - This callback is invoked if the function - /// returns an aggregate value by using a "shadow" first parameter. If - /// RetPtr is set to true, the pointer argument itself is returned from the - /// function. - void HandleAggregateShadowResult(const PointerType *PtrArgTy, bool /*RetPtr*/) { - // We need to pass memory to write the return value into. - // FIXME: alignment and volatility are being ignored! - assert(!DestLoc || PtrArgTy == DestLoc->Ptr->getType()); - - if (DestLoc == 0) { - // The result is unused, but still needs to be stored somewhere. - Value *Buf = TheTreeToLLVM->CreateTemporary(PtrArgTy->getElementType()); - CallOperands.push_back(Buf); - } else if (useReturnSlot) { - // Letting the call write directly to the final destination is safe and - // may be required. Do not use a buffer. - CallOperands.push_back(DestLoc->Ptr); - } else { - // Letting the call write directly to the final destination may not be - // safe (eg: if DestLoc aliases a parameter) and is not required - pass - // a buffer and copy it to DestLoc after the call. - RetBuf = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType()); - CallOperands.push_back(RetBuf.Ptr); - } - - // Note the use of a shadow argument. - isShadowRet = true; - } - - void HandlePad(const llvm::Type *LLVMTy) { - CallOperands.push_back(UndefValue::get(LLVMTy)); - } - - /// HandleScalarShadowResult - This callback is invoked if the function - /// returns a scalar value by using a "shadow" first parameter, which is a - /// pointer to the scalar, of type PtrArgTy. If RetPtr is set to true, - /// the pointer argument itself is returned from the function. - void HandleScalarShadowResult(const PointerType *PtrArgTy, - bool /*RetPtr*/) { - assert(DestLoc == 0 && - "Call returns a scalar but caller expects aggregate!"); - // Create a buffer to hold the result. The result will be loaded out of - // it after the call. - RetBuf = TheTreeToLLVM->CreateTempLoc(PtrArgTy->getElementType()); - CallOperands.push_back(RetBuf.Ptr); - - // Note the use of a shadow argument. - isShadowRet = true; - } - - /// HandleScalarArgument - This is the primary callback that specifies an - /// LLVM argument to pass. It is only used for first class types. - void HandleScalarArgument(const llvm::Type *LLVMTy, tree type, - unsigned RealSize = 0) { - Value *Loc = NULL; - if (RealSize) { - Value *L = getAddress(); - Loc = LLVM_LOAD_SCALAR_ARGUMENT(L,LLVMTy,RealSize,Builder); - } else - Loc = getValue(LLVMTy); - - // Perform any implicit type conversions. - if (CallOperands.size() < FTy->getNumParams()) { - const Type *CalledTy= FTy->getParamType(CallOperands.size()); - if (Loc->getType() != CalledTy) { - assert(type && "Inconsistent parameter types?"); - bool isSigned = !TYPE_UNSIGNED(type); - Loc = TheTreeToLLVM->CastToAnyType(Loc, isSigned, CalledTy, false); - } - } - - CallOperands.push_back(Loc); - } - - /// HandleByInvisibleReferenceArgument - This callback is invoked if a - /// pointer (of type PtrTy) to the argument is passed rather than the - /// argument itself. - void HandleByInvisibleReferenceArgument(const llvm::Type *PtrTy, - tree /*type*/) { - Value *Loc = getAddress(); - Loc = Builder.CreateBitCast(Loc, PtrTy); - CallOperands.push_back(Loc); - } - - /// HandleByValArgument - This callback is invoked if the aggregate function - /// argument is passed by value. It is lowered to a parameter passed by - /// reference with an additional parameter attribute "ByVal". - void HandleByValArgument(const llvm::Type *LLVMTy, tree /*type*/) { - Value *Loc = getAddress(); - assert(LLVMTy->getPointerTo() == Loc->getType()); - (void)LLVMTy; // Otherwise unused if asserts off - avoid compiler warning. - CallOperands.push_back(Loc); - } - - /// HandleFCAArgument - This callback is invoked if the aggregate function - /// argument is passed as a first class aggregate. - void HandleFCAArgument(const llvm::Type *LLVMTy, tree /*type*/) { - Value *Loc = getAddress(); - assert(LLVMTy->getPointerTo() == Loc->getType()); - (void)LLVMTy; // Otherwise unused if asserts off - avoid compiler warning. - CallOperands.push_back(Builder.CreateLoad(Loc)); - } - - /// EnterField - Called when we're about the enter the field of a struct - /// or union. FieldNo is the number of the element we are entering in the - /// LLVM Struct, StructTy is the LLVM type of the struct we are entering. - void EnterField(unsigned FieldNo, const llvm::Type *StructTy) { - Value *Loc = getAddress(); - Loc = Builder.CreateBitCast(Loc, StructTy->getPointerTo()); - pushAddress(Builder.CreateStructGEP(Loc, FieldNo, "elt")); - } - void ExitField() { - assert(!LocStack.empty()); - LocStack.pop_back(); - } - }; -} - -/// EmitCallOf - Emit a call to the specified callee with the operands specified -/// in the GIMPLE_CALL 'stmt'. If the result of the call is a scalar, return the -/// result, otherwise store it in DestLoc. -Value *TreeToLLVM::EmitCallOf(Value *Callee, gimple stmt, const MemRef *DestLoc, - const AttrListPtr &InPAL) { - BasicBlock *LandingPad = 0; // Non-zero indicates an invoke. - int LPadNo = 0; - - AttrListPtr PAL = InPAL; - if (PAL.isEmpty() && isa(Callee)) - PAL = cast(Callee)->getAttributes(); - - // Work out whether to use an invoke or an ordinary call. - if (!stmt_could_throw_p(stmt)) - // This call does not throw - mark it 'nounwind'. - PAL = PAL.addAttr(~0, Attribute::NoUnwind); - - if (!PAL.paramHasAttr(~0, Attribute::NoUnwind)) { - // This call may throw. Determine if we need to generate - // an invoke rather than a simple call. - LPadNo = lookup_stmt_eh_lp(stmt); - - if (LPadNo > 0) { - // The call is in an exception handling region with a landing pad. - // Generate an invoke, with the GCC landing pad as the unwind destination. - // The destination may change to an LLVM only landing pad, which precedes - // the GCC one, after phi nodes have been populated (doing things this way - // simplifies the generation of phi nodes). - eh_landing_pad lp = get_eh_landing_pad_from_number(LPadNo); - assert(lp && "Post landing pad not found!"); - LandingPad = getLabelDeclBlock(lp->post_landing_pad); - } else if (LPadNo < 0) { - eh_region region = get_eh_region_from_lp_number(LPadNo); - // The call is in a must-not-throw region. Generate an invoke that causes - // the region's failure code to be run if an exception is thrown. - assert(region->type == ERT_MUST_NOT_THROW && "Unexpected region type!"); - - // Unwind to the block containing the failure code. - LandingPad = getFailureBlock(region->index); - } - } - - tree fndecl = gimple_call_fndecl(stmt); - tree fntype = fndecl ? - TREE_TYPE(fndecl) : TREE_TYPE (TREE_TYPE(gimple_call_fn(stmt))); - - // Determine the calling convention. - CallingConv::ID CallingConvention = CallingConv::C; -#ifdef TARGET_ADJUST_LLVM_CC - TARGET_ADJUST_LLVM_CC(CallingConvention, fntype); -#endif - - SmallVector CallOperands; - const PointerType *PFTy = cast(Callee->getType()); - const FunctionType *FTy = cast(PFTy->getElementType()); - FunctionCallArgumentConversion Client(CallOperands, FTy, DestLoc, - gimple_call_return_slot_opt_p(stmt), - Builder, CallingConvention); - DefaultABI ABIConverter(Client); - - // Handle the result, including struct returns. - ABIConverter.HandleReturnType(gimple_call_return_type(stmt), - fndecl ? fndecl : fntype, - fndecl ? DECL_BUILT_IN(fndecl) : false); - - // Pass the static chain, if any, as the first parameter. - if (gimple_call_chain(stmt)) - CallOperands.push_back(EmitMemory(gimple_call_chain(stmt))); - - // Loop over the arguments, expanding them and adding them to the op list. - std::vector ScalarArgs; - for (unsigned i = 0, e = gimple_call_num_args(stmt); i != e; ++i) { - tree arg = gimple_call_arg(stmt, i); - tree type = TREE_TYPE(arg); - const Type *ArgTy = ConvertType(type); - - // Push the argument. - if (ArgTy->isSingleValueType()) { - // A scalar - push the value. - Client.pushValue(EmitMemory(arg)); - } else if (LLVM_SHOULD_PASS_AGGREGATE_AS_FCA(type, ArgTy)) { - if (AGGREGATE_TYPE_P(type)) { - // Pass the aggregate as a first class value. - LValue ArgVal = EmitLV(arg); - Client.pushValue(Builder.CreateLoad(ArgVal.Ptr)); - } else { - // Already first class (eg: a complex number) - push the value. - Client.pushValue(EmitMemory(arg)); - } - } else { - if (AGGREGATE_TYPE_P(type)) { - // An aggregate - push the address. - LValue ArgVal = EmitLV(arg); - assert(!ArgVal.isBitfield() && "Bitfields are first-class types!"); - Client.pushAddress(ArgVal.Ptr); - } else { - // A first class value (eg: a complex number). Push the address of a - // temporary copy. - MemRef Copy = CreateTempLoc(ArgTy); - StoreRegisterToMemory(EmitRegister(arg), Copy, type, Builder); - Client.pushAddress(Copy.Ptr); - } - } - - Attributes Attrs = Attribute::None; - - unsigned OldSize = CallOperands.size(); - - ABIConverter.HandleArgument(type, ScalarArgs, &Attrs); - - if (Attrs != Attribute::None) { - // If the argument is split into multiple scalars, assign the - // attributes to all scalars of the aggregate. - for (unsigned i = OldSize + 1; i <= CallOperands.size(); ++i) { - PAL = PAL.addAttr(i, Attrs); - } - } - - Client.clear(); - } - - // Compile stuff like: - // %tmp = call float (...)* bitcast (float ()* @foo to float (...)*)( ) - // to: - // %tmp = call float @foo( ) - // This commonly occurs due to C "implicit ..." semantics. - if (ConstantExpr *CE = dyn_cast(Callee)) { - if (CallOperands.empty() && CE->getOpcode() == Instruction::BitCast) { - Constant *RealCallee = CE->getOperand(0); - assert(RealCallee->getType()->isPointerTy() && - "Bitcast to ptr not from ptr?"); - const PointerType *RealPT = cast(RealCallee->getType()); - if (const FunctionType *RealFT = - dyn_cast(RealPT->getElementType())) { - const PointerType *ActualPT = cast(Callee->getType()); - const FunctionType *ActualFT = - cast(ActualPT->getElementType()); - if (RealFT->getReturnType() == ActualFT->getReturnType() && - RealFT->getNumParams() == 0) - Callee = RealCallee; - } - } - } - - // Unlike LLVM, GCC does not require that call statements provide a value for - // every function argument (it passes rubbish for arguments with no value). - // To get the same effect we pass 'undef' for any unspecified arguments. - PFTy = cast(Callee->getType()); - FTy = cast(PFTy->getElementType()); - if (CallOperands.size() < FTy->getNumParams()) - for (unsigned i = CallOperands.size(), e = FTy->getNumParams(); i != e; ++i) - CallOperands.push_back(UndefValue::get(FTy->getParamType(i))); - - Value *Call; - if (!LandingPad) { - Call = Builder.CreateCall(Callee, CallOperands.begin(), CallOperands.end()); - cast(Call)->setCallingConv(CallingConvention); - cast(Call)->setAttributes(PAL); - } else { - BasicBlock *NextBlock = BasicBlock::Create(Context); - Call = Builder.CreateInvoke(Callee, NextBlock, LandingPad, - CallOperands.begin(), CallOperands.end()); - cast(Call)->setCallingConv(CallingConvention); - cast(Call)->setAttributes(PAL); - - if (LPadNo > 0) { - // The invoke's destination may change to an LLVM only landing pad, which - // precedes the GCC one, after phi nodes have been populated (doing things - // this way simplifies the generation of phi nodes). Record the invoke as - // well as the GCC exception handling region. - if ((unsigned)LPadNo >= NormalInvokes.size()) - NormalInvokes.resize(LPadNo + 1); - NormalInvokes[LPadNo].push_back(cast(Call)); - } - - BeginBlock(NextBlock); - } - - if (Client.isShadowReturn()) - return Client.EmitShadowResult(gimple_call_return_type(stmt), DestLoc); - - if (Call->getType()->isVoidTy()) - return 0; - - if (Client.isAggrReturn()) { - MemRef Target; - if (DestLoc) - Target = *DestLoc; - else - // Destination is a first class value (eg: a complex number). Extract to - // a temporary then load the value out later. - Target = CreateTempLoc(ConvertType(gimple_call_return_type(stmt))); - - if (TD.getTypeAllocSize(Call->getType()) <= - TD.getTypeAllocSize(cast(Target.Ptr->getType()) - ->getElementType())) { - Value *Dest = Builder.CreateBitCast(Target.Ptr, - Call->getType()->getPointerTo()); - LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call, Dest, Target.Volatile, - Builder); - } else { - // The call will return an aggregate value in registers, but - // those registers are bigger than Target. Allocate a - // temporary to match the registers, store the registers there, - // cast the temporary into the correct (smaller) type, and using - // the correct type, copy the value into Target. Assume the - // optimizer will delete the temporary and clean this up. - AllocaInst *biggerTmp = CreateTemporary(Call->getType()); - LLVM_EXTRACT_MULTIPLE_RETURN_VALUE(Call,biggerTmp,/*Volatile=*/false, - Builder); - EmitAggregateCopy(Target, - MemRef(Builder.CreateBitCast(biggerTmp,Call->getType()-> - getPointerTo()), - Target.getAlignment(), Target.Volatile), - gimple_call_return_type(stmt)); - } - - return DestLoc ? 0 : Builder.CreateLoad(Target.Ptr); - } - - if (!DestLoc) { - const Type *RetTy = ConvertType(gimple_call_return_type(stmt)); - if (Call->getType() == RetTy) - return Call; // Normal scalar return. - - // May be something as simple as a float being returned as an integer, or - // something trickier like a complex int type { i32, i32 } being returned - // as an i64. - if (Call->getType()->canLosslesslyBitCastTo(RetTy)) - return Builder.CreateBitCast(Call, RetTy); // Simple case. - // Probably a scalar to complex conversion. - assert(TD.getTypeAllocSize(Call->getType()) == TD.getTypeAllocSize(RetTy) && - "Size mismatch in scalar to scalar conversion!"); - Value *Tmp = CreateTemporary(Call->getType()); - Builder.CreateStore(Call, Tmp); - return Builder.CreateLoad(Builder.CreateBitCast(Tmp,RetTy->getPointerTo())); - } - - // If the caller expects an aggregate, we have a situation where the ABI for - // the current target specifies that the aggregate be returned in scalar - // registers even though it is an aggregate. We must bitconvert the scalar - // to the destination aggregate type. We do this by casting the DestLoc - // pointer and storing into it. The store does not necessarily start at the - // beginning of the aggregate (x86-64). - Value *Ptr = DestLoc->Ptr; - // AggTy - The type of the aggregate being stored to. - const Type *AggTy = cast(Ptr->getType())->getElementType(); - // MaxStoreSize - The maximum number of bytes we can store without overflowing - // the aggregate. - int64_t MaxStoreSize = TD.getTypeAllocSize(AggTy); - if (Client.Offset) { - Ptr = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context)); - Ptr = Builder.CreateGEP(Ptr, - ConstantInt::get(TD.getIntPtrType(Context), Client.Offset)); - MaxStoreSize -= Client.Offset; - } - assert(MaxStoreSize > 0 && "Storing off end of aggregate?"); - Value *Val = Call; - // Check whether storing the scalar directly would overflow the aggregate. - if (TD.getTypeStoreSize(Call->getType()) > (uint64_t)MaxStoreSize) { - // Chop down the size of the scalar to the maximum number of bytes that can - // be stored without overflowing the destination. - // TODO: Check whether this works correctly on big-endian machines. - // Store the scalar to a temporary. - Value *Tmp = CreateTemporary(Call->getType()); - Builder.CreateStore(Call, Tmp); - // Load the desired number of bytes back out again as an integer of the - // appropriate size. - const Type *SmallTy = IntegerType::get(Context, MaxStoreSize*8); - Tmp = Builder.CreateBitCast(Tmp, PointerType::getUnqual(SmallTy)); - Val = Builder.CreateLoad(Tmp); - // Store the integer rather than the call result to the aggregate. - } - Ptr = Builder.CreateBitCast(Ptr, PointerType::getUnqual(Val->getType())); - StoreInst *St = Builder.CreateStore(Val, Ptr, DestLoc->Volatile); - St->setAlignment(DestLoc->getAlignment()); - return 0; -} - -/// EmitSimpleCall - Emit a call to the function with the given name and return -/// type, passing the provided arguments (which should all be gimple registers -/// or local constants of register type). No marshalling is done: the arguments -/// are directly passed through. -CallInst *TreeToLLVM::EmitSimpleCall(StringRef CalleeName, tree ret_type, - /* arguments */ ...) { - va_list ops; - va_start(ops, ret_type); - - // Build the list of arguments. - std::vector Args; -#ifdef TARGET_ADJUST_LLVM_CC - // Build the list of GCC argument types. - tree arg_types; - tree *chainp = &arg_types; -#endif - while (tree arg = va_arg(ops, tree)) { - Args.push_back(EmitRegister(arg)); -#ifdef TARGET_ADJUST_LLVM_CC - *chainp = build_tree_list(NULL, TREE_TYPE(arg)); - chainp = &TREE_CHAIN(*chainp); -#endif - } -#ifdef TARGET_ADJUST_LLVM_CC - // Indicate that this function is not varargs. - *chainp = void_list_node; -#endif - va_end(ops); - - const Type *RetTy = TREE_CODE(ret_type) == VOID_TYPE ? - Type::getVoidTy(Context) : GetRegType(ret_type); - - // The LLVM argument types. - std::vector ArgTys; - ArgTys.reserve(Args.size()); - for (unsigned i = 0, e = Args.size(); i != e; ++i) - ArgTys.push_back(Args[i]->getType()); - - // Determine the calling convention. - CallingConv::ID CC = CallingConv::C; -#ifdef TARGET_ADJUST_LLVM_CC - // Query the target for the calling convention to use. - tree fntype = build_function_type(ret_type, arg_types); - TARGET_ADJUST_LLVM_CC(CC, fntype); -#endif - - // Get the function declaration for the callee. - const FunctionType *FTy = FunctionType::get(RetTy, ArgTys, /*isVarArg*/false); - Constant *Func = TheModule->getOrInsertFunction(CalleeName, FTy); - - // If the function already existed with the wrong prototype then don't try to - // muck with its calling convention. Otherwise, set the calling convention. - if (Function *F = dyn_cast(Func)) - F->setCallingConv(CC); - - // Finally, call the function. - CallInst *CI = Builder.CreateCall(Func, Args.begin(), Args.end()); - CI->setCallingConv(CC); - return CI; -} - - -//===----------------------------------------------------------------------===// -// ... Inline Assembly and Register Variables ... -//===----------------------------------------------------------------------===// - -// LLVM_GET_REG_NAME - Default to use GCC's register names. Targets may -// override this to use different names for some registers. The REG_NAME is -// the name before it was decoded; it may be null in some contexts. -#ifndef LLVM_GET_REG_NAME -#define LLVM_GET_REG_NAME(REG_NAME, REG_NUM) reg_names[REG_NUM] -#endif - -// LLVM_CANONICAL_ADDRESS_CONSTRAINTS - GCC defines the "p" constraint to -// allow a valid memory address, but targets differ widely on what is allowed -// as an address. This macro is a string containing the canonical constraint -// characters that are conservatively valid addresses. Default to allowing an -// address in a register, since that works for many targets. -#ifndef LLVM_CANONICAL_ADDRESS_CONSTRAINTS -#define LLVM_CANONICAL_ADDRESS_CONSTRAINTS "r" -#endif - -/// Reads from register variables are handled by emitting an inline asm node -/// that copies the value out of the specified register. -Value *TreeToLLVM::EmitReadOfRegisterVariable(tree decl) { - const Type *MemTy = ConvertType(TREE_TYPE(decl)); - const Type *RegTy = GetRegType(TREE_TYPE(decl)); - - // If there was an error, return something bogus. - if (ValidateRegisterVariable(decl)) - return UndefValue::get(RegTy); - - // Turn this into a 'tmp = call Ty asm "", "={reg}"()'. - FunctionType *FTy = FunctionType::get(MemTy, std::vector(), - false); - - const char *Name = extractRegisterName(decl); - Name = LLVM_GET_REG_NAME(Name, decode_reg_name(Name)); - - InlineAsm *IA = InlineAsm::get(FTy, "", "={"+std::string(Name)+"}", true); - CallInst *Call = Builder.CreateCall(IA); - Call->setDoesNotThrow(); - - // Convert the call result to in-register type. - return Mem2Reg(Call, TREE_TYPE(decl), Builder); -} - -/// Stores to register variables are handled by emitting an inline asm node -/// that copies the value into the specified register. -void TreeToLLVM::EmitModifyOfRegisterVariable(tree decl, Value *RHS) { - // If there was an error, bail out. - if (ValidateRegisterVariable(decl)) - return; - - // Convert to in-memory type. - RHS = Reg2Mem(RHS, TREE_TYPE(decl), Builder); - - // Turn this into a 'call void asm sideeffect "", "{reg}"(Ty %RHS)'. - std::vector ArgTys; - ArgTys.push_back(RHS->getType()); - FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), ArgTys, - false); - - const char *Name = extractRegisterName(decl); - Name = LLVM_GET_REG_NAME(Name, decode_reg_name(Name)); - - InlineAsm *IA = InlineAsm::get(FTy, "", "{"+std::string(Name)+"}", true); - CallInst *Call = Builder.CreateCall(IA, RHS); - Call->setDoesNotThrow(); -} - -/// ConvertInlineAsmStr - Convert the specified inline asm string to an LLVM -/// InlineAsm string. The GNU style inline asm template string has the -/// following format: -/// %N (for N a digit) means print operand N in usual manner. -/// %= means a unique number for the inline asm. -/// %lN means require operand N to be a CODE_LABEL or LABEL_REF -/// and print the label name with no punctuation. -/// %cN means require operand N to be a constant -/// and print the constant expression with no punctuation. -/// %aN means expect operand N to be a memory address -/// (not a memory reference!) and print a reference to that address. -/// %nN means expect operand N to be a constant and print a constant -/// expression for minus the value of the operand, with no other -/// punctuation. -/// Other %xN expressions are turned into LLVM ${N:x} operands. -/// -static std::string ConvertInlineAsmStr(gimple stmt, unsigned NumOperands) { - const char *AsmStr = gimple_asm_string(stmt); - - // gimple_asm_input_p - This flag is set if this is a non-extended ASM, - // which means that the asm string should not be interpreted, other than - // to escape $'s. - if (gimple_asm_input_p(stmt)) { - const char *InStr = AsmStr; - std::string Result; - while (1) { - switch (*InStr++) { - case 0: return Result; // End of string. - default: Result += InStr[-1]; break; // Normal character. - case '$': Result += "$$"; break; // Escape '$' characters. - } - } - } - - std::string Result; - while (1) { - switch (*AsmStr++) { - case 0: return Result; // End of string. - default: Result += AsmStr[-1]; break; // Normal character. - case '$': Result += "$$"; break; // Escape '$' characters. -#ifdef ASSEMBLER_DIALECT - // Note that we can't escape to ${, because that is the syntax for vars. - case '{': Result += "$("; break; // Escape '{' character. - case '}': Result += "$)"; break; // Escape '}' character. - case '|': Result += "$|"; break; // Escape '|' character. -#endif - case '%': // GCC escape character. - char EscapedChar = *AsmStr++; - if (EscapedChar == '%') { // Escaped '%' character - Result += '%'; - } else if (EscapedChar == '=') { // Unique ID for the asm instance. - Result += "${:uid}"; - } -#ifdef LLVM_ASM_EXTENSIONS - LLVM_ASM_EXTENSIONS(EscapedChar, AsmStr, Result) -#endif - else if (ISALPHA(EscapedChar)) { - // % followed by a letter and some digits. This outputs an operand in a - // special way depending on the letter. We turn this into LLVM ${N:o} - // syntax. - char *EndPtr; - unsigned long OpNum = strtoul(AsmStr, &EndPtr, 10); - - if (AsmStr == EndPtr) { - error_at(gimple_location(stmt), - "operand number missing after %%-letter"); - return Result; - } else if (OpNum >= NumOperands) { - error_at(gimple_location(stmt), "operand number out of range"); - return Result; - } - Result += "${" + utostr(OpNum) + ":" + EscapedChar + "}"; - AsmStr = EndPtr; - } else if (ISDIGIT(EscapedChar)) { - char *EndPtr; - unsigned long OpNum = strtoul(AsmStr-1, &EndPtr, 10); - AsmStr = EndPtr; - Result += "$" + utostr(OpNum); -#ifdef PRINT_OPERAND_PUNCT_VALID_P - } else if (PRINT_OPERAND_PUNCT_VALID_P((unsigned char)EscapedChar)) { - Result += "${:"; - Result += EscapedChar; - Result += "}"; -#endif - } else { - output_operand_lossage("invalid %%-code"); - } - break; - } - } -} - -/// isOperandMentioned - Return true if the given operand is explicitly -/// mentioned in the asm string. For example if passed operand 1 then -/// this routine checks that the asm string does not contain "%1". -static bool isOperandMentioned(gimple stmt, unsigned OpNum) { - // If this is a non-extended ASM then the contents of the asm string are not - // to be interpreted. - if (gimple_asm_input_p(stmt)) - return false; - // Search for a non-escaped '%' character followed by OpNum. - for (const char *AsmStr = gimple_asm_string(stmt); *AsmStr; ++AsmStr) { - if (*AsmStr != '%') - // Not a '%', move on to next character. - continue; - char Next = AsmStr[1]; - // If this is "%%" then the '%' is escaped - skip both '%' characters. - if (Next == '%') { - ++AsmStr; - continue; - } - // Whitespace is not allowed between the '%' and the number, so check that - // the next character is a digit. - if (!ISDIGIT(Next)) - continue; - char *EndPtr; - // If this is an explicit reference to OpNum then we are done. - if (OpNum == strtoul(AsmStr+1, &EndPtr, 10)) - return true; - // Otherwise, skip over the number and keep scanning. - AsmStr = EndPtr - 1; - } - return false; -} - -/// CanonicalizeConstraint - If we can canonicalize the constraint into -/// something simpler, do so now. This turns register classes with a single -/// register into the register itself, expands builtin constraints to multiple -/// alternatives, etc. -static std::string CanonicalizeConstraint(const char *Constraint) { - std::string Result; - - // Skip over modifier characters. - bool DoneModifiers = false; - while (!DoneModifiers) { - switch (*Constraint) { - default: DoneModifiers = true; break; - case '=': assert(0 && "Should be after '='s"); - case '+': assert(0 && "'+' should already be expanded"); - case '*': - case '?': - case '!': - ++Constraint; - break; - case '&': // Pass earlyclobber to LLVM. - case '%': // Pass commutative to LLVM. - Result += *Constraint++; - break; - case '#': // No constraint letters left. - return Result; - } - } - - while (*Constraint) { - char ConstraintChar = *Constraint++; - - // 'g' is just short-hand for 'imr'. - if (ConstraintChar == 'g') { - Result += "imr"; - continue; - } - - // Translate 'p' to a target-specific set of constraints that - // conservatively allow a valid memory address. For inline assembly there - // is no way to know the mode of the data being addressed, so this is only - // a rough approximation of how GCC handles this constraint. - if (ConstraintChar == 'p') { - Result += LLVM_CANONICAL_ADDRESS_CONSTRAINTS; - continue; - } - - // See if this is a regclass constraint. - unsigned RegClass; - if (ConstraintChar == 'r') - // REG_CLASS_FROM_CONSTRAINT doesn't support 'r' for some reason. - RegClass = GENERAL_REGS; - else - RegClass = REG_CLASS_FROM_CONSTRAINT(Constraint[-1], Constraint-1); - - if (RegClass == NO_REGS) { // not a reg class. - Result += ConstraintChar; - continue; - } - - // Look to see if the specified regclass has exactly one member, and if so, - // what it is. Cache this information in AnalyzedRegClasses once computed. - static std::map AnalyzedRegClasses; - - std::map::iterator I = - AnalyzedRegClasses.lower_bound(RegClass); - - int RegMember; - if (I != AnalyzedRegClasses.end() && I->first == RegClass) { - // We've already computed this, reuse value. - RegMember = I->second; - } else { - // Otherwise, scan the regclass, looking for exactly one member. - RegMember = -1; // -1 => not a single-register class. - for (unsigned j = 0; j != FIRST_PSEUDO_REGISTER; ++j) - if (TEST_HARD_REG_BIT(reg_class_contents[RegClass], j)) { - if (RegMember == -1) { - RegMember = j; - } else { - RegMember = -1; - break; - } - } - // Remember this answer for the next query of this regclass. - AnalyzedRegClasses.insert(I, std::make_pair(RegClass, RegMember)); - } - - // If we found a single register register class, return the register. - if (RegMember != -1) { - Result += '{'; - Result += LLVM_GET_REG_NAME(0, RegMember); - Result += '}'; - } else { - Result += ConstraintChar; - } - } - - return Result; -} - -/// See if operand "exp" can use the indicated Constraint (which is -/// terminated by a null or a comma). -/// Returns: -1=no, 0=yes but auxiliary instructions needed, 1=yes and free -static int MatchWeight(const char *Constraint, tree Operand) { - const char *p = Constraint; - int RetVal = 0; - // Look for hard register operand. This matches only a constraint of a - // register class that includes that hard register, and it matches that - // perfectly, so we never return 0 in this case. - if (TREE_CODE(Operand) == VAR_DECL && DECL_HARD_REGISTER(Operand)) { - int RegNum = decode_reg_name(extractRegisterName(Operand)); - RetVal = -1; - if (RegNum >= 0) { - do { - unsigned RegClass; - if (*p == 'r') - RegClass = GENERAL_REGS; - else - RegClass = REG_CLASS_FROM_CONSTRAINT(*p, p); - if (RegClass != NO_REGS && - TEST_HARD_REG_BIT(reg_class_contents[RegClass], RegNum)) { - RetVal = 1; - break; - } - ++p; - } while (*p != ',' && *p != 0); - } - } - // Look for integer constant operand. This cannot match "m", and "i" is - // better than "r". FIXME target-dependent immediate letters are not handled - // yet; in general they require looking at the value. - if (TREE_CODE(Operand) == INTEGER_CST) { - do { - RetVal = -1; - if (*p == 'i' || *p == 'n') { // integer constant - RetVal = 1; - break; - } - if (*p != 'm' && *p != 'o' && *p != 'V') // not memory - RetVal = 0; - ++p; - } while (*p != ',' && *p != 0); - } - /// TEMPORARY. This has the effect that alternative 0 is always chosen, - /// except in the cases handled above. - return RetVal; -} - -/// ChooseConstraintTuple: we know each of the NumInputs+NumOutputs strings -/// in Constraints[] is a comma-separated list of NumChoices different -/// constraints. Look through the operands and constraint possibilities -/// and pick a tuple where all the operands match. Replace the strings -/// in Constraints[] with the shorter strings from that tuple (malloc'ed, -/// caller is responsible for cleaning it up). Later processing can alter what -/// Constraints points to, so to make sure we delete everything, the addresses -/// of everything we allocated also are returned in StringStorage. -/// Casting back and forth from char* to const char* is Ugly, but we have to -/// interface with C code that expects const char*. -/// -/// gcc's algorithm for picking "the best" tuple is quite complicated, and -/// is performed after things like SROA, not before. At the moment we are -/// just trying to pick one that will work. This may get refined. -static void ChooseConstraintTuple(gimple stmt, const char **Constraints, - unsigned NumChoices, - BumpPtrAllocator &StringStorage) { - unsigned NumInputs = gimple_asm_ninputs(stmt); - unsigned NumOutputs = gimple_asm_noutputs(stmt); - - int MaxWeight = -1; - unsigned int CommasToSkip = 0; - int *Weights = (int *)alloca(NumChoices * sizeof(int)); - // RunningConstraints is pointers into the Constraints strings which - // are incremented as we go to point to the beginning of each - // comma-separated alternative. - const char** RunningConstraints = - (const char**)alloca((NumInputs+NumOutputs)*sizeof(const char*)); - memcpy(RunningConstraints, Constraints, - (NumInputs+NumOutputs) * sizeof(const char*)); - // The entire point of this loop is to compute CommasToSkip. - for (unsigned i = 0; i != NumChoices; ++i) { - Weights[i] = 0; - for (unsigned j = 0; j != NumOutputs; ++j) { - tree Output = gimple_asm_output_op(stmt, j); - if (i==0) - RunningConstraints[j]++; // skip leading = - const char* p = RunningConstraints[j]; - while (*p=='*' || *p=='&' || *p=='%') // skip modifiers - p++; - if (Weights[i] != -1) { - int w = MatchWeight(p, TREE_VALUE(Output)); - // Nonmatch means the entire tuple doesn't match. However, we - // keep scanning to set up RunningConstraints correctly for the - // next tuple. - if (w < 0) - Weights[i] = -1; - else - Weights[i] += w; - } - while (*p!=0 && *p!=',') - p++; - if (*p!=0) { - p++; // skip comma - while (*p=='*' || *p=='&' || *p=='%') - p++; // skip modifiers - } - RunningConstraints[j] = p; - } - for (unsigned j = 0; j != NumInputs; ++j) { - tree Input = gimple_asm_input_op(stmt, j); - const char* p = RunningConstraints[NumOutputs + j]; - if (Weights[i] != -1) { - int w = MatchWeight(p, TREE_VALUE(Input)); - if (w < 0) - Weights[i] = -1; // As above. - else - Weights[i] += w; - } - while (*p!=0 && *p!=',') - p++; - if (*p!=0) - p++; - RunningConstraints[NumOutputs + j] = p; - } - if (Weights[i]>MaxWeight) { - CommasToSkip = i; - MaxWeight = Weights[i]; - } - } - // We have picked an alternative (the CommasToSkip'th one). - // Change Constraints to point to malloc'd copies of the appropriate - // constraints picked out of the original strings. - for (unsigned int i=0; i(end-start+1+1); - newstring[0] = *(Constraints[i]); - strncpy(newstring+1, start, end-start); - newstring[end-start+1] = 0; - } else { - newstring = StringStorage.Allocate(end-start+1); - strncpy(newstring, start, end-start); - newstring[end-start] = 0; - } - Constraints[i] = (const char *)newstring; - } -} - - -//===----------------------------------------------------------------------===// -// ... Helpers for Builtin Function Expansion ... -//===----------------------------------------------------------------------===// - -Value *TreeToLLVM::BuildVector(const std::vector &Ops) { - assert((Ops.size() & (Ops.size()-1)) == 0 && - "Not a power-of-two sized vector!"); - bool AllConstants = true; - for (unsigned i = 0, e = Ops.size(); i != e && AllConstants; ++i) - AllConstants &= isa(Ops[i]); - - // If this is a constant vector, create a ConstantVector. - if (AllConstants) { - std::vector CstOps; - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - CstOps.push_back(cast(Ops[i])); - return ConstantVector::get(CstOps); - } - - // Otherwise, insertelement the values to build the vector. - Value *Result = - UndefValue::get(VectorType::get(Ops[0]->getType(), Ops.size())); - - for (unsigned i = 0, e = Ops.size(); i != e; ++i) - Result = Builder.CreateInsertElement(Result, Ops[i], - ConstantInt::get(Type::getInt32Ty(Context), i)); - - return Result; -} - -/// BuildVector - This varargs function builds a literal vector ({} syntax) with -/// the specified null-terminated list of elements. The elements must be all -/// the same element type and there must be a power of two of them. -Value *TreeToLLVM::BuildVector(Value *Elt, ...) { - std::vector Ops; - va_list VA; - va_start(VA, Elt); - - Ops.push_back(Elt); - while (Value *Arg = va_arg(VA, Value *)) - Ops.push_back(Arg); - va_end(VA); - - return BuildVector(Ops); -} - -/// BuildVectorShuffle - Given two vectors and a variable length list of int -/// constants, create a shuffle of the elements of the inputs, where each dest -/// is specified by the indexes. The int constant list must be as long as the -/// number of elements in the input vector. -/// -/// Undef values may be specified by passing in -1 as the result value. -/// -Value *TreeToLLVM::BuildVectorShuffle(Value *InVec1, Value *InVec2, ...) { - assert(InVec1->getType()->isVectorTy() && - InVec1->getType() == InVec2->getType() && "Invalid shuffle!"); - unsigned NumElements = cast(InVec1->getType())->getNumElements(); - - // Get all the indexes from varargs. - std::vector Idxs; - va_list VA; - va_start(VA, InVec2); - for (unsigned i = 0; i != NumElements; ++i) { - int idx = va_arg(VA, int); - if (idx == -1) - Idxs.push_back(UndefValue::get(Type::getInt32Ty(Context))); - else { - assert((unsigned)idx < 2*NumElements && "Element index out of range!"); - Idxs.push_back(ConstantInt::get(Type::getInt32Ty(Context), idx)); - } - } - va_end(VA); - - // Turn this into the appropriate shuffle operation. - return Builder.CreateShuffleVector(InVec1, InVec2, - ConstantVector::get(Idxs)); -} - -//===----------------------------------------------------------------------===// -// ... Builtin Function Expansion ... -//===----------------------------------------------------------------------===// - -/// EmitFrontendExpandedBuiltinCall - We allow the target to do some amount -/// of lowering. This allows us to avoid having intrinsics for operations that -/// directly correspond to LLVM constructs. -/// -/// This method returns true if the builtin is handled, otherwise false. -/// -bool TreeToLLVM::EmitFrontendExpandedBuiltinCall(gimple stmt, tree fndecl, - const MemRef *DestLoc, - Value *&Result) { -#ifdef LLVM_TARGET_INTRINSIC_LOWER - // Get the result type and operand line in an easy to consume format. - const Type *ResultType = ConvertType(TREE_TYPE(TREE_TYPE(fndecl))); - std::vector Operands; - for (unsigned i = 0, e = gimple_call_num_args(stmt); i != e; ++i) { - tree OpVal = gimple_call_arg(stmt, i); - if (AGGREGATE_TYPE_P(TREE_TYPE(OpVal))) { - MemRef OpLoc = CreateTempLoc(ConvertType(TREE_TYPE(OpVal))); - EmitAggregate(OpVal, OpLoc); - Operands.push_back(Builder.CreateLoad(OpLoc.Ptr)); - } else { - Operands.push_back(EmitMemory(OpVal)); - } - } - - return LLVM_TARGET_INTRINSIC_LOWER(stmt, fndecl, DestLoc, Result, ResultType, - Operands); -#endif - return false; -} - -/// TargetBuiltinCache - A cache of builtin intrinsics indexed by the GCC -/// builtin number. -static std::vector TargetBuiltinCache; - -void TreeToLLVM::EmitMemoryBarrier(bool ll, bool ls, bool sl, bool ss, - bool device) { - Value* C[5]; - C[0] = ConstantInt::get(Type::getInt1Ty(Context), ll); - C[1] = ConstantInt::get(Type::getInt1Ty(Context), ls); - C[2] = ConstantInt::get(Type::getInt1Ty(Context), sl); - C[3] = ConstantInt::get(Type::getInt1Ty(Context), ss); - C[4] = ConstantInt::get(Type::getInt1Ty(Context), device); - - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::memory_barrier), - C, C + 5); -} - -Value * -TreeToLLVM::BuildBinaryAtomicBuiltin(gimple stmt, Intrinsic::ID id) { - tree return_type = gimple_call_return_type(stmt); - const Type *ResultTy = ConvertType(return_type); - Value* C[2] = { - EmitMemory(gimple_call_arg(stmt, 0)), - EmitMemory(gimple_call_arg(stmt, 1)) - }; - const Type* Ty[2]; - Ty[0] = ResultTy; - Ty[1] = ResultTy->getPointerTo(); - C[0] = Builder.CreateBitCast(C[0], Ty[1]); - C[1] = Builder.CreateIntCast(C[1], Ty[0], - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Value *Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, id, - Ty, 2), - C, C + 2); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = Builder.CreateIntToPtr(Result, ResultTy); - return Result; -} - -Value * -TreeToLLVM::BuildCmpAndSwapAtomicBuiltin(gimple stmt, tree type, bool isBool) { - const Type *ResultTy = ConvertType(type); - Value* C[3] = { - EmitMemory(gimple_call_arg(stmt, 0)), - EmitMemory(gimple_call_arg(stmt, 1)), - EmitMemory(gimple_call_arg(stmt, 2)) - }; - const Type* Ty[2]; - Ty[0] = ResultTy; - Ty[1] = ResultTy->getPointerTo(); - C[0] = Builder.CreateBitCast(C[0], Ty[1]); - C[1] = Builder.CreateIntCast(C[1], Ty[0], /*isSigned*/!TYPE_UNSIGNED(type), - "cast"); - C[2] = Builder.CreateIntCast(C[2], Ty[0], /*isSigned*/!TYPE_UNSIGNED(type), - "cast"); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Value *Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::atomic_cmp_swap, - Ty, 2), - C, C + 3); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - if (isBool) - Result = Builder.CreateIntCast(Builder.CreateICmpEQ(Result, C[1]), - ConvertType(boolean_type_node), - /*isSigned*/false); - else - Result = Builder.CreateIntToPtr(Result, ResultTy); - return Result; -} - -/// EmitBuiltinCall - stmt is a call to fndecl, a builtin function. Try to emit -/// the call in a special way, setting Result to the scalar result if necessary. -/// If we can't handle the builtin, return false, otherwise return true. -bool TreeToLLVM::EmitBuiltinCall(gimple stmt, tree fndecl, - const MemRef *DestLoc, Value *&Result) { - if (DECL_BUILT_IN_CLASS(fndecl) == BUILT_IN_MD) { - unsigned FnCode = DECL_FUNCTION_CODE(fndecl); - if (TargetBuiltinCache.size() <= FnCode) - TargetBuiltinCache.resize(FnCode+1); - - // If we haven't converted this intrinsic over yet, do so now. - if (TargetBuiltinCache[FnCode] == 0) { - const char *TargetPrefix = ""; -#ifdef LLVM_TARGET_INTRINSIC_PREFIX - TargetPrefix = LLVM_TARGET_INTRINSIC_PREFIX; -#endif - // If the backend has some special code to lower, go ahead and try to - // do that first. - if (EmitFrontendExpandedBuiltinCall(stmt, fndecl, DestLoc, Result)) - return true; - - // If this builtin directly corresponds to an LLVM intrinsic, get the - // IntrinsicID now. - const char *BuiltinName = IDENTIFIER_POINTER(DECL_NAME(fndecl)); - Intrinsic::ID IntrinsicID = - Intrinsic::getIntrinsicForGCCBuiltin(TargetPrefix, BuiltinName); - if (IntrinsicID == Intrinsic::not_intrinsic) { - error_at(gimple_location(stmt), - "unsupported target builtin %<%s%> used", BuiltinName); - const Type *ResTy = ConvertType(gimple_call_return_type(stmt)); - if (ResTy->isSingleValueType()) - Result = UndefValue::get(ResTy); - return true; - } - - // Finally, map the intrinsic ID back to a name. - TargetBuiltinCache[FnCode] = - Intrinsic::getDeclaration(TheModule, IntrinsicID); - } - - Result = EmitCallOf(TargetBuiltinCache[FnCode], stmt, DestLoc, - AttrListPtr()); - return true; - } - - enum built_in_function fcode = DECL_FUNCTION_CODE(fndecl); - switch (fcode) { - default: return false; - // Varargs builtins. - case BUILT_IN_VA_START: return EmitBuiltinVAStart(stmt); - case BUILT_IN_VA_END: return EmitBuiltinVAEnd(stmt); - case BUILT_IN_VA_COPY: return EmitBuiltinVACopy(stmt); - case BUILT_IN_CONSTANT_P: return EmitBuiltinConstantP(stmt, Result); - case BUILT_IN_ALLOCA: return EmitBuiltinAlloca(stmt, Result); - case BUILT_IN_EXTEND_POINTER: return EmitBuiltinExtendPointer(stmt, Result); - case BUILT_IN_EXPECT: return EmitBuiltinExpect(stmt, Result); - case BUILT_IN_MEMCPY: return EmitBuiltinMemCopy(stmt, Result, - false, false); - case BUILT_IN_MEMCPY_CHK: return EmitBuiltinMemCopy(stmt, Result, - false, true); - case BUILT_IN_MEMMOVE: return EmitBuiltinMemCopy(stmt, Result, - true, false); - case BUILT_IN_MEMMOVE_CHK: return EmitBuiltinMemCopy(stmt, Result, - true, true); - case BUILT_IN_MEMSET: return EmitBuiltinMemSet(stmt, Result, false); - case BUILT_IN_MEMSET_CHK: return EmitBuiltinMemSet(stmt, Result, true); - case BUILT_IN_BZERO: return EmitBuiltinBZero(stmt, Result); - case BUILT_IN_PREFETCH: return EmitBuiltinPrefetch(stmt); - case BUILT_IN_FRAME_ADDRESS: return EmitBuiltinReturnAddr(stmt, Result,true); - case BUILT_IN_RETURN_ADDRESS: - return EmitBuiltinReturnAddr(stmt, Result,false); - case BUILT_IN_STACK_SAVE: return EmitBuiltinStackSave(stmt, Result); - case BUILT_IN_STACK_RESTORE: return EmitBuiltinStackRestore(stmt); - case BUILT_IN_EXTRACT_RETURN_ADDR: - return EmitBuiltinExtractReturnAddr(stmt, Result); - case BUILT_IN_FROB_RETURN_ADDR: - return EmitBuiltinFrobReturnAddr(stmt, Result); - case BUILT_IN_ADJUST_TRAMPOLINE: - return EmitBuiltinAdjustTrampoline(stmt, Result); - case BUILT_IN_INIT_TRAMPOLINE: - return EmitBuiltinInitTrampoline(stmt, Result); - - // Exception handling builtins. - case BUILT_IN_EH_POINTER: - return EmitBuiltinEHPointer(stmt, Result); - - // Builtins used by the exception handling runtime. - case BUILT_IN_DWARF_CFA: - return EmitBuiltinDwarfCFA(stmt, Result); -#ifdef DWARF2_UNWIND_INFO - case BUILT_IN_DWARF_SP_COLUMN: - return EmitBuiltinDwarfSPColumn(stmt, Result); - case BUILT_IN_INIT_DWARF_REG_SIZES: - return EmitBuiltinInitDwarfRegSizes(stmt, Result); -#endif - case BUILT_IN_EH_RETURN: - return EmitBuiltinEHReturn(stmt, Result); -#ifdef EH_RETURN_DATA_REGNO - case BUILT_IN_EH_RETURN_DATA_REGNO: - return EmitBuiltinEHReturnDataRegno(stmt, Result); -#endif - case BUILT_IN_UNWIND_INIT: - return EmitBuiltinUnwindInit(stmt, Result); - - case BUILT_IN_OBJECT_SIZE: { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - error("Invalid builtin_object_size argument types"); - return false; - } - tree ObjSizeTree = gimple_call_arg(stmt, 1); - STRIP_NOPS (ObjSizeTree); - if (TREE_CODE (ObjSizeTree) != INTEGER_CST - || tree_int_cst_sgn (ObjSizeTree) < 0 - || compare_tree_int (ObjSizeTree, 3) > 0) { - error("Invalid second builtin_object_size argument"); - return false; - } - - // LLVM doesn't handle type 1 or type 3. Deal with that here. - Value *Tmp = EmitMemory(gimple_call_arg(stmt, 1)); - - ConstantInt *CI = cast(Tmp); - - // Clear the bottom bit since we only handle whole objects and shift to turn - // the second bit into our boolean. - uint64_t val = (CI->getZExtValue() & 0x2) >> 1; - - Value *NewTy = ConstantInt::get(Tmp->getType(), val); - - Value* Args[] = { - EmitMemory(gimple_call_arg(stmt, 0)), - NewTy - }; - - // Grab the current return type. - const Type* Ty = ConvertType(gimple_call_return_type(stmt)); - - // Manually coerce the arg to the correct pointer type. - Args[0] = Builder.CreateBitCast(Args[0], Type::getInt8PtrTy(Context)); - Args[1] = Builder.CreateIntCast(Args[1], Type::getInt1Ty(Context), - /*isSigned*/false); - - Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::objectsize, - &Ty, - 1), - Args, Args + 2); - return true; - } - // Unary bit counting intrinsics. - // NOTE: do not merge these case statements. That will cause the memoized - // Function* to be incorrectly shared across the different typed functions. - case BUILT_IN_CLZ: // These GCC builtins always return int. - case BUILT_IN_CLZL: - case BUILT_IN_CLZLL: { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::ctlz); - tree return_type = gimple_call_return_type(stmt); - const Type *DestTy = ConvertType(return_type); - Result = Builder.CreateIntCast(Result, DestTy, - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - return true; - } - case BUILT_IN_CTZ: // These GCC builtins always return int. - case BUILT_IN_CTZL: - case BUILT_IN_CTZLL: { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::cttz); - tree return_type = gimple_call_return_type(stmt); - const Type *DestTy = ConvertType(return_type); - Result = Builder.CreateIntCast(Result, DestTy, - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - return true; - } - case BUILT_IN_PARITYLL: - case BUILT_IN_PARITYL: - case BUILT_IN_PARITY: { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::ctpop); - Result = Builder.CreateBinOp(Instruction::And, Result, - ConstantInt::get(Result->getType(), 1)); - tree return_type = gimple_call_return_type(stmt); - const Type *DestTy = ConvertType(return_type); - Result = Builder.CreateIntCast(Result, DestTy, - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - return true; - } - case BUILT_IN_POPCOUNT: // These GCC builtins always return int. - case BUILT_IN_POPCOUNTL: - case BUILT_IN_POPCOUNTLL: { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::ctpop); - tree return_type = gimple_call_return_type(stmt); - const Type *DestTy = ConvertType(return_type); - Result = Builder.CreateIntCast(Result, DestTy, - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - return true; - } - case BUILT_IN_BSWAP32: - case BUILT_IN_BSWAP64: { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::bswap); - tree return_type = gimple_call_return_type(stmt); - const Type *DestTy = ConvertType(return_type); - Result = Builder.CreateIntCast(Result, DestTy, - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - return true; - } - - case BUILT_IN_SQRT: - case BUILT_IN_SQRTF: - case BUILT_IN_SQRTL: - // The result of sqrt(negative) is implementation-defined, but follows - // IEEE754 in most current implementations. llvm.sqrt, which has undefined - // behavior for such inputs, is an inappropriate substitute. - break; - case BUILT_IN_POWI: - case BUILT_IN_POWIF: - case BUILT_IN_POWIL: - Result = EmitBuiltinPOWI(stmt); - return true; - case BUILT_IN_POW: - case BUILT_IN_POWF: - case BUILT_IN_POWL: - // If errno math has been disabled, expand these to llvm.pow calls. - if (!flag_errno_math) { - Result = EmitBuiltinPOW(stmt); - return true; - } - break; - case BUILT_IN_LOG: - case BUILT_IN_LOGF: - case BUILT_IN_LOGL: - // If errno math has been disabled, expand these to llvm.log calls. - if (!flag_errno_math) { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::log); - Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt))); - return true; - } - break; - case BUILT_IN_LOG2: - case BUILT_IN_LOG2F: - case BUILT_IN_LOG2L: - // If errno math has been disabled, expand these to llvm.log2 calls. - if (!flag_errno_math) { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::log2); - Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt))); - return true; - } - break; - case BUILT_IN_LOG10: - case BUILT_IN_LOG10F: - case BUILT_IN_LOG10L: - // If errno math has been disabled, expand these to llvm.log10 calls. - if (!flag_errno_math) { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::log10); - Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt))); - return true; - } - break; - case BUILT_IN_EXP: - case BUILT_IN_EXPF: - case BUILT_IN_EXPL: - // If errno math has been disabled, expand these to llvm.exp calls. - if (!flag_errno_math) { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::exp); - Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt))); - return true; - } - break; - case BUILT_IN_EXP2: - case BUILT_IN_EXP2F: - case BUILT_IN_EXP2L: - // If errno math has been disabled, expand these to llvm.exp2 calls. - if (!flag_errno_math) { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::exp2); - Result = CastToFPType(Result, ConvertType(gimple_call_return_type(stmt))); - return true; - } - break; - case BUILT_IN_FFS: // These GCC builtins always return int. - case BUILT_IN_FFSL: - case BUILT_IN_FFSLL: { // FFS(X) -> (x == 0 ? 0 : CTTZ(x)+1) - // The argument and return type of cttz should match the argument type of - // the ffs, but should ignore the return type of ffs. - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - EmitBuiltinUnaryOp(Amt, Result, Intrinsic::cttz); - Result = Builder.CreateAdd(Result, - ConstantInt::get(Result->getType(), 1)); - Result = Builder.CreateIntCast(Result, - ConvertType(gimple_call_return_type(stmt)), - /*isSigned*/false); - Value *Cond = - Builder.CreateICmpEQ(Amt, - Constant::getNullValue(Amt->getType())); - Result = Builder.CreateSelect(Cond, - Constant::getNullValue(Result->getType()), - Result); - return true; - } - case BUILT_IN_LCEIL: - case BUILT_IN_LCEILF: - case BUILT_IN_LCEILL: - case BUILT_IN_LLCEIL: - case BUILT_IN_LLCEILF: - case BUILT_IN_LLCEILL: - Result = EmitBuiltinLCEIL(stmt); - return true; - case BUILT_IN_LFLOOR: - case BUILT_IN_LFLOORF: - case BUILT_IN_LFLOORL: - case BUILT_IN_LLFLOOR: - case BUILT_IN_LLFLOORF: - case BUILT_IN_LLFLOORL: - Result = EmitBuiltinLFLOOR(stmt); - return true; -//TODO case BUILT_IN_FLT_ROUNDS: { -//TODO Result = -//TODO Builder.CreateCall(Intrinsic::getDeclaration(TheModule, -//TODO Intrinsic::flt_rounds)); -//TODO Result = Builder.CreateBitCast(Result, ConvertType(gimple_call_return_type(stmt))); -//TODO return true; -//TODO } - case BUILT_IN_TRAP: - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::trap)); - // Emit an explicit unreachable instruction. - Builder.CreateUnreachable(); - BeginBlock(BasicBlock::Create(Context)); - return true; - -//TODO // Convert annotation built-in to llvm.annotation intrinsic. -//TODO case BUILT_IN_ANNOTATION: { -//TODO -//TODO // Get file and line number -//TODO location_t locus = gimple_location(stmt); -//TODO Constant *lineNo = ConstantInt::get(Type::getInt32Ty, LOCATION_LINE(locus)); -//TODO Constant *file = ConvertMetadataStringToGV(LOCATION_FILE(locus)); -//TODO const Type *SBP= Type::getInt8PtrTy(Context); -//TODO file = TheFolder->CreateBitCast(file, SBP); -//TODO -//TODO // Get arguments. -//TODO tree arglist = CALL_EXPR_ARGS(stmt); -//TODO Value *ExprVal = EmitMemory(gimple_call_arg(stmt, 0)); -//TODO const Type *Ty = ExprVal->getType(); -//TODO Value *StrVal = EmitMemory(gimple_call_arg(stmt, 1)); -//TODO -//TODO SmallVector Args; -//TODO Args.push_back(ExprVal); -//TODO Args.push_back(StrVal); -//TODO Args.push_back(file); -//TODO Args.push_back(lineNo); -//TODO -//TODO assert(Ty && "llvm.annotation arg type may not be null"); -//TODO Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, -//TODO Intrinsic::annotation, -//TODO &Ty, -//TODO 1), -//TODO Args.begin(), Args.end()); -//TODO return true; -//TODO } - - case BUILT_IN_SYNCHRONIZE: { - // We assume like gcc appears to, that this only applies to cached memory. - Value* C[5]; - C[0] = C[1] = C[2] = C[3] = ConstantInt::get(Type::getInt1Ty(Context), 1); - C[4] = ConstantInt::get(Type::getInt1Ty(Context), 0); - - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::memory_barrier), - C, C + 5); - return true; - } -#if defined(TARGET_ALPHA) || defined(TARGET_386) || defined(TARGET_POWERPC) \ - || defined(TARGET_ARM) - // gcc uses many names for the sync intrinsics - // The type of the first argument is not reliable for choosing the - // right llvm function; if the original type is not volatile, gcc has - // helpfully changed it to "volatile void *" at this point. The - // original type can be recovered from the function type in most cases. - // For lock_release and bool_compare_and_swap even that is not good - // enough, we have to key off the opcode. - // Note that Intrinsic::getDeclaration expects the type list in reversed - // order, while CreateCall expects the parameter list in normal order. - case BUILT_IN_BOOL_COMPARE_AND_SWAP_1: { - Result = BuildCmpAndSwapAtomicBuiltin(stmt, unsigned_char_type_node, true); - return true; - } - case BUILT_IN_BOOL_COMPARE_AND_SWAP_2: { - Result = BuildCmpAndSwapAtomicBuiltin(stmt, short_unsigned_type_node, true); - return true; - } - case BUILT_IN_BOOL_COMPARE_AND_SWAP_4: { - Result = BuildCmpAndSwapAtomicBuiltin(stmt, unsigned_type_node, true); - return true; - } - case BUILT_IN_BOOL_COMPARE_AND_SWAP_8: { -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - Result = BuildCmpAndSwapAtomicBuiltin(stmt, long_long_unsigned_type_node, - true); - return true; - } - - case BUILT_IN_VAL_COMPARE_AND_SWAP_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_VAL_COMPARE_AND_SWAP_1: - case BUILT_IN_VAL_COMPARE_AND_SWAP_2: - case BUILT_IN_VAL_COMPARE_AND_SWAP_4: { - tree type = gimple_call_return_type(stmt); - Result = BuildCmpAndSwapAtomicBuiltin(stmt, type, false); - return true; - } - case BUILT_IN_FETCH_AND_ADD_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_FETCH_AND_ADD_1: - case BUILT_IN_FETCH_AND_ADD_2: - case BUILT_IN_FETCH_AND_ADD_4: { - Result = BuildBinaryAtomicBuiltin(stmt, Intrinsic::atomic_load_add); - return true; - } - case BUILT_IN_FETCH_AND_SUB_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_FETCH_AND_SUB_1: - case BUILT_IN_FETCH_AND_SUB_2: - case BUILT_IN_FETCH_AND_SUB_4: { - Result = BuildBinaryAtomicBuiltin(stmt, Intrinsic::atomic_load_sub); - return true; - } - case BUILT_IN_FETCH_AND_OR_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_FETCH_AND_OR_1: - case BUILT_IN_FETCH_AND_OR_2: - case BUILT_IN_FETCH_AND_OR_4: { - Result = BuildBinaryAtomicBuiltin(stmt, Intrinsic::atomic_load_or); - return true; - } - case BUILT_IN_FETCH_AND_AND_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_FETCH_AND_AND_1: - case BUILT_IN_FETCH_AND_AND_2: - case BUILT_IN_FETCH_AND_AND_4: { - Result = BuildBinaryAtomicBuiltin(stmt, Intrinsic::atomic_load_and); - return true; - } - case BUILT_IN_FETCH_AND_XOR_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_FETCH_AND_XOR_1: - case BUILT_IN_FETCH_AND_XOR_2: - case BUILT_IN_FETCH_AND_XOR_4: { - Result = BuildBinaryAtomicBuiltin(stmt, Intrinsic::atomic_load_xor); - return true; - } - case BUILT_IN_FETCH_AND_NAND_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_FETCH_AND_NAND_1: - case BUILT_IN_FETCH_AND_NAND_2: - case BUILT_IN_FETCH_AND_NAND_4: { - Result = BuildBinaryAtomicBuiltin(stmt, Intrinsic::atomic_load_nand); - return true; - } - case BUILT_IN_LOCK_TEST_AND_SET_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_LOCK_TEST_AND_SET_1: - case BUILT_IN_LOCK_TEST_AND_SET_2: - case BUILT_IN_LOCK_TEST_AND_SET_4: { - Result = BuildBinaryAtomicBuiltin(stmt, Intrinsic::atomic_swap); - return true; - } - - case BUILT_IN_ADD_AND_FETCH_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_ADD_AND_FETCH_1: - case BUILT_IN_ADD_AND_FETCH_2: - case BUILT_IN_ADD_AND_FETCH_4: { - tree return_type = gimple_call_return_type(stmt); - const Type *ResultTy = ConvertType(return_type); - Value* C[2] = { - EmitMemory(gimple_call_arg(stmt, 0)), - EmitMemory(gimple_call_arg(stmt, 1)) - }; - const Type* Ty[2]; - Ty[0] = ResultTy; - Ty[1] = ResultTy->getPointerTo(); - C[0] = Builder.CreateBitCast(C[0], Ty[1]); - C[1] = Builder.CreateIntCast(C[1], Ty[0], - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::atomic_load_add, - Ty, 2), - C, C + 2); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = Builder.CreateAdd(Result, C[1]); - Result = Builder.CreateIntToPtr(Result, ResultTy); - return true; - } - case BUILT_IN_SUB_AND_FETCH_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_SUB_AND_FETCH_1: - case BUILT_IN_SUB_AND_FETCH_2: - case BUILT_IN_SUB_AND_FETCH_4: { - tree return_type = gimple_call_return_type(stmt); - const Type *ResultTy = ConvertType(return_type); - Value* C[2] = { - EmitMemory(gimple_call_arg(stmt, 0)), - EmitMemory(gimple_call_arg(stmt, 1)) - }; - const Type* Ty[2]; - Ty[0] = ResultTy; - Ty[1] = ResultTy->getPointerTo(); - C[0] = Builder.CreateBitCast(C[0], Ty[1]); - C[1] = Builder.CreateIntCast(C[1], Ty[0], - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::atomic_load_sub, - Ty, 2), - C, C + 2); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = Builder.CreateSub(Result, C[1]); - Result = Builder.CreateIntToPtr(Result, ResultTy); - return true; - } - case BUILT_IN_OR_AND_FETCH_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_OR_AND_FETCH_1: - case BUILT_IN_OR_AND_FETCH_2: - case BUILT_IN_OR_AND_FETCH_4: { - tree return_type = gimple_call_return_type(stmt); - const Type *ResultTy = ConvertType(return_type); - Value* C[2] = { - EmitMemory(gimple_call_arg(stmt, 0)), - EmitMemory(gimple_call_arg(stmt, 1)) - }; - const Type* Ty[2]; - Ty[0] = ResultTy; - Ty[1] = ResultTy->getPointerTo(); - C[0] = Builder.CreateBitCast(C[0], Ty[1]); - C[1] = Builder.CreateIntCast(C[1], Ty[0], - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::atomic_load_or, - Ty, 2), - C, C + 2); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = Builder.CreateOr(Result, C[1]); - Result = Builder.CreateIntToPtr(Result, ResultTy); - return true; - } - case BUILT_IN_AND_AND_FETCH_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_AND_AND_FETCH_1: - case BUILT_IN_AND_AND_FETCH_2: - case BUILT_IN_AND_AND_FETCH_4: { - tree return_type = gimple_call_return_type(stmt); - const Type *ResultTy = ConvertType(return_type); - Value* C[2] = { - EmitMemory(gimple_call_arg(stmt, 0)), - EmitMemory(gimple_call_arg(stmt, 1)) - }; - const Type* Ty[2]; - Ty[0] = ResultTy; - Ty[1] = ResultTy->getPointerTo(); - C[0] = Builder.CreateBitCast(C[0], Ty[1]); - C[1] = Builder.CreateIntCast(C[1], Ty[0], - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::atomic_load_and, - Ty, 2), - C, C + 2); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = Builder.CreateAnd(Result, C[1]); - Result = Builder.CreateIntToPtr(Result, ResultTy); - return true; - } - case BUILT_IN_XOR_AND_FETCH_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_XOR_AND_FETCH_1: - case BUILT_IN_XOR_AND_FETCH_2: - case BUILT_IN_XOR_AND_FETCH_4: { - tree return_type = gimple_call_return_type(stmt); - const Type *ResultTy = ConvertType(return_type); - Value* C[2] = { - EmitMemory(gimple_call_arg(stmt, 0)), - EmitMemory(gimple_call_arg(stmt, 1)) - }; - const Type* Ty[2]; - Ty[0] = ResultTy; - Ty[1] = ResultTy->getPointerTo(); - C[0] = Builder.CreateBitCast(C[0], Ty[1]); - C[1] = Builder.CreateIntCast(C[1], Ty[0], - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::atomic_load_xor, - Ty, 2), - C, C + 2); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = Builder.CreateXor(Result, C[1]); - Result = Builder.CreateIntToPtr(Result, ResultTy); - return true; - } - case BUILT_IN_NAND_AND_FETCH_8: -#if defined(TARGET_POWERPC) - if (!TARGET_64BIT) - return false; -#endif - case BUILT_IN_NAND_AND_FETCH_1: - case BUILT_IN_NAND_AND_FETCH_2: - case BUILT_IN_NAND_AND_FETCH_4: { - tree return_type = gimple_call_return_type(stmt); - const Type *ResultTy = ConvertType(return_type); - Value* C[2] = { - EmitMemory(gimple_call_arg(stmt, 0)), - EmitMemory(gimple_call_arg(stmt, 1)) - }; - const Type* Ty[2]; - Ty[0] = ResultTy; - Ty[1] = ResultTy->getPointerTo(); - C[0] = Builder.CreateBitCast(C[0], Ty[1]); - C[1] = Builder.CreateIntCast(C[1], Ty[0], - /*isSigned*/!TYPE_UNSIGNED(return_type), - "cast"); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::atomic_load_nand, - Ty, 2), - C, C + 2); - - // The gcc builtins are also full memory barriers. - // FIXME: __sync_lock_test_and_set and __sync_lock_release require less. -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - EmitMemoryBarrier(true, true, true, true, false); -#else - EmitMemoryBarrier(true, true, true, true, true); -#endif - - Result = Builder.CreateAnd(Builder.CreateNot(Result), C[1]); - Result = Builder.CreateIntToPtr(Result, ResultTy); - return true; - } - - case BUILT_IN_LOCK_RELEASE_1: - case BUILT_IN_LOCK_RELEASE_2: - case BUILT_IN_LOCK_RELEASE_4: - case BUILT_IN_LOCK_RELEASE_8: - case BUILT_IN_LOCK_RELEASE_16: { - // This is effectively a volatile store of 0, and has no return value. - // The argument has typically been coerced to "volatile void*"; the - // only way to find the size of the operation is from the builtin - // opcode. - const Type *Ty; - switch(DECL_FUNCTION_CODE(fndecl)) { - case BUILT_IN_LOCK_RELEASE_16: // not handled; should use SSE on x86 - default: - DieAbjectly("Not handled; should use SSE on x86!"); - case BUILT_IN_LOCK_RELEASE_1: - Ty = Type::getInt8Ty(Context); break; - case BUILT_IN_LOCK_RELEASE_2: - Ty = Type::getInt16Ty(Context); break; - case BUILT_IN_LOCK_RELEASE_4: - Ty = Type::getInt32Ty(Context); break; - case BUILT_IN_LOCK_RELEASE_8: - Ty = Type::getInt64Ty(Context); break; - } - Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0)); - Ptr = Builder.CreateBitCast(Ptr, Ty->getPointerTo()); - Builder.CreateStore(Constant::getNullValue(Ty), Ptr, true); - Result = 0; - return true; - } - -#endif //FIXME: these break the build for backends that haven't implemented them - - -#if 1 // FIXME: Should handle these GCC extensions eventually. - case BUILT_IN_LONGJMP: { - if (validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) { - tree value = gimple_call_arg(stmt, 1); - - if (TREE_CODE(value) != INTEGER_CST || - cast(EmitMemory(value))->getValue() != 1) { - error ("%<__builtin_longjmp%> second argument must be 1"); - return false; - } - } -#if defined(TARGET_ARM) && defined(CONFIG_DARWIN_H) - Value *Buf = Emit(TREE_VALUE(arglist), 0); - Buf = Builder.CreateBitCast(Buf, Type::getInt8Ty(Context)->getPointerTo()); - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::eh_sjlj_longjmp), - Buf); - Result = 0; - return true; -#endif - // Fall-through - } - case BUILT_IN_APPLY_ARGS: - case BUILT_IN_APPLY: - case BUILT_IN_RETURN: - case BUILT_IN_SAVEREGS: - case BUILT_IN_ARGS_INFO: - case BUILT_IN_NEXT_ARG: - case BUILT_IN_CLASSIFY_TYPE: - case BUILT_IN_AGGREGATE_INCOMING_ADDRESS: - case BUILT_IN_SETJMP_SETUP: - case BUILT_IN_SETJMP_DISPATCHER: - case BUILT_IN_SETJMP_RECEIVER: - case BUILT_IN_UPDATE_SETJMP_BUF: - - // FIXME: HACK: Just ignore these. - { - const Type *Ty = ConvertType(gimple_call_return_type(stmt)); - if (!Ty->isVoidTy()) - Result = Constant::getNullValue(Ty); - return true; - } -#endif // FIXME: Should handle these GCC extensions eventually. - } - return false; -} - -bool TreeToLLVM::EmitBuiltinUnaryOp(Value *InVal, Value *&Result, - Intrinsic::ID Id) { - // The intrinsic might be overloaded in which case the argument is of - // varying type. Make sure that we specify the actual type for "iAny" - // by passing it as the 3rd and 4th parameters. This isn't needed for - // most intrinsics, but is needed for ctpop, cttz, ctlz. - const Type *Ty = InVal->getType(); - Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Id, &Ty, 1), - InVal); - return true; -} - -Value *TreeToLLVM::EmitBuiltinSQRT(gimple stmt) { - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - const Type* Ty = Amt->getType(); - - return Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::sqrt, &Ty, 1), - Amt); -} - -Value *TreeToLLVM::EmitBuiltinPOWI(gimple stmt) { - if (!validate_gimple_arglist(stmt, REAL_TYPE, INTEGER_TYPE, VOID_TYPE)) - return 0; - - Value *Val = EmitMemory(gimple_call_arg(stmt, 0)); - Value *Pow = EmitMemory(gimple_call_arg(stmt, 1)); - const Type *Ty = Val->getType(); - Pow = Builder.CreateIntCast(Pow, Type::getInt32Ty(Context), /*isSigned*/true); - - SmallVector Args; - Args.push_back(Val); - Args.push_back(Pow); - return Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::powi, &Ty, 1), - Args.begin(), Args.end()); -} - -Value *TreeToLLVM::EmitBuiltinPOW(gimple stmt) { - if (!validate_gimple_arglist(stmt, REAL_TYPE, REAL_TYPE, VOID_TYPE)) - return 0; - - Value *Val = EmitMemory(gimple_call_arg(stmt, 0)); - Value *Pow = EmitMemory(gimple_call_arg(stmt, 1)); - const Type *Ty = Val->getType(); - - SmallVector Args; - Args.push_back(Val); - Args.push_back(Pow); - return Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::pow, &Ty, 1), - Args.begin(), Args.end()); -} - -Value *TreeToLLVM::EmitBuiltinLCEIL(gimple stmt) { - if (!validate_gimple_arglist(stmt, REAL_TYPE, VOID_TYPE)) - return 0; - - // Cast the result of "ceil" to the appropriate integer type. - // First call the appropriate version of "ceil". - tree op = gimple_call_arg(stmt, 0); - StringRef Name = SelectFPName(TREE_TYPE(op), "ceilf", "ceil", "ceill"); - CallInst *Call = EmitSimpleCall(Name, TREE_TYPE(op), op, NULL); - Call->setDoesNotThrow(); - Call->setDoesNotAccessMemory(); - - // Then type cast the result of the "ceil" call. - tree type = gimple_call_return_type(stmt); - const Type *RetTy = GetRegType(type); - return TYPE_UNSIGNED(type) ? Builder.CreateFPToUI(Call, RetTy) : - Builder.CreateFPToSI(Call, RetTy); -} - -Value *TreeToLLVM::EmitBuiltinLFLOOR(gimple stmt) { - if (!validate_gimple_arglist(stmt, REAL_TYPE, VOID_TYPE)) - return 0; - - // Cast the result of "floor" to the appropriate integer type. - // First call the appropriate version of "floor". - tree op = gimple_call_arg(stmt, 0); - StringRef Name = SelectFPName(TREE_TYPE(op), "floorf", "floor", "floorl"); - CallInst *Call = EmitSimpleCall(Name, TREE_TYPE(op), op, NULL); - Call->setDoesNotThrow(); - Call->setDoesNotAccessMemory(); - - // Then type cast the result of the "floor" call. - tree type = gimple_call_return_type(stmt); - const Type *RetTy = GetRegType(type); - return TYPE_UNSIGNED(type) ? Builder.CreateFPToUI(Call, RetTy) : - Builder.CreateFPToSI(Call, RetTy); -} - -bool TreeToLLVM::EmitBuiltinConstantP(gimple stmt, Value *&Result) { - Result = Constant::getNullValue(ConvertType(gimple_call_return_type(stmt))); - return true; -} - -bool TreeToLLVM::EmitBuiltinExtendPointer(gimple stmt, Value *&Result) { - tree arg0 = gimple_call_arg(stmt, 0); - Value *Amt = EmitMemory(arg0); - bool AmtIsSigned = !TYPE_UNSIGNED(TREE_TYPE(arg0)); - bool ExpIsSigned = !TYPE_UNSIGNED(gimple_call_return_type(stmt)); - Result = CastToAnyType(Amt, AmtIsSigned, - ConvertType(gimple_call_return_type(stmt)), - ExpIsSigned); - return true; -} - -/// OptimizeIntoPlainBuiltIn - Return true if it's safe to lower the object -/// size checking builtin calls (e.g. __builtin___memcpy_chk into the -/// plain non-checking calls. If the size of the argument is either -1 (unknown) -/// or large enough to ensure no overflow (> len), then it's safe to do so. -static bool OptimizeIntoPlainBuiltIn(gimple stmt, Value *Len, Value *Size) { - if (BitCastInst *SizeBC = dyn_cast(Size)) - Size = SizeBC->getOperand(0); - ConstantInt *SizeCI = dyn_cast(Size); - if (!SizeCI) - return false; - if (SizeCI->isAllOnesValue()) - // If size is -1, convert to plain memcpy, etc. - return true; - - if (BitCastInst *LenBC = dyn_cast(Len)) - Len = LenBC->getOperand(0); - ConstantInt *LenCI = dyn_cast(Len); - if (!LenCI) - return false; - if (SizeCI->getValue().ult(LenCI->getValue())) { - warning_at (gimple_location(stmt), 0, - "call to %D will always overflow destination buffer", - gimple_call_fndecl(stmt)); - return false; - } - return true; -} - -/// EmitBuiltinMemCopy - Emit an llvm.memcpy or llvm.memmove intrinsic, -/// depending on the value of isMemMove. -bool TreeToLLVM::EmitBuiltinMemCopy(gimple stmt, Value *&Result, bool isMemMove, - bool SizeCheck) { - if (SizeCheck) { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, POINTER_TYPE, - INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return false; - } else { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, POINTER_TYPE, - INTEGER_TYPE, VOID_TYPE)) - return false; - } - - tree Dst = gimple_call_arg(stmt, 0); - tree Src = gimple_call_arg(stmt, 1); - unsigned SrcAlign = getPointerAlignment(Src); - unsigned DstAlign = getPointerAlignment(Dst); - - Value *DstV = EmitMemory(Dst); - Value *SrcV = EmitMemory(Src); - Value *Len = EmitMemory(gimple_call_arg(stmt, 2)); - if (SizeCheck) { - tree SizeArg = gimple_call_arg(stmt, 3); - Value *Size = EmitMemory(SizeArg); - if (!OptimizeIntoPlainBuiltIn(stmt, Len, Size)) - return false; - } - - Result = isMemMove ? - EmitMemMove(DstV, SrcV, Len, std::min(SrcAlign, DstAlign)) : - EmitMemCpy(DstV, SrcV, Len, std::min(SrcAlign, DstAlign)); - return true; -} - -bool TreeToLLVM::EmitBuiltinMemSet(gimple stmt, Value *&Result, bool SizeCheck){ - if (SizeCheck) { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, - INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return false; - } else { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, - INTEGER_TYPE, VOID_TYPE)) - return false; - } - - tree Dst = gimple_call_arg(stmt, 0); - unsigned DstAlign = getPointerAlignment(Dst); - - Value *DstV = EmitMemory(Dst); - Value *Val = EmitMemory(gimple_call_arg(stmt, 1)); - Value *Len = EmitMemory(gimple_call_arg(stmt, 2)); - if (SizeCheck) { - tree SizeArg = gimple_call_arg(stmt, 3); - Value *Size = EmitMemory(SizeArg); - if (!OptimizeIntoPlainBuiltIn(stmt, Len, Size)) - return false; - } - Result = EmitMemSet(DstV, Val, Len, DstAlign); - return true; -} - -bool TreeToLLVM::EmitBuiltinBZero(gimple stmt, Value *&/*Result*/) { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) - return false; - - tree Dst = gimple_call_arg(stmt, 0); - unsigned DstAlign = getPointerAlignment(Dst); - - Value *DstV = EmitMemory(Dst); - Value *Val = Constant::getNullValue(Type::getInt32Ty(Context)); - Value *Len = EmitMemory(gimple_call_arg(stmt, 1)); - EmitMemSet(DstV, Val, Len, DstAlign); - return true; -} - -bool TreeToLLVM::EmitBuiltinPrefetch(gimple stmt) { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, 0)) - return false; - - Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0)); - Value *ReadWrite = 0; - Value *Locality = 0; - - if (gimple_call_num_args(stmt) > 1) { // Args 1/2 are optional - ReadWrite = EmitMemory(gimple_call_arg(stmt, 1)); - if (!isa(ReadWrite)) { - error("second argument to %<__builtin_prefetch%> must be a constant"); - ReadWrite = 0; - } else if (cast(ReadWrite)->getZExtValue() > 1) { - warning (0, "invalid second argument to %<__builtin_prefetch%>;" - " using zero"); - ReadWrite = 0; - } else { - ReadWrite = TheFolder->CreateIntCast(cast(ReadWrite), - Type::getInt32Ty(Context), - /*isSigned*/false); - } - - if (gimple_call_num_args(stmt) > 2) { - Locality = EmitMemory(gimple_call_arg(stmt, 2)); - if (!isa(Locality)) { - error("third argument to %<__builtin_prefetch%> must be a constant"); - Locality = 0; - } else if (cast(Locality)->getZExtValue() > 3) { - warning(0, "invalid third argument to %<__builtin_prefetch%>; using 3"); - Locality = 0; - } else { - Locality = TheFolder->CreateIntCast(cast(Locality), - Type::getInt32Ty(Context), - /*isSigned*/false); - } - } - } - - // Default to highly local read. - if (ReadWrite == 0) - ReadWrite = Constant::getNullValue(Type::getInt32Ty(Context)); - if (Locality == 0) - Locality = ConstantInt::get(Type::getInt32Ty(Context), 3); - - Ptr = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context)); - - Value *Ops[3] = { Ptr, ReadWrite, Locality }; - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::prefetch), - Ops, Ops+3); - return true; -} - -/// EmitBuiltinReturnAddr - Emit an llvm.returnaddress or llvm.frameaddress -/// instruction, depending on whether isFrame is true or not. -bool TreeToLLVM::EmitBuiltinReturnAddr(gimple stmt, Value *&Result, - bool isFrame) { - if (!validate_gimple_arglist(stmt, INTEGER_TYPE, VOID_TYPE)) - return false; - - ConstantInt *Level = - dyn_cast(EmitMemory(gimple_call_arg(stmt, 0))); - if (!Level) { - if (isFrame) - error("invalid argument to %<__builtin_frame_address%>"); - else - error("invalid argument to %<__builtin_return_address%>"); - return false; - } - - Intrinsic::ID IID = - !isFrame ? Intrinsic::returnaddress : Intrinsic::frameaddress; - Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, IID), Level); - Result = Builder.CreateBitCast(Result, - ConvertType(gimple_call_return_type(stmt))); - return true; -} - -bool TreeToLLVM::EmitBuiltinExtractReturnAddr(gimple stmt, Value *&Result) { - Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0)); - - // FIXME: Actually we should do something like this: - // - // Result = (Ptr & MASK_RETURN_ADDR) + RETURN_ADDR_OFFSET, if mask and - // offset are defined. This seems to be needed for: ARM, MIPS, Sparc. - // Unfortunately, these constants are defined as RTL expressions and - // should be handled separately. - - Result = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context)); - - return true; -} - -bool TreeToLLVM::EmitBuiltinFrobReturnAddr(gimple stmt, Value *&Result) { - Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0)); - - // FIXME: Actually we should do something like this: - // - // Result = Ptr - RETURN_ADDR_OFFSET, if offset is defined. This seems to be - // needed for: MIPS, Sparc. Unfortunately, these constants are defined - // as RTL expressions and should be handled separately. - - Result = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context)); - - return true; -} - -bool TreeToLLVM::EmitBuiltinStackSave(gimple stmt, Value *&Result) { - if (!validate_gimple_arglist(stmt, VOID_TYPE)) - return false; - - Result = Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::stacksave)); - return true; -} - - -// Exception handling builtins. - -bool TreeToLLVM::EmitBuiltinEHPointer(gimple stmt, Value *&Result) { - // Lookup the local that holds the exception pointer for this region. - unsigned RegionNo = tree_low_cst(gimple_call_arg(stmt, 0), 0); - AllocaInst *ExcPtr = getExceptionPtr(RegionNo); - // Load the exception pointer out. - Result = Builder.CreateLoad(ExcPtr); - // Ensure the returned value has the right pointer type. - tree type = gimple_call_return_type(stmt); - Result = Builder.CreateBitCast(Result, ConvertType(type)); - return true; -} - - -// Builtins used by the exception handling runtime. - -// On most machines, the CFA coincides with the first incoming parm. -#ifndef ARG_POINTER_CFA_OFFSET -#define ARG_POINTER_CFA_OFFSET(FNDECL) FIRST_PARM_OFFSET (FNDECL) -#endif - -// The mapping from gcc register number to DWARF 2 CFA column number. By -// default, we just provide columns for all registers. -#ifndef DWARF_FRAME_REGNUM -#define DWARF_FRAME_REGNUM(REG) DBX_REGISTER_NUMBER (REG) -#endif - -// Map register numbers held in the call frame info that gcc has -// collected using DWARF_FRAME_REGNUM to those that should be output in -// .debug_frame and .eh_frame. -#ifndef DWARF2_FRAME_REG_OUT -#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO) -#endif - -/* Registers that get partially clobbered by a call in a given mode. - These must not be call used registers. */ -#ifndef HARD_REGNO_CALL_PART_CLOBBERED -#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0 -#endif - -bool TreeToLLVM::EmitBuiltinDwarfCFA(gimple stmt, Value *&Result) { - if (!validate_gimple_arglist(stmt, VOID_TYPE)) - return false; - - int cfa_offset = ARG_POINTER_CFA_OFFSET(exp); - - // FIXME: is i32 always enough here? - Result = - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::eh_dwarf_cfa), - ConstantInt::get(Type::getInt32Ty(Context), cfa_offset)); - - return true; -} - -bool TreeToLLVM::EmitBuiltinDwarfSPColumn(gimple stmt, Value *&Result) { - if (!validate_gimple_arglist(stmt, VOID_TYPE)) - return false; - - unsigned int dwarf_regnum = DWARF_FRAME_REGNUM(STACK_POINTER_REGNUM); - Result = ConstantInt::get(ConvertType(gimple_call_return_type(stmt)), - dwarf_regnum); - - return true; -} - -bool TreeToLLVM::EmitBuiltinEHReturnDataRegno(gimple stmt, Value *&Result) { -#ifdef EH_RETURN_DATA_REGNO - if (!validate_gimple_arglist(stmt, INTEGER_TYPE, VOID_TYPE)) - return false; - - tree which = gimple_call_arg(stmt, 0); - unsigned HOST_WIDE_INT iwhich; - - if (TREE_CODE (which) != INTEGER_CST) { - error ("argument of %<__builtin_eh_return_regno%> must be constant"); - return false; - } - - iwhich = tree_low_cst (which, 1); - iwhich = EH_RETURN_DATA_REGNO (iwhich); - if (iwhich == INVALID_REGNUM) - return false; - - iwhich = DWARF_FRAME_REGNUM (iwhich); - - Result = ConstantInt::get(ConvertType(gimple_call_return_type(stmt)), iwhich); -#endif - - return true; -} - -bool TreeToLLVM::EmitBuiltinEHReturn(gimple stmt, Value *&/*Result*/) { - if (!validate_gimple_arglist(stmt, INTEGER_TYPE, POINTER_TYPE, VOID_TYPE)) - return false; - - const Type *IntPtr = TD.getIntPtrType(Context); - Value *Offset = EmitMemory(gimple_call_arg(stmt, 0)); - Value *Handler = EmitMemory(gimple_call_arg(stmt, 1)); - - Intrinsic::ID IID = IntPtr->isIntegerTy(32) ? - Intrinsic::eh_return_i32 : Intrinsic::eh_return_i64; - - Offset = Builder.CreateIntCast(Offset, IntPtr, /*isSigned*/true); - Handler = Builder.CreateBitCast(Handler, Type::getInt8PtrTy(Context)); - - Value *Args[2] = { Offset, Handler }; - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, IID), Args, Args + 2); - Builder.CreateUnreachable(); - BeginBlock(BasicBlock::Create(Context)); - - return true; -} - -bool TreeToLLVM::EmitBuiltinInitDwarfRegSizes(gimple stmt, Value *&/*Result*/) { -#ifdef DWARF2_UNWIND_INFO - unsigned int i; - bool wrote_return_column = false; - static bool reg_modes_initialized = false; - - if (!validate_gimple_arglist(stmt, POINTER_TYPE, VOID_TYPE)) - return false; - - if (!reg_modes_initialized) { - init_reg_modes_target(); - reg_modes_initialized = true; - } - - Value *Addr = - Builder.CreateBitCast(EmitMemory(gimple_call_arg(stmt, 0)), - Type::getInt8PtrTy(Context)); - Constant *Size, *Idx; - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { - int rnum = DWARF2_FRAME_REG_OUT (DWARF_FRAME_REGNUM (i), 1); - - if (rnum < DWARF_FRAME_REGISTERS) { - enum machine_mode save_mode = reg_raw_mode[i]; - HOST_WIDE_INT size; - - if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode)) - save_mode = choose_hard_reg_mode (i, 1, true); - if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN) { - if (save_mode == VOIDmode) - continue; - wrote_return_column = true; - } - size = GET_MODE_SIZE (save_mode); - if (rnum < 0) - continue; - - Size = ConstantInt::get(Type::getInt8Ty(Context), size); - Idx = ConstantInt::get(Type::getInt32Ty(Context), rnum); - Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx), false); - } - } - - if (!wrote_return_column) { - Size = ConstantInt::get(Type::getInt8Ty(Context), - GET_MODE_SIZE (Pmode)); - Idx = ConstantInt::get(Type::getInt32Ty(Context), - DWARF_FRAME_RETURN_COLUMN); - Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx), false); - } - -#ifdef DWARF_ALT_FRAME_RETURN_COLUMN - Size = ConstantInt::get(Type::getInt8Ty(Context), - GET_MODE_SIZE (Pmode)); - Idx = ConstantInt::get(Type::getInt32Ty(Context), - DWARF_ALT_FRAME_RETURN_COLUMN); - Builder.CreateStore(Size, Builder.CreateGEP(Addr, Idx), false); -#endif - -#endif /* DWARF2_UNWIND_INFO */ - - // TODO: the RS6000 target needs extra initialization [gcc changeset 122468]. - - return true; -} - -bool TreeToLLVM::EmitBuiltinUnwindInit(gimple stmt, Value *&/*Result*/) { - if (!validate_gimple_arglist(stmt, VOID_TYPE)) - return false; - - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::eh_unwind_init)); - - return true; -} - -bool TreeToLLVM::EmitBuiltinStackRestore(gimple stmt) { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, VOID_TYPE)) - return false; - - Value *Ptr = EmitMemory(gimple_call_arg(stmt, 0)); - Ptr = Builder.CreateBitCast(Ptr, Type::getInt8PtrTy(Context)); - - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, - Intrinsic::stackrestore), Ptr); - return true; -} - - -bool TreeToLLVM::EmitBuiltinAlloca(gimple stmt, Value *&Result) { - if (!validate_gimple_arglist(stmt, INTEGER_TYPE, VOID_TYPE)) - return false; - Value *Amt = EmitMemory(gimple_call_arg(stmt, 0)); - Result = Builder.CreateAlloca(Type::getInt8Ty(Context), Amt); - return true; -} - -bool TreeToLLVM::EmitBuiltinExpect(gimple stmt, Value *&Result) { - // Ignore the hint for now, just expand the expr. This is safe, but not - // optimal. - Result = gimple_call_num_args(stmt) < 2 ? - Constant::getNullValue(ConvertType(gimple_call_return_type(stmt))) : - EmitMemory(gimple_call_arg(stmt, 0)); - return true; -} - -bool TreeToLLVM::EmitBuiltinVAStart(gimple stmt) { - if (gimple_call_num_args(stmt) < 2) { - error_at (gimple_location(stmt), - "too few arguments to function %"); - return true; - } - - tree fntype = TREE_TYPE(current_function_decl); - if (TYPE_ARG_TYPES(fntype) == 0 || - (tree_last(TYPE_ARG_TYPES(fntype)) == void_type_node)) { - error("% used in function with fixed args"); - return true; - } - - Constant *va_start = Intrinsic::getDeclaration(TheModule, Intrinsic::vastart); - Value *ArgVal = EmitMemory(gimple_call_arg(stmt, 0)); - ArgVal = Builder.CreateBitCast(ArgVal, Type::getInt8PtrTy(Context)); - Builder.CreateCall(va_start, ArgVal); - return true; -} - -bool TreeToLLVM::EmitBuiltinVAEnd(gimple stmt) { - Value *Arg = EmitMemory(gimple_call_arg(stmt, 0)); - Arg = Builder.CreateBitCast(Arg, Type::getInt8PtrTy(Context)); - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::vaend), - Arg); - return true; -} - -bool TreeToLLVM::EmitBuiltinVACopy(gimple stmt) { - tree Arg1T = gimple_call_arg(stmt, 0); - tree Arg2T = gimple_call_arg(stmt, 1); - - Value *Arg1 = EmitMemory(Arg1T); // Emit the address of the destination. - // The second arg of llvm.va_copy is a pointer to a valist. - Value *Arg2; - if (!AGGREGATE_TYPE_P(va_list_type_node)) { - // Emit it as a value, then store it to a temporary slot. - Value *V2 = EmitMemory(Arg2T); - Arg2 = CreateTemporary(V2->getType()); - Builder.CreateStore(V2, Arg2); - } else { - // If the target has aggregate valists, then the second argument - // from GCC is the address of the source valist and we don't - // need to do anything special. - Arg2 = EmitMemory(Arg2T); - } - - static const Type *VPTy = Type::getInt8PtrTy(Context); - - // FIXME: This ignores alignment and volatility of the arguments. - SmallVector Args; - Args.push_back(Builder.CreateBitCast(Arg1, VPTy)); - Args.push_back(Builder.CreateBitCast(Arg2, VPTy)); - - Builder.CreateCall(Intrinsic::getDeclaration(TheModule, Intrinsic::vacopy), - Args.begin(), Args.end()); - return true; -} - -bool TreeToLLVM::EmitBuiltinAdjustTrampoline(gimple stmt, Value *&Result) { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, VOID_TYPE)) - return false; - - const Type *ResultTy = ConvertType(gimple_call_return_type(stmt)); - - // The adjusted value is stored as a pointer at the start of the storage GCC - // allocated for the trampoline - load it out and return it. - assert(TD.getPointerSize() <= TRAMPOLINE_SIZE && - "Trampoline smaller than a pointer!"); - Value *Tramp = EmitMemory(gimple_call_arg(stmt, 0)); - Tramp = Builder.CreateBitCast(Tramp, ResultTy->getPointerTo()); - Result = Builder.CreateLoad(Tramp, "adjusted"); - - // The load has the alignment of the trampoline storage. - unsigned Align = TYPE_ALIGN(TREE_TYPE(TREE_TYPE(gimple_call_arg(stmt, 0))))/8; - cast(Result)->setAlignment(Align); - - return true; -} - -bool TreeToLLVM::EmitBuiltinInitTrampoline(gimple stmt, Value *&/*Result*/) { - if (!validate_gimple_arglist(stmt, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE, - VOID_TYPE)) - return false; - - // LLVM's trampoline intrinsic, llvm.init.trampoline, combines the effect of - // GCC's init_trampoline and adjust_trampoline. Calls to adjust_trampoline - // should return the result of the llvm.init.trampoline call. This is tricky - // because the adjust_trampoline and init_trampoline calls need not occur in - // the same function. To overcome this, we don't store the trampoline machine - // code in the storage GCC created for it, we store the result of the call to - // llvm.init.trampoline there instead. Since this storage is the argument to - // adjust_trampoline, we turn adjust_trampoline into a load from its argument. - // The trampoline machine code itself is stored in a stack temporary that we - // create (one for each init_trampoline) in the function where init_trampoline - // is called. - static const Type *VPTy = Type::getInt8PtrTy(Context); - - // Create a stack temporary to hold the trampoline machine code. - const Type *TrampType = ArrayType::get(Type::getInt8Ty(Context), - TRAMPOLINE_SIZE); - AllocaInst *TrampTmp = CreateTemporary(TrampType); - TrampTmp->setAlignment(TRAMPOLINE_ALIGNMENT); - TrampTmp->setName("TRAMP"); - - Value *Func = EmitMemory(gimple_call_arg(stmt, 1)); - Value *Chain = EmitMemory(gimple_call_arg(stmt, 2)); - - Value *Ops[3] = { - Builder.CreateBitCast(TrampTmp, VPTy), - Builder.CreateBitCast(Func, VPTy), - Builder.CreateBitCast(Chain, VPTy) - }; - - Function *Intr = Intrinsic::getDeclaration(TheModule, - Intrinsic::init_trampoline); - Value *Adjusted = Builder.CreateCall(Intr, Ops, Ops + 3, "adjusted"); - - // Store the llvm.init.trampoline result to the GCC trampoline storage. - assert(TD.getPointerSize() <= TRAMPOLINE_SIZE && - "Trampoline smaller than a pointer!"); - Value *Tramp = EmitMemory(gimple_call_arg(stmt, 0)); - Tramp = Builder.CreateBitCast(Tramp, Adjusted->getType()->getPointerTo()); - StoreInst *Store = Builder.CreateStore(Adjusted, Tramp); - - // The store has the alignment of the trampoline storage. - unsigned Align = TYPE_ALIGN(TREE_TYPE(TREE_TYPE(gimple_call_arg(stmt, 0))))/8; - Store->setAlignment(Align); - - // The GCC trampoline storage is constant from this point on. Tell this to - // the optimizers. - Intr = Intrinsic::getDeclaration(TheModule, Intrinsic::invariant_start); - Ops[0] = ConstantInt::get(Type::getInt64Ty(Context), TRAMPOLINE_SIZE); - Ops[1] = Builder.CreateBitCast(Tramp, VPTy); - Builder.CreateCall(Intr, Ops, Ops + 2); - - return true; -} - -//===----------------------------------------------------------------------===// -// ... Complex Math Expressions ... -//===----------------------------------------------------------------------===// - -Value *TreeToLLVM::CreateComplex(Value *Real, Value *Imag, tree elt_type) { - assert(Real->getType() == Imag->getType() && "Component type mismatch!"); - Real = Reg2Mem(Real, elt_type, Builder); - Imag = Reg2Mem(Imag, elt_type, Builder); - const Type *EltTy = Real->getType(); - Value *Result = UndefValue::get(StructType::get(Context, EltTy, EltTy, NULL)); - Result = Builder.CreateInsertValue(Result, Real, 0); - Result = Builder.CreateInsertValue(Result, Imag, 1); - return Result; -} - -void TreeToLLVM::SplitComplex(Value *Complex, Value *&Real, Value *&Imag, - tree elt_type) { - Real = Mem2Reg(Builder.CreateExtractValue(Complex, 0), elt_type, Builder); - Imag = Mem2Reg(Builder.CreateExtractValue(Complex, 1), elt_type, Builder); -} - - -//===----------------------------------------------------------------------===// -// ... L-Value Expressions ... -//===----------------------------------------------------------------------===// - -Value *TreeToLLVM::EmitFieldAnnotation(Value *FieldPtr, tree FieldDecl) { - tree AnnotateAttr = lookup_attribute("annotate", DECL_ATTRIBUTES(FieldDecl)); - - const Type *SBP = Type::getInt8PtrTy(Context); - - Function *Fn = Intrinsic::getDeclaration(TheModule, - Intrinsic::ptr_annotation, - &SBP, 1); - - // Get file and line number. FIXME: Should this be for the decl or the - // use. Is there a location info for the use? - Constant *LineNo = ConstantInt::get(Type::getInt32Ty(Context), - DECL_SOURCE_LINE(FieldDecl)); - Constant *File = ConvertMetadataStringToGV(DECL_SOURCE_FILE(FieldDecl)); - - File = TheFolder->CreateBitCast(File, SBP); - - // There may be multiple annotate attributes. Pass return of lookup_attr - // to successive lookups. - while (AnnotateAttr) { - // Each annotate attribute is a tree list. - // Get value of list which is our linked list of args. - tree args = TREE_VALUE(AnnotateAttr); - - // Each annotate attribute may have multiple args. - // Treat each arg as if it were a separate annotate attribute. - for (tree a = args; a; a = TREE_CHAIN(a)) { - // Each element of the arg list is a tree list, so get value - tree val = TREE_VALUE(a); - - // Assert its a string, and then get that string. - assert(TREE_CODE(val) == STRING_CST && - "Annotate attribute arg should always be a string"); - - Constant *strGV = AddressOf(val); - - // We can not use the IRBuilder because it will constant fold away - // the GEP that is critical to distinguish between an annotate - // attribute on a whole struct from one on the first element of the - // struct. - BitCastInst *CastFieldPtr = new BitCastInst(FieldPtr, SBP, - FieldPtr->getName()); - Builder.Insert(CastFieldPtr); - - Value *Ops[4] = { - CastFieldPtr, Builder.CreateBitCast(strGV, SBP), - File, LineNo - }; - - const Type* FieldPtrType = FieldPtr->getType(); - FieldPtr = Builder.CreateCall(Fn, Ops, Ops+4); - FieldPtr = Builder.CreateBitCast(FieldPtr, FieldPtrType); - } - - // Get next annotate attribute. - AnnotateAttr = TREE_CHAIN(AnnotateAttr); - if (AnnotateAttr) - AnnotateAttr = lookup_attribute("annotate", AnnotateAttr); - } - return FieldPtr; -} - -LValue TreeToLLVM::EmitLV_ARRAY_REF(tree exp) { - // The result type is an ElementTy* in the case of an ARRAY_REF, an array - // of ElementTy in the case of ARRAY_RANGE_REF. - - tree Array = TREE_OPERAND(exp, 0); - tree ArrayTreeType = TREE_TYPE(Array); - tree Index = TREE_OPERAND(exp, 1); - tree IndexType = TREE_TYPE(Index); - tree ElementType = TREE_TYPE(ArrayTreeType); - - assert(TREE_CODE (ArrayTreeType) == ARRAY_TYPE && "Unknown ARRAY_REF!"); - - Value *ArrayAddr; - unsigned ArrayAlign; - - // First subtract the lower bound, if any, in the type of the index. - Value *IndexVal = EmitRegister(Index); - tree LowerBound = array_ref_low_bound(exp); - if (!integer_zerop(LowerBound)) - IndexVal = Builder.CreateSub(IndexVal, EmitRegister(LowerBound), "", - hasNUW(TREE_TYPE(Index)), - hasNSW(TREE_TYPE(Index))); - - LValue ArrayAddrLV = EmitLV(Array); - assert(!ArrayAddrLV.isBitfield() && "Arrays cannot be bitfields!"); - ArrayAddr = ArrayAddrLV.Ptr; - ArrayAlign = ArrayAddrLV.getAlignment(); - - const Type *IntPtrTy = getTargetData().getIntPtrType(Context); - IndexVal = Builder.CreateIntCast(IndexVal, IntPtrTy, - /*isSigned*/!TYPE_UNSIGNED(IndexType)); - - // If we are indexing over a fixed-size type, just use a GEP. - if (isSequentialCompatible(ArrayTreeType)) { - // Avoid any assumptions about how the array type is represented in LLVM by - // doing the GEP on a pointer to the first array element. - const Type *EltTy = ConvertType(ElementType); - ArrayAddr = Builder.CreateBitCast(ArrayAddr, EltTy->getPointerTo()); - Value *Ptr = POINTER_TYPE_OVERFLOW_UNDEFINED ? - Builder.CreateInBoundsGEP(ArrayAddr, IndexVal) : - Builder.CreateGEP(ArrayAddr, IndexVal); - unsigned Alignment = MinAlign(ArrayAlign, TD.getABITypeAlignment(EltTy)); - return LValue(Builder.CreateBitCast(Ptr, - PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))), - Alignment); - } - - // Otherwise, just do raw, low-level pointer arithmetic. FIXME: this could be - // much nicer in cases like: - // float foo(int w, float A[][w], int g) { return A[g][0]; } - - if (VOID_TYPE_P(TREE_TYPE(ArrayTreeType))) { - ArrayAddr = Builder.CreateBitCast(ArrayAddr, Type::getInt8PtrTy(Context)); - ArrayAddr = POINTER_TYPE_OVERFLOW_UNDEFINED ? - Builder.CreateInBoundsGEP(ArrayAddr, IndexVal) : - Builder.CreateGEP(ArrayAddr, IndexVal); - return LValue(ArrayAddr, 1); - } - - // FIXME: Might also get here if the element type has constant size, but is - // humongous. Add support for this case. - assert(TREE_OPERAND(exp, 3) && "Size missing for variable sized element!"); - // ScaleFactor is the size of the element type in units divided by (exactly) - // TYPE_ALIGN_UNIT(ElementType). - Value *ScaleFactor = Builder.CreateIntCast(EmitRegister(TREE_OPERAND(exp, 3)), - IntPtrTy, /*isSigned*/false); - assert(isPowerOf2_32(TYPE_ALIGN(ElementType)) && - "Alignment not a power of two!"); - assert(TYPE_ALIGN(ElementType) >= 8 && "Unit size not a multiple of 8 bits!"); - // ScaleType is chosen to correct for the division in ScaleFactor. - const Type *ScaleType = IntegerType::get(Context, TYPE_ALIGN(ElementType)); - ArrayAddr = Builder.CreateBitCast(ArrayAddr, ScaleType->getPointerTo()); - - IndexVal = Builder.CreateMul(IndexVal, ScaleFactor); - unsigned Alignment = MinAlign(ArrayAlign, TYPE_ALIGN(ElementType) / 8); - Value *Ptr = POINTER_TYPE_OVERFLOW_UNDEFINED ? - Builder.CreateInBoundsGEP(ArrayAddr, IndexVal) : - Builder.CreateGEP(ArrayAddr, IndexVal); - return LValue(Builder.CreateBitCast(Ptr, - PointerType::getUnqual(ConvertType(TREE_TYPE(exp)))), - Alignment); -} - -LValue TreeToLLVM::EmitLV_BIT_FIELD_REF(tree exp) { - LValue Ptr = EmitLV(TREE_OPERAND(exp, 0)); - assert(!Ptr.isBitfield() && "BIT_FIELD_REF operands cannot be bitfields!"); - - unsigned BitStart = (unsigned)TREE_INT_CST_LOW(TREE_OPERAND(exp, 2)); - unsigned BitSize = (unsigned)TREE_INT_CST_LOW(TREE_OPERAND(exp, 1)); - const Type *ValTy = ConvertType(TREE_TYPE(exp)); - - unsigned ValueSizeInBits = TD.getTypeSizeInBits(ValTy); - assert(BitSize <= ValueSizeInBits && - "ValTy isn't large enough to hold the value loaded!"); - - assert(ValueSizeInBits == TD.getTypeAllocSizeInBits(ValTy) && - "FIXME: BIT_FIELD_REF logic is broken for non-round types"); - - // BIT_FIELD_REF values can have BitStart values that are quite large. We - // know that the thing we are loading is ValueSizeInBits large. If BitStart - // is larger than ValueSizeInBits, bump the pointer over to where it should - // be. - if (unsigned UnitOffset = BitStart / ValueSizeInBits) { - // TODO: If Ptr.Ptr is a struct type or something, we can do much better - // than this. e.g. check out when compiling unwind-dw2-fde-darwin.c. - Ptr.Ptr = Builder.CreateBitCast(Ptr.Ptr, ValTy->getPointerTo()); - Ptr.Ptr = Builder.CreateGEP(Ptr.Ptr, - ConstantInt::get(Type::getInt32Ty(Context), - UnitOffset)); - BitStart -= UnitOffset*ValueSizeInBits; - } - - // If this is referring to the whole field, return the whole thing. - if (BitStart == 0 && BitSize == ValueSizeInBits) { - return LValue(Builder.CreateBitCast(Ptr.Ptr, ValTy->getPointerTo()), - Ptr.getAlignment()); - } - - return LValue(Builder.CreateBitCast(Ptr.Ptr, ValTy->getPointerTo()), - 1, BitStart, BitSize); -} - -LValue TreeToLLVM::EmitLV_COMPONENT_REF(tree exp) { - LValue StructAddrLV = EmitLV(TREE_OPERAND(exp, 0)); - tree FieldDecl = TREE_OPERAND(exp, 1); - unsigned LVAlign = StructAddrLV.getAlignment(); - - assert((TREE_CODE(DECL_CONTEXT(FieldDecl)) == RECORD_TYPE || - TREE_CODE(DECL_CONTEXT(FieldDecl)) == UNION_TYPE || - TREE_CODE(DECL_CONTEXT(FieldDecl)) == QUAL_UNION_TYPE)); - - const Type *StructTy = ConvertType(DECL_CONTEXT(FieldDecl)); - - assert((!StructAddrLV.isBitfield() || - StructAddrLV.BitStart == 0) && "structs cannot be bitfields!"); - - StructAddrLV.Ptr = Builder.CreateBitCast(StructAddrLV.Ptr, - StructTy->getPointerTo()); - const Type *FieldTy = ConvertType(TREE_TYPE(FieldDecl)); - - // BitStart - This is the actual offset of the field from the start of the - // struct, in bits. For bitfields this may be on a non-byte boundary. - unsigned BitStart; - Value *FieldPtr; - - // If the GCC field directly corresponds to an LLVM field, handle it. - unsigned MemberIndex = GetFieldIndex(FieldDecl, StructTy); - if (MemberIndex < INT_MAX) { - assert(!TREE_OPERAND(exp, 2) && "Constant not gimple min invariant?"); - // Get a pointer to the byte in which the GCC field starts. - FieldPtr = Builder.CreateStructGEP(StructAddrLV.Ptr, MemberIndex); - // Within that byte, the bit at which the GCC field starts. - BitStart = TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(TREE_OPERAND(exp, 1))); - BitStart &= 7; - } else { - // Offset will hold the field offset in octets. - Value *Offset; - - assert(!(BITS_PER_UNIT & 7) && "Unit size not a multiple of 8 bits!"); - if (TREE_OPERAND(exp, 2)) { - Offset = EmitRegister(TREE_OPERAND(exp, 2)); - // At this point the offset is measured in units divided by (exactly) - // (DECL_OFFSET_ALIGN / BITS_PER_UNIT). Convert to octets. - unsigned factor = DECL_OFFSET_ALIGN(FieldDecl) / 8; - if (factor != 1) - Offset = Builder.CreateMul(Offset, - ConstantInt::get(Offset->getType(), factor)); - } else { - assert(DECL_FIELD_OFFSET(FieldDecl) && "Field offset not available!"); - Offset = EmitRegister(DECL_FIELD_OFFSET(FieldDecl)); - // At this point the offset is measured in units. Convert to octets. - unsigned factor = BITS_PER_UNIT / 8; - if (factor != 1) - Offset = Builder.CreateMul(Offset, - ConstantInt::get(Offset->getType(), factor)); - } - - // Here BitStart gives the offset of the field in bits from Offset. - BitStart = getInt64(DECL_FIELD_BIT_OFFSET(FieldDecl), true); - - // Incorporate as much of it as possible into the pointer computation. - unsigned ByteOffset = BitStart / 8; - if (ByteOffset > 0) { - Offset = Builder.CreateAdd(Offset, - ConstantInt::get(Offset->getType(), ByteOffset)); - BitStart -= ByteOffset*8; - } - - const Type *BytePtrTy = Type::getInt8PtrTy(Context); - FieldPtr = Builder.CreateBitCast(StructAddrLV.Ptr, BytePtrTy); - FieldPtr = Builder.CreateInBoundsGEP(FieldPtr, Offset); - FieldPtr = Builder.CreateBitCast(FieldPtr, FieldTy->getPointerTo()); - } - - assert(BitStart < 8 && "Bit offset not properly incorporated in the pointer"); - - // The alignment is given by DECL_ALIGN. Be conservative and don't assume - // that the field is properly aligned even if the type is not. - LVAlign = MinAlign(LVAlign, DECL_ALIGN(FieldDecl) / 8); - - // If the FIELD_DECL has an annotate attribute on it, emit it. - if (lookup_attribute("annotate", DECL_ATTRIBUTES(FieldDecl))) - FieldPtr = EmitFieldAnnotation(FieldPtr, FieldDecl); - - if (!isBitfield(FieldDecl)) { - assert(BitStart == 0 && "Not a bitfield but not at a byte offset!"); - // Make sure we return a pointer to the right type. - const Type *EltTy = ConvertType(TREE_TYPE(exp)); - FieldPtr = Builder.CreateBitCast(FieldPtr, EltTy->getPointerTo()); - return LValue(FieldPtr, LVAlign); - } - - // If this is a bitfield, the declared type must be an integral type. - assert(FieldTy->isIntegerTy() && "Invalid bitfield"); - - assert(DECL_SIZE(FieldDecl) && - TREE_CODE(DECL_SIZE(FieldDecl)) == INTEGER_CST && - "Variable sized bitfield?"); - unsigned BitfieldSize = TREE_INT_CST_LOW(DECL_SIZE(FieldDecl)); - - const Type *LLVMFieldTy = - cast(FieldPtr->getType())->getElementType(); - - // If the LLVM notion of the field type contains the entire bitfield being - // accessed, use the LLVM type. This avoids pointer casts and other bad - // things that are difficult to clean up later. This occurs in cases like - // "struct X{ unsigned long long x:50; unsigned y:2; }" when accessing y. - // We want to access the field as a ulong, not as a uint with an offset. - if (LLVMFieldTy->isIntegerTy() && - LLVMFieldTy->getPrimitiveSizeInBits() >= BitStart + BitfieldSize && - LLVMFieldTy->getPrimitiveSizeInBits() == - TD.getTypeAllocSizeInBits(LLVMFieldTy)) - FieldTy = LLVMFieldTy; - else - // If the field result type T is a bool or some other curiously sized - // integer type, then not all bits may be accessible by advancing a T* - // and loading through it. For example, if the result type is i1 then - // only the first bit in each byte would be loaded. Even if T is byte - // sized like an i24 there may be trouble: incrementing a T* will move - // the position by 32 bits not 24, leaving the upper 8 of those 32 bits - // inaccessible. Avoid this by rounding up the size appropriately. - FieldTy = IntegerType::get(Context, TD.getTypeAllocSizeInBits(FieldTy)); - - assert(FieldTy->getPrimitiveSizeInBits() == - TD.getTypeAllocSizeInBits(FieldTy) && "Field type not sequential!"); - - // If this is a bitfield, the field may span multiple fields in the LLVM - // type. As such, cast the pointer to be a pointer to the declared type. - FieldPtr = Builder.CreateBitCast(FieldPtr, FieldTy->getPointerTo()); - - unsigned LLVMValueBitSize = FieldTy->getPrimitiveSizeInBits(); - // Finally, because bitfields can span LLVM fields, and because the start - // of the first LLVM field (where FieldPtr currently points) may be up to - // 63 bits away from the start of the bitfield), it is possible that - // *FieldPtr doesn't contain any of the bits for this bitfield. If needed, - // adjust FieldPtr so that it is close enough to the bitfield that - // *FieldPtr contains the first needed bit. Be careful to make sure that - // the pointer remains appropriately aligned. - if (BitStart >= LLVMValueBitSize) { - // In this case, we know that the alignment of the field is less than - // the size of the field. To get the pointer close enough, add some - // number of alignment units to the pointer. - unsigned ByteAlignment = TD.getABITypeAlignment(FieldTy); - // It is possible that an individual field is Packed. This information is - // not reflected in FieldTy. Check DECL_PACKED here. - if (DECL_PACKED(FieldDecl)) - ByteAlignment = 1; - assert(ByteAlignment*8 <= LLVMValueBitSize && "Unknown overlap case!"); - unsigned NumAlignmentUnits = BitStart/(ByteAlignment*8); - assert(NumAlignmentUnits && "Not adjusting pointer?"); - - // Compute the byte offset, and add it to the pointer. - unsigned ByteOffset = NumAlignmentUnits*ByteAlignment; - LVAlign = MinAlign(LVAlign, ByteOffset); - - Constant *Offset = ConstantInt::get(TD.getIntPtrType(Context), ByteOffset); - FieldPtr = Builder.CreatePtrToInt(FieldPtr, Offset->getType()); - FieldPtr = Builder.CreateAdd(FieldPtr, Offset); - FieldPtr = Builder.CreateIntToPtr(FieldPtr, FieldTy->getPointerTo()); - - // Adjust bitstart to account for the pointer movement. - BitStart -= ByteOffset*8; - - // Check that this worked. Note that the bitfield may extend beyond - // the end of *FieldPtr, for example because BitfieldSize is the same - // as LLVMValueBitSize but BitStart > 0. - assert(BitStart < LLVMValueBitSize && - BitStart+BitfieldSize < 2*LLVMValueBitSize && - "Couldn't get bitfield into value!"); - } - - // Okay, everything is good. Return this as a bitfield if we can't - // return it as a normal l-value. (e.g. "struct X { int X : 32 };" ). - LValue LV(FieldPtr, LVAlign); - if (BitfieldSize != LLVMValueBitSize || BitStart != 0) { - // Writing these fields directly rather than using the appropriate LValue - // constructor works around a miscompilation by gcc-4.4 in Release mode. - LV.BitStart = BitStart; - LV.BitSize = BitfieldSize; - } - return LV; -} - -LValue TreeToLLVM::EmitLV_DECL(tree exp) { - Value *Decl = DEFINITION_LOCAL(exp); - if (Decl == 0) { - if (errorcount || sorrycount) { - const Type *Ty = ConvertType(TREE_TYPE(exp)); - const PointerType *PTy = Ty->getPointerTo(); - LValue LV(ConstantPointerNull::get(PTy), 1); - return LV; - } - DieAbjectly("Referencing decl that hasn't been laid out!", exp); - } - - const Type *Ty = ConvertType(TREE_TYPE(exp)); - // If we have "extern void foo", make the global have type {} instead of - // type void. - if (Ty->isVoidTy()) Ty = StructType::get(Context); - const PointerType *PTy = Ty->getPointerTo(); - unsigned Alignment = Ty->isSized() ? TD.getABITypeAlignment(Ty) : 1; - if (DECL_ALIGN(exp)) { - if (DECL_USER_ALIGN(exp) || 8 * Alignment < (unsigned)DECL_ALIGN(exp)) - Alignment = DECL_ALIGN(exp) / 8; - } - - return LValue(Builder.CreateBitCast(Decl, PTy), Alignment); -} - -LValue TreeToLLVM::EmitLV_INDIRECT_REF(tree exp) { - // The lvalue is just the address. - LValue LV = LValue(EmitRegister(TREE_OPERAND(exp, 0)), expr_align(exp) / 8); - // May need a useless type conversion (useless_type_conversion_p), for example - // when INDIRECT_REF is applied to a void*, resulting in a non-void type. - LV.Ptr = UselesslyTypeConvert(LV.Ptr, - ConvertType(TREE_TYPE(exp))->getPointerTo()); - return LV; -} - -LValue TreeToLLVM::EmitLV_VIEW_CONVERT_EXPR(tree exp) { - // The address is the address of the operand. - LValue LV = EmitLV(TREE_OPERAND(exp, 0)); - // The type is the type of the expression. - LV.Ptr = Builder.CreateBitCast(LV.Ptr, - ConvertType(TREE_TYPE(exp))->getPointerTo()); - return LV; -} - -LValue TreeToLLVM::EmitLV_WITH_SIZE_EXPR(tree exp) { - // The address is the address of the operand. - return EmitLV(TREE_OPERAND(exp, 0)); -} - -LValue TreeToLLVM::EmitLV_XXXXPART_EXPR(tree exp, unsigned Idx) { - LValue Ptr = EmitLV(TREE_OPERAND(exp, 0)); - assert(!Ptr.isBitfield() && - "REALPART_EXPR / IMAGPART_EXPR operands cannot be bitfields!"); - unsigned Alignment; - if (Idx == 0) - // REALPART alignment is same as the complex operand. - Alignment = Ptr.getAlignment(); - else - // IMAGPART alignment = MinAlign(Ptr.Alignment, sizeof field); - Alignment = MinAlign(Ptr.getAlignment(), - TD.getTypeAllocSize(Ptr.Ptr->getType())); - return LValue(Builder.CreateStructGEP(Ptr.Ptr, Idx), Alignment); -} - -LValue TreeToLLVM::EmitLV_SSA_NAME(tree exp) { - // TODO: Check the ssa name is being used as an rvalue, see EmitLoadOfLValue. - Value *Temp = CreateTemporary(ConvertType(TREE_TYPE(exp))); - Builder.CreateStore(EmitReg_SSA_NAME(exp), Temp); - return LValue(Temp, 1); -} - -LValue TreeToLLVM::EmitLV_TARGET_MEM_REF(tree exp) { - // TODO: Take the address space into account. - // TODO: Improve the alignment estimate. - struct mem_address addr; - get_address_description (exp, &addr); - - LValue Ref; - Value *Delta = 0; // Offset from base pointer in units - if (addr.symbol) { - Ref = EmitLV(addr.symbol); - if (addr.base && !integer_zerop (addr.base)) - Delta = EmitRegister(addr.base); - } else { - assert(addr.base && "TARGET_MEM_REF has neither base nor symbol!"); - Ref = LValue(EmitRegister(addr.base), 1); - } - - if (addr.index) { - Value *Index = EmitRegister(addr.index); - if (addr.step && !integer_onep (addr.step)) - Index = Builder.CreateMul(Index, EmitRegisterConstant(addr.step)); - Delta = Delta ? Builder.CreateAdd(Delta, Index) : Index; - } - - if (addr.offset && !integer_zerop (addr.offset)) { - Constant *Offset = EmitRegisterConstant(addr.offset); - Delta = Delta ? Builder.CreateAdd(Delta, Offset) : Offset; - } - - if (Delta) { - // Advance the base pointer by the given number of units. - Ref.Ptr = Builder.CreateBitCast(Ref.Ptr, GetUnitPointerType(Context)); - Ref.Ptr = POINTER_TYPE_OVERFLOW_UNDEFINED ? - Builder.CreateInBoundsGEP(Ref.Ptr, Delta) - : Builder.CreateGEP(Ref.Ptr, Delta); - Ref.setAlignment(1); // Let the optimizers compute the alignment. - } - - // The result can be of a different pointer type even if we didn't advance it. - Ref.Ptr = UselesslyTypeConvert(Ref.Ptr, - GetRegType(TREE_TYPE(exp))->getPointerTo()); - - return Ref; -} - -Constant *TreeToLLVM::AddressOfLABEL_DECL(tree exp) { - return BlockAddress::get(Fn, getLabelDeclBlock(exp)); -} - - -//===----------------------------------------------------------------------===// -// ... Emit helpers ... -//===----------------------------------------------------------------------===// - -/// EmitMinInvariant - The given value is constant in this function. Return the -/// corresponding LLVM value. Only creates code in the entry block. -Value *TreeToLLVM::EmitMinInvariant(tree reg) { - Value *V = (TREE_CODE(reg) == ADDR_EXPR) ? - EmitInvariantAddress(reg) : EmitRegisterConstant(reg); - assert(V->getType() == GetRegType(TREE_TYPE(reg)) && - "Gimple min invariant has wrong type!"); - return V; -} - -/// EmitInvariantAddress - The given address is constant in this function. -/// Return the corresponding LLVM value. Only creates code in the entry block. -Value *TreeToLLVM::EmitInvariantAddress(tree addr) { - assert(is_gimple_invariant_address(addr) && - "Expected a locally constant address!"); - assert(is_gimple_reg_type(TREE_TYPE(addr)) && "Not of register type!"); - - // Any generated code goes in the entry block. - BasicBlock *EntryBlock = Fn->begin(); - - // Note the current builder position. - BasicBlock *SavedInsertBB = Builder.GetInsertBlock(); - BasicBlock::iterator SavedInsertPoint = Builder.GetInsertPoint(); - - // Pop the entry block terminator. There may not be a terminator if we are - // recursing or if the entry block was not yet finished. - Instruction *Terminator = EntryBlock->getTerminator(); - assert(((SavedInsertBB != EntryBlock && Terminator) || - (SavedInsertPoint == EntryBlock->end() && !Terminator)) && - "Insertion point doesn't make sense!"); - if (Terminator) - Terminator->removeFromParent(); - - // Point the builder at the end of the entry block. - Builder.SetInsertPoint(EntryBlock); - - // Calculate the address. - assert(TREE_CODE(addr) == ADDR_EXPR && "Invariant address not ADDR_EXPR!"); - Value *Address = EmitADDR_EXPR(addr); - - // Restore the entry block terminator. - if (Terminator) - EntryBlock->getInstList().push_back(Terminator); - - // Restore the builder insertion point. - if (SavedInsertBB != EntryBlock) - Builder.SetInsertPoint(SavedInsertBB, SavedInsertPoint); - - assert(Address->getType() == GetRegType(TREE_TYPE(addr)) && - "Invariant address has wrong type!"); - return Address; -} - -/// EmitRegisterConstant - Convert the given global constant of register type to -/// an LLVM constant. Creates no code, only constants. -Constant *TreeToLLVM::EmitRegisterConstant(tree reg) { -#ifndef NDEBUG - if (!is_gimple_constant(reg)) - DieAbjectly("Not a gimple constant!", reg); -#endif - assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!"); - - switch (TREE_CODE(reg)) { - default: - DieAbjectly("Unhandled GIMPLE constant!", reg); - - case INTEGER_CST: - return EmitIntegerRegisterConstant(reg); - case REAL_CST: - return EmitRealRegisterConstant(reg); - //case FIXED_CST: // Fixed point constant - not yet supported. - //case STRING_CST: // Allowed by is_gimple_constant, but no known examples. - case COMPLEX_CST: - return EmitComplexRegisterConstant(reg); - case VECTOR_CST: - return EmitVectorRegisterConstant(reg); - case CONSTRUCTOR: - // Vector constant constructors are gimple invariant. See GCC testcase - // pr34856.c for an example. - return EmitConstantVectorConstructor(reg); - } -} - -/// EncodeExpr - Write the given expression into Buffer as it would appear in -/// memory on the target (the buffer is resized to contain exactly the bytes -/// written). Return the number of bytes written; this can also be obtained -/// by querying the buffer's size. -/// The following kinds of expressions are currently supported: INTEGER_CST, -/// REAL_CST, COMPLEX_CST, VECTOR_CST, STRING_CST. -static unsigned EncodeExpr(tree exp, SmallVectorImpl &Buffer) { - const tree type = TREE_TYPE(exp); - unsigned SizeInBytes = (TREE_INT_CST_LOW(TYPE_SIZE(type)) + 7) / 8; - Buffer.resize(SizeInBytes); - unsigned BytesWritten = native_encode_expr(exp, &Buffer[0], SizeInBytes); - assert(BytesWritten == SizeInBytes && "Failed to fully encode expression!"); - return BytesWritten; -} - -/// EmitComplexRegisterConstant - Turn the given COMPLEX_CST into an LLVM -/// constant of the corresponding register type. -Constant *TreeToLLVM::EmitComplexRegisterConstant(tree reg) { - Constant *Elts[2] = { - EmitRegisterConstant(TREE_REALPART(reg)), - EmitRegisterConstant(TREE_IMAGPART(reg)) - }; - return ConstantStruct::get(Context, Elts, 2, false); -} - -/// EmitIntegerRegisterConstant - Turn the given INTEGER_CST into an LLVM -/// constant of the corresponding register type. -Constant *TreeToLLVM::EmitIntegerRegisterConstant(tree reg) { - unsigned Precision = TYPE_PRECISION(TREE_TYPE(reg)); - - ConstantInt *CI; - if (HOST_BITS_PER_WIDE_INT < integerPartWidth) { - assert(2 * HOST_BITS_PER_WIDE_INT <= integerPartWidth && - "Unsupported host integer precision!"); - unsigned ShiftAmt = HOST_BITS_PER_WIDE_INT; - integerPart Val = (integerPart)(unsigned HOST_WIDE_INT)TREE_INT_CST_LOW(reg) - + ((integerPart)(unsigned HOST_WIDE_INT)TREE_INT_CST_HIGH(reg) << ShiftAmt); - CI = ConstantInt::get(Context, APInt(Precision, Val)); - } else { - assert(HOST_BITS_PER_WIDE_INT == integerPartWidth && - "The engines cannae' take it captain!"); - integerPart Parts[] = { TREE_INT_CST_LOW(reg), TREE_INT_CST_HIGH(reg) }; - CI = ConstantInt::get(Context, APInt(Precision, 2, Parts)); - } - - // The destination can be a pointer, integer or floating point type so we need - // a generalized cast here - const Type *Ty = GetRegType(TREE_TYPE(reg)); - Instruction::CastOps opcode = CastInst::getCastOpcode(CI, false, Ty, - !TYPE_UNSIGNED(TREE_TYPE(reg))); - return TheFolder->CreateCast(opcode, CI, Ty); -} - -/// EmitRealRegisterConstant - Turn the given REAL_CST into an LLVM constant -/// of the corresponding register type. -Constant *TreeToLLVM::EmitRealRegisterConstant(tree reg) { - // TODO: Rather than going through memory, construct the APFloat directly from - // the real_value. This works fine for zero, inf and nan values, but APFloat - // has no constructor for normal numbers, i.e. constructing a normal number - // from the exponent and significand. - // TODO: Test implementation on a big-endian machine. - - // Encode the constant in Buffer in target format. - SmallVector Buffer; - EncodeExpr(reg, Buffer); - - // Discard any alignment padding, which we assume comes at the end. - unsigned Precision = TYPE_PRECISION(TREE_TYPE(reg)); - assert((Precision & 7) == 0 && "Unsupported real number precision!"); - Buffer.resize(Precision / 8); - - // We are going to view the buffer as an array of APInt words. Ensure that - // the buffer contains a whole number of words by extending it if necessary. - unsigned Words = (Precision + integerPartWidth - 1) / integerPartWidth; - // On a little-endian machine extend the buffer by adding bytes to the end. - Buffer.resize(Words * (integerPartWidth / 8)); - // On a big-endian machine extend the buffer by adding bytes to the beginning. - if (BYTES_BIG_ENDIAN) - std::copy_backward(Buffer.begin(), Buffer.begin() + Precision / 8, - Buffer.end()); - - // Ensure that the least significant word comes first: we are going to make an - // APInt, and the APInt constructor wants the least significant word first. - integerPart *Parts = (integerPart *)&Buffer[0]; - if (BYTES_BIG_ENDIAN) - std::reverse(Parts, Parts + Words); - - bool isPPC_FP128 = ConvertType(TREE_TYPE(reg))->isPPC_FP128Ty(); - if (isPPC_FP128) { - // This type is actually a pair of doubles in disguise. They turn up the - // wrong way round here, so flip them. - assert(FLOAT_WORDS_BIG_ENDIAN && "PPC not big endian!"); - assert(Words == 2 && Precision == 128 && "Strange size for PPC_FP128!"); - std::swap(Parts[0], Parts[1]); - } - - // Form an APInt from the buffer, an APFloat from the APInt, and the desired - // floating point constant from the APFloat, phew! - const APInt &I = APInt(Precision, Words, Parts); - return ConstantFP::get(Context, APFloat(I, !isPPC_FP128)); -} - -/// EmitConstantVectorConstructor - Turn the given constant CONSTRUCTOR into -/// an LLVM constant of the corresponding vector register type. -Constant *TreeToLLVM::EmitConstantVectorConstructor(tree reg) { - // Get the constructor as an LLVM constant. - Constant *C = ConvertInitializer(reg); - // The constant may have pretty much any type, for example it could be a bunch - // of bytes. Extract the vector elements from the constant. - tree elt_type = TREE_TYPE (TREE_TYPE (reg)); - const Type *EltTy = GetRegType(elt_type); - unsigned NumElts = TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg)); - // Get the spacing between consecutive vector elements. Obtain this from the - // GCC type in case the LLVM type is something funky like i1. - unsigned Stride = GET_MODE_BITSIZE (TYPE_MODE (elt_type)); - SmallVector Vals(NumElts); - for (unsigned i = 0; i != NumElts; ++i) - Vals[i] = InterpretAsType(C, EltTy, i*Stride); - return ConstantVector::get(Vals); -} - -/// EmitVectorRegisterConstant - Turn the given VECTOR_CST into an LLVM constant -/// of the corresponding register type. -Constant *TreeToLLVM::EmitVectorRegisterConstant(tree reg) { - // If there are no elements then immediately return the default value for a - // small speedup. - if (!TREE_VECTOR_CST_ELTS(reg)) - return getDefaultValue(GetRegType(TREE_TYPE(reg))); - - // Convert the elements. - SmallVector Elts; - for (tree elt = TREE_VECTOR_CST_ELTS(reg); elt; elt = TREE_CHAIN(elt)) - Elts.push_back(EmitRegisterConstant(TREE_VALUE(elt))); - - // If there weren't enough elements then set the rest of the vector to the - // default value. - if (Elts.size() < TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg))) { - Constant *Default = getDefaultValue(GetRegType(TREE_TYPE(TREE_TYPE(reg)))); - Elts.append(TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg)) - Elts.size(), Default); - } - - return ConstantVector::get(Elts); -} - -/// Mem2Reg - Convert a value of in-memory type (that given by ConvertType) -/// to in-register type (that given by GetRegType). -Value *TreeToLLVM::Mem2Reg(Value *V, tree type, LLVMBuilder &Builder) { - const Type *MemTy = V->getType(); - const Type *RegTy = GetRegType(type); - assert(MemTy == ConvertType(type) && "Not of memory type!"); - - if (MemTy == RegTy) - return V; - - assert(RegTy->isIntegerTy() && MemTy->isIntegerTy() && - "Unexpected type mismatch!"); - return Builder.CreateIntCast(V, RegTy, /*isSigned*/!TYPE_UNSIGNED(type)); -} -Constant *TreeToLLVM::Mem2Reg(Constant *C, tree type, TargetFolder &Folder) { - const Type *MemTy = C->getType(); - const Type *RegTy = GetRegType(type); - assert(MemTy == ConvertType(type) && "Not of memory type!"); - - if (MemTy == RegTy) - return C; - - assert(RegTy->isIntegerTy() && MemTy->isIntegerTy() && - "Unexpected type mismatch!"); - return Folder.CreateIntCast(C, RegTy, /*isSigned*/!TYPE_UNSIGNED(type)); -} - -/// Reg2Mem - Convert a value of in-register type (that given by GetRegType) -/// to in-memory type (that given by ConvertType). -Value *TreeToLLVM::Reg2Mem(Value *V, tree type, LLVMBuilder &Builder) { - const Type *RegTy = V->getType(); - const Type *MemTy = ConvertType(type); - assert(RegTy == GetRegType(type) && "Not of register type!"); - - if (RegTy == MemTy) - return V; - - assert(RegTy->isIntegerTy() && MemTy->isIntegerTy() && - "Unexpected type mismatch!"); - return Builder.CreateIntCast(V, MemTy, /*isSigned*/!TYPE_UNSIGNED(type)); -} - -/// LoadRegisterFromMemory - Loads a value of the given scalar GCC type from -/// the memory location pointed to by Loc. Takes care of adjusting for any -/// differences between in-memory and in-register types (the returned value -/// is of in-register type, as returned by GetRegType). -Value *TreeToLLVM::LoadRegisterFromMemory(MemRef Loc, tree type, - LLVMBuilder &Builder) { - const Type *MemTy = ConvertType(type); - Value *Ptr = Builder.CreateBitCast(Loc.Ptr, MemTy->getPointerTo()); - LoadInst *LI = Builder.CreateLoad(Ptr, Loc.Volatile); - LI->setAlignment(Loc.getAlignment()); - return Mem2Reg(LI, type, Builder); -} - -/// StoreRegisterToMemory - Stores the given value to the memory pointed to by -/// Loc. Takes care of adjusting for any differences between the value's type -/// (which is the in-register type given by GetRegType) and the in-memory type. -void TreeToLLVM::StoreRegisterToMemory(Value *V, MemRef Loc, tree type, - LLVMBuilder &Builder) { - const Type *MemTy = ConvertType(type); - Value *Ptr = Builder.CreateBitCast(Loc.Ptr, MemTy->getPointerTo()); - StoreInst *SI = Builder.CreateStore(Reg2Mem(V, type, Builder), Ptr, - Loc.Volatile); - SI->setAlignment(Loc.getAlignment()); -} - - -//===----------------------------------------------------------------------===// -// ... EmitReg* - Convert register expression to LLVM... -//===----------------------------------------------------------------------===// - -/// GetRegType - Returns the LLVM type to use for registers that hold a value -/// of the scalar GCC type 'type'. All of the EmitReg* routines use this to -/// determine the LLVM type to return. -const Type *TreeToLLVM::GetRegType(tree type) { - assert(!AGGREGATE_TYPE_P(type) && "Registers must have a scalar type!"); - assert(TREE_CODE(type) != VOID_TYPE && "Registers cannot have void type!"); - - // For integral types, convert based on the type precision. - if (TREE_CODE(type) == BOOLEAN_TYPE || TREE_CODE(type) == ENUMERAL_TYPE || - TREE_CODE(type) == INTEGER_TYPE) - return IntegerType::get(Context, TYPE_PRECISION(type)); - - // Otherwise, return the type used to represent memory. - return ConvertType(type); -} - -/// EmitMemory - Convert the specified gimple register or local constant of -/// register type to an LLVM value with in-memory type (given by ConvertType). -Value *TreeToLLVM::EmitMemory(tree reg) { - return Reg2Mem(EmitRegister(reg), TREE_TYPE(reg), Builder); -} - -/// EmitRegister - Convert the specified gimple register or local constant of -/// register type to an LLVM value. Only creates code in the entry block. -Value *TreeToLLVM::EmitRegister(tree reg) { - while (TREE_CODE(reg) == OBJ_TYPE_REF) reg = OBJ_TYPE_REF_EXPR(reg); - return (TREE_CODE(reg) == SSA_NAME) ? - EmitReg_SSA_NAME(reg) : EmitMinInvariant(reg); -} - -/// EmitReg_SSA_NAME - Return the defining value of the given SSA_NAME. -/// Only creates code in the entry block. -Value *TreeToLLVM::EmitReg_SSA_NAME(tree reg) { - assert(is_gimple_reg_type(TREE_TYPE(reg)) && "Not of register type!"); - - // If we already found the definition of the SSA name, return it. - if (Value *ExistingValue = SSANames[reg]) { - assert(ExistingValue->getType() == GetRegType(TREE_TYPE(reg)) && - "SSA name has wrong type!"); - if (!isSSAPlaceholder(ExistingValue)) - return ExistingValue; - } - - // If this is not the definition of the SSA name, return a placeholder value. - if (!SSA_NAME_IS_DEFAULT_DEF(reg)) { - if (Value *ExistingValue = SSANames[reg]) - return ExistingValue; // The type was sanity checked above. - return SSANames[reg] = GetSSAPlaceholder(GetRegType(TREE_TYPE(reg))); - } - - // This SSA name is the default definition for the underlying symbol. - - // The underlying symbol is an SSA variable. - tree var = SSA_NAME_VAR(reg); - assert(SSA_VAR_P(var) && "Not an SSA variable!"); - - // If the variable is itself an ssa name, use its LLVM value. - if (TREE_CODE (var) == SSA_NAME) { - Value *Val = EmitReg_SSA_NAME(var); - assert(Val->getType() == GetRegType(TREE_TYPE(reg)) && - "SSA name has wrong type!"); - return DefineSSAName(reg, Val); - } - - // Otherwise the symbol is a VAR_DECL, PARM_DECL or RESULT_DECL. Since a - // default definition is only created if the very first reference to the - // variable in the function is a read operation, and refers to the value - // read, it has an undefined value except for PARM_DECLs. - if (TREE_CODE(var) != PARM_DECL) - return DefineSSAName(reg, UndefValue::get(GetRegType(TREE_TYPE(reg)))); - - // Read the initial value of the parameter and associate it with the ssa name. - assert(DECL_LOCAL_IF_SET(var) && "Parameter not laid out?"); - - unsigned Alignment = DECL_ALIGN(var); - assert(Alignment != 0 && "Parameter with unknown alignment!"); - - // Perform the load in the entry block, after all parameters have been set up - // with their initial values, and before any modifications to their values. - - // Create a builder that inserts code before the SSAInsertionPoint marker. - LLVMBuilder SSABuilder(Context, Builder.getFolder()); - SSABuilder.SetInsertPoint(SSAInsertionPoint->getParent(), SSAInsertionPoint); - - // Use it to load the parameter value. - MemRef ParamLoc(DECL_LOCAL_IF_SET(var), Alignment, false); - Value *Def = LoadRegisterFromMemory(ParamLoc, TREE_TYPE(reg), SSABuilder); - - if (flag_verbose_asm) - NameValue(Def, reg); - return DefineSSAName(reg, Def); -} - -// Unary expressions. -Value *TreeToLLVM::EmitReg_ABS_EXPR(tree op) { - if (!FLOAT_TYPE_P(TREE_TYPE(op))) { - Value *Op = EmitRegister(op); - Value *OpN = Builder.CreateNeg(Op, Op->getName()+"neg"); - ICmpInst::Predicate pred = TYPE_UNSIGNED(TREE_TYPE(op)) ? - ICmpInst::ICMP_UGE : ICmpInst::ICMP_SGE; - Value *Cmp = Builder.CreateICmp(pred, Op, - Constant::getNullValue(Op->getType()), "abscond"); - return Builder.CreateSelect(Cmp, Op, OpN, Op->getName()+"abs"); - } - - // Turn FP abs into fabs/fabsf. - StringRef Name = SelectFPName(TREE_TYPE(op), "fabsf", "fabs", "fabsl"); - CallInst *Call = EmitSimpleCall(Name, TREE_TYPE(op), op, NULL); - Call->setDoesNotThrow(); - Call->setDoesNotAccessMemory(); - return Call; -} - -Value *TreeToLLVM::EmitReg_BIT_NOT_EXPR(tree op) { - Value *Op = EmitRegister(op); - return Builder.CreateNot(Op, Op->getName()+"not"); -} - -Value *TreeToLLVM::EmitReg_CONJ_EXPR(tree op) { - tree elt_type = TREE_TYPE(TREE_TYPE(op)); - Value *R, *I; - SplitComplex(EmitRegister(op), R, I, elt_type); - - // ~(a+ib) = a + i*-b - I = CreateAnyNeg(I, elt_type); - - return CreateComplex(R, I, elt_type); -} - -Value *TreeToLLVM::EmitReg_CONVERT_EXPR(tree type, tree op) { - return CastToAnyType(EmitRegister(op), !TYPE_UNSIGNED(TREE_TYPE(op)), - GetRegType(type), !TYPE_UNSIGNED(type)); -} - -Value *TreeToLLVM::EmitReg_NEGATE_EXPR(tree op) { - Value *V = EmitRegister(op); - tree type = TREE_TYPE(op); - - if (TREE_CODE(type) == COMPLEX_TYPE) { - tree elt_type = TREE_TYPE(type); - Value *R, *I; SplitComplex(V, R, I, elt_type); - - // -(a+ib) = -a + i*-b - R = CreateAnyNeg(R, elt_type); - I = CreateAnyNeg(I, elt_type); - - return CreateComplex(R, I, elt_type); - } - - return CreateAnyNeg(V, type); -} - -Value *TreeToLLVM::EmitReg_PAREN_EXPR(tree op) { - // TODO: Understand and correctly deal with this subtle expression. - return EmitRegister(op); -} - -Value *TreeToLLVM::EmitReg_TRUTH_NOT_EXPR(tree type, tree op) { - Value *V = EmitRegister(op); - if (!V->getType()->isIntegerTy(1)) - V = Builder.CreateICmpNE(V, - Constant::getNullValue(V->getType()), "toBool"); - V = Builder.CreateNot(V, V->getName()+"not"); - return Builder.CreateIntCast(V, GetRegType(type), /*isSigned*/false); -} - -// Comparisons. - -/// EmitCompare - Compare LHS with RHS using the appropriate comparison code. -/// The result is an i1 boolean. -Value *TreeToLLVM::EmitCompare(tree lhs, tree rhs, unsigned code) { - Value *LHS = EmitRegister(lhs); - Value *RHS = UselesslyTypeConvert(EmitRegister(rhs), LHS->getType()); - - // Compute the LLVM opcodes corresponding to the GCC comparison. - CmpInst::Predicate UIPred = CmpInst::BAD_ICMP_PREDICATE; - CmpInst::Predicate SIPred = CmpInst::BAD_ICMP_PREDICATE; - CmpInst::Predicate FPPred = CmpInst::BAD_FCMP_PREDICATE; - - switch (code) { - default: - assert(false && "Unhandled condition code!"); - case LT_EXPR: - UIPred = CmpInst::ICMP_ULT; - SIPred = CmpInst::ICMP_SLT; - FPPred = CmpInst::FCMP_OLT; - break; - case LE_EXPR: - UIPred = CmpInst::ICMP_ULE; - SIPred = CmpInst::ICMP_SLE; - FPPred = CmpInst::FCMP_OLE; - break; - case GT_EXPR: - UIPred = CmpInst::ICMP_UGT; - SIPred = CmpInst::ICMP_SGT; - FPPred = CmpInst::FCMP_OGT; - break; - case GE_EXPR: - UIPred = CmpInst::ICMP_UGE; - SIPred = CmpInst::ICMP_SGE; - FPPred = CmpInst::FCMP_OGE; - break; - case EQ_EXPR: - UIPred = SIPred = CmpInst::ICMP_EQ; - FPPred = CmpInst::FCMP_OEQ; - break; - case NE_EXPR: - UIPred = SIPred = CmpInst::ICMP_NE; - FPPred = CmpInst::FCMP_UNE; - break; - case UNORDERED_EXPR: FPPred = CmpInst::FCMP_UNO; break; - case ORDERED_EXPR: FPPred = CmpInst::FCMP_ORD; break; - case UNLT_EXPR: FPPred = CmpInst::FCMP_ULT; break; - case UNLE_EXPR: FPPred = CmpInst::FCMP_ULE; break; - case UNGT_EXPR: FPPred = CmpInst::FCMP_UGT; break; - case UNGE_EXPR: FPPred = CmpInst::FCMP_UGE; break; - case UNEQ_EXPR: FPPred = CmpInst::FCMP_UEQ; break; - case LTGT_EXPR: FPPred = CmpInst::FCMP_ONE; break; - } - - if (TREE_CODE(TREE_TYPE(lhs)) == COMPLEX_TYPE) { - Value *LHSr, *LHSi; - SplitComplex(LHS, LHSr, LHSi, TREE_TYPE(TREE_TYPE(lhs))); - Value *RHSr, *RHSi; - SplitComplex(RHS, RHSr, RHSi, TREE_TYPE(TREE_TYPE(lhs))); - - Value *DSTr, *DSTi; - if (LHSr->getType()->isFloatingPointTy()) { - DSTr = Builder.CreateFCmp(FPPred, LHSr, RHSr); - DSTi = Builder.CreateFCmp(FPPred, LHSi, RHSi); - if (FPPred == CmpInst::FCMP_OEQ) - return Builder.CreateAnd(DSTr, DSTi); - assert(FPPred == CmpInst::FCMP_UNE && "Unhandled complex comparison!"); - return Builder.CreateOr(DSTr, DSTi); - } - - assert(SIPred == UIPred && "(In)equality comparison depends on sign!"); - DSTr = Builder.CreateICmp(UIPred, LHSr, RHSr); - DSTi = Builder.CreateICmp(UIPred, LHSi, RHSi); - if (UIPred == CmpInst::ICMP_EQ) - return Builder.CreateAnd(DSTr, DSTi); - assert(UIPred == CmpInst::ICMP_NE && "Unhandled complex comparison!"); - return Builder.CreateOr(DSTr, DSTi); - } - - if (LHS->getType()->isFPOrFPVectorTy()) - return Builder.CreateFCmp(FPPred, LHS, RHS); - - // Determine which predicate to use based on signedness. - CmpInst::Predicate pred = TYPE_UNSIGNED(TREE_TYPE(lhs)) ? UIPred : SIPred; - return Builder.CreateICmp(pred, LHS, RHS); -} - -Value *TreeToLLVM::EmitReg_MinMaxExpr(tree type, tree op0, tree op1, - unsigned UIPred, unsigned SIPred, - unsigned FPPred, bool isMax) { - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - - const Type *Ty = GetRegType(type); - - // The LHS, RHS and Ty could be integer, floating or pointer typed. We need - // to convert the LHS and RHS into the destination type before doing the - // comparison. Use CastInst::getCastOpcode to get this right. - bool TyIsSigned = !TYPE_UNSIGNED(type); - bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op0)); - bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(op1)); - Instruction::CastOps opcode = - CastInst::getCastOpcode(LHS, LHSIsSigned, Ty, TyIsSigned); - LHS = Builder.CreateCast(opcode, LHS, Ty); - opcode = CastInst::getCastOpcode(RHS, RHSIsSigned, Ty, TyIsSigned); - RHS = Builder.CreateCast(opcode, RHS, Ty); - - Value *Compare; - if (LHS->getType()->isFloatingPointTy()) - Compare = Builder.CreateFCmp(FCmpInst::Predicate(FPPred), LHS, RHS); - else if (TYPE_UNSIGNED(type)) - Compare = Builder.CreateICmp(ICmpInst::Predicate(UIPred), LHS, RHS); - else - Compare = Builder.CreateICmp(ICmpInst::Predicate(SIPred), LHS, RHS); - - return Builder.CreateSelect(Compare, LHS, RHS, isMax ? "max" : "min"); -} - -Value *TreeToLLVM::EmitReg_RotateOp(tree type, tree op0, tree op1, - unsigned Opc1, unsigned Opc2) { - Value *In = EmitRegister(op0); - Value *Amt = EmitRegister(op1); - - if (Amt->getType() != In->getType()) - Amt = Builder.CreateIntCast(Amt, In->getType(), /*isSigned*/false, - Amt->getName()+".cast"); - - Value *TypeSize = - ConstantInt::get(In->getType(), - In->getType()->getPrimitiveSizeInBits()); - - // Do the two shifts. - Value *V1 = Builder.CreateBinOp((Instruction::BinaryOps)Opc1, In, Amt); - Value *OtherShift = Builder.CreateSub(TypeSize, Amt); - Value *V2 = Builder.CreateBinOp((Instruction::BinaryOps)Opc2, In, OtherShift); - - // Or the two together to return them. - Value *Merge = Builder.CreateOr(V1, V2); - return Builder.CreateIntCast(Merge, GetRegType(type), /*isSigned*/false); -} - -Value *TreeToLLVM::EmitReg_ShiftOp(tree op0, tree op1, unsigned Opc) { - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - if (RHS->getType() != LHS->getType()) - RHS = Builder.CreateIntCast(RHS, LHS->getType(), /*isSigned*/false, - RHS->getName()+".cast"); - - return Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS); -} - -Value *TreeToLLVM::EmitReg_TruthOp(tree type, tree op0, tree op1, unsigned Opc){ - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - - // This is a truth operation like the strict &&,||,^^. Convert to bool as - // a test against zero - LHS = Builder.CreateICmpNE(LHS, - Constant::getNullValue(LHS->getType()), - "toBool"); - RHS = Builder.CreateICmpNE(RHS, - Constant::getNullValue(RHS->getType()), - "toBool"); - - Value *Res = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS); - return Builder.CreateZExt(Res, GetRegType(type)); -} - -Value *TreeToLLVM::EmitReg_CEIL_DIV_EXPR(tree type, tree op0, tree op1) { - // Notation: CEIL_DIV_EXPR <-> CDiv, TRUNC_DIV_EXPR <-> Div. - - // CDiv calculates LHS/RHS by rounding up to the nearest integer. In terms - // of Div this means if the values of LHS and RHS have opposite signs or if - // LHS is zero, then CDiv necessarily equals Div; and - // LHS CDiv RHS = (LHS - Sign(RHS)) Div RHS + 1 - // otherwise. - - const Type *Ty = GetRegType(type); - Constant *Zero = ConstantInt::get(Ty, 0); - Constant *One = ConstantInt::get(Ty, 1); - Constant *MinusOne = Constant::getAllOnesValue(Ty); - - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - - if (!TYPE_UNSIGNED(type)) { - // In the case of signed arithmetic, we calculate CDiv as follows: - // LHS CDiv RHS = (LHS - Sign(RHS) * Offset) Div RHS + Offset, - // where Offset is 1 if LHS and RHS have the same sign and LHS is - // not zero, and 0 otherwise. - - // On some machines INT_MIN Div -1 traps. You might expect a trap for - // INT_MIN CDiv -1 too, but this implementation will not generate one. - // Quick quiz question: what value is returned for INT_MIN CDiv -1? - - // Determine the signs of LHS and RHS, and whether they have the same sign. - Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero); - Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero); - Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive); - - // Offset equals 1 if LHS and RHS have the same sign and LHS is not zero. - Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero); - Value *OffsetOne = Builder.CreateAnd(HaveSameSign, LHSNotZero); - // ... otherwise it is 0. - Value *Offset = Builder.CreateSelect(OffsetOne, One, Zero); - - // Calculate Sign(RHS) ... - Value *SignRHS = Builder.CreateSelect(RHSIsPositive, One, MinusOne); - // ... and Sign(RHS) * Offset - Value *SignedOffset = Builder.CreateSExt(OffsetOne, Ty); - SignedOffset = Builder.CreateAnd(SignRHS, SignedOffset); - - // Return CDiv = (LHS - Sign(RHS) * Offset) Div RHS + Offset. - Value *CDiv = Builder.CreateSub(LHS, SignedOffset); - CDiv = Builder.CreateSDiv(CDiv, RHS); - return Builder.CreateAdd(CDiv, Offset, "cdiv"); - } - - // In the case of unsigned arithmetic, LHS and RHS necessarily have the - // same sign, so we can use - // LHS CDiv RHS = (LHS - 1) Div RHS + 1 - // as long as LHS is non-zero. - - // Offset is 1 if LHS is non-zero, 0 otherwise. - Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero); - Value *Offset = Builder.CreateSelect(LHSNotZero, One, Zero); - - // Return CDiv = (LHS - Offset) Div RHS + Offset. - Value *CDiv = Builder.CreateSub(LHS, Offset); - CDiv = Builder.CreateUDiv(CDiv, RHS); - return Builder.CreateAdd(CDiv, Offset, "cdiv"); -} - -Value *TreeToLLVM::EmitReg_BIT_AND_EXPR(tree op0, tree op1) { - return Builder.CreateAnd(EmitRegister(op0), EmitRegister(op1)); -} - -Value *TreeToLLVM::EmitReg_BIT_IOR_EXPR(tree op0, tree op1) { - return Builder.CreateOr(EmitRegister(op0), EmitRegister(op1)); -} - -Value *TreeToLLVM::EmitReg_BIT_XOR_EXPR(tree op0, tree op1) { - return Builder.CreateXor(EmitRegister(op0), EmitRegister(op1)); -} - -Value *TreeToLLVM::EmitReg_COMPLEX_EXPR(tree op0, tree op1) { - return CreateComplex(EmitRegister(op0), EmitRegister(op1), TREE_TYPE(op1)); -} - -Value *TreeToLLVM::EmitReg_FLOOR_DIV_EXPR(tree type, tree op0, tree op1) { - // Notation: FLOOR_DIV_EXPR <-> FDiv, TRUNC_DIV_EXPR <-> Div. - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - - // FDiv calculates LHS/RHS by rounding down to the nearest integer. In terms - // of Div this means if the values of LHS and RHS have the same sign or if LHS - // is zero, then FDiv necessarily equals Div; and - // LHS FDiv RHS = (LHS + Sign(RHS)) Div RHS - 1 - // otherwise. - - if (TYPE_UNSIGNED(type)) - // In the case of unsigned arithmetic, LHS and RHS necessarily have the - // same sign, so FDiv is the same as Div. - return Builder.CreateUDiv(LHS, RHS, "fdiv"); - - const Type *Ty = GetRegType(type); - Constant *Zero = ConstantInt::get(Ty, 0); - Constant *One = ConstantInt::get(Ty, 1); - Constant *MinusOne = Constant::getAllOnesValue(Ty); - - // In the case of signed arithmetic, we calculate FDiv as follows: - // LHS FDiv RHS = (LHS + Sign(RHS) * Offset) Div RHS - Offset, - // where Offset is 1 if LHS and RHS have opposite signs and LHS is - // not zero, and 0 otherwise. - - // Determine the signs of LHS and RHS, and whether they have the same sign. - Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero); - Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero); - Value *SignsDiffer = Builder.CreateICmpNE(LHSIsPositive, RHSIsPositive); - - // Offset equals 1 if LHS and RHS have opposite signs and LHS is not zero. - Value *LHSNotZero = Builder.CreateICmpNE(LHS, Zero); - Value *OffsetOne = Builder.CreateAnd(SignsDiffer, LHSNotZero); - // ... otherwise it is 0. - Value *Offset = Builder.CreateSelect(OffsetOne, One, Zero); - - // Calculate Sign(RHS) ... - Value *SignRHS = Builder.CreateSelect(RHSIsPositive, One, MinusOne); - // ... and Sign(RHS) * Offset - Value *SignedOffset = Builder.CreateSExt(OffsetOne, Ty); - SignedOffset = Builder.CreateAnd(SignRHS, SignedOffset); - - // Return FDiv = (LHS + Sign(RHS) * Offset) Div RHS - Offset. - Value *FDiv = Builder.CreateAdd(LHS, SignedOffset); - FDiv = Builder.CreateSDiv(FDiv, RHS); - return Builder.CreateSub(FDiv, Offset, "fdiv"); -} - -Value *TreeToLLVM::EmitReg_FLOOR_MOD_EXPR(tree type, tree op0, tree op1) { - // Notation: FLOOR_MOD_EXPR <-> Mod, TRUNC_MOD_EXPR <-> Rem. - - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - - // We express Mod in terms of Rem as follows: if RHS exactly divides LHS, - // or the values of LHS and RHS have the same sign, then Mod equals Rem. - // Otherwise Mod equals Rem + RHS. This means that LHS Mod RHS traps iff - // LHS Rem RHS traps. - if (TYPE_UNSIGNED(type)) - // LHS and RHS values must have the same sign if their type is unsigned. - return Builder.CreateURem(LHS, RHS); - - const Type *Ty = GetRegType(type); - Constant *Zero = ConstantInt::get(Ty, 0); - - // The two possible values for Mod. - Value *Rem = Builder.CreateSRem(LHS, RHS, "rem"); - Value *RemPlusRHS = Builder.CreateAdd(Rem, RHS); - - // HaveSameSign: (LHS >= 0) == (RHS >= 0). - Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero); - Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero); - Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive,RHSIsPositive); - - // RHS exactly divides LHS iff Rem is zero. - Value *RemIsZero = Builder.CreateICmpEQ(Rem, Zero); - - Value *SameAsRem = Builder.CreateOr(HaveSameSign, RemIsZero); - return Builder.CreateSelect(SameAsRem, Rem, RemPlusRHS, "mod"); -} - -Value *TreeToLLVM::EmitReg_MINUS_EXPR(tree op0, tree op1) { - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - tree type = TREE_TYPE(op0); - - if (TREE_CODE(type) == COMPLEX_TYPE) { - tree elt_type = TREE_TYPE(type); - Value *LHSr, *LHSi; SplitComplex(LHS, LHSr, LHSi, elt_type); - Value *RHSr, *RHSi; SplitComplex(RHS, RHSr, RHSi, elt_type); - - // (a+ib) - (c+id) = (a-c) + i(b-d) - LHSr = CreateAnySub(LHSr, RHSr, elt_type); - LHSi = CreateAnySub(LHSi, RHSi, elt_type); - - return CreateComplex(LHSr, LHSi, elt_type); - } - - return CreateAnySub(LHS, RHS, type); -} - -Value *TreeToLLVM::EmitReg_MULT_EXPR(tree op0, tree op1) { - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - tree type = TREE_TYPE(op0); - - if (TREE_CODE(type) == COMPLEX_TYPE) { - tree elt_type = TREE_TYPE(type); - Value *LHSr, *LHSi; SplitComplex(LHS, LHSr, LHSi, elt_type); - Value *RHSr, *RHSi; SplitComplex(RHS, RHSr, RHSi, elt_type); - Value *DSTr, *DSTi; - - // (a+ib) * (c+id) = (ac-bd) + i(ad+cb) - if (SCALAR_FLOAT_TYPE_P(elt_type)) { - Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr); // a*c - Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi); // b*d - DSTr = Builder.CreateFSub(Tmp1, Tmp2); // ac-bd - - Value *Tmp3 = Builder.CreateFMul(LHSr, RHSi); // a*d - Value *Tmp4 = Builder.CreateFMul(RHSr, LHSi); // c*b - DSTi = Builder.CreateFAdd(Tmp3, Tmp4); // ad+cb - } else { - // If overflow does not wrap in the element type then it is tempting to - // use NSW operations here. However that would be wrong since overflow - // of an intermediate value calculated here does not necessarily imply - // that the final result overflows. - Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c - Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d - DSTr = Builder.CreateSub(Tmp1, Tmp2); // ac-bd - - Value *Tmp3 = Builder.CreateMul(LHSr, RHSi); // a*d - Value *Tmp4 = Builder.CreateMul(RHSr, LHSi); // c*b - DSTi = Builder.CreateAdd(Tmp3, Tmp4); // ad+cb - } - - return CreateComplex(DSTr, DSTi, elt_type); - } - - return CreateAnyMul(LHS, RHS, type); -} - -Value *TreeToLLVM::EmitReg_PLUS_EXPR(tree op0, tree op1) { - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - tree type = TREE_TYPE(op0); - - if (TREE_CODE(type) == COMPLEX_TYPE) { - tree elt_type = TREE_TYPE(type); - Value *LHSr, *LHSi; SplitComplex(LHS, LHSr, LHSi, elt_type); - Value *RHSr, *RHSi; SplitComplex(RHS, RHSr, RHSi, elt_type); - - // (a+ib) + (c+id) = (a+c) + i(b+d) - LHSr = CreateAnyAdd(LHSr, RHSr, elt_type); - LHSi = CreateAnyAdd(LHSi, RHSi, elt_type); - - return CreateComplex(LHSr, LHSi, elt_type); - } - - return CreateAnyAdd(LHS, RHS, type); -} - -Value *TreeToLLVM::EmitReg_POINTER_PLUS_EXPR(tree type, tree op0, tree op1) { - Value *Ptr = EmitRegister(op0); // The pointer. - Value *Idx = EmitRegister(op1); // The offset in units. - - // Convert the pointer into an i8* and add the offset to it. - Ptr = Builder.CreateBitCast(Ptr, GetUnitPointerType(Context)); - Value *GEP = POINTER_TYPE_OVERFLOW_UNDEFINED ? - Builder.CreateInBoundsGEP(Ptr, Idx) : Builder.CreateGEP(Ptr, Idx); - - // The result may be of a different pointer type. - return UselesslyTypeConvert(GEP, GetRegType(type)); -} - -Value *TreeToLLVM::EmitReg_RDIV_EXPR(tree op0, tree op1) { - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - tree type = TREE_TYPE(op0); - - if (TREE_CODE(type) == COMPLEX_TYPE) { - tree elt_type = TREE_TYPE(type); - Value *LHSr, *LHSi; SplitComplex(LHS, LHSr, LHSi, elt_type); - Value *RHSr, *RHSi; SplitComplex(RHS, RHSr, RHSi, elt_type); - Value *DSTr, *DSTi; - - // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) - assert (SCALAR_FLOAT_TYPE_P(elt_type) && "RDIV_EXPR not floating point!"); - Value *Tmp1 = Builder.CreateFMul(LHSr, RHSr); // a*c - Value *Tmp2 = Builder.CreateFMul(LHSi, RHSi); // b*d - Value *Tmp3 = Builder.CreateFAdd(Tmp1, Tmp2); // ac+bd - - Value *Tmp4 = Builder.CreateFMul(RHSr, RHSr); // c*c - Value *Tmp5 = Builder.CreateFMul(RHSi, RHSi); // d*d - Value *Tmp6 = Builder.CreateFAdd(Tmp4, Tmp5); // cc+dd - DSTr = Builder.CreateFDiv(Tmp3, Tmp6); - - Value *Tmp7 = Builder.CreateFMul(LHSi, RHSr); // b*c - Value *Tmp8 = Builder.CreateFMul(LHSr, RHSi); // a*d - Value *Tmp9 = Builder.CreateFSub(Tmp7, Tmp8); // bc-ad - DSTi = Builder.CreateFDiv(Tmp9, Tmp6); - - return CreateComplex(DSTr, DSTi, elt_type); - } - - assert(FLOAT_TYPE_P(type) && "RDIV_EXPR not floating point!"); - return Builder.CreateFDiv(LHS, RHS); -} - -Value *TreeToLLVM::EmitReg_ROUND_DIV_EXPR(tree type, tree op0, tree op1) { - // Notation: ROUND_DIV_EXPR <-> RDiv, TRUNC_DIV_EXPR <-> Div. - - // RDiv calculates LHS/RHS by rounding to the nearest integer. Ties - // are broken by rounding away from zero. In terms of Div this means: - // LHS RDiv RHS = (LHS + (RHS Div 2)) Div RHS - // if the values of LHS and RHS have the same sign; and - // LHS RDiv RHS = (LHS - (RHS Div 2)) Div RHS - // if the values of LHS and RHS differ in sign. The intermediate - // expressions in these formulae can overflow, so some tweaking is - // required to ensure correct results. The details depend on whether - // we are doing signed or unsigned arithmetic. - - const Type *Ty = GetRegType(type); - Constant *Zero = ConstantInt::get(Ty, 0); - Constant *Two = ConstantInt::get(Ty, 2); - - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - - if (!TYPE_UNSIGNED(type)) { - // In the case of signed arithmetic, we calculate RDiv as follows: - // LHS RDiv RHS = (sign) ( (|LHS| + (|RHS| UDiv 2)) UDiv |RHS| ), - // where sign is +1 if LHS and RHS have the same sign, -1 if their - // signs differ. Doing the computation unsigned ensures that there - // is no overflow. - - // On some machines INT_MIN Div -1 traps. You might expect a trap for - // INT_MIN RDiv -1 too, but this implementation will not generate one. - // Quick quiz question: what value is returned for INT_MIN RDiv -1? - - // Determine the signs of LHS and RHS, and whether they have the same sign. - Value *LHSIsPositive = Builder.CreateICmpSGE(LHS, Zero); - Value *RHSIsPositive = Builder.CreateICmpSGE(RHS, Zero); - Value *HaveSameSign = Builder.CreateICmpEQ(LHSIsPositive, RHSIsPositive); - - // Calculate |LHS| ... - Value *MinusLHS = Builder.CreateNeg(LHS); - Value *AbsLHS = Builder.CreateSelect(LHSIsPositive, LHS, MinusLHS, - LHS->getName()+".abs"); - // ... and |RHS| - Value *MinusRHS = Builder.CreateNeg(RHS); - Value *AbsRHS = Builder.CreateSelect(RHSIsPositive, RHS, MinusRHS, - RHS->getName()+".abs"); - - // Calculate AbsRDiv = (|LHS| + (|RHS| UDiv 2)) UDiv |RHS|. - Value *HalfAbsRHS = Builder.CreateUDiv(AbsRHS, Two); - Value *Numerator = Builder.CreateAdd(AbsLHS, HalfAbsRHS); - Value *AbsRDiv = Builder.CreateUDiv(Numerator, AbsRHS); - - // Return AbsRDiv or -AbsRDiv according to whether LHS and RHS have the - // same sign or not. - Value *MinusAbsRDiv = Builder.CreateNeg(AbsRDiv); - return Builder.CreateSelect(HaveSameSign, AbsRDiv, MinusAbsRDiv, "rdiv"); - } - - // In the case of unsigned arithmetic, LHS and RHS necessarily have the - // same sign, however overflow is a problem. We want to use the formula - // LHS RDiv RHS = (LHS + (RHS Div 2)) Div RHS, - // but if LHS + (RHS Div 2) overflows then we get the wrong result. Since - // the use of a conditional branch seems to be unavoidable, we choose the - // simple solution of explicitly checking for overflow, and using - // LHS RDiv RHS = ((LHS + (RHS Div 2)) - RHS) Div RHS + 1 - // if it occurred. - - // Usually the numerator is LHS + (RHS Div 2); calculate this. - Value *HalfRHS = Builder.CreateUDiv(RHS, Two); - Value *Numerator = Builder.CreateAdd(LHS, HalfRHS); - - // Did the calculation overflow? - Value *Overflowed = Builder.CreateICmpULT(Numerator, HalfRHS); - - // If so, use (LHS + (RHS Div 2)) - RHS for the numerator instead. - Value *AltNumerator = Builder.CreateSub(Numerator, RHS); - Numerator = Builder.CreateSelect(Overflowed, AltNumerator, Numerator); - - // Quotient = Numerator / RHS. - Value *Quotient = Builder.CreateUDiv(Numerator, RHS); - - // Return Quotient unless we overflowed, in which case return Quotient + 1. - return Builder.CreateAdd(Quotient, Builder.CreateIntCast(Overflowed, Ty, - /*isSigned*/false), - "rdiv"); -} - -Value *TreeToLLVM::EmitReg_TRUNC_DIV_EXPR(tree op0, tree op1, bool isExact) { - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - tree type = TREE_TYPE(op0); - - if (TREE_CODE(type) == COMPLEX_TYPE) { - tree elt_type = TREE_TYPE(type); - Value *LHSr, *LHSi; SplitComplex(LHS, LHSr, LHSi, elt_type); - Value *RHSr, *RHSi; SplitComplex(RHS, RHSr, RHSi, elt_type); - Value *DSTr, *DSTi; - - // (a+ib) / (c+id) = ((ac+bd)/(cc+dd)) + i((bc-ad)/(cc+dd)) - assert (LHSr->getType()->isIntegerTy() && "TRUNC_DIV_EXPR not integer!"); - // If overflow does not wrap in the element type then it is tempting to - // use NSW operations here. However that would be wrong since overflow - // of an intermediate value calculated here does not necessarily imply - // that the final result overflows. - Value *Tmp1 = Builder.CreateMul(LHSr, RHSr); // a*c - Value *Tmp2 = Builder.CreateMul(LHSi, RHSi); // b*d - Value *Tmp3 = Builder.CreateAdd(Tmp1, Tmp2); // ac+bd - - Value *Tmp4 = Builder.CreateMul(RHSr, RHSr); // c*c - Value *Tmp5 = Builder.CreateMul(RHSi, RHSi); // d*d - Value *Tmp6 = Builder.CreateAdd(Tmp4, Tmp5); // cc+dd - DSTr = TYPE_UNSIGNED(elt_type) ? - Builder.CreateUDiv(Tmp3, Tmp6) : Builder.CreateSDiv(Tmp3, Tmp6); - - Value *Tmp7 = Builder.CreateMul(LHSi, RHSr); // b*c - Value *Tmp8 = Builder.CreateMul(LHSr, RHSi); // a*d - Value *Tmp9 = Builder.CreateSub(Tmp7, Tmp8); // bc-ad - DSTi = TYPE_UNSIGNED(elt_type) ? - Builder.CreateUDiv(Tmp9, Tmp6) : Builder.CreateSDiv(Tmp9, Tmp6); - - return CreateComplex(DSTr, DSTi, elt_type); - } - - assert(LHS->getType()->isIntOrIntVectorTy() && "TRUNC_DIV_EXPR not integer!"); - if (TYPE_UNSIGNED(type)) - return Builder.CreateUDiv(LHS, RHS, "", isExact); - else - return Builder.CreateSDiv(LHS, RHS, "", isExact); -} - -Value *TreeToLLVM::EmitReg_TRUNC_MOD_EXPR(tree op0, tree op1) { - Value *LHS = EmitRegister(op0); - Value *RHS = EmitRegister(op1); - return TYPE_UNSIGNED(TREE_TYPE(op0)) ? - Builder.CreateURem(LHS, RHS) : Builder.CreateSRem(LHS, RHS); -} - - -//===----------------------------------------------------------------------===// -// ... Exception Handling ... -//===----------------------------------------------------------------------===// - - - -//===----------------------------------------------------------------------===// -// ... Render* - Convert GIMPLE to LLVM ... -//===----------------------------------------------------------------------===// - -void TreeToLLVM::RenderGIMPLE_ASM(gimple stmt) { - // A gimple asm statement consists of an asm string, a list of outputs, a list - // of inputs, a list of clobbers, a list of labels and a "volatile" flag. - // These correspond directly to the elements of an asm statement. For example - // asm ("combine %2,%0" : "=r" (x) : "0" (x), "g" (y)); - // Here the asm string is "combine %2,%0" and can be obtained as a const char* - // by calling gimple_asm_string. The only output is "=r" (x). The number of - // outputs is given by gimple_asm_noutputs, 1 in this case, and the outputs - // themselves can be obtained by calling gimple_asm_output_op. This returns a - // TREE_LIST node with an SSA name for "x" as the TREE_VALUE; the TREE_PURPOSE - // is also a TREE_LIST with TREE_VALUE a string constant holding "=r". There - // are two inputs, "0" (x) and "g" (y), so gimple_asm_ninputs returns 2. The - // routine gimple_asm_input_op returns them in the same format as for outputs. - // The number of clobbers is returned by gimple_asm_nclobbers, 0 in this case. - // To get the clobbers use gimple_asm_clobber_op. This returns a TREE_LIST - // node with TREE_VALUE a string constant holding the clobber. To find out if - // the asm is volatile call gimple_asm_volatile_p, which returns true if so. - // See below for labels (this example does not have any). - - // Note that symbolic names have been substituted before getting here. For - // example this - // asm ("cmoveq %1,%2,%[result]" : [result] "=r"(result) - // : "r"(test), "r"(new), "[result]"(old)); - // turns up as - // asm ("cmoveq %1,%2,%0" : "=r"(result) : "r"(test), "r"(new), "0"(old)); - - // Note that clobbers may not turn up in the same order as in the original, eg - // asm volatile ("movc3 %0,%1,%2" : /* no outputs */ - // : "g" (from), "g" (to), "g" (count) - // : "r0", "r1", "r2", "r3", "r4", "r5"); - // The clobbers turn up as "r5", "r4", "r3", "r2", "r1", "r0". - - // Here is an example of the "asm goto" construct (not yet supported by LLVM): - // int frob(int x) { - // int y; - // asm goto ("frob %%r5, %1; jc %l[error]; mov (%2), %%r5" - // : : "r"(x), "r"(&y) : "r5", "memory" : error); - // return y; - // error: - // return -1; - // } - // The number of labels, one in this case, is returned by gimple_asm_nlabels. - // The labels themselves are returned by gimple_asm_label_op as a TREE_LIST - // node with TREE_PURPOSE a string constant holding the label name ("error") - // and TREE_VALUE holding the appropriate LABEL_DECL. - - // TODO: Add support for labels. - if (gimple_asm_nlabels(stmt) > 0) { - sorry("'asm goto' not supported"); - return; - } - - const unsigned NumOutputs = gimple_asm_noutputs (stmt); - const unsigned NumInputs = gimple_asm_ninputs(stmt); - const unsigned NumClobbers = gimple_asm_nclobbers (stmt); - - /// Constraints - The output/input constraints, concatenated together in array - /// form instead of list form. This way of doing things is forced on us by - /// GCC routines like parse_output_constraint which rummage around inside the - /// array. - const char **Constraints = - (const char **)alloca((NumOutputs + NumInputs) * sizeof(const char *)); - - // Initialize the Constraints array. - for (unsigned i = 0; i != NumOutputs; ++i) { - tree Output = gimple_asm_output_op(stmt, i); - // If there's an erroneous arg then bail out. - if (TREE_TYPE(TREE_VALUE(Output)) == error_mark_node) return; - // Record the output constraint. - const char *Constraint = - TREE_STRING_POINTER(TREE_VALUE(TREE_PURPOSE(Output))); - Constraints[i] = Constraint; - } - for (unsigned i = 0; i != NumInputs; ++i) { - tree Input = gimple_asm_input_op(stmt, i); - // If there's an erroneous arg then bail out. - if (TREE_TYPE(TREE_VALUE(Input)) == error_mark_node) return; - // Record the input constraint. - const char *Constraint = - TREE_STRING_POINTER(TREE_VALUE(TREE_PURPOSE(Input))); - Constraints[NumOutputs+i] = Constraint; - } - - // Look for multiple alternative constraints: multiple alternatives separated - // by commas. - unsigned NumChoices = 0; // sentinal; real value is always at least 1. - for (unsigned i = 0; i != NumInputs; ++i) { - tree Input = gimple_asm_input_op(stmt, i); - unsigned NumInputChoices = 1; - for (const char *p = TREE_STRING_POINTER(TREE_VALUE(TREE_PURPOSE(Input))); - *p; ++p) - if (*p == ',') - ++NumInputChoices; - if (NumChoices && (NumInputChoices != NumChoices)) { - error_at(gimple_location(stmt), "operand constraints for % differ " - "in number of alternatives"); - return; - } - if (NumChoices == 0) - NumChoices = NumInputChoices; - } - for (unsigned i = 0; i != NumOutputs; ++i) { - tree Output = gimple_asm_output_op(stmt, i); - unsigned NumOutputChoices = 1; - for (const char *p = TREE_STRING_POINTER(TREE_VALUE(TREE_PURPOSE(Output))); - *p; ++p) - if (*p == ',') - ++NumOutputChoices; - if (NumChoices && (NumOutputChoices != NumChoices)) { - error_at(gimple_location(stmt), "operand constraints for % differ " - "in number of alternatives"); - return; - } - if (NumChoices == 0) - NumChoices = NumOutputChoices; - } - - // If there are multiple constraint tuples, pick one. Constraints is - // altered to point to shorter strings (which are malloc'ed), and everything - // below Just Works as in the NumChoices==1 case. - BumpPtrAllocator StringStorage(256, 256); - if (NumChoices > 1) - ChooseConstraintTuple(stmt, Constraints, NumChoices, StringStorage); - - // HasSideEffects - Whether the LLVM inline asm should be marked as having - // side effects. - bool HasSideEffects = gimple_asm_volatile_p(stmt) || (NumOutputs == 0); - - // CallResultTypes - The inline asm call may return one or more results. The - // types of the results are recorded here along with a flag indicating whether - // the corresponding GCC type is signed. - SmallVector, 4> CallResultTypes; - - // CallResultDests - Each result returned by the inline asm call is stored in - // a memory location. These are listed here along with a flag indicating if - // the GCC type corresponding to the memory location is signed. The type of - // the memory location is allowed to differ from the type of the call result, - // in which case the result is converted before being stored. - SmallVector, 4> CallResultDests; - - // CallOps - The operands pass to the inline asm call. - std::vector CallOps; - - // OutputLocations - For each output holds an index into CallOps (if the flag - // is false) or into CallResultTypes (if the flag is true). Outputs returned - // in memory are passed to the asm as an operand and thus appear in CallOps. - // Those returned in registers are obtained as one of the results of the asm - // call and thus correspond to an entry in CallResultTypes. - SmallVector, 4> OutputLocations; - - // SSADefinitions - If the asm defines an SSA name then the SSA name and a - // memory location are recorded here. The asm result defining the SSA name - // will be stored to the memory memory location, and loaded out afterwards - // to define the SSA name. - SmallVector, 4> SSADefinitions; - - // ConstraintStr - The string of constraints in LLVM format. - std::string ConstraintStr; - - // Process outputs. - for (unsigned i = 0; i != NumOutputs; ++i) { - tree Output = gimple_asm_output_op(stmt, i); - tree Operand = TREE_VALUE(Output); - - // Parse the output constraint. - const char *Constraint = Constraints[i]; - bool IsInOut, AllowsReg, AllowsMem; - if (!parse_output_constraint(&Constraint, i, NumInputs, NumOutputs, - &AllowsMem, &AllowsReg, &IsInOut)) - return; - assert(Constraint[0] == '=' && "Not an output constraint?"); - assert(!IsInOut && "asm expression not gimplified?"); - - std::string SimplifiedConstraint; - // If this output register is pinned to a machine register, use that machine - // register instead of the specified constraint. - if (TREE_CODE(Operand) == VAR_DECL && DECL_HARD_REGISTER(Operand)) { - const char* RegName = extractRegisterName(Operand); - int RegNum = decode_reg_name(RegName); - if (RegNum >= 0) { - RegName = LLVM_GET_REG_NAME(RegName, RegNum); - unsigned RegNameLen = strlen(RegName); - char *NewConstraint = (char*)alloca(RegNameLen+3); - NewConstraint[0] = '{'; - memcpy(NewConstraint+1, RegName, RegNameLen); - NewConstraint[RegNameLen+1] = '}'; - NewConstraint[RegNameLen+2] = 0; - SimplifiedConstraint = NewConstraint; - // This output will now be implicit; set the sideffect flag on the asm. - HasSideEffects = true; - // We should no longer consider mem constraints. - AllowsMem = false; - } else { - // If we can simplify the constraint into something else, do so now. - // This avoids LLVM having to know about all the (redundant) GCC - // constraints. - SimplifiedConstraint = CanonicalizeConstraint(Constraint+1); - } - } else { - SimplifiedConstraint = CanonicalizeConstraint(Constraint+1); - } - - LValue Dest; - const Type *DestValTy = ConvertType(TREE_TYPE(Operand)); - if (TREE_CODE(Operand) == SSA_NAME) { - // The ASM is defining an ssa name. Store the output to a temporary, then - // load it out again later as the ssa name. - MemRef TmpLoc = CreateTempLoc(DestValTy); - SSADefinitions.push_back(std::make_pair(Operand, TmpLoc)); - Dest = LValue(TmpLoc); - } else { - Dest = EmitLV(Operand); - assert(cast(Dest.Ptr->getType())->getElementType() == - DestValTy && "LValue has wrong type!"); - } - - assert(!Dest.isBitfield() && "Cannot assign into a bitfield!"); - if (!AllowsMem && DestValTy->isSingleValueType()) {// Reg dest -> asm return - ConstraintStr += ",="; - ConstraintStr += SimplifiedConstraint; - bool IsSigned = !TYPE_UNSIGNED(TREE_TYPE(Operand)); - CallResultDests.push_back(std::make_pair(Dest.Ptr, IsSigned)); - CallResultTypes.push_back(std::make_pair(DestValTy, IsSigned)); - OutputLocations.push_back(std::make_pair(true, CallResultTypes.size()-1)); - } else { - ConstraintStr += ",=*"; - ConstraintStr += SimplifiedConstraint; - CallOps.push_back(Dest.Ptr); - OutputLocations.push_back(std::make_pair(false, CallOps.size()-1)); - } - } - - // Process inputs. - for (unsigned i = 0; i != NumInputs; ++i) { - tree Input = gimple_asm_input_op(stmt, i); - tree Val = TREE_VALUE(Input); - tree type = TREE_TYPE(Val); - bool IsSigned = !TYPE_UNSIGNED(type); - - const char *Constraint = Constraints[NumOutputs+i]; - - bool AllowsReg, AllowsMem; - if (!parse_input_constraint(Constraints+NumOutputs+i, i, - NumInputs, NumOutputs, 0, - Constraints, &AllowsMem, &AllowsReg)) - return; - bool isIndirect = false; - if (AllowsReg || !AllowsMem) { // Register operand. - const Type *LLVMTy = ConvertType(type); - - Value *Op = 0; - const Type *OpTy = LLVMTy; - if (LLVMTy->isSingleValueType()) { - if (TREE_CODE(Val)==ADDR_EXPR && - TREE_CODE(TREE_OPERAND(Val,0))==LABEL_DECL) { - // Emit the label, but do not assume it is going to be the target - // of an indirect branch. Having this logic here is a hack; there - // should be a bit in the label identifying it as in an asm. - Op = getLabelDeclBlock(TREE_OPERAND(Val, 0)); - } else if (TREE_CODE(Val) == VAR_DECL && DECL_HARD_REGISTER(Val)) { - // GCC special cases hard registers used as inputs to asm statements. - // Emit an inline asm node that copies the value out of the specified - // register. - assert(canEmitRegisterVariable(Val) && "Cannot read hard register!"); - Op = EmitReadOfRegisterVariable(Val); - } else { - Op = EmitMemory(Val); - } - } else { - LValue LV = EmitLV(Val); - assert(!LV.isBitfield() && "Inline asm can't have bitfield operand"); - - // Small structs and unions can be treated as integers. - uint64_t TySize = TD.getTypeSizeInBits(LLVMTy); - if (TySize == 1 || TySize == 8 || TySize == 16 || - TySize == 32 || TySize == 64 || (TySize == 128 && !AllowsMem)) { - LLVMTy = IntegerType::get(Context, TySize); - Op = - Builder.CreateLoad(Builder.CreateBitCast(LV.Ptr, - LLVMTy->getPointerTo())); - } else { - // Codegen only supports indirect operands with mem constraints. - if (!AllowsMem) - error_at(gimple_location(stmt), - "aggregate does not match inline asm register constraint"); - // Otherwise, emit our value as a lvalue. - isIndirect = true; - Op = LV.Ptr; - OpTy = Op->getType(); - } - } - - // If this input operand is matching an output operand, e.g. '0', check if - // this is something that llvm supports. If the operand types are - // different, then emit an error if 1) one of the types is not integer or - // pointer, 2) if size of input type is larger than the output type. If - // the size of the integer input size is smaller than the integer output - // type, then cast it to the larger type and shift the value if the target - // is big endian. - if (ISDIGIT(Constraint[0])) { - unsigned Match = atoi(Constraint); - // This output might have gotten put in either CallResult or CallArg - // depending whether it's a register or not. Find its type. - const Type *OTy = 0; - unsigned OutputIndex = ~0U; - if (Match < OutputLocations.size()) { - // Indices here known to be within range. - OutputIndex = OutputLocations[Match].second; - if (OutputLocations[Match].first) - OTy = CallResultTypes[OutputIndex].first; - else { - OTy = CallOps[OutputIndex]->getType(); - assert(OTy->isPointerTy() && "Expected pointer type!"); - OTy = cast(OTy)->getElementType(); - } - } - if (OTy && OTy != OpTy) { - if (!(OTy->isIntegerTy() || OTy->isPointerTy()) || - !(OpTy->isIntegerTy() || OpTy->isPointerTy())) { - error_at(gimple_location(stmt), - "unsupported inline asm: input constraint with a matching " - "output constraint of incompatible type!"); - return; - } - unsigned OTyBits = TD.getTypeSizeInBits(OTy); - unsigned OpTyBits = TD.getTypeSizeInBits(OpTy); - if (OTyBits == 0 || OpTyBits == 0) { - error_at(gimple_location(stmt), "unsupported inline asm: input " - "constraint with a matching output constraint of " - "incompatible type!"); - return; - } else if (OTyBits < OpTyBits) { - // The output is smaller than the input. If the output is not a - // register then bail out. Likewise, if the output is explicitly - // mentioned in the asm string then we cannot safely promote it, - // so bail out in this case too. - if (!OutputLocations[Match].first || - isOperandMentioned(stmt, Match)) { - error_at(gimple_location(stmt), "unsupported inline asm: input " - "constraint with a matching output constraint of " - "incompatible type!"); - return; - } - // Use the input type for the output, and arrange for the result to - // be truncated to the original output type after the asm call. - CallResultTypes[OutputIndex] = std::make_pair(OpTy, IsSigned); - } else if (OTyBits > OpTyBits) { - // The input is smaller than the output. If the input is explicitly - // mentioned in the asm string then we cannot safely promote it, so - // bail out. - if (isOperandMentioned(stmt, NumOutputs + i)) { - error_at(gimple_location(stmt), "unsupported inline asm: input " - "constraint with a matching output constraint of " - "incompatible type!"); - return; - } - Op = CastToAnyType(Op, IsSigned, OTy, - CallResultTypes[OutputIndex].second); - } - } - } - - CallOps.push_back(Op); - } else { // Memory operand. - mark_addressable(TREE_VALUE(Input)); - isIndirect = true; - LValue Src = EmitLV(Val); - assert(!Src.isBitfield() && "Cannot read from a bitfield!"); - CallOps.push_back(Src.Ptr); - } - - ConstraintStr += ','; - if (isIndirect) - ConstraintStr += '*'; - - // If this input register is pinned to a machine register, use that machine - // register instead of the specified constraint. - if (TREE_CODE(Val) == VAR_DECL && DECL_HARD_REGISTER(Val)) { - const char *RegName = extractRegisterName(Val); - int RegNum = decode_reg_name(RegName); - if (RegNum >= 0) { - RegName = LLVM_GET_REG_NAME(RegName, RegNum); - ConstraintStr += '{'; - ConstraintStr += RegName; - ConstraintStr += '}'; - continue; - } - } - - // If there is a simpler form for the register constraint, use it. - std::string Simplified = CanonicalizeConstraint(Constraint); - ConstraintStr += Simplified; - } - - // Process clobbers. - - // Some targets automatically clobber registers across an asm. - tree Clobbers; - { - // Create input, output & clobber lists for the benefit of md_asm_clobbers. - tree outputs = NULL_TREE; - if (NumOutputs) { - tree t = outputs = gimple_asm_output_op (stmt, 0); - for (unsigned i = 1; i < NumOutputs; i++) { - TREE_CHAIN (t) = gimple_asm_output_op (stmt, i); - t = gimple_asm_output_op (stmt, i); - } - } - - tree inputs = NULL_TREE; - if (NumInputs) { - tree t = inputs = gimple_asm_input_op (stmt, 0); - for (unsigned i = 1; i < NumInputs; i++) { - TREE_CHAIN (t) = gimple_asm_input_op (stmt, i); - t = gimple_asm_input_op (stmt, i); - } - } - - tree clobbers = NULL_TREE; - if (NumClobbers) { - tree t = clobbers = gimple_asm_clobber_op (stmt, 0); - for (unsigned i = 1; i < NumClobbers; i++) { - TREE_CHAIN (t) = gimple_asm_clobber_op (stmt, i); - t = gimple_asm_clobber_op (stmt, i); - } - } - - Clobbers = targetm.md_asm_clobbers(outputs, inputs, clobbers); - } - - for (; Clobbers; Clobbers = TREE_CHAIN(Clobbers)) { - const char *RegName = TREE_STRING_POINTER(TREE_VALUE(Clobbers)); - int RegCode = decode_reg_name(RegName); - - switch (RegCode) { - case -1: // Nothing specified? - case -2: // Invalid. - error_at(gimple_location(stmt), "unknown register name %qs in %", - RegName); - return; - case -3: // cc - ConstraintStr += ",~{cc}"; - break; - case -4: // memory - ConstraintStr += ",~{memory}"; - break; - default: // Normal register name. - RegName = LLVM_GET_REG_NAME(RegName, RegCode); - ConstraintStr += ",~{"; - ConstraintStr += RegName; - ConstraintStr += "}"; - break; - } - } - - // Compute the return type to use for the asm call. - const Type *CallResultType; - switch (CallResultTypes.size()) { - // If there are no results then the return type is void! - case 0: CallResultType = Type::getVoidTy(Context); break; - // If there is one result then use the result's type as the return type. - case 1: CallResultType = CallResultTypes[0].first; break; - // If the asm returns multiple results then create a struct type with the - // result types as its fields, and use it for the return type. - default: - std::vector Fields(CallResultTypes.size()); - for (unsigned i = 0, e = CallResultTypes.size(); i != e; ++i) - Fields[i] = CallResultTypes[i].first; - CallResultType = StructType::get(Context, Fields); - break; - } - - // Compute the types of the arguments to the asm call. - std::vector CallArgTypes(CallOps.size()); - for (unsigned i = 0, e = CallOps.size(); i != e; ++i) - CallArgTypes[i] = CallOps[i]->getType(); - - // Get the type of the called asm "function". - const FunctionType *FTy = - FunctionType::get(CallResultType, CallArgTypes, false); - - // Remove the leading comma if we have operands. - if (!ConstraintStr.empty()) - ConstraintStr.erase(ConstraintStr.begin()); - - // Make sure we're created a valid inline asm expression. - if (!InlineAsm::Verify(FTy, ConstraintStr)) { - error_at(gimple_location(stmt), "Invalid or unsupported inline assembly!"); - return; - } - - std::string NewAsmStr = ConvertInlineAsmStr(stmt, NumOutputs+NumInputs); - Value *Asm = InlineAsm::get(FTy, NewAsmStr, ConstraintStr, HasSideEffects); - CallInst *CV = Builder.CreateCall(Asm, CallOps.begin(), CallOps.end(), - CallResultTypes.empty() ? "" : "asmtmp"); - CV->setDoesNotThrow(); - - // If the call produces a value, store it into the destination. - for (unsigned i = 0, NumResults = CallResultTypes.size(); i != NumResults; - ++i) { - Value *Val = NumResults == 1 ? - CV : Builder.CreateExtractValue(CV, i, "asmresult"); - bool ValIsSigned = CallResultTypes[i].second; - - Value *Dest = CallResultDests[i].first; - const Type *DestTy = cast(Dest->getType())->getElementType(); - bool DestIsSigned = CallResultDests[i].second; - Val = CastToAnyType(Val, ValIsSigned, DestTy, DestIsSigned); - Builder.CreateStore(Val, Dest); - } - - // If the call defined any ssa names, associate them with their value. - for (unsigned i = 0, e = SSADefinitions.size(); i != e; ++i) { - tree Name = SSADefinitions[i].first; - MemRef Loc = SSADefinitions[i].second; - Value *Val = LoadRegisterFromMemory(Loc, TREE_TYPE(Name), Builder); - DefineSSAName(Name, Val); - } - - // Give the backend a chance to upgrade the inline asm to LLVM code. This - // handles some common cases that LLVM has intrinsics for, e.g. x86 bswap -> - // llvm.bswap. - if (const TargetLowering *TLI = TheTarget->getTargetLowering()) - TLI->ExpandInlineAsm(CV); -} - -void TreeToLLVM::RenderGIMPLE_ASSIGN(gimple stmt) { - tree lhs = gimple_assign_lhs(stmt); - if (AGGREGATE_TYPE_P(TREE_TYPE(lhs))) { - assert(get_gimple_rhs_class(gimple_expr_code(stmt)) == GIMPLE_SINGLE_RHS && - "Aggregate type but rhs not simple!"); - LValue LV = EmitLV(lhs); - MemRef NewLoc(LV.Ptr, LV.getAlignment(), TREE_THIS_VOLATILE(lhs)); - EmitAggregate(gimple_assign_rhs1 (stmt), NewLoc); - return; - } - WriteScalarToLHS(lhs, EmitAssignRHS(stmt)); -} - -void TreeToLLVM::RenderGIMPLE_CALL(gimple stmt) { - tree lhs = gimple_call_lhs(stmt); - if (!lhs) { - // The returned value is not used. - if (!AGGREGATE_TYPE_P(gimple_call_return_type(stmt))) { - OutputCallRHS(stmt, 0); - return; - } - // Create a temporary to hold the returned value. - // TODO: Figure out how to avoid creating this temporary and the - // associated useless code that stores the returned value into it. - MemRef Loc = CreateTempLoc(ConvertType(gimple_call_return_type(stmt))); - OutputCallRHS(stmt, &Loc); - return; - } - - if (AGGREGATE_TYPE_P(TREE_TYPE(lhs))) { - LValue LV = EmitLV(lhs); - MemRef NewLoc(LV.Ptr, LV.getAlignment(), TREE_THIS_VOLATILE(lhs)); - OutputCallRHS(stmt, &NewLoc); - return; - } - WriteScalarToLHS(lhs, OutputCallRHS(stmt, 0)); -} - -void TreeToLLVM::RenderGIMPLE_COND(gimple stmt) { - // Emit the comparison. - Value *Cond = EmitCompare(gimple_cond_lhs(stmt), gimple_cond_rhs(stmt), - gimple_cond_code(stmt)); - - // Extract the target basic blocks. - edge true_edge, false_edge; - extract_true_false_edges_from_block(gimple_bb(stmt), &true_edge, &false_edge); - BasicBlock *IfTrue = getBasicBlock(true_edge->dest); - BasicBlock *IfFalse = getBasicBlock(false_edge->dest); - - // Branch based on the condition. - Builder.CreateCondBr(Cond, IfTrue, IfFalse); -} - -void TreeToLLVM::RenderGIMPLE_EH_DISPATCH(gimple stmt) { - int RegionNo = gimple_eh_dispatch_region(stmt); - eh_region region = get_eh_region_from_number(RegionNo); - - switch (region->type) { - default: - DieAbjectly("Unexpected region type!"); - case ERT_ALLOWED_EXCEPTIONS: { - // Filter. - BasicBlock *Dest = getLabelDeclBlock(region->u.allowed.label); - - if (!region->u.allowed.type_list) { - // Not allowed to throw. Branch directly to the post landing pad. - Builder.CreateBr(Dest); - BeginBlock(BasicBlock::Create(Context)); - break; - } - - // The result of a filter selection will be a negative index if there is a - // match. - // FIXME: It looks like you have to compare against a specific value, - // checking for any old negative number is not enough! This should not - // matter if the failure code branched to on a filter match is always the - // same (as in C++), but might cause problems with other languages. - Value *Filter = Builder.CreateLoad(getExceptionFilter(RegionNo)); - - // Compare with the filter action value. - Value *Zero = ConstantInt::get(Filter->getType(), 0); - Value *Compare = Builder.CreateICmpSLT(Filter, Zero); - - // Branch on the compare. - BasicBlock *NoMatchBB = BasicBlock::Create(Context); - Builder.CreateCondBr(Compare, Dest, NoMatchBB); - BeginBlock(NoMatchBB); - break; - } - case ERT_TRY: - // Catches. - Value *Filter = NULL; - SmallSet AlreadyCaught; // Typeinfos known caught. - Function *TypeIDIntr = Intrinsic::getDeclaration(TheModule, - Intrinsic::eh_typeid_for); - for (eh_catch c = region->u.eh_try.first_catch; c ; c = c->next_catch) { - BasicBlock *Dest = getLabelDeclBlock(c->label); - if (!c->type_list) { - // Catch-all. Branch directly to the post landing pad. - Builder.CreateBr(Dest); - break; - } - - Value *Cond = NULL; - for (tree type = c->type_list; type; type = TREE_CHAIN (type)) { - Value *TypeInfo = ConvertTypeInfo(TREE_VALUE(type)); - // No point in trying to catch a typeinfo that was already caught. - if (!AlreadyCaught.insert(TypeInfo)) - continue; - - TypeInfo = Builder.CreateBitCast(TypeInfo, Type::getInt8PtrTy(Context)); - - // Call get eh type id. - Value *TypeID = Builder.CreateCall(TypeIDIntr, TypeInfo, "typeid"); - - if (!Filter) - Filter = Builder.CreateLoad(getExceptionFilter(RegionNo)); - - // Compare with the exception selector. - Value *Compare = Builder.CreateICmpEQ(Filter, TypeID); - - Cond = Cond ? Builder.CreateOr(Cond, Compare) : Compare; - } - - if (Cond) { - BasicBlock *NoMatchBB = BasicBlock::Create(Context); - Builder.CreateCondBr(Cond, Dest, NoMatchBB); - BeginBlock(NoMatchBB); - } - } - break; - } -} - -void TreeToLLVM::RenderGIMPLE_GOTO(gimple stmt) { - tree dest = gimple_goto_dest(stmt); - - if (TREE_CODE(dest) == LABEL_DECL) { - // Direct branch. - Builder.CreateBr(getLabelDeclBlock(dest)); - return; - } - - // Indirect branch. - basic_block source = gimple_bb(stmt); - IndirectBrInst *Br = Builder.CreateIndirectBr(EmitRegister(dest), - EDGE_COUNT(source->succs)); - - // Add the list of possible destinations. - edge e; - edge_iterator ei; - FOR_EACH_EDGE (e, ei, source->succs) - Br->addDestination(getBasicBlock(e->dest)); -} - -void TreeToLLVM::RenderGIMPLE_RESX(gimple stmt) { - // Reraise an exception. If this statement is inside an exception handling - // region then the reraised exception may be caught by the current function, - // in which case it can be simplified into a branch. - int DstLPadNo = lookup_stmt_eh_lp(stmt); - eh_region dst_rgn = - DstLPadNo ? get_eh_region_from_lp_number(DstLPadNo) : NULL; - eh_region src_rgn = get_eh_region_from_number(gimple_resx_region(stmt)); - - if (!src_rgn) { - // Unreachable block? - Builder.CreateUnreachable(); - return; - } - - if (dst_rgn) { - if (DstLPadNo < 0) { - // The reraise is inside a must-not-throw region. Turn the reraise into a - // call to the failure routine (eg: std::terminate). - assert(dst_rgn->type == ERT_MUST_NOT_THROW && "Unexpected region type!"); - - // Branch to the block containing the failure code. - Builder.CreateBr(getFailureBlock(dst_rgn->index)); - return; - } - - // Use the exception pointer and filter value for the source region as the - // values for the destination region. - Value *ExcPtr = Builder.CreateLoad(getExceptionPtr(src_rgn->index)); - Builder.CreateStore(ExcPtr, getExceptionPtr(dst_rgn->index)); - Value *Filter = Builder.CreateLoad(getExceptionFilter(src_rgn->index)); - Builder.CreateStore(Filter, getExceptionFilter(dst_rgn->index)); - - // Branch to the post landing pad for the destination region. - eh_landing_pad lp = get_eh_landing_pad_from_number(DstLPadNo); - assert(lp && "Post landing pad not found!"); - Builder.CreateBr(getLabelDeclBlock(lp->post_landing_pad)); - return; - } - - // The exception unwinds out of the function. Note the exception to unwind. - if (!RewindTmp) { - RewindTmp = CreateTemporary(Type::getInt8PtrTy(Context)); - RewindTmp->setName("rewind_tmp"); - } - Value *ExcPtr = Builder.CreateLoad(getExceptionPtr(src_rgn->index)); - Builder.CreateStore(ExcPtr, RewindTmp); - - // Jump to the block containing the rewind code. - if (!RewindBB) - RewindBB = BasicBlock::Create(Context, "rewind"); - Builder.CreateBr(RewindBB); -} - -void TreeToLLVM::RenderGIMPLE_RETURN(gimple stmt) { - tree retval = gimple_return_retval(stmt); - tree result = DECL_RESULT(current_function_decl); - - if (retval && retval != error_mark_node && retval != result) { - // Store the return value to the function's DECL_RESULT. - MemRef DestLoc(DECL_LOCAL(result), 1, false); // FIXME: What alignment? - if (AGGREGATE_TYPE_P(TREE_TYPE(result))) { - EmitAggregate(retval, DestLoc); - } else { - Value *Val = Builder.CreateBitCast(EmitRegister(retval), - GetRegType(TREE_TYPE(result))); - StoreRegisterToMemory(Val, DestLoc, TREE_TYPE(result), Builder); - } - } - - // Emit a branch to the exit label. - Builder.CreateBr(ReturnBB); -} - -void TreeToLLVM::RenderGIMPLE_SWITCH(gimple stmt) { - // Emit the condition. - Value *Index = EmitRegister(gimple_switch_index(stmt)); - bool IndexIsSigned = !TYPE_UNSIGNED(TREE_TYPE(gimple_switch_index(stmt))); - - // Create the switch instruction. - tree default_label = CASE_LABEL(gimple_switch_label(stmt, 0)); - SwitchInst *SI = Builder.CreateSwitch(Index, getLabelDeclBlock(default_label), - gimple_switch_num_labels(stmt)); - - // Add the switch cases. - BasicBlock *IfBlock = 0; // Set if a range was output as an "if". - for (size_t i = 1, e = gimple_switch_num_labels(stmt); i != e; ++i) { - tree label = gimple_switch_label(stmt, i); - BasicBlock *Dest = getLabelDeclBlock(CASE_LABEL(label)); - - // Convert the integer to the right type. - Value *Val = EmitRegister(CASE_LOW(label)); - Val = CastToAnyType(Val, !TYPE_UNSIGNED(TREE_TYPE(CASE_LOW(label))), - Index->getType(), IndexIsSigned); - ConstantInt *LowC = cast(Val); - - if (!CASE_HIGH(label)) { - SI->addCase(LowC, Dest); // Single destination. - continue; - } - - // Otherwise, we have a range, like 'case 1 ... 17'. - Val = EmitRegister(CASE_HIGH(label)); - // Make sure the case value is the same type as the switch expression - Val = CastToAnyType(Val, !TYPE_UNSIGNED(TREE_TYPE(CASE_HIGH(label))), - Index->getType(), IndexIsSigned); - ConstantInt *HighC = cast(Val); - - APInt Range = HighC->getValue() - LowC->getValue(); - if (Range.ult(APInt(Range.getBitWidth(), 64))) { - // Add all of the necessary successors to the switch. - APInt CurrentValue = LowC->getValue(); - while (1) { - SI->addCase(LowC, Dest); - if (LowC == HighC) break; // Emitted the last one. - CurrentValue++; - LowC = ConstantInt::get(Context, CurrentValue); - } - } else { - // The range is too big to add to the switch - emit an "if". - if (!IfBlock) { - IfBlock = BasicBlock::Create(Context); - BeginBlock(IfBlock); - } - Value *Diff = Builder.CreateSub(Index, LowC); - Value *Cond = Builder.CreateICmpULE(Diff, - ConstantInt::get(Context, Range)); - BasicBlock *False_Block = BasicBlock::Create(Context); - Builder.CreateCondBr(Cond, Dest, False_Block); - BeginBlock(False_Block); - } - } - - if (IfBlock) { - Builder.CreateBr(SI->getDefaultDest()); - SI->setSuccessor(0, IfBlock); - } -} - - -//===----------------------------------------------------------------------===// -// ... Render helpers ... -//===----------------------------------------------------------------------===// - -/// EmitAssignRHS - Convert the RHS of a scalar GIMPLE_ASSIGN to LLVM. -Value *TreeToLLVM::EmitAssignRHS(gimple stmt) { - // Loads from memory and other non-register expressions are handled by - // EmitAssignSingleRHS. - if (get_gimple_rhs_class(gimple_expr_code(stmt)) == GIMPLE_SINGLE_RHS) { - Value *RHS = EmitAssignSingleRHS(gimple_assign_rhs1(stmt)); - assert(RHS->getType() == GetRegType(TREE_TYPE(gimple_assign_rhs1(stmt))) && - "RHS has wrong type!"); - return RHS; - } - - // The RHS is a register expression. Emit it now. - tree type = TREE_TYPE(gimple_assign_lhs(stmt)); - tree_code code = gimple_assign_rhs_code(stmt); - tree rhs1 = gimple_assign_rhs1(stmt); - tree rhs2 = gimple_assign_rhs2(stmt); - - Value *RHS = 0; - switch (code) { - default: - DieAbjectly("Unhandled GIMPLE assignment!", stmt); - - // Unary expressions. - case ABS_EXPR: - RHS = EmitReg_ABS_EXPR(rhs1); break; - case BIT_NOT_EXPR: - RHS = EmitReg_BIT_NOT_EXPR(rhs1); break; - case CONJ_EXPR: - RHS = EmitReg_CONJ_EXPR(rhs1); break; - case CONVERT_EXPR: - case FIX_TRUNC_EXPR: - case FLOAT_EXPR: - case NOP_EXPR: - RHS = EmitReg_CONVERT_EXPR(type, rhs1); break; - case NEGATE_EXPR: - RHS = EmitReg_NEGATE_EXPR(rhs1); break; - case PAREN_EXPR: - RHS = EmitReg_PAREN_EXPR(rhs1); break; - case TRUTH_NOT_EXPR: - RHS = EmitReg_TRUTH_NOT_EXPR(type, rhs1); break; - - // Comparisons. - case EQ_EXPR: - case GE_EXPR: - case GT_EXPR: - case LE_EXPR: - case LT_EXPR: - case LTGT_EXPR: - case NE_EXPR: - case ORDERED_EXPR: - case UNEQ_EXPR: - case UNGE_EXPR: - case UNGT_EXPR: - case UNLE_EXPR: - case UNLT_EXPR: - case UNORDERED_EXPR: - // The GCC result may be of any integer type. - RHS = Builder.CreateZExt(EmitCompare(rhs1, rhs2, code), GetRegType(type)); - break; - - // Binary expressions. - case BIT_AND_EXPR: - RHS = EmitReg_BIT_AND_EXPR(rhs1, rhs2); break; - case BIT_IOR_EXPR: - RHS = EmitReg_BIT_IOR_EXPR(rhs1, rhs2); break; - case BIT_XOR_EXPR: - RHS = EmitReg_BIT_XOR_EXPR(rhs1, rhs2); break; - case CEIL_DIV_EXPR: - RHS = EmitReg_CEIL_DIV_EXPR(type, rhs1, rhs2); break; - case COMPLEX_EXPR: - RHS = EmitReg_COMPLEX_EXPR(rhs1, rhs2); break; - case EXACT_DIV_EXPR: - RHS = EmitReg_TRUNC_DIV_EXPR(rhs1, rhs2, /*isExact*/true); break; - case FLOOR_DIV_EXPR: - RHS = EmitReg_FLOOR_DIV_EXPR(type, rhs1, rhs2); break; - case FLOOR_MOD_EXPR: - RHS = EmitReg_FLOOR_MOD_EXPR(type, rhs1, rhs2); break; - case LROTATE_EXPR: - RHS = EmitReg_RotateOp(type, rhs1, rhs2, Instruction::Shl, - Instruction::LShr); - break; - case LSHIFT_EXPR: - RHS = EmitReg_ShiftOp(rhs1, rhs2, Instruction::Shl); break; - case MAX_EXPR: - RHS = EmitReg_MinMaxExpr(type, rhs1, rhs2, ICmpInst::ICMP_UGE, - ICmpInst::ICMP_SGE, FCmpInst::FCMP_OGE, true); - break; - case MIN_EXPR: - RHS = EmitReg_MinMaxExpr(type, rhs1, rhs2, ICmpInst::ICMP_ULE, - ICmpInst::ICMP_SLE, FCmpInst::FCMP_OLE, false); - break; - case MINUS_EXPR: - RHS = EmitReg_MINUS_EXPR(rhs1, rhs2); break; - case MULT_EXPR: - RHS = EmitReg_MULT_EXPR(rhs1, rhs2); break; - case PLUS_EXPR: - RHS = EmitReg_PLUS_EXPR(rhs1, rhs2); break; - case POINTER_PLUS_EXPR: - RHS = EmitReg_POINTER_PLUS_EXPR(type, rhs1, rhs2); break; - case RDIV_EXPR: - RHS = EmitReg_RDIV_EXPR(rhs1, rhs2); break; - case ROUND_DIV_EXPR: - RHS = EmitReg_ROUND_DIV_EXPR(type, rhs1, rhs2); break; - case RROTATE_EXPR: - RHS = EmitReg_RotateOp(type, rhs1, rhs2, Instruction::LShr, - Instruction::Shl); - break; - case RSHIFT_EXPR: - RHS = EmitReg_ShiftOp(rhs1, rhs2, TYPE_UNSIGNED(type) ? - Instruction::LShr : Instruction::AShr); - break; - case TRUNC_DIV_EXPR: - RHS = EmitReg_TRUNC_DIV_EXPR(rhs1, rhs2, /*isExact*/false); break; - case TRUNC_MOD_EXPR: - RHS = EmitReg_TRUNC_MOD_EXPR(rhs1, rhs2); break; - case TRUTH_AND_EXPR: - RHS = EmitReg_TruthOp(type, rhs1, rhs2, Instruction::And); break; - case TRUTH_OR_EXPR: - RHS = EmitReg_TruthOp(type, rhs1, rhs2, Instruction::Or); break; - case TRUTH_XOR_EXPR: - RHS = EmitReg_TruthOp(type, rhs1, rhs2, Instruction::Xor); break; - } - - assert(RHS->getType() == GetRegType(type) && "RHS has wrong type!"); - return RHS; -} - -/// EmitAssignSingleRHS - Helper for EmitAssignRHS. Handles those RHS that are -/// not register expressions. -Value *TreeToLLVM::EmitAssignSingleRHS(tree rhs) { - assert(!AGGREGATE_TYPE_P(TREE_TYPE(rhs)) && "Expected a scalar type!"); - - switch (TREE_CODE(rhs)) { - // Catch-all for SSA names, constants etc. - default: return EmitRegister(rhs); - - // Expressions (tcc_expression). - case ADDR_EXPR: return EmitADDR_EXPR(rhs); - case OBJ_TYPE_REF: return EmitOBJ_TYPE_REF(rhs); - - // Exceptional (tcc_exceptional). - case CONSTRUCTOR: - // Vector constant constructors are gimple invariant. - return is_gimple_constant(rhs) ? - EmitRegisterConstant(rhs) : EmitCONSTRUCTOR(rhs, 0); - - // References (tcc_reference). - case ARRAY_REF: - case ARRAY_RANGE_REF: - case BIT_FIELD_REF: - case COMPONENT_REF: - case IMAGPART_EXPR: - case INDIRECT_REF: - case REALPART_EXPR: - case TARGET_MEM_REF: - case VIEW_CONVERT_EXPR: - return EmitLoadOfLValue(rhs); // Load from memory. - - // Declarations (tcc_declaration). - case PARM_DECL: - case RESULT_DECL: - case VAR_DECL: - return EmitLoadOfLValue(rhs); // Load from memory. - - // Constants (tcc_constant). - case STRING_CST: - return EmitLoadOfLValue(rhs); // Load from memory. - } -} - -/// OutputCallRHS - Convert the RHS of a GIMPLE_CALL. -Value *TreeToLLVM::OutputCallRHS(gimple stmt, const MemRef *DestLoc) { - // Check for a built-in function call. If we can lower it directly, do so - // now. - tree fndecl = gimple_call_fndecl(stmt); - if (fndecl && DECL_BUILT_IN(fndecl) && - DECL_BUILT_IN_CLASS(fndecl) != BUILT_IN_FRONTEND) { - Value *Res = 0; - if (EmitBuiltinCall(stmt, fndecl, DestLoc, Res)) - return Res ? Mem2Reg(Res, gimple_call_return_type(stmt), Builder) : 0; - } - - tree call_expr = gimple_call_fn(stmt); - assert(TREE_TYPE (call_expr) && - (TREE_CODE(TREE_TYPE (call_expr)) == POINTER_TYPE || - TREE_CODE(TREE_TYPE (call_expr)) == REFERENCE_TYPE) - && "Not calling a function pointer?"); - - tree function_type = TREE_TYPE(TREE_TYPE (call_expr)); - Value *Callee = EmitRegister(call_expr); - CallingConv::ID CallingConv; - AttrListPtr PAL; - - const Type *Ty = - TheTypeConverter->ConvertFunctionType(function_type, - fndecl, - gimple_call_chain(stmt), - CallingConv, PAL); - - // If this is a direct call to a function using a static chain then we need - // to ensure the function type is the one just calculated: it has an extra - // parameter for the chain. - Callee = Builder.CreateBitCast(Callee, Ty->getPointerTo()); - - Value *Result = EmitCallOf(Callee, stmt, DestLoc, PAL); - - // When calling a "noreturn" function output an unreachable instruction right - // after the function to prevent LLVM from thinking that control flow will - // fall into the subsequent block. - if (gimple_call_flags(stmt) & ECF_NORETURN) { - Builder.CreateUnreachable(); - BeginBlock(BasicBlock::Create(Context)); - } - - return Result ? Mem2Reg(Result, gimple_call_return_type(stmt), Builder) : 0; -} - -/// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS. -void TreeToLLVM::WriteScalarToLHS(tree lhs, Value *RHS) { - // Perform a useless type conversion (useless_type_conversion_p). - RHS = UselesslyTypeConvert(RHS, GetRegType(TREE_TYPE(lhs))); - - // If this is the definition of an ssa name, record it in the SSANames map. - if (TREE_CODE(lhs) == SSA_NAME) { - if (flag_verbose_asm) - NameValue(RHS, lhs); - DefineSSAName(lhs, RHS); - return; - } - - if (canEmitRegisterVariable(lhs)) { - // If this is a store to a register variable, EmitLV can't handle the dest - // (there is no l-value of a register variable). Emit an inline asm node - // that copies the value into the specified register. - EmitModifyOfRegisterVariable(lhs, RHS); - return; - } - - LValue LV = EmitLV(lhs); - LV.Volatile = TREE_THIS_VOLATILE(lhs); - // TODO: Arrange for Volatile to already be set in the LValue. - if (!LV.isBitfield()) { - // Non-bitfield, scalar value. Just emit a store. - StoreRegisterToMemory(RHS, LV, TREE_TYPE(lhs), Builder); - return; - } - - // Last case, this is a store to a bitfield, so we have to emit a - // read/modify/write sequence. - - if (!LV.BitSize) - return; - - unsigned Alignment = LV.getAlignment(); - - const Type *ValTy = cast(LV.Ptr->getType())->getElementType(); - unsigned ValSizeInBits = ValTy->getPrimitiveSizeInBits(); - - // The number of stores needed to write the entire bitfield. - unsigned Strides = 1 + (LV.BitStart + LV.BitSize - 1) / ValSizeInBits; - - assert(ValTy->isIntegerTy() && "Invalid bitfield lvalue!"); - assert(ValSizeInBits > LV.BitStart && "Bad bitfield lvalue!"); - assert(ValSizeInBits >= LV.BitSize && "Bad bitfield lvalue!"); - assert(2*ValSizeInBits > LV.BitSize+LV.BitStart && "Bad bitfield lvalue!"); - - bool Signed = !TYPE_UNSIGNED(TREE_TYPE(lhs)); - RHS = CastToAnyType(RHS, Signed, ValTy, Signed); - - for (unsigned I = 0; I < Strides; I++) { - unsigned Index = BYTES_BIG_ENDIAN ? Strides - I - 1 : I; // LSB first - unsigned ThisFirstBit = Index * ValSizeInBits; - unsigned ThisLastBitPlusOne = ThisFirstBit + ValSizeInBits; - if (ThisFirstBit < LV.BitStart) - ThisFirstBit = LV.BitStart; - if (ThisLastBitPlusOne > LV.BitStart+LV.BitSize) - ThisLastBitPlusOne = LV.BitStart+LV.BitSize; - - Value *Ptr = Index ? - Builder.CreateGEP(LV.Ptr, - ConstantInt::get(Type::getInt32Ty(Context), Index)) : - LV.Ptr; - LoadInst *LI = Builder.CreateLoad(Ptr, LV.Volatile); - LI->setAlignment(Alignment); - Value *OldVal = LI; - Value *NewVal = RHS; - - unsigned BitsInVal = ThisLastBitPlusOne - ThisFirstBit; - unsigned FirstBitInVal = ThisFirstBit % ValSizeInBits; - - if (BYTES_BIG_ENDIAN) - FirstBitInVal = ValSizeInBits-FirstBitInVal-BitsInVal; - - // If not storing into the zero'th bit, shift the Src value to the left. - if (FirstBitInVal) { - Value *ShAmt = ConstantInt::get(ValTy, FirstBitInVal); - NewVal = Builder.CreateShl(NewVal, ShAmt); - } - - // Next, if this doesn't touch the top bit, mask out any bits that shouldn't - // be set in the result. - uint64_t MaskVal = 1; - MaskVal = ((MaskVal << BitsInVal)-1) << FirstBitInVal; - Constant *Mask = ConstantInt::get(Type::getInt64Ty(Context), MaskVal); - Mask = Builder.getFolder().CreateTruncOrBitCast(Mask, ValTy); - - if (FirstBitInVal+BitsInVal != ValSizeInBits) - NewVal = Builder.CreateAnd(NewVal, Mask); - - // Next, mask out the bits this bit-field should include from the old value. - Mask = Builder.getFolder().CreateNot(Mask); - OldVal = Builder.CreateAnd(OldVal, Mask); - - // Finally, merge the two together and store it. - NewVal = Builder.CreateOr(OldVal, NewVal); - - StoreInst *SI = Builder.CreateStore(NewVal, Ptr, LV.Volatile); - SI->setAlignment(Alignment); - - if (I + 1 < Strides) { - Value *ShAmt = ConstantInt::get(ValTy, BitsInVal); - RHS = Builder.CreateLShr(RHS, ShAmt); - } - } -} Removed: dragonegg/trunk/Debug.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Debug.cpp?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/Debug.cpp (original) +++ dragonegg/trunk/Debug.cpp (removed) @@ -1,1811 +0,0 @@ -//===-------------- Debug.cpp - Debug information gathering ---------------===// -// -// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Jim Laskey, -// Duncan Sands et al. -// -// This file is part of DragonEgg. -// -// DragonEgg is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free Software -// Foundation; either version 2, or (at your option) any later version. -// -// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -// A PARTICULAR PURPOSE. See the GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along with -// DragonEgg; see the file COPYING. If not, write to the Free Software -// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. -// -//===----------------------------------------------------------------------===// -// This file implements debug information gathering. -//===----------------------------------------------------------------------===// - -// Plugin headers -#include "dragonegg/Debug.h" - -// LLVM headers -#include "llvm/Module.h" -#include "llvm/ADT/STLExtras.h" - -// System headers -#include - -// GCC headers -extern "C" { -#include "config.h" -// Stop GCC declaring 'getopt' as it can clash with the system's declaration. -#undef HAVE_DECL_GETOPT -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" - -#include "flags.h" -#include "langhooks.h" -#include "toplev.h" -#include "version.h" -} - -using namespace llvm; -using namespace llvm::dwarf; - -#ifndef LLVMTESTDEBUG -#define DEBUGASSERT(S) ((void)0) -#else -#define DEBUGASSERT(S) assert(S) -#endif - - -/// DirectoryAndFile - Extract the directory and file name from a path. If no -/// directory is specified, then use the source working directory. -static void DirectoryAndFile(const std::string &FullPath, - std::string &Directory, std::string &FileName) { - // Look for the directory slash. - size_t Slash = FullPath.rfind('/'); - - // If no slash - if (Slash == std::string::npos) { - // The entire path is the file name. - Directory = ""; - FileName = FullPath; - } else { - // Separate the directory from the file name. - Directory = FullPath.substr(0, Slash); - FileName = FullPath.substr(Slash + 1); - } - - // If no directory present then use source working directory. - if (Directory.empty() || Directory[0] != '/') { - Directory = std::string(get_src_pwd()) + "/" + Directory; - } -} - -/// NodeSizeInBits - Returns the size in bits stored in a tree node regardless -/// of whether the node is a TYPE or DECL. -static uint64_t NodeSizeInBits(tree Node) { - if (TREE_CODE(Node) == ERROR_MARK) { - return BITS_PER_WORD; - } else if (TYPE_P(Node)) { - if (TYPE_SIZE(Node) == NULL_TREE) - return 0; - else if (isInt64(TYPE_SIZE(Node), 1)) - return getINTEGER_CSTVal(TYPE_SIZE(Node)); - else - return TYPE_ALIGN(Node); - } else if (DECL_P(Node)) { - if (DECL_SIZE(Node) == NULL_TREE) - return 0; - else if (isInt64(DECL_SIZE(Node), 1)) - return getINTEGER_CSTVal(DECL_SIZE(Node)); - else - return DECL_ALIGN(Node); - } - - return 0; -} - -/// NodeAlignInBits - Returns the alignment in bits stored in a tree node -/// regardless of whether the node is a TYPE or DECL. -static uint64_t NodeAlignInBits(tree Node) { - if (TREE_CODE(Node) == ERROR_MARK) return BITS_PER_WORD; - if (TYPE_P(Node)) return TYPE_ALIGN(Node); - if (DECL_P(Node)) return DECL_ALIGN(Node); - return BITS_PER_WORD; -} - -/// FieldType - Returns the type node of a structure member field. -/// -static tree FieldType(tree Field) { - if (TREE_CODE (Field) == ERROR_MARK) return integer_type_node; - return DECL_BIT_FIELD_TYPE(Field) ? - DECL_BIT_FIELD_TYPE(Field) : TREE_TYPE (Field); -} - -/// GetNodeName - Returns the name stored in a node regardless of whether the -/// node is a TYPE or DECL. -static StringRef GetNodeName(tree Node) { - tree Name = NULL; - - if (DECL_P(Node)) { - Name = DECL_NAME(Node); - } else if (TYPE_P(Node)) { - Name = TYPE_NAME(Node); - } - - if (Name) { - if (TREE_CODE(Name) == IDENTIFIER_NODE) { - return IDENTIFIER_POINTER(Name); - } else if (TREE_CODE(Name) == TYPE_DECL && DECL_NAME(Name) && - !DECL_IGNORED_P(Name)) { - return StringRef(IDENTIFIER_POINTER(DECL_NAME(Name))); - } - } - - return StringRef(); -} - -/// GetNodeLocation - Returns the location stored in a node regardless of -/// whether the node is a TYPE or DECL. UseStub is true if we should consider -/// the type stub as the actually location (ignored in struct/unions/enums.) -static expanded_location GetNodeLocation(tree Node, bool UseStub = true) { - expanded_location Location = { NULL, 0, 0, false }; - - if (Node == NULL_TREE) - return Location; - - tree Name = NULL; - - if (DECL_P(Node)) { - Name = DECL_NAME(Node); - } else if (TYPE_P(Node)) { - Name = TYPE_NAME(Node); - } - - if (Name) { - if (TYPE_STUB_DECL(Name)) { - tree Stub = TYPE_STUB_DECL(Name); - Location = expand_location(DECL_SOURCE_LOCATION(Stub)); - } else if (DECL_P(Name)) { - Location = expand_location(DECL_SOURCE_LOCATION(Name)); - } - } - - if (!Location.line) { - if (UseStub && TYPE_STUB_DECL(Node)) { - tree Stub = TYPE_STUB_DECL(Node); - Location = expand_location(DECL_SOURCE_LOCATION(Stub)); - } else if (DECL_P(Node)) { - Location = expand_location(DECL_SOURCE_LOCATION(Node)); - } - } - - return Location; -} - -static StringRef getLinkageName(tree Node) { - - // Use llvm value name as linkage name if it is available. - if (DECL_LLVM_SET_P(Node)) { - Value *V = DECL_LLVM(Node); - return V->getName(); - } - - tree decl_name = DECL_NAME(Node); - if (decl_name != NULL && IDENTIFIER_POINTER (decl_name) != NULL) { - if (TREE_PUBLIC(Node) && - DECL_ASSEMBLER_NAME(Node) != DECL_NAME(Node) && - !DECL_ABSTRACT(Node)) { - return StringRef(IDENTIFIER_POINTER(DECL_ASSEMBLER_NAME(Node))); - } - } - return StringRef(); -} - -DebugInfo::DebugInfo(Module *m) -: M(m) -, DebugFactory(*m) -, CurFullPath("") -, CurLineNo(0) -, PrevFullPath("") -, PrevLineNo(0) -, PrevBB(NULL) -, RegionStack() -{} - -/// getFunctionName - Get function name for the given FnDecl. If the -/// name is constructred on demand (e.g. C++ destructor) then the name -/// is stored on the side. -StringRef DebugInfo::getFunctionName(tree FnDecl) { - StringRef FnNodeName = GetNodeName(FnDecl); - // Use dwarf_name to construct function names. In C++ this is used to - // create human readable destructor names. - StringRef FnName = lang_hooks.dwarf_name(FnDecl, 0); - if (FnNodeName.equals(FnName)) - return FnNodeName; - - // Use name returned by dwarf_name. It is in a temp. storage so make a - // copy first. - char *StrPtr = FunctionNames.Allocate(FnName.size() + 1); - strncpy(StrPtr, FnName.data(), FnName.size()); - StrPtr[FnName.size()] = 0; - return StringRef(StrPtr); -} - -/// EmitFunctionStart - Constructs the debug code for entering a function. -void DebugInfo::EmitFunctionStart(tree FnDecl, Function *Fn) { - DIType FNType = getOrCreateType(TREE_TYPE(FnDecl)); - - std::map::iterator I = SPCache.find(FnDecl); - if (I != SPCache.end()) { - DISubprogram SPDecl(cast(I->second)); - DISubprogram SP = - DebugFactory.CreateSubprogramDefinition(SPDecl); - SPDecl->replaceAllUsesWith(SP); - - // Push function on region stack. - RegionStack.push_back(WeakVH(SP)); - RegionMap[FnDecl] = WeakVH(SP); - return; - } - - bool ArtificialFnWithAbstractOrigin = false; - // If this artificial function has abstract origin then put this function - // at module scope. The abstract copy will be placed in appropriate region. - if (DECL_ARTIFICIAL (FnDecl) - && DECL_ABSTRACT_ORIGIN (FnDecl) - && DECL_ABSTRACT_ORIGIN (FnDecl) != FnDecl) - ArtificialFnWithAbstractOrigin = true; - - DIDescriptor SPContext = ArtificialFnWithAbstractOrigin ? - getOrCreateFile(main_input_filename) : - findRegion (DECL_CONTEXT(FnDecl)); - - // Creating context may have triggered creation of this SP descriptor. So - // check the cache again. - I = SPCache.find(FnDecl); - if (I != SPCache.end()) { - DISubprogram SPDecl(cast(I->second)); - DISubprogram SP = - DebugFactory.CreateSubprogramDefinition(SPDecl); - SPDecl->replaceAllUsesWith(SP); - - // Push function on region stack. - RegionStack.push_back(WeakVH(SP)); - RegionMap[FnDecl] = WeakVH(SP); - return; - } - - // Gather location information. - expanded_location Loc = GetNodeLocation(FnDecl, false); - StringRef LinkageName = getLinkageName(FnDecl); - - unsigned lineno = CurLineNo; - - unsigned Virtuality = 0; - unsigned VIndex = 0; - DIType ContainingType; - if (DECL_VINDEX (FnDecl) && - DECL_CONTEXT (FnDecl) && TYPE_P((DECL_CONTEXT (FnDecl)))) { // Workaround GCC PR42653 - if (host_integerp (DECL_VINDEX (FnDecl), 0)) - VIndex = tree_low_cst (DECL_VINDEX (FnDecl), 0); - Virtuality = dwarf::DW_VIRTUALITY_virtual; - ContainingType = getOrCreateType(DECL_CONTEXT (FnDecl)); - } - - StringRef FnName = getFunctionName(FnDecl); - - DISubprogram SP = - DebugFactory.CreateSubprogram(SPContext, - FnName, FnName, - LinkageName, - getOrCreateFile(Loc.file), lineno, - FNType, - Fn->hasInternalLinkage(), - true /*definition*/, - Virtuality, VIndex, ContainingType, - DECL_ARTIFICIAL (FnDecl), optimize); - - SPCache[FnDecl] = WeakVH(SP); - - // Push function on region stack. - RegionStack.push_back(WeakVH(SP)); - RegionMap[FnDecl] = WeakVH(SP); -} - -/// getOrCreateNameSpace - Get name space descriptor for the tree node. -DINameSpace DebugInfo::getOrCreateNameSpace(tree Node, DIDescriptor Context) { - std::map::iterator I = - NameSpaceCache.find(Node); - if (I != NameSpaceCache.end()) - return DINameSpace(cast(I->second)); - - expanded_location Loc = GetNodeLocation(Node, false); - DINameSpace DNS = - DebugFactory.CreateNameSpace(Context, GetNodeName(Node), - getOrCreateFile(Loc.file), Loc.line); - - NameSpaceCache[Node] = WeakVH(DNS); - return DNS; -} - -/// findRegion - Find tree_node N's region. -DIDescriptor DebugInfo::findRegion(tree Node) { - if (Node == NULL_TREE) - return getOrCreateFile(main_input_filename); - - std::map::iterator I = RegionMap.find(Node); - if (I != RegionMap.end()) - if (MDNode *R = dyn_cast_or_null(&*I->second)) - return DIDescriptor(R); - - if (TYPE_P (Node)) { - DIType Ty = getOrCreateType(Node); - return DIDescriptor(Ty); - } else if (DECL_P (Node)) { - if (TREE_CODE (Node) == NAMESPACE_DECL) { - DIDescriptor NSContext = findRegion(DECL_CONTEXT(Node)); - DINameSpace NS = getOrCreateNameSpace(Node, NSContext); - return DIDescriptor(NS); - } - return findRegion (DECL_CONTEXT (Node)); - } - - // Otherwise main compile unit covers everything. - return getOrCreateFile(main_input_filename); -} - -/// EmitFunctionEnd - Pop the region stack and reset current lexical block. -void DebugInfo::EmitFunctionEnd(bool EndFunction) { - assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); - RegionStack.pop_back(); - // Blocks get erased; clearing these is needed for determinism, and also - // a good idea if the next function gets inlined. - if (EndFunction) { - PrevBB = NULL; - PrevLineNo = 0; - PrevFullPath = NULL; - } -} - -/// EmitDeclare - Constructs the debug code for allocation of a new variable. -void DebugInfo::EmitDeclare(tree decl, unsigned Tag, const char *Name, - tree type, Value *AI, LLVMBuilder &Builder) { - - // Ignore compiler generated temporaries. - if (DECL_IGNORED_P(decl)) - return; - - assert(!RegionStack.empty() && "Region stack mismatch, stack empty!"); - - expanded_location Loc = GetNodeLocation(decl, false); - - // Construct variable. - DIScope VarScope = DIScope(cast(RegionStack.back())); - DIType Ty = getOrCreateType(type); - if (!Ty && TREE_CODE(type) == OFFSET_TYPE) - Ty = createPointerType(TREE_TYPE(type)); - if (DECL_ARTIFICIAL (decl)) - Ty = DebugFactory.CreateArtificialType(Ty); - // If type info is not available then do not emit debug info for this var. - if (!Ty) - return; - llvm::DIVariable D = - DebugFactory.CreateVariable(Tag, VarScope, - Name, getOrCreateFile(Loc.file), - Loc.line, Ty, optimize); - - Instruction *Call = - DebugFactory.InsertDeclare(AI, D, Builder.GetInsertBlock()); - - Call->setDebugLoc(DebugLoc::get(Loc.line, 0, VarScope)); -} - -/// EmitStopPoint - Set current source location. -void DebugInfo::EmitStopPoint(BasicBlock *CurBB, LLVMBuilder &Builder) { - // Don't bother if things are the same as last time. - if (PrevLineNo == CurLineNo && - PrevBB == CurBB && - (PrevFullPath == CurFullPath || - !strcmp(PrevFullPath, CurFullPath))) return; - if (!CurFullPath[0] || CurLineNo == 0) return; - - // Update last state. - PrevFullPath = CurFullPath; - PrevLineNo = CurLineNo; - PrevBB = CurBB; - - if (RegionStack.empty()) - return; - MDNode *Scope = cast(RegionStack.back()); - Builder.SetCurrentDebugLocation(DebugLoc::get(CurLineNo,0/*col*/,Scope)); -} - -/// EmitGlobalVariable - Emit information about a global variable. -/// -void DebugInfo::EmitGlobalVariable(GlobalVariable *GV, tree decl) { - if (DECL_ARTIFICIAL(decl) || DECL_IGNORED_P(decl)) - return; - // Gather location information. - expanded_location Loc = expand_location(DECL_SOURCE_LOCATION(decl)); - DIType TyD = getOrCreateType(TREE_TYPE(decl)); - StringRef DispName = GV->getName(); - if (DECL_NAME(decl)) { - if (IDENTIFIER_POINTER(DECL_NAME(decl))) - DispName = IDENTIFIER_POINTER(DECL_NAME(decl)); - } - StringRef LinkageName; - // The gdb does not expect linkage names for function local statics. - if (DECL_CONTEXT (decl)) - if (TREE_CODE (DECL_CONTEXT (decl)) != FUNCTION_DECL) - LinkageName = GV->getName(); - DebugFactory.CreateGlobalVariable(findRegion(DECL_CONTEXT(decl)), - DispName, DispName, LinkageName, - getOrCreateFile(Loc.file), Loc.line, - TyD, GV->hasInternalLinkage(), - true/*definition*/, GV); -} - -/// createBasicType - Create BasicType. -DIType DebugInfo::createBasicType(tree type) { - - StringRef TypeName = GetNodeName(type); - uint64_t Size = NodeSizeInBits(type); - uint64_t Align = NodeAlignInBits(type); - - unsigned Encoding = 0; - - switch (TREE_CODE(type)) { - case INTEGER_TYPE: - if (TYPE_STRING_FLAG (type)) { - if (TYPE_UNSIGNED (type)) - Encoding = DW_ATE_unsigned_char; - else - Encoding = DW_ATE_signed_char; - } - else if (TYPE_UNSIGNED (type)) - Encoding = DW_ATE_unsigned; - else - Encoding = DW_ATE_signed; - break; - case REAL_TYPE: - Encoding = DW_ATE_float; - break; - case COMPLEX_TYPE: - Encoding = TREE_CODE(TREE_TYPE(type)) == REAL_TYPE ? - DW_ATE_complex_float : DW_ATE_lo_user; - break; - case BOOLEAN_TYPE: - Encoding = DW_ATE_boolean; - break; - default: { - DEBUGASSERT(0 && "Basic type case missing"); - Encoding = DW_ATE_signed; - Size = BITS_PER_WORD; - Align = BITS_PER_WORD; - break; - } - } - - return - DebugFactory.CreateBasicType(getOrCreateFile(main_input_filename), - TypeName, - getOrCreateFile(main_input_filename), - 0, Size, Align, - 0, 0, Encoding); -} - -/// isArtificialArgumentType - Return true if arg_type represents artificial, -/// i.e. "this" in c++, argument. -static bool isArtificialArgumentType(tree arg_type, tree method_type) { - if (TREE_CODE (method_type) != METHOD_TYPE) return false; - if (TREE_CODE (arg_type) != POINTER_TYPE) return false; - if (TREE_TYPE (arg_type) == TYPE_METHOD_BASETYPE (method_type)) - return true; - if (TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) - && TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) != TREE_TYPE (arg_type) - && (TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) - == TYPE_METHOD_BASETYPE (method_type))) - return true; - return false; -} - -/// createMethodType - Create MethodType. -DIType DebugInfo::createMethodType(tree type) { - - // Create a place holder type first. The may be used as a context - // for the argument types. - llvm::DIType FwdType = DebugFactory.CreateTemporaryType(); - llvm::MDNode *FTN = FwdType; - llvm::TrackingVH FwdTypeNode = FTN; - TypeCache[type] = WeakVH(FwdType); - // Push the struct on region stack. - RegionStack.push_back(WeakVH(FwdType)); - RegionMap[type] = WeakVH(FwdType); - - llvm::SmallVector EltTys; - - // Add the result type at least. - EltTys.push_back(getOrCreateType(TREE_TYPE(type))); - - // Set up remainder of arguments. - bool ProcessedFirstArg = false; - for (tree arg = TYPE_ARG_TYPES(type); arg; arg = TREE_CHAIN(arg)) { - tree formal_type = TREE_VALUE(arg); - if (formal_type == void_type_node) break; - llvm::DIType FormalType = getOrCreateType(formal_type); - if (!ProcessedFirstArg && isArtificialArgumentType(formal_type, type)) { - DIType AFormalType = DebugFactory.CreateArtificialType(FormalType); - EltTys.push_back(AFormalType); - } else - EltTys.push_back(FormalType); - if (!ProcessedFirstArg) - ProcessedFirstArg = true; - } - - llvm::DIArray EltTypeArray = - DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); - - RegionStack.pop_back(); - std::map::iterator RI = RegionMap.find(type); - if (RI != RegionMap.end()) - RegionMap.erase(RI); - - llvm::DIType RealType = - DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, - findRegion(TYPE_CONTEXT(type)), - StringRef(), - getOrCreateFile(main_input_filename), - 0, 0, 0, 0, 0, - llvm::DIType(), EltTypeArray); - - // Now that we have a real decl for the struct, replace anything using the - // old decl with the new one. This will recursively update the debug info. - llvm::DIType(FwdTypeNode).replaceAllUsesWith(RealType); - - return RealType; -} - -/// createPointerType - Create PointerType. -DIType DebugInfo::createPointerType(tree type) { - - DIType FromTy = getOrCreateType(TREE_TYPE(type)); - // type* and type& - // FIXME: Should BLOCK_POINTER_TYP have its own DW_TAG? - unsigned Tag = TREE_CODE(type) == REFERENCE_TYPE ? - DW_TAG_reference_type: DW_TAG_pointer_type; - unsigned Flags = 0; - - // Check if this pointer type has a name. - if (tree TyName = TYPE_NAME(type)) - if (TREE_CODE(TyName) == TYPE_DECL && !DECL_ORIGINAL_TYPE(TyName)) { - expanded_location TypeNameLoc = GetNodeLocation(TyName); - DIType Ty = - DebugFactory.CreateDerivedType(Tag, findRegion(DECL_CONTEXT(TyName)), - GetNodeName(TyName), - getOrCreateFile(TypeNameLoc.file), - TypeNameLoc.line, - 0 /*size*/, - 0 /*align*/, - 0 /*offset */, - 0 /*flags*/, - FromTy); - TypeCache[TyName] = WeakVH(Ty); - return Ty; - } - - StringRef PName = FromTy.getName(); - DIType PTy = - DebugFactory.CreateDerivedType(Tag, findRegion(TYPE_CONTEXT(type)), - Tag == DW_TAG_pointer_type ? - StringRef() : PName, - getOrCreateFile(main_input_filename), - 0 /*line no*/, - NodeSizeInBits(type), - NodeAlignInBits(type), - 0 /*offset */, - Flags, - FromTy); - return PTy; -} - -/// createArrayType - Create ArrayType. -DIType DebugInfo::createArrayType(tree type) { - - // type[n][m]...[p] - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_STRING_FLAG(type) && TREE_CODE(TREE_TYPE(type)) == INTEGER_TYPE){ - DEBUGASSERT(0 && "Don't support pascal strings"); - return DIType(); - } - - unsigned Tag = 0; - - if (TREE_CODE(type) == VECTOR_TYPE) { - Tag = DW_TAG_vector_type; - type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type))); - } - else - Tag = DW_TAG_array_type; - - // Add the dimensions of the array. FIXME: This loses CV qualifiers from - // interior arrays, do we care? Why aren't nested arrays represented the - // obvious/recursive way? - llvm::SmallVector Subscripts; - - // There will be ARRAY_TYPE nodes for each rank. Followed by the derived - // type. - tree atype = type; - tree EltTy = TREE_TYPE(atype); - for (; TREE_CODE(atype) == ARRAY_TYPE; - atype = TREE_TYPE(atype)) { - tree Domain = TYPE_DOMAIN(atype); - if (Domain) { - // FIXME - handle dynamic ranges - tree MinValue = TYPE_MIN_VALUE(Domain); - tree MaxValue = TYPE_MAX_VALUE(Domain); - uint64_t Low = 0; - uint64_t Hi = 0; - if (isInt64(MinValue, false)) - Low = getINTEGER_CSTVal(MinValue); - if (isInt64(MaxValue, false)) - Hi = getINTEGER_CSTVal(MaxValue); - Subscripts.push_back(DebugFactory.GetOrCreateSubrange(Low, Hi)); - } - EltTy = TREE_TYPE(atype); - } - - llvm::DIArray SubscriptArray = - DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size()); - expanded_location Loc = GetNodeLocation(type); - return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type, - findRegion(TYPE_CONTEXT(type)), - StringRef(), - getOrCreateFile(Loc.file), 0, - NodeSizeInBits(type), - NodeAlignInBits(type), 0, 0, - getOrCreateType(EltTy), - SubscriptArray); -} - -/// createEnumType - Create EnumType. -DIType DebugInfo::createEnumType(tree type) { - // enum { a, b, ..., z }; - llvm::SmallVector Elements; - - if (TYPE_SIZE(type)) { - for (tree Link = TYPE_VALUES(type); Link; Link = TREE_CHAIN(Link)) { - tree EnumValue = TREE_VALUE(Link); - if (TREE_CODE(EnumValue) == CONST_DECL) - EnumValue = DECL_INITIAL(EnumValue); - int64_t Value = getINTEGER_CSTVal(EnumValue); - const char *EnumName = IDENTIFIER_POINTER(TREE_PURPOSE(Link)); - Elements.push_back(DebugFactory.CreateEnumerator(EnumName, Value)); - } - } - - llvm::DIArray EltArray = - DebugFactory.GetOrCreateArray(Elements.data(), Elements.size()); - - expanded_location Loc = { NULL, 0, 0, false }; - if (TYPE_SIZE(type)) - // Incomplete enums do not have any location info. - Loc = GetNodeLocation(TREE_CHAIN(type), false); - - return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type, - findRegion(TYPE_CONTEXT(type)), - GetNodeName(type), - getOrCreateFile(Loc.file), - Loc.line, - NodeSizeInBits(type), - NodeAlignInBits(type), 0, 0, - llvm::DIType(), EltArray); -} - -/// createStructType - Create StructType for struct or union or class. -DIType DebugInfo::createStructType(tree type) { - - // struct { a; b; ... z; }; | union { a; b; ... z; }; - unsigned Tag = TREE_CODE(type) == RECORD_TYPE ? DW_TAG_structure_type : - DW_TAG_union_type; - - unsigned RunTimeLang = 0; -//TODO if (TYPE_LANG_SPECIFIC (type) -//TODO && lang_hooks.types.is_runtime_specific_type (type)) -//TODO { -//TODO unsigned CULang = TheCU.getLanguage(); -//TODO switch (CULang) { -//TODO case DW_LANG_ObjC_plus_plus : -//TODO RunTimeLang = DW_LANG_ObjC_plus_plus; -//TODO break; -//TODO case DW_LANG_ObjC : -//TODO RunTimeLang = DW_LANG_ObjC; -//TODO break; -//TODO case DW_LANG_C_plus_plus : -//TODO RunTimeLang = DW_LANG_C_plus_plus; -//TODO break; -//TODO default: -//TODO break; -//TODO } -//TODO } - - // Records and classes and unions can all be recursive. To handle them, - // we first generate a debug descriptor for the struct as a forward - // declaration. Then (if it is a definition) we go through and get debug - // info for all of its members. Finally, we create a descriptor for the - // complete type (which may refer to the forward decl if the struct is - // recursive) and replace all uses of the forward declaration with the - // final definition. - expanded_location Loc = GetNodeLocation(TREE_CHAIN(type), false); - unsigned SFlags = 0; - DIDescriptor TyContext = findRegion(TYPE_CONTEXT(type)); - - // Check if this type is created while creating context information - // descriptor. - std::map::iterator I = TypeCache.find(type); - if (I != TypeCache.end()) - if (MDNode *TN = dyn_cast_or_null(&*I->second)) - return DIType(TN); - - // forward declaration, - if (TYPE_SIZE(type) == 0) { - llvm::DICompositeType FwdDecl = - DebugFactory.CreateCompositeType(Tag, - TyContext, - GetNodeName(type), - getOrCreateFile(Loc.file), - Loc.line, - 0, 0, 0, - SFlags | llvm::DIType::FlagFwdDecl, - llvm::DIType(), llvm::DIArray(), - RunTimeLang); - return FwdDecl; - } - - llvm::DIType FwdDecl = DebugFactory.CreateTemporaryType(); - - // Insert into the TypeCache so that recursive uses will find it. - llvm::MDNode *FDN = FwdDecl; - llvm::TrackingVH FwdDeclNode = FDN; - TypeCache[type] = WeakVH(FwdDecl); - - // Push the struct on region stack. - RegionStack.push_back(WeakVH(FwdDecl)); - RegionMap[type] = WeakVH(FwdDecl); - - // Convert all the elements. - llvm::SmallVector EltTys; - - if (tree binfo = TYPE_BINFO(type)) { - VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo); - - for (unsigned i = 0, e = BINFO_N_BASE_BINFOS(binfo); i != e; ++i) { - tree BInfo = BINFO_BASE_BINFO(binfo, i); - tree BInfoType = BINFO_TYPE (BInfo); - DIType BaseClass = getOrCreateType(BInfoType); - unsigned BFlags = 0; - if (BINFO_VIRTUAL_P (BInfo)) - BFlags = llvm::DIType::FlagVirtual; - if (accesses) { - tree access = VEC_index (tree, accesses, i); - if (access == access_protected_node) - BFlags |= llvm::DIType::FlagProtected; - else if (access == access_private_node) - BFlags |= llvm::DIType::FlagPrivate; - } - - // Check for zero BINFO_OFFSET. - // FIXME : Is this correct ? - unsigned Offset = BINFO_OFFSET(BInfo) ? - getINTEGER_CSTVal(BINFO_OFFSET(BInfo))*8 : 0; - - if (BINFO_VIRTUAL_P (BInfo)) - Offset = 0 - getINTEGER_CSTVal(BINFO_VPTR_FIELD (BInfo)); - // FIXME : name, size, align etc... - DIType DTy = - DebugFactory.CreateDerivedType(DW_TAG_inheritance, - findRegion(TYPE_CONTEXT(type)), StringRef(), - llvm::DIFile(), 0,0,0, - Offset, - BFlags, BaseClass); - EltTys.push_back(DTy); - } - } - - // Now add members of this class. - for (tree Member = TYPE_FIELDS(type); Member; - Member = TREE_CHAIN(Member)) { - // Should we skip. - if (DECL_P(Member) && DECL_IGNORED_P(Member)) continue; - - // Get the location of the member. - expanded_location MemLoc = GetNodeLocation(Member, false); - - if (TREE_CODE(Member) != FIELD_DECL) - // otherwise is a static variable, whose debug info is emitted - // when through EmitGlobalVariable(). - continue; - - if (!OffsetIsLLVMCompatible(Member)) - // FIXME: field with variable or humongous offset. - // Skip it for now. - continue; - - /* Ignore nameless fields. */ - if (DECL_NAME (Member) == NULL_TREE - && !(TREE_CODE (TREE_TYPE (Member)) == UNION_TYPE - || TREE_CODE (TREE_TYPE (Member)) == RECORD_TYPE)) - continue; - - // Field type is the declared type of the field. - tree FieldNodeType = FieldType(Member); - DIType MemberType = getOrCreateType(FieldNodeType); - StringRef MemberName = GetNodeName(Member); - unsigned MFlags = 0; - if (TREE_PROTECTED(Member)) - MFlags = llvm::DIType::FlagProtected; - else if (TREE_PRIVATE(Member)) - MFlags = llvm::DIType::FlagPrivate; - - DIType DTy = - DebugFactory.CreateDerivedType(DW_TAG_member, - findRegion(DECL_CONTEXT(Member)), - MemberName, - getOrCreateFile(MemLoc.file), - MemLoc.line, NodeSizeInBits(Member), - NodeAlignInBits(FieldNodeType), - int_bit_position(Member), - MFlags, MemberType); - EltTys.push_back(DTy); - } - - for (tree Member = TYPE_METHODS(type); Member; - Member = TREE_CHAIN(Member)) { - - if (DECL_ABSTRACT_ORIGIN (Member)) continue; - // Ignore unused aritificial members. - if (DECL_ARTIFICIAL (Member) && !TREE_USED (Member)) continue; - // In C++, TEMPLATE_DECLs are marked Ignored, and should be. - if (DECL_P (Member) && DECL_IGNORED_P (Member)) continue; - - std::map::iterator I = SPCache.find(Member); - if (I != SPCache.end()) - EltTys.push_back(DISubprogram(cast(I->second))); - else { - // Get the location of the member. - expanded_location MemLoc = GetNodeLocation(Member, false); - StringRef MemberName = getFunctionName(Member); - StringRef LinkageName = getLinkageName(Member); - DIType SPTy = getOrCreateType(TREE_TYPE(Member)); - unsigned Virtuality = 0; - unsigned VIndex = 0; - DIType ContainingType; - if (DECL_VINDEX (Member)) { - if (host_integerp (DECL_VINDEX (Member), 0)) - VIndex = tree_low_cst (DECL_VINDEX (Member), 0); - Virtuality = dwarf::DW_VIRTUALITY_virtual; - ContainingType = getOrCreateType(DECL_CONTEXT(Member)); - } - DISubprogram SP = - DebugFactory.CreateSubprogram(findRegion(DECL_CONTEXT(Member)), - MemberName, MemberName, - LinkageName, - getOrCreateFile(MemLoc.file), - MemLoc.line, SPTy, false, false, - Virtuality, VIndex, ContainingType, - DECL_ARTIFICIAL (Member), optimize); - EltTys.push_back(SP); - SPCache[Member] = WeakVH(SP); - } - } - - llvm::DIArray Elements = - DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); - - RegionStack.pop_back(); - std::map::iterator RI = RegionMap.find(type); - if (RI != RegionMap.end()) - RegionMap.erase(RI); - - llvm::DIType ContainingType; - if (TYPE_VFIELD (type)) { - tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type)); - ContainingType = getOrCreateType(vtype); - } - llvm::DICompositeType RealDecl = - DebugFactory.CreateCompositeType(Tag, findRegion(TYPE_CONTEXT(type)), - GetNodeName(type), - getOrCreateFile(Loc.file), - Loc.line, - NodeSizeInBits(type), NodeAlignInBits(type), - 0, SFlags, llvm::DIType(), Elements, - RunTimeLang, ContainingType); - RegionMap[type] = WeakVH(RealDecl); - - // Now that we have a real decl for the struct, replace anything using the - // old decl with the new one. This will recursively update the debug info. - llvm::DIType(FwdDeclNode).replaceAllUsesWith(RealDecl); - - return RealDecl; -} - -/// createVarinatType - Create variant type or return MainTy. -DIType DebugInfo::createVariantType(tree type, DIType MainTy) { - - DIType Ty; - if (tree TyDef = TYPE_NAME(type)) { - std::map::iterator I = TypeCache.find(TyDef); - if (I != TypeCache.end()) - if (Value *M = I->second) - return DIType(cast(M)); - if (TREE_CODE(TyDef) == TYPE_DECL && DECL_ORIGINAL_TYPE(TyDef)) { - expanded_location TypeDefLoc = GetNodeLocation(TyDef); - Ty = DebugFactory.CreateDerivedType(DW_TAG_typedef, - findRegion(DECL_CONTEXT(TyDef)), - GetNodeName(TyDef), - getOrCreateFile(TypeDefLoc.file), - TypeDefLoc.line, - 0 /*size*/, - 0 /*align*/, - 0 /*offset */, - 0 /*flags*/, - MainTy); - TypeCache[TyDef] = WeakVH(Ty); - return Ty; - } - } - - if (TYPE_VOLATILE(type)) { - Ty = DebugFactory.CreateDerivedType(DW_TAG_volatile_type, - findRegion(TYPE_CONTEXT(type)), - StringRef(), - getOrCreateFile(main_input_filename), - 0 /*line no*/, - NodeSizeInBits(type), - NodeAlignInBits(type), - 0 /*offset */, - 0 /* flags */, - MainTy); - MainTy = Ty; - } - - if (TYPE_READONLY(type)) - Ty = DebugFactory.CreateDerivedType(DW_TAG_const_type, - findRegion(TYPE_CONTEXT(type)), - StringRef(), - getOrCreateFile(main_input_filename), - 0 /*line no*/, - NodeSizeInBits(type), - NodeAlignInBits(type), - 0 /*offset */, - 0 /* flags */, - MainTy); - - if (TYPE_VOLATILE(type) || TYPE_READONLY(type)) { - TypeCache[type] = WeakVH(Ty); - return Ty; - } - - // If, for some reason, main type varaint type is seen then use it. - return MainTy; -} - -/// getOrCreateType - Get the type from the cache or create a new type if -/// necessary. -DIType DebugInfo::getOrCreateType(tree type) { - DEBUGASSERT(type != NULL_TREE && type != error_mark_node && - "Not a type."); - if (type == NULL_TREE || type == error_mark_node) return DIType(); - - // Should only be void if a pointer/reference/return type. Returning NULL - // allows the caller to produce a non-derived type. - if (TREE_CODE(type) == VOID_TYPE) return DIType(); - - // Check to see if the compile unit already has created this type. - std::map::iterator I = TypeCache.find(type); - if (I != TypeCache.end()) - if (Value *M = I->second) - return DIType(cast(M)); - - DIType MainTy; - if (type != TYPE_MAIN_VARIANT(type) && TYPE_MAIN_VARIANT(type)) - MainTy = getOrCreateType(TYPE_MAIN_VARIANT(type)); - - DIType Ty = createVariantType(type, MainTy); - if (Ty.isValid()) - return Ty; - - // Work out details of type. - switch (TREE_CODE(type)) { - case ERROR_MARK: - case LANG_TYPE: - case TRANSLATION_UNIT_DECL: - default: { - DEBUGASSERT(0 && "Unsupported type"); - return DIType(); - } - - case POINTER_TYPE: - case REFERENCE_TYPE: - // Do not cache pointer type. The pointer may point to forward declared - // struct. - return createPointerType(type); - break; - - case OFFSET_TYPE: { - // gen_type_die(TYPE_OFFSET_BASETYPE(type), context_die); - // gen_type_die(TREE_TYPE(type), context_die); - // gen_ptr_to_mbr_type_die(type, context_die); - // PR 7104 - break; - } - - case FUNCTION_TYPE: - case METHOD_TYPE: - Ty = createMethodType(type); - break; - - case VECTOR_TYPE: - case ARRAY_TYPE: - Ty = createArrayType(type); - break; - - case ENUMERAL_TYPE: - Ty = createEnumType(type); - break; - - case RECORD_TYPE: - case QUAL_UNION_TYPE: - case UNION_TYPE: - return createStructType(type); - break; - - case INTEGER_TYPE: - case REAL_TYPE: - case COMPLEX_TYPE: - case BOOLEAN_TYPE: - Ty = createBasicType(type); - break; - } - TypeCache[type] = WeakVH(Ty); - return Ty; -} - -/// Initialize - Initialize debug info by creating compile unit for -/// main_input_filename. This must be invoked after language dependent -/// initialization is done. -void DebugInfo::Initialize() { - - // Each input file is encoded as a separate compile unit in LLVM - // debugging information output. However, many target specific tool chains - // prefer to encode only one compile unit in an object file. In this - // situation, the LLVM code generator will include debugging information - // entities in the compile unit that is marked as main compile unit. The - // code generator accepts maximum one main compile unit per module. If a - // module does not contain any main compile unit then the code generator - // will emit multiple compile units in the output object file. - if (!strcmp (main_input_filename, "")) - TheCU = getOrCreateCompileUnit("", true); - else - TheCU = getOrCreateCompileUnit(main_input_filename, true); -} - -/// getOrCreateCompileUnit - Get the compile unit from the cache or -/// create a new one if necessary. -DICompileUnit DebugInfo::getOrCreateCompileUnit(const char *FullPath, - bool isMain) { - if (!FullPath) { - if (!strcmp (main_input_filename, "")) - FullPath = ""; - else - FullPath = main_input_filename; - } - - // Get source file information. - std::string Directory; - std::string FileName; - DirectoryAndFile(FullPath, Directory, FileName); - - // Set up Language number. - unsigned LangTag; - const std::string LanguageName(lang_hooks.name); - if (LanguageName == "GNU C") - LangTag = DW_LANG_C89; - else if (LanguageName == "GNU C++") - LangTag = DW_LANG_C_plus_plus; - else if (LanguageName == "GNU Ada") - LangTag = DW_LANG_Ada95; - else if (LanguageName == "GNU F77") - LangTag = DW_LANG_Fortran77; - else if (LanguageName == "GNU Pascal") - LangTag = DW_LANG_Pascal83; - else if (LanguageName == "GNU Java") - LangTag = DW_LANG_Java; - else if (LanguageName == "GNU Objective-C") - LangTag = DW_LANG_ObjC; - else if (LanguageName == "GNU Objective-C++") - LangTag = DW_LANG_ObjC_plus_plus; - else - LangTag = DW_LANG_C89; - - StringRef Flags; - - // flag_objc_abi represents Objective-C runtime version number. It is zero - // for all other language. - unsigned ObjcRunTimeVer = 0; -// if (flag_objc_abi != 0 && flag_objc_abi != -1) -// ObjcRunTimeVer = flag_objc_abi; - return DebugFactory.CreateCompileUnit(LangTag, FileName.c_str(), - Directory.c_str(), - version_string, isMain, - optimize, Flags, - ObjcRunTimeVer); -} - -/// getOrCreateFile - Get DIFile descriptor. -DIFile DebugInfo::getOrCreateFile(const char *FullPath) { - if (!FullPath) { - if (!strcmp (main_input_filename, "")) - FullPath = ""; - else - FullPath = main_input_filename; - } - - // Get source file information. - std::string Directory; - std::string FileName; - DirectoryAndFile(FullPath, Directory, FileName); - return DebugFactory.CreateFile(FileName, Directory, TheCU); -} - -//===----------------------------------------------------------------------===// -// DIFactory: Basic Helpers -//===----------------------------------------------------------------------===// - -DIFactory::DIFactory(Module &m) - : M(m), VMContext(M.getContext()), DeclareFn(0), ValueFn(0) {} - -Constant *DIFactory::GetTagConstant(unsigned TAG) { - assert((TAG & LLVMDebugVersionMask) == 0 && - "Tag too large for debug encoding!"); - return ConstantInt::get(Type::getInt32Ty(VMContext), TAG | LLVMDebugVersion); -} - -//===----------------------------------------------------------------------===// -// DIFactory: Primary Constructors -//===----------------------------------------------------------------------===// - -/// GetOrCreateArray - Create an descriptor for an array of descriptors. -/// This implicitly uniques the arrays created. -DIArray DIFactory::GetOrCreateArray(DIDescriptor *Tys, unsigned NumTys) { - if (NumTys == 0) { - Value *Null = llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)); - return DIArray(MDNode::get(VMContext, &Null, 1)); - } - - SmallVector Elts(Tys, Tys+NumTys); - return DIArray(MDNode::get(VMContext, Elts.data(), Elts.size())); -} - -/// GetOrCreateSubrange - Create a descriptor for a value range. This -/// implicitly uniques the values returned. -DISubrange DIFactory::GetOrCreateSubrange(int64_t Lo, int64_t Hi) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subrange_type), - ConstantInt::get(Type::getInt64Ty(VMContext), Lo), - ConstantInt::get(Type::getInt64Ty(VMContext), Hi) - }; - - return DISubrange(MDNode::get(VMContext, &Elts[0], 3)); -} - -/// CreateUnspecifiedParameter - Create unspeicified type descriptor -/// for the subroutine type. -DIDescriptor DIFactory::CreateUnspecifiedParameter() { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_unspecified_parameters) - }; - return DIDescriptor(MDNode::get(VMContext, &Elts[0], 1)); -} - -/// CreateCompileUnit - Create a new descriptor for the specified compile -/// unit. Note that this does not unique compile units within the module. -DICompileUnit DIFactory::CreateCompileUnit(unsigned LangID, - StringRef Filename, - StringRef Directory, - StringRef Producer, - bool isMain, - bool isOptimized, - StringRef Flags, - unsigned RunTimeVer) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_compile_unit), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - ConstantInt::get(Type::getInt32Ty(VMContext), LangID), - MDString::get(VMContext, Filename), - MDString::get(VMContext, Directory), - MDString::get(VMContext, Producer), - ConstantInt::get(Type::getInt1Ty(VMContext), isMain), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - MDString::get(VMContext, Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer) - }; - - return DICompileUnit(MDNode::get(VMContext, &Elts[0], 10)); -} - -/// CreateFile - Create a new descriptor for the specified file. -DIFile DIFactory::CreateFile(StringRef Filename, - StringRef Directory, - DICompileUnit CU) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_file_type), - MDString::get(VMContext, Filename), - MDString::get(VMContext, Directory), - CU - }; - - return DIFile(MDNode::get(VMContext, &Elts[0], 4)); -} - -/// CreateEnumerator - Create a single enumerator value. -DIEnumerator DIFactory::CreateEnumerator(StringRef Name, uint64_t Val){ - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_enumerator), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt64Ty(VMContext), Val) - }; - return DIEnumerator(MDNode::get(VMContext, &Elts[0], 3)); -} - - -/// CreateBasicType - Create a basic type like int, float, etc. -DIBasicType DIFactory::CreateBasicType(DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - unsigned Encoding) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_base_type), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) - }; - return DIBasicType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateBasicType - Create a basic type like int, float, etc. -DIBasicType DIFactory::CreateBasicTypeEx(DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, unsigned Flags, - unsigned Encoding) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_base_type), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) - }; - return DIBasicType(MDNode::get(VMContext, &Elts[0], 10)); -} - -/// CreateArtificialType - Create a new DIType with "artificial" flag set. -DIType DIFactory::CreateArtificialType(DIType Ty) { - if (Ty.isArtificial()) - return Ty; - - SmallVector Elts; - MDNode *N = Ty; - assert (N && "Unexpected input DIType!"); - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { - if (Value *V = N->getOperand(i)) - Elts.push_back(V); - else - Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))); - } - - unsigned CurFlags = Ty.getFlags(); - CurFlags = CurFlags | DIType::FlagArtificial; - - // Flags are stored at this slot. - Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); - - return DIType(MDNode::get(VMContext, Elts.data(), Elts.size())); -} - -/// CreateDerivedType - Create a derived type like const qualified type, -/// pointer, typedef, etc. -DIDerivedType DIFactory::CreateDerivedType(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, - unsigned Flags, - DIType DerivedFrom) { - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom, - }; - return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateDerivedType - Create a derived type like const qualified type, -/// pointer, typedef, etc. -DIDerivedType DIFactory::CreateDerivedTypeEx(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, - unsigned Flags, - DIType DerivedFrom) { - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom, - }; - return DIDerivedType(MDNode::get(VMContext, &Elts[0], 10)); -} - - -/// CreateCompositeType - Create a composite type like array, struct, etc. -DICompositeType DIFactory::CreateCompositeType(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - uint64_t SizeInBits, - uint64_t AlignInBits, - uint64_t OffsetInBits, - unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RuntimeLang, - MDNode *ContainingType) { - - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom, - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang), - ContainingType - }; - - MDNode *Node = MDNode::get(VMContext, &Elts[0], 13); - // Create a named metadata so that we do not lose this enum info. - if (Tag == dwarf::DW_TAG_enumeration_type) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum"); - NMD->addOperand(Node); - } - return DICompositeType(Node); -} - -/// CreateTemporaryType - Create a temporary forward-declared type. -DIType DIFactory::CreateTemporaryType() { - // Give the temporary MDNode a tag. It doesn't matter what tag we - // use here as long as DIType accepts it. - Value *Elts[] = { - GetTagConstant(DW_TAG_base_type) - }; - MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); - return DIType(Node); -} - -/// CreateTemporaryType - Create a temporary forward-declared type. -DIType DIFactory::CreateTemporaryType(DIFile F) { - // Give the temporary MDNode a tag. It doesn't matter what tag we - // use here as long as DIType accepts it. - Value *Elts[] = { - GetTagConstant(DW_TAG_base_type), - F.getCompileUnit(), - NULL, - F - }; - MDNode *Node = MDNode::getTemporary(VMContext, Elts, array_lengthof(Elts)); - return DIType(Node); -} - -/// CreateCompositeType - Create a composite type like array, struct, etc. -DICompositeType DIFactory::CreateCompositeTypeEx(unsigned Tag, - DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNumber, - Constant *SizeInBits, - Constant *AlignInBits, - Constant *OffsetInBits, - unsigned Flags, - DIType DerivedFrom, - DIArray Elements, - unsigned RuntimeLang, - MDNode *ContainingType) { - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - SizeInBits, - AlignInBits, - OffsetInBits, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom, - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang), - ContainingType - }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], 13); - // Create a named metadata so that we do not lose this enum info. - if (Tag == dwarf::DW_TAG_enumeration_type) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.enum"); - NMD->addOperand(Node); - } - return DICompositeType(Node); -} - - -/// CreateSubprogram - Create a new descriptor for the specified subprogram. -/// See comments in DISubprogram for descriptions of these fields. This -/// method does not unique the generated descriptors. -DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context, - StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty, - bool isLocalToUnit, - bool isDefinition, - unsigned VK, unsigned VIndex, - DIType ContainingType, - unsigned Flags, - bool isOptimized, - Function *Fn) { - - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subprogram), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, - MDString::get(VMContext, Name), - MDString::get(VMContext, DisplayName), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK), - ConstantInt::get(Type::getInt32Ty(VMContext), VIndex), - ContainingType, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - Fn - }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], 17); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); - NMD->addOperand(Node); - return DISubprogram(Node); -} - -/// CreateSubprogramDefinition - Create new subprogram descriptor for the -/// given declaration. -DISubprogram DIFactory::CreateSubprogramDefinition(DISubprogram &SPDeclaration){ - if (SPDeclaration.isDefinition()) - return DISubprogram(SPDeclaration); - - MDNode *DeclNode = SPDeclaration; - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_subprogram), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - DeclNode->getOperand(2), // Context - DeclNode->getOperand(3), // Name - DeclNode->getOperand(4), // DisplayName - DeclNode->getOperand(5), // LinkageName - DeclNode->getOperand(6), // CompileUnit - DeclNode->getOperand(7), // LineNo - DeclNode->getOperand(8), // Type - DeclNode->getOperand(9), // isLocalToUnit - ConstantInt::get(Type::getInt1Ty(VMContext), true), - DeclNode->getOperand(11), // Virtuality - DeclNode->getOperand(12), // VIndex - DeclNode->getOperand(13), // Containting Type - DeclNode->getOperand(14), // Flags - DeclNode->getOperand(15), // isOptimized - SPDeclaration.getFunction() - }; - MDNode *Node =MDNode::get(VMContext, &Elts[0], 16); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.sp"); - NMD->addOperand(Node); - return DISubprogram(Node); -} - -/// CreateGlobalVariable - Create a new descriptor for the specified global. -DIGlobalVariable -DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty,bool isLocalToUnit, - bool isDefinition, llvm::GlobalVariable *Val) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_variable), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, - MDString::get(VMContext, Name), - MDString::get(VMContext, DisplayName), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - Val - }; - - Value *const *Vs = &Elts[0]; - MDNode *Node = MDNode::get(VMContext,Vs, 12); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); - NMD->addOperand(Node); - - return DIGlobalVariable(Node); -} - -/// CreateGlobalVariable - Create a new descriptor for the specified constant. -DIGlobalVariable -DIFactory::CreateGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef DisplayName, - StringRef LinkageName, - DIFile F, - unsigned LineNo, DIType Ty,bool isLocalToUnit, - bool isDefinition, llvm::Constant *Val) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_variable), - llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)), - Context, - MDString::get(VMContext, Name), - MDString::get(VMContext, DisplayName), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - Val - }; - - Value *const *Vs = &Elts[0]; - MDNode *Node = MDNode::get(VMContext,Vs, 12); - - // Create a named metadata so that we do not lose this mdnode. - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.gv"); - NMD->addOperand(Node); - - return DIGlobalVariable(Node); -} - -/// CreateVariable - Create a new descriptor for the specified variable. -DIVariable DIFactory::CreateVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, - DIFile F, - unsigned LineNo, - DIType Ty, bool AlwaysPreserve, - unsigned Flags) { - Value *Elts[] = { - GetTagConstant(Tag), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags) - }; - MDNode *Node = MDNode::get(VMContext, &Elts[0], 7); - if (AlwaysPreserve) { - // The optimizer may remove local variable. If there is an interest - // to preserve variable info in such situation then stash it in a - // named mdnode. - DISubprogram Fn(getDISubprogram(Context)); - StringRef FName = "fn"; - if (Fn.getFunction()) - FName = Fn.getFunction()->getName(); - char One = '\1'; - if (FName.startswith(StringRef(&One, 1))) - FName = FName.substr(1); - - - NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, FName); - FnLocals->addOperand(Node); - } - return DIVariable(Node); -} - - -/// CreateComplexVariable - Create a new descriptor for the specified variable -/// which has a complex address expression for its address. -DIVariable DIFactory::CreateComplexVariable(unsigned Tag, DIDescriptor Context, - StringRef Name, DIFile F, - unsigned LineNo, - DIType Ty, Value *const *Addr, - unsigned NumAddr) { - SmallVector Elts; - Elts.push_back(GetTagConstant(Tag)); - Elts.push_back(Context); - Elts.push_back(MDString::get(VMContext, Name)); - Elts.push_back(F); - Elts.push_back(ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)); - Elts.push_back(Ty); - Elts.append(Addr, Addr+NumAddr); - - return DIVariable(MDNode::get(VMContext, Elts.data(), Elts.size())); -} - - -/// CreateBlock - This creates a descriptor for a lexical block with the -/// specified parent VMContext. -DILexicalBlock DIFactory::CreateLexicalBlock(DIDescriptor Context, - DIFile F, unsigned LineNo, - unsigned Col) { - // Defeat MDNode uniqing for lexical blocks. - static unsigned int unique_id = 0; - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_lexical_block), - Context, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), Col), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++) - }; - return DILexicalBlock(MDNode::get(VMContext, &Elts[0], 6)); -} - -/// CreateNameSpace - This creates new descriptor for a namespace -/// with the specified parent context. -DINameSpace DIFactory::CreateNameSpace(DIDescriptor Context, StringRef Name, - DIFile F, - unsigned LineNo) { - Value *Elts[] = { - GetTagConstant(dwarf::DW_TAG_namespace), - Context, - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) - }; - return DINameSpace(MDNode::get(VMContext, &Elts[0], 5)); -} - -/// CreateLocation - Creates a debug info location. -DILocation DIFactory::CreateLocation(unsigned LineNo, unsigned ColumnNo, - DIScope S, DILocation OrigLoc) { - Value *Elts[] = { - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo), - S, - OrigLoc, - }; - return DILocation(MDNode::get(VMContext, &Elts[0], 4)); -} - -//===----------------------------------------------------------------------===// -// DIFactory: Routines for inserting code into a function -//===----------------------------------------------------------------------===// - -/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. -Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, - Instruction *InsertBefore) { - assert(Storage && "no storage passed to dbg.declare"); - assert(D.Verify() && "empty DIVariable passed to dbg.declare"); - if (!DeclareFn) - DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - - Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), - D }; - return CallInst::Create(DeclareFn, Args, Args+2, "", InsertBefore); -} - -/// InsertDeclare - Insert a new llvm.dbg.declare intrinsic call. -Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D, - BasicBlock *InsertAtEnd) { - assert(Storage && "no storage passed to dbg.declare"); - assert(D.Verify() && "invalid DIVariable passed to dbg.declare"); - if (!DeclareFn) - DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - - Value *Args[] = { MDNode::get(Storage->getContext(), &Storage, 1), - D }; - - // If this block already has a terminator then insert this intrinsic - // before the terminator. - if (TerminatorInst *T = InsertAtEnd->getTerminator()) - return CallInst::Create(DeclareFn, Args, Args+2, "", T); - else - return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd);} - -/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. -Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, - DIVariable D, - Instruction *InsertBefore) { - assert(V && "no value passed to dbg.value"); - assert(D.Verify() && "invalid DIVariable passed to dbg.value"); - if (!ValueFn) - ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - - Value *Args[] = { MDNode::get(V->getContext(), &V, 1), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - D }; - return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore); -} - -/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. -Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, uint64_t Offset, - DIVariable D, - BasicBlock *InsertAtEnd) { - assert(V && "no value passed to dbg.value"); - assert(D.Verify() && "invalid DIVariable passed to dbg.value"); - if (!ValueFn) - ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - - Value *Args[] = { MDNode::get(V->getContext(), &V, 1), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - D }; - return CallInst::Create(ValueFn, Args, Args+3, "", InsertAtEnd); -} - -// RecordType - Record DIType in a module such that it is not lost even if -// it is not referenced through debug info anchors. -void DIFactory::RecordType(DIType T) { - NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.ty"); - NMD->addOperand(T); -} Removed: dragonegg/trunk/DefaultABI.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/DefaultABI.cpp?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/DefaultABI.cpp (original) +++ dragonegg/trunk/DefaultABI.cpp (removed) @@ -1,462 +0,0 @@ -//===------------ DefaultABI.cpp - Default ABI implementation -------------===// -// -// Copyright (C) 2010, 2011 Rafael Espindola, Duncan Sands et al. -// -// This file is part of DragonEgg. -// -// DragonEgg is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free Software -// Foundation; either version 2, or (at your option) any later version. -// -// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -// A PARTICULAR PURPOSE. See the GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along with -// DragonEgg; see the file COPYING. If not, write to the Free Software -// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. -// -//===----------------------------------------------------------------------===// -// This file implements the default ABI. -//===----------------------------------------------------------------------===// - -// Plugin headers -#include "dragonegg/ABI.h" - -// System headers -#include - -// GCC headers -extern "C" { -#include "config.h" -// Stop GCC declaring 'getopt' as it can clash with the system's declaration. -#undef HAVE_DECL_GETOPT -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" -} - -// doNotUseShadowReturn - Return true if the specified GCC type -// should not be returned using a pointer to struct parameter. -bool doNotUseShadowReturn(tree type, tree fndecl, CallingConv::ID /*CC*/) { - if (!TYPE_SIZE(type)) - return false; - if (TREE_CODE(TYPE_SIZE(type)) != INTEGER_CST) - return false; - // LLVM says do not use shadow argument. - if (LLVM_SHOULD_NOT_RETURN_COMPLEX_IN_MEMORY(type) || - LLVM_SHOULD_NOT_USE_SHADOW_RETURN(type, CC)) - return true; - // GCC says use shadow argument. - if (aggregate_value_p(type, fndecl)) - return false; - return true; -} - -/// isSingleElementStructOrArray - If this is (recursively) a structure with one -/// field or an array with one element, return the field type, otherwise return -/// null. Returns null for complex number types. If ignoreZeroLength, the -/// struct (recursively) may include zero-length fields in addition to the -/// single element that has data. If rejectFatBitField, and the single element -/// is a bitfield of a type that's bigger than the struct, return null anyway. -tree isSingleElementStructOrArray(tree type, bool ignoreZeroLength, - bool rejectFatBitfield) { - // Complex numbers have two fields. - if (TREE_CODE(type) == COMPLEX_TYPE) return 0; - // All other scalars are good. - if (!AGGREGATE_TYPE_P(type)) return type; - - tree FoundField = 0; - switch (TREE_CODE(type)) { - case QUAL_UNION_TYPE: - case UNION_TYPE: // Single element unions don't count. - case COMPLEX_TYPE: // Complex values are like 2-element records. - default: - return 0; - case RECORD_TYPE: - // If this record has variable length, reject it. - if (TREE_CODE(TYPE_SIZE(type)) != INTEGER_CST) - return 0; - - for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) - if (TREE_CODE(Field) == FIELD_DECL) { - if (ignoreZeroLength) { - if (DECL_SIZE(Field) && - TREE_CODE(DECL_SIZE(Field)) == INTEGER_CST && - TREE_INT_CST_LOW(DECL_SIZE(Field)) == 0) - continue; - } - if (!FoundField) { - if (rejectFatBitfield && - TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST && - TREE_INT_CST_LOW(TYPE_SIZE(TREE_TYPE(Field))) > - TREE_INT_CST_LOW(TYPE_SIZE(type))) - return 0; - FoundField = TREE_TYPE(Field); - } else { - return 0; // More than one field. - } - } - return FoundField ? isSingleElementStructOrArray(FoundField, - ignoreZeroLength, false) - : 0; - case ARRAY_TYPE: - const ArrayType *Ty = dyn_cast(ConvertType(type)); - if (!Ty || Ty->getNumElements() != 1) - return 0; - return isSingleElementStructOrArray(TREE_TYPE(type), false, false); - } -} - -/// isZeroSizedStructOrUnion - Returns true if this is a struct or union -/// which is zero bits wide. -bool isZeroSizedStructOrUnion(tree type) { - if (TREE_CODE(type) != RECORD_TYPE && - TREE_CODE(type) != UNION_TYPE && - TREE_CODE(type) != QUAL_UNION_TYPE) - return false; - return int_size_in_bytes(type) == 0; -} - -DefaultABI::DefaultABI(DefaultABIClient &c) : C(c) {} - -bool DefaultABI::isShadowReturn() const { return C.isShadowReturn(); } - -/// HandleReturnType - This is invoked by the target-independent code for the -/// return type. It potentially breaks down the argument and invokes methods -/// on the client that indicate how its pieces should be handled. This -/// handles things like returning structures via hidden parameters. -void DefaultABI::HandleReturnType(tree type, tree fn, bool isBuiltin) { - unsigned Offset = 0; - const Type *Ty = ConvertType(type); - if (Ty->isVectorTy()) { - // Vector handling is weird on x86. In particular builtin and - // non-builtin function of the same return types can use different - // calling conventions. - tree ScalarType = LLVM_SHOULD_RETURN_VECTOR_AS_SCALAR(type, isBuiltin); - if (ScalarType) - C.HandleAggregateResultAsScalar(ConvertType(ScalarType)); - else if (LLVM_SHOULD_RETURN_VECTOR_AS_SHADOW(type, isBuiltin)) - C.HandleScalarShadowResult(Ty->getPointerTo(), false); - else - C.HandleScalarResult(Ty); - } else if (Ty->isSingleValueType() || Ty->isVoidTy()) { - // Return scalar values normally. - C.HandleScalarResult(Ty); - } else if (doNotUseShadowReturn(type, fn, C.getCallingConv())) { - tree SingleElt = LLVM_SHOULD_RETURN_SELT_STRUCT_AS_SCALAR(type); - if (SingleElt && TYPE_SIZE(SingleElt) && - TREE_CODE(TYPE_SIZE(SingleElt)) == INTEGER_CST && - TREE_INT_CST_LOW(TYPE_SIZE_UNIT(type)) == - TREE_INT_CST_LOW(TYPE_SIZE_UNIT(SingleElt))) { - C.HandleAggregateResultAsScalar(ConvertType(SingleElt)); - } else { - // Otherwise return as an integer value large enough to hold the entire - // aggregate. - if (const Type *AggrTy = LLVM_AGGR_TYPE_FOR_STRUCT_RETURN(type, - C.getCallingConv())) - C.HandleAggregateResultAsAggregate(AggrTy); - else if (const Type* ScalarTy = - LLVM_SCALAR_TYPE_FOR_STRUCT_RETURN(type, &Offset)) - C.HandleAggregateResultAsScalar(ScalarTy, Offset); - else - DieAbjectly("Unable to determine how to return this aggregate!"); - } - } else { - // If the function is returning a struct or union, we pass the pointer to - // the struct as the first argument to the function. - - // FIXME: should return the hidden first argument for some targets - // (e.g. ELF i386). - if (AGGREGATE_TYPE_P(type)) - C.HandleAggregateShadowResult(Ty->getPointerTo(), false); - else - C.HandleScalarShadowResult(Ty->getPointerTo(), false); - } -} - -/// HandleArgument - This is invoked by the target-independent code for each -/// argument type passed into the function. It potentially breaks down the -/// argument and invokes methods on the client that indicate how its pieces -/// should be handled. This handles things like decimating structures into -/// their fields. -void DefaultABI::HandleArgument(tree type, std::vector &ScalarElts, - Attributes *Attributes) { - unsigned Size = 0; - bool DontCheckAlignment = false; - const Type *Ty = ConvertType(type); - // Figure out if this field is zero bits wide, e.g. {} or [0 x int]. Do - // not include variable sized fields here. - std::vector Elts; - if (Ty->isVoidTy()) { - // Handle void explicitly as an opaque type. - const Type *OpTy = OpaqueType::get(getGlobalContext()); - C.HandleScalarArgument(OpTy, type); - ScalarElts.push_back(OpTy); - } else if (isPassedByInvisibleReference(type)) { // variable size -> by-ref. - const Type *PtrTy = Ty->getPointerTo(); - C.HandleByInvisibleReferenceArgument(PtrTy, type); - ScalarElts.push_back(PtrTy); - } else if (Ty->isVectorTy()) { - if (LLVM_SHOULD_PASS_VECTOR_IN_INTEGER_REGS(type)) { - PassInIntegerRegisters(type, ScalarElts, 0, false); - } else if (LLVM_SHOULD_PASS_VECTOR_USING_BYVAL_ATTR(type)) { - C.HandleByValArgument(Ty, type); - if (Attributes) { - *Attributes |= Attribute::ByVal; - *Attributes |= - Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type)); - } - } else { - C.HandleScalarArgument(Ty, type); - ScalarElts.push_back(Ty); - } - } else if (LLVM_TRY_PASS_AGGREGATE_CUSTOM(type, ScalarElts, - C.getCallingConv(), &C)) { - // Nothing to do. - } else if (Ty->isSingleValueType()) { - C.HandleScalarArgument(Ty, type); - ScalarElts.push_back(Ty); - } else if (LLVM_SHOULD_PASS_AGGREGATE_AS_FCA(type, Ty)) { - C.HandleFCAArgument(Ty, type); - } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_MIXED_REGS(type, Ty, - C.getCallingConv(), - Elts)) { - if (!LLVM_AGGREGATE_PARTIALLY_PASSED_IN_REGS(Elts, ScalarElts, - C.isShadowReturn(), - C.getCallingConv())) - PassInMixedRegisters(Ty, Elts, ScalarElts); - else { - C.HandleByValArgument(Ty, type); - if (Attributes) { - *Attributes |= Attribute::ByVal; - *Attributes |= - Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type)); - } - } - } else if (LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(type, Ty)) { - C.HandleByValArgument(Ty, type); - if (Attributes) { - *Attributes |= Attribute::ByVal; - *Attributes |= - Attribute::constructAlignmentFromInt(LLVM_BYVAL_ALIGNMENT(type)); - } - } else if (LLVM_SHOULD_PASS_AGGREGATE_IN_INTEGER_REGS(type, &Size, - &DontCheckAlignment)) { - PassInIntegerRegisters(type, ScalarElts, Size, DontCheckAlignment); - } else if (isZeroSizedStructOrUnion(type)) { - // Zero sized struct or union, just drop it! - ; - } else if (TREE_CODE(type) == RECORD_TYPE) { - for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) - if (TREE_CODE(Field) == FIELD_DECL) { - const tree Ftype = TREE_TYPE(Field); - const Type *FTy = ConvertType(Ftype); - unsigned FNo = GetFieldIndex(Field, Ty); - assert(FNo < INT_MAX && "Case not handled yet!"); - - // Currently, a bvyal type inside a non-byval struct is a zero-length - // object inside a bigger object on x86-64. This type should be - // skipped (but only when it is inside a bigger object). - // (We know there currently are no other such cases active because - // they would hit the assert in FunctionPrologArgumentConversion:: - // HandleByValArgument.) - if (!LLVM_SHOULD_PASS_AGGREGATE_USING_BYVAL_ATTR(Ftype, FTy)) { - C.EnterField(FNo, Ty); - HandleArgument(TREE_TYPE(Field), ScalarElts); - C.ExitField(); - } - } - } else if (TREE_CODE(type) == COMPLEX_TYPE) { - C.EnterField(0, Ty); - HandleArgument(TREE_TYPE(type), ScalarElts); - C.ExitField(); - C.EnterField(1, Ty); - HandleArgument(TREE_TYPE(type), ScalarElts); - C.ExitField(); - } else if ((TREE_CODE(type) == UNION_TYPE) || - (TREE_CODE(type) == QUAL_UNION_TYPE)) { - HandleUnion(type, ScalarElts); - } else if (TREE_CODE(type) == ARRAY_TYPE) { - // Array with padding? - if (Ty->isStructTy()) - Ty = cast(Ty)->getTypeAtIndex(0U); - const ArrayType *ATy = cast(Ty); - for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) { - C.EnterField(i, Ty); - HandleArgument(TREE_TYPE(type), ScalarElts); - C.ExitField(); - } - } else { - DieAbjectly("Unknown aggregate type!"); - } -} - -/// HandleUnion - Handle a UNION_TYPE or QUAL_UNION_TYPE tree. -void DefaultABI::HandleUnion(tree type, std::vector &ScalarElts) { - if (TYPE_TRANSPARENT_AGGR(type)) { - tree Field = TYPE_FIELDS(type); - assert(Field && "Transparent union must have some elements!"); - while (TREE_CODE(Field) != FIELD_DECL) { - Field = TREE_CHAIN(Field); - assert(Field && "Transparent union must have some elements!"); - } - - HandleArgument(TREE_TYPE(Field), ScalarElts); - } else { - // Unions pass the largest element. - unsigned MaxSize = 0; - tree MaxElt = 0; - for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) { - if (TREE_CODE(Field) == FIELD_DECL) { - // Skip fields that are known not to be present. - if (TREE_CODE(type) == QUAL_UNION_TYPE && - integer_zerop(DECL_QUALIFIER(Field))) - continue; - - tree SizeTree = TYPE_SIZE(TREE_TYPE(Field)); - unsigned Size = ((unsigned)TREE_INT_CST_LOW(SizeTree)+7)/8; - if (Size > MaxSize) { - MaxSize = Size; - MaxElt = Field; - } - - // Skip remaining fields if this one is known to be present. - if (TREE_CODE(type) == QUAL_UNION_TYPE && - integer_onep(DECL_QUALIFIER(Field))) - break; - } - } - - if (MaxElt) - HandleArgument(TREE_TYPE(MaxElt), ScalarElts); - } -} - -/// PassInIntegerRegisters - Given an aggregate value that should be passed in -/// integer registers, convert it to a structure containing ints and pass all -/// of the struct elements in. If Size is set we pass only that many bytes. -void DefaultABI::PassInIntegerRegisters(tree type, - std::vector &ScalarElts, - unsigned origSize, - bool DontCheckAlignment) { - unsigned Size; - if (origSize) - Size = origSize; - else - Size = TREE_INT_CST_LOW(TYPE_SIZE(type))/8; - - // FIXME: We should preserve all aggregate value alignment information. - // Work around to preserve some aggregate value alignment information: - // don't bitcast aggregate value to Int64 if its alignment is different - // from Int64 alignment. ARM backend needs this. - unsigned Align = TYPE_ALIGN(type)/8; - unsigned Int64Align = - getTargetData().getABITypeAlignment(Type::getInt64Ty(getGlobalContext())); - bool UseInt64 = (DontCheckAlignment || Align >= Int64Align); - - unsigned ElementSize = UseInt64 ? 8:4; - unsigned ArraySize = Size / ElementSize; - - // Put as much of the aggregate as possible into an array. - const Type *ATy = NULL; - const Type *ArrayElementType = NULL; - if (ArraySize) { - Size = Size % ElementSize; - ArrayElementType = (UseInt64 ? - Type::getInt64Ty(getGlobalContext()) : - Type::getInt32Ty(getGlobalContext())); - ATy = ArrayType::get(ArrayElementType, ArraySize); - } - - // Pass any leftover bytes as a separate element following the array. - unsigned LastEltRealSize = 0; - const llvm::Type *LastEltTy = 0; - if (Size > 4) { - LastEltTy = Type::getInt64Ty(getGlobalContext()); - } else if (Size > 2) { - LastEltTy = Type::getInt32Ty(getGlobalContext()); - } else if (Size > 1) { - LastEltTy = Type::getInt16Ty(getGlobalContext()); - } else if (Size > 0) { - LastEltTy = Type::getInt8Ty(getGlobalContext()); - } - if (LastEltTy) { - if (Size != getTargetData().getTypeAllocSize(LastEltTy)) - LastEltRealSize = Size; - } - - std::vector Elts; - if (ATy) - Elts.push_back(ATy); - if (LastEltTy) - Elts.push_back(LastEltTy); - const StructType *STy = StructType::get(getGlobalContext(), Elts, false); - - unsigned i = 0; - if (ArraySize) { - C.EnterField(0, STy); - for (unsigned j = 0; j < ArraySize; ++j) { - C.EnterField(j, ATy); - C.HandleScalarArgument(ArrayElementType, 0); - ScalarElts.push_back(ArrayElementType); - C.ExitField(); - } - C.ExitField(); - ++i; - } - if (LastEltTy) { - C.EnterField(i, STy); - C.HandleScalarArgument(LastEltTy, 0, LastEltRealSize); - ScalarElts.push_back(LastEltTy); - C.ExitField(); - } -} - -/// PassInMixedRegisters - Given an aggregate value that should be passed in -/// mixed integer, floating point, and vector registers, convert it to a -/// structure containing the specified struct elements in. -void DefaultABI::PassInMixedRegisters(const Type *Ty, - std::vector &OrigElts, - std::vector &ScalarElts) { - // We use VoidTy in OrigElts to mean "this is a word in the aggregate - // that occupies storage but has no useful information, and is not passed - // anywhere". Happens on x86-64. - std::vector Elts(OrigElts); - const Type* wordType = getTargetData().getPointerSize() == 4 ? - Type::getInt32Ty(getGlobalContext()) : Type::getInt64Ty(getGlobalContext()); - for (unsigned i=0, e=Elts.size(); i!=e; ++i) - if (OrigElts[i]->isVoidTy()) - Elts[i] = wordType; - - const StructType *STy = StructType::get(getGlobalContext(), Elts, false); - - unsigned Size = getTargetData().getTypeAllocSize(STy); - const StructType *InSTy = dyn_cast(Ty); - unsigned InSize = 0; - // If Ty and STy size does not match then last element is accessing - // extra bits. - unsigned LastEltSizeDiff = 0; - if (InSTy) { - InSize = getTargetData().getTypeAllocSize(InSTy); - if (InSize < Size) { - unsigned N = STy->getNumElements(); - const llvm::Type *LastEltTy = STy->getElementType(N-1); - if (LastEltTy->isIntegerTy()) - LastEltSizeDiff = - getTargetData().getTypeAllocSize(LastEltTy) - (Size - InSize); - } - } - for (unsigned i = 0, e = Elts.size(); i != e; ++i) { - if (!OrigElts[i]->isVoidTy()) { - C.EnterField(i, STy); - unsigned RealSize = 0; - if (LastEltSizeDiff && i == (e - 1)) - RealSize = LastEltSizeDiff; - C.HandleScalarArgument(Elts[i], 0, RealSize); - ScalarElts.push_back(Elts[i]); - C.ExitField(); - } - } -} Modified: dragonegg/trunk/Makefile URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Makefile?rev=129352&r1=129351&r2=129352&view=diff ============================================================================== --- dragonegg/trunk/Makefile (original) +++ dragonegg/trunk/Makefile Tue Apr 12 04:15:29 2011 @@ -9,9 +9,12 @@ # that was created during the build. LLVM_CONFIG?=llvm-config -# Location of the dragonegg source, useful if you want separate source and -# object directories. -SRC_DIR?=$(PWD) +# Location of this Makefile, useful if you want separate source and object +# directories. +TOP_DIR?=$(PWD) + +INCLUDE_DIR=$(TOP_DIR)/include +SRC_DIR=$(TOP_DIR)/src ifndef VERBOSE QUIET:=@ @@ -24,7 +27,7 @@ ifeq ($(shell uname),Darwin) LOADABLE_MODULE_OPTIONS=-bundle -undefined dynamic_lookup else -LOADABLE_MODULE_OPTIONS=-shared -Wl,-O1 -Wl,--version-script=$(SRC_DIR)/exports.map +LOADABLE_MODULE_OPTIONS=-shared -Wl,-O1 -Wl,--version-script=$(TOP_DIR)/exports.map endif GCC_PLUGIN_DIR:=$(shell $(GCC) -print-file-name=plugin) @@ -34,14 +37,14 @@ TARGET_TRIPLE:=$(shell $(GCC) -dumpmachine) # NOTE: replace with an informative string when doing a release. -REVISION:=$(shell svnversion -n $(SRC_DIR)) +REVISION:=$(shell svnversion -n $(TOP_DIR)) PLUGIN=dragonegg.so PLUGIN_OBJECTS=cache.o Backend.o Constants.o Convert.o Debug.o DefaultABI.o \ Trees.o Types.o bits_and_bobs.o TARGET_OBJECT=Target.o -TARGET_SOURCE=$(SRC_DIR)/$(shell $(TARGET_UTIL) -p)/Target.cpp +TARGET_SOURCE=$(TOP_DIR)/$(shell $(TARGET_UTIL) -p)/Target.cpp TARGET_UTIL_OBJECTS=TargetInfo.o TARGET_UTIL=./TargetInfo @@ -52,19 +55,19 @@ -MD -MP \ -DIN_GCC -DREVISION=\"$(REVISION)\" \ -DGCC_MAJOR=$(GCC_MAJOR) -DGCC_MINOR=$(GCC_MINOR) \ - -I$(SRC_DIR)/include -I$(GCC_PLUGIN_DIR)/include + -I$(INCLUDE_DIR) -I$(GCC_PLUGIN_DIR)/include LD_OPTIONS+=$(shell $(LLVM_CONFIG) --ldflags) $(LDFLAGS) # NOTE: The following flags can only be used after TARGET_UTIL has been built. TARGET_HEADERS+=-DTARGET_NAME=\"$(shell $(TARGET_UTIL) -t)\" \ - -I$(SRC_DIR)/$(shell $(TARGET_UTIL) -p) \ - -I$(SRC_DIR)/$(shell $(TARGET_UTIL) -o) + -I$(TOP_DIR)/$(shell $(TARGET_UTIL) -p) \ + -I$(TOP_DIR)/$(shell $(TARGET_UTIL) -o) default: $(PLUGIN) -$(TARGET_UTIL_OBJECTS): %.o : $(SRC_DIR)/utils/%.cpp +$(TARGET_UTIL_OBJECTS): %.o : $(TOP_DIR)/utils/%.cpp @echo Compiling utils/$*.cpp $(QUIET)$(CXX) -c -DTARGET_TRIPLE=\"$(TARGET_TRIPLE)\" \ $(CPP_OPTIONS) $(CXXFLAGS) $< @@ -103,7 +106,7 @@ # The following target exists for the benefit of the dragonegg maintainers, and # is not used in a normal build. GENGTYPE_INPUT=$(SRC_DIR)/cache.c -GENGTYPE_OUTPUT=$(SRC_DIR)/gt-cache.h +GENGTYPE_OUTPUT=$(INCLUDE_DIR)/dragonegg/gt-cache.h gt-cache.h:: cd $(HOME)/GCC/objects/gcc && ./build/gengtype \ -P $(GENGTYPE_OUTPUT) $(GCC_PLUGIN_DIR) gtyp-input.list \ Removed: dragonegg/trunk/Trees.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Trees.cpp?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/Trees.cpp (original) +++ dragonegg/trunk/Trees.cpp (removed) @@ -1,143 +0,0 @@ -//===------ Trees.cpp - Utility functions for working with GCC trees ------===// -// -// Copyright (C) 2010, 2011 Duncan Sands. -// -// This file is part of DragonEgg. -// -// DragonEgg is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free Software -// Foundation; either version 2, or (at your option) any later version. -// -// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -// A PARTICULAR PURPOSE. See the GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along with -// DragonEgg; see the file COPYING. If not, write to the Free Software -// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. -// -//===----------------------------------------------------------------------===// -// This file defines utility functions for working with GCC trees. -//===----------------------------------------------------------------------===// - -// Plugin headers -#include "dragonegg/Trees.h" - -// LLVM headers -#include "llvm/ADT/Twine.h" - -// System headers -#include - -// GCC headers -extern "C" { -#include "config.h" -// Stop GCC declaring 'getopt' as it can clash with the system's declaration. -#undef HAVE_DECL_GETOPT -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" - -#include "flags.h" -} - -using namespace llvm; - -/// concatIfNotEmpty - Concatenate the given strings if they are both non-empty. -/// Otherwise return the empty string. -static std::string concatIfNotEmpty(const std::string &Left, - const std::string &Right) { - if (Left.empty() || Right.empty()) - return std::string(); - return Left + Right; -} - -/// getDescriptiveName - Return a helpful name for the given tree, or an empty -/// string if no sensible name was found. These names are used to make the IR -/// more readable, and have no official status. -std::string getDescriptiveName(tree t) { - if (!t) return std::string(); // Occurs when recursing. - - // Name identifier nodes after their contents. This gives the desired effect - // when called recursively. - if (TREE_CODE(t) == IDENTIFIER_NODE) - return std::string(IDENTIFIER_POINTER(t), IDENTIFIER_LENGTH(t)); - - // Handle declarations of all kinds. - if (DECL_P(t)) { - // If the declaration comes with a name then use it. - if (DECL_NAME(t)) // Always an identifier node. - return std::string(IDENTIFIER_POINTER(DECL_NAME(t)), - IDENTIFIER_LENGTH(DECL_NAME(t))); - // Use a generic name for function results. - if (TREE_CODE(t) == RESULT_DECL) - return ""; - // Labels have their own numeric unique identifiers. - if (TREE_CODE(t) == LABEL_DECL && LABEL_DECL_UID(t) != -1) { - Twine LUID(LABEL_DECL_UID(t)); - return ("L" + LUID).str(); - } - // Otherwise use the generic UID. - const char *Annotation = TREE_CODE(t) == CONST_DECL ? "C." : "D."; - Twine UID(DECL_UID(t)); - return (Annotation + UID).str(); - } - - // Handle types of all kinds. - if (TYPE_P(t)) { - // If the type comes with a name then use it. - const std::string &TypeName = getDescriptiveName(TYPE_NAME(t)); - if (!TypeName.empty()) { - // Annotate the name with a description of the type's class. - if (TREE_CODE(t) == ENUMERAL_TYPE) - return "enum." + TypeName; - if (TREE_CODE(t) == RECORD_TYPE) - return "struct." + TypeName; - if (TREE_CODE(t) == QUAL_UNION_TYPE) - return "qualunion." + TypeName; - if (TREE_CODE(t) == UNION_TYPE) - return "union." + TypeName; - return TypeName; - } - - // Try to deduce a useful name. - if (TREE_CODE(t) == ARRAY_TYPE) - // If the element type is E, name the array E[] (regardless of the number - // of dimensions). - return concatIfNotEmpty(getDescriptiveName(TREE_TYPE(t)), "[]"); - if (TREE_CODE(t) == COMPLEX_TYPE) - // If the element type is E, name the complex number complex.E. - return concatIfNotEmpty("complex.", getDescriptiveName(TREE_TYPE(t))); - if (TREE_CODE(t) == POINTER_TYPE) - // If the element type is E, name the pointer E*. - return concatIfNotEmpty(getDescriptiveName(TREE_TYPE(t)), "*"); - if (TREE_CODE(t) == REFERENCE_TYPE) - // If the element type is E, name the reference E&. - return concatIfNotEmpty(getDescriptiveName(TREE_TYPE(t)), "&"); - - return TypeName; - } - - // Handle SSA names. - if (TREE_CODE(t) == SSA_NAME) { - Twine NameVersion(SSA_NAME_VERSION(t)); - return concatIfNotEmpty(getDescriptiveName(SSA_NAME_VAR(t)), - ("_" + NameVersion).str()); - } - - // A mysterious tree, just give up. - return std::string(); -} - -/// hasNUW - Return whether overflowing unsigned operations on this type result -/// in undefined behaviour. -bool hasNUW(tree type) { - return TYPE_UNSIGNED(type) && !TYPE_OVERFLOW_WRAPS(type); -} - -/// hasNSW - Return whether overflowing signed operations on this type result -/// in undefined behaviour. -bool hasNSW(tree type) { - return !TYPE_UNSIGNED(type) && !TYPE_OVERFLOW_WRAPS(type); -} Removed: dragonegg/trunk/Types.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Types.cpp?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/Types.cpp (original) +++ dragonegg/trunk/Types.cpp (removed) @@ -1,2074 +0,0 @@ -//===----------- Types.cpp - Converting GCC types to LLVM types -----------===// -// -// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Chris Lattner, -// Duncan Sands et al. -// -// This file is part of DragonEgg. -// -// DragonEgg is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free Software -// Foundation; either version 2, or (at your option) any later version. -// -// DragonEgg is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR -// A PARTICULAR PURPOSE. See the GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License along with -// DragonEgg; see the file COPYING. If not, write to the Free Software -// Foundation, 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA. -// -//===----------------------------------------------------------------------===// -// This is the code that converts GCC tree types into LLVM types. -//===----------------------------------------------------------------------===// - -// Plugin headers -#include "dragonegg/ABI.h" -#include "dragonegg/Trees.h" -extern "C" { -#include "dragonegg/cache.h" -} - -// LLVM headers -#include "llvm/Module.h" -#include "llvm/Assembly/Writer.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetMachine.h" - -// System headers -#include -#include - -// GCC headers -extern "C" { -#include "config.h" -// Stop GCC declaring 'getopt' as it can clash with the system's declaration. -#undef HAVE_DECL_GETOPT -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" -} - -// NoLength - Special value used to indicate that an array has variable or -// unknown length. -static const uint64_t NoLength = ~(uint64_t)0; - -static LLVMContext &Context = getGlobalContext(); - -//===----------------------------------------------------------------------===// -// Matching LLVM types with GCC trees -//===----------------------------------------------------------------------===// - -// GET_TYPE_LLVM/SET_TYPE_LLVM - Associate an LLVM type with each TREE type. -// These are lazily computed by ConvertType. - -const Type *llvm_set_type(tree Tr, const Type *Ty) { - assert(TYPE_P(Tr) && "Expected a gcc type!"); - - // Check that the LLVM and GCC types have the same size, or, if the type has - // variable size, that the LLVM type is not bigger than any possible value of - // the GCC type. -#ifndef NDEBUG - if (Ty->isSized() && isInt64(TYPE_SIZE(Tr), true)) { - uint64_t LLVMSize = getTargetData().getTypeAllocSizeInBits(Ty); - if (getInt64(TYPE_SIZE(Tr), true) != LLVMSize) { - errs() << "GCC: "; - debug_tree(Tr); - errs() << "LLVM: "; - Ty->print(errs()); - errs() << " (" << LLVMSize << " bits)\n"; - DieAbjectly("LLVM type size doesn't match GCC type size!"); - } - } -#endif - - return (const Type *)llvm_set_cached(Tr, Ty); -} - -#define SET_TYPE_LLVM(NODE, TYPE) llvm_set_type(NODE, TYPE) - -const Type *llvm_get_type(tree Tr) { - assert(TYPE_P(Tr) && "Expected a gcc type!"); - return (const Type *)llvm_get_cached(Tr); -} - -#define GET_TYPE_LLVM(NODE) llvm_get_type(NODE) - -//TODO// Read LLVM Types string table -//TODOvoid readLLVMTypesStringTable() { -//TODO -//TODO GlobalValue *V = TheModule->getNamedGlobal("llvm.pch.types"); -//TODO if (!V) -//TODO return; -//TODO -//TODO // Value *GV = TheModule->getValueSymbolTable().lookup("llvm.pch.types"); -//TODO GlobalVariable *GV = cast(V); -//TODO ConstantStruct *LTypesNames = cast(GV->getOperand(0)); -//TODO -//TODO for (unsigned i = 0; i < LTypesNames->getNumOperands(); ++i) { -//TODO const Type *Ty = NULL; -//TODO -//TODO if (ConstantArray *CA = -//TODO dyn_cast(LTypesNames->getOperand(i))) { -//TODO std::string Str = CA->getAsString(); -//TODO Ty = TheModule->getTypeByName(Str); -//TODO assert (Ty != NULL && "Invalid Type in LTypes string table"); -//TODO } -//TODO // If V is not a string then it is empty. Insert NULL to represent -//TODO // empty entries. -//TODO LTypes.push_back(Ty); -//TODO } -//TODO -//TODO // Now, llvm.pch.types value is not required so remove it from the symbol -//TODO // table. -//TODO GV->eraseFromParent(); -//TODO} -//TODO -//TODO -//TODO// GCC tree's uses LTypes vector's index to reach LLVM types. -//TODO// Create a string table to hold these LLVM types' names. This string -//TODO// table will be used to recreate LTypes vector after loading PCH. -//TODOvoid writeLLVMTypesStringTable() { -//TODO -//TODO if (LTypes.empty()) -//TODO return; -//TODO -//TODO std::vector LTypesNames; -//TODO std::map < const Type *, std::string > TypeNameMap; -//TODO -//TODO // Collect Type Names in advance. -//TODO const TypeSymbolTable &ST = TheModule->getTypeSymbolTable(); -//TODO TypeSymbolTable::const_iterator TI = ST.begin(); -//TODO for (; TI != ST.end(); ++TI) { -//TODO TypeNameMap[TI->second] = TI->first; -//TODO } -//TODO -//TODO // Populate LTypesNames vector. -//TODO for (std::vector::iterator I = LTypes.begin(), -//TODO E = LTypes.end(); I != E; ++I) { -//TODO const Type *Ty = *I; -//TODO -//TODO // Give names to nameless types. -//TODO if (Ty && TypeNameMap[Ty].empty()) { -//TODO std::string NewName = -//TODO TheModule->getTypeSymbolTable().getUniqueName("llvm.fe.ty"); -//TODO TheModule->addTypeName(NewName, Ty); -//TODO TypeNameMap[*I] = NewName; -//TODO } -//TODO -//TODO const std::string &TypeName = TypeNameMap[*I]; -//TODO LTypesNames.push_back(ConstantArray::get(Context, TypeName, false)); -//TODO } -//TODO -//TODO // Create string table. -//TODO Constant *LTypesNameTable = ConstantStruct::get(Context, LTypesNames, false); -//TODO -//TODO // Create variable to hold this string table. -//TODO GlobalVariable *GV = new GlobalVariable(*TheModule, -//TODO LTypesNameTable->getType(), true, -//TODO GlobalValue::ExternalLinkage, -//TODO LTypesNameTable, -//TODO "llvm.pch.types"); -//TODO} - -//===----------------------------------------------------------------------===// -// Recursive Type Handling Code and Data -//===----------------------------------------------------------------------===// - -// Recursive types are a major pain to handle for a couple of reasons. Because -// of this, when we start parsing a struct or a union, we globally change how -// POINTER_TYPE and REFERENCE_TYPE are handled. In particular, instead of -// actually recursing and computing the type they point to, they will return an -// opaque*, and remember that they did this in PointersToReresolve. - - -/// GetFunctionType - This is just a helper like FunctionType::get but that -/// takes PATypeHolders. -static FunctionType *GetFunctionType(const PATypeHolder &Res, - std::vector &ArgTys, - bool isVarArg) { - std::vector ArgTysP; - ArgTysP.reserve(ArgTys.size()); - for (unsigned i = 0, e = ArgTys.size(); i != e; ++i) - ArgTysP.push_back(ArgTys[i]); - - return FunctionType::get(Res, ArgTysP, isVarArg); -} - -//===----------------------------------------------------------------------===// -// Type Conversion Utilities -//===----------------------------------------------------------------------===// - -/// ArrayLengthOf - Returns the length of the given gcc array type, or NoLength -/// if the array has variable or unknown length. -uint64_t ArrayLengthOf(tree type) { - assert(TREE_CODE(type) == ARRAY_TYPE && "Only for array types!"); - tree range = array_type_nelts(type); // The number of elements minus one. - // Bail out if the array has variable or unknown length. - if (!isInt64(range, false)) - return NoLength; - int64_t Range = getInt64(range, false); - return Range < 0 ? 0 : 1 + (uint64_t)Range; -} - -/// getFieldOffsetInBits - Return the bit offset of a FIELD_DECL in a structure. -uint64_t getFieldOffsetInBits(tree field) { - assert(OffsetIsLLVMCompatible(field) && "Offset is not constant!"); - uint64_t Result = getInt64(DECL_FIELD_BIT_OFFSET(field), true); - Result += getInt64(DECL_FIELD_OFFSET(field), true) * BITS_PER_UNIT; - return Result; -} - -/// GetUnitType - Returns an integer one address unit wide if 'NumUnits' is 1; -/// otherwise returns an array of such integers with 'NumUnits' elements. For -/// example, on a machine which has 16 bit bytes returns an i16 or an array of -/// i16. -const Type *GetUnitType(LLVMContext &C, unsigned NumUnits) { - assert(!(BITS_PER_UNIT & 7) && "Unit size not a multiple of 8 bits!"); - const Type *UnitTy = IntegerType::get(C, BITS_PER_UNIT); - if (NumUnits == 1) - return UnitTy; - return ArrayType::get(UnitTy, NumUnits); -} - -/// GetUnitPointerType - Returns an LLVM pointer type which points to memory one -/// address unit wide. For example, on a machine which has 16 bit bytes returns -/// an i16*. -const Type *GetUnitPointerType(LLVMContext &C, unsigned AddrSpace) { - return GetUnitType(C)->getPointerTo(AddrSpace); -} - -// isPassedByInvisibleReference - Return true if an argument of the specified -// type should be passed in by invisible reference. -// -bool isPassedByInvisibleReference(tree Type) { - // Don't crash in this case. - if (Type == error_mark_node) - return false; - - // FIXME: Search for TREE_ADDRESSABLE in calls.c, and see if there are other - // cases that make arguments automatically passed in by reference. - return TREE_ADDRESSABLE(Type) || TYPE_SIZE(Type) == 0 || - TREE_CODE(TYPE_SIZE(Type)) != INTEGER_CST; -} - -/// isSequentialCompatible - Return true if the specified gcc array, pointer or -/// vector type and the corresponding LLVM SequentialType lay out their elements -/// identically in memory, so doing a GEP accesses the right memory location. -/// We assume that objects without a known size do not. -bool isSequentialCompatible(tree type) { - assert((TREE_CODE(type) == ARRAY_TYPE || - TREE_CODE(type) == POINTER_TYPE || - TREE_CODE(type) == VECTOR_TYPE || - TREE_CODE(type) == REFERENCE_TYPE) && "not a sequential type!"); - // This relies on gcc types with constant size mapping to LLVM types with the - // same size. It is possible for the component type not to have a size: - // struct foo; extern foo bar[]; - return isInt64(TYPE_SIZE(TREE_TYPE(type)), true); -} - -/// OffsetIsLLVMCompatible - Return true if the given field is offset from the -/// start of the record by a constant amount which is not humongously big. -bool OffsetIsLLVMCompatible(tree field_decl) { - return isInt64(DECL_FIELD_OFFSET(field_decl), true); -} - -/// isBitfield - Returns whether to treat the specified field as a bitfield. -bool isBitfield(tree_node *field_decl) { - if (!DECL_BIT_FIELD(field_decl)) - return false; - - // A bitfield. But do we need to treat it as one? - - assert(DECL_FIELD_BIT_OFFSET(field_decl) && "Bitfield with no bit offset!"); - if (TREE_INT_CST_LOW(DECL_FIELD_BIT_OFFSET(field_decl)) & 7) - // Does not start on a byte boundary - must treat as a bitfield. - return true; - - if (!isInt64(TYPE_SIZE (TREE_TYPE(field_decl)), true)) - // No size or variable sized - play safe, treat as a bitfield. - return true; - - uint64_t TypeSizeInBits = getInt64(TYPE_SIZE (TREE_TYPE(field_decl)), true); - assert(!(TypeSizeInBits & 7) && "A type with a non-byte size!"); - - assert(DECL_SIZE(field_decl) && "Bitfield with no bit size!"); - uint64_t FieldSizeInBits = getInt64(DECL_SIZE(field_decl), true); - if (FieldSizeInBits < TypeSizeInBits) - // Not wide enough to hold the entire type - treat as a bitfield. - return true; - - return false; -} - -/// refine_type_to - Cause all users of the opaque type old_type to switch -/// to the more concrete type new_type. -void refine_type_to(tree old_type, tree new_type) -{ - const OpaqueType *OldTy = cast_or_null(GET_TYPE_LLVM(old_type)); - if (OldTy) { - const Type *NewTy = ConvertType (new_type); - const_cast(OldTy)->refineAbstractTypeTo(NewTy); - } -} - - -//===----------------------------------------------------------------------===// -// Abstract Type Refinement Helpers -//===----------------------------------------------------------------------===// -// -// This code is built to make sure that the TYPE_LLVM field on tree types are -// updated when LLVM types are refined. This prevents dangling pointers from -// occuring due to type coallescing. -// -namespace { - class TypeRefinementDatabase : public AbstractTypeUser { - virtual void refineAbstractType(const DerivedType *OldTy, - const Type *NewTy); - virtual void typeBecameConcrete(const DerivedType *AbsTy); - - // TypeUsers - For each abstract LLVM type, we keep track of all of the GCC - // types that point to it. - std::map > TypeUsers; - public: - /// setType - call SET_TYPE_LLVM(type, Ty), associating the type with the - /// specified tree type. In addition, if the LLVM type is an abstract type, - /// we add it to our data structure to track it. - inline const Type *setType(tree type, const Type *Ty) { - if (GET_TYPE_LLVM(type)) - RemoveTypeFromTable(type); - - if (Ty->isAbstract()) { - std::vector &Users = TypeUsers[Ty]; - if (Users.empty()) Ty->addAbstractTypeUser(this); - Users.push_back(type); - } - return SET_TYPE_LLVM(type, Ty); - } - - void RemoveTypeFromTable(tree type); - void dump() const; - }; - - /// TypeDB - The main global type database. - TypeRefinementDatabase TypeDB; -} - -/// RemoveTypeFromTable - We're about to change the LLVM type of 'type' -/// -void TypeRefinementDatabase::RemoveTypeFromTable(tree type) { - const Type *Ty = GET_TYPE_LLVM(type); - if (!Ty->isAbstract()) return; - std::map >::iterator I = TypeUsers.find(Ty); - assert(I != TypeUsers.end() && "Using an abstract type but not in table?"); - - bool FoundIt = false; - for (unsigned i = 0, e = I->second.size(); i != e; ++i) - if (I->second[i] == type) { - FoundIt = true; - std::swap(I->second[i], I->second.back()); - I->second.pop_back(); - break; - } - assert(FoundIt && "Using an abstract type but not in table?"); - - // If the type plane is now empty, nuke it. - if (I->second.empty()) { - TypeUsers.erase(I); - Ty->removeAbstractTypeUser(this); - } -} - -/// refineAbstractType - The callback method invoked when an abstract type is -/// resolved to another type. An object must override this method to update -/// its internal state to reference NewType instead of OldType. -/// -void TypeRefinementDatabase::refineAbstractType(const DerivedType *OldTy, - const Type *NewTy) { - if (OldTy == NewTy && OldTy->isAbstract()) return; // Nothing to do. - - std::map >::iterator I = TypeUsers.find(OldTy); - assert(I != TypeUsers.end() && "Using an abstract type but not in table?"); - - if (!NewTy->isAbstract()) { - // If the type became concrete, update everything pointing to it, and remove - // all of our entries from the map. - if (OldTy != NewTy) - for (unsigned i = 0, e = I->second.size(); i != e; ++i) - SET_TYPE_LLVM(I->second[i], NewTy); - } else { - // Otherwise, it was refined to another instance of an abstract type. Move - // everything over and stop monitoring OldTy. - std::vector &NewSlot = TypeUsers[NewTy]; - if (NewSlot.empty()) NewTy->addAbstractTypeUser(this); - - for (unsigned i = 0, e = I->second.size(); i != e; ++i) { - NewSlot.push_back(I->second[i]); - SET_TYPE_LLVM(I->second[i], NewTy); - } - } - - TypeUsers.erase(I); - - // Next, remove OldTy's entry in the TargetData object if it has one. - if (const StructType *STy = dyn_cast(OldTy)) - getTargetData().InvalidateStructLayoutInfo(STy); - - OldTy->removeAbstractTypeUser(this); -} - -/// The other case which AbstractTypeUsers must be aware of is when a type -/// makes the transition from being abstract (where it has clients on it's -/// AbstractTypeUsers list) to concrete (where it does not). This method -/// notifies ATU's when this occurs for a type. -/// -void TypeRefinementDatabase::typeBecameConcrete(const DerivedType *AbsTy) { - assert(TypeUsers.count(AbsTy) && "Not using this type!"); - // Remove the type from our collection of tracked types. - TypeUsers.erase(AbsTy); - AbsTy->removeAbstractTypeUser(this); -} -void TypeRefinementDatabase::dump() const { - outs() << "TypeRefinementDatabase\n"; - outs().flush(); -} - -//===----------------------------------------------------------------------===// -// Helper Routines -//===----------------------------------------------------------------------===// - -/// GetFieldIndex - Return the index of the field in the given LLVM type that -/// corresponds to the GCC field declaration 'decl'. This means that the LLVM -/// and GCC fields start in the same byte (if 'decl' is a bitfield, this means -/// that its first bit is within the byte the LLVM field starts at). Returns -/// INT_MAX if there is no such LLVM field. -int GetFieldIndex(tree decl, const Type *Ty) { - assert(TREE_CODE(decl) == FIELD_DECL && "Expected a FIELD_DECL!"); - assert(Ty == ConvertType(DECL_CONTEXT(decl)) && "Field not for this type!"); - - // If we previously cached the field index, return the cached value. - unsigned Index = (unsigned)get_decl_index(decl); - if (Index <= INT_MAX) - return Index; - - // TODO: At this point we could process all fields of DECL_CONTEXT(decl), and - // incrementally advance over the StructLayout. This would make indexing be - // O(N) rather than O(N log N) if all N fields are used. It's not clear if it - // would really be a win though. - - const StructType *STy = dyn_cast(Ty); - // If this is not a struct type, then for sure there is no corresponding LLVM - // field (we do not require GCC record types to be converted to LLVM structs). - if (!STy) - return set_decl_index(decl, INT_MAX); - - // If the field declaration is at a variable or humongous offset then there - // can be no corresponding LLVM field. - if (!OffsetIsLLVMCompatible(decl)) - return set_decl_index(decl, INT_MAX); - - // Find the LLVM field that contains the first bit of the GCC field. - uint64_t OffsetInBytes = getFieldOffsetInBits(decl) / 8; // Ignore bit in byte - const StructLayout *SL = getTargetData().getStructLayout(STy); - Index = SL->getElementContainingOffset(OffsetInBytes); - - // The GCC field must start in the first byte of the LLVM field. - if (OffsetInBytes != SL->getElementOffset(Index)) - return set_decl_index(decl, INT_MAX); - - // We are not able to cache values bigger than INT_MAX, so bail out if the - // LLVM field index is that huge. - if (Index >= INT_MAX) - return set_decl_index(decl, INT_MAX); - - // Found an appropriate LLVM field - return it. - return set_decl_index(decl, Index); -} - -/// FindLLVMTypePadding - If the specified struct has any inter-element padding, -/// add it to the Padding array. -static void FindLLVMTypePadding(const Type *Ty, tree type, uint64_t BitOffset, - SmallVector, 16> &Padding) { - if (const StructType *STy = dyn_cast(Ty)) { - const TargetData &TD = getTargetData(); - const StructLayout *SL = TD.getStructLayout(STy); - uint64_t PrevFieldEnd = 0; - for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { - // If this field is marked as being padding, then pretend it is not there. - // This results in it (or something bigger) being added to Padding. This - // matches the logic in CopyAggregate. - if (type && isPaddingElement(type, i)) - continue; - - uint64_t FieldBitOffset = SL->getElementOffset(i)*8; - - // Get padding of sub-elements. - FindLLVMTypePadding(STy->getElementType(i), 0, - BitOffset+FieldBitOffset, Padding); - // Check to see if there is any padding between this element and the - // previous one. - if (PrevFieldEnd < FieldBitOffset) - Padding.push_back(std::make_pair(PrevFieldEnd+BitOffset, - FieldBitOffset-PrevFieldEnd)); - PrevFieldEnd = - FieldBitOffset + TD.getTypeSizeInBits(STy->getElementType(i)); - } - - // Check for tail padding. - if (PrevFieldEnd < SL->getSizeInBits()) - Padding.push_back(std::make_pair(PrevFieldEnd, - SL->getSizeInBits()-PrevFieldEnd)); - } else if (const ArrayType *ATy = dyn_cast(Ty)) { - uint64_t EltSize = getTargetData().getTypeSizeInBits(ATy->getElementType()); - for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) - FindLLVMTypePadding(ATy->getElementType(), 0, BitOffset+i*EltSize, - Padding); - } - - // primitive and vector types have no padding. -} - -/// GCCTypeOverlapsWithPadding - Return true if the specified gcc type overlaps -/// with the specified region of padding. This only needs to handle types with -/// a constant size. -static bool GCCTypeOverlapsWithPadding(tree type, int PadStartBits, - int PadSizeBits) { - assert(type != error_mark_node); - // LLVM doesn't care about variants such as const, volatile, or restrict. - type = TYPE_MAIN_VARIANT(type); - - // If the type does not overlap, don't bother checking below. - - if (!isInt64(TYPE_SIZE(type), true)) - // No size, negative size (!) or huge - be conservative. - return true; - - if (!getInt64(TYPE_SIZE(type), true) || - PadStartBits >= (int64_t)getInt64(TYPE_SIZE(type), false) || - PadStartBits+PadSizeBits <= 0) - return false; - - - switch (TREE_CODE(type)) { - default: - DieAbjectly("Unknown type to compare!", type); - case VOID_TYPE: - case BOOLEAN_TYPE: - case ENUMERAL_TYPE: - case INTEGER_TYPE: - case REAL_TYPE: - case COMPLEX_TYPE: - case VECTOR_TYPE: - case POINTER_TYPE: - case REFERENCE_TYPE: - case OFFSET_TYPE: - // These types have no holes. - return true; - - case ARRAY_TYPE: { - uint64_t NumElts = ArrayLengthOf(type); - if (NumElts == NoLength) - return true; - unsigned EltSizeBits = getInt64(TYPE_SIZE(TREE_TYPE(type)), true); - - // Check each element for overlap. This is inelegant, but effective. - for (unsigned i = 0; i != NumElts; ++i) - if (GCCTypeOverlapsWithPadding(TREE_TYPE(type), - PadStartBits- i*EltSizeBits, PadSizeBits)) - return true; - return false; - } - case QUAL_UNION_TYPE: - case UNION_TYPE: { - // If this is a union with the transparent_union attribute set, it is - // treated as if it were just the same as its first type. - if (TYPE_TRANSPARENT_AGGR(type)) { - tree Field = TYPE_FIELDS(type); - assert(Field && "Transparent union must have some elements!"); - while (TREE_CODE(Field) != FIELD_DECL) { - Field = TREE_CHAIN(Field); - assert(Field && "Transparent union must have some elements!"); - } - return GCCTypeOverlapsWithPadding(TREE_TYPE(Field), - PadStartBits, PadSizeBits); - } - - // See if any elements overlap. - for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) { - if (TREE_CODE(Field) != FIELD_DECL) continue; - assert(getFieldOffsetInBits(Field) == 0 && "Union with non-zero offset?"); - // Skip fields that are known not to be present. - if (TREE_CODE(type) == QUAL_UNION_TYPE && - integer_zerop(DECL_QUALIFIER(Field))) - continue; - - if (GCCTypeOverlapsWithPadding(TREE_TYPE(Field), - PadStartBits, PadSizeBits)) - return true; - - // Skip remaining fields if this one is known to be present. - if (TREE_CODE(type) == QUAL_UNION_TYPE && - integer_onep(DECL_QUALIFIER(Field))) - break; - } - - return false; - } - - case RECORD_TYPE: - for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) { - if (TREE_CODE(Field) != FIELD_DECL) continue; - - if (!OffsetIsLLVMCompatible(Field)) - // Variable or humongous offset. - return true; - - uint64_t FieldBitOffset = getFieldOffsetInBits(Field); - if (GCCTypeOverlapsWithPadding(TREE_TYPE(Field), - PadStartBits-FieldBitOffset, PadSizeBits)) - return true; - } - return false; - } -} - -bool TypeConverter::GCCTypeOverlapsWithLLVMTypePadding(tree type, - const Type *Ty) { - - // Start by finding all of the padding in the LLVM Type. - SmallVector, 16> StructPadding; - FindLLVMTypePadding(Ty, type, 0, StructPadding); - - for (unsigned i = 0, e = StructPadding.size(); i != e; ++i) - if (GCCTypeOverlapsWithPadding(type, StructPadding[i].first, - StructPadding[i].second)) - return true; - return false; -} - - -//===----------------------------------------------------------------------===// -// Main Type Conversion Routines -//===----------------------------------------------------------------------===// - -const Type *TypeConverter::ConvertType(tree type) { - if (type == error_mark_node) return Type::getInt32Ty(Context); - - // LLVM doesn't care about variants such as const, volatile, or restrict. - type = TYPE_MAIN_VARIANT(type); - const Type *Ty; - - switch (TREE_CODE(type)) { - default: - DieAbjectly("Unknown type to convert!", type); - - case VOID_TYPE: - Ty = SET_TYPE_LLVM(type, Type::getVoidTy(Context)); - break; - - case RECORD_TYPE: - case QUAL_UNION_TYPE: - case UNION_TYPE: - Ty = ConvertRECORD(type); - break; - - case ENUMERAL_TYPE: - // Use of an enum that is implicitly declared? - if (TYPE_SIZE(type) == 0) { - // If we already compiled this type, use the old type. - if ((Ty = GET_TYPE_LLVM(type))) - return Ty; - - Ty = OpaqueType::get(Context); - Ty = TypeDB.setType(type, Ty); - break; - } - // FALL THROUGH. - case BOOLEAN_TYPE: - case INTEGER_TYPE: { - if ((Ty = GET_TYPE_LLVM(type))) return Ty; - uint64_t Size = getInt64(TYPE_SIZE(type), true); - Ty = SET_TYPE_LLVM(type, IntegerType::get(Context, Size)); - break; - } - - case REAL_TYPE: - if ((Ty = GET_TYPE_LLVM(type))) return Ty; - switch (TYPE_PRECISION(type)) { - default: - DieAbjectly("Unknown FP type!", type); - case 32: Ty = SET_TYPE_LLVM(type, Type::getFloatTy(Context)); break; - case 64: Ty = SET_TYPE_LLVM(type, Type::getDoubleTy(Context)); break; - case 80: Ty = SET_TYPE_LLVM(type, Type::getX86_FP80Ty(Context)); break; - case 128: -#ifdef TARGET_POWERPC - Ty = SET_TYPE_LLVM(type, Type::getPPC_FP128Ty(Context)); -#else - // IEEE quad precision. - Ty = SET_TYPE_LLVM(type, Type::getFP128Ty(Context)); -#endif - break; - } - break; - - case COMPLEX_TYPE: { - if ((Ty = GET_TYPE_LLVM(type))) return Ty; - Ty = ConvertType(TREE_TYPE(type)); - assert(!Ty->isAbstract() && "should use TypeDB.setType()"); - Ty = StructType::get(Context, Ty, Ty, NULL); - Ty = SET_TYPE_LLVM(type, Ty); - break; - } - - case VECTOR_TYPE: { - if ((Ty = GET_TYPE_LLVM(type))) return Ty; - Ty = ConvertType(TREE_TYPE(type)); - assert(!Ty->isAbstract() && "should use TypeDB.setType()"); - Ty = VectorType::get(Ty, TYPE_VECTOR_SUBPARTS(type)); - Ty = SET_TYPE_LLVM(type, Ty); - break; - } - - case POINTER_TYPE: - case REFERENCE_TYPE: - if (const PointerType *PTy = cast_or_null(GET_TYPE_LLVM(type))){ - // We already converted this type. If this isn't a case where we have to - // reparse it, just return it. - if (PointersToReresolve.empty() || PointersToReresolve.back() != type || - ConvertingStruct) - return PTy; - - // Okay, we know that we're !ConvertingStruct and that type is on the end - // of the vector. Remove this entry from the PointersToReresolve list and - // get the pointee type. Note that this order is important in case the - // pointee type uses this pointer. - assert(PTy->getElementType()->isOpaqueTy() && "Not a deferred ref!"); - - // We are actively resolving this pointer. We want to pop this value from - // the stack, as we are no longer resolving it. However, we don't want to - // make it look like we are now resolving the previous pointer on the - // stack, so pop this value and push a null. - PointersToReresolve.back() = 0; - - - // Do not do any nested resolution. We know that there is a higher-level - // loop processing deferred pointers, let it handle anything new. - ConvertingStruct = true; - - // Note that we know that PTy cannot be resolved or invalidated here. - const Type *Actual = ConvertType(TREE_TYPE(type)); - assert(GET_TYPE_LLVM(type) == PTy && "Pointer invalidated!"); - - // Restore ConvertingStruct for the caller. - ConvertingStruct = false; - - if (Actual->isVoidTy()) - Actual = Type::getInt8Ty(Context); // void* -> sbyte* - - // Update the type, potentially updating TYPE_LLVM(type). - const OpaqueType *OT = cast(PTy->getElementType()); - const_cast(OT)->refineAbstractTypeTo(Actual); - Ty = GET_TYPE_LLVM(type); - break; - } else { - // If we are converting a struct, and if we haven't converted the pointee - // type, add this pointer to PointersToReresolve and return an opaque*. - if (ConvertingStruct) { - // If the pointee type has not already been converted to LLVM, create - // a new opaque type and remember it in the database. - Ty = GET_TYPE_LLVM(TYPE_MAIN_VARIANT(TREE_TYPE(type))); - if (Ty == 0) { - PointersToReresolve.push_back(type); - Ty = TypeDB.setType(type, - PointerType::getUnqual(OpaqueType::get(Context))); - break; - } - - // A type has already been computed. However, this may be some sort of - // recursive struct. We don't want to call ConvertType on it, because - // this will try to resolve it, and not adding the type to the - // PointerToReresolve collection is just an optimization. Instead, - // we'll use the type returned by GET_TYPE_LLVM directly, even if this - // may be resolved further in the future. - } else { - // If we're not in a struct, just call ConvertType. If it has already - // been converted, this will return the precomputed value, otherwise - // this will compute and return the new type. - Ty = ConvertType(TREE_TYPE(type)); - } - - if (Ty->isVoidTy()) - Ty = Type::getInt8Ty(Context); // void* -> sbyte* - Ty = TypeDB.setType(type, Ty->getPointerTo()); - break; - } - - case METHOD_TYPE: - case FUNCTION_TYPE: { - if ((Ty = GET_TYPE_LLVM(type))) - return Ty; - - // No declaration to pass through, passing NULL. - CallingConv::ID CallingConv; - AttrListPtr PAL; - Ty = TypeDB.setType(type, ConvertFunctionType(type, NULL, NULL, - CallingConv, PAL)); - break; - } - - case ARRAY_TYPE: { - if ((Ty = GET_TYPE_LLVM(type))) - return Ty; - - const Type *ElementTy = ConvertType(TREE_TYPE(type)); - uint64_t NumElements = ArrayLengthOf(type); - - if (NumElements == NoLength) // Variable length array? - NumElements = 0; - - // Create the array type. - Ty = ArrayType::get(ElementTy, NumElements); - - // If the user increased the alignment of the array element type, then the - // size of the array is rounded up by that alignment even though the size - // of the array element type is not (!). Correct for this if necessary by - // adding padding. May also need padding if the element type has variable - // size and the array type has variable length, but by a miracle the product - // gives a constant size. - if (isInt64(TYPE_SIZE(type), true)) { - uint64_t PadBits = getInt64(TYPE_SIZE(type), true) - - getTargetData().getTypeAllocSizeInBits(Ty); - if (PadBits) { - const Type *Padding = ArrayType::get(Type::getInt8Ty(Context), PadBits / 8); - Ty = StructType::get(Context, Ty, Padding, NULL); - } - } - - Ty = TypeDB.setType(type, Ty); - break; - } - - case OFFSET_TYPE: - // Handle OFFSET_TYPE specially. This is used for pointers to members, - // which are really just integer offsets. As such, return the appropriate - // integer directly. - switch (getTargetData().getPointerSize()) { - default: assert(0 && "Unknown pointer size!"); - case 4: Ty = Type::getInt32Ty(Context); break; - case 8: Ty = Type::getInt64Ty(Context); break; - } - } - - // Try to give the type a helpful name. There is no point in doing this for - // array and pointer types since LLVM automatically gives them a useful name - // based on the element type. - if (!Ty->isVoidTy() && !isa(Ty)) { - const std::string &TypeName = getDescriptiveName(type); - if (!TypeName.empty()) - TheModule->addTypeName(TypeName, Ty); - } - - return Ty; -} - -//===----------------------------------------------------------------------===// -// FUNCTION/METHOD_TYPE Conversion Routines -//===----------------------------------------------------------------------===// - -namespace { - class FunctionTypeConversion : public DefaultABIClient { - PATypeHolder &RetTy; - std::vector &ArgTypes; - CallingConv::ID &CallingConv; - bool isShadowRet; - bool KNRPromotion; - unsigned Offset; - public: - FunctionTypeConversion(PATypeHolder &retty, std::vector &AT, - CallingConv::ID &CC, bool KNR) - : RetTy(retty), ArgTypes(AT), CallingConv(CC), KNRPromotion(KNR), Offset(0) { - CallingConv = CallingConv::C; - isShadowRet = false; - } - - /// getCallingConv - This provides the desired CallingConv for the function. - CallingConv::ID& getCallingConv(void) { return CallingConv; } - - bool isShadowReturn() const { return isShadowRet; } - - /// HandleScalarResult - This callback is invoked if the function returns a - /// simple scalar result value. - void HandleScalarResult(const Type *RetTy) { - this->RetTy = RetTy; - } - - /// HandleAggregateResultAsScalar - This callback is invoked if the function - /// returns an aggregate value by bit converting it to the specified scalar - /// type and returning that. - void HandleAggregateResultAsScalar(const Type *ScalarTy, unsigned Offset=0) { - RetTy = ScalarTy; - this->Offset = Offset; - } - - /// HandleAggregateResultAsAggregate - This callback is invoked if the function - /// returns an aggregate value using multiple return values. - void HandleAggregateResultAsAggregate(const Type *AggrTy) { - RetTy = AggrTy; - } - - /// HandleShadowResult - Handle an aggregate or scalar shadow argument. - void HandleShadowResult(const PointerType *PtrArgTy, bool RetPtr) { - // This function either returns void or the shadow argument, - // depending on the target. - RetTy = RetPtr ? PtrArgTy : Type::getVoidTy(Context); - - // In any case, there is a dummy shadow argument though! - ArgTypes.push_back(PtrArgTy); - - // Also, note the use of a shadow argument. - isShadowRet = true; - } - - /// HandleAggregateShadowResult - This callback is invoked if the function - /// returns an aggregate value by using a "shadow" first parameter, which is - /// a pointer to the aggregate, of type PtrArgTy. If RetPtr is set to true, - /// the pointer argument itself is returned from the function. - void HandleAggregateShadowResult(const PointerType *PtrArgTy, - bool RetPtr) { - HandleShadowResult(PtrArgTy, RetPtr); - } - - /// HandleScalarShadowResult - This callback is invoked if the function - /// returns a scalar value by using a "shadow" first parameter, which is a - /// pointer to the scalar, of type PtrArgTy. If RetPtr is set to true, - /// the pointer argument itself is returned from the function. - void HandleScalarShadowResult(const PointerType *PtrArgTy, bool RetPtr) { - HandleShadowResult(PtrArgTy, RetPtr); - } - - void HandlePad(const llvm::Type *LLVMTy) { - HandleScalarArgument(LLVMTy, 0, 0); - } - - void HandleScalarArgument(const llvm::Type *LLVMTy, tree type, - unsigned /*RealSize*/ = 0) { - if (KNRPromotion) { - if (type == float_type_node) - LLVMTy = ConvertType(double_type_node); - else if (LLVMTy->isIntegerTy(16) || LLVMTy->isIntegerTy(8) || - LLVMTy->isIntegerTy(1)) - LLVMTy = Type::getInt32Ty(Context); - } - ArgTypes.push_back(LLVMTy); - } - - /// HandleByInvisibleReferenceArgument - This callback is invoked if a pointer - /// (of type PtrTy) to the argument is passed rather than the argument itself. - void HandleByInvisibleReferenceArgument(const llvm::Type *PtrTy, - tree /*type*/) { - ArgTypes.push_back(PtrTy); - } - - /// HandleByValArgument - This callback is invoked if the aggregate function - /// argument is passed by value. It is lowered to a parameter passed by - /// reference with an additional parameter attribute "ByVal". - void HandleByValArgument(const llvm::Type *LLVMTy, tree type) { - HandleScalarArgument(LLVMTy->getPointerTo(), type); - } - - /// HandleFCAArgument - This callback is invoked if the aggregate function - /// argument is a first class aggregate passed by value. - void HandleFCAArgument(const llvm::Type *LLVMTy, tree /*type*/) { - ArgTypes.push_back(LLVMTy); - } - }; -} - - -static Attributes HandleArgumentExtension(tree ArgTy) { - if (TREE_CODE(ArgTy) == BOOLEAN_TYPE) { - if (TREE_INT_CST_LOW(TYPE_SIZE(ArgTy)) < INT_TYPE_SIZE) - return Attribute::ZExt; - } else if (TREE_CODE(ArgTy) == INTEGER_TYPE && - TREE_INT_CST_LOW(TYPE_SIZE(ArgTy)) < INT_TYPE_SIZE) { - if (TYPE_UNSIGNED(ArgTy)) - return Attribute::ZExt; - else - return Attribute::SExt; - } - - return Attribute::None; -} - -/// ConvertParamListToLLVMSignature - This method is used to build the argument -/// type list for K&R prototyped functions. In this case, we have to figure out -/// the type list (to build a FunctionType) from the actual DECL_ARGUMENTS list -/// for the function. This method takes the DECL_ARGUMENTS list (Args), and -/// fills in Result with the argument types for the function. It returns the -/// specified result type for the function. -const FunctionType *TypeConverter:: -ConvertArgListToFnType(tree type, tree Args, tree static_chain, - CallingConv::ID &CallingConv, AttrListPtr &PAL) { - tree ReturnType = TREE_TYPE(type); - std::vector ArgTys; - PATypeHolder RetTy(Type::getVoidTy(Context)); - - FunctionTypeConversion Client(RetTy, ArgTys, CallingConv, true /*K&R*/); - DefaultABI ABIConverter(Client); - -#ifdef TARGET_ADJUST_LLVM_CC - TARGET_ADJUST_LLVM_CC(CallingConv, type); -#endif - - // Builtins are always prototyped, so this isn't one. - ABIConverter.HandleReturnType(ReturnType, current_function_decl, false); - - SmallVector Attrs; - - // Compute whether the result needs to be zext or sext'd. - Attributes RAttributes = HandleArgumentExtension(ReturnType); - - // Allow the target to change the attributes. -#ifdef TARGET_ADJUST_LLVM_RETATTR - TARGET_ADJUST_LLVM_RETATTR(RAttributes, type); -#endif - - if (RAttributes != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(0, RAttributes)); - - // If this function returns via a shadow argument, the dest loc is passed - // in as a pointer. Mark that pointer as struct-ret and noalias. - if (ABIConverter.isShadowReturn()) - Attrs.push_back(AttributeWithIndex::get(ArgTys.size(), - Attribute::StructRet | Attribute::NoAlias)); - - std::vector ScalarArgs; - if (static_chain) { - // Pass the static chain as the first parameter. - ABIConverter.HandleArgument(TREE_TYPE(static_chain), ScalarArgs); - // Mark it as the chain argument. - Attrs.push_back(AttributeWithIndex::get(ArgTys.size(), - Attribute::Nest)); - } - - for (; Args && TREE_TYPE(Args) != void_type_node; Args = TREE_CHAIN(Args)) { - tree ArgTy = TREE_TYPE(Args); - - // Determine if there are any attributes for this param. - Attributes PAttributes = Attribute::None; - - ABIConverter.HandleArgument(ArgTy, ScalarArgs, &PAttributes); - - // Compute zext/sext attributes. - PAttributes |= HandleArgumentExtension(ArgTy); - - if (PAttributes != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(ArgTys.size(), PAttributes)); - } - - PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); - return GetFunctionType(RetTy, ArgTys, false); -} - -const FunctionType *TypeConverter:: -ConvertFunctionType(tree type, tree decl, tree static_chain, - CallingConv::ID &CallingConv, AttrListPtr &PAL) { - PATypeHolder RetTy = Type::getVoidTy(Context); - std::vector ArgTypes; - bool isVarArg = false; - FunctionTypeConversion Client(RetTy, ArgTypes, CallingConv, false/*not K&R*/); - DefaultABI ABIConverter(Client); - - // Allow the target to set the CC for things like fastcall etc. -#ifdef TARGET_ADJUST_LLVM_CC - TARGET_ADJUST_LLVM_CC(CallingConv, type); -#endif - - ABIConverter.HandleReturnType(TREE_TYPE(type), current_function_decl, - decl ? DECL_BUILT_IN(decl) : false); - - // Compute attributes for return type (and function attributes). - SmallVector Attrs; - Attributes FnAttributes = Attribute::None; - - int flags = flags_from_decl_or_type(decl ? decl : type); - - // Check for 'noreturn' function attribute. - if (flags & ECF_NORETURN) - FnAttributes |= Attribute::NoReturn; - - // Check for 'nounwind' function attribute. - if (flags & ECF_NOTHROW) - FnAttributes |= Attribute::NoUnwind; - - // Check for 'readnone' function attribute. - // Both PURE and CONST will be set if the user applied - // __attribute__((const)) to a function the compiler - // knows to be pure, such as log. A user or (more - // likely) libm implementor might know their local log - // is in fact const, so this should be valid (and gcc - // accepts it). But llvm IR does not allow both, so - // set only ReadNone. - if (flags & ECF_CONST) - FnAttributes |= Attribute::ReadNone; - - // Check for 'readonly' function attribute. - if (flags & ECF_PURE && !(flags & ECF_CONST)) - FnAttributes |= Attribute::ReadOnly; - - // Since they write the return value through a pointer, - // 'sret' functions cannot be 'readnone' or 'readonly'. - if (ABIConverter.isShadowReturn()) - FnAttributes &= ~(Attribute::ReadNone|Attribute::ReadOnly); - - // Demote 'readnone' nested functions to 'readonly' since - // they may need to read through the static chain. - if (static_chain && (FnAttributes & Attribute::ReadNone)) { - FnAttributes &= ~Attribute::ReadNone; - FnAttributes |= Attribute::ReadOnly; - } - - // Compute whether the result needs to be zext or sext'd. - Attributes RAttributes = Attribute::None; - RAttributes |= HandleArgumentExtension(TREE_TYPE(type)); - - // Allow the target to change the attributes. -#ifdef TARGET_ADJUST_LLVM_RETATTR - TARGET_ADJUST_LLVM_RETATTR(RAttributes, type); -#endif - - // The value returned by a 'malloc' function does not alias anything. - if (flags & ECF_MALLOC) - RAttributes |= Attribute::NoAlias; - - if (RAttributes != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(0, RAttributes)); - - // If this function returns via a shadow argument, the dest loc is passed - // in as a pointer. Mark that pointer as struct-ret and noalias. - if (ABIConverter.isShadowReturn()) - Attrs.push_back(AttributeWithIndex::get(ArgTypes.size(), - Attribute::StructRet | Attribute::NoAlias)); - - std::vector ScalarArgs; - if (static_chain) { - // Pass the static chain as the first parameter. - ABIConverter.HandleArgument(TREE_TYPE(static_chain), ScalarArgs); - // Mark it as the chain argument. - Attrs.push_back(AttributeWithIndex::get(ArgTypes.size(), - Attribute::Nest)); - } - - // If the target has regparam parameters, allow it to inspect the function - // type. - int local_regparam = 0; - int local_fp_regparam = 0; -#ifdef LLVM_TARGET_ENABLE_REGPARM - LLVM_TARGET_INIT_REGPARM(local_regparam, local_fp_regparam, type); -#endif // LLVM_TARGET_ENABLE_REGPARM - - // Keep track of whether we see a byval argument. - bool HasByVal = false; - - // Check if we have a corresponding decl to inspect. - tree DeclArgs = (decl) ? DECL_ARGUMENTS(decl) : NULL; - // Loop over all of the arguments, adding them as we go. - tree Args = TYPE_ARG_TYPES(type); - for (; Args && TREE_VALUE(Args) != void_type_node; Args = TREE_CHAIN(Args)){ - tree ArgTy = TREE_VALUE(Args); - if (!isPassedByInvisibleReference(ArgTy) && - ConvertType(ArgTy)->isOpaqueTy()) { - // If we are passing an opaque struct by value, we don't know how many - // arguments it will turn into. Because we can't handle this yet, - // codegen the prototype as (...). - if (CallingConv == CallingConv::C) - ArgTypes.clear(); - else - // Don't nuke last argument. - ArgTypes.erase(ArgTypes.begin()+1, ArgTypes.end()); - Args = 0; - break; - } - - // Determine if there are any attributes for this param. - Attributes PAttributes = Attribute::None; - - unsigned OldSize = ArgTypes.size(); - - ABIConverter.HandleArgument(ArgTy, ScalarArgs, &PAttributes); - - // Compute zext/sext attributes. - PAttributes |= HandleArgumentExtension(ArgTy); - - // Compute noalias attributes. If we have a decl for the function - // inspect it for restrict qualifiers, otherwise try the argument - // types. - tree RestrictArgTy = (DeclArgs) ? TREE_TYPE(DeclArgs) : ArgTy; - if (TREE_CODE(RestrictArgTy) == POINTER_TYPE || - TREE_CODE(RestrictArgTy) == REFERENCE_TYPE) { - if (TYPE_RESTRICT(RestrictArgTy)) - PAttributes |= Attribute::NoAlias; - } - -#ifdef LLVM_TARGET_ENABLE_REGPARM - // Allow the target to mark this as inreg. - if (INTEGRAL_TYPE_P(ArgTy) || POINTER_TYPE_P(ArgTy) || - SCALAR_FLOAT_TYPE_P(ArgTy)) - LLVM_ADJUST_REGPARM_ATTRIBUTE(PAttributes, ArgTy, - TREE_INT_CST_LOW(TYPE_SIZE(ArgTy)), - local_regparam, local_fp_regparam); -#endif // LLVM_TARGET_ENABLE_REGPARM - - if (PAttributes != Attribute::None) { - HasByVal |= PAttributes & Attribute::ByVal; - - // If the argument is split into multiple scalars, assign the - // attributes to all scalars of the aggregate. - for (unsigned i = OldSize + 1; i <= ArgTypes.size(); ++i) { - Attrs.push_back(AttributeWithIndex::get(i, PAttributes)); - } - } - - if (DeclArgs) - DeclArgs = TREE_CHAIN(DeclArgs); - } - - // If there is a byval argument then it is not safe to mark the function - // 'readnone' or 'readonly': gcc permits a 'const' or 'pure' function to - // write to struct arguments passed by value, but in LLVM this becomes a - // write through the byval pointer argument, which LLVM does not allow for - // readonly/readnone functions. - if (HasByVal) - FnAttributes &= ~(Attribute::ReadNone | Attribute::ReadOnly); - - if (flag_force_vararg_prototypes) - // If forcing prototypes to be varargs, make all function types varargs - // except those for builtin functions. - isVarArg = decl ? !DECL_BUILT_IN(decl) : true; - else - // If the argument list ends with a void type node, it isn't vararg. - isVarArg = (Args == 0); - assert(RetTy && "Return type not specified!"); - - if (FnAttributes != Attribute::None) - Attrs.push_back(AttributeWithIndex::get(~0, FnAttributes)); - - // Finally, make the function type and result attributes. - PAL = AttrListPtr::get(Attrs.begin(), Attrs.end()); - return GetFunctionType(RetTy, ArgTypes, isVarArg); -} - -//===----------------------------------------------------------------------===// -// RECORD/Struct Conversion Routines -//===----------------------------------------------------------------------===// - -/// StructTypeConversionInfo - A temporary structure that is used when -/// translating a RECORD_TYPE to an LLVM type. -struct StructTypeConversionInfo { - std::vector Elements; - std::vector ElementOffsetInBytes; - std::vector ElementSizeInBytes; - std::vector PaddingElement; // True if field is used for padding - const TargetData &TD; - unsigned GCCStructAlignmentInBytes; - bool Packed; // True if struct is packed - bool AllBitFields; // True if all struct fields are bit fields - bool LastFieldStartsAtNonByteBoundry; - unsigned ExtraBitsAvailable; // Non-zero if last field is bit field and it - // does not use all allocated bits - - StructTypeConversionInfo(TargetMachine &TM, unsigned GCCAlign, bool P) - : TD(*TM.getTargetData()), GCCStructAlignmentInBytes(GCCAlign), - Packed(P), AllBitFields(true), LastFieldStartsAtNonByteBoundry(false), - ExtraBitsAvailable(0) {} - - void lastFieldStartsAtNonByteBoundry(bool value) { - LastFieldStartsAtNonByteBoundry = value; - } - - void extraBitsAvailable (unsigned E) { - ExtraBitsAvailable = E; - } - - bool isPacked() { return Packed; } - - void markAsPacked() { - Packed = true; - } - - void allFieldsAreNotBitFields() { - AllBitFields = false; - // Next field is not a bitfield. - LastFieldStartsAtNonByteBoundry = false; - } - - unsigned getGCCStructAlignmentInBytes() const { - return GCCStructAlignmentInBytes; - } - - /// getTypeAlignment - Return the alignment of the specified type in bytes. - /// - unsigned getTypeAlignment(const Type *Ty) const { - return Packed ? 1 : TD.getABITypeAlignment(Ty); - } - - /// getTypeSize - Return the size of the specified type in bytes. - /// - uint64_t getTypeSize(const Type *Ty) const { - return TD.getTypeAllocSize(Ty); - } - - /// getLLVMType - Return the LLVM type for the specified object. - /// - const Type *getLLVMType() const { - // Use Packed type if Packed is set or all struct fields are bitfields. - // Empty struct is not packed unless packed is set. - return StructType::get(Context, Elements, - Packed || (!Elements.empty() && AllBitFields)); - } - - /// getAlignmentAsLLVMStruct - Return the alignment of this struct if it were - /// converted to an LLVM type. - uint64_t getAlignmentAsLLVMStruct() const { - if (Packed || AllBitFields) return 1; - unsigned MaxAlign = 1; - for (unsigned i = 0, e = Elements.size(); i != e; ++i) - MaxAlign = std::max(MaxAlign, getTypeAlignment(Elements[i])); - return MaxAlign; - } - - /// getSizeAsLLVMStruct - Return the size of this struct if it were converted - /// to an LLVM type. This is the end of last element push an alignment pad at - /// the end. - uint64_t getSizeAsLLVMStruct() const { - if (Elements.empty()) return 0; - unsigned MaxAlign = getAlignmentAsLLVMStruct(); - uint64_t Size = ElementOffsetInBytes.back()+ElementSizeInBytes.back(); - return (Size+MaxAlign-1) & ~(MaxAlign-1); - } - - // If this is a Packed struct and ExtraBitsAvailable is not zero then - // remove Extra bytes if ExtraBitsAvailable > 8. - void RemoveExtraBytes () { - - unsigned NoOfBytesToRemove = ExtraBitsAvailable/8; - - if (!Packed && !AllBitFields) - return; - - if (NoOfBytesToRemove == 0) - return; - - const Type *LastType = Elements.back(); - unsigned PadBytes = 0; - - if (LastType->isIntegerTy(8)) - PadBytes = 1 - NoOfBytesToRemove; - else if (LastType->isIntegerTy(16)) - PadBytes = 2 - NoOfBytesToRemove; - else if (LastType->isIntegerTy(32)) - PadBytes = 4 - NoOfBytesToRemove; - else if (LastType->isIntegerTy(64)) - PadBytes = 8 - NoOfBytesToRemove; - else - return; - - assert (PadBytes > 0 && "Unable to remove extra bytes"); - - // Update last element type and size, element offset is unchanged. - const Type *Pad = ArrayType::get(Type::getInt8Ty(Context), PadBytes); - unsigned OriginalSize = ElementSizeInBytes.back(); - Elements.pop_back(); - Elements.push_back(Pad); - - ElementSizeInBytes.pop_back(); - ElementSizeInBytes.push_back(OriginalSize - NoOfBytesToRemove); - } - - /// ResizeLastElementIfOverlapsWith - If the last element in the struct - /// includes the specified byte, remove it. Return true struct - /// layout is sized properly. Return false if unable to handle ByteOffset. - /// In this case caller should redo this struct as a packed structure. - bool ResizeLastElementIfOverlapsWith(uint64_t ByteOffset, tree /*Field*/, - const Type *Ty) { - const Type *SavedTy = NULL; - - if (!Elements.empty()) { - assert(ElementOffsetInBytes.back() <= ByteOffset && - "Cannot go backwards in struct"); - - SavedTy = Elements.back(); - if (ElementOffsetInBytes.back()+ElementSizeInBytes.back() > ByteOffset) { - // The last element overlapped with this one, remove it. - uint64_t PoppedOffset = ElementOffsetInBytes.back(); - Elements.pop_back(); - ElementOffsetInBytes.pop_back(); - ElementSizeInBytes.pop_back(); - PaddingElement.pop_back(); - uint64_t EndOffset = getNewElementByteOffset(1); - if (EndOffset < PoppedOffset) { - // Make sure that some field starts at the position of the - // field we just popped. Otherwise we might end up with a - // gcc non-bitfield being mapped to an LLVM field with a - // different offset. - const Type *Pad = Type::getInt8Ty(Context); - if (PoppedOffset != EndOffset + 1) - Pad = ArrayType::get(Pad, PoppedOffset - EndOffset); - addElement(Pad, EndOffset, PoppedOffset - EndOffset); - } - } - } - - // Get the LLVM type for the field. If this field is a bitfield, use the - // declared type, not the shrunk-to-fit type that GCC gives us in TREE_TYPE. - unsigned ByteAlignment = getTypeAlignment(Ty); - uint64_t NextByteOffset = getNewElementByteOffset(ByteAlignment); - if (NextByteOffset > ByteOffset || - ByteAlignment > getGCCStructAlignmentInBytes()) { - // LLVM disagrees as to where this field should go in the natural field - // ordering. Therefore convert to a packed struct and try again. - return false; - } - - // If alignment won't round us up to the right boundary, insert explicit - // padding. - if (NextByteOffset < ByteOffset) { - uint64_t CurOffset = getNewElementByteOffset(1); - const Type *Pad = Type::getInt8Ty(Context); - if (SavedTy && LastFieldStartsAtNonByteBoundry) - // We want to reuse SavedType to access this bit field. - // e.g. struct __attribute__((packed)) { - // unsigned int A, - // unsigned short B : 6, - // C : 15; - // char D; }; - // In this example, previous field is C and D is current field. - addElement(SavedTy, CurOffset, ByteOffset - CurOffset); - else if (ByteOffset - CurOffset != 1) - Pad = ArrayType::get(Pad, ByteOffset - CurOffset); - addElement(Pad, CurOffset, ByteOffset - CurOffset); - } - return true; - } - - /// FieldNo - Remove the specified field and all of the fields that come after - /// it. - void RemoveFieldsAfter(unsigned FieldNo) { - Elements.erase(Elements.begin()+FieldNo, Elements.end()); - ElementOffsetInBytes.erase(ElementOffsetInBytes.begin()+FieldNo, - ElementOffsetInBytes.end()); - ElementSizeInBytes.erase(ElementSizeInBytes.begin()+FieldNo, - ElementSizeInBytes.end()); - PaddingElement.erase(PaddingElement.begin()+FieldNo, - PaddingElement.end()); - } - - /// getNewElementByteOffset - If we add a new element with the specified - /// alignment, what byte offset will it land at? - uint64_t getNewElementByteOffset(unsigned ByteAlignment) { - if (Elements.empty()) return 0; - uint64_t LastElementEnd = - ElementOffsetInBytes.back() + ElementSizeInBytes.back(); - - return (LastElementEnd+ByteAlignment-1) & ~(ByteAlignment-1); - } - - /// addElement - Add an element to the structure with the specified type, - /// offset and size. - void addElement(const Type *Ty, uint64_t Offset, uint64_t Size, - bool ExtraPadding = false) { - Elements.push_back(Ty); - ElementOffsetInBytes.push_back(Offset); - ElementSizeInBytes.push_back(Size); - PaddingElement.push_back(ExtraPadding); - lastFieldStartsAtNonByteBoundry(false); - ExtraBitsAvailable = 0; - } - - /// getFieldEndOffsetInBytes - Return the byte offset of the byte immediately - /// after the specified field. For example, if FieldNo is 0 and the field - /// is 4 bytes in size, this will return 4. - uint64_t getFieldEndOffsetInBytes(unsigned FieldNo) const { - assert(FieldNo < ElementOffsetInBytes.size() && "Invalid field #!"); - return ElementOffsetInBytes[FieldNo]+ElementSizeInBytes[FieldNo]; - } - - /// getEndUnallocatedByte - Return the first byte that isn't allocated at the - /// end of a structure. For example, for {}, it's 0, for {int} it is 4, for - /// {int,short}, it is 6. - uint64_t getEndUnallocatedByte() const { - if (ElementOffsetInBytes.empty()) return 0; - return getFieldEndOffsetInBytes(ElementOffsetInBytes.size()-1); - } - - void addNewBitField(uint64_t Size, uint64_t Extra, - uint64_t FirstUnallocatedByte); - - void dump() const; -}; - -// Add new element which is a bit field. Size is not the size of bit field, -// but size of bits required to determine type of new Field which will be -// used to access this bit field. -// If possible, allocate a field with room for Size+Extra bits. -void StructTypeConversionInfo::addNewBitField(uint64_t Size, uint64_t Extra, - uint64_t FirstUnallocatedByte) { - - // Figure out the LLVM type that we will use for the new field. - // Note, Size is not necessarily size of the new field. It indicates - // additional bits required after FirstunallocatedByte to cover new field. - const Type *NewFieldTy = 0; - - // First try an ABI-aligned field including (some of) the Extra bits. - // This field must satisfy Size <= w && w <= XSize. - uint64_t XSize = Size + Extra; - for (unsigned w = NextPowerOf2(std::min(UINT64_C(64), XSize))/2; - w >= Size && w >= 8; w /= 2) { - if (TD.isIllegalInteger(w)) - continue; - // Would a w-sized integer field be aligned here? - const unsigned a = TD.getABIIntegerTypeAlignment(w); - if (FirstUnallocatedByte & (a-1) || a > getGCCStructAlignmentInBytes()) - continue; - // OK, use w-sized integer. - NewFieldTy = IntegerType::get(Context, w); - break; - } - - // Try an integer field that holds Size bits. - if (!NewFieldTy) { - if (Size <= 8) - NewFieldTy = Type::getInt8Ty(Context); - else if (Size <= 16) - NewFieldTy = Type::getInt16Ty(Context); - else if (Size <= 32) - NewFieldTy = Type::getInt32Ty(Context); - else { - assert(Size <= 64 && "Bitfield too large!"); - NewFieldTy = Type::getInt64Ty(Context); - } - } - - // Check that the alignment of NewFieldTy won't cause a gap in the structure! - unsigned ByteAlignment = getTypeAlignment(NewFieldTy); - if (FirstUnallocatedByte & (ByteAlignment-1) || - ByteAlignment > getGCCStructAlignmentInBytes()) { - // Instead of inserting a nice whole field, insert a small array of ubytes. - NewFieldTy = ArrayType::get(Type::getInt8Ty(Context), (Size+7)/8); - } - - // Finally, add the new field. - addElement(NewFieldTy, FirstUnallocatedByte, getTypeSize(NewFieldTy)); - ExtraBitsAvailable = NewFieldTy->getPrimitiveSizeInBits() - Size; -} - -void StructTypeConversionInfo::dump() const { - raw_ostream &OS = outs(); - OS << "Info has " << Elements.size() << " fields:\n"; - for (unsigned i = 0, e = Elements.size(); i != e; ++i) { - OS << " Offset = " << ElementOffsetInBytes[i] - << " Size = " << ElementSizeInBytes[i] - << " Type = "; - WriteTypeSymbolic(OS, Elements[i], TheModule); - OS << "\n"; - } - OS.flush(); -} - -std::map StructTypeInfoMap; - -/// Return true if and only if field no. N from struct type T is a padding -/// element added to match llvm struct type size and gcc struct type size. -bool isPaddingElement(tree type, unsigned index) { - - StructTypeConversionInfo *Info = StructTypeInfoMap[type]; - - // If info is not available then be conservative and return false. - if (!Info) - return false; - - assert ( Info->Elements.size() == Info->PaddingElement.size() - && "Invalid StructTypeConversionInfo"); - assert ( index < Info->PaddingElement.size() - && "Invalid PaddingElement index"); - return Info->PaddingElement[index]; -} - -/// OldTy and NewTy are union members. If they are representing -/// structs then adjust their PaddingElement bits. Padding -/// field in one struct may not be a padding field in another -/// struct. -void adjustPaddingElement(tree oldtree, tree newtree) { - - StructTypeConversionInfo *OldInfo = StructTypeInfoMap[oldtree]; - StructTypeConversionInfo *NewInfo = StructTypeInfoMap[newtree]; - - if (!OldInfo || !NewInfo) - return; - - /// FIXME : Find overlapping padding fields and preserve their - /// isPaddingElement bit. For now, clear all isPaddingElement bits. - for (unsigned i = 0, size = NewInfo->PaddingElement.size(); i != size; ++i) - NewInfo->PaddingElement[i] = false; - - for (unsigned i = 0, size = OldInfo->PaddingElement.size(); i != size; ++i) - OldInfo->PaddingElement[i] = false; - -} - -/// DecodeStructFields - This method decodes the specified field, if it is a -/// FIELD_DECL, adding or updating the specified StructTypeConversionInfo to -/// reflect it. Return true if field is decoded correctly. Otherwise return -/// false. -bool TypeConverter::DecodeStructFields(tree Field, - StructTypeConversionInfo &Info) { - // Handle bit-fields specially. - if (isBitfield(Field)) { - // If this field is forcing packed llvm struct then retry entire struct - // layout. - if (!Info.isPacked()) { - // Unnamed bitfield type does not contribute in struct alignment - // computations. Use packed llvm structure in such cases. - if (!DECL_NAME(Field)) - return false; - // If this field is packed then the struct may need padding fields - // before this field. - if (DECL_PACKED(Field)) - return false; - // If Field has user defined alignment and it does not match Ty alignment - // then convert to a packed struct and try again. - if (TYPE_USER_ALIGN(TREE_TYPE(Field))) { - const Type *Ty = ConvertType(TREE_TYPE(Field)); - if (TYPE_ALIGN(TREE_TYPE(Field)) != - 8 * Info.getTypeAlignment(Ty)) - return false; - } - } - DecodeStructBitField(Field, Info); - return true; - } - - Info.allFieldsAreNotBitFields(); - - // Get the starting offset in the record. - uint64_t StartOffsetInBits = getFieldOffsetInBits(Field); - assert((StartOffsetInBits & 7) == 0 && "Non-bit-field has non-byte offset!"); - uint64_t StartOffsetInBytes = StartOffsetInBits/8; - - const Type *Ty = ConvertType(TREE_TYPE(Field)); - - // If this field is packed then the struct may need padding fields - // before this field. - if (DECL_PACKED(Field) && !Info.isPacked()) - return false; - // Pop any previous elements out of the struct if they overlap with this one. - // This can happen when the C++ front-end overlaps fields with tail padding in - // C++ classes. - else if (!Info.ResizeLastElementIfOverlapsWith(StartOffsetInBytes, Field, Ty)) { - // LLVM disagrees as to where this field should go in the natural field - // ordering. Therefore convert to a packed struct and try again. - return false; - } - else if (TYPE_USER_ALIGN(TREE_TYPE(Field)) - && (unsigned)DECL_ALIGN(Field) != 8 * Info.getTypeAlignment(Ty) - && !Info.isPacked()) { - // If Field has user defined alignment and it does not match Ty alignment - // then convert to a packed struct and try again. - return false; - } else - // At this point, we know that adding the element will happen at the right - // offset. Add it. - Info.addElement(Ty, StartOffsetInBytes, Info.getTypeSize(Ty)); - return true; -} - -/// DecodeStructBitField - This method decodes the specified bit-field, adding -/// or updating the specified StructTypeConversionInfo to reflect it. -/// -/// Note that in general, we cannot produce a good covering of struct fields for -/// bitfields. As such, we only make sure that all bits in a struct that -/// correspond to a bitfield are represented in the LLVM struct with -/// (potentially multiple) integer fields of integer type. This ensures that -/// initialized globals with bitfields can have the initializers for the -/// bitfields specified. -void TypeConverter::DecodeStructBitField(tree_node *Field, - StructTypeConversionInfo &Info) { - unsigned FieldSizeInBits = TREE_INT_CST_LOW(DECL_SIZE(Field)); - - if (FieldSizeInBits == 0) // Ignore 'int:0', which just affects layout. - return; - - // Get the starting offset in the record. - uint64_t StartOffsetInBits = getFieldOffsetInBits(Field); - uint64_t EndBitOffset = FieldSizeInBits+StartOffsetInBits; - - // If the last inserted LLVM field completely contains this bitfield, just - // ignore this field. - if (!Info.Elements.empty()) { - uint64_t LastFieldBitOffset = Info.ElementOffsetInBytes.back()*8; - unsigned LastFieldBitSize = Info.ElementSizeInBytes.back()*8; - assert(LastFieldBitOffset <= StartOffsetInBits && - "This bitfield isn't part of the last field!"); - if (EndBitOffset <= LastFieldBitOffset+LastFieldBitSize && - LastFieldBitOffset+LastFieldBitSize >= StartOffsetInBits) { - // Already contained in previous field. Update remaining extra bits that - // are available. - Info.extraBitsAvailable(Info.getEndUnallocatedByte()*8 - EndBitOffset); - return; - } - } - - // Otherwise, this bitfield lives (potentially) partially in the preceeding - // field and in fields that exist after it. Add integer-typed fields to the - // LLVM struct such that there are no holes in the struct where the bitfield - // is: these holes would make it impossible to statically initialize a global - // of this type that has an initializer for the bitfield. - - // We want the integer-typed fields as large as possible up to the machine - // word size. If there are more bitfields following this one, try to include - // them in the same field. - - // Calculate the total number of bits in the continuous group of bitfields - // following this one. This is the number of bits that addNewBitField should - // try to include. - unsigned ExtraSizeInBits = 0; - tree LastBitField = 0; - for (tree f = TREE_CHAIN(Field); f; f = TREE_CHAIN(f)) { - if (TREE_CODE(f) != FIELD_DECL || - TREE_CODE(DECL_FIELD_OFFSET(f)) != INTEGER_CST) - break; - if (isBitfield(f)) - LastBitField = f; - else { - // We can use all this bits up to the next non-bitfield. - LastBitField = 0; - ExtraSizeInBits = getFieldOffsetInBits(f) - EndBitOffset; - break; - } - } - // Record ended in a bitfield? Use all of the last byte. - if (LastBitField) - ExtraSizeInBits = RoundUpToAlignment(getFieldOffsetInBits(LastBitField) + - TREE_INT_CST_LOW(DECL_SIZE(LastBitField)), 8) - EndBitOffset; - - // Compute the number of bits that we need to add to this struct to cover - // this field. - uint64_t FirstUnallocatedByte = Info.getEndUnallocatedByte(); - uint64_t StartOffsetFromByteBoundry = StartOffsetInBits & 7; - - if (StartOffsetInBits < FirstUnallocatedByte*8) { - - uint64_t AvailableBits = FirstUnallocatedByte * 8 - StartOffsetInBits; - // This field's starting point is already allocated. - if (StartOffsetFromByteBoundry == 0) { - // This field starts at byte boundry. Need to allocate space - // for additional bytes not yet allocated. - unsigned NumBitsToAdd = FieldSizeInBits - AvailableBits; - Info.addNewBitField(NumBitsToAdd, ExtraSizeInBits, FirstUnallocatedByte); - return; - } - - // Otherwise, this field's starting point is inside previously used byte. - // This happens with Packed bit fields. In this case one LLVM Field is - // used to access previous field and current field. - unsigned prevFieldTypeSizeInBits = - Info.ElementSizeInBytes[Info.Elements.size() - 1] * 8; - - unsigned NumBitsRequired = prevFieldTypeSizeInBits - + (FieldSizeInBits - AvailableBits); - - if (NumBitsRequired > 64) { - // Use bits from previous field. - NumBitsRequired = FieldSizeInBits - AvailableBits; - } else { - // If type used to access previous field is not large enough then - // remove previous field and insert new field that is large enough to - // hold both fields. - Info.RemoveFieldsAfter(Info.Elements.size() - 1); - for (unsigned idx = 0; idx < (prevFieldTypeSizeInBits/8); ++idx) - FirstUnallocatedByte--; - } - Info.addNewBitField(NumBitsRequired, ExtraSizeInBits, FirstUnallocatedByte); - // Do this after adding Field. - Info.lastFieldStartsAtNonByteBoundry(true); - return; - } - - if (StartOffsetInBits > FirstUnallocatedByte*8) { - // If there is padding between the last field and the struct, insert - // explicit bytes into the field to represent it. - unsigned PadBytes = 0; - unsigned PadBits = 0; - if (StartOffsetFromByteBoundry != 0) { - // New field does not start at byte boundry. - PadBits = StartOffsetInBits - (FirstUnallocatedByte*8); - PadBytes = PadBits/8; - PadBits = PadBits - PadBytes*8; - } else - PadBytes = StartOffsetInBits/8-FirstUnallocatedByte; - - if (PadBytes) { - const Type *Pad = Type::getInt8Ty(Context); - if (PadBytes != 1) - Pad = ArrayType::get(Pad, PadBytes); - Info.addElement(Pad, FirstUnallocatedByte, PadBytes); - } - - FirstUnallocatedByte = StartOffsetInBits/8; - // This field will use some of the bits from this PadBytes, if - // starting offset is not at byte boundry. - if (StartOffsetFromByteBoundry != 0) - FieldSizeInBits += PadBits; - } - - // Now, Field starts at FirstUnallocatedByte and everything is aligned. - Info.addNewBitField(FieldSizeInBits, ExtraSizeInBits, FirstUnallocatedByte); -} - -/// UnionHasOnlyZeroOffsets - Check if a union type has only members with -/// offsets that are zero, e.g., no Fortran equivalences. -static bool UnionHasOnlyZeroOffsets(tree type) { - for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) { - if (TREE_CODE(Field) != FIELD_DECL) continue; - if (!OffsetIsLLVMCompatible(Field)) - return false; - if (getFieldOffsetInBits(Field) != 0) - return false; - } - return true; -} - -/// SelectUnionMember - Find the union member with the largest aligment. If -/// there are multiple types with the same alignment, select the one with -/// the largest size. If the type with max. align is smaller than other types, -/// then we will add padding later on anyway to match union size. -void TypeConverter::SelectUnionMember(tree type, - StructTypeConversionInfo &Info) { - bool FindBiggest = TREE_CODE(type) != QUAL_UNION_TYPE; - - const Type *UnionTy = 0; - tree GccUnionTy = 0; - tree UnionField = 0; - unsigned MinAlign = ~0U; - uint64_t BestSize = FindBiggest ? 0 : ~(uint64_t)0; - for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) { - if (TREE_CODE(Field) != FIELD_DECL) continue; - assert(DECL_FIELD_OFFSET(Field) && integer_zerop(DECL_FIELD_OFFSET(Field)) - && "Union with non-zero offset?"); - - // Skip fields that are known not to be present. - if (TREE_CODE(type) == QUAL_UNION_TYPE && - integer_zerop(DECL_QUALIFIER(Field))) - continue; - - tree TheGccTy = TREE_TYPE(Field); - - // Skip zero-length bitfields. These are only used for setting the - // alignment. - if (DECL_BIT_FIELD(Field) && DECL_SIZE(Field) && - integer_zerop(DECL_SIZE(Field))) - continue; - - const Type *TheTy = ConvertType(TheGccTy); - unsigned Align = Info.getTypeAlignment(TheTy); - uint64_t Size = Info.getTypeSize(TheTy); - - adjustPaddingElement(GccUnionTy, TheGccTy); - - // Select TheTy as union type if it is the biggest/smallest field (depending - // on the value of FindBiggest). If more than one field achieves this size - // then choose the least aligned. - if ((Size == BestSize && Align < MinAlign) || - (FindBiggest && Size > BestSize) || - (!FindBiggest && Size < BestSize)) { - UnionTy = TheTy; - UnionField = Field; - GccUnionTy = TheGccTy; - BestSize = Size; - MinAlign = Align; - } - - // Skip remaining fields if this one is known to be present. - if (TREE_CODE(type) == QUAL_UNION_TYPE && - integer_onep(DECL_QUALIFIER(Field))) - break; - } - - if (UnionTy) { // Not an empty union. - if (8 * Info.getTypeAlignment(UnionTy) > TYPE_ALIGN(type)) - Info.markAsPacked(); - - if (isBitfield(UnionField)) { - unsigned FieldSizeInBits = TREE_INT_CST_LOW(DECL_SIZE(UnionField)); - Info.addNewBitField(FieldSizeInBits, 0, 0); - } else { - Info.allFieldsAreNotBitFields(); - Info.addElement(UnionTy, 0, Info.getTypeSize(UnionTy)); - } - } -} - -/// ConvertRECORD - Convert a RECORD_TYPE, UNION_TYPE or QUAL_UNION_TYPE to -/// an LLVM type. -// A note on C++ virtual base class layout. Consider the following example: -// class A { public: int i0; }; -// class B : public virtual A { public: int i1; }; -// class C : public virtual A { public: int i2; }; -// class D : public virtual B, public virtual C { public: int i3; }; -// -// The TYPE nodes gcc builds for classes represent that class as it looks -// standing alone. Thus B is size 12 and looks like { vptr; i2; baseclass A; } -// However, this is not the layout used when that class is a base class for -// some other class, yet the same TYPE node is still used. D in the above has -// both a BINFO list entry and a FIELD that reference type B, but the virtual -// base class A within B is not allocated in that case; B-within-D is only -// size 8. The correct size is in the FIELD node (does not match the size -// in its child TYPE node.) The fields to be omitted from the child TYPE, -// as far as I can tell, are always the last ones; but also, there is a -// TYPE_DECL node sitting in the middle of the FIELD list separating virtual -// base classes from everything else. -// -// Similarly, a nonvirtual base class which has virtual base classes might -// not contain those virtual base classes when used as a nonvirtual base class. -// There is seemingly no way to detect this except for the size differential. -// -// For LLVM purposes, we build a new type for B-within-D that -// has the correct size and layout for that usage. - -const Type *TypeConverter::ConvertRECORD(tree type) { - if (const Type *Ty = GET_TYPE_LLVM(type)) { - // If we already compiled this type, and if it was not a forward - // definition that is now defined, use the old type. - if (!Ty->isOpaqueTy() || TYPE_SIZE(type) == 0) - return Ty; - } - - if (TYPE_SIZE(type) == 0) { // Forward declaration? - const Type *Ty = OpaqueType::get(Context); - return TypeDB.setType(type, Ty); - } - - // Note that we are compiling a struct now. - bool OldConvertingStruct = ConvertingStruct; - ConvertingStruct = true; - - // Record those fields which will be converted to LLVM fields. - SmallVector, 32> Fields; - for (tree Field = TYPE_FIELDS(type); Field; Field = TREE_CHAIN(Field)) - if (TREE_CODE(Field) == FIELD_DECL && OffsetIsLLVMCompatible(Field)) - Fields.push_back(std::make_pair(Field, getFieldOffsetInBits(Field))); - - // The fields are almost always sorted, but occasionally not. Sort them by - // field offset. - for (unsigned i = 1, e = Fields.size(); i < e; i++) - for (unsigned j = i; j && Fields[j].second < Fields[j-1].second; j--) - std::swap(Fields[j], Fields[j-1]); - - StructTypeConversionInfo *Info = - new StructTypeConversionInfo(*TheTarget, TYPE_ALIGN(type) / 8, - TYPE_PACKED(type)); - - // Convert over all of the elements of the struct. - // Workaround to get Fortran EQUIVALENCE working. - // TODO: Unify record and union logic and handle this optimally. - bool HasOnlyZeroOffsets = TREE_CODE(type) != RECORD_TYPE && - UnionHasOnlyZeroOffsets(type); - if (HasOnlyZeroOffsets) { - SelectUnionMember(type, *Info); - } else { - // Convert over all of the elements of the struct. - bool retryAsPackedStruct = false; - for (unsigned i = 0, e = Fields.size(); i < e; i++) - if (DecodeStructFields(Fields[i].first, *Info) == false) { - retryAsPackedStruct = true; - break; - } - - if (retryAsPackedStruct) { - delete Info; - Info = new StructTypeConversionInfo(*TheTarget, TYPE_ALIGN(type) / 8, - true); - for (unsigned i = 0, e = Fields.size(); i < e; i++) - if (DecodeStructFields(Fields[i].first, *Info) == false) { - assert(0 && "Unable to decode struct fields."); - } - } - } - - // Insert tail padding if the LLVM struct requires explicit tail padding to - // be the same size as the GCC struct or union. This handles, e.g., "{}" in - // C++, and cases where a union has larger alignment than the largest member - // does. - if (TYPE_SIZE(type) && TREE_CODE(TYPE_SIZE(type)) == INTEGER_CST) { - uint64_t GCCTypeSize = getInt64(TYPE_SIZE_UNIT(type), true); - uint64_t LLVMStructSize = Info->getSizeAsLLVMStruct(); - - if (LLVMStructSize > GCCTypeSize) { - Info->RemoveExtraBytes(); - LLVMStructSize = Info->getSizeAsLLVMStruct(); - } - - if (LLVMStructSize != GCCTypeSize) { - assert(LLVMStructSize < GCCTypeSize && - "LLVM type size doesn't match GCC type size!"); - uint64_t LLVMLastElementEnd = Info->getNewElementByteOffset(1); - - // If only one byte is needed then insert i8. - if (GCCTypeSize-LLVMLastElementEnd == 1) - Info->addElement(Type::getInt8Ty(Context), 1, 1); - else { - if (((GCCTypeSize-LLVMStructSize) % 4) == 0 && - (Info->getAlignmentAsLLVMStruct() % - Info->getTypeAlignment(Type::getInt32Ty(Context))) == 0) { - // Insert array of i32. - unsigned Int32ArraySize = (GCCTypeSize-LLVMStructSize) / 4; - const Type *PadTy = - ArrayType::get(Type::getInt32Ty(Context), Int32ArraySize); - Info->addElement(PadTy, GCCTypeSize - LLVMLastElementEnd, - Int32ArraySize, true /* Padding Element */); - } else { - const Type *PadTy = ArrayType::get(Type::getInt8Ty(Context), - GCCTypeSize-LLVMStructSize); - Info->addElement(PadTy, GCCTypeSize - LLVMLastElementEnd, - GCCTypeSize - LLVMLastElementEnd, - true /* Padding Element */); - } - } - } - } else - Info->RemoveExtraBytes(); - - const Type *ResultTy = Info->getLLVMType(); - StructTypeInfoMap[type] = Info; - - const OpaqueType *OldTy = cast_or_null(GET_TYPE_LLVM(type)); - TypeDB.setType(type, ResultTy); - - // If there was a forward declaration for this type that is now resolved, - // refine anything that used it to the new type. - if (OldTy) - const_cast(OldTy)->refineAbstractTypeTo(ResultTy); - - // We have finished converting this struct. See if the is the outer-most - // struct or union being converted by ConvertType. - ConvertingStruct = OldConvertingStruct; - if (!ConvertingStruct) { - - // If this is the outer-most level of structness, resolve any pointers - // that were deferred. - while (!PointersToReresolve.empty()) { - if (tree PtrTy = PointersToReresolve.back()) { - ConvertType(PtrTy); // Reresolve this pointer type. - assert((PointersToReresolve.empty() || - PointersToReresolve.back() != PtrTy) && - "Something went wrong with pointer resolution!"); - } else { - // Null marker element. - PointersToReresolve.pop_back(); - } - } - } - - return GET_TYPE_LLVM(type); -} Removed: dragonegg/trunk/bits_and_bobs.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/bits_and_bobs.cpp?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/bits_and_bobs.cpp (original) +++ dragonegg/trunk/bits_and_bobs.cpp (removed) @@ -1,2 +0,0 @@ -int ix86_regparm; -union tree_node; Removed: dragonegg/trunk/cache.c URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/cache.c?rev=129351&view=auto ============================================================================== --- dragonegg/trunk/cache.c (original) +++ dragonegg/trunk/cache.c (removed) @@ -1,142 +0,0 @@ -/* Caching values "in" trees -Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 59 Temple Place - Suite 330, Boston, MA -02111-1307, USA. */ - -/*===----------------------------------------------------------------------=== - This code lets you to associate a void* with a tree, as if it were cached - inside the tree: if the tree is garbage collected and reallocated, then the - cached value will have been cleared. - ===----------------------------------------------------------------------===*/ - -/* Plugin headers. */ -#include "dragonegg/cache.h" - -/* GCC headers. */ -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "target.h" -#include "tree.h" -#include "ggc.h" - -struct GTY(()) tree_llvm_map { - struct tree_map_base base; - const void * GTY((skip)) val; -}; - -#define tree_llvm_map_eq tree_map_base_eq -#define tree_llvm_map_hash tree_map_base_hash -#define tree_llvm_map_marked_p tree_map_base_marked_p - -static GTY ((if_marked ("tree_llvm_map_marked_p"), - param_is(struct tree_llvm_map))) - htab_t llvm_cache; - -/* Garbage collector header. */ -#include "dragonegg/gt-cache.h" - -/* llvm_has_cached - Returns whether a value has been associated with the - tree. */ -int llvm_has_cached(union tree_node *tree) { - struct tree_map_base in; - - if (!llvm_cache) - return false; - - in.from = tree; - return htab_find(llvm_cache, &in) != NULL; -} - -/* llvm_get_cached - Returns the value associated with the tree, or NULL. */ -const void *llvm_get_cached(union tree_node *tree) { - struct tree_llvm_map *h; - struct tree_map_base in; - - if (!llvm_cache) - return NULL; - - in.from = tree; - h = (struct tree_llvm_map *) htab_find(llvm_cache, &in); - return h ? h->val : NULL; -} - -/* llvm_set_cached - Associates the given value with the tree (and returns it). - To delete an association, pass a NULL value here. */ -const void *llvm_set_cached(union tree_node *tree, const void *val) { - struct tree_llvm_map **slot; - struct tree_map_base in; - - in.from = tree; - - /* If deleting, remove the slot. */ - if (val == NULL) { - if (llvm_cache) - htab_remove_elt(llvm_cache, &in); - return NULL; - } - - if (!llvm_cache) - llvm_cache = htab_create_ggc(1024, tree_llvm_map_hash, tree_llvm_map_eq, NULL); - - slot = (struct tree_llvm_map **) htab_find_slot(llvm_cache, &in, INSERT); - gcc_assert(slot); - - if (!*slot) { - *slot = GGC_NEW(struct tree_llvm_map); - (*slot)->base.from = tree; - } - - (*slot)->val = val; - - return val; -} - -struct update { - const void *old_val; - const void *new_val; -}; - -/* replace - If the current value for the slot matches old_val, then replace - it with new_val, or delete it if new_val is NULL. */ -static int replace(void **slot, void *data) { - struct tree_llvm_map *entry = *(struct tree_llvm_map **)slot; - struct update *u = (struct update *)data; - - if (entry->val != u->old_val) - return 1; - - if (u->new_val != NULL) - entry->val = u->new_val; - else - htab_clear_slot(llvm_cache, slot); - - return 1; -} - -/* llvm_replace_cached - Replaces all occurrences of old_val with new_val. */ -void llvm_replace_cached(const void *old_val, const void *new_val) { - struct update u; - u.old_val = old_val; - u.new_val = new_val; - - if (!llvm_cache || old_val == NULL) - return; - - htab_traverse(llvm_cache, replace, &u); -} Modified: dragonegg/trunk/extras/do_self_strap URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/extras/do_self_strap?rev=129352&r1=129351&r2=129352&view=diff ============================================================================== --- dragonegg/trunk/extras/do_self_strap (original) +++ dragonegg/trunk/extras/do_self_strap Tue Apr 12 04:15:29 2011 @@ -189,7 +189,7 @@ mkdir -p $DRAGONEGG_BUILD-pre cd $DRAGONEGG_BUILD-pre $MAKE -f $DRAGONEGG_SOURCE/Makefile clean - SRC_DIR=$DRAGONEGG_SOURCE $MAKE -f $DRAGONEGG_SOURCE/Makefile VERBOSE=1 + TOP_DIR=$DRAGONEGG_SOURCE $MAKE -f $DRAGONEGG_SOURCE/Makefile VERBOSE=1 # <== end: Build dragonegg using the just built GCC and DRAGONEGG. @@ -206,7 +206,7 @@ mkdir -p $DRAGONEGG_BUILD cd $DRAGONEGG_BUILD $MAKE -f $DRAGONEGG_SOURCE/Makefile clean - SRC_DIR=$DRAGONEGG_SOURCE $MAKE -f $DRAGONEGG_SOURCE/Makefile VERBOSE=1 + TOP_DIR=$DRAGONEGG_SOURCE $MAKE -f $DRAGONEGG_SOURCE/Makefile VERBOSE=1 # <== end: Build dragonegg again using the just built dragonegg From baldrick at free.fr Tue Apr 12 04:38:36 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 09:38:36 -0000 Subject: [llvm-commits] [dragonegg] r129353 - in /dragonegg/trunk: Makefile darwin/ freebsd/ include/darwin/ include/freebsd/ include/linux/ linux/ src/darwin/ src/freebsd/ src/linux/ Message-ID: <20110412093836.2F2442A6C12D@llvm.org> Author: baldrick Date: Tue Apr 12 04:38:35 2011 New Revision: 129353 URL: http://llvm.org/viewvc/llvm-project?rev=129353&view=rev Log: Move platform headers to an appropriate place under include/. Add directories for putting platform specific source code (though there currently isn't any). Added: dragonegg/trunk/include/darwin/ - copied from r129217, dragonegg/trunk/darwin/ dragonegg/trunk/include/freebsd/ - copied from r129217, dragonegg/trunk/freebsd/ dragonegg/trunk/include/linux/ - copied from r129217, dragonegg/trunk/linux/ dragonegg/trunk/src/darwin/ dragonegg/trunk/src/freebsd/ dragonegg/trunk/src/linux/ Removed: dragonegg/trunk/darwin/ dragonegg/trunk/freebsd/ dragonegg/trunk/linux/ Modified: dragonegg/trunk/Makefile Modified: dragonegg/trunk/Makefile URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Makefile?rev=129353&r1=129352&r2=129353&view=diff ============================================================================== --- dragonegg/trunk/Makefile (original) +++ dragonegg/trunk/Makefile Tue Apr 12 04:38:35 2011 @@ -62,7 +62,7 @@ # NOTE: The following flags can only be used after TARGET_UTIL has been built. TARGET_HEADERS+=-DTARGET_NAME=\"$(shell $(TARGET_UTIL) -t)\" \ -I$(TOP_DIR)/$(shell $(TARGET_UTIL) -p) \ - -I$(TOP_DIR)/$(shell $(TARGET_UTIL) -o) + -I$(INCLUDE_DIR)/$(shell $(TARGET_UTIL) -o) default: $(PLUGIN) From baldrick at free.fr Tue Apr 12 04:43:00 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 09:43:00 -0000 Subject: [llvm-commits] [dragonegg] r129354 - in /dragonegg/trunk: Makefile include/x86/ include/x86/dragonegg/ x86/dragonegg/ Message-ID: <20110412094300.42EF32A6C12D@llvm.org> Author: baldrick Date: Tue Apr 12 04:43:00 2011 New Revision: 129354 URL: http://llvm.org/viewvc/llvm-project?rev=129354&view=rev Log: Move target headers under the include directory. Added: dragonegg/trunk/include/x86/ dragonegg/trunk/include/x86/dragonegg/ - copied from r129217, dragonegg/trunk/x86/dragonegg/ Removed: dragonegg/trunk/x86/dragonegg/ Modified: dragonegg/trunk/Makefile Modified: dragonegg/trunk/Makefile URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Makefile?rev=129354&r1=129353&r2=129354&view=diff ============================================================================== --- dragonegg/trunk/Makefile (original) +++ dragonegg/trunk/Makefile Tue Apr 12 04:43:00 2011 @@ -61,7 +61,7 @@ # NOTE: The following flags can only be used after TARGET_UTIL has been built. TARGET_HEADERS+=-DTARGET_NAME=\"$(shell $(TARGET_UTIL) -t)\" \ - -I$(TOP_DIR)/$(shell $(TARGET_UTIL) -p) \ + -I$(INCLUDE_DIR)/$(shell $(TARGET_UTIL) -p) \ -I$(INCLUDE_DIR)/$(shell $(TARGET_UTIL) -o) From baldrick at free.fr Tue Apr 12 04:48:41 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 09:48:41 -0000 Subject: [llvm-commits] [dragonegg] r129355 - in /dragonegg/trunk: Makefile src/x86/ x86/ Message-ID: <20110412094841.DA6862A6C12D@llvm.org> Author: baldrick Date: Tue Apr 12 04:48:41 2011 New Revision: 129355 URL: http://llvm.org/viewvc/llvm-project?rev=129355&view=rev Log: Move target source files under the src directory. Added: dragonegg/trunk/src/x86/ - copied from r129354, dragonegg/trunk/x86/ Removed: dragonegg/trunk/x86/ Modified: dragonegg/trunk/Makefile Modified: dragonegg/trunk/Makefile URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Makefile?rev=129355&r1=129354&r2=129355&view=diff ============================================================================== --- dragonegg/trunk/Makefile (original) +++ dragonegg/trunk/Makefile Tue Apr 12 04:48:41 2011 @@ -44,7 +44,7 @@ Trees.o Types.o bits_and_bobs.o TARGET_OBJECT=Target.o -TARGET_SOURCE=$(TOP_DIR)/$(shell $(TARGET_UTIL) -p)/Target.cpp +TARGET_SOURCE=$(SRC_DIR)/$(shell $(TARGET_UTIL) -p)/Target.cpp TARGET_UTIL_OBJECTS=TargetInfo.o TARGET_UTIL=./TargetInfo From baldrick at free.fr Tue Apr 12 04:54:20 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 09:54:20 -0000 Subject: [llvm-commits] [dragonegg] r129356 - in /dragonegg/trunk: include/unknown/ include/unknown/dragonegg/ unknown/dragonegg/ Message-ID: <20110412095420.CBB4C2A6C12D@llvm.org> Author: baldrick Date: Tue Apr 12 04:54:20 2011 New Revision: 129356 URL: http://llvm.org/viewvc/llvm-project?rev=129356&view=rev Log: Move error checking header under include (this catches the case when we failed to identify the platform). Added: dragonegg/trunk/include/unknown/ dragonegg/trunk/include/unknown/dragonegg/ - copied from r129354, dragonegg/trunk/unknown/dragonegg/ Removed: dragonegg/trunk/unknown/dragonegg/ From baldrick at free.fr Tue Apr 12 04:56:19 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 09:56:19 -0000 Subject: [llvm-commits] [dragonegg] r129357 - in /dragonegg/trunk: src/unknown/ unknown/ Message-ID: <20110412095619.5B6E62A6C12D@llvm.org> Author: baldrick Date: Tue Apr 12 04:56:19 2011 New Revision: 129357 URL: http://llvm.org/viewvc/llvm-project?rev=129357&view=rev Log: Move code to catch attempts to build for an unknown target under src. Added: dragonegg/trunk/src/unknown/ - copied from r129356, dragonegg/trunk/unknown/ Removed: dragonegg/trunk/unknown/ From baldrick at free.fr Tue Apr 12 06:54:40 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 12 Apr 2011 11:54:40 -0000 Subject: [llvm-commits] [dragonegg] r129359 - in /dragonegg/trunk: include/dragonegg/Internals.h src/Constants.cpp src/Convert.cpp Message-ID: <20110412115440.8E9812A6C12D@llvm.org> Author: baldrick Date: Tue Apr 12 06:54:40 2011 New Revision: 129359 URL: http://llvm.org/viewvc/llvm-project?rev=129359&view=rev Log: Add support for MISALIGNED_INDIRECT_REF in the hope of fixing PR9663. Modified: dragonegg/trunk/include/dragonegg/Internals.h dragonegg/trunk/src/Constants.cpp dragonegg/trunk/src/Convert.cpp Modified: dragonegg/trunk/include/dragonegg/Internals.h URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Internals.h?rev=129359&r1=129358&r2=129359&view=diff ============================================================================== --- dragonegg/trunk/include/dragonegg/Internals.h (original) +++ dragonegg/trunk/include/dragonegg/Internals.h Tue Apr 12 06:54:40 2011 @@ -789,6 +789,7 @@ LValue EmitLV_COMPONENT_REF(tree_node *exp); LValue EmitLV_DECL(tree_node *exp); LValue EmitLV_INDIRECT_REF(tree_node *exp); + LValue EmitLV_MISALIGNED_INDIRECT_REF(tree_node *exp); LValue EmitLV_VIEW_CONVERT_EXPR(tree_node *exp); LValue EmitLV_WITH_SIZE_EXPR(tree_node *exp); LValue EmitLV_XXXXPART_EXPR(tree_node *exp, unsigned Idx); Modified: dragonegg/trunk/src/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Constants.cpp?rev=129359&r1=129358&r2=129359&view=diff ============================================================================== --- dragonegg/trunk/src/Constants.cpp (original) +++ dragonegg/trunk/src/Constants.cpp Tue Apr 12 06:54:40 2011 @@ -1335,6 +1335,7 @@ Addr = AddressOfDecl(exp); break; case INDIRECT_REF: + case MISALIGNED_INDIRECT_REF: Addr = AddressOfINDIRECT_REF(exp); break; case LABEL_DECL: Modified: dragonegg/trunk/src/Convert.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=129359&r1=129358&r2=129359&view=diff ============================================================================== --- dragonegg/trunk/src/Convert.cpp (original) +++ dragonegg/trunk/src/Convert.cpp Tue Apr 12 06:54:40 2011 @@ -1298,6 +1298,9 @@ case INDIRECT_REF: LV = EmitLV_INDIRECT_REF(exp); break; + case MISALIGNED_INDIRECT_REF: + LV = EmitLV_MISALIGNED_INDIRECT_REF(exp); + break; } // Check that the type of the lvalue is indeed that of a pointer to the tree @@ -5736,6 +5739,19 @@ return LV; } +LValue TreeToLLVM::EmitLV_MISALIGNED_INDIRECT_REF(tree exp) { + // The lvalue is just the address. The alignment is given by operand 1. + unsigned Alignment = tree_low_cst(TREE_OPERAND(exp, 1), true); + if (!Alignment) Alignment = 8; + assert(!(Alignment & 7) && "Alignment not in octets!"); + LValue LV = LValue(EmitRegister(TREE_OPERAND(exp, 0)), Alignment / 8); + // May need a useless type conversion (useless_type_conversion_p), for example + // when INDIRECT_REF is applied to a void*, resulting in a non-void type. + LV.Ptr = UselesslyTypeConvert(LV.Ptr, + ConvertType(TREE_TYPE(exp))->getPointerTo()); + return LV; +} + LValue TreeToLLVM::EmitLV_VIEW_CONVERT_EXPR(tree exp) { // The address is the address of the operand. LValue LV = EmitLV(TREE_OPERAND(exp, 0)); @@ -7873,6 +7889,7 @@ case COMPONENT_REF: case IMAGPART_EXPR: case INDIRECT_REF: + case MISALIGNED_INDIRECT_REF: case REALPART_EXPR: case TARGET_MEM_REF: case VIEW_CONVERT_EXPR: From fvbommel at gmail.com Tue Apr 12 07:05:51 2011 From: fvbommel at gmail.com (Frits van Bommel) Date: Tue, 12 Apr 2011 14:05:51 +0200 Subject: [llvm-commits] [PATCH] - endless loop in instcombine and a small constant folding optimization on vectors In-Reply-To: <4DA3EFF5.3050507@mxc.ca> References: <6594DDFF12B03D4E89690887C2486994027889605C@hasmsx504.ger.corp.intel.com> <4DA3EFF5.3050507@mxc.ca> Message-ID: On Tue, Apr 12, 2011 at 8:23 AM, Nick Lewycky wrote: > Rotem, Nadav wrote: >> Please review the attached patch: >> >> 1. Fix an endless loop in instcombine. VisitAnd changes the instruction, and VisitXor fixes it in an endless loop. > > Hrmm. Neither visitAnd nor visitXor should be swapping operands for > funsies, there should be one canonical form of the expression and > instcombine should produce it. Yet apparently visitAnd does swap operands even if it isn't sure yet whether that helps. A better fix would probably be to not swap them in the first place... > I tried to analyze this, but I found that in your testcase, my > breakpoint in visitXor never fired, there was only a look on visitAnd... > >> 2. A small constant folding patch vector select with a splat condition. > > + ?// Handles cases where the condition is splat vector. > + ?// select , X, Y -> Y > + ?// select , X, Y -> X > + ?if (isa(CondVal)) return FalseVal; > + ?if (ConstantVector *CP = dyn_cast(CondVal)) { > + ? ?if (CP->isAllOnesValue()) return TrueVal; > > if (CP->isNullValue()) return FalseVal; ?? ConstantVectors can't be null values, that's the reason for the ConstantAggregateZero check. This could probably be written more cleanly by using m_Zero and m_AllOnes/m_One from llvm/Support/PatternMatch.h though (and combined with the non-vector versions at the top of the function). From gvenn.cfe.dev at gmail.com Tue Apr 12 07:30:10 2011 From: gvenn.cfe.dev at gmail.com (Garrison Venn) Date: Tue, 12 Apr 2011 12:30:10 -0000 Subject: [llvm-commits] [llvm] r129360 - /llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Message-ID: <20110412123010.DF9BF2A6C12D@llvm.org> Author: gvenn Date: Tue Apr 12 07:30:10 2011 New Revision: 129360 URL: http://llvm.org/viewvc/llvm-project?rev=129360&view=rev Log: Added new FIXME note Modified: llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Modified: llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp?rev=129360&r1=129359&r2=129360&view=diff ============================================================================== --- llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp (original) +++ llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Tue Apr 12 07:30:10 2011 @@ -62,7 +62,16 @@ #include "llvm/Support/IRBuilder.h" #include "llvm/Support/Dwarf.h" +// 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 +// defined for the system in question, and fix the issue by finding out +// which LLVM header file, if any, would include these symbols. #include + #include #include From 6yearold at gmail.com Tue Apr 12 08:45:13 2011 From: 6yearold at gmail.com (arrowdodger) Date: Tue, 12 Apr 2011 17:45:13 +0400 Subject: [llvm-commits] [PATCH][CMake] Document CMake build feature to develop passes out-source. Message-ID: This patch adds explanation and code snippets how to develop LLVM passes out of LLVM source tree. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110412/3356e623/attachment.html -------------- next part -------------- A non-text attachment was scrubbed... Name: llvm.doc.patch Type: text/x-patch Size: 2854 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110412/3356e623/attachment.bin From ofv at wanadoo.es Tue Apr 12 10:15:05 2011 From: ofv at wanadoo.es (=?utf-8?Q?=C3=93scar_Fuentes?=) Date: Tue, 12 Apr 2011 17:15:05 +0200 Subject: [llvm-commits] [PATCH][CMake] Document CMake build feature to develop passes out-source. References: Message-ID: <874o63fqme.fsf@wanadoo.es> arrowdodger <6yearold at gmail.com> writes: > This patch adds explanation and code snippets how to develop LLVM passes out > of LLVM source tree. [snip] > +

It is possible to develop LLVM passes against installed LLVM. > + An example of project layout provided below:

> + > +
> +
> +      <project dir>/
> +          |
> +          CMakeLists.txt
> +          <pass name>/
> +              |
> +              CMakeLists.txt
> +              Pass.cpp
> +              ...

Here you mention Pass.cpp ...

> +    
> +
> + > +

Contents of <project dir>/CMakeLists.txt:

> + > +
> +
> +    find_package(LLVM)
> +
> +    # Define add_llvm_* macro's.
> +    include(AddLLVM)
> +
> +    add_definitions(${LLVM_DEFINITIONS})
> +    include_directories(${LLVM_INCLUDE_DIRS})
> +    link_directories(${LLVM_LIBRARY_DIRS})
> +
> +    add_subdirectory(<pass name>)
> +    
> +
> + > +

Contents of <project dir>/<pass name>/CMakeLists.txt:

> + > +
> +
> +    add_llvm_loadable_module(LLVMHello
> +      Hello.cpp

... and here Hello.cpp.

Also, LLVMHello is a bad name because it is already created by the LLVM
build. As the current practice in LLVM is to name directories after the
library it contains, I suggest something like LLVMYourPass as the name
for both the directory and the pass.

> +      )
> +    
> +
> + > +

This layout allows easy integration of developed pass > + into mainstream. It consists in two steps:
> + 1. Copying <pass name> folder into <LLVM root>/lib/Transform directory.
> + 2. Adding "add_subdirectory(<pass name>)" line into <LLVM root>/lib/Transform/CMakeLists.txt

Maybe you should make clear that the above paragraph is meaningful only after you finished your work and want to contribute your pass to LLVM. From rafael.espindola at gmail.com Tue Apr 12 10:31:05 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Tue, 12 Apr 2011 15:31:05 -0000 Subject: [llvm-commits] [llvm] r129361 - in /llvm/trunk: include/llvm/MC/MCDwarf.h include/llvm/MC/MCStreamer.h lib/MC/MCDwarf.cpp lib/MC/MCParser/AsmParser.cpp lib/MC/MCStreamer.cpp test/MC/ELF/cfi-same-value.s Message-ID: <20110412153105.A67012A6C12D@llvm.org> Author: rafael Date: Tue Apr 12 10:31:05 2011 New Revision: 129361 URL: http://llvm.org/viewvc/llvm-project?rev=129361&view=rev Log: Implement .cfi_same_value. Added: llvm/trunk/test/MC/ELF/cfi-same-value.s Modified: llvm/trunk/include/llvm/MC/MCDwarf.h llvm/trunk/include/llvm/MC/MCStreamer.h llvm/trunk/lib/MC/MCDwarf.cpp llvm/trunk/lib/MC/MCParser/AsmParser.cpp llvm/trunk/lib/MC/MCStreamer.cpp Modified: llvm/trunk/include/llvm/MC/MCDwarf.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCDwarf.h?rev=129361&r1=129360&r2=129361&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCDwarf.h (original) +++ llvm/trunk/include/llvm/MC/MCDwarf.h Tue Apr 12 10:31:05 2011 @@ -230,7 +230,7 @@ class MCCFIInstruction { public: - enum OpType { Remember, Restore, Move }; + enum OpType { SameValue, Remember, Restore, Move }; private: OpType Operation; MCSymbol *Label; @@ -242,6 +242,10 @@ : Operation(Op), Label(L) { assert(Op == Remember || Op == Restore); } + MCCFIInstruction(OpType Op, MCSymbol *L, unsigned Register) + : Operation(Op), Label(L), Destination(Register) { + assert(Op == SameValue); + } MCCFIInstruction(MCSymbol *L, const MachineLocation &D, const MachineLocation &S) : Operation(Move), Label(L), Destination(D), Source(S) { Modified: llvm/trunk/include/llvm/MC/MCStreamer.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=129361&r1=129360&r2=129361&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCStreamer.h (original) +++ llvm/trunk/include/llvm/MC/MCStreamer.h Tue Apr 12 10:31:05 2011 @@ -446,6 +446,7 @@ virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); virtual bool EmitCFIRememberState(); virtual bool EmitCFIRestoreState(); + void EmitCFISameValue(int64_t Register); /// EmitInstruction - Emit the given @p Instruction into the current /// section. Modified: llvm/trunk/lib/MC/MCDwarf.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDwarf.cpp?rev=129361&r1=129360&r2=129361&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCDwarf.cpp (original) +++ llvm/trunk/lib/MC/MCDwarf.cpp Tue Apr 12 10:31:05 2011 @@ -493,6 +493,12 @@ case MCCFIInstruction::Restore: Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); return; + case MCCFIInstruction::SameValue: { + unsigned Reg = Instr.getDestination().getReg(); + Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); + Streamer.EmitULEB128IntValue(Reg, 1); + return; + } } llvm_unreachable("Unhandled case in switch"); } Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=129361&r1=129360&r2=129361&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Tue Apr 12 10:31:05 2011 @@ -283,6 +283,8 @@ &GenericAsmParser::ParseDirectiveCFIRememberState>(".cfi_remember_state"); AddDirectiveHandler< &GenericAsmParser::ParseDirectiveCFIRestoreState>(".cfi_restore_state"); + AddDirectiveHandler< + &GenericAsmParser::ParseDirectiveCFISameValue>(".cfi_same_value"); // Macro directives. AddDirectiveHandler<&GenericAsmParser::ParseDirectiveMacrosOnOff>( @@ -314,6 +316,7 @@ bool ParseDirectiveCFIPersonalityOrLsda(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIRememberState(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveCFIRestoreState(StringRef, SMLoc DirectiveLoc); + bool ParseDirectiveCFISameValue(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveMacrosOnOff(StringRef, SMLoc DirectiveLoc); bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc); @@ -2472,6 +2475,20 @@ return getStreamer().EmitCFIRestoreState(); } +/// ParseDirectiveCFISameValue +/// ::= .cfi_same_value register +bool GenericAsmParser::ParseDirectiveCFISameValue(StringRef IDVal, + SMLoc DirectiveLoc) { + int64_t Register = 0; + + if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) + return true; + + getStreamer().EmitCFISameValue(Register); + + return false; +} + /// ParseDirectiveMacrosOnOff /// ::= .macros_on /// ::= .macros_off Modified: llvm/trunk/lib/MC/MCStreamer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=129361&r1=129360&r2=129361&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCStreamer.cpp (original) +++ llvm/trunk/lib/MC/MCStreamer.cpp Tue Apr 12 10:31:05 2011 @@ -259,6 +259,15 @@ return false; } +void MCStreamer::EmitCFISameValue(int64_t Register) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MCCFIInstruction Instruction(MCCFIInstruction::SameValue, Label, Register); + CurFrame->Instructions.push_back(Instruction); +} + void MCStreamer::EmitFnStart() { errs() << "Not implemented yet\n"; abort(); Added: llvm/trunk/test/MC/ELF/cfi-same-value.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/cfi-same-value.s?rev=129361&view=auto ============================================================================== --- llvm/trunk/test/MC/ELF/cfi-same-value.s (added) +++ llvm/trunk/test/MC/ELF/cfi-same-value.s Tue Apr 12 10:31:05 2011 @@ -0,0 +1,42 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +f: + .cfi_startproc + nop + .cfi_same_value 6 + nop + .cfi_endproc + +// CHECK: # Section 0x00000004 +// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000001) +// CHECK-NEXT: ('sh_flags', 0x00000002) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000048) +// CHECK-NEXT: ('sh_size', 0x00000030) +// CHECK-NEXT: ('sh_link', 0x00000000) +// CHECK-NEXT: ('sh_info', 0x00000000) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000000) +// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 02000000 00410806 00000000') +// CHECK-NEXT: ), +// CHECK-NEXT: # Section 0x00000005 +// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000004) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000390) +// CHECK-NEXT: ('sh_size', 0x00000018) +// CHECK-NEXT: ('sh_link', 0x00000007) +// CHECK-NEXT: ('sh_info', 0x00000004) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000018) +// CHECK-NEXT: ('_relocations', [ +// CHECK-NEXT: # Relocation 0x00000000 +// CHECK-NEXT: (('r_offset', 0x00000020) +// CHECK-NEXT: ('r_sym', 0x00000002) +// CHECK-NEXT: ('r_type', 0x00000002) +// CHECK-NEXT: ('r_addend', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) +// CHECK-NEXT: ), From grosbach at apple.com Tue Apr 12 10:55:34 2011 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 12 Apr 2011 08:55:34 -0700 Subject: [llvm-commits] [llvm] r129340 - in /llvm/trunk: include/llvm/InitializePasses.h include/llvm/LinkAllPasses.h include/llvm/Transforms/Instrumentation.h lib/Transforms/Instrumentation/Instrumentation.cpp lib/Transforms/Instrumentation/LineProfiling.cpp runtime/libprofile/LineProfiling.c runtime/libprofile/libprofile.exports In-Reply-To: <20110412010609.B39542A6C12D@llvm.org> References: <20110412010609.B39542A6C12D@llvm.org> Message-ID: <74454408-E240-4AAF-BF73-596C00DA88CE@apple.com> Hi Nick, clang is issuing a warning for this. Mind having a look? llvm[2]: Compiling LineProfiling.c for Debug+Asserts build (PIC) /Volumes/Home/grosbaj/sources/llvm/runtime/libprofile/LineProfiling.c:32:25: warning: conversion specifies type 'unsigned long' but the argument has type 'int64_t' (aka 'long long') [-Wformat] printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); ~~^ ~~~~~~~~ %lld 1 warning generated. (highlighting points to the "%lu" and "*counter" inputs) -Jim On Apr 11, 2011, at 6:06 PM, Nick Lewycky wrote: > Author: nicholas > Date: Mon Apr 11 20:06:09 2011 > New Revision: 129340 > > URL: http://llvm.org/viewvc/llvm-project?rev=129340&view=rev > Log: > Add support for line profiling. Very work-in-progress. > > Use debug info in the IR to find the directory/file:line:col. Each time that location changes, bump a counter. > > Unlike the existing profiling system, we don't try to look at argv[], and thusly don't require main() to be present in the IR. This matches GCC's technique where you specify the profiling flag when producing each .o file. > > The runtime library is minimal, currently just calling printf at program shutdown time. The API is designed to make it possible to emit GCOV data later on. > > Added: > llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp > llvm/trunk/runtime/libprofile/LineProfiling.c > Modified: > llvm/trunk/include/llvm/InitializePasses.h > llvm/trunk/include/llvm/LinkAllPasses.h > llvm/trunk/include/llvm/Transforms/Instrumentation.h > llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp > llvm/trunk/runtime/libprofile/libprofile.exports > > Modified: llvm/trunk/include/llvm/InitializePasses.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=129340&r1=129339&r2=129340&view=diff > ============================================================================== > --- llvm/trunk/include/llvm/InitializePasses.h (original) > +++ llvm/trunk/include/llvm/InitializePasses.h Mon Apr 11 20:06:09 2011 > @@ -94,6 +94,7 @@ > void initializeEdgeBundlesPass(PassRegistry&); > void initializeEdgeProfilerPass(PassRegistry&); > void initializePathProfilerPass(PassRegistry&); > +void initializeLineProfilerPass(PassRegistry&); > void initializeEarlyCSEPass(PassRegistry&); > void initializeExpandISelPseudosPass(PassRegistry&); > void initializeFindUsedTypesPass(PassRegistry&); > > Modified: llvm/trunk/include/llvm/LinkAllPasses.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=129340&r1=129339&r2=129340&view=diff > ============================================================================== > --- llvm/trunk/include/llvm/LinkAllPasses.h (original) > +++ llvm/trunk/include/llvm/LinkAllPasses.h Mon Apr 11 20:06:09 2011 > @@ -70,6 +70,7 @@ > (void) llvm::createEdgeProfilerPass(); > (void) llvm::createOptimalEdgeProfilerPass(); > (void) llvm::createPathProfilerPass(); > + (void) llvm::createLineProfilerPass(); > (void) llvm::createFunctionInliningPass(); > (void) llvm::createAlwaysInlinerPass(); > (void) llvm::createGlobalDCEPass(); > > Modified: llvm/trunk/include/llvm/Transforms/Instrumentation.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=129340&r1=129339&r2=129340&view=diff > ============================================================================== > --- llvm/trunk/include/llvm/Transforms/Instrumentation.h (original) > +++ llvm/trunk/include/llvm/Transforms/Instrumentation.h Mon Apr 11 20:06:09 2011 > @@ -17,7 +17,6 @@ > namespace llvm { > > class ModulePass; > -class FunctionPass; > > // Insert edge profiling instrumentation > ModulePass *createEdgeProfilerPass(); > @@ -28,6 +27,9 @@ > // Insert path profiling instrumentation > ModulePass *createPathProfilerPass(); > > +// Insert line profiling instrumentation > +ModulePass *createLineProfilerPass(); > + > } // End llvm namespace > > #endif > > Modified: llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp?rev=129340&r1=129339&r2=129340&view=diff > ============================================================================== > --- llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp (original) > +++ llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp Mon Apr 11 20:06:09 2011 > @@ -23,6 +23,7 @@ > initializeEdgeProfilerPass(Registry); > initializeOptimalEdgeProfilerPass(Registry); > initializePathProfilerPass(Registry); > + initializeLineProfilerPass(Registry); > } > > /// LLVMInitializeInstrumentation - C binding for > > Added: llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp?rev=129340&view=auto > ============================================================================== > --- llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp (added) > +++ llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp Mon Apr 11 20:06:09 2011 > @@ -0,0 +1,217 @@ > +//===- LineProfiling.cpp - Insert counters for line profiling -------------===// > +// > +// The LLVM Compiler Infrastructure > +// > +// This file is distributed under the University of Illinois Open Source > +// License. See LICENSE.TXT for details. > +// > +//===----------------------------------------------------------------------===// > +// > +// This pass creates counters for the number of times that the original source > +// lines of code were executed. > +// > +// The lines are found from existing debug info in the LLVM IR. Iterating > +// through LLVM instructions, every time the debug location changes we insert a > +// new counter and instructions to increment the counter there. A global > +// destructor runs to dump the counters out to a file. > +// > +//===----------------------------------------------------------------------===// > + > +#define DEBUG_TYPE "insert-line-profiling" > + > +#include "ProfilingUtils.h" > +#include "llvm/Transforms/Instrumentation.h" > +#include "llvm/Analysis/DebugInfo.h" > +#include "llvm/Module.h" > +#include "llvm/Pass.h" > +#include "llvm/Instructions.h" > +#include "llvm/Support/raw_ostream.h" > +#include "llvm/Support/Debug.h" > +#include "llvm/Support/DebugLoc.h" > +#include "llvm/Support/InstIterator.h" > +#include "llvm/Support/IRBuilder.h" > +#include "llvm/ADT/DenseMap.h" > +#include "llvm/ADT/Statistic.h" > +#include "llvm/ADT/StringExtras.h" > +#include > +#include > +using namespace llvm; > + > +STATISTIC(NumUpdatesInserted, "The # of counter increments inserted."); > + > +namespace { > + class LineProfiler : public ModulePass { > + bool runOnModule(Module &M); > + public: > + static char ID; > + LineProfiler() : ModulePass(ID) { > + initializeLineProfilerPass(*PassRegistry::getPassRegistry()); > + } > + virtual const char *getPassName() const { > + return "Line Profiler"; > + } > + > + private: > + // Get pointers to the functions in the runtime library. > + Constant *getStartFileFunc(); > + Constant *getCounterFunc(); > + Constant *getEndFileFunc(); > + > + // Insert an increment of the counter before instruction I. > + void InsertCounterUpdateBefore(Instruction *I); > + > + // Add the function to write out all our counters to the global destructor > + // list. > + void InsertCounterWriteout(); > + > + // Mapping from the source location to the counter tracking that location. > + DenseMap counters; > + > + Module *Mod; > + LLVMContext *Ctx; > + }; > +} > + > +char LineProfiler::ID = 0; > +INITIALIZE_PASS(LineProfiler, "insert-line-profiling", > + "Insert instrumentation for line profiling", false, false) > + > +ModulePass *llvm::createLineProfilerPass() { return new LineProfiler(); } > + > +bool LineProfiler::runOnModule(Module &M) { > + Mod = &M; > + Ctx = &M.getContext(); > + > + DebugLoc last_line; // initializes to unknown > + bool Changed = false; > + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { > + for (inst_iterator II = inst_begin(F), IE = inst_end(F); II != IE; ++II) { > + const DebugLoc &loc = II->getDebugLoc(); > + if (loc.isUnknown()) continue; > + if (loc == last_line) continue; > + last_line = loc; > + > + InsertCounterUpdateBefore(&*II); > + ++NumUpdatesInserted; > + Changed = true; > + } > + } > + > + if (Changed) { > + InsertCounterWriteout(); > + } > + > + return Changed; > +} > + > +void LineProfiler::InsertCounterUpdateBefore(Instruction *I) { > + const DebugLoc &loc = I->getDebugLoc(); > + GlobalVariable *&counter = counters[loc]; > + const Type *Int64Ty = Type::getInt64Ty(*Ctx); > + if (!counter) { > + counter = new GlobalVariable(*Mod, Int64Ty, false, > + GlobalValue::InternalLinkage, > + Constant::getNullValue(Int64Ty), > + "__llvm_prof_linecov_ctr", 0, false, 0); > + counter->setVisibility(GlobalVariable::HiddenVisibility); > + counter->setUnnamedAddr(true); > + } > + > + if (isa(I)) { > + // We may not error out or crash in this case, because a module could put > + // changing line numbers on phi nodes and still pass the verifier. > + dbgs() << "Refusing to insert code before phi: " << *I << "\n"; > + I = I->getParent()->getFirstNonPHI(); > + } > + > + IRBuilder<> builder(I); > + Value *ctr = builder.CreateLoad(counter); > + ctr = builder.CreateAdd(ctr, ConstantInt::get(Int64Ty, 1)); > + builder.CreateStore(ctr, counter); > +} > + > +static DISubprogram FindSubprogram(DIScope scope) { > + while (!scope.isSubprogram()) { > + assert(scope.isLexicalBlock() && > + "Debug location not lexical block or subprogram"); > + scope = DILexicalBlock(scope).getContext(); > + } > + return DISubprogram(scope); > +} > + > +Constant *LineProfiler::getStartFileFunc() { > + const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) }; > + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), > + Args, false); > + return Mod->getOrInsertFunction("llvm_prof_linectr_start_file", FTy); > +} > + > +Constant *LineProfiler::getCounterFunc() { > + const Type *Args[] = { > + Type::getInt8PtrTy(*Ctx), // const char *dir > + Type::getInt8PtrTy(*Ctx), // const char *file > + Type::getInt32Ty(*Ctx), // uint32_t line > + Type::getInt32Ty(*Ctx), // uint32_t column > + Type::getInt64PtrTy(*Ctx), // int64_t *counter > + }; > + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), > + Args, false); > + return Mod->getOrInsertFunction("llvm_prof_linectr_emit_counter", FTy); > +} > + > +Constant *LineProfiler::getEndFileFunc() { > + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); > + return Mod->getOrInsertFunction("llvm_prof_linectr_end_file", FTy); > +} > + > +void LineProfiler::InsertCounterWriteout() { > + std::set compile_units; > + for (DenseMap::iterator I = counters.begin(), > + E = counters.end(); I != E; ++I) { > + const DebugLoc &loc = I->first; > + DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx)))); > + compile_units.insert(subprogram.getCompileUnit().getFilename().str()); > + } > + > + const FunctionType *WriteoutFTy = > + FunctionType::get(Type::getVoidTy(*Ctx), false); > + Function *WriteoutF = Function::Create(WriteoutFTy, > + GlobalValue::InternalLinkage, > + "__llvm_prof_linecov_dtor", > + Mod); > + WriteoutF->setUnnamedAddr(true); > + BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF); > + IRBuilder<> builder(BB); > + > + Constant *StartFile = getStartFileFunc(); > + Constant *EmitCounter = getCounterFunc(); > + Constant *EndFile = getEndFileFunc(); > + > + for (std::set::const_iterator CUI = compile_units.begin(), > + CUE = compile_units.end(); CUI != CUE; ++CUI) { > + builder.CreateCall(StartFile, > + builder.CreateGlobalStringPtr(*CUI)); > + for (DenseMap::iterator I = counters.begin(), > + E = counters.end(); I != E; ++I) { > + const DebugLoc &loc = I->first; > + DISubprogram subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx)))); > + DICompileUnit compileunit(subprogram.getCompileUnit()); > + > + if (compileunit.getFilename() != *CUI) > + continue; > + > + Value *Args[] = { > + builder.CreateGlobalStringPtr(subprogram.getDirectory()), > + builder.CreateGlobalStringPtr(subprogram.getFilename()), > + ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getLine()), > + ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getCol()), > + I->second > + }; > + builder.CreateCall(EmitCounter, Args); > + } > + builder.CreateCall(EndFile); > + } > + builder.CreateRetVoid(); > + > + InsertProfilingShutdownCall(WriteoutF, Mod); > +} > > Added: llvm/trunk/runtime/libprofile/LineProfiling.c > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129340&view=auto > ============================================================================== > --- llvm/trunk/runtime/libprofile/LineProfiling.c (added) > +++ llvm/trunk/runtime/libprofile/LineProfiling.c Mon Apr 11 20:06:09 2011 > @@ -0,0 +1,37 @@ > +/*===- LineProfiling.c - Support library for line profiling ---------------===*\ > +|* > +|* The LLVM Compiler Infrastructure > +|* > +|* This file is distributed under the University of Illinois Open Source > +|* License. See LICENSE.TXT for details. > +|* > +|*===----------------------------------------------------------------------===*| > +|* > +|* This file implements the call back routines for the line profiling > +|* instrumentation pass. Link against this library when running code through > +|* the -insert-line-profiling LLVM pass. > +|* > +\*===----------------------------------------------------------------------===*/ > + > +#include > +#include > +#include > + > +/* A file in this case is a translation unit. Each .o file built with line > + * profiling enabled will emit to a different file. Only one file may be > + * started at a time. > + */ > +void llvm_prof_linectr_start_file(const char *orig_filename) { > + printf("[%s]\n", orig_filename); > +} > + > +/* Emit data about a counter to the data file. */ > +void llvm_prof_linectr_emit_counter(const char *dir, const char *file, > + uint32_t line, uint32_t column, > + int64_t *counter) { > + printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); > +} > + > +void llvm_prof_linectr_end_file() { > + printf("-----\n"); > +} > > Modified: llvm/trunk/runtime/libprofile/libprofile.exports > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/libprofile.exports?rev=129340&r1=129339&r2=129340&view=diff > ============================================================================== > --- llvm/trunk/runtime/libprofile/libprofile.exports (original) > +++ llvm/trunk/runtime/libprofile/libprofile.exports Mon Apr 11 20:06:09 2011 > @@ -5,3 +5,6 @@ > llvm_trace_basic_block > llvm_increment_path_count > llvm_decrement_path_count > +llvm_prof_linectr_start_file > +llvm_prof_linectr_emit_counter > +llvm_prof_linectr_end_file > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From rafael.espindola at gmail.com Tue Apr 12 11:12:03 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Tue, 12 Apr 2011 16:12:03 -0000 Subject: [llvm-commits] [llvm] r129362 - in /llvm/trunk: include/llvm/MC/MCDwarf.h include/llvm/MC/MCStreamer.h lib/MC/MCDwarf.cpp lib/MC/MCParser/AsmParser.cpp lib/MC/MCStreamer.cpp test/MC/ELF/cfi-rel-offset2.s Message-ID: <20110412161203.EAA322A6C12D@llvm.org> Author: rafael Date: Tue Apr 12 11:12:03 2011 New Revision: 129362 URL: http://llvm.org/viewvc/llvm-project?rev=129362&view=rev Log: Fix the case of a .cfi_rel_offset before any .cfi_def_cfa_offset. Added: llvm/trunk/test/MC/ELF/cfi-rel-offset2.s Modified: llvm/trunk/include/llvm/MC/MCDwarf.h llvm/trunk/include/llvm/MC/MCStreamer.h llvm/trunk/lib/MC/MCDwarf.cpp llvm/trunk/lib/MC/MCParser/AsmParser.cpp llvm/trunk/lib/MC/MCStreamer.cpp Modified: llvm/trunk/include/llvm/MC/MCDwarf.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCDwarf.h?rev=129362&r1=129361&r2=129362&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCDwarf.h (original) +++ llvm/trunk/include/llvm/MC/MCDwarf.h Tue Apr 12 11:12:03 2011 @@ -230,7 +230,7 @@ class MCCFIInstruction { public: - enum OpType { SameValue, Remember, Restore, Move }; + enum OpType { SameValue, Remember, Restore, Move, RelMove }; private: OpType Operation; MCSymbol *Label; @@ -250,6 +250,11 @@ const MachineLocation &S) : Operation(Move), Label(L), Destination(D), Source(S) { } + MCCFIInstruction(OpType Op, MCSymbol *L, const MachineLocation &D, + const MachineLocation &S) + : Operation(Op), Label(L), Destination(D), Source(S) { + assert(Op == RelMove); + } OpType getOperation() const { return Operation; } MCSymbol *getLabel() const { return Label; } const MachineLocation &getDestination() const { return Destination; } Modified: llvm/trunk/include/llvm/MC/MCStreamer.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=129362&r1=129361&r2=129362&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCStreamer.h (original) +++ llvm/trunk/include/llvm/MC/MCStreamer.h Tue Apr 12 11:12:03 2011 @@ -447,6 +447,7 @@ virtual bool EmitCFIRememberState(); virtual bool EmitCFIRestoreState(); void EmitCFISameValue(int64_t Register); + void EmitCFIRelOffset(int64_t Register, int64_t Offset); /// EmitInstruction - Emit the given @p Instruction into the current /// section. Modified: llvm/trunk/lib/MC/MCDwarf.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDwarf.cpp?rev=129362&r1=129361&r2=129362&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCDwarf.cpp (original) +++ llvm/trunk/lib/MC/MCDwarf.cpp Tue Apr 12 11:12:03 2011 @@ -439,12 +439,88 @@ return -size; } -static void EmitCFIInstruction(MCStreamer &Streamer, - const MCCFIInstruction &Instr) { +static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, + unsigned symbolEncoding) { + MCContext &context = streamer.getContext(); + const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); + unsigned format = symbolEncoding & 0x0f; + unsigned application = symbolEncoding & 0x70; + unsigned size; + switch (format) { + default: + assert(0 && "Unknown Encoding"); + case dwarf::DW_EH_PE_absptr: + case dwarf::DW_EH_PE_signed: + size = asmInfo.getPointerSize(); + break; + case dwarf::DW_EH_PE_udata2: + case dwarf::DW_EH_PE_sdata2: + size = 2; + break; + case dwarf::DW_EH_PE_udata4: + case dwarf::DW_EH_PE_sdata4: + size = 4; + break; + case dwarf::DW_EH_PE_udata8: + case dwarf::DW_EH_PE_sdata8: + size = 8; + break; + } + switch (application) { + default: + assert(0 && "Unknown Encoding"); + break; + case 0: + streamer.EmitSymbolValue(&symbol, size); + break; + case dwarf::DW_EH_PE_pcrel: + streamer.EmitPCRelSymbolValue(&symbol, size); + break; + } +} + +static const MachineLocation TranslateMachineLocation( + const TargetAsmInfo &AsmInfo, + const MachineLocation &Loc) { + unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? + MachineLocation::VirtualFP : + unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true)); + const MachineLocation &NewLoc = Loc.isReg() ? + MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); + return NewLoc; +} + +namespace { + class FrameEmitterImpl { + int CFAOffset; + + public: + FrameEmitterImpl() : CFAOffset(0) { + } + + const MCSymbol &EmitCIE(MCStreamer &streamer, + const MCSymbol *personality, + unsigned personalityEncoding, + const MCSymbol *lsda, + unsigned lsdaEncoding); + MCSymbol *EmitFDE(MCStreamer &streamer, + const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame); + void EmitCFIInstructions(MCStreamer &streamer, + const std::vector &Instrs, + MCSymbol *BaseLabel); + void EmitCFIInstruction(MCStreamer &Streamer, + const MCCFIInstruction &Instr); + }; +} + +void FrameEmitterImpl::EmitCFIInstruction(MCStreamer &Streamer, + const MCCFIInstruction &Instr) { int dataAlignmentFactor = getDataAlignmentFactor(Streamer); switch (Instr.getOperation()) { - case MCCFIInstruction::Move: { + case MCCFIInstruction::Move: + case MCCFIInstruction::RelMove: { const MachineLocation &Dst = Instr.getDestination(); const MachineLocation &Src = Instr.getSource(); @@ -459,7 +535,8 @@ Streamer.EmitULEB128IntValue(Src.getReg()); } - Streamer.EmitULEB128IntValue(-Src.getOffset(), 1); + CFAOffset = -Src.getOffset(); + Streamer.EmitULEB128IntValue(CFAOffset, 1); return; } @@ -471,7 +548,12 @@ } unsigned Reg = Src.getReg(); - int Offset = Dst.getOffset() / dataAlignmentFactor; + + const bool IsRelative = Instr.getOperation() == MCCFIInstruction::RelMove; + int Offset = Dst.getOffset(); + if (IsRelative) + Offset -= CFAOffset; + Offset = Offset / dataAlignmentFactor; if (Offset < 0) { Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); @@ -505,9 +587,9 @@ /// EmitFrameMoves - Emit frame instructions to describe the layout of the /// frame. -static void EmitCFIInstructions(MCStreamer &streamer, - const std::vector &Instrs, - MCSymbol *BaseLabel) { +void FrameEmitterImpl::EmitCFIInstructions(MCStreamer &streamer, + const std::vector &Instrs, + MCSymbol *BaseLabel) { for (unsigned i = 0, N = Instrs.size(); i < N; ++i) { const MCCFIInstruction &Instr = Instrs[i]; MCSymbol *Label = Instr.getLabel(); @@ -527,62 +609,11 @@ } } -static void EmitSymbol(MCStreamer &streamer, const MCSymbol &symbol, - unsigned symbolEncoding) { - MCContext &context = streamer.getContext(); - const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); - unsigned format = symbolEncoding & 0x0f; - unsigned application = symbolEncoding & 0x70; - unsigned size; - switch (format) { - default: - assert(0 && "Unknown Encoding"); - case dwarf::DW_EH_PE_absptr: - case dwarf::DW_EH_PE_signed: - size = asmInfo.getPointerSize(); - break; - case dwarf::DW_EH_PE_udata2: - case dwarf::DW_EH_PE_sdata2: - size = 2; - break; - case dwarf::DW_EH_PE_udata4: - case dwarf::DW_EH_PE_sdata4: - size = 4; - break; - case dwarf::DW_EH_PE_udata8: - case dwarf::DW_EH_PE_sdata8: - size = 8; - break; - } - switch (application) { - default: - assert(0 && "Unknown Encoding"); - break; - case 0: - streamer.EmitSymbolValue(&symbol, size); - break; - case dwarf::DW_EH_PE_pcrel: - streamer.EmitPCRelSymbolValue(&symbol, size); - break; - } -} - -static const MachineLocation TranslateMachineLocation( - const TargetAsmInfo &AsmInfo, - const MachineLocation &Loc) { - unsigned Reg = Loc.getReg() == MachineLocation::VirtualFP ? - MachineLocation::VirtualFP : - unsigned(AsmInfo.getDwarfRegNum(Loc.getReg(), true)); - const MachineLocation &NewLoc = Loc.isReg() ? - MachineLocation(Reg) : MachineLocation(Reg, Loc.getOffset()); - return NewLoc; -} - -static const MCSymbol &EmitCIE(MCStreamer &streamer, - const MCSymbol *personality, - unsigned personalityEncoding, - const MCSymbol *lsda, - unsigned lsdaEncoding) { +const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer, + const MCSymbol *personality, + unsigned personalityEncoding, + const MCSymbol *lsda, + unsigned lsdaEncoding) { MCContext &context = streamer.getContext(); const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); const MCSection §ion = *asmInfo.getEHFrameSection(); @@ -670,9 +701,9 @@ return *sectionStart; } -static MCSymbol *EmitFDE(MCStreamer &streamer, - const MCSymbol &cieStart, - const MCDwarfFrameInfo &frame) { +MCSymbol *FrameEmitterImpl::EmitFDE(MCStreamer &streamer, + const MCSymbol &cieStart, + const MCDwarfFrameInfo &frame) { MCContext &context = streamer.getContext(); MCSymbol *fdeStart = context.CreateTempSymbol(); MCSymbol *fdeEnd = context.CreateTempSymbol(); @@ -764,6 +795,7 @@ const TargetAsmInfo &asmInfo = context.getTargetAsmInfo(); MCSymbol *fdeEnd = NULL; DenseMap CIEStarts; + FrameEmitterImpl Emitter; for (unsigned i = 0, n = streamer.getNumFrameInfos(); i < n; ++i) { const MCDwarfFrameInfo &frame = streamer.getFrameInfo(i); @@ -771,10 +803,10 @@ frame.LsdaEncoding); const MCSymbol *&cieStart = CIEStarts[key]; if (!cieStart) - cieStart = &EmitCIE(streamer, frame.Personality, - frame.PersonalityEncoding, frame.Lsda, - frame.LsdaEncoding); - fdeEnd = EmitFDE(streamer, *cieStart, frame); + cieStart = &Emitter.EmitCIE(streamer, frame.Personality, + frame.PersonalityEncoding, frame.Lsda, + frame.LsdaEncoding); + fdeEnd = Emitter.EmitFDE(streamer, *cieStart, frame); if (i != n - 1) streamer.EmitLabel(fdeEnd); } Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=129362&r1=129361&r2=129362&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Tue Apr 12 11:12:03 2011 @@ -149,9 +149,6 @@ LastOffset += Adjustment; return LastOffset; } - int64_t getLastOffset() { - return LastOffset; - } void setLastOffset(int64_t Offset) { LastOffset = Offset; } @@ -2402,9 +2399,8 @@ if (getParser().ParseAbsoluteExpression(Offset)) return true; - Offset -= getParser().getLastOffset(); - - return getStreamer().EmitCFIOffset(Register, Offset); + getStreamer().EmitCFIRelOffset(Register, Offset); + return false; } static bool isValidEncoding(int64_t Encoding) { Modified: llvm/trunk/lib/MC/MCStreamer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=129362&r1=129361&r2=129362&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCStreamer.cpp (original) +++ llvm/trunk/lib/MC/MCStreamer.cpp Tue Apr 12 11:12:03 2011 @@ -221,6 +221,17 @@ return false; } +void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(Register, Offset); + MachineLocation Source(Register, Offset); + MCCFIInstruction Instruction(MCCFIInstruction::RelMove, Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); +} + bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) { EnsureValidFrame(); Added: llvm/trunk/test/MC/ELF/cfi-rel-offset2.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/cfi-rel-offset2.s?rev=129362&view=auto ============================================================================== --- llvm/trunk/test/MC/ELF/cfi-rel-offset2.s (added) +++ llvm/trunk/test/MC/ELF/cfi-rel-offset2.s Tue Apr 12 11:12:03 2011 @@ -0,0 +1,41 @@ +// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s + +f: + .cfi_startproc + nop + .cfi_rel_offset 6,16 + .cfi_endproc + +// CHECK: # Section 0x00000004 +// CHECK-NEXT: (('sh_name', 0x00000011) # '.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000001) +// CHECK-NEXT: ('sh_flags', 0x00000002) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000048) +// CHECK-NEXT: ('sh_size', 0x00000030) +// CHECK-NEXT: ('sh_link', 0x00000000) +// CHECK-NEXT: ('sh_info', 0x00000000) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000000) +// CHECK-NEXT: ('_section_data', '14000000 00000000 017a5200 01781001 1b0c0708 90010000 14000000 1c000000 00000000 01000000 00411106 7f000000') +// CHECK-NEXT: ), +// CHECK-NEXT: # Section 0x00000005 +// CHECK-NEXT: (('sh_name', 0x0000000c) # '.rela.eh_frame' +// CHECK-NEXT: ('sh_type', 0x00000004) +// CHECK-NEXT: ('sh_flags', 0x00000000) +// CHECK-NEXT: ('sh_addr', 0x00000000) +// CHECK-NEXT: ('sh_offset', 0x00000390) +// CHECK-NEXT: ('sh_size', 0x00000018) +// CHECK-NEXT: ('sh_link', 0x00000007) +// CHECK-NEXT: ('sh_info', 0x00000004) +// CHECK-NEXT: ('sh_addralign', 0x00000008) +// CHECK-NEXT: ('sh_entsize', 0x00000018) +// CHECK-NEXT: ('_relocations', [ +// CHECK-NEXT: # Relocation 0x00000000 +// CHECK-NEXT: (('r_offset', 0x00000020) +// CHECK-NEXT: ('r_sym', 0x00000002) +// CHECK-NEXT: ('r_type', 0x00000002) +// CHECK-NEXT: ('r_addend', 0x00000000) +// CHECK-NEXT: ), +// CHECK-NEXT: ]) +// CHECK-NEXT: ), From johnny.chen at apple.com Tue Apr 12 12:09:04 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Apr 2011 17:09:04 -0000 Subject: [llvm-commits] [llvm] r129365 - in /llvm/trunk: lib/Target/ARM/Disassembler/ARMDisassemblerCore.h lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt Message-ID: <20110412170904.4EA062A6C12E@llvm.org> Author: johnny Date: Tue Apr 12 12:09:04 2011 New Revision: 129365 URL: http://llvm.org/viewvc/llvm-project?rev=129365&view=rev Log: Print out a debug message when the reglist fails the sanity check for Thumb Ld/St Multiple. Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h?rev=129365&r1=129364&r2=129365&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h Tue Apr 12 12:09:04 2011 @@ -139,6 +139,31 @@ Bits |= (Val & Mask) << To; } +// Return an integer result equal to the number of bits of x that are ones. +static inline uint32_t +BitCount (uint64_t x) +{ + // c accumulates the total bits set in x + uint32_t c; + for (c = 0; x; ++c) + { + x &= x - 1; // clear the least significant bit set + } + return c; +} + +static inline bool +BitIsSet (const uint64_t value, const uint64_t bit) +{ + return (value & (1ull << bit)) != 0; +} + +static inline bool +BitIsClear (const uint64_t value, const uint64_t bit) +{ + return (value & (1ull << bit)) == 0; +} + /// Various utilities for checking the target specific flags. /// A unary data processing instruction doesn't have an Rn operand. Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129365&r1=129364&r2=129365&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Tue Apr 12 12:09:04 2011 @@ -901,6 +901,10 @@ } unsigned RegListBits = slice(insn, 7, 0); + if (BitCount(RegListBits) < 1) { + DEBUG(errs() << "if BitCount(registers) < 1 then UNPREDICTABLE\n"); + return false; + } // Fill the variadic part of reglist. for (unsigned i = 0; i < 8; ++i) Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt?rev=129365&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt Tue Apr 12 12:09:04 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=2313 Name=tSTMIA_UPD Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| 1: 1: 0: 0| 0: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| +# ------------------------------------------------------------------------------------------------- +# +# if BitCount(registers) < 1 then UNPREDICTABLE +0x00 0xc7 From dpatel at apple.com Tue Apr 12 12:40:33 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 12 Apr 2011 17:40:33 -0000 Subject: [llvm-commits] [llvm] r129367 - in /llvm/trunk/lib/CodeGen/AsmPrinter: DwarfCompileUnit.h DwarfDebug.cpp Message-ID: <20110412174033.195DA2A6C12D@llvm.org> Author: dpatel Date: Tue Apr 12 12:40:32 2011 New Revision: 129367 URL: http://llvm.org/viewvc/llvm-project?rev=129367&view=rev Log: Refactor CompileUnit into a separate header. Added: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Added: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h?rev=129367&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (added) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Tue Apr 12 12:40:32 2011 @@ -0,0 +1,123 @@ +//===-- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit ---*- 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 support for writing dwarf compile unit. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H +#define CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H + +#include "DIE.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/OwningPtr.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// CompileUnit - This dwarf writer support class manages information associate +/// with a source file. +class CompileUnit { + /// ID - File identifier for source. + /// + unsigned ID; + + /// Die - Compile unit debug information entry. + /// + const OwningPtr CUDie; + + /// IndexTyDie - An anonymous type for index type. Owned by CUDie. + DIE *IndexTyDie; + + /// MDNodeToDieMap - Tracks the mapping of unit level debug informaton + /// variables to debug information entries. + DenseMap MDNodeToDieMap; + + /// MDNodeToDIEEntryMap - Tracks the mapping of unit level debug informaton + /// descriptors to debug information entries using a DIEEntry proxy. + DenseMap MDNodeToDIEEntryMap; + + /// Globals - A map of globally visible named entities for this unit. + /// + StringMap Globals; + + /// GlobalTypes - A map of globally visible types for this unit. + /// + StringMap GlobalTypes; + +public: + CompileUnit(unsigned I, DIE *D) + : ID(I), CUDie(D), IndexTyDie(0) {} + + // Accessors. + unsigned getID() const { return ID; } + DIE* getCUDie() const { return CUDie.get(); } + const StringMap &getGlobals() const { return Globals; } + const StringMap &getGlobalTypes() const { return GlobalTypes; } + + /// hasContent - Return true if this compile unit has something to write out. + /// + bool hasContent() const { return !CUDie->getChildren().empty(); } + + /// addGlobal - Add a new global entity to the compile unit. + /// + void addGlobal(StringRef Name, DIE *Die) { Globals[Name] = Die; } + + /// addGlobalType - Add a new global type to the compile unit. + /// + void addGlobalType(StringRef Name, DIE *Die) { + GlobalTypes[Name] = Die; + } + + /// getDIE - Returns the debug information entry map slot for the + /// specified debug variable. + DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); } + + /// insertDIE - Insert DIE into the map. + void insertDIE(const MDNode *N, DIE *D) { + MDNodeToDieMap.insert(std::make_pair(N, D)); + } + + /// getDIEEntry - Returns the debug information entry for the speciefied + /// debug variable. + DIEEntry *getDIEEntry(const MDNode *N) { + DenseMap::iterator I = + MDNodeToDIEEntryMap.find(N); + if (I == MDNodeToDIEEntryMap.end()) + return NULL; + return I->second; + } + + /// insertDIEEntry - Insert debug information entry into the map. + void insertDIEEntry(const MDNode *N, DIEEntry *E) { + MDNodeToDIEEntryMap.insert(std::make_pair(N, E)); + } + + /// addDie - Adds or interns the DIE to the compile unit. + /// + void addDie(DIE *Buffer) { + this->CUDie->addChild(Buffer); + } + + // getIndexTyDie - Get an anonymous type for index type. + DIE *getIndexTyDie() { + return IndexTyDie; + } + + // setIndexTyDie - Set D as anonymous type for index which can be reused + // later. + void setIndexTyDie(DIE *D) { + IndexTyDie = D; + } + +}; + +} // end llvm namespace +#endif Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=129367&r1=129366&r2=129367&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Apr 12 12:40:32 2011 @@ -14,6 +14,7 @@ #define DEBUG_TYPE "dwarfdebug" #include "DwarfDebug.h" #include "DIE.h" +#include "DwarfCompileUnit.h" #include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/Instructions.h" @@ -73,104 +74,6 @@ namespace llvm { //===----------------------------------------------------------------------===// -/// CompileUnit - This dwarf writer support class manages information associate -/// with a source file. -class CompileUnit { - /// ID - File identifier for source. - /// - unsigned ID; - - /// Die - Compile unit debug information entry. - /// - const OwningPtr CUDie; - - /// IndexTyDie - An anonymous type for index type. Owned by CUDie. - DIE *IndexTyDie; - - /// MDNodeToDieMap - Tracks the mapping of unit level debug informaton - /// variables to debug information entries. - DenseMap MDNodeToDieMap; - - /// MDNodeToDIEEntryMap - Tracks the mapping of unit level debug informaton - /// descriptors to debug information entries using a DIEEntry proxy. - DenseMap MDNodeToDIEEntryMap; - - /// Globals - A map of globally visible named entities for this unit. - /// - StringMap Globals; - - /// GlobalTypes - A map of globally visible types for this unit. - /// - StringMap GlobalTypes; - -public: - CompileUnit(unsigned I, DIE *D) - : ID(I), CUDie(D), IndexTyDie(0) {} - - // Accessors. - unsigned getID() const { return ID; } - DIE* getCUDie() const { return CUDie.get(); } - const StringMap &getGlobals() const { return Globals; } - const StringMap &getGlobalTypes() const { return GlobalTypes; } - - /// hasContent - Return true if this compile unit has something to write out. - /// - bool hasContent() const { return !CUDie->getChildren().empty(); } - - /// addGlobal - Add a new global entity to the compile unit. - /// - void addGlobal(StringRef Name, DIE *Die) { Globals[Name] = Die; } - - /// addGlobalType - Add a new global type to the compile unit. - /// - void addGlobalType(StringRef Name, DIE *Die) { - GlobalTypes[Name] = Die; - } - - /// getDIE - Returns the debug information entry map slot for the - /// specified debug variable. - DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); } - - /// insertDIE - Insert DIE into the map. - void insertDIE(const MDNode *N, DIE *D) { - MDNodeToDieMap.insert(std::make_pair(N, D)); - } - - /// getDIEEntry - Returns the debug information entry for the speciefied - /// debug variable. - DIEEntry *getDIEEntry(const MDNode *N) { - DenseMap::iterator I = - MDNodeToDIEEntryMap.find(N); - if (I == MDNodeToDIEEntryMap.end()) - return NULL; - return I->second; - } - - /// insertDIEEntry - Insert debug information entry into the map. - void insertDIEEntry(const MDNode *N, DIEEntry *E) { - MDNodeToDIEEntryMap.insert(std::make_pair(N, E)); - } - - /// addDie - Adds or interns the DIE to the compile unit. - /// - void addDie(DIE *Buffer) { - this->CUDie->addChild(Buffer); - } - - // getIndexTyDie - Get an anonymous type for index type. - DIE *getIndexTyDie() { - return IndexTyDie; - } - - // setIndexTyDie - Set D as anonymous type for index which can be reused - // later. - void setIndexTyDie(DIE *D) { - IndexTyDie = D; - } - -}; - -//===----------------------------------------------------------------------===// /// DbgVariable - This class is used to track local variable information. /// class DbgVariable { From dpatel at apple.com Tue Apr 12 12:43:12 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 12 Apr 2011 17:43:12 -0000 Subject: [llvm-commits] [llvm] r129368 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Message-ID: <20110412174312.C4A022A6C12D@llvm.org> Author: dpatel Date: Tue Apr 12 12:43:12 2011 New Revision: 129368 URL: http://llvm.org/viewvc/llvm-project?rev=129368&view=rev Log: Remove dead typedef. Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=129368&r1=129367&r2=129368&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Tue Apr 12 12:43:12 2011 @@ -198,8 +198,6 @@ /// corresponds to the MDNode mapped with the subprogram DIE. DenseMap ContainingTypeMap; - typedef SmallVector ScopeVector; - /// InlineInfo - Keep track of inlined functions and their location. This /// information is used to populate debug_inlined section. typedef std::pair InlineInfoLabels; From stoklund at 2pi.dk Tue Apr 12 13:11:28 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 12 Apr 2011 18:11:28 -0000 Subject: [llvm-commits] [llvm] r129373 - /llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Message-ID: <20110412181128.E105B2A6C12D@llvm.org> Author: stoklund Date: Tue Apr 12 13:11:28 2011 New Revision: 129373 URL: http://llvm.org/viewvc/llvm-project?rev=129373&view=rev Log: Fix a bug in RegAllocBase::addMBBLiveIns() where a basic block could accidentally be skipped. Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocBasic.cpp?rev=129373&r1=129372&r2=129373&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocBasic.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Tue Apr 12 13:11:28 2011 @@ -429,7 +429,7 @@ if (!MBB->isLiveIn(PhysReg)) MBB->addLiveIn(PhysReg); } else if (SI.start() > Stop) - MBB = Indexes->getMBBFromIndex(SI.start()); + MBB = Indexes->getMBBFromIndex(SI.start().getPrevIndex()); if (++MBB == MFE) break; tie(Start, Stop) = Indexes->getMBBRange(MBB); From stoklund at 2pi.dk Tue Apr 12 13:11:31 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 12 Apr 2011 18:11:31 -0000 Subject: [llvm-commits] [llvm] r129374 - in /llvm/trunk/lib/CodeGen: SplitKit.cpp SplitKit.h Message-ID: <20110412181131.6B7AC2A6C12E@llvm.org> Author: stoklund Date: Tue Apr 12 13:11:31 2011 New Revision: 129374 URL: http://llvm.org/viewvc/llvm-project?rev=129374&view=rev Log: Add SplitKit API to query and select the current interval being worked on. This makes it possible to target multiple registers in one pass. Modified: llvm/trunk/lib/CodeGen/SplitKit.cpp llvm/trunk/lib/CodeGen/SplitKit.h Modified: llvm/trunk/lib/CodeGen/SplitKit.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.cpp?rev=129374&r1=129373&r2=129374&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SplitKit.cpp (original) +++ llvm/trunk/lib/CodeGen/SplitKit.cpp Tue Apr 12 13:11:31 2011 @@ -557,7 +557,7 @@ } /// Create a new virtual register and live interval. -void SplitEditor::openIntv() { +unsigned SplitEditor::openIntv() { assert(!OpenIdx && "Previous LI not closed before openIntv"); // Create the complement as index 0. @@ -567,6 +567,13 @@ // Create the open interval. OpenIdx = Edit->size(); Edit->create(LIS, VRM); + return OpenIdx; +} + +void SplitEditor::selectIntv(unsigned Idx) { + assert(Idx != 0 && "Cannot select the complement interval"); + assert(Idx < Edit->size() && "Can only select previously opened interval"); + OpenIdx = Idx; } SlotIndex SplitEditor::enterIntvBefore(SlotIndex Idx) { Modified: llvm/trunk/lib/CodeGen/SplitKit.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.h?rev=129374&r1=129373&r2=129374&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SplitKit.h (original) +++ llvm/trunk/lib/CodeGen/SplitKit.h Tue Apr 12 13:11:31 2011 @@ -283,7 +283,15 @@ void reset(LiveRangeEdit&); /// Create a new virtual register and live interval. - void openIntv(); + /// Return the interval index, starting from 1. Interval index 0 is the + /// implicit complement interval. + unsigned openIntv(); + + /// currentIntv - Return the current interval index. + unsigned currentIntv() const { return OpenIdx; } + + /// selectIntv - Select a previously opened interval index. + void selectIntv(unsigned Idx); /// enterIntvBefore - Enter the open interval before the instruction at Idx. /// If the parent interval is not live before Idx, a COPY is not inserted. From jabbey at arxan.com Tue Apr 12 13:36:46 2011 From: jabbey at arxan.com (Joe Abbey) Date: Tue, 12 Apr 2011 14:36:46 -0400 Subject: [llvm-commits] Source register same as write-back base In-Reply-To: References: <88D727341410A44C9E34E8E3EF37D8ED04213C3E@be25.exg3.exghost.com> <12BD8D01-BDE4-4E21-8608-A24EFF90A48C@apple.com> Message-ID: <88D727341410A44C9E34E8E3EF37D8ED0427A419@be25.exg3.exghost.com> -----Original Message----- From: Jakob Stoklund Olesen [mailto:stoklund at 2pi.dk] Sent: Monday, April 11, 2011 7:44 PM To: Johnny Chen Cc: Joe Abbey; Commit Messages and Patches for LLVM Subject: Re: [llvm-commits] Source register same as write-back base On Apr 11, 2011, at 2:27 PM, Johnny Chen wrote: > Hi Joe, > > I've CCed llvm-commit. Hopefully the backend folks can help you out! > Thanks. > > On Apr 11, 2011, at 2:20 PM, Joe Abbey wrote: > >> Johnny, >> >> I saw your changelist which adds a check to the disassembly of ARM instructions. >> >> I'm currently trying to debug how the register allocation works to produce: >> >> str r3, [r3], #4 >> >> My assembler is complaining that: >> >> libtest-libstl.so.bc:46025: Warning: source register same as write-back base >> >> And it should because as you (and ARM) note, this is UNPREDICTABLE. Is this the same situation as the armV5 MUL instructions where the documents say it is unpredictable, but all existing hardware implementations behave correctly? Which architecture revisions have this constraint? /jakob Jakob, Yes this is the same restriction as armV5 MUL, and it is likely the case that all hardware implementations behave correctly. However, this restriction is documented in ARMv5 & ARMv7: DD101001 A4.1.99 If specifies base register write-back, and the same register is specified for and , the results are UNPREDICTABLE. DDI0406B A8.6.194 if wback && (n == 15 || n == t) then UNPREDICTABLE; I see that in ARMInstrInfo.td MULv5 considers $Rd to be earlyclobber. Could a similar pattern of making $Rt earlyclobber be applied in the store instrucitons? Cheers, Joe From evan.cheng at apple.com Tue Apr 12 13:51:20 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 12 Apr 2011 11:51:20 -0700 Subject: [llvm-commits] [llvm-gcc-4.2] r129344 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp In-Reply-To: <4DA40199.4050302@free.fr> References: <20110412021741.C5BB52A6C12D@llvm.org> <4DA40199.4050302@free.fr> Message-ID: Crap. I forgot about non-C compilers. I'll take a look. Evan On Apr 12, 2011, at 12:39 AM, Duncan Sands wrote: > Hi Evan, > >> Disable loop idiom recognition if -fno-builtin-* options are specified. rdar://9268471 > > from http://google1.osuosl.org:8011/builders/llvm-x86_64-linux-checks > > /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/./prev-gcc/xgcc -B/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/./prev-gcc/ > -B/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.install/x86_64-pc-linux-gnu/bin/ > -c -g -O2 -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes > -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros > -Wno-overlength-strings -Wold-style-definition -Wmissing-format-attribute > -DHAVE_CONFIG_H -I. -I. -I../../llvm-gcc.src/gcc -I../../llvm-gcc.src/gcc/. > -I../../llvm-gcc.src/gcc/../include -I../../llvm-gcc.src/gcc/../libcpp/include > -I/opt/cfarm/gmp/include -I/opt/cfarm/mpfr/include > -I../../llvm-gcc.src/gcc/../libdecnumber -I../libdecnumber > -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.obj/include > -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.src/include > -DENABLE_LLVM > -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.src/include > -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.obj/include > -D_DEBUG -D_GLIBCXX_DEBUG -DXDEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS > -D__STDC_CONSTANT_MACROS cc1-checksum.c -o cc1-checksum.o > libbackend.a(llvm-backend.o): In function `createPerFunctionOptimizationPasses': > /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:678: > undefined reference to `flag_no_builtin' > /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:681: > undefined reference to `builtin_function_disabled_p' > /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:683: > undefined reference to `builtin_function_disabled_p' > libbackend.a(llvm-backend.o): In function `createPerModuleOptimizationPasses': > /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:762: > undefined reference to `flag_no_builtin' > /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:765: > undefined reference to `builtin_function_disabled_p' > /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:767: > undefined reference to `builtin_function_disabled_p' > collect2: ld returned 1 exit status > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From johnny.chen at apple.com Tue Apr 12 13:48:00 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Apr 2011 18:48:00 -0000 Subject: [llvm-commits] [llvm] r129377 - in /llvm/trunk: lib/Target/ARM/ARMInstrThumb2.td lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110412184800.761D52A6C12D@llvm.org> Author: johnny Date: Tue Apr 12 13:48:00 2011 New Revision: 129377 URL: http://llvm.org/viewvc/llvm-project?rev=129377&view=rev Log: The Thumb2 Ld, St, and Preload instructions with the i12 forms should have its Inst{23} be specified as '1' (add = TRUE). Also add a utility function for Thumb2. Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=129377&r1=129376&r2=129377&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Apr 12 13:48:00 2011 @@ -845,6 +845,7 @@ let Inst{15-12} = Rt; bits<17> addr; + let addr{12} = 1; // add = TRUE let Inst{19-16} = addr{16-13}; // Rn let Inst{23} = addr{12}; // U let Inst{11-0} = addr{11-0}; // imm @@ -925,6 +926,7 @@ let Inst{15-12} = Rt; bits<17> addr; + let addr{12} = 1; // add = TRUE let Inst{19-16} = addr{16-13}; // Rn let Inst{23} = addr{12}; // U let Inst{11-0} = addr{11-0}; // imm @@ -1522,6 +1524,7 @@ let Inst{15-12} = 0b1111; bits<17> addr; + let addr{12} = 1; // add = TRUE let Inst{19-16} = addr{16-13}; // Rn let Inst{23} = addr{12}; // U let Inst{11-0} = addr{11-0}; // imm12 Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129377&r1=129376&r2=129377&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Tue Apr 12 13:48:00 2011 @@ -108,6 +108,8 @@ // Utilities for 32-bit Thumb instructions. +static inline bool BadReg(uint32_t n) { return n == 13 || n == 15; } + // Extract imm4: Inst{19-16}. static inline unsigned getImm4(uint32_t insn) { return slice(insn, 19, 16); Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129377&r1=129376&r2=129377&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Tue Apr 12 13:48:00 2011 @@ -171,7 +171,16 @@ 0x5d 0xf8 0x34 0x40 # CHECK: ldr.w r5, [r6, #30] -0x56 0xf8 0x1e 0x56 +0xd6 0xf8 0x1e 0x50 + +# CHECK: ldrh.w r5, [r6, #30] +0xb6 0xf8 0x1e 0x50 + +# CHECK: ldrt r5, [r6, #30] +0x56 0xf8 0x1e 0x5e + +# CHECK: ldr r5, [r6, #-30] +0x56 0xf8 0x1e 0x5c # CHECK: sel r7, r3, r5 0xa3 0xfa 0x85 0xf7 @@ -197,6 +206,9 @@ # CHECK: pld [pc, #-16] 0x1f 0xf8 0x10 0xf0 +# CHECK: pld [r5, #30] +0x95 0xf8 0x1e 0xf0 + # CHECK: stc2 p12, cr15, [r9], {137} 0x89 0xfc 0x89 0xfc From rafael.espindola at gmail.com Tue Apr 12 13:53:30 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Tue, 12 Apr 2011 18:53:30 -0000 Subject: [llvm-commits] [llvm] r129378 - in /llvm/trunk: include/llvm/MC/MCStreamer.h lib/MC/MCDwarf.cpp lib/MC/MCParser/AsmParser.cpp lib/MC/MCStreamer.cpp Message-ID: <20110412185330.C40D92A6C12D@llvm.org> Author: rafael Date: Tue Apr 12 13:53:30 2011 New Revision: 129378 URL: http://llvm.org/viewvc/llvm-project?rev=129378&view=rev Log: Remove LastOffset from the asm parser. Modified: llvm/trunk/include/llvm/MC/MCStreamer.h llvm/trunk/lib/MC/MCDwarf.cpp llvm/trunk/lib/MC/MCParser/AsmParser.cpp llvm/trunk/lib/MC/MCStreamer.cpp Modified: llvm/trunk/include/llvm/MC/MCStreamer.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=129378&r1=129377&r2=129378&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCStreamer.h (original) +++ llvm/trunk/include/llvm/MC/MCStreamer.h Tue Apr 12 13:53:30 2011 @@ -448,6 +448,7 @@ virtual bool EmitCFIRestoreState(); void EmitCFISameValue(int64_t Register); void EmitCFIRelOffset(int64_t Register, int64_t Offset); + void EmitCFIAdjustCfaOffset(int64_t Adjustment); /// EmitInstruction - Emit the given @p Instruction into the current /// section. Modified: llvm/trunk/lib/MC/MCDwarf.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDwarf.cpp?rev=129378&r1=129377&r2=129378&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCDwarf.cpp (original) +++ llvm/trunk/lib/MC/MCDwarf.cpp Tue Apr 12 13:53:30 2011 @@ -523,6 +523,7 @@ case MCCFIInstruction::RelMove: { const MachineLocation &Dst = Instr.getDestination(); const MachineLocation &Src = Instr.getSource(); + const bool IsRelative = Instr.getOperation() == MCCFIInstruction::RelMove; // If advancing cfa. if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { @@ -535,7 +536,11 @@ Streamer.EmitULEB128IntValue(Src.getReg()); } - CFAOffset = -Src.getOffset(); + if (IsRelative) + CFAOffset += Src.getOffset(); + else + CFAOffset = -Src.getOffset(); + Streamer.EmitULEB128IntValue(CFAOffset, 1); return; } @@ -549,7 +554,6 @@ unsigned Reg = Src.getReg(); - const bool IsRelative = Instr.getOperation() == MCCFIInstruction::RelMove; int Offset = Dst.getOffset(); if (IsRelative) Offset -= CFAOffset; Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=129378&r1=129377&r2=129378&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Tue Apr 12 13:53:30 2011 @@ -81,11 +81,6 @@ MCAsmParserExtension *GenericParser; MCAsmParserExtension *PlatformParser; - // FIXME: This is not the best place to store this. To handle a (for example) - // .cfi_rel_offset before a .cfi_def_cfa_offset we need to know the initial - // frame state. - int64_t LastOffset; - /// This is the current buffer index we're lexing from as managed by the /// SourceMgr object. int CurBuffer; @@ -145,14 +140,6 @@ /// } - int64_t adjustLastOffset(int64_t Adjustment) { - LastOffset += Adjustment; - return LastOffset; - } - void setLastOffset(int64_t Offset) { - LastOffset = Offset; - } - private: void CheckForValidSection(); @@ -337,7 +324,7 @@ AsmParser::AsmParser(const Target &T, SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, const MCAsmInfo &_MAI) : Lexer(_MAI), Ctx(_Ctx), Out(_Out), SrcMgr(_SM), - GenericParser(new GenericAsmParser), PlatformParser(0), LastOffset(0), + GenericParser(new GenericAsmParser), PlatformParser(0), CurBuffer(0), MacrosEnabled(true) { Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)); @@ -2334,8 +2321,6 @@ if (getParser().ParseAbsoluteExpression(Offset)) return true; - getParser().setLastOffset(Offset); - return getStreamer().EmitCFIDefCfaOffset(Offset); } @@ -2347,9 +2332,8 @@ if (getParser().ParseAbsoluteExpression(Adjustment)) return true; - int64_t Offset = getParser().adjustLastOffset(Adjustment); - - return getStreamer().EmitCFIDefCfaOffset(Offset); + getStreamer().EmitCFIAdjustCfaOffset(Adjustment); + return false; } /// ParseDirectiveCFIDefCfaRegister Modified: llvm/trunk/lib/MC/MCStreamer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=129378&r1=129377&r2=129378&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCStreamer.cpp (original) +++ llvm/trunk/lib/MC/MCStreamer.cpp Tue Apr 12 13:53:30 2011 @@ -197,6 +197,17 @@ return false; } +void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { + EnsureValidFrame(); + MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + MachineLocation Dest(MachineLocation::VirtualFP); + MachineLocation Source(MachineLocation::VirtualFP, Adjustment); + MCCFIInstruction Instruction(MCCFIInstruction::RelMove, Label, Dest, Source); + CurFrame->Instructions.push_back(Instruction); +} + bool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); From stoklund at 2pi.dk Tue Apr 12 14:32:54 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 12 Apr 2011 19:32:54 -0000 Subject: [llvm-commits] [llvm] r129379 - in /llvm/trunk/lib/CodeGen: RegAllocGreedy.cpp SplitKit.cpp SplitKit.h Message-ID: <20110412193254.349162A6C12D@llvm.org> Author: stoklund Date: Tue Apr 12 14:32:53 2011 New Revision: 129379 URL: http://llvm.org/viewvc/llvm-project?rev=129379&view=rev Log: Create new intervals for isolated blocks during region splitting. This merges the behavior of splitSingleBlocks into splitAroundRegion, so the RS_Region and RS_Block register stages can be coalesced. That means the leftover intervals after region splitting go directly to spilling instead of a second pass of per-block splitting. Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp llvm/trunk/lib/CodeGen/SplitKit.cpp llvm/trunk/lib/CodeGen/SplitKit.h Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp?rev=129379&r1=129378&r2=129379&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Tue Apr 12 14:32:53 2011 @@ -95,8 +95,7 @@ RS_New, ///< Never seen before. RS_First, ///< First time in the queue. RS_Second, ///< Second time in the queue. - RS_Region, ///< Produced by region splitting. - RS_Block, ///< Produced by per-block splitting. + RS_Global, ///< Produced by global splitting. RS_Local, ///< Produced by local splitting. RS_Spill ///< Produced by spilling. }; @@ -636,7 +635,7 @@ SE->reset(LREdit); // Create the main cross-block interval. - SE->openIntv(); + const unsigned MainIntv = SE->openIntv(); // First add all defs that are live out of a block. ArrayRef UseBlocks = SA->getUseBlocks(); @@ -645,6 +644,14 @@ bool RegIn = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 0)]; bool RegOut = LiveBundles[Bundles->getBundle(BI.MBB->getNumber(), 1)]; + // Create separate intervals for isolated blocks with multiple uses. + if (!RegIn && !RegOut && BI.FirstUse != BI.LastUse) { + DEBUG(dbgs() << "BB#" << BI.MBB->getNumber() << " isolated.\n"); + SE->splitSingleBlock(BI); + SE->selectIntv(MainIntv); + continue; + } + // Should the register be live out? if (!BI.LiveOut || !RegOut) continue; @@ -894,7 +901,7 @@ return 0; splitAroundRegion(VirtReg, BestReg, BestBundles, NewVRegs); - setStage(NewVRegs.begin(), NewVRegs.end(), RS_Region); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Global); return 0; } @@ -1185,30 +1192,25 @@ // Don't iterate global splitting. // Move straight to spilling if this range was produced by a global split. - LiveRangeStage Stage = getStage(VirtReg); - if (Stage >= RS_Block) + if (getStage(VirtReg) >= RS_Global) return 0; SA->analyze(&VirtReg); // First try to split around a region spanning multiple blocks. - if (Stage < RS_Region) { - unsigned PhysReg = tryRegionSplit(VirtReg, Order, NewVRegs); - if (PhysReg || !NewVRegs.empty()) - return PhysReg; - } + unsigned PhysReg = tryRegionSplit(VirtReg, Order, NewVRegs); + if (PhysReg || !NewVRegs.empty()) + return PhysReg; // Then isolate blocks with multiple uses. - if (Stage < RS_Block) { - SplitAnalysis::BlockPtrSet Blocks; - if (SA->getMultiUseBlocks(Blocks)) { - LiveRangeEdit LREdit(VirtReg, NewVRegs, this); - SE->reset(LREdit); - SE->splitSingleBlocks(Blocks); - setStage(NewVRegs.begin(), NewVRegs.end(), RS_Block); - if (VerifyEnabled) - MF->verify(this, "After splitting live range around basic blocks"); - } + SplitAnalysis::BlockPtrSet Blocks; + if (SA->getMultiUseBlocks(Blocks)) { + LiveRangeEdit LREdit(VirtReg, NewVRegs, this); + SE->reset(LREdit); + SE->splitSingleBlocks(Blocks); + setStage(NewVRegs.begin(), NewVRegs.end(), RS_Global); + if (VerifyEnabled) + MF->verify(this, "After splitting live range around basic blocks"); } // Don't assign any physregs. Modified: llvm/trunk/lib/CodeGen/SplitKit.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.cpp?rev=129379&r1=129378&r2=129379&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SplitKit.cpp (original) +++ llvm/trunk/lib/CodeGen/SplitKit.cpp Tue Apr 12 14:32:53 2011 @@ -935,6 +935,22 @@ return !Blocks.empty(); } +void SplitEditor::splitSingleBlock(const SplitAnalysis::BlockInfo &BI) { + openIntv(); + SlotIndex LastSplitPoint = SA.getLastSplitPoint(BI.MBB->getNumber()); + SlotIndex SegStart = enterIntvBefore(std::min(BI.FirstUse, + LastSplitPoint)); + if (!BI.LiveOut || BI.LastUse < LastSplitPoint) { + useIntv(SegStart, leaveIntvAfter(BI.LastUse)); + } else { + // The last use is after the last valid split point. + SlotIndex SegStop = leaveIntvBefore(LastSplitPoint); + useIntv(SegStart, SegStop); + overlapIntv(SegStop, BI.LastUse); + } + closeIntv(); +} + /// splitSingleBlocks - Split CurLI into a separate live interval inside each /// basic block in Blocks. void SplitEditor::splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks) { @@ -942,22 +958,8 @@ ArrayRef UseBlocks = SA.getUseBlocks(); for (unsigned i = 0; i != UseBlocks.size(); ++i) { const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; - if (!Blocks.count(BI.MBB)) - continue; - - openIntv(); - SlotIndex LastSplitPoint = SA.getLastSplitPoint(BI.MBB->getNumber()); - SlotIndex SegStart = enterIntvBefore(std::min(BI.FirstUse, - LastSplitPoint)); - if (!BI.LiveOut || BI.LastUse < LastSplitPoint) { - useIntv(SegStart, leaveIntvAfter(BI.LastUse)); - } else { - // The last use is after the last valid split point. - SlotIndex SegStop = leaveIntvBefore(LastSplitPoint); - useIntv(SegStart, SegStop); - overlapIntv(SegStop, BI.LastUse); - } - closeIntv(); + if (Blocks.count(BI.MBB)) + splitSingleBlock(BI); } finish(); } Modified: llvm/trunk/lib/CodeGen/SplitKit.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.h?rev=129379&r1=129378&r2=129379&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SplitKit.h (original) +++ llvm/trunk/lib/CodeGen/SplitKit.h Tue Apr 12 14:32:53 2011 @@ -347,6 +347,11 @@ // ===--- High level methods ---=== + /// splitSingleBlock - Split CurLI into a separate live interval around the + /// uses in a single block. This is intended to be used as part of a larger + /// split, and doesn't call finish(). + void splitSingleBlock(const SplitAnalysis::BlockInfo &BI); + /// splitSingleBlocks - Split CurLI into a separate live interval inside each /// basic block in Blocks. void splitSingleBlocks(const SplitAnalysis::BlockPtrSet &Blocks); From nicholas at mxc.ca Tue Apr 12 14:35:45 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 12 Apr 2011 19:35:45 -0000 Subject: [llvm-commits] [llvm] r129380 - /llvm/trunk/runtime/libprofile/LineProfiling.c Message-ID: <20110412193545.8D15D2A6C12D@llvm.org> Author: nicholas Date: Tue Apr 12 14:35:45 2011 New Revision: 129380 URL: http://llvm.org/viewvc/llvm-project?rev=129380&view=rev Log: The counters are unsigned. Modified: llvm/trunk/runtime/libprofile/LineProfiling.c Modified: llvm/trunk/runtime/libprofile/LineProfiling.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129380&r1=129379&r2=129380&view=diff ============================================================================== --- llvm/trunk/runtime/libprofile/LineProfiling.c (original) +++ llvm/trunk/runtime/libprofile/LineProfiling.c Tue Apr 12 14:35:45 2011 @@ -28,7 +28,7 @@ /* Emit data about a counter to the data file. */ void llvm_prof_linectr_emit_counter(const char *dir, const char *file, uint32_t line, uint32_t column, - int64_t *counter) { + uint64_t *counter) { printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); } From nlewycky at google.com Tue Apr 12 14:41:27 2011 From: nlewycky at google.com (Nick Lewycky) Date: Tue, 12 Apr 2011 12:41:27 -0700 Subject: [llvm-commits] [llvm] r129340 - in /llvm/trunk: include/llvm/InitializePasses.h include/llvm/LinkAllPasses.h include/llvm/Transforms/Instrumentation.h lib/Transforms/Instrumentation/Instrumentation.cpp lib/Transforms/Instrumentation/LineProfiling Message-ID: On 12 April 2011 08:55, Jim Grosbach wrote: > Hi Nick, > > clang is issuing a warning for this. Mind having a look? > Sorry! I meant for counter to be a uint64_t, and updated that. Neither gcc nor clang warned when I built it this time, but I could imagine that it still might on a different platform. Let me know if it's not fixed past r129380. Nick > > llvm[2]: Compiling LineProfiling.c for Debug+Asserts build (PIC) > /Volumes/Home/grosbaj/sources/llvm/runtime/libprofile/LineProfiling.c:32:25: > warning: > conversion specifies type 'unsigned long' but the argument has type > 'int64_t' (aka 'long long') [-Wformat] > printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); > ~~^ ~~~~~~~~ > %lld > 1 warning generated. > > (highlighting points to the "%lu" and "*counter" inputs) > > -Jim > > On Apr 11, 2011, at 6:06 PM, Nick Lewycky wrote: > > > Author: nicholas > > Date: Mon Apr 11 20:06:09 2011 > > New Revision: 129340 > > > > URL: http://llvm.org/viewvc/llvm-project?rev=129340&view=rev > > Log: > > Add support for line profiling. Very work-in-progress. > > > > Use debug info in the IR to find the directory/file:line:col. Each time > that location changes, bump a counter. > > > > Unlike the existing profiling system, we don't try to look at argv[], and > thusly don't require main() to be present in the IR. This matches GCC's > technique where you specify the profiling flag when producing each .o file. > > > > The runtime library is minimal, currently just calling printf at program > shutdown time. The API is designed to make it possible to emit GCOV data > later on. > > > > Added: > > llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp > > llvm/trunk/runtime/libprofile/LineProfiling.c > > Modified: > > llvm/trunk/include/llvm/InitializePasses.h > > llvm/trunk/include/llvm/LinkAllPasses.h > > llvm/trunk/include/llvm/Transforms/Instrumentation.h > > llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp > > llvm/trunk/runtime/libprofile/libprofile.exports > > > > Modified: llvm/trunk/include/llvm/InitializePasses.h > > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=129340&r1=129339&r2=129340&view=diff > > > ============================================================================== > > --- llvm/trunk/include/llvm/InitializePasses.h (original) > > +++ llvm/trunk/include/llvm/InitializePasses.h Mon Apr 11 20:06:09 2011 > > @@ -94,6 +94,7 @@ > > void initializeEdgeBundlesPass(PassRegistry&); > > void initializeEdgeProfilerPass(PassRegistry&); > > void initializePathProfilerPass(PassRegistry&); > > +void initializeLineProfilerPass(PassRegistry&); > > void initializeEarlyCSEPass(PassRegistry&); > > void initializeExpandISelPseudosPass(PassRegistry&); > > void initializeFindUsedTypesPass(PassRegistry&); > > > > Modified: llvm/trunk/include/llvm/LinkAllPasses.h > > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=129340&r1=129339&r2=129340&view=diff > > > ============================================================================== > > --- llvm/trunk/include/llvm/LinkAllPasses.h (original) > > +++ llvm/trunk/include/llvm/LinkAllPasses.h Mon Apr 11 20:06:09 2011 > > @@ -70,6 +70,7 @@ > > (void) llvm::createEdgeProfilerPass(); > > (void) llvm::createOptimalEdgeProfilerPass(); > > (void) llvm::createPathProfilerPass(); > > + (void) llvm::createLineProfilerPass(); > > (void) llvm::createFunctionInliningPass(); > > (void) llvm::createAlwaysInlinerPass(); > > (void) llvm::createGlobalDCEPass(); > > > > Modified: llvm/trunk/include/llvm/Transforms/Instrumentation.h > > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Instrumentation.h?rev=129340&r1=129339&r2=129340&view=diff > > > ============================================================================== > > --- llvm/trunk/include/llvm/Transforms/Instrumentation.h (original) > > +++ llvm/trunk/include/llvm/Transforms/Instrumentation.h Mon Apr 11 > 20:06:09 2011 > > @@ -17,7 +17,6 @@ > > namespace llvm { > > > > class ModulePass; > > -class FunctionPass; > > > > // Insert edge profiling instrumentation > > ModulePass *createEdgeProfilerPass(); > > @@ -28,6 +27,9 @@ > > // Insert path profiling instrumentation > > ModulePass *createPathProfilerPass(); > > > > +// Insert line profiling instrumentation > > +ModulePass *createLineProfilerPass(); > > + > > } // End llvm namespace > > > > #endif > > > > Modified: llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp > > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp?rev=129340&r1=129339&r2=129340&view=diff > > > ============================================================================== > > --- llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp > (original) > > +++ llvm/trunk/lib/Transforms/Instrumentation/Instrumentation.cpp Mon Apr > 11 20:06:09 2011 > > @@ -23,6 +23,7 @@ > > initializeEdgeProfilerPass(Registry); > > initializeOptimalEdgeProfilerPass(Registry); > > initializePathProfilerPass(Registry); > > + initializeLineProfilerPass(Registry); > > } > > > > /// LLVMInitializeInstrumentation - C binding for > > > > Added: llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp > > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp?rev=129340&view=auto > > > ============================================================================== > > --- llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp (added) > > +++ llvm/trunk/lib/Transforms/Instrumentation/LineProfiling.cpp Mon Apr > 11 20:06:09 2011 > > @@ -0,0 +1,217 @@ > > +//===- LineProfiling.cpp - Insert counters for line profiling > -------------===// > > +// > > +// The LLVM Compiler Infrastructure > > +// > > +// This file is distributed under the University of Illinois Open Source > > +// License. See LICENSE.TXT for details. > > +// > > > +//===----------------------------------------------------------------------===// > > +// > > +// This pass creates counters for the number of times that the original > source > > +// lines of code were executed. > > +// > > +// The lines are found from existing debug info in the LLVM IR. > Iterating > > +// through LLVM instructions, every time the debug location changes we > insert a > > +// new counter and instructions to increment the counter there. A global > > +// destructor runs to dump the counters out to a file. > > +// > > > +//===----------------------------------------------------------------------===// > > + > > +#define DEBUG_TYPE "insert-line-profiling" > > + > > +#include "ProfilingUtils.h" > > +#include "llvm/Transforms/Instrumentation.h" > > +#include "llvm/Analysis/DebugInfo.h" > > +#include "llvm/Module.h" > > +#include "llvm/Pass.h" > > +#include "llvm/Instructions.h" > > +#include "llvm/Support/raw_ostream.h" > > +#include "llvm/Support/Debug.h" > > +#include "llvm/Support/DebugLoc.h" > > +#include "llvm/Support/InstIterator.h" > > +#include "llvm/Support/IRBuilder.h" > > +#include "llvm/ADT/DenseMap.h" > > +#include "llvm/ADT/Statistic.h" > > +#include "llvm/ADT/StringExtras.h" > > +#include > > +#include > > +using namespace llvm; > > + > > +STATISTIC(NumUpdatesInserted, "The # of counter increments inserted."); > > + > > +namespace { > > + class LineProfiler : public ModulePass { > > + bool runOnModule(Module &M); > > + public: > > + static char ID; > > + LineProfiler() : ModulePass(ID) { > > + initializeLineProfilerPass(*PassRegistry::getPassRegistry()); > > + } > > + virtual const char *getPassName() const { > > + return "Line Profiler"; > > + } > > + > > + private: > > + // Get pointers to the functions in the runtime library. > > + Constant *getStartFileFunc(); > > + Constant *getCounterFunc(); > > + Constant *getEndFileFunc(); > > + > > + // Insert an increment of the counter before instruction I. > > + void InsertCounterUpdateBefore(Instruction *I); > > + > > + // Add the function to write out all our counters to the global > destructor > > + // list. > > + void InsertCounterWriteout(); > > + > > + // Mapping from the source location to the counter tracking that > location. > > + DenseMap counters; > > + > > + Module *Mod; > > + LLVMContext *Ctx; > > + }; > > +} > > + > > +char LineProfiler::ID = 0; > > +INITIALIZE_PASS(LineProfiler, "insert-line-profiling", > > + "Insert instrumentation for line profiling", false, > false) > > + > > +ModulePass *llvm::createLineProfilerPass() { return new LineProfiler(); > } > > + > > +bool LineProfiler::runOnModule(Module &M) { > > + Mod = &M; > > + Ctx = &M.getContext(); > > + > > + DebugLoc last_line; // initializes to unknown > > + bool Changed = false; > > + for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { > > + for (inst_iterator II = inst_begin(F), IE = inst_end(F); II != IE; > ++II) { > > + const DebugLoc &loc = II->getDebugLoc(); > > + if (loc.isUnknown()) continue; > > + if (loc == last_line) continue; > > + last_line = loc; > > + > > + InsertCounterUpdateBefore(&*II); > > + ++NumUpdatesInserted; > > + Changed = true; > > + } > > + } > > + > > + if (Changed) { > > + InsertCounterWriteout(); > > + } > > + > > + return Changed; > > +} > > + > > +void LineProfiler::InsertCounterUpdateBefore(Instruction *I) { > > + const DebugLoc &loc = I->getDebugLoc(); > > + GlobalVariable *&counter = counters[loc]; > > + const Type *Int64Ty = Type::getInt64Ty(*Ctx); > > + if (!counter) { > > + counter = new GlobalVariable(*Mod, Int64Ty, false, > > + GlobalValue::InternalLinkage, > > + Constant::getNullValue(Int64Ty), > > + "__llvm_prof_linecov_ctr", 0, false, > 0); > > + counter->setVisibility(GlobalVariable::HiddenVisibility); > > + counter->setUnnamedAddr(true); > > + } > > + > > + if (isa(I)) { > > + // We may not error out or crash in this case, because a module > could put > > + // changing line numbers on phi nodes and still pass the verifier. > > + dbgs() << "Refusing to insert code before phi: " << *I << "\n"; > > + I = I->getParent()->getFirstNonPHI(); > > + } > > + > > + IRBuilder<> builder(I); > > + Value *ctr = builder.CreateLoad(counter); > > + ctr = builder.CreateAdd(ctr, ConstantInt::get(Int64Ty, 1)); > > + builder.CreateStore(ctr, counter); > > +} > > + > > +static DISubprogram FindSubprogram(DIScope scope) { > > + while (!scope.isSubprogram()) { > > + assert(scope.isLexicalBlock() && > > + "Debug location not lexical block or subprogram"); > > + scope = DILexicalBlock(scope).getContext(); > > + } > > + return DISubprogram(scope); > > +} > > + > > +Constant *LineProfiler::getStartFileFunc() { > > + const Type *Args[1] = { Type::getInt8PtrTy(*Ctx) }; > > + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), > > + Args, false); > > + return Mod->getOrInsertFunction("llvm_prof_linectr_start_file", FTy); > > +} > > + > > +Constant *LineProfiler::getCounterFunc() { > > + const Type *Args[] = { > > + Type::getInt8PtrTy(*Ctx), // const char *dir > > + Type::getInt8PtrTy(*Ctx), // const char *file > > + Type::getInt32Ty(*Ctx), // uint32_t line > > + Type::getInt32Ty(*Ctx), // uint32_t column > > + Type::getInt64PtrTy(*Ctx), // int64_t *counter > > + }; > > + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), > > + Args, false); > > + return Mod->getOrInsertFunction("llvm_prof_linectr_emit_counter", > FTy); > > +} > > + > > +Constant *LineProfiler::getEndFileFunc() { > > + const FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), > false); > > + return Mod->getOrInsertFunction("llvm_prof_linectr_end_file", FTy); > > +} > > + > > +void LineProfiler::InsertCounterWriteout() { > > + std::set compile_units; > > + for (DenseMap::iterator I = > counters.begin(), > > + E = counters.end(); I != E; ++I) { > > + const DebugLoc &loc = I->first; > > + DISubprogram > subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx)))); > > + > compile_units.insert(subprogram.getCompileUnit().getFilename().str()); > > + } > > + > > + const FunctionType *WriteoutFTy = > > + FunctionType::get(Type::getVoidTy(*Ctx), false); > > + Function *WriteoutF = Function::Create(WriteoutFTy, > > + GlobalValue::InternalLinkage, > > + "__llvm_prof_linecov_dtor", > > + Mod); > > + WriteoutF->setUnnamedAddr(true); > > + BasicBlock *BB = BasicBlock::Create(*Ctx, "", WriteoutF); > > + IRBuilder<> builder(BB); > > + > > + Constant *StartFile = getStartFileFunc(); > > + Constant *EmitCounter = getCounterFunc(); > > + Constant *EndFile = getEndFileFunc(); > > + > > + for (std::set::const_iterator CUI = > compile_units.begin(), > > + CUE = compile_units.end(); CUI != CUE; ++CUI) { > > + builder.CreateCall(StartFile, > > + builder.CreateGlobalStringPtr(*CUI)); > > + for (DenseMap::iterator I = > counters.begin(), > > + E = counters.end(); I != E; ++I) { > > + const DebugLoc &loc = I->first; > > + DISubprogram > subprogram(FindSubprogram(DIScope(loc.getScope(*Ctx)))); > > + DICompileUnit compileunit(subprogram.getCompileUnit()); > > + > > + if (compileunit.getFilename() != *CUI) > > + continue; > > + > > + Value *Args[] = { > > + builder.CreateGlobalStringPtr(subprogram.getDirectory()), > > + builder.CreateGlobalStringPtr(subprogram.getFilename()), > > + ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getLine()), > > + ConstantInt::get(Type::getInt32Ty(*Ctx), loc.getCol()), > > + I->second > > + }; > > + builder.CreateCall(EmitCounter, Args); > > + } > > + builder.CreateCall(EndFile); > > + } > > + builder.CreateRetVoid(); > > + > > + InsertProfilingShutdownCall(WriteoutF, Mod); > > +} > > > > Added: llvm/trunk/runtime/libprofile/LineProfiling.c > > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129340&view=auto > > > ============================================================================== > > --- llvm/trunk/runtime/libprofile/LineProfiling.c (added) > > +++ llvm/trunk/runtime/libprofile/LineProfiling.c Mon Apr 11 20:06:09 > 2011 > > @@ -0,0 +1,37 @@ > > +/*===- LineProfiling.c - Support library for line profiling > ---------------===*\ > > +|* > > +|* The LLVM Compiler Infrastructure > > +|* > > +|* This file is distributed under the University of Illinois Open Source > > +|* License. See LICENSE.TXT for details. > > +|* > > > +|*===----------------------------------------------------------------------===*| > > +|* > > +|* This file implements the call back routines for the line profiling > > +|* instrumentation pass. Link against this library when running code > through > > +|* the -insert-line-profiling LLVM pass. > > +|* > > > +\*===----------------------------------------------------------------------===*/ > > + > > +#include > > +#include > > +#include > > + > > +/* A file in this case is a translation unit. Each .o file built with > line > > + * profiling enabled will emit to a different file. Only one file may be > > + * started at a time. > > + */ > > +void llvm_prof_linectr_start_file(const char *orig_filename) { > > + printf("[%s]\n", orig_filename); > > +} > > + > > +/* Emit data about a counter to the data file. */ > > +void llvm_prof_linectr_emit_counter(const char *dir, const char *file, > > + uint32_t line, uint32_t column, > > + int64_t *counter) { > > + printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); > > +} > > + > > +void llvm_prof_linectr_end_file() { > > + printf("-----\n"); > > +} > > > > Modified: llvm/trunk/runtime/libprofile/libprofile.exports > > URL: > http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/libprofile.exports?rev=129340&r1=129339&r2=129340&view=diff > > > ============================================================================== > > --- llvm/trunk/runtime/libprofile/libprofile.exports (original) > > +++ llvm/trunk/runtime/libprofile/libprofile.exports Mon Apr 11 20:06:09 > 2011 > > @@ -5,3 +5,6 @@ > > llvm_trace_basic_block > > llvm_increment_path_count > > llvm_decrement_path_count > > +llvm_prof_linectr_start_file > > +llvm_prof_linectr_emit_counter > > +llvm_prof_linectr_end_file > > > > > > _______________________________________________ > > llvm-commits mailing list > > llvm-commits at cs.uiuc.edu > > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110412/d0385ec8/attachment-0001.html From ofv at wanadoo.es Tue Apr 12 14:40:35 2011 From: ofv at wanadoo.es (Oscar Fuentes) Date: Tue, 12 Apr 2011 19:40:35 -0000 Subject: [llvm-commits] [llvm] r129381 - in /llvm/trunk/docs: CMake.html WritingAnLLVMPass.html Message-ID: <20110412194036.0A51E2A6C12D@llvm.org> Author: ofv Date: Tue Apr 12 14:40:35 2011 New Revision: 129381 URL: http://llvm.org/viewvc/llvm-project?rev=129381&view=rev Log: Document how to build a LLVM pass with CMake out of source. Patch by arrowdodger! Modified: llvm/trunk/docs/CMake.html llvm/trunk/docs/WritingAnLLVMPass.html Modified: llvm/trunk/docs/CMake.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CMake.html?rev=129381&r1=129380&r2=129381&view=diff ============================================================================== --- llvm/trunk/docs/CMake.html (original) +++ llvm/trunk/docs/CMake.html Tue Apr 12 14:40:35 2011 @@ -22,6 +22,9 @@
  • Executing the test suite
  • Cross compiling
  • Embedding LLVM in your project +
  • Compiler/Platform specific topics
    • Microsoft Visual C++
    • @@ -458,6 +461,61 @@ + + + +
      + +

      It is possible to develop LLVM passes against installed LLVM. + An example of project layout provided below:

      + +
      +
      +      <project dir>/
      +          |
      +          CMakeLists.txt
      +          <pass name>/
      +              |
      +              CMakeLists.txt
      +              Pass.cpp
      +              ...
      +    
      +
      + +

      Contents of <project dir>/CMakeLists.txt:

      + +
      +
      +    find_package(LLVM)
      +
      +    # Define add_llvm_* macro's.
      +    include(AddLLVM)
      +
      +    add_definitions(${LLVM_DEFINITIONS})
      +    include_directories(${LLVM_INCLUDE_DIRS})
      +    link_directories(${LLVM_LIBRARY_DIRS})
      +
      +    add_subdirectory(<pass name>)
      +    
      +
      + +

      Contents of <project dir>/<pass name>/CMakeLists.txt:

      + +
      +
      +    add_llvm_loadable_module(LLVMPassname
      +      Pass.cpp
      +      )
      +    
      +
      + +

      When you are done developing your pass, you may wish to integrate it + into LLVM source tree. You can achieve it in two easy steps:
      + 1. Copying <pass name> folder into <LLVM root>/lib/Transform directory.
      + 2. Adding "add_subdirectory(<pass name>)" line into <LLVM root>/lib/Transform/CMakeLists.txt

      +
      Modified: llvm/trunk/docs/WritingAnLLVMPass.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/WritingAnLLVMPass.html?rev=129381&r1=129380&r2=129381&view=diff ============================================================================== --- llvm/trunk/docs/WritingAnLLVMPass.html (original) +++ llvm/trunk/docs/WritingAnLLVMPass.html Tue Apr 12 14:40:35 2011 @@ -211,6 +211,9 @@ If your operating system uses a suffix other than .so (such as windows or Mac OS/X), the appropriate extension will be used.

      +

      If you are used CMake to build LLVM, see +Developing an LLVM pass with CMake.

      +

      Now that we have the build scripts set up, we just need to write the code for the pass itself.

      From mclow.lists at gmail.com Tue Apr 12 14:47:20 2011 From: mclow.lists at gmail.com (Marshall Clow) Date: Tue, 12 Apr 2011 12:47:20 -0700 Subject: [llvm-commits] [llvm] r129340 - in /llvm/trunk: include/llvm/InitializePasses.h include/llvm/LinkAllPasses.h include/llvm/Transforms/Instrumentation.h lib/Transforms/Instrumentation/Instrumentation.cpp lib/Transforms/Instrumentation/LineProfiling In-Reply-To: References: Message-ID: <7D0507F0-7161-4C64-8EA7-614891C1E05A@gmail.com> On Apr 12, 2011, at 12:41 PM, Nick Lewycky wrote: > On 12 April 2011 08:55, Jim Grosbach wrote: > Hi Nick, > > clang is issuing a warning for this. Mind having a look? > > Sorry! I meant for counter to be a uint64_t, and updated that. Neither gcc nor clang warned when I built it this time, but I could imagine that it still might on a different platform. Let me know if it's not fixed past r129380. > > Nick > > > llvm[2]: Compiling LineProfiling.c for Debug+Asserts build (PIC) > /Volumes/Home/grosbaj/sources/llvm/runtime/libprofile/LineProfiling.c:32:25: warning: > conversion specifies type 'unsigned long' but the argument has type > 'int64_t' (aka 'long long') [-Wformat] > printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); > ~~^ ~~~~~~~~ > %lld > 1 warning generated. > > (highlighting points to the "%lu" and "*counter" inputs) Should the specifier in the printf be "%ull" (or maybe "%llu") to match the "unsigned long long"-ness of counter? -- Marshall -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110412/fce28a25/attachment.html From stoklund at 2pi.dk Tue Apr 12 14:51:39 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 12 Apr 2011 12:51:39 -0700 Subject: [llvm-commits] Source register same as write-back base In-Reply-To: <88D727341410A44C9E34E8E3EF37D8ED0427A419@be25.exg3.exghost.com> References: <88D727341410A44C9E34E8E3EF37D8ED04213C3E@be25.exg3.exghost.com> <12BD8D01-BDE4-4E21-8608-A24EFF90A48C@apple.com> <88D727341410A44C9E34E8E3EF37D8ED0427A419@be25.exg3.exghost.com> Message-ID: On Apr 12, 2011, at 11:36 AM, Joe Abbey wrote: > Yes this is the same restriction as armV5 MUL, and it is likely the case > that all hardware implementations behave correctly. > > However, this restriction is documented in ARMv5 & ARMv7: > > DD101001 A4.1.99 > If specifies base register write-back, and the same > register is specified for and , the results are UNPREDICTABLE. > > DDI0406B A8.6.194 > if wback && (n == 15 || n == t) then UNPREDICTABLE; > > I see that in ARMInstrInfo.td MULv5 considers $Rd to be earlyclobber. > > Could a similar pattern of making $Rt earlyclobber be applied in the > store instrucitons? Yes, it could. However, that would cause the fast register allocator to take the slow path for store instructions, and as you can imagine, they are prevalent in debug code. I would rather not slow down register allocation in order to work around a problem that only shows up as an assembler warning. What kind of code is producing this instruction? It seems odd to store a pointer to itself: *p++ = p; /jakob From nlewycky at google.com Tue Apr 12 14:52:25 2011 From: nlewycky at google.com (Nick Lewycky) Date: Tue, 12 Apr 2011 12:52:25 -0700 Subject: [llvm-commits] [llvm] r129340 - in /llvm/trunk: include/llvm/InitializePasses.h include/llvm/LinkAllPasses.h include/llvm/Transforms/Instrumentation.h lib/Transforms/Instrumentation/Instrumentation.cpp lib/Transforms/Instrumentation/LineProfiling In-Reply-To: <7D0507F0-7161-4C64-8EA7-614891C1E05A@gmail.com> References: <7D0507F0-7161-4C64-8EA7-614891C1E05A@gmail.com> Message-ID: On 12 April 2011 12:47, Marshall Clow wrote: > On Apr 12, 2011, at 12:41 PM, Nick Lewycky wrote: > > On 12 April 2011 08:55, Jim Grosbach wrote: > >> Hi Nick, >> >> clang is issuing a warning for this. Mind having a look? >> > > Sorry! I meant for counter to be a uint64_t, and updated that. Neither gcc > nor clang warned when I built it this time, but I could imagine that it > still might on a different platform. Let me know if it's not fixed past > r129380. > > Nick > > >> >> llvm[2]: Compiling LineProfiling.c for Debug+Asserts build (PIC) >> /Volumes/Home/grosbaj/sources/llvm/runtime/libprofile/LineProfiling.c:32:25: >> warning: >> conversion specifies type 'unsigned long' but the argument has type >> 'int64_t' (aka 'long long') [-Wformat] >> printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); >> ~~^ ~~~~~~~~ >> %lld >> 1 warning generated. >> >> (highlighting points to the "%lu" and "*counter" inputs) > > > Should the specifier in the printf be "%ull" (or maybe "%llu") to match the > "unsigned long long"-ness of counter? > Only on 32-bit platforms. Would you rather I used PRIu64? Will that work on all platforms LLVM supports, or do I need to add it to DataTypes.h myself? Does Windows have inttypes.h? Nick -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110412/a23384ad/attachment.html From evan.cheng at apple.com Tue Apr 12 14:50:28 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 12 Apr 2011 19:50:28 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r129382 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Message-ID: <20110412195028.3C4E42A6C12D@llvm.org> Author: evancheng Date: Tue Apr 12 14:50:28 2011 New Revision: 129382 URL: http://llvm.org/viewvc/llvm-project?rev=129382&view=rev Log: Attempt to unbreak Fortran (and other non-c languages) llvm-gcc builds. Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=129382&r1=129381&r2=129382&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Tue Apr 12 14:50:28 2011 @@ -71,7 +71,12 @@ #include "langhooks.h" #include "cgraph.h" #include "params.h" -#include "c-common.h" + +// These are defined in c-common.c. The weak symbols are for linking non-c +// compilers. +int flag_no_builtin __attribute__ ((__weak__)) = 0; +int builtin_function_disabled_p(const char *name) __attribute__ ((__weak__)); +int builtin_function_disabled_p(const char *name) { return 0; } } // Non-zero if bytecode from PCH is successfully read. @@ -662,6 +667,7 @@ CodeGenPasses = 0; } + static void createPerFunctionOptimizationPasses() { if (PerFunctionPasses) return; From evan.cheng at apple.com Tue Apr 12 14:55:36 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Tue, 12 Apr 2011 12:55:36 -0700 Subject: [llvm-commits] [llvm-gcc-4.2] r129344 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp In-Reply-To: References: <20110412021741.C5BB52A6C12D@llvm.org> <4DA40199.4050302@free.fr> Message-ID: I can't verify this. But hopefully r129382 would fix it. Evan On Apr 12, 2011, at 11:51 AM, Evan Cheng wrote: > Crap. I forgot about non-C compilers. I'll take a look. > > Evan > > On Apr 12, 2011, at 12:39 AM, Duncan Sands wrote: > >> Hi Evan, >> >>> Disable loop idiom recognition if -fno-builtin-* options are specified. rdar://9268471 >> >> from http://google1.osuosl.org:8011/builders/llvm-x86_64-linux-checks >> >> /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/./prev-gcc/xgcc -B/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/./prev-gcc/ >> -B/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.install/x86_64-pc-linux-gnu/bin/ >> -c -g -O2 -DIN_GCC -W -Wall -Wwrite-strings -Wstrict-prototypes >> -Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros >> -Wno-overlength-strings -Wold-style-definition -Wmissing-format-attribute >> -DHAVE_CONFIG_H -I. -I. -I../../llvm-gcc.src/gcc -I../../llvm-gcc.src/gcc/. >> -I../../llvm-gcc.src/gcc/../include -I../../llvm-gcc.src/gcc/../libcpp/include >> -I/opt/cfarm/gmp/include -I/opt/cfarm/mpfr/include >> -I../../llvm-gcc.src/gcc/../libdecnumber -I../libdecnumber >> -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.obj/include >> -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.src/include >> -DENABLE_LLVM >> -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.src/include >> -I/home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm.obj/include >> -D_DEBUG -D_GLIBCXX_DEBUG -DXDEBUG -D_GNU_SOURCE -D__STDC_LIMIT_MACROS >> -D__STDC_CONSTANT_MACROS cc1-checksum.c -o cc1-checksum.o >> libbackend.a(llvm-backend.o): In function `createPerFunctionOptimizationPasses': >> /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:678: >> undefined reference to `flag_no_builtin' >> /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:681: >> undefined reference to `builtin_function_disabled_p' >> /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:683: >> undefined reference to `builtin_function_disabled_p' >> libbackend.a(llvm-backend.o): In function `createPerModuleOptimizationPasses': >> /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:762: >> undefined reference to `flag_no_builtin' >> /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:765: >> undefined reference to `builtin_function_disabled_p' >> /home/baldrick/osuosl/slave/llvm-x86_64-linux-checks/llvm-gcc.obj/gcc/../../llvm-gcc.src/gcc/llvm-backend.cpp:767: >> undefined reference to `builtin_function_disabled_p' >> collect2: ld returned 1 exit status >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From atrick at apple.com Tue Apr 12 14:54:36 2011 From: atrick at apple.com (Andrew Trick) Date: Tue, 12 Apr 2011 19:54:36 -0000 Subject: [llvm-commits] [llvm] r129383 - in /llvm/trunk: lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp test/CodeGen/ARM/memcpy-inline.ll test/CodeGen/ARM/vfp.ll Message-ID: <20110412195436.F26992A6C12D@llvm.org> Author: atrick Date: Tue Apr 12 14:54:36 2011 New Revision: 129383 URL: http://llvm.org/viewvc/llvm-project?rev=129383&view=rev Log: PreRA scheduler heuristic fixes: VRegCycle, TokenFactor latency. UnitsSharePred was a source of randomness in the scheduler: node priority depended on the queue data structure. I rewrote the recent VRegCycle heuristics to completely replace the old heuristic without any randomness. To make these heuristic adjustments to node latency work, I also needed to do something a little more reasonable with TokenFactor. I gave it zero latency to its consumers and always schedule it as low as possible. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll llvm/trunk/test/CodeGen/ARM/vfp.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=129383&r1=129382&r2=129383&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Tue Apr 12 14:54:36 2011 @@ -102,11 +102,11 @@ #ifndef NDEBUG namespace { // For sched=list-ilp, Count the number of times each factor comes into play. - enum { FactPressureDiff, FactRegUses, FactHeight, FactDepth, FactStatic, - FactOther, NumFactors }; + enum { FactPressureDiff, FactRegUses, FactStall, FactHeight, FactDepth, + FactStatic, FactOther, NumFactors }; } static const char *FactorName[NumFactors] = -{"PressureDiff", "RegUses", "Height", "Depth","Static", "Other"}; +{"PressureDiff", "RegUses", "Stall", "Height", "Depth","Static", "Other"}; static int FactorCount[NumFactors]; #endif //!NDEBUG @@ -463,6 +463,13 @@ if (DisableSchedCycles) return; + // FIXME: Nodes such as CopyFromReg probably should not advance the current + // cycle. Otherwise, we can wrongly mask real stalls. If the non-machine node + // has predecessors the cycle will be advanced when they are scheduled. + // But given the crude nature of modeling latency though such nodes, we + // currently need to treat these nodes like real instructions. + // if (!SU->getNode() || !SU->getNode()->isMachineOpcode()) return; + unsigned ReadyCycle = isBottomUp ? SU->getHeight() : SU->getDepth(); // Bump CurCycle to account for latency. We assume the latency of other @@ -533,16 +540,19 @@ } } +static void resetVRegCycle(SUnit *SU); + /// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending /// count of its predecessors. If a predecessor pending count is zero, add it to /// the Available queue. void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) { - DEBUG(dbgs() << "\n*** Scheduling [" << CurCycle << "]: "); + DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: "); DEBUG(SU->dump(this)); #ifndef NDEBUG if (CurCycle < SU->getHeight()) - DEBUG(dbgs() << " Height [" << SU->getHeight() << "] pipeline stall!\n"); + DEBUG(dbgs() << " Height [" << SU->getHeight() + << "] pipeline stall!\n"); #endif // FIXME: Do not modify node height. It may interfere with @@ -559,7 +569,7 @@ AvailableQueue->ScheduledNode(SU); // If HazardRec is disabled, and each inst counts as one cycle, then - // advance CurCycle before ReleasePredecessors to avoid useles pushed to + // advance CurCycle before ReleasePredecessors to avoid useless pushes to // PendingQueue for schedulers that implement HasReadyFilter. if (!HazardRec->isEnabled() && AvgIPC < 2) AdvanceToCycle(CurCycle + 1); @@ -580,20 +590,25 @@ } } + resetVRegCycle(SU); + SU->isScheduled = true; // Conditions under which the scheduler should eagerly advance the cycle: // (1) No available instructions // (2) All pipelines full, so available instructions must have hazards. // - // If HazardRec is disabled, the cycle was advanced earlier. + // If HazardRec is disabled, the cycle was pre-advanced before calling + // ReleasePredecessors. In that case, IssueCount should remain 0. // // Check AvailableQueue after ReleasePredecessors in case of zero latency. - ++IssueCount; - if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) - || (!HazardRec->isEnabled() && AvgIPC > 1 && IssueCount == AvgIPC) - || AvailableQueue->empty()) - AdvanceToCycle(CurCycle + 1); + if (HazardRec->isEnabled() || AvgIPC > 1) { + if (SU->getNode() && SU->getNode()->isMachineOpcode()) + ++IssueCount; + if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) + || (!HazardRec->isEnabled() && IssueCount == AvgIPC)) + AdvanceToCycle(CurCycle + 1); + } } /// CapturePred - This does the opposite of ReleasePred. Since SU is being @@ -1220,7 +1235,7 @@ // priority. If it is not ready put it back. Schedule the node. Sequence.reserve(SUnits.size()); while (!AvailableQueue->empty()) { - DEBUG(dbgs() << "\n*** Examining Available\n"; + DEBUG(dbgs() << "Examining Available:\n"; AvailableQueue->dump(this)); // Pick the best node to schedule taking all constraints into @@ -1661,17 +1676,6 @@ CalcNodeSethiUllmanNumber(&(*SUnits)[i], SethiUllmanNumbers); } -void RegReductionPQBase::initNodes(std::vector &sunits) { - SUnits = &sunits; - // Add pseudo dependency edges for two-address nodes. - AddPseudoTwoAddrDeps(); - // Reroute edges to nodes with multiple uses. - if (!TracksRegPressure) - PrescheduleNodesWithMultipleUses(); - // Calculate node priorities. - CalculateSethiUllmanNumbers(); -} - void RegReductionPQBase::addNode(const SUnit *SU) { unsigned SUSize = SethiUllmanNumbers.size(); if (SUnits->size() > SUSize) @@ -2008,7 +2012,29 @@ return Scratches; } -/// hasOnlyLiveOutUse - Return true if SU has a single value successor that is a +/// hasOnlyLiveInOpers - Return true if SU has only value predecessors that are +/// CopyFromReg from a virtual register. +static bool hasOnlyLiveInOpers(const SUnit *SU) { + bool RetVal = false; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; + const SUnit *PredSU = I->getSUnit(); + if (PredSU->getNode() && + PredSU->getNode()->getOpcode() == ISD::CopyFromReg) { + unsigned Reg = + cast(PredSU->getNode()->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + RetVal = true; + continue; + } + } + return false; + } + return RetVal; +} + +/// hasOnlyLiveOutUses - Return true if SU has only value successors that are /// CopyToReg to a virtual register. This SU def is probably a liveout and /// it has no other use. It should be scheduled closer to the terminator. static bool hasOnlyLiveOutUses(const SUnit *SU) { @@ -2030,62 +2056,71 @@ return RetVal; } -/// UnitsSharePred - Return true if the two scheduling units share a common -/// data predecessor. -static bool UnitsSharePred(const SUnit *left, const SUnit *right) { - SmallSet Preds; - for (SUnit::const_pred_iterator I = left->Preds.begin(),E = left->Preds.end(); +// Set isVRegCycle for a node with only live in opers and live out uses. Also +// set isVRegCycle for its CopyFromReg operands. +// +// This is only relevant for single-block loops, in which case the VRegCycle +// node is likely an induction variable in which the operand and target virtual +// registers should be coalesced (e.g. pre/post increment values). Setting the +// isVRegCycle flag helps the scheduler prioritize other uses of the same +// CopyFromReg so that this node becomes the virtual register "kill". This +// avoids interference between the values live in and out of the block and +// eliminates a copy inside the loop. +static void initVRegCycle(SUnit *SU) { + if (DisableSchedVRegCycle) + return; + + if (!hasOnlyLiveInOpers(SU) || !hasOnlyLiveOutUses(SU)) + return; + + DEBUG(dbgs() << "VRegCycle: SU(" << SU->NodeNum << ")\n"); + + SU->isVRegCycle = true; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); I != E; ++I) { - if (I->isCtrl()) continue; // ignore chain preds - Preds.insert(I->getSUnit()); + if (I->isCtrl()) continue; + I->getSUnit()->isVRegCycle = true; } - for (SUnit::const_pred_iterator I = right->Preds.begin(),E = right->Preds.end(); +} + +// After scheduling the definition of a VRegCycle, clear the isVRegCycle flag of +// CopyFromReg operands. We should no longer penalize other uses of this VReg. +static void resetVRegCycle(SUnit *SU) { + if (!SU->isVRegCycle) + return; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); I != E; ++I) { if (I->isCtrl()) continue; // ignore chain preds - if (Preds.count(I->getSUnit())) - return true; + SUnit *PredSU = I->getSUnit(); + if (PredSU->isVRegCycle) { + assert(PredSU->getNode()->getOpcode() == ISD::CopyFromReg && + "VRegCycle def must be CopyFromReg"); + I->getSUnit()->isVRegCycle = 0; + } } - return false; } -// Return true if the virtual register defined by VRCycleSU may interfere with -// VRUseSU. -// -// Note: We may consider two SU's that use the same value live into a loop as -// interferng even though the value is not an induction variable. This is an -// unfortunate consequence of scheduling on the selection DAG. -static bool checkVRegCycleInterference(const SUnit *VRCycleSU, - const SUnit *VRUseSU) { - for (SUnit::const_pred_iterator I = VRCycleSU->Preds.begin(), - E = VRCycleSU->Preds.end(); I != E; ++I) { +// Return true if this SUnit uses a CopyFromReg node marked as a VRegCycle. This +// means a node that defines the VRegCycle has not been scheduled yet. +static bool hasVRegCycleUse(const SUnit *SU) { + // If this SU also defines the VReg, don't hoist it as a "use". + if (SU->isVRegCycle) + return false; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); + I != E; ++I) { if (I->isCtrl()) continue; // ignore chain preds - SDNode *InNode = I->getSUnit()->getNode(); - if (!InNode || InNode->getOpcode() != ISD::CopyFromReg) - continue; - for (SUnit::const_pred_iterator II = VRUseSU->Preds.begin(), - EE = VRUseSU->Preds.end(); II != EE; ++II) { - if (II->getSUnit() == I->getSUnit()) - return true; + if (I->getSUnit()->isVRegCycle && + I->getSUnit()->getNode()->getOpcode() == ISD::CopyFromReg) { + DEBUG(dbgs() << " VReg cycle use: SU (" << SU->NodeNum << ")\n"); + return true; } } return false; } -// Compare the VRegCycle properties of the nodes. -// Return -1 if left has higher priority, 1 if right has higher priority. -// Return 0 if priority is equivalent. -static int BUCompareVRegCycle(const SUnit *left, const SUnit *right) { - if (left->isVRegCycle && !right->isVRegCycle) { - if (checkVRegCycleInterference(left, right)) - return -1; - } - else if (!left->isVRegCycle && right->isVRegCycle) { - if (checkVRegCycleInterference(right, left)) - return 1; - } - return 0; -} - // Check for either a dependence (latency) or resource (hazard) stall. // // Note: The ScheduleHazardRecognizer interface requires a non-const SU. @@ -2101,23 +2136,12 @@ // Return 0 if latency-based priority is equivalent. static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, RegReductionPQBase *SPQ) { - // If the two nodes share an operand and one of them has a single - // use that is a live out copy, favor the one that is live out. Otherwise - // it will be difficult to eliminate the copy if the instruction is a - // loop induction variable update. e.g. - // BB: - // sub r1, r3, #1 - // str r0, [r2, r3] - // mov r3, r1 - // cmp - // bne BB - bool SharePred = UnitsSharePred(left, right); - // FIXME: Only adjust if BB is a loop back edge. - // FIXME: What's the cost of a copy? - int LBonus = (SharePred && hasOnlyLiveOutUses(left)) ? 1 : 0; - int RBonus = (SharePred && hasOnlyLiveOutUses(right)) ? 1 : 0; - int LHeight = (int)left->getHeight() - LBonus; - int RHeight = (int)right->getHeight() - RBonus; + // Scheduling an instruction that uses a VReg whose postincrement has not yet + // been scheduled will induce a copy. Model this as an extra cycle of latency. + int LPenalty = hasVRegCycleUse(left) ? 1 : 0; + int RPenalty = hasVRegCycleUse(right) ? 1 : 0; + int LHeight = (int)left->getHeight() + LPenalty; + int RHeight = (int)right->getHeight() + RPenalty; bool LStall = (!checkPref || left->SchedulingPref == Sched::Latency) && BUHasStall(left, LHeight, SPQ); @@ -2128,36 +2152,47 @@ // If scheduling either one of the node will cause a pipeline stall, sort // them according to their height. if (LStall) { - if (!RStall) + if (!RStall) { + DEBUG(++FactorCount[FactStall]); return 1; - if (LHeight != RHeight) + } + if (LHeight != RHeight) { + DEBUG(++FactorCount[FactStall]); return LHeight > RHeight ? 1 : -1; - } else if (RStall) + } + } else if (RStall) { + DEBUG(++FactorCount[FactStall]); return -1; + } // If either node is scheduling for latency, sort them by height/depth // and latency. if (!checkPref || (left->SchedulingPref == Sched::Latency || right->SchedulingPref == Sched::Latency)) { if (DisableSchedCycles) { - if (LHeight != RHeight) + if (LHeight != RHeight) { + DEBUG(++FactorCount[FactHeight]); return LHeight > RHeight ? 1 : -1; + } } else { // If neither instruction stalls (!LStall && !RStall) then // its height is already covered so only its depth matters. We also reach // this if both stall but have the same height. - unsigned LDepth = left->getDepth(); - unsigned RDepth = right->getDepth(); + int LDepth = left->getDepth() - LPenalty; + int RDepth = right->getDepth() - RPenalty; if (LDepth != RDepth) { + DEBUG(++FactorCount[FactDepth]); DEBUG(dbgs() << " Comparing latency of SU (" << left->NodeNum << ") depth " << LDepth << " vs SU (" << right->NodeNum << ") depth " << RDepth << "\n"); return LDepth < RDepth ? 1 : -1; } } - if (left->Latency != right->Latency) + if (left->Latency != right->Latency) { + DEBUG(++FactorCount[FactOther]); return left->Latency > right->Latency ? 1 : -1; + } } return 0; } @@ -2169,7 +2204,19 @@ DEBUG(++FactorCount[FactStatic]); return LPriority > RPriority; } - DEBUG(++FactorCount[FactOther]); + else if(LPriority == 0) { + // Schedule zero-latency TokenFactor below any other special + // nodes. The alternative may be to avoid artificially boosting the + // TokenFactor's height when it is scheduled, but we currently rely on an + // instruction's final height to equal the cycle in which it is scheduled, + // so heights are monotonically increasing. + unsigned LOpc = left->getNode() ? left->getNode()->getOpcode() : 0; + unsigned ROpc = right->getNode() ? right->getNode()->getOpcode() : 0; + if (LOpc == ISD::TokenFactor) + return false; + if (ROpc == ISD::TokenFactor) + return true; + } // Try schedule def + use closer when Sethi-Ullman numbers are the same. // e.g. @@ -2190,14 +2237,18 @@ // This creates more short live intervals. unsigned LDist = closestSucc(left); unsigned RDist = closestSucc(right); - if (LDist != RDist) + if (LDist != RDist) { + DEBUG(++FactorCount[FactOther]); return LDist < RDist; + } // How many registers becomes live when the node is scheduled. unsigned LScratch = calcMaxScratches(left); unsigned RScratch = calcMaxScratches(right); - if (LScratch != RScratch) + if (LScratch != RScratch) { + DEBUG(++FactorCount[FactOther]); return LScratch > RScratch; + } if (!DisableSchedCycles) { int result = BUCompareLatency(left, right, false /*checkPref*/, SPQ); @@ -2205,15 +2256,20 @@ return result > 0; } else { - if (left->getHeight() != right->getHeight()) + if (left->getHeight() != right->getHeight()) { + DEBUG(++FactorCount[FactHeight]); return left->getHeight() > right->getHeight(); + } - if (left->getDepth() != right->getDepth()) + if (left->getDepth() != right->getDepth()) { + DEBUG(++FactorCount[FactDepth]); return left->getDepth() < right->getDepth(); + } } assert(left->NodeQueueId && right->NodeQueueId && "NodeQueueId cannot be zero"); + DEBUG(++FactorCount[FactOther]); return (left->NodeQueueId > right->NodeQueueId); } @@ -2264,24 +2320,22 @@ // Avoid causing spills. If register pressure is high, schedule for // register pressure reduction. if (LHigh && !RHigh) { + DEBUG(++FactorCount[FactPressureDiff]); DEBUG(dbgs() << " pressure SU(" << left->NodeNum << ") > SU(" << right->NodeNum << ")\n"); return true; } else if (!LHigh && RHigh) { + DEBUG(++FactorCount[FactPressureDiff]); DEBUG(dbgs() << " pressure SU(" << right->NodeNum << ") > SU(" << left->NodeNum << ")\n"); return false; } - int result = 0; - if (!DisableSchedVRegCycle) { - result = BUCompareVRegCycle(left, right); - } - if (result == 0 && !LHigh && !RHigh) { - result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); + if (!LHigh && !RHigh) { + int result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); + if (result != 0) + return result > 0; } - if (result != 0) - return result > 0; return BURRSort(left, right, SPQ); } @@ -2347,12 +2401,6 @@ if (RReduce && !LReduce) return true; } - if (!DisableSchedVRegCycle) { - int result = BUCompareVRegCycle(left, right); - if (result != 0) - return result > 0; - } - if (!DisableSchedLiveUses && (LLiveUses != RLiveUses)) { DEBUG(dbgs() << "Live uses SU(" << left->NodeNum << "): " << LLiveUses << " != SU(" << right->NodeNum << "): " << RLiveUses << "\n"); @@ -2391,6 +2439,24 @@ return BURRSort(left, right, SPQ); } +void RegReductionPQBase::initNodes(std::vector &sunits) { + SUnits = &sunits; + // Add pseudo dependency edges for two-address nodes. + AddPseudoTwoAddrDeps(); + // Reroute edges to nodes with multiple uses. + if (!TracksRegPressure) + PrescheduleNodesWithMultipleUses(); + // Calculate node priorities. + CalculateSethiUllmanNumbers(); + + // For single block loops, mark nodes that look like canonical IV increments. + if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB)) { + for (unsigned i = 0, e = sunits.size(); i != e; ++i) { + initVRegCycle(&sunits[i]); + } + } +} + //===----------------------------------------------------------------------===// // Preschedule for Register Pressure //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=129383&r1=129382&r2=129383&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Tue Apr 12 14:54:36 2011 @@ -342,10 +342,6 @@ assert(N->getNodeId() == -1 && "Node already inserted!"); N->setNodeId(NodeSUnit->NodeNum); - // Set isVRegCycle if the node operands are live into and value is live out - // of a single block loop. - InitVRegCycleFlag(NodeSUnit); - // Compute NumRegDefsLeft. This must be done before AddSchedEdges. InitNumRegDefsLeft(NodeSUnit); @@ -416,7 +412,13 @@ PhysReg = 0; // If this is a ctrl dep, latency is 1. - unsigned OpLatency = isChain ? 1 : OpSU->Latency; + // Special-case TokenFactor chains as zero-latency. + unsigned OpLatency = 1; + if (!isChain && OpSU->Latency > 0) + OpLatency = OpSU->Latency; + else if(isChain && OpN->getOpcode() == ISD::TokenFactor) + OpLatency = 0; + const SDep &dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data, OpLatency, PhysReg); if (!isChain && !UnitLatencies) { @@ -512,47 +514,6 @@ } } -// Set isVRegCycle if this node's single use is CopyToReg and its only active -// data operands are CopyFromReg. -// -// This is only relevant for single-block loops, in which case the VRegCycle -// node is likely an induction variable in which the operand and target virtual -// registers should be coalesced (e.g. pre/post increment values). Setting the -// isVRegCycle flag helps the scheduler prioritize other uses of the same -// CopyFromReg so that this node becomes the virtual register "kill". This -// avoids interference between the values live in and out of the block and -// eliminates a copy inside the loop. -void ScheduleDAGSDNodes::InitVRegCycleFlag(SUnit *SU) { - if (!BB->isSuccessor(BB)) - return; - - SDNode *N = SU->getNode(); - if (N->getGluedNode()) - return; - - if (!N->hasOneUse() || N->use_begin()->getOpcode() != ISD::CopyToReg) - return; - - bool FoundLiveIn = false; - for (SDNode::op_iterator OI = N->op_begin(), E = N->op_end(); OI != E; ++OI) { - EVT OpVT = OI->getValueType(); - assert(OpVT != MVT::Glue && "Glued nodes should be in same sunit!"); - - if (OpVT == MVT::Other) - continue; // ignore chain operands - - if (isPassiveNode(OI->getNode())) - continue; // ignore constants and such - - if (OI->getNode()->getOpcode() != ISD::CopyFromReg) - return; - - FoundLiveIn = true; - } - if (FoundLiveIn) - SU->isVRegCycle = true; -} - void ScheduleDAGSDNodes::InitNumRegDefsLeft(SUnit *SU) { assert(SU->NumRegDefsLeft == 0 && "expect a new node"); for (RegDefIter I(SU, this); I.IsValid(); I.Advance()) { Modified: llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll?rev=129383&r1=129382&r2=129383&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll (original) +++ llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll Tue Apr 12 14:54:36 2011 @@ -1,10 +1,8 @@ -; RUN: llc < %s -mtriple=arm-apple-darwin -regalloc=linearscan -disable-post-ra | FileCheck %s -; RUN: llc < %s -mtriple=arm-apple-darwin -regalloc=basic -disable-post-ra | FileCheck %s +; RUN: llc < %s -mtriple=thumbv7-apple-darwin -regalloc=linearscan -disable-post-ra | FileCheck %s ; The ARM magic hinting works best with linear scan. -; CHECK: ldmia -; CHECK: stmia -; CHECK: ldrh +; CHECK: ldrd +; CHECK: strd ; CHECK: ldrb %struct.x = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 } Modified: llvm/trunk/test/CodeGen/ARM/vfp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vfp.ll?rev=129383&r1=129382&r2=129383&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/vfp.ll (original) +++ llvm/trunk/test/CodeGen/ARM/vfp.ll Tue Apr 12 14:54:36 2011 @@ -40,8 +40,8 @@ define void @test_ext_round(float* %P, double* %D) { ;CHECK: test_ext_round: %a = load float* %P ; [#uses=1] -;CHECK: vcvt.f32.f64 ;CHECK: vcvt.f64.f32 +;CHECK: vcvt.f32.f64 %b = fpext float %a to double ; [#uses=1] %A = load double* %D ; [#uses=1] %B = fptrunc double %A to float ; [#uses=1] From jabbey at arxan.com Tue Apr 12 15:02:12 2011 From: jabbey at arxan.com (Joe Abbey) Date: Tue, 12 Apr 2011 16:02:12 -0400 Subject: [llvm-commits] Source register same as write-back base In-Reply-To: References: <88D727341410A44C9E34E8E3EF37D8ED04213C3E@be25.exg3.exghost.com> <12BD8D01-BDE4-4E21-8608-A24EFF90A48C@apple.com> <88D727341410A44C9E34E8E3EF37D8ED0427A419@be25.exg3.exghost.com> Message-ID: <88D727341410A44C9E34E8E3EF37D8ED0427A46C@be25.exg3.exghost.com> > What kind of code is producing this instruction? It seems odd to store a pointer to itself: > *p++ = p; STL: #include #include using namespace std; int main(void) { list intList; vector > vectorOfLists; vectorOfLists.push_back(intList); return 0; } Built with the following commands: #!/bin/bash echo Assuming Android NDKr5b installed in /opt/android-ndk-r5b-llvm with llvm-gcc toolchain added echo Assuming LLC is in path set -x export PATH=/opt/android-ndk-r5-llvm/toolchains/arm-eabi-4.2.1/prebuilt/darwin- x86/bin/:$PATH #Build bitcode arm-eabi-g++ --emit-llvm -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -D__ANDROID__ -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -fno-exceptions -fno-rtti -O2 -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300 -I/opt/android-ndk-r5b-llvm/sources/cxx-stl/stlport/stlport -I/opt/android-ndk-r5b-llvm/sources/cxx-stl/system/include -DANDROID -Wa,--noexecstack -O2 -DNDEBUG -g -g0 -g0 -I/opt/android-ndk-r5b-llvm/platforms/android-9/arch-arm/usr/include -c test-libstl.cpp -o test-libstl.o #Lower bitcode to arm assembly llc -O0 -relocation-model=pic -enable-local-stack-alloc=false test-libstl.o -o libtest-libstl.so.bc.s #Assemble/link arm-eabi-gcc libtest-libstl.so.bc.s -nostdlib -Wl,-soname,libtest-libstl.so -Wl,-shared,-Bsymbolic /opt/android-ndk-r5b-llvm/platforms/android-9/arch-arm/usr/lib/crtbegin_ so.o libstlport_static.a /opt/android-ndk-r5b-llvm/llvmToolchain/arm-eabi-4.2.1/prebuilt/darwin-x 86/bin/../lib/gcc/arm-eabi/4.2.1/libgcc.a /opt/android-ndk-r5b-llvm/platforms/android-9/arch-arm/usr/lib/libc.so /opt/android-ndk-r5b-llvm/platforms/android-9/arch-arm/usr/lib/libstdc++ .so /opt/android-ndk-r5b-llvm/platforms/android-9/arch-arm/usr/lib/libm.so -Wl,--fix-cortex-a8 -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -Wl,--no-undefined -Wl,-z,noexecstack -L/opt/android-ndk-r5b-llvm/platforms/android-9/arch-arm/usr/lib -lstdc++ -Wl,-rpath-link=/opt/android-ndk-r5b-llvm/platforms/android-9/arch-arm/u sr/lib -lsupc++ /opt/android-ndk-r5b-llvm/platforms/android-9/arch-arm/usr/lib/crtend_so .o -Xlinker -Map -Xlinker libtest-libstl.so.map -o libtest-libstl.so Cheers, Joe From nicholas at mxc.ca Tue Apr 12 15:06:50 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Tue, 12 Apr 2011 20:06:50 -0000 Subject: [llvm-commits] [llvm] r129384 - /llvm/trunk/runtime/libprofile/LineProfiling.c Message-ID: <20110412200650.9C0682A6C12D@llvm.org> Author: nicholas Date: Tue Apr 12 15:06:50 2011 New Revision: 129384 URL: http://llvm.org/viewvc/llvm-project?rev=129384&view=rev Log: Print our uint64_t with the more portable (C99 and C++0x) %PRIu64 format specifier. Modified: llvm/trunk/runtime/libprofile/LineProfiling.c Modified: llvm/trunk/runtime/libprofile/LineProfiling.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129384&r1=129383&r2=129384&view=diff ============================================================================== --- llvm/trunk/runtime/libprofile/LineProfiling.c (original) +++ llvm/trunk/runtime/libprofile/LineProfiling.c Tue Apr 12 15:06:50 2011 @@ -17,6 +17,8 @@ #include #include +#include "llvm/Support/DataTypes.h" + /* A file in this case is a translation unit. Each .o file built with line * profiling enabled will emit to a different file. Only one file may be * started at a time. @@ -29,7 +31,7 @@ void llvm_prof_linectr_emit_counter(const char *dir, const char *file, uint32_t line, uint32_t column, uint64_t *counter) { - printf("%s/%s:%u:%u %lu\n", dir, file, line, column, *counter); + printf("%s/%s:%u:%u %" PRIu64 "\n", dir, file, line, column, *counter); } void llvm_prof_linectr_end_file() { From atrick at apple.com Tue Apr 12 15:14:07 2011 From: atrick at apple.com (Andrew Trick) Date: Tue, 12 Apr 2011 20:14:07 -0000 Subject: [llvm-commits] [llvm] r129385 - in /llvm/trunk: lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp test/CodeGen/ARM/memcpy-inline.ll test/CodeGen/ARM/vfp.ll Message-ID: <20110412201407.D5E202A6C12D@llvm.org> Author: atrick Date: Tue Apr 12 15:14:07 2011 New Revision: 129385 URL: http://llvm.org/viewvc/llvm-project?rev=129385&view=rev Log: Revert 129383. It causes some targets to hit a scheduler assert. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll llvm/trunk/test/CodeGen/ARM/vfp.ll Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=129385&r1=129384&r2=129385&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Tue Apr 12 15:14:07 2011 @@ -102,11 +102,11 @@ #ifndef NDEBUG namespace { // For sched=list-ilp, Count the number of times each factor comes into play. - enum { FactPressureDiff, FactRegUses, FactStall, FactHeight, FactDepth, - FactStatic, FactOther, NumFactors }; + enum { FactPressureDiff, FactRegUses, FactHeight, FactDepth, FactStatic, + FactOther, NumFactors }; } static const char *FactorName[NumFactors] = -{"PressureDiff", "RegUses", "Stall", "Height", "Depth","Static", "Other"}; +{"PressureDiff", "RegUses", "Height", "Depth","Static", "Other"}; static int FactorCount[NumFactors]; #endif //!NDEBUG @@ -463,13 +463,6 @@ if (DisableSchedCycles) return; - // FIXME: Nodes such as CopyFromReg probably should not advance the current - // cycle. Otherwise, we can wrongly mask real stalls. If the non-machine node - // has predecessors the cycle will be advanced when they are scheduled. - // But given the crude nature of modeling latency though such nodes, we - // currently need to treat these nodes like real instructions. - // if (!SU->getNode() || !SU->getNode()->isMachineOpcode()) return; - unsigned ReadyCycle = isBottomUp ? SU->getHeight() : SU->getDepth(); // Bump CurCycle to account for latency. We assume the latency of other @@ -540,19 +533,16 @@ } } -static void resetVRegCycle(SUnit *SU); - /// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending /// count of its predecessors. If a predecessor pending count is zero, add it to /// the Available queue. void ScheduleDAGRRList::ScheduleNodeBottomUp(SUnit *SU) { - DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: "); + DEBUG(dbgs() << "\n*** Scheduling [" << CurCycle << "]: "); DEBUG(SU->dump(this)); #ifndef NDEBUG if (CurCycle < SU->getHeight()) - DEBUG(dbgs() << " Height [" << SU->getHeight() - << "] pipeline stall!\n"); + DEBUG(dbgs() << " Height [" << SU->getHeight() << "] pipeline stall!\n"); #endif // FIXME: Do not modify node height. It may interfere with @@ -569,7 +559,7 @@ AvailableQueue->ScheduledNode(SU); // If HazardRec is disabled, and each inst counts as one cycle, then - // advance CurCycle before ReleasePredecessors to avoid useless pushes to + // advance CurCycle before ReleasePredecessors to avoid useles pushed to // PendingQueue for schedulers that implement HasReadyFilter. if (!HazardRec->isEnabled() && AvgIPC < 2) AdvanceToCycle(CurCycle + 1); @@ -590,25 +580,20 @@ } } - resetVRegCycle(SU); - SU->isScheduled = true; // Conditions under which the scheduler should eagerly advance the cycle: // (1) No available instructions // (2) All pipelines full, so available instructions must have hazards. // - // If HazardRec is disabled, the cycle was pre-advanced before calling - // ReleasePredecessors. In that case, IssueCount should remain 0. + // If HazardRec is disabled, the cycle was advanced earlier. // // Check AvailableQueue after ReleasePredecessors in case of zero latency. - if (HazardRec->isEnabled() || AvgIPC > 1) { - if (SU->getNode() && SU->getNode()->isMachineOpcode()) - ++IssueCount; - if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) - || (!HazardRec->isEnabled() && IssueCount == AvgIPC)) - AdvanceToCycle(CurCycle + 1); - } + ++IssueCount; + if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) + || (!HazardRec->isEnabled() && AvgIPC > 1 && IssueCount == AvgIPC) + || AvailableQueue->empty()) + AdvanceToCycle(CurCycle + 1); } /// CapturePred - This does the opposite of ReleasePred. Since SU is being @@ -1235,7 +1220,7 @@ // priority. If it is not ready put it back. Schedule the node. Sequence.reserve(SUnits.size()); while (!AvailableQueue->empty()) { - DEBUG(dbgs() << "Examining Available:\n"; + DEBUG(dbgs() << "\n*** Examining Available\n"; AvailableQueue->dump(this)); // Pick the best node to schedule taking all constraints into @@ -1676,6 +1661,17 @@ CalcNodeSethiUllmanNumber(&(*SUnits)[i], SethiUllmanNumbers); } +void RegReductionPQBase::initNodes(std::vector &sunits) { + SUnits = &sunits; + // Add pseudo dependency edges for two-address nodes. + AddPseudoTwoAddrDeps(); + // Reroute edges to nodes with multiple uses. + if (!TracksRegPressure) + PrescheduleNodesWithMultipleUses(); + // Calculate node priorities. + CalculateSethiUllmanNumbers(); +} + void RegReductionPQBase::addNode(const SUnit *SU) { unsigned SUSize = SethiUllmanNumbers.size(); if (SUnits->size() > SUSize) @@ -2012,29 +2008,7 @@ return Scratches; } -/// hasOnlyLiveInOpers - Return true if SU has only value predecessors that are -/// CopyFromReg from a virtual register. -static bool hasOnlyLiveInOpers(const SUnit *SU) { - bool RetVal = false; - for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); - I != E; ++I) { - if (I->isCtrl()) continue; - const SUnit *PredSU = I->getSUnit(); - if (PredSU->getNode() && - PredSU->getNode()->getOpcode() == ISD::CopyFromReg) { - unsigned Reg = - cast(PredSU->getNode()->getOperand(1))->getReg(); - if (TargetRegisterInfo::isVirtualRegister(Reg)) { - RetVal = true; - continue; - } - } - return false; - } - return RetVal; -} - -/// hasOnlyLiveOutUses - Return true if SU has only value successors that are +/// hasOnlyLiveOutUse - Return true if SU has a single value successor that is a /// CopyToReg to a virtual register. This SU def is probably a liveout and /// it has no other use. It should be scheduled closer to the terminator. static bool hasOnlyLiveOutUses(const SUnit *SU) { @@ -2056,71 +2030,62 @@ return RetVal; } -// Set isVRegCycle for a node with only live in opers and live out uses. Also -// set isVRegCycle for its CopyFromReg operands. -// -// This is only relevant for single-block loops, in which case the VRegCycle -// node is likely an induction variable in which the operand and target virtual -// registers should be coalesced (e.g. pre/post increment values). Setting the -// isVRegCycle flag helps the scheduler prioritize other uses of the same -// CopyFromReg so that this node becomes the virtual register "kill". This -// avoids interference between the values live in and out of the block and -// eliminates a copy inside the loop. -static void initVRegCycle(SUnit *SU) { - if (DisableSchedVRegCycle) - return; - - if (!hasOnlyLiveInOpers(SU) || !hasOnlyLiveOutUses(SU)) - return; - - DEBUG(dbgs() << "VRegCycle: SU(" << SU->NodeNum << ")\n"); - - SU->isVRegCycle = true; - - for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); +/// UnitsSharePred - Return true if the two scheduling units share a common +/// data predecessor. +static bool UnitsSharePred(const SUnit *left, const SUnit *right) { + SmallSet Preds; + for (SUnit::const_pred_iterator I = left->Preds.begin(),E = left->Preds.end(); I != E; ++I) { - if (I->isCtrl()) continue; - I->getSUnit()->isVRegCycle = true; + if (I->isCtrl()) continue; // ignore chain preds + Preds.insert(I->getSUnit()); } -} - -// After scheduling the definition of a VRegCycle, clear the isVRegCycle flag of -// CopyFromReg operands. We should no longer penalize other uses of this VReg. -static void resetVRegCycle(SUnit *SU) { - if (!SU->isVRegCycle) - return; - - for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); + for (SUnit::const_pred_iterator I = right->Preds.begin(),E = right->Preds.end(); I != E; ++I) { if (I->isCtrl()) continue; // ignore chain preds - SUnit *PredSU = I->getSUnit(); - if (PredSU->isVRegCycle) { - assert(PredSU->getNode()->getOpcode() == ISD::CopyFromReg && - "VRegCycle def must be CopyFromReg"); - I->getSUnit()->isVRegCycle = 0; - } + if (Preds.count(I->getSUnit())) + return true; } + return false; } -// Return true if this SUnit uses a CopyFromReg node marked as a VRegCycle. This -// means a node that defines the VRegCycle has not been scheduled yet. -static bool hasVRegCycleUse(const SUnit *SU) { - // If this SU also defines the VReg, don't hoist it as a "use". - if (SU->isVRegCycle) - return false; - - for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); - I != E; ++I) { +// Return true if the virtual register defined by VRCycleSU may interfere with +// VRUseSU. +// +// Note: We may consider two SU's that use the same value live into a loop as +// interferng even though the value is not an induction variable. This is an +// unfortunate consequence of scheduling on the selection DAG. +static bool checkVRegCycleInterference(const SUnit *VRCycleSU, + const SUnit *VRUseSU) { + for (SUnit::const_pred_iterator I = VRCycleSU->Preds.begin(), + E = VRCycleSU->Preds.end(); I != E; ++I) { if (I->isCtrl()) continue; // ignore chain preds - if (I->getSUnit()->isVRegCycle && - I->getSUnit()->getNode()->getOpcode() == ISD::CopyFromReg) { - DEBUG(dbgs() << " VReg cycle use: SU (" << SU->NodeNum << ")\n"); - return true; + SDNode *InNode = I->getSUnit()->getNode(); + if (!InNode || InNode->getOpcode() != ISD::CopyFromReg) + continue; + for (SUnit::const_pred_iterator II = VRUseSU->Preds.begin(), + EE = VRUseSU->Preds.end(); II != EE; ++II) { + if (II->getSUnit() == I->getSUnit()) + return true; } } return false; } +// Compare the VRegCycle properties of the nodes. +// Return -1 if left has higher priority, 1 if right has higher priority. +// Return 0 if priority is equivalent. +static int BUCompareVRegCycle(const SUnit *left, const SUnit *right) { + if (left->isVRegCycle && !right->isVRegCycle) { + if (checkVRegCycleInterference(left, right)) + return -1; + } + else if (!left->isVRegCycle && right->isVRegCycle) { + if (checkVRegCycleInterference(right, left)) + return 1; + } + return 0; +} + // Check for either a dependence (latency) or resource (hazard) stall. // // Note: The ScheduleHazardRecognizer interface requires a non-const SU. @@ -2136,12 +2101,23 @@ // Return 0 if latency-based priority is equivalent. static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, RegReductionPQBase *SPQ) { - // Scheduling an instruction that uses a VReg whose postincrement has not yet - // been scheduled will induce a copy. Model this as an extra cycle of latency. - int LPenalty = hasVRegCycleUse(left) ? 1 : 0; - int RPenalty = hasVRegCycleUse(right) ? 1 : 0; - int LHeight = (int)left->getHeight() + LPenalty; - int RHeight = (int)right->getHeight() + RPenalty; + // If the two nodes share an operand and one of them has a single + // use that is a live out copy, favor the one that is live out. Otherwise + // it will be difficult to eliminate the copy if the instruction is a + // loop induction variable update. e.g. + // BB: + // sub r1, r3, #1 + // str r0, [r2, r3] + // mov r3, r1 + // cmp + // bne BB + bool SharePred = UnitsSharePred(left, right); + // FIXME: Only adjust if BB is a loop back edge. + // FIXME: What's the cost of a copy? + int LBonus = (SharePred && hasOnlyLiveOutUses(left)) ? 1 : 0; + int RBonus = (SharePred && hasOnlyLiveOutUses(right)) ? 1 : 0; + int LHeight = (int)left->getHeight() - LBonus; + int RHeight = (int)right->getHeight() - RBonus; bool LStall = (!checkPref || left->SchedulingPref == Sched::Latency) && BUHasStall(left, LHeight, SPQ); @@ -2152,47 +2128,36 @@ // If scheduling either one of the node will cause a pipeline stall, sort // them according to their height. if (LStall) { - if (!RStall) { - DEBUG(++FactorCount[FactStall]); + if (!RStall) return 1; - } - if (LHeight != RHeight) { - DEBUG(++FactorCount[FactStall]); + if (LHeight != RHeight) return LHeight > RHeight ? 1 : -1; - } - } else if (RStall) { - DEBUG(++FactorCount[FactStall]); + } else if (RStall) return -1; - } // If either node is scheduling for latency, sort them by height/depth // and latency. if (!checkPref || (left->SchedulingPref == Sched::Latency || right->SchedulingPref == Sched::Latency)) { if (DisableSchedCycles) { - if (LHeight != RHeight) { - DEBUG(++FactorCount[FactHeight]); + if (LHeight != RHeight) return LHeight > RHeight ? 1 : -1; - } } else { // If neither instruction stalls (!LStall && !RStall) then // its height is already covered so only its depth matters. We also reach // this if both stall but have the same height. - int LDepth = left->getDepth() - LPenalty; - int RDepth = right->getDepth() - RPenalty; + unsigned LDepth = left->getDepth(); + unsigned RDepth = right->getDepth(); if (LDepth != RDepth) { - DEBUG(++FactorCount[FactDepth]); DEBUG(dbgs() << " Comparing latency of SU (" << left->NodeNum << ") depth " << LDepth << " vs SU (" << right->NodeNum << ") depth " << RDepth << "\n"); return LDepth < RDepth ? 1 : -1; } } - if (left->Latency != right->Latency) { - DEBUG(++FactorCount[FactOther]); + if (left->Latency != right->Latency) return left->Latency > right->Latency ? 1 : -1; - } } return 0; } @@ -2204,19 +2169,7 @@ DEBUG(++FactorCount[FactStatic]); return LPriority > RPriority; } - else if(LPriority == 0) { - // Schedule zero-latency TokenFactor below any other special - // nodes. The alternative may be to avoid artificially boosting the - // TokenFactor's height when it is scheduled, but we currently rely on an - // instruction's final height to equal the cycle in which it is scheduled, - // so heights are monotonically increasing. - unsigned LOpc = left->getNode() ? left->getNode()->getOpcode() : 0; - unsigned ROpc = right->getNode() ? right->getNode()->getOpcode() : 0; - if (LOpc == ISD::TokenFactor) - return false; - if (ROpc == ISD::TokenFactor) - return true; - } + DEBUG(++FactorCount[FactOther]); // Try schedule def + use closer when Sethi-Ullman numbers are the same. // e.g. @@ -2237,18 +2190,14 @@ // This creates more short live intervals. unsigned LDist = closestSucc(left); unsigned RDist = closestSucc(right); - if (LDist != RDist) { - DEBUG(++FactorCount[FactOther]); + if (LDist != RDist) return LDist < RDist; - } // How many registers becomes live when the node is scheduled. unsigned LScratch = calcMaxScratches(left); unsigned RScratch = calcMaxScratches(right); - if (LScratch != RScratch) { - DEBUG(++FactorCount[FactOther]); + if (LScratch != RScratch) return LScratch > RScratch; - } if (!DisableSchedCycles) { int result = BUCompareLatency(left, right, false /*checkPref*/, SPQ); @@ -2256,20 +2205,15 @@ return result > 0; } else { - if (left->getHeight() != right->getHeight()) { - DEBUG(++FactorCount[FactHeight]); + if (left->getHeight() != right->getHeight()) return left->getHeight() > right->getHeight(); - } - if (left->getDepth() != right->getDepth()) { - DEBUG(++FactorCount[FactDepth]); + if (left->getDepth() != right->getDepth()) return left->getDepth() < right->getDepth(); - } } assert(left->NodeQueueId && right->NodeQueueId && "NodeQueueId cannot be zero"); - DEBUG(++FactorCount[FactOther]); return (left->NodeQueueId > right->NodeQueueId); } @@ -2320,22 +2264,24 @@ // Avoid causing spills. If register pressure is high, schedule for // register pressure reduction. if (LHigh && !RHigh) { - DEBUG(++FactorCount[FactPressureDiff]); DEBUG(dbgs() << " pressure SU(" << left->NodeNum << ") > SU(" << right->NodeNum << ")\n"); return true; } else if (!LHigh && RHigh) { - DEBUG(++FactorCount[FactPressureDiff]); DEBUG(dbgs() << " pressure SU(" << right->NodeNum << ") > SU(" << left->NodeNum << ")\n"); return false; } - if (!LHigh && !RHigh) { - int result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); - if (result != 0) - return result > 0; + int result = 0; + if (!DisableSchedVRegCycle) { + result = BUCompareVRegCycle(left, right); } + if (result == 0 && !LHigh && !RHigh) { + result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); + } + if (result != 0) + return result > 0; return BURRSort(left, right, SPQ); } @@ -2401,6 +2347,12 @@ if (RReduce && !LReduce) return true; } + if (!DisableSchedVRegCycle) { + int result = BUCompareVRegCycle(left, right); + if (result != 0) + return result > 0; + } + if (!DisableSchedLiveUses && (LLiveUses != RLiveUses)) { DEBUG(dbgs() << "Live uses SU(" << left->NodeNum << "): " << LLiveUses << " != SU(" << right->NodeNum << "): " << RLiveUses << "\n"); @@ -2439,24 +2391,6 @@ return BURRSort(left, right, SPQ); } -void RegReductionPQBase::initNodes(std::vector &sunits) { - SUnits = &sunits; - // Add pseudo dependency edges for two-address nodes. - AddPseudoTwoAddrDeps(); - // Reroute edges to nodes with multiple uses. - if (!TracksRegPressure) - PrescheduleNodesWithMultipleUses(); - // Calculate node priorities. - CalculateSethiUllmanNumbers(); - - // For single block loops, mark nodes that look like canonical IV increments. - if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB)) { - for (unsigned i = 0, e = sunits.size(); i != e; ++i) { - initVRegCycle(&sunits[i]); - } - } -} - //===----------------------------------------------------------------------===// // Preschedule for Register Pressure //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=129385&r1=129384&r2=129385&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Tue Apr 12 15:14:07 2011 @@ -342,6 +342,10 @@ assert(N->getNodeId() == -1 && "Node already inserted!"); N->setNodeId(NodeSUnit->NodeNum); + // Set isVRegCycle if the node operands are live into and value is live out + // of a single block loop. + InitVRegCycleFlag(NodeSUnit); + // Compute NumRegDefsLeft. This must be done before AddSchedEdges. InitNumRegDefsLeft(NodeSUnit); @@ -412,13 +416,7 @@ PhysReg = 0; // If this is a ctrl dep, latency is 1. - // Special-case TokenFactor chains as zero-latency. - unsigned OpLatency = 1; - if (!isChain && OpSU->Latency > 0) - OpLatency = OpSU->Latency; - else if(isChain && OpN->getOpcode() == ISD::TokenFactor) - OpLatency = 0; - + unsigned OpLatency = isChain ? 1 : OpSU->Latency; const SDep &dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data, OpLatency, PhysReg); if (!isChain && !UnitLatencies) { @@ -514,6 +512,47 @@ } } +// Set isVRegCycle if this node's single use is CopyToReg and its only active +// data operands are CopyFromReg. +// +// This is only relevant for single-block loops, in which case the VRegCycle +// node is likely an induction variable in which the operand and target virtual +// registers should be coalesced (e.g. pre/post increment values). Setting the +// isVRegCycle flag helps the scheduler prioritize other uses of the same +// CopyFromReg so that this node becomes the virtual register "kill". This +// avoids interference between the values live in and out of the block and +// eliminates a copy inside the loop. +void ScheduleDAGSDNodes::InitVRegCycleFlag(SUnit *SU) { + if (!BB->isSuccessor(BB)) + return; + + SDNode *N = SU->getNode(); + if (N->getGluedNode()) + return; + + if (!N->hasOneUse() || N->use_begin()->getOpcode() != ISD::CopyToReg) + return; + + bool FoundLiveIn = false; + for (SDNode::op_iterator OI = N->op_begin(), E = N->op_end(); OI != E; ++OI) { + EVT OpVT = OI->getValueType(); + assert(OpVT != MVT::Glue && "Glued nodes should be in same sunit!"); + + if (OpVT == MVT::Other) + continue; // ignore chain operands + + if (isPassiveNode(OI->getNode())) + continue; // ignore constants and such + + if (OI->getNode()->getOpcode() != ISD::CopyFromReg) + return; + + FoundLiveIn = true; + } + if (FoundLiveIn) + SU->isVRegCycle = true; +} + void ScheduleDAGSDNodes::InitNumRegDefsLeft(SUnit *SU) { assert(SU->NumRegDefsLeft == 0 && "expect a new node"); for (RegDefIter I(SU, this); I.IsValid(); I.Advance()) { Modified: llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll?rev=129385&r1=129384&r2=129385&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll (original) +++ llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll Tue Apr 12 15:14:07 2011 @@ -1,8 +1,10 @@ -; RUN: llc < %s -mtriple=thumbv7-apple-darwin -regalloc=linearscan -disable-post-ra | FileCheck %s +; RUN: llc < %s -mtriple=arm-apple-darwin -regalloc=linearscan -disable-post-ra | FileCheck %s +; RUN: llc < %s -mtriple=arm-apple-darwin -regalloc=basic -disable-post-ra | FileCheck %s ; The ARM magic hinting works best with linear scan. -; CHECK: ldrd -; CHECK: strd +; CHECK: ldmia +; CHECK: stmia +; CHECK: ldrh ; CHECK: ldrb %struct.x = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 } Modified: llvm/trunk/test/CodeGen/ARM/vfp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vfp.ll?rev=129385&r1=129384&r2=129385&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/vfp.ll (original) +++ llvm/trunk/test/CodeGen/ARM/vfp.ll Tue Apr 12 15:14:07 2011 @@ -40,8 +40,8 @@ define void @test_ext_round(float* %P, double* %D) { ;CHECK: test_ext_round: %a = load float* %P ; [#uses=1] -;CHECK: vcvt.f64.f32 ;CHECK: vcvt.f32.f64 +;CHECK: vcvt.f64.f32 %b = fpext float %a to double ; [#uses=1] %A = load double* %D ; [#uses=1] %B = fptrunc double %A to float ; [#uses=1] From kledzik at apple.com Tue Apr 12 16:11:47 2011 From: kledzik at apple.com (Nick Kledzik) Date: Tue, 12 Apr 2011 21:11:47 -0000 Subject: [llvm-commits] [compiler-rt] r129386 - /compiler-rt/trunk/lib/apple_versioning.c Message-ID: <20110412211147.6C4582A6C12D@llvm.org> Author: kledzik Date: Tue Apr 12 16:11:47 2011 New Revision: 129386 URL: http://llvm.org/viewvc/llvm-project?rev=129386&view=rev Log: update version info for arm Modified: compiler-rt/trunk/lib/apple_versioning.c Modified: compiler-rt/trunk/lib/apple_versioning.c URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/apple_versioning.c?rev=129386&r1=129385&r2=129386&view=diff ============================================================================== --- compiler-rt/trunk/lib/apple_versioning.c (original) +++ compiler-rt/trunk/lib/apple_versioning.c Tue Apr 12 16:11:47 2011 @@ -143,6 +143,147 @@ NOT_HERE_BEFORE_10_6(__trampoline_setup) #endif /* __ppc__ */ +#if __arm__ + #define NOT_HERE_UNITL_AFTER_4_3(sym) \ + extern const char sym##_tmp1 __asm("$ld$hide$os3.0$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp1 = 0; \ + extern const char sym##_tmp2 __asm("$ld$hide$os3.1$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp2 = 0; \ + extern const char sym##_tmp3 __asm("$ld$hide$os3.2$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp3 = 0; \ + extern const char sym##_tmp4 __asm("$ld$hide$os4.0$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp4 = 0; \ + extern const char sym##_tmp5 __asm("$ld$hide$os4.1$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp5 = 0; \ + extern const char sym##_tmp6 __asm("$ld$hide$os4.2$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp6 = 0; \ + extern const char sym##_tmp7 __asm("$ld$hide$os4.3$_" #sym ); \ + __attribute__((visibility("default"))) const char sym##_tmp7 = 0; + +NOT_HERE_UNITL_AFTER_4_3(__absvdi2) +NOT_HERE_UNITL_AFTER_4_3(__absvsi2) +NOT_HERE_UNITL_AFTER_4_3(__adddf3) +NOT_HERE_UNITL_AFTER_4_3(__adddf3vfp) +NOT_HERE_UNITL_AFTER_4_3(__addsf3) +NOT_HERE_UNITL_AFTER_4_3(__addsf3vfp) +NOT_HERE_UNITL_AFTER_4_3(__addvdi3) +NOT_HERE_UNITL_AFTER_4_3(__addvsi3) +NOT_HERE_UNITL_AFTER_4_3(__ashldi3) +NOT_HERE_UNITL_AFTER_4_3(__ashrdi3) +NOT_HERE_UNITL_AFTER_4_3(__bswapdi2) +NOT_HERE_UNITL_AFTER_4_3(__bswapsi2) +NOT_HERE_UNITL_AFTER_4_3(__clzdi2) +NOT_HERE_UNITL_AFTER_4_3(__clzsi2) +NOT_HERE_UNITL_AFTER_4_3(__cmpdi2) +NOT_HERE_UNITL_AFTER_4_3(__ctzdi2) +NOT_HERE_UNITL_AFTER_4_3(__ctzsi2) +NOT_HERE_UNITL_AFTER_4_3(__divdc3) +NOT_HERE_UNITL_AFTER_4_3(__divdf3) +NOT_HERE_UNITL_AFTER_4_3(__divdf3vfp) +NOT_HERE_UNITL_AFTER_4_3(__divdi3) +NOT_HERE_UNITL_AFTER_4_3(__divsc3) +NOT_HERE_UNITL_AFTER_4_3(__divsf3) +NOT_HERE_UNITL_AFTER_4_3(__divsf3vfp) +NOT_HERE_UNITL_AFTER_4_3(__divsi3) +NOT_HERE_UNITL_AFTER_4_3(__eqdf2) +NOT_HERE_UNITL_AFTER_4_3(__eqdf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__eqsf2) +NOT_HERE_UNITL_AFTER_4_3(__eqsf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__extendsfdf2) +NOT_HERE_UNITL_AFTER_4_3(__extendsfdf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__ffsdi2) +NOT_HERE_UNITL_AFTER_4_3(__fixdfdi) +NOT_HERE_UNITL_AFTER_4_3(__fixdfsi) +NOT_HERE_UNITL_AFTER_4_3(__fixdfsivfp) +NOT_HERE_UNITL_AFTER_4_3(__fixsfdi) +NOT_HERE_UNITL_AFTER_4_3(__fixsfsi) +NOT_HERE_UNITL_AFTER_4_3(__fixsfsivfp) +NOT_HERE_UNITL_AFTER_4_3(__fixunsdfdi) +NOT_HERE_UNITL_AFTER_4_3(__fixunsdfsi) +NOT_HERE_UNITL_AFTER_4_3(__fixunsdfsivfp) +NOT_HERE_UNITL_AFTER_4_3(__fixunssfdi) +NOT_HERE_UNITL_AFTER_4_3(__fixunssfsi) +NOT_HERE_UNITL_AFTER_4_3(__fixunssfsivfp) +NOT_HERE_UNITL_AFTER_4_3(__floatdidf) +NOT_HERE_UNITL_AFTER_4_3(__floatdisf) +NOT_HERE_UNITL_AFTER_4_3(__floatsidf) +NOT_HERE_UNITL_AFTER_4_3(__floatsidfvfp) +NOT_HERE_UNITL_AFTER_4_3(__floatsisf) +NOT_HERE_UNITL_AFTER_4_3(__floatsisfvfp) +NOT_HERE_UNITL_AFTER_4_3(__floatundidf) +NOT_HERE_UNITL_AFTER_4_3(__floatundisf) +NOT_HERE_UNITL_AFTER_4_3(__floatunsidf) +NOT_HERE_UNITL_AFTER_4_3(__floatunsisf) +NOT_HERE_UNITL_AFTER_4_3(__floatunssidfvfp) +NOT_HERE_UNITL_AFTER_4_3(__floatunssisfvfp) +NOT_HERE_UNITL_AFTER_4_3(__gedf2) +NOT_HERE_UNITL_AFTER_4_3(__gedf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__gesf2) +NOT_HERE_UNITL_AFTER_4_3(__gesf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__gtdf2) +NOT_HERE_UNITL_AFTER_4_3(__gtdf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__gtsf2) +NOT_HERE_UNITL_AFTER_4_3(__gtsf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__ledf2) +NOT_HERE_UNITL_AFTER_4_3(__ledf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__lesf2) +NOT_HERE_UNITL_AFTER_4_3(__lesf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__lshrdi3) +NOT_HERE_UNITL_AFTER_4_3(__ltdf2) +NOT_HERE_UNITL_AFTER_4_3(__ltdf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__ltsf2) +NOT_HERE_UNITL_AFTER_4_3(__ltsf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__moddi3) +NOT_HERE_UNITL_AFTER_4_3(__modsi3) +NOT_HERE_UNITL_AFTER_4_3(__muldc3) +NOT_HERE_UNITL_AFTER_4_3(__muldf3) +NOT_HERE_UNITL_AFTER_4_3(__muldf3vfp) +NOT_HERE_UNITL_AFTER_4_3(__muldi3) +NOT_HERE_UNITL_AFTER_4_3(__mulsc3) +NOT_HERE_UNITL_AFTER_4_3(__mulsf3) +NOT_HERE_UNITL_AFTER_4_3(__mulsf3vfp) +NOT_HERE_UNITL_AFTER_4_3(__mulvdi3) +NOT_HERE_UNITL_AFTER_4_3(__mulvsi3) +NOT_HERE_UNITL_AFTER_4_3(__nedf2) +NOT_HERE_UNITL_AFTER_4_3(__nedf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__negdi2) +NOT_HERE_UNITL_AFTER_4_3(__negvdi2) +NOT_HERE_UNITL_AFTER_4_3(__negvsi2) +NOT_HERE_UNITL_AFTER_4_3(__nesf2) +NOT_HERE_UNITL_AFTER_4_3(__nesf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__paritydi2) +NOT_HERE_UNITL_AFTER_4_3(__paritysi2) +NOT_HERE_UNITL_AFTER_4_3(__popcountdi2) +NOT_HERE_UNITL_AFTER_4_3(__popcountsi2) +NOT_HERE_UNITL_AFTER_4_3(__powidf2) +NOT_HERE_UNITL_AFTER_4_3(__powisf2) +NOT_HERE_UNITL_AFTER_4_3(__subdf3) +NOT_HERE_UNITL_AFTER_4_3(__subdf3vfp) +NOT_HERE_UNITL_AFTER_4_3(__subsf3) +NOT_HERE_UNITL_AFTER_4_3(__subsf3vfp) +NOT_HERE_UNITL_AFTER_4_3(__subvdi3) +NOT_HERE_UNITL_AFTER_4_3(__subvsi3) +NOT_HERE_UNITL_AFTER_4_3(__truncdfsf2) +NOT_HERE_UNITL_AFTER_4_3(__truncdfsf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__ucmpdi2) +NOT_HERE_UNITL_AFTER_4_3(__udivdi3) +NOT_HERE_UNITL_AFTER_4_3(__udivmoddi4) +NOT_HERE_UNITL_AFTER_4_3(__udivsi3) +NOT_HERE_UNITL_AFTER_4_3(__umoddi3) +NOT_HERE_UNITL_AFTER_4_3(__umodsi3) +NOT_HERE_UNITL_AFTER_4_3(__unorddf2) +NOT_HERE_UNITL_AFTER_4_3(__unorddf2vfp) +NOT_HERE_UNITL_AFTER_4_3(__unordsf2) +NOT_HERE_UNITL_AFTER_4_3(__unordsf2vfp) + +NOT_HERE_UNITL_AFTER_4_3(__divmodsi4) +NOT_HERE_UNITL_AFTER_4_3(__udivmodsi4) +#endif + + + + + #else /* !__APPLE__ */ extern int avoid_empty_file; From ismail at namtrac.org Tue Apr 12 16:18:36 2011 From: ismail at namtrac.org (=?UTF-8?B?xLBzbWFpbCBEw7ZubWV6?=) Date: Tue, 12 Apr 2011 23:18:36 +0200 Subject: [llvm-commits] [compiler-rt] r129386 - /compiler-rt/trunk/lib/apple_versioning.c In-Reply-To: <20110412211147.6C4582A6C12D@llvm.org> References: <20110412211147.6C4582A6C12D@llvm.org> Message-ID: Hi; On Tue, Apr 12, 2011 at 11:11 PM, Nick Kledzik wrote: > Author: kledzik > Date: Tue Apr 12 16:11:47 2011 > New Revision: 129386 > > URL: http://llvm.org/viewvc/llvm-project?rev=129386&view=rev > Log: > update version info for arm > > Modified: > compiler-rt/trunk/lib/apple_versioning.c > > Modified: compiler-rt/trunk/lib/apple_versioning.c > URL: > http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/apple_versioning.c?rev=129386&r1=129385&r2=129386&view=diff > > ============================================================================== > --- compiler-rt/trunk/lib/apple_versioning.c (original) > +++ compiler-rt/trunk/lib/apple_versioning.c Tue Apr 12 16:11:47 2011 > @@ -143,6 +143,147 @@ > NOT_HERE_BEFORE_10_6(__trampoline_setup) > #endif /* __ppc__ */ > > +#if __arm__ > + #define NOT_HERE_UNITL_AFTER_4_3(sym) \ > s/UNITL/UNTIL/g Regards. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110412/d5b2f13b/attachment.html From stoklund at 2pi.dk Tue Apr 12 16:21:57 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 12 Apr 2011 14:21:57 -0700 Subject: [llvm-commits] Source register same as write-back base In-Reply-To: <88D727341410A44C9E34E8E3EF37D8ED0427A46C@be25.exg3.exghost.com> References: <88D727341410A44C9E34E8E3EF37D8ED04213C3E@be25.exg3.exghost.com> <12BD8D01-BDE4-4E21-8608-A24EFF90A48C@apple.com> <88D727341410A44C9E34E8E3EF37D8ED0427A419@be25.exg3.exghost.com> <88D727341410A44C9E34E8E3EF37D8ED0427A46C@be25.exg3.exghost.com> Message-ID: On Apr 12, 2011, at 1:02 PM, Joe Abbey wrote: > >> What kind of code is producing this instruction? It seems odd to store > a pointer to itself: >> *p++ = p; > > STL: > > #include > #include > > using namespace std; > > int main(void) > { > list intList; > vector > vectorOfLists; > vectorOfLists.push_back(intList); > > return 0; > } Ah, that makes sense, std::list is probably implemented as a circular list. It seems that fast-isel doesn't generate the *_POST variants of stores, so there is no harm in adding @earlyclobber constraints to those instructions. Do you know exactly which instructions have this constraint? /jakob From johnny.chen at apple.com Tue Apr 12 16:17:51 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Apr 2011 21:17:51 -0000 Subject: [llvm-commits] [llvm] r129387 - in /llvm/trunk: lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt Message-ID: <20110412211752.05DBC2A6C12D@llvm.org> Author: johnny Date: Tue Apr 12 16:17:51 2011 New Revision: 129387 URL: http://llvm.org/viewvc/llvm-project?rev=129387&view=rev Log: Add bad register checks for Thumb2 Ld/St instructions. rdar://problem/9269047 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129387&r1=129386&r2=129387&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Tue Apr 12 16:17:51 2011 @@ -1862,6 +1862,47 @@ return true; } +static bool BadRegsThumb2LdSt(unsigned Opcode, uint32_t insn, bool Load, + unsigned R0, unsigned R1, unsigned R2, bool UseRm, bool WB) { + + // Inst{22-21} encodes the data item transferred for load/store. + // For single word, it is encoded as ob10. + bool Word = (slice(insn, 22, 21) == 2); + + if (UseRm && BadReg(R2)) { + DEBUG(errs() << "if BadReg(m) then UNPREDICTABLE\n"); + return true; + } + + if (Load) { + if (!Word && R0 == 13) { + DEBUG(errs() << "if t == 13 then UNPREDICTABLE\n"); + return true; + } + } else { + if (WB && R0 == R1) { + DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n"); + return true; + } + if ((WB && R0 == 15) || (!WB && R1 == 15)) { + DEBUG(errs() << "if Rn == '1111' then UNDEFINED\n"); + return true; + } + if (Word) { + if ((WB && R1 == 15) || (!WB && R0 == 15)) { + DEBUG(errs() << "if t == 15 then UNPREDICTABLE\n"); + return true; + } + } else { + if ((WB && BadReg(R1)) || (!WB && BadReg(R0))) { + DEBUG(errs() << "if BadReg(t) then UNPREDICTABLE\n"); + return true; + } + } + } + return false; +} + // A6.3.10 Store single data item // A6.3.9 Load byte, memory hints // A6.3.8 Load halfword, memory hints @@ -1961,6 +2002,10 @@ ++OpIdx; } + if (BadRegsThumb2LdSt(Opcode, insn, Load, R0, R1, R2, ThreeReg & !TIED_TO, + TIED_TO)) + return false; + assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef() && "Pure imm operand expected"); Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt?rev=129387&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt Tue Apr 12 16:17:51 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=2137 Name=t2STR_POST Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 1| 1: 0: 0: 0| 0: 1: 0: 0| 1: 1: 1: 1| 1: 1: 1: 0| 1: 0: 1: 1| 1: 1: 1: 1| 1: 1: 1: 1| +# ------------------------------------------------------------------------------------------------- +# +# if Rn == '1111' then UNDEFINED +0x4f 0xf8 0xff 0xeb From grosbach at apple.com Tue Apr 12 16:20:41 2011 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 12 Apr 2011 21:20:41 -0000 Subject: [llvm-commits] [llvm] r129388 - in /llvm/trunk: include/llvm/ExecutionEngine/RuntimeDyld.h lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp tools/llvm-rtdyld/llvm-rtdyld.cpp Message-ID: <20110412212041.A00662A6C12D@llvm.org> Author: grosbach Date: Tue Apr 12 16:20:41 2011 New Revision: 129388 URL: http://llvm.org/viewvc/llvm-project?rev=129388&view=rev Log: MCJIT lazy relocation resolution and symbol address re-assignment. Add handling for tracking the relocations on symbols and resolving them. Keep track of the relocations even after they are resolved so that if the RuntimeDyld client moves the object, it can update the address and any relocations to that object will be updated. For our trival object file load/run test harness (llvm-rtdyld), this enables relocations between functions located in the same object module. It should be trivially extendable to load multiple objects with mutual references. As a simple example, the following now works (running on x86_64 Darwin 10.6): $ cat t.c int bar() { return 65; } int main() { return bar(); } $ clang t.c -fno-asynchronous-unwind-tables -o t.o -c $ otool -vt t.o t.o: (__TEXT,__text) section _bar: 0000000000000000 pushq %rbp 0000000000000001 movq %rsp,%rbp 0000000000000004 movl $0x00000041,%eax 0000000000000009 popq %rbp 000000000000000a ret 000000000000000b nopl 0x00(%rax,%rax) _main: 0000000000000010 pushq %rbp 0000000000000011 movq %rsp,%rbp 0000000000000014 subq $0x10,%rsp 0000000000000018 movl $0x00000000,0xfc(%rbp) 000000000000001f callq 0x00000024 0000000000000024 addq $0x10,%rsp 0000000000000028 popq %rbp 0000000000000029 ret $ llvm-rtdyld t.o -debug-only=dyld ; echo $? Function sym: '_bar' @ 0 Function sym: '_main' @ 16 Extracting function: _bar from [0, 15] allocated to 0x100153000 Extracting function: _main from [16, 41] allocated to 0x100154000 Relocation at '_main' + 16 from '_bar(Word1: 0x2d000000) Resolving relocation at '_main' + 16 (0x100154010) from '_bar (0x100153000)(pcrel, type: 2, Size: 4). loaded '_main' at: 0x100154000 65 $ Modified: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Modified: llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h?rev=129388&r1=129387&r2=129388&view=diff ============================================================================== --- llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h (original) +++ llvm/trunk/include/llvm/ExecutionEngine/RuntimeDyld.h Tue Apr 12 16:20:41 2011 @@ -62,7 +62,11 @@ // be the address used for relocation (clients can copy the data around // and resolve relocatons based on where they put it). void *getSymbolAddress(StringRef Name); - void reassignSymbolAddress(StringRef Name, uint64_t Addr); + // Resolve the relocations for all symbols we currently know about. + void resolveRelocations(); + // Change the address associated with a symbol when resolving relocations. + // Any relocations already associated with the symbol will be re-resolved. + void reassignSymbolAddress(StringRef Name, uint8_t *Addr); StringRef getErrorString(); }; Modified: llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp?rev=129388&r1=129387&r2=129388&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp Tue Apr 12 16:20:41 2011 @@ -41,17 +41,38 @@ // The MemoryManager to load objects into. RTDyldMemoryManager *MemMgr; + // FIXME: This all assumes we're dealing with external symbols for anything + // explicitly referenced. I.e., we can index by name and things + // will work out. In practice, this may not be the case, so we + // should find a way to effectively generalize. // For each function, we have a MemoryBlock of it's instruction data. StringMap Functions; // Master symbol table. As modules are loaded and external symbols are // resolved, their addresses are stored here. - StringMap SymbolTable; + StringMap SymbolTable; - // FIXME: Should have multiple data blocks, one for each loaded chunk of - // compiled code. -// sys::MemoryBlock Data; + // For each symbol, keep a list of relocations based on it. Anytime + // its address is reassigned (the JIT re-compiled the function, e.g.), + // the relocations get re-resolved. + struct RelocationEntry { + std::string Target; // Object this relocation is contained in. + uint64_t Offset; // Offset into the object for the relocation. + uint32_t Data; // Second word of the raw macho relocation entry. + int64_t Addend; // Addend encoded in the instruction itself, if any. + bool isResolved; // Has this relocation been resolved previously? + + RelocationEntry(StringRef t, uint64_t offset, uint32_t data, int64_t addend) + : Target(t), Offset(offset), Data(data), Addend(addend), + isResolved(false) {} + }; + typedef SmallVector RelocationList; + StringMap Relocations; + + // FIXME: Also keep a map of all the relocations contained in an object. Use + // this to dynamically answer whether all of the relocations in it have + // been resolved or not. bool HasError; std::string ErrorStr; @@ -65,12 +86,11 @@ void extractFunction(StringRef Name, uint8_t *StartAddress, uint8_t *EndAddress); - bool resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE, - SmallVectorImpl &SectionBases, - SmallVectorImpl &SymbolNames); - bool resolveX86_64Relocation(intptr_t Address, intptr_t Value, bool isPCRel, + bool resolveRelocation(uint8_t *Address, uint8_t *Value, bool isPCRel, + unsigned Type, unsigned Size); + bool resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, bool isPCRel, unsigned Type, unsigned Size); - bool resolveARMRelocation(intptr_t Address, intptr_t Value, bool isPCRel, + bool resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel, unsigned Type, unsigned Size); bool loadSegment32(const MachOObject *Obj, @@ -88,9 +108,13 @@ void *getSymbolAddress(StringRef Name) { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. - return Functions.lookup(Name).base(); + return SymbolTable.lookup(Name); } + void resolveRelocations(); + + void reassignSymbolAddress(StringRef Name, uint8_t *Addr); + // Is the linker in an error state? bool hasError() { return HasError; } @@ -113,67 +137,32 @@ MemMgr->endFunctionBody(Name.data(), Mem, Mem + Size); // Remember where we put it. Functions[Name] = sys::MemoryBlock(Mem, Size); + // Default the assigned address for this symbol to wherever this + // allocated it. + SymbolTable[Name] = Mem; DEBUG(dbgs() << " allocated to " << Mem << "\n"); } bool RuntimeDyldImpl:: -resolveRelocation(uint32_t BaseSection, macho::RelocationEntry RE, - SmallVectorImpl &SectionBases, - SmallVectorImpl &SymbolNames) { - // struct relocation_info { - // int32_t r_address; - // uint32_t r_symbolnum:24, - // r_pcrel:1, - // r_length:2, - // r_extern:1, - // r_type:4; - // }; - uint32_t SymbolNum = RE.Word1 & 0xffffff; // 24-bit value - bool isPCRel = (RE.Word1 >> 24) & 1; - unsigned Log2Size = (RE.Word1 >> 25) & 3; - bool isExtern = (RE.Word1 >> 27) & 1; - unsigned Type = (RE.Word1 >> 28) & 0xf; - if (RE.Word0 & macho::RF_Scattered) - return Error("NOT YET IMPLEMENTED: scattered relocations."); - - // The address requiring a relocation. - intptr_t Address = (intptr_t)SectionBases[BaseSection] + RE.Word0; - - // Figure out the target address of the relocation. If isExtern is true, - // this relocation references the symbol table, otherwise it references - // a section in the same object, numbered from 1 through NumSections - // (SectionBases is [0, NumSections-1]). - intptr_t Value; - if (isExtern) { - StringRef Name = SymbolNames[SymbolNum]; - if (SymbolTable.lookup(Name)) { - // The symbol is in our symbol table, so we can resolve it directly. - Value = (intptr_t)SymbolTable[Name]; - } else { - return Error("NOT YET IMPLEMENTED: relocations to pre-compiled code."); - } - DEBUG(dbgs() << "Resolve relocation(" << Type << ") from '" << Name - << "' to " << format("0x%x", Address) << ".\n"); - } else { - // For non-external relocations, the SymbolNum is actual a section number - // as described above. - Value = (intptr_t)SectionBases[SymbolNum - 1]; - } - - unsigned Size = 1 << Log2Size; +resolveRelocation(uint8_t *Address, uint8_t *Value, bool isPCRel, + unsigned Type, unsigned Size) { + // This just dispatches to the proper target specific routine. switch (CPUType) { default: assert(0 && "Unsupported CPU type!"); case mach::CTM_x86_64: - return resolveX86_64Relocation(Address, Value, isPCRel, Type, Size); + return resolveX86_64Relocation((uintptr_t)Address, (uintptr_t)Value, + isPCRel, Type, Size); case mach::CTM_ARM: - return resolveARMRelocation(Address, Value, isPCRel, Type, Size); + return resolveARMRelocation((uintptr_t)Address, (uintptr_t)Value, + isPCRel, Type, Size); } llvm_unreachable(""); } -bool RuntimeDyldImpl::resolveX86_64Relocation(intptr_t Address, intptr_t Value, - bool isPCRel, unsigned Type, - unsigned Size) { +bool RuntimeDyldImpl:: +resolveX86_64Relocation(uintptr_t Address, uintptr_t Value, + bool isPCRel, unsigned Type, + unsigned Size) { // If the relocation is PC-relative, the value to be encoded is the // pointer difference. if (isPCRel) @@ -208,7 +197,7 @@ return false; } -bool RuntimeDyldImpl::resolveARMRelocation(intptr_t Address, intptr_t Value, +bool RuntimeDyldImpl::resolveARMRelocation(uintptr_t Address, uintptr_t Value, bool isPCRel, unsigned Type, unsigned Size) { // If the relocation is PC-relative, the value to be encoded is the @@ -223,6 +212,7 @@ switch(Type) { default: + llvm_unreachable("Invalid relocation type!"); case macho::RIT_Vanilla: { llvm_unreachable("Invalid relocation type!"); // Mask in the target value a byte at a time (we don't have an alignment @@ -234,10 +224,6 @@ } break; } - case macho::RIT_Pair: - case macho::RIT_Difference: - case macho::RIT_ARM_LocalDifference: - case macho::RIT_ARM_PreboundLazyPointer: case macho::RIT_ARM_Branch24Bit: { // Mask the value into the target address. We know instructions are // 32-bit aligned, so we can do it all at once. @@ -258,6 +244,10 @@ case macho::RIT_ARM_ThumbBranch32Bit: case macho::RIT_ARM_Half: case macho::RIT_ARM_HalfDifference: + case macho::RIT_Pair: + case macho::RIT_Difference: + case macho::RIT_ARM_LocalDifference: + case macho::RIT_ARM_PreboundLazyPointer: return Error("Relocation type not implemented yet!"); } return false; @@ -267,12 +257,12 @@ loadSegment32(const MachOObject *Obj, const MachOObject::LoadCommandInfo *SegmentLCI, const InMemoryStruct &SymtabLC) { - InMemoryStruct Segment32LC; - Obj->ReadSegmentLoadCommand(*SegmentLCI, Segment32LC); - if (!Segment32LC) + InMemoryStruct SegmentLC; + Obj->ReadSegmentLoadCommand(*SegmentLCI, SegmentLC); + if (!SegmentLC) return Error("unable to load segment load command"); - for (unsigned SectNum = 0; SectNum != Segment32LC->NumSections; ++SectNum) { + for (unsigned SectNum = 0; SectNum != SegmentLC->NumSections; ++SectNum) { InMemoryStruct Sect; Obj->ReadSection(*SegmentLCI, SectNum, Sect); if (!Sect) @@ -284,45 +274,47 @@ // Address and names of symbols in the section. typedef std::pair SymbolEntry; - SmallVector Symbols; + SmallVector Symbols; + // Index of all the names, in this section or not. Used when we're + // dealing with relocation entries. + SmallVector SymbolNames; for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { InMemoryStruct STE; Obj->ReadSymbolTableEntry(SymtabLC->SymbolTableOffset, i, STE); if (!STE) return Error("unable to read symbol: '" + Twine(i) + "'"); - if (STE->SectionIndex > Segment32LC->NumSections) + if (STE->SectionIndex > SegmentLC->NumSections) return Error("invalid section index for symbol: '" + Twine(i) + "'"); + // Get the symbol name. + StringRef Name = Obj->getStringAtIndex(STE->StringIndex); + SymbolNames.push_back(Name); // Just skip symbols not defined in this section. if ((unsigned)STE->SectionIndex - 1 != SectNum) continue; - // Get the symbol name. - StringRef Name = Obj->getStringAtIndex(STE->StringIndex); - // FIXME: Check the symbol type and flags. if (STE->Type != 0xF) // external, defined in this section. return Error("unexpected symbol type!"); - if (STE->Flags != 0x0) + // Flags == 0x8 marks a thumb function for ARM, which is fine as it + // doesn't require any special handling here. + if (STE->Flags != 0x0 && STE->Flags != 0x8) return Error("unexpected symbol type!"); - uint64_t BaseAddress = Sect->Address; - uint64_t Address = BaseAddress + STE->Value; - // Remember the symbol. - Symbols.push_back(SymbolEntry(Address, Name)); + Symbols.push_back(SymbolEntry(STE->Value, Name)); - DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << Address << "\n"); + DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << + (Sect->Address + STE->Value) << "\n"); } - // Sort the symbols by address, just in case they didn't come in that - // way. + // Sort the symbols by address, just in case they didn't come in that way. array_pod_sort(Symbols.begin(), Symbols.end()); // Extract the function data. - uint8_t *Base = (uint8_t*)Obj->getData(Segment32LC->FileOffset, - Segment32LC->FileSize).data(); + uint8_t *Base = (uint8_t*)Obj->getData(SegmentLC->FileOffset, + SegmentLC->FileSize).data(); for (unsigned i = 0, e = Symbols.size() - 1; i != e; ++i) { - uint64_t StartOffset = Symbols[i].first; + uint64_t StartOffset = Sect->Address + Symbols[i].first; uint64_t EndOffset = Symbols[i + 1].first - 1; DEBUG(dbgs() << "Extracting function: " << Symbols[i].second << " from [" << StartOffset << ", " << EndOffset << "]\n"); @@ -336,8 +328,62 @@ << " from [" << StartOffset << ", " << EndOffset << "]\n"); extractFunction(Symbols[Symbols.size()-1].second, Base + StartOffset, Base + EndOffset); - } + // Now extract the relocation information for each function and process it. + for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) { + InMemoryStruct RE; + Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE); + if (RE->Word0 & macho::RF_Scattered) + return Error("NOT YET IMPLEMENTED: scattered relocations."); + // Word0 of the relocation is the offset into the section where the + // relocation should be applied. We need to translate that into an + // offset into a function since that's our atom. + uint32_t Offset = RE->Word0; + // Look for the function containing the address. This is used for JIT + // code, so the number of functions in section is almost always going + // to be very small (usually just one), so until we have use cases + // where that's not true, just use a trivial linear search. + unsigned SymbolNum; + unsigned NumSymbols = Symbols.size(); + assert(NumSymbols > 0 && Symbols[0].first <= Offset && + "No symbol containing relocation!"); + for (SymbolNum = 0; SymbolNum < NumSymbols - 1; ++SymbolNum) + if (Symbols[SymbolNum + 1].first > Offset) + break; + // Adjust the offset to be relative to the symbol. + Offset -= Symbols[SymbolNum].first; + // Get the name of the symbol containing the relocation. + StringRef TargetName = SymbolNames[SymbolNum]; + + bool isExtern = (RE->Word1 >> 27) & 1; + // Figure out the source symbol of the relocation. If isExtern is true, + // this relocation references the symbol table, otherwise it references + // a section in the same object, numbered from 1 through NumSections + // (SectionBases is [0, NumSections-1]). + // FIXME: Some targets (ARM) use internal relocations even for + // externally visible symbols, if the definition is in the same + // file as the reference. We need to convert those back to by-name + // references. We can resolve the address based on the section + // offset and see if we have a symbol at that address. If we do, + // use that; otherwise, puke. + if (!isExtern) + return Error("Internal relocations not supported."); + uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value + StringRef SourceName = SymbolNames[SourceNum]; + + // FIXME: Get the relocation addend from the target address. + + // Now store the relocation information. Associate it with the source + // symbol. + Relocations[SourceName].push_back(RelocationEntry(TargetName, + Offset, + RE->Word1, + 0 /*Addend*/)); + DEBUG(dbgs() << "Relocation at '" << TargetName << "' + " << Offset + << " from '" << SourceName << "(Word1: " + << format("0x%x", RE->Word1) << ")\n"); + } + } return false; } @@ -364,6 +410,9 @@ // Address and names of symbols in the section. typedef std::pair SymbolEntry; SmallVector Symbols; + // Index of all the names, in this section or not. Used when we're + // dealing with relocation entries. + SmallVector SymbolNames; for (unsigned i = 0; i != SymtabLC->NumSymbolTableEntries; ++i) { InMemoryStruct STE; Obj->ReadSymbol64TableEntry(SymtabLC->SymbolTableOffset, i, STE); @@ -371,37 +420,34 @@ return Error("unable to read symbol: '" + Twine(i) + "'"); if (STE->SectionIndex > Segment64LC->NumSections) return Error("invalid section index for symbol: '" + Twine(i) + "'"); + // Get the symbol name. + StringRef Name = Obj->getStringAtIndex(STE->StringIndex); + SymbolNames.push_back(Name); // Just skip symbols not defined in this section. if ((unsigned)STE->SectionIndex - 1 != SectNum) continue; - // Get the symbol name. - StringRef Name = Obj->getStringAtIndex(STE->StringIndex); - // FIXME: Check the symbol type and flags. if (STE->Type != 0xF) // external, defined in this section. return Error("unexpected symbol type!"); if (STE->Flags != 0x0) return Error("unexpected symbol type!"); - uint64_t BaseAddress = Sect->Address; - uint64_t Address = BaseAddress + STE->Value; - // Remember the symbol. - Symbols.push_back(SymbolEntry(Address, Name)); + Symbols.push_back(SymbolEntry(STE->Value, Name)); - DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << Address << "\n"); + DEBUG(dbgs() << "Function sym: '" << Name << "' @ " << + (Sect->Address + STE->Value) << "\n"); } - // Sort the symbols by address, just in case they didn't come in that - // way. + // Sort the symbols by address, just in case they didn't come in that way. array_pod_sort(Symbols.begin(), Symbols.end()); // Extract the function data. uint8_t *Base = (uint8_t*)Obj->getData(Segment64LC->FileOffset, Segment64LC->FileSize).data(); for (unsigned i = 0, e = Symbols.size() - 1; i != e; ++i) { - uint64_t StartOffset = Symbols[i].first; + uint64_t StartOffset = Sect->Address + Symbols[i].first; uint64_t EndOffset = Symbols[i + 1].first - 1; DEBUG(dbgs() << "Extracting function: " << Symbols[i].second << " from [" << StartOffset << ", " << EndOffset << "]\n"); @@ -415,8 +461,56 @@ << " from [" << StartOffset << ", " << EndOffset << "]\n"); extractFunction(Symbols[Symbols.size()-1].second, Base + StartOffset, Base + EndOffset); - } + // Now extract the relocation information for each function and process it. + for (unsigned j = 0; j != Sect->NumRelocationTableEntries; ++j) { + InMemoryStruct RE; + Obj->ReadRelocationEntry(Sect->RelocationTableOffset, j, RE); + if (RE->Word0 & macho::RF_Scattered) + return Error("NOT YET IMPLEMENTED: scattered relocations."); + // Word0 of the relocation is the offset into the section where the + // relocation should be applied. We need to translate that into an + // offset into a function since that's our atom. + uint32_t Offset = RE->Word0; + // Look for the function containing the address. This is used for JIT + // code, so the number of functions in section is almost always going + // to be very small (usually just one), so until we have use cases + // where that's not true, just use a trivial linear search. + unsigned SymbolNum; + unsigned NumSymbols = Symbols.size(); + assert(NumSymbols > 0 && Symbols[0].first <= Offset && + "No symbol containing relocation!"); + for (SymbolNum = 0; SymbolNum < NumSymbols - 1; ++SymbolNum) + if (Symbols[SymbolNum + 1].first > Offset) + break; + // Adjust the offset to be relative to the symbol. + Offset -= Symbols[SymbolNum].first; + // Get the name of the symbol containing the relocation. + StringRef TargetName = SymbolNames[SymbolNum]; + + bool isExtern = (RE->Word1 >> 27) & 1; + // Figure out the source symbol of the relocation. If isExtern is true, + // this relocation references the symbol table, otherwise it references + // a section in the same object, numbered from 1 through NumSections + // (SectionBases is [0, NumSections-1]). + if (!isExtern) + return Error("Internal relocations not supported."); + uint32_t SourceNum = RE->Word1 & 0xffffff; // 24-bit value + StringRef SourceName = SymbolNames[SourceNum]; + + // FIXME: Get the relocation addend from the target address. + + // Now store the relocation information. Associate it with the source + // symbol. + Relocations[SourceName].push_back(RelocationEntry(TargetName, + Offset, + RE->Word1, + 0 /*Addend*/)); + DEBUG(dbgs() << "Relocation at '" << TargetName << "' + " << Offset + << " from '" << SourceName << "(Word1: " + << format("0x%x", RE->Word1) << ")\n"); + } + } return false; } @@ -507,6 +601,40 @@ return false; } +// Resolve the relocations for all symbols we currently know about. +void RuntimeDyldImpl::resolveRelocations() { + // Just iterate over the symbols in our symbol table and assign their + // addresses. + StringMap::iterator i = SymbolTable.begin(); + StringMap::iterator e = SymbolTable.end(); + for (;i != e; ++i) + reassignSymbolAddress(i->getKey(), i->getValue()); +} + +// Assign an address to a symbol name and resolve all the relocations +// associated with it. +void RuntimeDyldImpl::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { + // Assign the address in our symbol table. + SymbolTable[Name] = Addr; + + RelocationList &Relocs = Relocations[Name]; + for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { + RelocationEntry &RE = Relocs[i]; + uint8_t *Target = SymbolTable[RE.Target] + RE.Offset; + bool isPCRel = (RE.Data >> 24) & 1; + unsigned Type = (RE.Data >> 28) & 0xf; + unsigned Size = 1 << ((RE.Data >> 25) & 3); + + DEBUG(dbgs() << "Resolving relocation at '" << RE.Target + << "' + " << RE.Offset << " (" << format("%p", Target) << ")" + << " from '" << Name << " (" << format("%p", Addr) << ")" + << "(" << (isPCRel ? "pcrel" : "absolute") + << ", type: " << Type << ", Size: " << Size << ").\n"); + + resolveRelocation(Target, Addr, isPCRel, Type, Size); + RE.isResolved = true; + } +} //===----------------------------------------------------------------------===// // RuntimeDyld class implementation @@ -526,6 +654,14 @@ return Dyld->getSymbolAddress(Name); } +void RuntimeDyld::resolveRelocations() { + Dyld->resolveRelocations(); +} + +void RuntimeDyld::reassignSymbolAddress(StringRef Name, uint8_t *Addr) { + Dyld->reassignSymbolAddress(Name, Addr); +} + StringRef RuntimeDyld::getErrorString() { return Dyld->getErrorString(); } Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp?rev=129388&r1=129387&r2=129388&view=diff ============================================================================== --- llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp (original) +++ llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Tue Apr 12 16:20:41 2011 @@ -90,6 +90,8 @@ if (Dyld.loadObject(InputBuffer.take())) { return Error(Dyld.getErrorString()); } + // Resolve all the relocations we can. + Dyld.resolveRelocations(); // Get the address of "_main". void *MainAddress = Dyld.getSymbolAddress("_main"); From kledzik at apple.com Tue Apr 12 16:22:49 2011 From: kledzik at apple.com (Nick Kledzik) Date: Tue, 12 Apr 2011 21:22:49 -0000 Subject: [llvm-commits] [compiler-rt] r129389 - /compiler-rt/trunk/lib/apple_versioning.c Message-ID: <20110412212249.223B12A6C12D@llvm.org> Author: kledzik Date: Tue Apr 12 16:22:48 2011 New Revision: 129389 URL: http://llvm.org/viewvc/llvm-project?rev=129389&view=rev Log: fix typo Modified: compiler-rt/trunk/lib/apple_versioning.c Modified: compiler-rt/trunk/lib/apple_versioning.c URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/apple_versioning.c?rev=129389&r1=129388&r2=129389&view=diff ============================================================================== --- compiler-rt/trunk/lib/apple_versioning.c (original) +++ compiler-rt/trunk/lib/apple_versioning.c Tue Apr 12 16:22:48 2011 @@ -144,7 +144,7 @@ #endif /* __ppc__ */ #if __arm__ - #define NOT_HERE_UNITL_AFTER_4_3(sym) \ + #define NOT_HERE_UNTIL_AFTER_4_3(sym) \ extern const char sym##_tmp1 __asm("$ld$hide$os3.0$_" #sym ); \ __attribute__((visibility("default"))) const char sym##_tmp1 = 0; \ extern const char sym##_tmp2 __asm("$ld$hide$os3.1$_" #sym ); \ @@ -160,124 +160,124 @@ extern const char sym##_tmp7 __asm("$ld$hide$os4.3$_" #sym ); \ __attribute__((visibility("default"))) const char sym##_tmp7 = 0; -NOT_HERE_UNITL_AFTER_4_3(__absvdi2) -NOT_HERE_UNITL_AFTER_4_3(__absvsi2) -NOT_HERE_UNITL_AFTER_4_3(__adddf3) -NOT_HERE_UNITL_AFTER_4_3(__adddf3vfp) -NOT_HERE_UNITL_AFTER_4_3(__addsf3) -NOT_HERE_UNITL_AFTER_4_3(__addsf3vfp) -NOT_HERE_UNITL_AFTER_4_3(__addvdi3) -NOT_HERE_UNITL_AFTER_4_3(__addvsi3) -NOT_HERE_UNITL_AFTER_4_3(__ashldi3) -NOT_HERE_UNITL_AFTER_4_3(__ashrdi3) -NOT_HERE_UNITL_AFTER_4_3(__bswapdi2) -NOT_HERE_UNITL_AFTER_4_3(__bswapsi2) -NOT_HERE_UNITL_AFTER_4_3(__clzdi2) -NOT_HERE_UNITL_AFTER_4_3(__clzsi2) -NOT_HERE_UNITL_AFTER_4_3(__cmpdi2) -NOT_HERE_UNITL_AFTER_4_3(__ctzdi2) -NOT_HERE_UNITL_AFTER_4_3(__ctzsi2) -NOT_HERE_UNITL_AFTER_4_3(__divdc3) -NOT_HERE_UNITL_AFTER_4_3(__divdf3) -NOT_HERE_UNITL_AFTER_4_3(__divdf3vfp) -NOT_HERE_UNITL_AFTER_4_3(__divdi3) -NOT_HERE_UNITL_AFTER_4_3(__divsc3) -NOT_HERE_UNITL_AFTER_4_3(__divsf3) -NOT_HERE_UNITL_AFTER_4_3(__divsf3vfp) -NOT_HERE_UNITL_AFTER_4_3(__divsi3) -NOT_HERE_UNITL_AFTER_4_3(__eqdf2) -NOT_HERE_UNITL_AFTER_4_3(__eqdf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__eqsf2) -NOT_HERE_UNITL_AFTER_4_3(__eqsf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__extendsfdf2) -NOT_HERE_UNITL_AFTER_4_3(__extendsfdf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__ffsdi2) -NOT_HERE_UNITL_AFTER_4_3(__fixdfdi) -NOT_HERE_UNITL_AFTER_4_3(__fixdfsi) -NOT_HERE_UNITL_AFTER_4_3(__fixdfsivfp) -NOT_HERE_UNITL_AFTER_4_3(__fixsfdi) -NOT_HERE_UNITL_AFTER_4_3(__fixsfsi) -NOT_HERE_UNITL_AFTER_4_3(__fixsfsivfp) -NOT_HERE_UNITL_AFTER_4_3(__fixunsdfdi) -NOT_HERE_UNITL_AFTER_4_3(__fixunsdfsi) -NOT_HERE_UNITL_AFTER_4_3(__fixunsdfsivfp) -NOT_HERE_UNITL_AFTER_4_3(__fixunssfdi) -NOT_HERE_UNITL_AFTER_4_3(__fixunssfsi) -NOT_HERE_UNITL_AFTER_4_3(__fixunssfsivfp) -NOT_HERE_UNITL_AFTER_4_3(__floatdidf) -NOT_HERE_UNITL_AFTER_4_3(__floatdisf) -NOT_HERE_UNITL_AFTER_4_3(__floatsidf) -NOT_HERE_UNITL_AFTER_4_3(__floatsidfvfp) -NOT_HERE_UNITL_AFTER_4_3(__floatsisf) -NOT_HERE_UNITL_AFTER_4_3(__floatsisfvfp) -NOT_HERE_UNITL_AFTER_4_3(__floatundidf) -NOT_HERE_UNITL_AFTER_4_3(__floatundisf) -NOT_HERE_UNITL_AFTER_4_3(__floatunsidf) -NOT_HERE_UNITL_AFTER_4_3(__floatunsisf) -NOT_HERE_UNITL_AFTER_4_3(__floatunssidfvfp) -NOT_HERE_UNITL_AFTER_4_3(__floatunssisfvfp) -NOT_HERE_UNITL_AFTER_4_3(__gedf2) -NOT_HERE_UNITL_AFTER_4_3(__gedf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__gesf2) -NOT_HERE_UNITL_AFTER_4_3(__gesf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__gtdf2) -NOT_HERE_UNITL_AFTER_4_3(__gtdf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__gtsf2) -NOT_HERE_UNITL_AFTER_4_3(__gtsf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__ledf2) -NOT_HERE_UNITL_AFTER_4_3(__ledf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__lesf2) -NOT_HERE_UNITL_AFTER_4_3(__lesf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__lshrdi3) -NOT_HERE_UNITL_AFTER_4_3(__ltdf2) -NOT_HERE_UNITL_AFTER_4_3(__ltdf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__ltsf2) -NOT_HERE_UNITL_AFTER_4_3(__ltsf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__moddi3) -NOT_HERE_UNITL_AFTER_4_3(__modsi3) -NOT_HERE_UNITL_AFTER_4_3(__muldc3) -NOT_HERE_UNITL_AFTER_4_3(__muldf3) -NOT_HERE_UNITL_AFTER_4_3(__muldf3vfp) -NOT_HERE_UNITL_AFTER_4_3(__muldi3) -NOT_HERE_UNITL_AFTER_4_3(__mulsc3) -NOT_HERE_UNITL_AFTER_4_3(__mulsf3) -NOT_HERE_UNITL_AFTER_4_3(__mulsf3vfp) -NOT_HERE_UNITL_AFTER_4_3(__mulvdi3) -NOT_HERE_UNITL_AFTER_4_3(__mulvsi3) -NOT_HERE_UNITL_AFTER_4_3(__nedf2) -NOT_HERE_UNITL_AFTER_4_3(__nedf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__negdi2) -NOT_HERE_UNITL_AFTER_4_3(__negvdi2) -NOT_HERE_UNITL_AFTER_4_3(__negvsi2) -NOT_HERE_UNITL_AFTER_4_3(__nesf2) -NOT_HERE_UNITL_AFTER_4_3(__nesf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__paritydi2) -NOT_HERE_UNITL_AFTER_4_3(__paritysi2) -NOT_HERE_UNITL_AFTER_4_3(__popcountdi2) -NOT_HERE_UNITL_AFTER_4_3(__popcountsi2) -NOT_HERE_UNITL_AFTER_4_3(__powidf2) -NOT_HERE_UNITL_AFTER_4_3(__powisf2) -NOT_HERE_UNITL_AFTER_4_3(__subdf3) -NOT_HERE_UNITL_AFTER_4_3(__subdf3vfp) -NOT_HERE_UNITL_AFTER_4_3(__subsf3) -NOT_HERE_UNITL_AFTER_4_3(__subsf3vfp) -NOT_HERE_UNITL_AFTER_4_3(__subvdi3) -NOT_HERE_UNITL_AFTER_4_3(__subvsi3) -NOT_HERE_UNITL_AFTER_4_3(__truncdfsf2) -NOT_HERE_UNITL_AFTER_4_3(__truncdfsf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__ucmpdi2) -NOT_HERE_UNITL_AFTER_4_3(__udivdi3) -NOT_HERE_UNITL_AFTER_4_3(__udivmoddi4) -NOT_HERE_UNITL_AFTER_4_3(__udivsi3) -NOT_HERE_UNITL_AFTER_4_3(__umoddi3) -NOT_HERE_UNITL_AFTER_4_3(__umodsi3) -NOT_HERE_UNITL_AFTER_4_3(__unorddf2) -NOT_HERE_UNITL_AFTER_4_3(__unorddf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__unordsf2) -NOT_HERE_UNITL_AFTER_4_3(__unordsf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__absvdi2) +NOT_HERE_UNTIL_AFTER_4_3(__absvsi2) +NOT_HERE_UNTIL_AFTER_4_3(__adddf3) +NOT_HERE_UNTIL_AFTER_4_3(__adddf3vfp) +NOT_HERE_UNTIL_AFTER_4_3(__addsf3) +NOT_HERE_UNTIL_AFTER_4_3(__addsf3vfp) +NOT_HERE_UNTIL_AFTER_4_3(__addvdi3) +NOT_HERE_UNTIL_AFTER_4_3(__addvsi3) +NOT_HERE_UNTIL_AFTER_4_3(__ashldi3) +NOT_HERE_UNTIL_AFTER_4_3(__ashrdi3) +NOT_HERE_UNTIL_AFTER_4_3(__bswapdi2) +NOT_HERE_UNTIL_AFTER_4_3(__bswapsi2) +NOT_HERE_UNTIL_AFTER_4_3(__clzdi2) +NOT_HERE_UNTIL_AFTER_4_3(__clzsi2) +NOT_HERE_UNTIL_AFTER_4_3(__cmpdi2) +NOT_HERE_UNTIL_AFTER_4_3(__ctzdi2) +NOT_HERE_UNTIL_AFTER_4_3(__ctzsi2) +NOT_HERE_UNTIL_AFTER_4_3(__divdc3) +NOT_HERE_UNTIL_AFTER_4_3(__divdf3) +NOT_HERE_UNTIL_AFTER_4_3(__divdf3vfp) +NOT_HERE_UNTIL_AFTER_4_3(__divdi3) +NOT_HERE_UNTIL_AFTER_4_3(__divsc3) +NOT_HERE_UNTIL_AFTER_4_3(__divsf3) +NOT_HERE_UNTIL_AFTER_4_3(__divsf3vfp) +NOT_HERE_UNTIL_AFTER_4_3(__divsi3) +NOT_HERE_UNTIL_AFTER_4_3(__eqdf2) +NOT_HERE_UNTIL_AFTER_4_3(__eqdf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__eqsf2) +NOT_HERE_UNTIL_AFTER_4_3(__eqsf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__extendsfdf2) +NOT_HERE_UNTIL_AFTER_4_3(__extendsfdf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__ffsdi2) +NOT_HERE_UNTIL_AFTER_4_3(__fixdfdi) +NOT_HERE_UNTIL_AFTER_4_3(__fixdfsi) +NOT_HERE_UNTIL_AFTER_4_3(__fixdfsivfp) +NOT_HERE_UNTIL_AFTER_4_3(__fixsfdi) +NOT_HERE_UNTIL_AFTER_4_3(__fixsfsi) +NOT_HERE_UNTIL_AFTER_4_3(__fixsfsivfp) +NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfdi) +NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfsi) +NOT_HERE_UNTIL_AFTER_4_3(__fixunsdfsivfp) +NOT_HERE_UNTIL_AFTER_4_3(__fixunssfdi) +NOT_HERE_UNTIL_AFTER_4_3(__fixunssfsi) +NOT_HERE_UNTIL_AFTER_4_3(__fixunssfsivfp) +NOT_HERE_UNTIL_AFTER_4_3(__floatdidf) +NOT_HERE_UNTIL_AFTER_4_3(__floatdisf) +NOT_HERE_UNTIL_AFTER_4_3(__floatsidf) +NOT_HERE_UNTIL_AFTER_4_3(__floatsidfvfp) +NOT_HERE_UNTIL_AFTER_4_3(__floatsisf) +NOT_HERE_UNTIL_AFTER_4_3(__floatsisfvfp) +NOT_HERE_UNTIL_AFTER_4_3(__floatundidf) +NOT_HERE_UNTIL_AFTER_4_3(__floatundisf) +NOT_HERE_UNTIL_AFTER_4_3(__floatunsidf) +NOT_HERE_UNTIL_AFTER_4_3(__floatunsisf) +NOT_HERE_UNTIL_AFTER_4_3(__floatunssidfvfp) +NOT_HERE_UNTIL_AFTER_4_3(__floatunssisfvfp) +NOT_HERE_UNTIL_AFTER_4_3(__gedf2) +NOT_HERE_UNTIL_AFTER_4_3(__gedf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__gesf2) +NOT_HERE_UNTIL_AFTER_4_3(__gesf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__gtdf2) +NOT_HERE_UNTIL_AFTER_4_3(__gtdf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__gtsf2) +NOT_HERE_UNTIL_AFTER_4_3(__gtsf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__ledf2) +NOT_HERE_UNTIL_AFTER_4_3(__ledf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__lesf2) +NOT_HERE_UNTIL_AFTER_4_3(__lesf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__lshrdi3) +NOT_HERE_UNTIL_AFTER_4_3(__ltdf2) +NOT_HERE_UNTIL_AFTER_4_3(__ltdf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__ltsf2) +NOT_HERE_UNTIL_AFTER_4_3(__ltsf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__moddi3) +NOT_HERE_UNTIL_AFTER_4_3(__modsi3) +NOT_HERE_UNTIL_AFTER_4_3(__muldc3) +NOT_HERE_UNTIL_AFTER_4_3(__muldf3) +NOT_HERE_UNTIL_AFTER_4_3(__muldf3vfp) +NOT_HERE_UNTIL_AFTER_4_3(__muldi3) +NOT_HERE_UNTIL_AFTER_4_3(__mulsc3) +NOT_HERE_UNTIL_AFTER_4_3(__mulsf3) +NOT_HERE_UNTIL_AFTER_4_3(__mulsf3vfp) +NOT_HERE_UNTIL_AFTER_4_3(__mulvdi3) +NOT_HERE_UNTIL_AFTER_4_3(__mulvsi3) +NOT_HERE_UNTIL_AFTER_4_3(__nedf2) +NOT_HERE_UNTIL_AFTER_4_3(__nedf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__negdi2) +NOT_HERE_UNTIL_AFTER_4_3(__negvdi2) +NOT_HERE_UNTIL_AFTER_4_3(__negvsi2) +NOT_HERE_UNTIL_AFTER_4_3(__nesf2) +NOT_HERE_UNTIL_AFTER_4_3(__nesf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__paritydi2) +NOT_HERE_UNTIL_AFTER_4_3(__paritysi2) +NOT_HERE_UNTIL_AFTER_4_3(__popcountdi2) +NOT_HERE_UNTIL_AFTER_4_3(__popcountsi2) +NOT_HERE_UNTIL_AFTER_4_3(__powidf2) +NOT_HERE_UNTIL_AFTER_4_3(__powisf2) +NOT_HERE_UNTIL_AFTER_4_3(__subdf3) +NOT_HERE_UNTIL_AFTER_4_3(__subdf3vfp) +NOT_HERE_UNTIL_AFTER_4_3(__subsf3) +NOT_HERE_UNTIL_AFTER_4_3(__subsf3vfp) +NOT_HERE_UNTIL_AFTER_4_3(__subvdi3) +NOT_HERE_UNTIL_AFTER_4_3(__subvsi3) +NOT_HERE_UNTIL_AFTER_4_3(__truncdfsf2) +NOT_HERE_UNTIL_AFTER_4_3(__truncdfsf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__ucmpdi2) +NOT_HERE_UNTIL_AFTER_4_3(__udivdi3) +NOT_HERE_UNTIL_AFTER_4_3(__udivmoddi4) +NOT_HERE_UNTIL_AFTER_4_3(__udivsi3) +NOT_HERE_UNTIL_AFTER_4_3(__umoddi3) +NOT_HERE_UNTIL_AFTER_4_3(__umodsi3) +NOT_HERE_UNTIL_AFTER_4_3(__unorddf2) +NOT_HERE_UNTIL_AFTER_4_3(__unorddf2vfp) +NOT_HERE_UNTIL_AFTER_4_3(__unordsf2) +NOT_HERE_UNTIL_AFTER_4_3(__unordsf2vfp) -NOT_HERE_UNITL_AFTER_4_3(__divmodsi4) -NOT_HERE_UNITL_AFTER_4_3(__udivmodsi4) +NOT_HERE_UNTIL_AFTER_4_3(__divmodsi4) +NOT_HERE_UNTIL_AFTER_4_3(__udivmodsi4) #endif From stoklund at 2pi.dk Tue Apr 12 16:30:53 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 12 Apr 2011 21:30:53 -0000 Subject: [llvm-commits] [llvm] r129390 - in /llvm/trunk/lib/CodeGen: RegAllocGreedy.cpp SplitKit.h Message-ID: <20110412213053.C265D2A6C12D@llvm.org> Author: stoklund Date: Tue Apr 12 16:30:53 2011 New Revision: 129390 URL: http://llvm.org/viewvc/llvm-project?rev=129390&view=rev Log: SparseBitVector is SLOW. Use a Bitvector instead, we didn't need the smaller memory footprint anyway. This makes the greedy register allocator 10% faster. Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp llvm/trunk/lib/CodeGen/SplitKit.h Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp?rev=129390&r1=129389&r2=129390&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Tue Apr 12 16:30:53 2011 @@ -22,7 +22,6 @@ #include "SpillPlacement.h" #include "SplitKit.h" #include "VirtRegMap.h" -#include "llvm/ADT/SparseBitVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Function.h" @@ -126,13 +125,17 @@ /// All basic blocks where the current register has uses. SmallVector SplitConstraints; - /// Live-through blocks that have already been added to SpillPlacer. - SparseBitVector<> ActiveThroughBlocks; - /// Global live range splitting candidate info. struct GlobalSplitCandidate { unsigned PhysReg; BitVector LiveBundles; + SmallVector ActiveBlocks; + + void reset(unsigned Reg) { + PhysReg = Reg; + LiveBundles.clear(); + ActiveBlocks.clear(); + } }; /// Candidate info for for each PhysReg in AllocationOrder. @@ -174,9 +177,9 @@ bool addSplitConstraints(InterferenceCache::Cursor, float&); void addThroughConstraints(InterferenceCache::Cursor, ArrayRef); - void growRegion(InterferenceCache::Cursor); - float calcGlobalSplitCost(unsigned, const BitVector&); - void splitAroundRegion(LiveInterval&, unsigned, const BitVector&, + void growRegion(GlobalSplitCandidate &Cand, InterferenceCache::Cursor); + float calcGlobalSplitCost(GlobalSplitCandidate&, InterferenceCache::Cursor); + void splitAroundRegion(LiveInterval&, GlobalSplitCandidate&, SmallVectorImpl&); void calcGapWeights(unsigned, SmallVectorImpl&); SlotIndex getPrevMappedIndex(const MachineInstr*); @@ -288,6 +291,7 @@ void RAGreedy::releaseMemory() { SpillerInstance.reset(0); LRStage.clear(); + GlobalCand.clear(); RegAllocBase::releaseMemory(); } @@ -526,13 +530,16 @@ SpillPlacer->addLinks(ArrayRef(TBS, T)); } -void RAGreedy::growRegion(InterferenceCache::Cursor Intf) { - // Keep track of through blocks that have already been added to SpillPlacer. - SparseBitVector<> Added; - SmallVector ThroughBlocks; +void RAGreedy::growRegion(GlobalSplitCandidate &Cand, + InterferenceCache::Cursor Intf) { + // Keep track of through blocks that have not been added to SpillPlacer. + BitVector Todo = SA->getThroughBlocks(); + SmallVectorImpl &ActiveBlocks = Cand.ActiveBlocks; + unsigned AddedTo = 0; #ifndef NDEBUG unsigned Visited = 0; #endif + for (;;) { ArrayRef NewBundles = SpillPlacer->getRecentPositive(); if (NewBundles.empty()) @@ -545,26 +552,26 @@ for (ArrayRef::iterator I = Blocks.begin(), E = Blocks.end(); I != E; ++I) { unsigned Block = *I; - if (!SA->isThroughBlock(Block) || !Added.test_and_set(Block)) + if (!Todo.test(Block)) continue; + Todo.reset(Block); // This is a new through block. Add it to SpillPlacer later. - ThroughBlocks.push_back(Block); + ActiveBlocks.push_back(Block); #ifndef NDEBUG ++Visited; #endif } } // Any new blocks to add? - if (!ThroughBlocks.empty()) { - addThroughConstraints(Intf, ThroughBlocks); - ThroughBlocks.clear(); + if (ActiveBlocks.size() > AddedTo) { + ArrayRef Add(&ActiveBlocks[AddedTo], + ActiveBlocks.size() - AddedTo); + addThroughConstraints(Intf, Add); + AddedTo = ActiveBlocks.size(); } // Perhaps iterating can enable more bundles? SpillPlacer->iterate(); } - - // Rememeber the relevant set of through blocks for splitAroundRegion(). - ActiveThroughBlocks |= Added; DEBUG(dbgs() << ", v=" << Visited); } @@ -572,9 +579,10 @@ /// pattern in LiveBundles. This cost should be added to the local cost of the /// interference pattern in SplitConstraints. /// -float RAGreedy::calcGlobalSplitCost(unsigned PhysReg, - const BitVector &LiveBundles) { +float RAGreedy::calcGlobalSplitCost(GlobalSplitCandidate &Cand, + InterferenceCache::Cursor Intf) { float GlobalCost = 0; + const BitVector &LiveBundles = Cand.LiveBundles; ArrayRef UseBlocks = SA->getUseBlocks(); for (unsigned i = 0; i != UseBlocks.size(); ++i) { const SplitAnalysis::BlockInfo &BI = UseBlocks[i]; @@ -591,10 +599,8 @@ GlobalCost += Ins * SpillPlacer->getBlockFrequency(BC.Number); } - InterferenceCache::Cursor Intf(IntfCache, PhysReg); - for (SparseBitVector<>::iterator I = ActiveThroughBlocks.begin(), - E = ActiveThroughBlocks.end(); I != E; ++I) { - unsigned Number = *I; + for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) { + unsigned Number = Cand.ActiveBlocks[i]; bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)]; bool RegOut = LiveBundles[Bundles->getBundle(Number, 1)]; if (!RegIn && !RegOut) @@ -619,18 +625,20 @@ /// avoiding interference. The 'stack' interval is the complement constructed by /// SplitEditor. It will contain the rest. /// -void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, unsigned PhysReg, - const BitVector &LiveBundles, +void RAGreedy::splitAroundRegion(LiveInterval &VirtReg, + GlobalSplitCandidate &Cand, SmallVectorImpl &NewVRegs) { + const BitVector &LiveBundles = Cand.LiveBundles; + DEBUG({ - dbgs() << "Splitting around region for " << PrintReg(PhysReg, TRI) + dbgs() << "Splitting around region for " << PrintReg(Cand.PhysReg, TRI) << " with bundles"; for (int i = LiveBundles.find_first(); i>=0; i = LiveBundles.find_next(i)) dbgs() << " EB#" << i; dbgs() << ".\n"; }); - InterferenceCache::Cursor Intf(IntfCache, PhysReg); + InterferenceCache::Cursor Intf(IntfCache, Cand.PhysReg); LiveRangeEdit LREdit(VirtReg, NewVRegs, this); SE->reset(LREdit); @@ -815,9 +823,8 @@ } // Handle live-through blocks. - for (SparseBitVector<>::iterator I = ActiveThroughBlocks.begin(), - E = ActiveThroughBlocks.end(); I != E; ++I) { - unsigned Number = *I; + for (unsigned i = 0, e = Cand.ActiveBlocks.size(); i != e; ++i) { + unsigned Number = Cand.ActiveBlocks[i]; bool RegIn = LiveBundles[Bundles->getBundle(Number, 0)]; bool RegOut = LiveBundles[Bundles->getBundle(Number, 1)]; DEBUG(dbgs() << "Live through BB#" << Number << '\n'); @@ -850,18 +857,17 @@ unsigned RAGreedy::tryRegionSplit(LiveInterval &VirtReg, AllocationOrder &Order, SmallVectorImpl &NewVRegs) { - BitVector LiveBundles, BestBundles; float BestCost = 0; - unsigned BestReg = 0; - ActiveThroughBlocks.clear(); + const unsigned NoCand = ~0u; + unsigned BestCand = NoCand; Order.rewind(); for (unsigned Cand = 0; unsigned PhysReg = Order.next(); ++Cand) { if (GlobalCand.size() <= Cand) GlobalCand.resize(Cand+1); - GlobalCand[Cand].PhysReg = PhysReg; + GlobalCand[Cand].reset(PhysReg); - SpillPlacer->prepare(LiveBundles); + SpillPlacer->prepare(GlobalCand[Cand].LiveBundles); float Cost; InterferenceCache::Cursor Intf(IntfCache, PhysReg); if (!addSplitConstraints(Intf, Cost)) { @@ -869,38 +875,39 @@ continue; } DEBUG(dbgs() << PrintReg(PhysReg, TRI) << "\tstatic = " << Cost); - if (BestReg && Cost >= BestCost) { - DEBUG(dbgs() << " worse than " << PrintReg(BestReg, TRI) << '\n'); + if (BestCand != NoCand && Cost >= BestCost) { + DEBUG(dbgs() << " worse than " + << PrintReg(GlobalCand[BestCand].PhysReg, TRI) << '\n'); continue; } - growRegion(Intf); + growRegion(GlobalCand[Cand], Intf); SpillPlacer->finish(); // No live bundles, defer to splitSingleBlocks(). - if (!LiveBundles.any()) { + if (!GlobalCand[Cand].LiveBundles.any()) { DEBUG(dbgs() << " no bundles.\n"); continue; } - Cost += calcGlobalSplitCost(PhysReg, LiveBundles); + Cost += calcGlobalSplitCost(GlobalCand[Cand], Intf); DEBUG({ dbgs() << ", total = " << Cost << " with bundles"; - for (int i = LiveBundles.find_first(); i>=0; i = LiveBundles.find_next(i)) + for (int i = GlobalCand[Cand].LiveBundles.find_first(); i>=0; + i = GlobalCand[Cand].LiveBundles.find_next(i)) dbgs() << " EB#" << i; dbgs() << ".\n"; }); - if (!BestReg || Cost < BestCost) { - BestReg = PhysReg; + if (BestCand == NoCand || Cost < BestCost) { + BestCand = Cand; BestCost = 0.98f * Cost; // Prevent rounding effects. - BestBundles.swap(LiveBundles); } } - if (!BestReg) + if (BestCand == NoCand) return 0; - splitAroundRegion(VirtReg, BestReg, BestBundles, NewVRegs); + splitAroundRegion(VirtReg, GlobalCand[BestCand], NewVRegs); setStage(NewVRegs.begin(), NewVRegs.end(), RS_Global); return 0; } Modified: llvm/trunk/lib/CodeGen/SplitKit.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.h?rev=129390&r1=129389&r2=129390&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SplitKit.h (original) +++ llvm/trunk/lib/CodeGen/SplitKit.h Tue Apr 12 16:30:53 2011 @@ -144,6 +144,9 @@ /// isThroughBlock - Return true if CurLI is live through MBB without uses. bool isThroughBlock(unsigned MBB) const { return ThroughBlocks.test(MBB); } + /// getThroughBlocks - Return the set of through blocks. + const BitVector &getThroughBlocks() const { return ThroughBlocks; } + typedef SmallPtrSet BlockPtrSet; /// getMultiUseBlocks - Add basic blocks to Blocks that may benefit from From johnny.chen at apple.com Tue Apr 12 16:41:51 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Apr 2011 21:41:51 -0000 Subject: [llvm-commits] [llvm] r129391 - in /llvm/trunk: lib/Target/ARM/ARMInstrThumb2.td lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110412214151.73F132A6C12D@llvm.org> Author: johnny Date: Tue Apr 12 16:41:51 2011 New Revision: 129391 URL: http://llvm.org/viewvc/llvm-project?rev=129391&view=rev Log: The Thumb2 RFE instructions need to have their second halfword fully specified. In addition, the base register is not rGPR, but GPR with th exception that: if n == 15 then UNPREDICTABLE rdar://problem/9273836 Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=129391&r1=129390&r2=129391&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Apr 12 16:41:51 2011 @@ -3228,19 +3228,20 @@ bits<4> Rn; let Inst{19-16} = Rn; + let Inst{15-0} = 0xc000; } def t2RFEDBW : T2RFE<0b111010000011, - (outs), (ins rGPR:$Rn), NoItinerary, "rfedb", "\t$Rn!", + (outs), (ins GPR:$Rn), NoItinerary, "rfedb", "\t$Rn!", [/* For disassembly only; pattern left blank */]>; def t2RFEDB : T2RFE<0b111010000001, - (outs), (ins rGPR:$Rn), NoItinerary, "rfeab", "\t$Rn", + (outs), (ins GPR:$Rn), NoItinerary, "rfedb", "\t$Rn", [/* For disassembly only; pattern left blank */]>; def t2RFEIAW : T2RFE<0b111010011011, - (outs), (ins rGPR:$Rn), NoItinerary, "rfeia", "\t$Rn!", + (outs), (ins GPR:$Rn), NoItinerary, "rfeia", "\t$Rn!", [/* For disassembly only; pattern left blank */]>; def t2RFEIA : T2RFE<0b111010011001, - (outs), (ins rGPR:$Rn), NoItinerary, "rfeia", "\t$Rn", + (outs), (ins GPR:$Rn), NoItinerary, "rfeia", "\t$Rn", [/* For disassembly only; pattern left blank */]>; //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129391&r1=129390&r2=129391&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Tue Apr 12 16:41:51 2011 @@ -1142,8 +1142,12 @@ // t2RFE[IA|DB]W/t2RFE[IA|DB]: Rn static bool DisassembleThumb2RFE(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); + unsigned Rn = decodeRn(insn); + if (Rn == 15) { + DEBUG(errs() << "if n == 15 then UNPREDICTABLE\n"); + return false; + } + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,ARM::GPRRegClassID,Rn))); NumOpsAdded = 1; return true; } Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129391&r1=129390&r2=129391&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Tue Apr 12 16:41:51 2011 @@ -238,3 +238,6 @@ # CHECK: svc #230 0xe6 0xdf + +# CHECK: rfedb lr +0x1e 0xe8 0x00 0xc0 From jabbey at arxan.com Tue Apr 12 16:49:28 2011 From: jabbey at arxan.com (Joe Abbey) Date: Tue, 12 Apr 2011 17:49:28 -0400 Subject: [llvm-commits] Source register same as write-back base In-Reply-To: References: <88D727341410A44C9E34E8E3EF37D8ED04213C3E@be25.exg3.exghost.com> <12BD8D01-BDE4-4E21-8608-A24EFF90A48C@apple.com> <88D727341410A44C9E34E8E3EF37D8ED0427A419@be25.exg3.exghost.com> <88D727341410A44C9E34E8E3EF37D8ED0427A46C@be25.exg3.exghost.com> Message-ID: <88D727341410A44C9E34E8E3EF37D8ED0427A4CC@be25.exg3.exghost.com> > Do you know exactly which instructions have this constraint? Yep, Every store instruction appears to have at least one encoding which has the unpredictable constraint. The two that are currently tripping me up are: STR ,[{,#+/-}] STR ,[],#+/- But here's an exhaustive list pulled from ARM(r) Architecture Reference Manual ARM(r)v7-A and ARM(r)v7-R edition. A8.6.193 STR (immediate, Thumb) ============================== Encoding T4 ARMv6T2, ARMv7 STR ,[,#-] STR ,[],#+/- STR ,[,#+/-]! if t == 15 || (wback && n == t) then UNPREDICTABLE; A8.6.194 STR (immediate, ARM) ============================== Encoding A1 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STR ,[{,#+/-}] STR ,[],#+/- STR ,[,#+/-]! if wback && (n == 15 || n == t) then UNPREDICTABLE; A8.6.195 STR (register) ============================== Encoding A1 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STR ,[,+/-{, }]{!} STR ,[],+/-{, } if wback && (n == 15 || n == t) then UNPREDICTABLE; if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; A8.6.196 STRB (immediate, Thumb) ============================== Encoding T3 ARMv6T2, ARMv7 STRB ,[,#-] STRB ,[],#+/- STRB ,[,#+/-]! if BadReg(t) || (wback && n == t) then UNPREDICTABLE; A8.6.197 STRB (immediate, ARM) ============================== Encoding A1 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STRB ,[{,#+/-}] STRB ,[],#+/- STRB ,[,#+/-]! if wback && (n == 15 || n == t) then UNPREDICTABLE; A8.6.198 STRB (register) ============================== Encoding A1 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STRB ,[,+/-{, }]{!} STRB ,[],+/-{, } if wback && (n == 15 || n == t) then UNPREDICTABLE; if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; A8.6.199 STRBT ============================== Encoding A1 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STRBT ,[],#+/- if t == 15 || n == 15 || n == t then UNPREDICTABLE; Encoding A2 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STRBT ,[],+/-{, } if t == 15 || n == 15 || n == t || m == 15 then UNPREDICTABLE; if ArchVersion() < 6 && m == n then UNPREDICTABLE; A8.6.200 STRD (immediate) ============================== Encoding T1 ARMv6T2, ARMv7 STRD ,,[{,#+/-}] STRD ,,[],#+/- STRD ,,[,#+/-]! if wback && (n == t || n == t2) then UNPREDICTABLE; Encoding A1 ARMv5TE*, ARMv6*, ARMv7 STRD ,,[{,#+/-}] STRD ,,[],#+/- STRD ,,[,#+/-]! if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; A8.6.201 STRD (register) ============================== Encoding A1 ARMv5TE*, ARMv6*, ARMv7 STRD ,,[,+/-]{!} STRD ,,[],+/- if wback && (n == 15 || n == t || n == t2) then UNPREDICTABLE; if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; A8.6.202 STREX ============================== Encoding T1 ARMv6T2, ARMv7 STREX ,,[{,#}] if d == n || d == t then UNPREDICTABLE; Encoding A1 ARMv6*, ARMv7 STREX ,,[] if d == n || d == t then UNPREDICTABLE; A8.6.203 STREXB ============================== Encoding T1 ARMv7 STREXB ,,[] if d == n || d == t then UNPREDICTABLE; Encoding A1 ARMv6K, ARMv7 STREXB ,,[] if d == n || d == t then UNPREDICTABLE; A8.6.204 STREXD ============================== Encoding T1 ARMv7 STREXD ,,,[] if d == n || d == t || d == t2 then UNPREDICTABLE; Encoding A1 ARMv6K, ARMv7 STREXD ,,,[] if d == n || d == t || d == t2 then UNPREDICTABLE; A8.6.205 STREXH ============================== Encoding T1 ARMv7 STREXH ,,[] if d == n || d == t then UNPREDICTABLE; Encoding A1 ARMv6K, ARMv7 STREXH ,,[] if d == n || d == t then UNPREDICTABLE; A8.6.206 STRH (immediate, Thumb) ============================== Encoding T3 ARMv6T2, ARMv7 STRH ,[,#-] STRH ,[],#+/- STRH ,[,#+/-]! if BadReg(t) || (wback && n == t) then UNPREDICTABLE; A8.6.207 STRH (immediate, ARM) ============================== Encoding A1 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STRH ,[{,#+/-}] STRH ,[],#+/- STRH ,[,#+/-]! if wback && (n == 15 || n == t) then UNPREDICTABLE; A8.6.208 STRH (register) ============================== Encoding A1 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STRH ,[,+/-]{!} STRH ,[],+/- if wback && (n == 15 || n == t) then UNPREDICTABLE; if ArchVersion() < 6 && wback && m == n then UNPREDICTABLE; A8.6.209 STRHT ============================== Encoding A1 ARMv6T2, ARMv7 STRHT , [] {, #+/-} if t == 15 || n == 15 || n == t then UNPREDICTABLE; Encoding A2 ARMv6T2, ARMv7 STRHT , [], +/- if t == 15 || n == 15 || n == t || m == 15 then UNPREDICTABLE; A8.6.210 STRT ============================== Encoding A1 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STRT , [] {, +/-} if n == 15 || n == t then UNPREDICTABLE; Encoding A2 ARMv4*, ARMv5T*, ARMv6*, ARMv7 STRT ,[],+/-{, } if n == 15 || n == t || m == 15 then UNPREDICTABLE; if ArchVersion() < 6 && m == n then UNPREDICTABLE; Cheers, Joe From ofv at wanadoo.es Tue Apr 12 17:10:38 2011 From: ofv at wanadoo.es (Oscar Fuentes) Date: Tue, 12 Apr 2011 22:10:38 -0000 Subject: [llvm-commits] [llvm] r129398 - /llvm/trunk/test/CMakeLists.txt Message-ID: <20110412221038.7911A2A6C12D@llvm.org> Author: ofv Date: Tue Apr 12 17:10:38 2011 New Revision: 129398 URL: http://llvm.org/viewvc/llvm-project?rev=129398&view=rev Log: Fix compiler command line used by lit.py when working with NMake generators. It may improve robustness when testing from VS too. Based on a patch by David Neto! Modified: llvm/trunk/test/CMakeLists.txt Modified: llvm/trunk/test/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CMakeLists.txt?rev=129398&r1=129397&r2=129398&view=diff ============================================================================== --- llvm/trunk/test/CMakeLists.txt (original) +++ llvm/trunk/test/CMakeLists.txt Tue Apr 12 17:10:38 2011 @@ -37,14 +37,32 @@ foreach(INC_DIR ${INC_DIRS}) set(IDIRS "${IDIRS} -I${INC_DIR}") endforeach() - string(REPLACE "" "${CMAKE_CXX_COMPILER}" TEST_COMPILE_CXX_CMD ${CMAKE_CXX_COMPILE_OBJECT}) + + if( MSVC ) + # The compiler's path may contain white space. Wrap it: + string(REPLACE "" "\\\"${CMAKE_CXX_COMPILER}\\\"" TEST_COMPILE_CXX_CMD ${CMAKE_CXX_COMPILE_OBJECT}) + # Eliminate continuation lines from NMake flow. PR9680 + string(REPLACE "@<<\n" " " TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) + string(REPLACE "\n<<" " " TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) + else() + string(REPLACE "" "${CMAKE_CXX_COMPILER}" TEST_COMPILE_CXX_CMD ${CMAKE_CXX_COMPILE_OBJECT}) + endif() + string(REPLACE "" "${DEFS}" TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) string(REPLACE "" "${CMAKE_CXX_FLAGS}" TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) - string(REPLACE "-o" "" TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) + if (MSVC) # PR9680 + # Eliminate MSVC equivalent of -o + string(REPLACE "/Fo" "" TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) + # Eliminate "how to rename program database" argument + string(REPLACE "/Fd" "" TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) + else() + string(REPLACE "-o" "" TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) + endif(MSVC) string(REGEX REPLACE "<[^>]+>" "" TEST_COMPILE_CXX_CMD ${TEST_COMPILE_CXX_CMD}) set(TEST_COMPILE_CXX_CMD "${TEST_COMPILE_CXX_CMD} ${IDIRS}") if(NOT MSVC) set(TEST_COMPILE_CXX_CMD "${TEST_COMPILE_CXX_CMD} -x c++") + # MSVC already has /TP to indicate a C++ source file endif() configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/site.exp.in From kledzik at apple.com Tue Apr 12 17:15:33 2011 From: kledzik at apple.com (Nick Kledzik) Date: Tue, 12 Apr 2011 22:15:33 -0000 Subject: [llvm-commits] [compiler-rt] r129399 - /compiler-rt/tags/Apple/Libcompiler_rt-15/ Message-ID: <20110412221533.2F2922A6C12D@llvm.org> Author: kledzik Date: Tue Apr 12 17:15:33 2011 New Revision: 129399 URL: http://llvm.org/viewvc/llvm-project?rev=129399&view=rev Log: Libcompiler_rt-15 Added: compiler-rt/tags/Apple/Libcompiler_rt-15/ - copied from r129398, compiler-rt/trunk/ From echristo at apple.com Tue Apr 12 17:17:44 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 12 Apr 2011 22:17:44 -0000 Subject: [llvm-commits] [llvm] r129400 - /llvm/trunk/lib/CodeGen/RegAllocFast.cpp Message-ID: <20110412221744.802022A6C12D@llvm.org> Author: echristo Date: Tue Apr 12 17:17:44 2011 New Revision: 129400 URL: http://llvm.org/viewvc/llvm-project?rev=129400&view=rev Log: Add more comments... err debug statements to the fast allocator. Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocFast.cpp?rev=129400&r1=129399&r2=129400&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocFast.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocFast.cpp Tue Apr 12 17:17:44 2011 @@ -420,20 +420,25 @@ // can be allocated directly. // Returns spillImpossible when PhysReg or an alias can't be spilled. unsigned RAFast::calcSpillCost(unsigned PhysReg) const { - if (UsedInInstr.test(PhysReg)) + if (UsedInInstr.test(PhysReg)) { + DEBUG(dbgs() << "PhysReg: " << PhysReg << " is already used in instr.\n"); return spillImpossible; + } switch (unsigned VirtReg = PhysRegState[PhysReg]) { case regDisabled: break; case regFree: return 0; case regReserved: + DEBUG(dbgs() << "VirtReg: " << VirtReg << " corresponding to PhysReg: " + << PhysReg << " is reserved already.\n"); return spillImpossible; default: return LiveVirtRegs.lookup(VirtReg).Dirty ? spillDirty : spillClean; } // This is a disabled register, add up cost of aliases. + DEBUG(dbgs() << "\tRegister: " << PhysReg << " is disabled.\n"); unsigned Cost = 0; for (const unsigned *AS = TRI->getAliasSet(PhysReg); unsigned Alias = *AS; ++AS) { @@ -511,9 +516,14 @@ unsigned BestReg = 0, BestCost = spillImpossible; for (TargetRegisterClass::iterator I = AOB; I != AOE; ++I) { - if (!Allocatable.test(*I)) + if (!Allocatable.test(*I)) { + DEBUG(dbgs() << "\tRegister " << *I << " is not allocatable.\n"); continue; + } unsigned Cost = calcSpillCost(*I); + DEBUG(dbgs() << "\tRegister: " << *I << "\n"); + DEBUG(dbgs() << "\tCost: " << Cost << "\n"); + DEBUG(dbgs() << "\tBestCost: " << BestCost << "\n"); // Cost is 0 when all aliases are already disabled. if (Cost == 0) return assignVirtToPhysReg(LRE, *I); @@ -722,9 +732,12 @@ if (!MO.isReg() || (MO.isDef() && !MO.isEarlyClobber())) continue; unsigned Reg = MO.getReg(); if (!Reg || !TargetRegisterInfo::isPhysicalRegister(Reg)) continue; + DEBUG(dbgs() << "\tSetting reg " << Reg << " as used in instr\n"); UsedInInstr.set(Reg); - for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) + for (const unsigned *AS = TRI->getAliasSet(Reg); *AS; ++AS) { + DEBUG(dbgs() << "\tSetting alias reg " << *AS << " as used in instr\n"); UsedInInstr.set(*AS); + } } // Also mark PartialDefs as used to avoid reallocation. From gohman at apple.com Tue Apr 12 17:45:17 2011 From: gohman at apple.com (Dan Gohman) Date: Tue, 12 Apr 2011 15:45:17 -0700 Subject: [llvm-commits] [PATCH] - Instcombine vector code optimizations In-Reply-To: <6594DDFF12B03D4E89690887C24869940278825A6A@hasmsx504.ger.corp.intel.com> References: <6594DDFF12B03D4E89690887C24869940278825861@hasmsx504.ger.corp.intel.com> <49C5E629-DA52-4FCC-8113-5CB596EFE10F@apple.com> <6594DDFF12B03D4E89690887C24869940278825A6A@hasmsx504.ger.corp.intel.com> Message-ID: <65853F55-A469-4A58-9576-C2802951680A@apple.com> On Apr 7, 2011, at 12:34 PM, Rotem, Nadav wrote: > Hi Dan, > > Thanks for the quick reply. > > 1. If ExtractElem has only one user, then Yes. However, it's not always profitable to break vector casts to multiple scalar casts. Conversions such as i32->float should stay in vector form. I am not sure about vector Zext/Sext/Trunc. I worked on workloads on which the codegen did a better job scalarizing the casts. Generally the GEP optimization is very profitable on my programs. I plan to experiment with other patterns as well. > > 2. Unlike the GEP optimization, I have not seen real-life workloads which benefit from this optimizations. However, adding support for these vector types to the existing optimization was tempting enough to give it a try. The attached LL test has several cases which do get optimized thanks to this optimization. > > I agree that in some cases this optimization may propagate illegal code. I just want to point that the same thing can be said about vectorizing compilers which may generate illegal vector types. I had a discussion with Duncan on making changes to the legalizer in order to support strange types such as <4 x i36> and the infamous <4 x i1> type. Duncan had a plan. In short, he proposed to generalize getTypeAction and getTypeToTransformTo, have them work with a different enum, the enum in LegalizeTypes.h (LegalizeAction). I intend to start working on in next week. I will write you once I have a better understanding of things there. Hi Nadav, Sorry for the late reply. I don't have time to review this further, so I'll just post what I know and let you make an educated judgement about what to do. Most of LLVM's major SIMD users are not public, so it's hard to get broadly representative workloads. Instcombine doesn't currently know what types and operations are legal on the target. In contrast, vectorizers (human, compiler, and hybrid) are essentially required to know a fair amount about the target, because that's the only way to know what's going to be worthwhile. Legalize may be able to help out more, but even then, it won't be able to do everything. Under these circumstances, instcombine should err on the side of trusting the vectorizer, esepcially when it comes to things like folding casts through expressions. On that note, it's worth understanding why your vectorizer is producing Getelementptr (PTR, extract (vcast))) in the first place. Dan From isanbard at gmail.com Tue Apr 12 17:46:32 2011 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 12 Apr 2011 22:46:32 -0000 Subject: [llvm-commits] [llvm] r129401 - in /llvm/trunk: include/llvm/IntrinsicsX86.td lib/Target/X86/X86InstrInfo.cpp lib/Target/X86/X86InstrSSE.td lib/Transforms/InstCombine/InstCombineCalls.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp lib/VMCore/AutoUpgrade.cpp test/Assembler/AutoUpgradeIntrinsics.ll test/CodeGen/X86/avx-intrinsics-x86.ll Message-ID: <20110412224632.36E4F2A6C12D@llvm.org> Author: void Date: Tue Apr 12 17:46:31 2011 New Revision: 129401 URL: http://llvm.org/viewvc/llvm-project?rev=129401&view=rev Log: Remove the unaligned load intrinsics in favor of using native unaligned loads. Now that we have a first-class way to represent unaligned loads, the unaligned load intrinsics are superfluous. First part of . Modified: llvm/trunk/include/llvm/IntrinsicsX86.td llvm/trunk/lib/Target/X86/X86InstrInfo.cpp llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp llvm/trunk/lib/VMCore/AutoUpgrade.cpp llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll Modified: llvm/trunk/include/llvm/IntrinsicsX86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IntrinsicsX86.td?rev=129401&r1=129400&r2=129401&view=diff ============================================================================== --- llvm/trunk/include/llvm/IntrinsicsX86.td (original) +++ llvm/trunk/include/llvm/IntrinsicsX86.td Tue Apr 12 17:46:31 2011 @@ -138,12 +138,6 @@ llvm_x86mmx_ty], [IntrNoMem]>; } -// SIMD load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_loadu_ps : GCCBuiltin<"__builtin_ia32_loadups">, - Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadMem]>; -} - // SIMD store ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">, @@ -452,14 +446,6 @@ Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>; } -// SIMD load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_loadu_pd : GCCBuiltin<"__builtin_ia32_loadupd">, - Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem]>; - def int_x86_sse2_loadu_dq : GCCBuiltin<"__builtin_ia32_loaddqu">, - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; -} - // SIMD store ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">, Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=129401&r1=129400&r2=129401&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue Apr 12 17:46:31 2011 @@ -916,7 +916,6 @@ case X86::MOVSDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MMX_MOVD64rm: @@ -2845,11 +2844,9 @@ case X86::FsMOVAPDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: - case X86::MOVDQUrm_Int: break; } switch (Opc2) { @@ -2869,11 +2866,9 @@ case X86::FsMOVAPDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: - case X86::MOVDQUrm_Int: break; } Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=129401&r1=129400&r2=129401&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Tue Apr 12 17:46:31 2011 @@ -329,15 +329,6 @@ // Intrinsic forms of MOVUPS/D load and store let isAsmParserOnly = 0 in { - let canFoldAsLoad = 1, isReMaterializable = 1 in - def VMOVUPSrm_Int : VPSI<0x10, MRMSrcMem, (outs VR128:$dst), - (ins f128mem:$src), - "movups\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>, VEX; - def VMOVUPDrm_Int : VPDI<0x10, MRMSrcMem, (outs VR128:$dst), - (ins f128mem:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>, VEX; def VMOVUPSmr_Int : VPSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movups\t{$src, $dst|$dst, $src}", @@ -347,13 +338,6 @@ "movupd\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>, VEX; } -let canFoldAsLoad = 1, isReMaterializable = 1 in -def MOVUPSrm_Int : PSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "movups\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>; -def MOVUPDrm_Int : PDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>; def MOVUPSmr_Int : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movups\t{$src, $dst|$dst, $src}", @@ -2229,22 +2213,12 @@ // Intrinsic forms of MOVDQU load and store let isAsmParserOnly = 0 in { -let canFoldAsLoad = 1 in -def VMOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, - XS, VEX, Requires<[HasAVX]>; def VMOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "vmovdqu\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, XS, VEX, Requires<[HasAVX]>; } -let canFoldAsLoad = 1 in -def MOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, - XS, Requires<[HasSSE2]>; def MOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "movdqu\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=129401&r1=129400&r2=129401&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original) +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Tue Apr 12 17:46:31 2011 @@ -537,11 +537,7 @@ break; case Intrinsic::ppc_altivec_lvx: case Intrinsic::ppc_altivec_lvxl: - case Intrinsic::x86_sse_loadu_ps: - case Intrinsic::x86_sse2_loadu_pd: - case Intrinsic::x86_sse2_loadu_dq: - // Turn PPC lvx -> load if the pointer is known aligned. - // Turn X86 loadups -> load if the pointer is known aligned. + // Turn PPC lvx -> load if the pointer is known aligned. if (getOrEnforceKnownAlignment(II->getArgOperand(0), 16, TD) >= 16) { Value *Ptr = Builder->CreateBitCast(II->getArgOperand(0), PointerType::getUnqual(II->getType())); Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=129401&r1=129400&r2=129401&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Tue Apr 12 17:46:31 2011 @@ -572,9 +572,6 @@ switch (II->getIntrinsicID()) { default: break; case Intrinsic::prefetch: - case Intrinsic::x86_sse2_loadu_dq: - case Intrinsic::x86_sse2_loadu_pd: - case Intrinsic::x86_sse_loadu_ps: case Intrinsic::x86_sse_storeu_ps: case Intrinsic::x86_sse2_storeu_pd: case Intrinsic::x86_sse2_storeu_dq: Modified: llvm/trunk/lib/VMCore/AutoUpgrade.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AutoUpgrade.cpp?rev=129401&r1=129400&r2=129401&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/AutoUpgrade.cpp (original) +++ llvm/trunk/lib/VMCore/AutoUpgrade.cpp Tue Apr 12 17:46:31 2011 @@ -527,6 +527,12 @@ // or 0. NewFn = 0; return true; + } else if (Name.compare(5, 16, "x86.sse.loadu.ps", 16) == 0 || + Name.compare(5, 17, "x86.sse2.loadu.dq", 17) == 0 || + Name.compare(5, 17, "x86.sse2.loadu.pd", 17) == 0) { + // Calls to these instructions are transformed into unaligned loads. + NewFn = 0; + return true; } else if (Name.compare(5, 17, "x86.ssse3.pshuf.w", 17) == 0) { // This is an SSE/MMX instruction. const Type *X86_MMXTy = VectorType::getX86_MMXTy(FTy->getContext()); @@ -946,7 +952,29 @@ // Remove upgraded instruction. CI->eraseFromParent(); - + + } else if (F->getName() == "llvm.x86.sse.loadu.ps" || + F->getName() == "llvm.x86.sse2.loadu.dq" || + F->getName() == "llvm.x86.sse2.loadu.pd") { + // Convert to a native, unaligned load. + const Type *VecTy = CI->getType(); + const Type *IntTy = IntegerType::get(C, 128); + IRBuilder<> Builder(C); + Builder.SetInsertPoint(CI->getParent(), CI); + + Value *BC = Builder.CreateBitCast(CI->getArgOperand(0), + PointerType::getUnqual(IntTy), + "cast"); + LoadInst *LI = Builder.CreateLoad(BC, CI->getName()); + LI->setAlignment(1); // Unaligned load. + BC = Builder.CreateBitCast(LI, VecTy, "new.cast"); + + // Fix up all the uses with our new load. + if (!CI->use_empty()) + CI->replaceAllUsesWith(BC); + + // Remove intrinsic. + CI->eraseFromParent(); } else { llvm_unreachable("Unknown function for CallInst upgrade."); } Modified: llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll?rev=129401&r1=129400&r2=129401&view=diff ============================================================================== --- llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll (original) +++ llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll Tue Apr 12 17:46:31 2011 @@ -7,6 +7,8 @@ ; RUN: llvm-as < %s | llvm-dis | \ ; RUN: not grep {llvm\\.bswap\\.i\[0-9\]*\\.i\[0-9\]*} ; RUN: llvm-as < %s | llvm-dis | \ +; RUN: not grep {llvm\\.x86\\.sse2\\.loadu} +; RUN: llvm-as < %s | llvm-dis | \ ; RUN: grep {llvm\\.x86\\.mmx\\.ps} | grep {x86_mmx} | count 16 declare i32 @llvm.ctpop.i28(i28 %val) @@ -79,3 +81,13 @@ %r2 = call <1 x i64> @llvm.x86.mmx.psrl.q( <1 x i64> %A, <2 x i32> %B ) ; <<1 x i64>> [#uses=0] ret void } + +declare <4 x float> @llvm.x86.sse.loadu.ps(i8*) nounwind readnone +declare <16 x i8> @llvm.x86.sse2.loadu.dq(i8*) nounwind readnone +declare <2 x double> @llvm.x86.sse2.loadu.pd(double*) nounwind readnone +define void @test_loadu(i8* %a, double* %b) { + %v0 = call <4 x float> @llvm.x86.sse.loadu.ps(i8* %a) + %v1 = call <16 x i8> @llvm.x86.sse2.loadu.dq(i8* %a) + %v2 = call <2 x double> @llvm.x86.sse2.loadu.pd(double* %b) + ret void +} Modified: llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll?rev=129401&r1=129400&r2=129401&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll Tue Apr 12 17:46:31 2011 @@ -247,7 +247,7 @@ define <16 x i8> @test_x86_sse2_loadu_dq(i8* %a0) { ; CHECK: movl - ; CHECK: vmovdqu + ; CHECK: vmovups %res = call <16 x i8> @llvm.x86.sse2.loadu.dq(i8* %a0) ; <<16 x i8>> [#uses=1] ret <16 x i8> %res } @@ -256,7 +256,7 @@ define <2 x double> @test_x86_sse2_loadu_pd(i8* %a0) { ; CHECK: movl - ; CHECK: vmovupd + ; CHECK: vmovups %res = call <2 x double> @llvm.x86.sse2.loadu.pd(i8* %a0) ; <<2 x double>> [#uses=1] ret <2 x double> %res } From dpatel at apple.com Tue Apr 12 17:53:02 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 12 Apr 2011 22:53:02 -0000 Subject: [llvm-commits] [llvm] r129402 - in /llvm/trunk/lib/CodeGen/AsmPrinter: CMakeLists.txt DwarfCompileUnit.h DwarfDebug.cpp DwarfDebug.h Message-ID: <20110412225302.E703D2A6C12D@llvm.org> Author: dpatel Date: Tue Apr 12 17:53:02 2011 New Revision: 129402 URL: http://llvm.org/viewvc/llvm-project?rev=129402&view=rev Log: This mechanical patch moves type handling into CompileUnit from DwarfDebug. In case of multiple compile unit in one object file, each compile unit is responsible for its own set of type entries anyway. This refactoring makes this obvious. Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt?rev=129402&r1=129401&r2=129402&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt Tue Apr 12 17:53:02 2011 @@ -5,6 +5,7 @@ AsmPrinterInlineAsm.cpp DIE.cpp DwarfCFIException.cpp + DwarfCompileUnit.cpp DwarfDebug.cpp DwarfException.cpp DwarfTableException.cpp Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h?rev=129402&r1=129401&r2=129402&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Tue Apr 12 17:53:02 2011 @@ -15,12 +15,19 @@ #define CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H #include "DIE.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/OwningPtr.h" namespace llvm { +class DwarfDebug; +class MachineLocation; +class MachineOperand; +class ConstantInt; +class DbgVariable; + //===----------------------------------------------------------------------===// /// CompileUnit - This dwarf writer support class manages information associate /// with a source file. @@ -33,6 +40,11 @@ /// const OwningPtr CUDie; + /// Asm - Target of Dwarf emission. + AsmPrinter *Asm; + + DwarfDebug *DD; + /// IndexTyDie - An anonymous type for index type. Owned by CUDie. DIE *IndexTyDie; @@ -52,9 +64,12 @@ /// StringMap GlobalTypes; + /// DIEBlocks - A list of all the DIEBlocks in use. + std::vector DIEBlocks; + public: - CompileUnit(unsigned I, DIE *D) - : ID(I), CUDie(D), IndexTyDie(0) {} + CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *D); + ~CompileUnit(); // Accessors. unsigned getID() const { return ID; } @@ -80,6 +95,10 @@ /// specified debug variable. DIE *getDIE(const MDNode *N) { return MDNodeToDieMap.lookup(N); } + DIEBlock *getDIEBlock() { + return new (DIEValueAllocator) DIEBlock(); + } + /// insertDIE - Insert DIE into the map. void insertDIE(const MDNode *N, DIE *D) { MDNodeToDieMap.insert(std::make_pair(N, D)); @@ -116,7 +135,144 @@ void setIndexTyDie(DIE *D) { IndexTyDie = D; } +public: + + /// addUInt - Add an unsigned integer attribute data and value. + /// + void addUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer); + + /// addSInt - Add an signed integer attribute data and value. + /// + void addSInt(DIE *Die, unsigned Attribute, unsigned Form, int64_t Integer); + + /// addString - Add a string attribute data and value. + /// + void addString(DIE *Die, unsigned Attribute, unsigned Form, + const StringRef Str); + + /// addLabel - Add a Dwarf label attribute data and value. + /// + void addLabel(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Label); + + /// addDelta - Add a label delta attribute data and value. + /// + void addDelta(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Hi, const MCSymbol *Lo); + + /// addDIEEntry - Add a DIE attribute data and value. + /// + void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry); + + /// addBlock - Add block data. + /// + void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); + + /// addSourceLine - Add location information to specified debug information + /// entry. + void addSourceLine(DIE *Die, DIVariable V); + void addSourceLine(DIE *Die, DIGlobalVariable G); + void addSourceLine(DIE *Die, DISubprogram SP); + void addSourceLine(DIE *Die, DIType Ty); + void addSourceLine(DIE *Die, DINameSpace NS); + + /// addAddress - Add an address attribute to a die based on the location + /// provided. + void addAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + /// addRegisterAddress - Add register location entry in variable DIE. + bool addRegisterAddress(DIE *Die, const MachineOperand &MO); + + /// addConstantValue - Add constant value entry in variable DIE. + bool addConstantValue(DIE *Die, const MachineOperand &MO); + bool addConstantValue(DIE *Die, ConstantInt *CI, bool Unsigned); + + /// addConstantFPValue - Add constant value entry in variable DIE. + bool addConstantFPValue(DIE *Die, const MachineOperand &MO); + + /// addTemplateParams - Add template parameters in buffer. + void addTemplateParams(DIE &Buffer, DIArray TParams); + + /// addComplexAddress - Start with the address based on the location provided, + /// and generate the DWARF information necessary to find the actual variable + /// (navigating the extra location information encoded in the type) based on + /// the starting location. Add the DWARF information to the die. + /// + void addComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + // FIXME: Should be reformulated in terms of addComplexAddress. + /// addBlockByrefAddress - Start with the address based on the location + /// provided, and generate the DWARF information necessary to find the + /// actual Block variable (navigating the Block struct) based on the + /// starting location. Add the DWARF information to the die. Obsolete, + /// please use addComplexAddress instead. + /// + void addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, + const MachineLocation &Location); + + /// addVariableAddress - Add DW_AT_location attribute for a DbgVariable based + /// on provided frame index. + void addVariableAddress(DbgVariable *&DV, DIE *Die, int64_t FI); + + /// addToContextOwner - Add Die into the list of its context owner's children. + void addToContextOwner(DIE *Die, DIDescriptor Context); + + /// addType - Add a new type attribute to the specified entity. + void addType(DIE *Entity, DIType Ty); + + /// getOrCreateNameSpace - Create a DIE for DINameSpace. + DIE *getOrCreateNameSpace(DINameSpace NS); + + /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the + /// given DIType. + DIE *getOrCreateTypeDIE(DIType Ty); + + /// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE + /// for the given DITemplateTypeParameter. + DIE *getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP); + + /// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE + /// for the given DITemplateValueParameter. + DIE *getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TVP); + + /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug + /// information entry. + DIEEntry *createDIEEntry(DIE *Entry); + + void addPubTypes(DISubprogram SP); + + /// constructTypeDIE - Construct basic type die from DIBasicType. + void constructTypeDIE(DIE &Buffer, + DIBasicType BTy); + + /// constructTypeDIE - Construct derived type die from DIDerivedType. + void constructTypeDIE(DIE &Buffer, + DIDerivedType DTy); + + /// constructTypeDIE - Construct type DIE from DICompositeType. + void constructTypeDIE(DIE &Buffer, + DICompositeType CTy); + + /// constructSubrangeDIE - Construct subrange DIE from DISubrange. + void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); + + /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. + void constructArrayTypeDIE(DIE &Buffer, + DICompositeType *CTy); + + /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. + DIE *constructEnumTypeDIE(DIEnumerator ETy); + + /// createMemberDIE - Create new member DIE. + DIE *createMemberDIE(DIDerivedType DT); + +private: + // DIEValueAllocator - All DIEValues are allocated through this allocator. + BumpPtrAllocator DIEValueAllocator; + DIEInteger *DIEIntegerOne; }; } // end llvm namespace Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=129402&r1=129401&r2=129402&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Apr 12 17:53:02 2011 @@ -73,91 +73,56 @@ namespace llvm { -//===----------------------------------------------------------------------===// -/// DbgVariable - This class is used to track local variable information. -/// -class DbgVariable { - DIVariable Var; // Variable Descriptor. - DIE *TheDIE; // Variable DIE. - unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. -public: - // AbsVar may be NULL. - DbgVariable(DIVariable V) : Var(V), TheDIE(0), DotDebugLocOffset(~0U) {} - - // Accessors. - DIVariable getVariable() const { return Var; } - void setDIE(DIE *D) { TheDIE = D; } - DIE *getDIE() const { return TheDIE; } - void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } - unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } - StringRef getName() const { return Var.getName(); } - unsigned getTag() const { return Var.getTag(); } - bool variableHasComplexAddress() const { - assert(Var.Verify() && "Invalid complex DbgVariable!"); - return Var.hasComplexAddress(); - } - bool isBlockByrefVariable() const { - assert(Var.Verify() && "Invalid complex DbgVariable!"); - return Var.isBlockByrefVariable(); - } - unsigned getNumAddrElements() const { - assert(Var.Verify() && "Invalid complex DbgVariable!"); - return Var.getNumAddrElements(); - } - uint64_t getAddrElement(unsigned i) const { - return Var.getAddrElement(i); - } - DIType getType() const { - DIType Ty = Var.getType(); - // FIXME: isBlockByrefVariable should be reformulated in terms of complex - // addresses instead. - if (Var.isBlockByrefVariable()) { - /* Byref variables, in Blocks, are declared by the programmer as - "SomeType VarName;", but the compiler creates a - __Block_byref_x_VarName struct, and gives the variable VarName - either the struct, or a pointer to the struct, as its type. This - is necessary for various behind-the-scenes things the compiler - needs to do with by-reference variables in blocks. - - However, as far as the original *programmer* is concerned, the - variable should still have type 'SomeType', as originally declared. - - The following function dives into the __Block_byref_x_VarName - struct to find the original type of the variable. This will be - passed back to the code generating the type for the Debug - Information Entry for the variable 'VarName'. 'VarName' will then - have the original type 'SomeType' in its debug information. - - The original type 'SomeType' will be the type of the field named - 'VarName' inside the __Block_byref_x_VarName struct. - - NOTE: In order for this to not completely fail on the debugger - side, the Debug Information Entry for the variable VarName needs to - have a DW_AT_location that tells the debugger how to unwind through - the pointers and __Block_byref_x_VarName struct to find the actual - value of the variable. The function addBlockByrefType does this. */ - DIType subType = Ty; - unsigned tag = Ty.getTag(); - - if (tag == dwarf::DW_TAG_pointer_type) { - DIDerivedType DTy = DIDerivedType(Ty); - subType = DTy.getTypeDerivedFrom(); - } - - DICompositeType blockStruct = DICompositeType(subType); - DIArray Elements = blockStruct.getTypeArray(); - - for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Element = Elements.getElement(i); - DIDerivedType DT = DIDerivedType(Element); - if (getName() == DT.getName()) - return (DT.getTypeDerivedFrom()); - } - return Ty; +DIType DbgVariable::getType() const { + DIType Ty = Var.getType(); + // FIXME: isBlockByrefVariable should be reformulated in terms of complex + // addresses instead. + if (Var.isBlockByrefVariable()) { + /* Byref variables, in Blocks, are declared by the programmer as + "SomeType VarName;", but the compiler creates a + __Block_byref_x_VarName struct, and gives the variable VarName + either the struct, or a pointer to the struct, as its type. This + is necessary for various behind-the-scenes things the compiler + needs to do with by-reference variables in blocks. + + However, as far as the original *programmer* is concerned, the + variable should still have type 'SomeType', as originally declared. + + The following function dives into the __Block_byref_x_VarName + struct to find the original type of the variable. This will be + passed back to the code generating the type for the Debug + Information Entry for the variable 'VarName'. 'VarName' will then + have the original type 'SomeType' in its debug information. + + The original type 'SomeType' will be the type of the field named + 'VarName' inside the __Block_byref_x_VarName struct. + + NOTE: In order for this to not completely fail on the debugger + side, the Debug Information Entry for the variable VarName needs to + have a DW_AT_location that tells the debugger how to unwind through + the pointers and __Block_byref_x_VarName struct to find the actual + value of the variable. The function addBlockByrefType does this. */ + DIType subType = Ty; + unsigned tag = Ty.getTag(); + + if (tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty); + subType = DTy.getTypeDerivedFrom(); + } + + DICompositeType blockStruct = DICompositeType(subType); + DIArray Elements = blockStruct.getTypeArray(); + + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIDerivedType DT = DIDerivedType(Element); + if (getName() == DT.getName()) + return (DT.getTypeDerivedFrom()); } return Ty; } -}; + return Ty; +} //===----------------------------------------------------------------------===// /// DbgRange - This is used to track range of instructions with identical @@ -299,15 +264,12 @@ DwarfStrSectionSym = TextSectionSym = 0; DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = 0; FunctionBeginSym = FunctionEndSym = 0; - DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); beginModule(M); } } DwarfDebug::~DwarfDebug() { - for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) - DIEBlocks[j]->~DIEBlock(); } MCSymbol *DwarfDebug::getStringPoolEntry(StringRef Str) { @@ -342,867 +304,6 @@ } } -/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug -/// information entry. -DIEEntry *DwarfDebug::createDIEEntry(DIE *Entry) { - DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry); - return Value; -} - -/// addUInt - Add an unsigned integer attribute data and value. -/// -void DwarfDebug::addUInt(DIE *Die, unsigned Attribute, - unsigned Form, uint64_t Integer) { - if (!Form) Form = DIEInteger::BestForm(false, Integer); - DIEValue *Value = Integer == 1 ? - DIEIntegerOne : new (DIEValueAllocator) DIEInteger(Integer); - Die->addValue(Attribute, Form, Value); -} - -/// addSInt - Add an signed integer attribute data and value. -/// -void DwarfDebug::addSInt(DIE *Die, unsigned Attribute, - unsigned Form, int64_t Integer) { - if (!Form) Form = DIEInteger::BestForm(true, Integer); - DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer); - Die->addValue(Attribute, Form, Value); -} - -/// addString - Add a string attribute data and value. DIEString only -/// keeps string reference. -void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form, - StringRef String) { - DIEValue *Value = new (DIEValueAllocator) DIEString(String); - Die->addValue(Attribute, Form, Value); -} - -/// addLabel - Add a Dwarf label attribute data and value. -/// -void DwarfDebug::addLabel(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Label) { - DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); - Die->addValue(Attribute, Form, Value); -} - -/// addDelta - Add a label delta attribute data and value. -/// -void DwarfDebug::addDelta(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Hi, const MCSymbol *Lo) { - DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); - Die->addValue(Attribute, Form, Value); -} - -/// addDIEEntry - Add a DIE attribute data and value. -/// -void DwarfDebug::addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, - DIE *Entry) { - Die->addValue(Attribute, Form, createDIEEntry(Entry)); -} - - -/// addBlock - Add block data. -/// -void DwarfDebug::addBlock(DIE *Die, unsigned Attribute, unsigned Form, - DIEBlock *Block) { - Block->ComputeSize(Asm); - DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. - Die->addValue(Attribute, Block->BestForm(), Block); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DIVariable V) { - // Verify variable. - if (!V.Verify()) - return; - - unsigned Line = V.getLineNumber(); - if (Line == 0) - return; - unsigned FileID = GetOrCreateSourceID(V.getContext().getFilename(), - V.getContext().getDirectory()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DIGlobalVariable G) { - // Verify global variable. - if (!G.Verify()) - return; - - unsigned Line = G.getLineNumber(); - if (Line == 0) - return; - unsigned FileID = GetOrCreateSourceID(G.getContext().getFilename(), - G.getContext().getDirectory()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DISubprogram SP) { - // Verify subprogram. - if (!SP.Verify()) - return; - // If the line number is 0, don't add it. - if (SP.getLineNumber() == 0) - return; - - unsigned Line = SP.getLineNumber(); - if (!SP.getContext().Verify()) - return; - unsigned FileID = GetOrCreateSourceID(SP.getFilename(), SP.getDirectory()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DIType Ty) { - // Verify type. - if (!Ty.Verify()) - return; - - unsigned Line = Ty.getLineNumber(); - if (Line == 0 || !Ty.getContext().Verify()) - return; - unsigned FileID = GetOrCreateSourceID(Ty.getFilename(), Ty.getDirectory()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addSourceLine - Add location information to specified debug information -/// entry. -void DwarfDebug::addSourceLine(DIE *Die, DINameSpace NS) { - // Verify namespace. - if (!NS.Verify()) - return; - - unsigned Line = NS.getLineNumber(); - if (Line == 0) - return; - StringRef FN = NS.getFilename(); - - unsigned FileID = GetOrCreateSourceID(FN, NS.getDirectory()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); -} - -/// addVariableAddress - Add DW_AT_location attribute for a DbgVariable based -/// on provided frame index. -void DwarfDebug::addVariableAddress(DbgVariable *&DV, DIE *Die, int64_t FI) { - MachineLocation Location; - unsigned FrameReg; - const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); - int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); - Location.set(FrameReg, Offset); - - if (DV->variableHasComplexAddress()) - addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); - else if (DV->isBlockByrefVariable()) - addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); - else - addAddress(Die, dwarf::DW_AT_location, Location); -} - -/// addComplexAddress - Start with the address based on the location provided, -/// and generate the DWARF information necessary to find the actual variable -/// given the extra address information encoded in the DIVariable, starting from -/// the starting location. Add the DWARF information to the die. -/// -void DwarfDebug::addComplexAddress(DbgVariable *&DV, DIE *Die, - unsigned Attribute, - const MachineLocation &Location) { - DIType Ty = DV->getType(); - - // Decode the original location, and use that as the start of the byref - // variable's location. - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); - unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - - if (Location.isReg()) { - if (Reg < 32) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); - } else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - } else { - if (Reg < 32) - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); - else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - - addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); - } - - for (unsigned i = 0, N = DV->getNumAddrElements(); i < N; ++i) { - uint64_t Element = DV->getAddrElement(i); - - if (Element == DIBuilder::OpPlus) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i)); - } else if (Element == DIBuilder::OpDeref) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - } else llvm_unreachable("unknown DIBuilder Opcode"); - } - - // Now attach the location information to the DIE. - addBlock(Die, Attribute, 0, Block); -} - -/* Byref variables, in Blocks, are declared by the programmer as "SomeType - VarName;", but the compiler creates a __Block_byref_x_VarName struct, and - gives the variable VarName either the struct, or a pointer to the struct, as - its type. This is necessary for various behind-the-scenes things the - compiler needs to do with by-reference variables in Blocks. - - However, as far as the original *programmer* is concerned, the variable - should still have type 'SomeType', as originally declared. - - The function getBlockByrefType dives into the __Block_byref_x_VarName - struct to find the original type of the variable, which is then assigned to - the variable's Debug Information Entry as its real type. So far, so good. - However now the debugger will expect the variable VarName to have the type - SomeType. So we need the location attribute for the variable to be an - expression that explains to the debugger how to navigate through the - pointers and struct to find the actual variable of type SomeType. - - The following function does just that. We start by getting - the "normal" location for the variable. This will be the location - of either the struct __Block_byref_x_VarName or the pointer to the - struct __Block_byref_x_VarName. - - The struct will look something like: - - struct __Block_byref_x_VarName { - ... - struct __Block_byref_x_VarName *forwarding; - ... - SomeType VarName; - ... - }; - - If we are given the struct directly (as our starting point) we - need to tell the debugger to: - - 1). Add the offset of the forwarding field. - - 2). Follow that pointer to get the real __Block_byref_x_VarName - struct to use (the real one may have been copied onto the heap). - - 3). Add the offset for the field VarName, to find the actual variable. - - If we started with a pointer to the struct, then we need to - dereference that pointer first, before the other steps. - Translating this into DWARF ops, we will need to append the following - to the current location description for the variable: - - DW_OP_deref -- optional, if we start with a pointer - DW_OP_plus_uconst - DW_OP_deref - DW_OP_plus_uconst - - That is what this function does. */ - -/// addBlockByrefAddress - Start with the address based on the location -/// provided, and generate the DWARF information necessary to find the -/// actual Block variable (navigating the Block struct) based on the -/// starting location. Add the DWARF information to the die. For -/// more information, read large comment just above here. -/// -void DwarfDebug::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, - unsigned Attribute, - const MachineLocation &Location) { - DIType Ty = DV->getType(); - DIType TmpTy = Ty; - unsigned Tag = Ty.getTag(); - bool isPointer = false; - - StringRef varName = DV->getName(); - - if (Tag == dwarf::DW_TAG_pointer_type) { - DIDerivedType DTy = DIDerivedType(Ty); - TmpTy = DTy.getTypeDerivedFrom(); - isPointer = true; - } - - DICompositeType blockStruct = DICompositeType(TmpTy); - - // Find the __forwarding field and the variable field in the __Block_byref - // struct. - DIArray Fields = blockStruct.getTypeArray(); - DIDescriptor varField = DIDescriptor(); - DIDescriptor forwardingField = DIDescriptor(); - - for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { - DIDescriptor Element = Fields.getElement(i); - DIDerivedType DT = DIDerivedType(Element); - StringRef fieldName = DT.getName(); - if (fieldName == "__forwarding") - forwardingField = Element; - else if (fieldName == varName) - varField = Element; - } - - // Get the offsets for the forwarding field and the variable field. - unsigned forwardingFieldOffset = - DIDerivedType(forwardingField).getOffsetInBits() >> 3; - unsigned varFieldOffset = - DIDerivedType(varField).getOffsetInBits() >> 3; - - // Decode the original location, and use that as the start of the byref - // variable's location. - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); - unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - - if (Location.isReg()) { - if (Reg < 32) - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); - else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - } else { - if (Reg < 32) - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); - else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - - addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); - } - - // If we started with a pointer to the __Block_byref... struct, then - // the first thing we need to do is dereference the pointer (DW_OP_deref). - if (isPointer) - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - - // Next add the offset for the '__forwarding' field: - // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in - // adding the offset if it's 0. - if (forwardingFieldOffset > 0) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset); - } - - // Now dereference the __forwarding field to get to the real __Block_byref - // struct: DW_OP_deref. - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - - // Now that we've got the real __Block_byref... struct, add the offset - // for the variable's field to get to the location of the actual variable: - // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. - if (varFieldOffset > 0) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset); - } - - // Now attach the location information to the DIE. - addBlock(Die, Attribute, 0, Block); -} - -/// addAddress - Add an address attribute to a die based on the location -/// provided. -void DwarfDebug::addAddress(DIE *Die, unsigned Attribute, - const MachineLocation &Location) { - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); - unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - - if (RI->getFrameRegister(*Asm->MF) == Location.getReg() - && Location.getOffset()) { - // If variable offset is based in frame register then use fbreg. - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg); - addSInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); - addBlock(Die, Attribute, 0, Block); - return; - } - - if (Location.isReg()) { - if (Reg < 32) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); - } else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - } else { - if (Reg < 32) { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); - } else { - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); - addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); - } - - addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); - } - - addBlock(Die, Attribute, 0, Block); -} - -/// addRegisterAddress - Add register location entry in variable DIE. -bool DwarfDebug::addRegisterAddress(DIE *Die, const MachineOperand &MO) { - assert (MO.isReg() && "Invalid machine operand!"); - if (!MO.getReg()) - return false; - MachineLocation Location; - Location.set(MO.getReg()); - addAddress(Die, dwarf::DW_AT_location, Location); - return true; -} - -/// addConstantValue - Add constant value entry in variable DIE. -bool DwarfDebug::addConstantValue(DIE *Die, const MachineOperand &MO) { - assert (MO.isImm() && "Invalid machine operand!"); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - unsigned Imm = MO.getImm(); - addUInt(Block, 0, dwarf::DW_FORM_udata, Imm); - addBlock(Die, dwarf::DW_AT_const_value, 0, Block); - return true; -} - -/// addConstantFPValue - Add constant value entry in variable DIE. -bool DwarfDebug::addConstantFPValue(DIE *Die, const MachineOperand &MO) { - assert (MO.isFPImm() && "Invalid machine operand!"); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - APFloat FPImm = MO.getFPImm()->getValueAPF(); - - // Get the raw data form of the floating point. - const APInt FltVal = FPImm.bitcastToAPInt(); - const char *FltPtr = (const char*)FltVal.getRawData(); - - int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. - bool LittleEndian = Asm->getTargetData().isLittleEndian(); - int Incr = (LittleEndian ? 1 : -1); - int Start = (LittleEndian ? 0 : NumBytes - 1); - int Stop = (LittleEndian ? NumBytes : -1); - - // Output the constant to DWARF one byte at a time. - for (; Start != Stop; Start += Incr) - addUInt(Block, 0, dwarf::DW_FORM_data1, - (unsigned char)0xFF & FltPtr[Start]); - - addBlock(Die, dwarf::DW_AT_const_value, 0, Block); - return true; -} - -/// addConstantValue - Add constant value entry in variable DIE. -bool DwarfDebug::addConstantValue(DIE *Die, ConstantInt *CI, - bool Unsigned) { - if (CI->getBitWidth() <= 64) { - if (Unsigned) - addUInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, - CI->getZExtValue()); - else - addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, - CI->getSExtValue()); - return true; - } - - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - - // Get the raw data form of the large APInt. - const APInt Val = CI->getValue(); - const char *Ptr = (const char*)Val.getRawData(); - - int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte. - bool LittleEndian = Asm->getTargetData().isLittleEndian(); - int Incr = (LittleEndian ? 1 : -1); - int Start = (LittleEndian ? 0 : NumBytes - 1); - int Stop = (LittleEndian ? NumBytes : -1); - - // Output the constant to DWARF one byte at a time. - for (; Start != Stop; Start += Incr) - addUInt(Block, 0, dwarf::DW_FORM_data1, - (unsigned char)0xFF & Ptr[Start]); - - addBlock(Die, dwarf::DW_AT_const_value, 0, Block); - return true; -} - -/// addTemplateParams - Add template parameters in buffer. -void DwarfDebug::addTemplateParams(DIE &Buffer, DIArray TParams) { - // Add template parameters. - for (unsigned i = 0, e = TParams.getNumElements(); i != e; ++i) { - DIDescriptor Element = TParams.getElement(i); - if (Element.isTemplateTypeParameter()) - Buffer.addChild(getOrCreateTemplateTypeParameterDIE( - DITemplateTypeParameter(Element))); - else if (Element.isTemplateValueParameter()) - Buffer.addChild(getOrCreateTemplateValueParameterDIE( - DITemplateValueParameter(Element))); - } - -} -/// addToContextOwner - Add Die into the list of its context owner's children. -void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) { - if (Context.isType()) { - DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context)); - ContextDIE->addChild(Die); - } else if (Context.isNameSpace()) { - DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context)); - ContextDIE->addChild(Die); - } else if (Context.isSubprogram()) { - DIE *ContextDIE = createSubprogramDIE(DISubprogram(Context)); - ContextDIE->addChild(Die); - } else if (DIE *ContextDIE = getCompileUnit(Context)->getDIE(Context)) - ContextDIE->addChild(Die); - else - getCompileUnit(Context)->addDie(Die); -} - -/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the -/// given DIType. -DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) { - CompileUnit *TypeCU = getCompileUnit(Ty); - DIE *TyDIE = TypeCU->getDIE(Ty); - if (TyDIE) - return TyDIE; - - // Create new type. - TyDIE = new DIE(dwarf::DW_TAG_base_type); - TypeCU->insertDIE(Ty, TyDIE); - if (Ty.isBasicType()) - constructTypeDIE(*TyDIE, DIBasicType(Ty)); - else if (Ty.isCompositeType()) - constructTypeDIE(*TyDIE, DICompositeType(Ty)); - else { - assert(Ty.isDerivedType() && "Unknown kind of DIType"); - constructTypeDIE(*TyDIE, DIDerivedType(Ty)); - } - - addToContextOwner(TyDIE, Ty.getContext()); - return TyDIE; -} - -/// addType - Add a new type attribute to the specified entity. -void DwarfDebug::addType(DIE *Entity, DIType Ty) { - if (!Ty.Verify()) - return; - - // Check for pre-existence. - CompileUnit *TypeCU = getCompileUnit(Ty); - DIEEntry *Entry = TypeCU->getDIEEntry(Ty); - // If it exists then use the existing value. - if (Entry) { - Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); - return; - } - - // Construct type. - DIE *Buffer = getOrCreateTypeDIE(Ty); - - // Set up proxy. - Entry = createDIEEntry(Buffer); - TypeCU->insertDIEEntry(Ty, Entry); - - Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); -} - -/// constructTypeDIE - Construct basic type die from DIBasicType. -void DwarfDebug::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { - // Get core information. - StringRef Name = BTy.getName(); - Buffer.setTag(dwarf::DW_TAG_base_type); - addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - BTy.getEncoding()); - - // Add name if not anonymous or intermediate type. - if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - uint64_t Size = BTy.getSizeInBits() >> 3; - addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); -} - -/// constructTypeDIE - Construct derived type die from DIDerivedType. -void DwarfDebug::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { - // Get core information. - StringRef Name = DTy.getName(); - uint64_t Size = DTy.getSizeInBits() >> 3; - unsigned Tag = DTy.getTag(); - - // FIXME - Workaround for templates. - if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type; - - Buffer.setTag(Tag); - - // Map to main type, void will not have a type. - DIType FromTy = DTy.getTypeDerivedFrom(); - addType(&Buffer, FromTy); - - // Add name if not anonymous or intermediate type. - if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - - // Add size if non-zero (derived types might be zero-sized.) - if (Size) - addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); - - // Add source line info if available and TyDesc is not a forward declaration. - if (!DTy.isForwardDecl()) - addSourceLine(&Buffer, DTy); -} - -/// constructTypeDIE - Construct type DIE from DICompositeType. -void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { - // Get core information. - StringRef Name = CTy.getName(); - - uint64_t Size = CTy.getSizeInBits() >> 3; - unsigned Tag = CTy.getTag(); - Buffer.setTag(Tag); - - switch (Tag) { - case dwarf::DW_TAG_vector_type: - case dwarf::DW_TAG_array_type: - constructArrayTypeDIE(Buffer, &CTy); - break; - case dwarf::DW_TAG_enumeration_type: { - DIArray Elements = CTy.getTypeArray(); - - // Add enumerators to enumeration type. - for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { - DIE *ElemDie = NULL; - DIDescriptor Enum(Elements.getElement(i)); - if (Enum.isEnumerator()) { - ElemDie = constructEnumTypeDIE(DIEnumerator(Enum)); - Buffer.addChild(ElemDie); - } - } - } - break; - case dwarf::DW_TAG_subroutine_type: { - // Add return type. - DIArray Elements = CTy.getTypeArray(); - DIDescriptor RTy = Elements.getElement(0); - addType(&Buffer, DIType(RTy)); - - bool isPrototyped = true; - // Add arguments. - for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Ty = Elements.getElement(i); - if (Ty.isUnspecifiedParameter()) { - DIE *Arg = new DIE(dwarf::DW_TAG_unspecified_parameters); - Buffer.addChild(Arg); - isPrototyped = false; - } else { - DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); - addType(Arg, DIType(Ty)); - Buffer.addChild(Arg); - } - } - // Add prototype flag. - if (isPrototyped) - addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); - } - break; - case dwarf::DW_TAG_structure_type: - case dwarf::DW_TAG_union_type: - case dwarf::DW_TAG_class_type: { - // Add elements to structure type. - DIArray Elements = CTy.getTypeArray(); - - // A forward struct declared type may not have elements available. - unsigned N = Elements.getNumElements(); - if (N == 0) - break; - - // Add elements to structure type. - for (unsigned i = 0; i < N; ++i) { - DIDescriptor Element = Elements.getElement(i); - DIE *ElemDie = NULL; - if (Element.isSubprogram()) { - DISubprogram SP(Element); - ElemDie = createSubprogramDIE(DISubprogram(Element)); - if (SP.isProtected()) - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_protected); - else if (SP.isPrivate()) - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_private); - else - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_public); - if (SP.isExplicit()) - addUInt(ElemDie, dwarf::DW_AT_explicit, dwarf::DW_FORM_flag, 1); - } - else if (Element.isVariable()) { - DIVariable DV(Element); - ElemDie = new DIE(dwarf::DW_TAG_variable); - addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, - DV.getName()); - addType(ElemDie, DV.getType()); - addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); - addSourceLine(ElemDie, DV); - } else if (Element.isDerivedType()) - ElemDie = createMemberDIE(DIDerivedType(Element)); - else - continue; - Buffer.addChild(ElemDie); - } - - if (CTy.isAppleBlockExtension()) - addUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1); - - unsigned RLang = CTy.getRunTimeLang(); - if (RLang) - addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, - dwarf::DW_FORM_data1, RLang); - - DICompositeType ContainingType = CTy.getContainingType(); - if (DIDescriptor(ContainingType).isCompositeType()) - addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, - getOrCreateTypeDIE(DIType(ContainingType))); - else { - DIDescriptor Context = CTy.getContext(); - addToContextOwner(&Buffer, Context); - } - - if (Tag == dwarf::DW_TAG_class_type) - addTemplateParams(Buffer, CTy.getTemplateParams()); - - break; - } - default: - break; - } - - // Add name if not anonymous or intermediate type. - if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - - if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type - || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) - { - // Add size if non-zero (derived types might be zero-sized.) - if (Size) - addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); - else { - // Add zero size if it is not a forward declaration. - if (CTy.isForwardDecl()) - addUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - else - addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0); - } - - // Add source line info if available. - if (!CTy.isForwardDecl()) - addSourceLine(&Buffer, CTy); - } -} - -/// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE -/// for the given DITemplateTypeParameter. -DIE * -DwarfDebug::getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP) { - CompileUnit *TypeCU = getCompileUnit(TP); - DIE *ParamDIE = TypeCU->getDIE(TP); - if (ParamDIE) - return ParamDIE; - - ParamDIE = new DIE(dwarf::DW_TAG_template_type_parameter); - addType(ParamDIE, TP.getType()); - addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TP.getName()); - return ParamDIE; -} - -/// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE -/// for the given DITemplateValueParameter. -DIE * -DwarfDebug::getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TPV) { - CompileUnit *TVCU = getCompileUnit(TPV); - DIE *ParamDIE = TVCU->getDIE(TPV); - if (ParamDIE) - return ParamDIE; - - ParamDIE = new DIE(dwarf::DW_TAG_template_value_parameter); - addType(ParamDIE, TPV.getType()); - if (!TPV.getName().empty()) - addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TPV.getName()); - addUInt(ParamDIE, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, - TPV.getValue()); - return ParamDIE; -} - -/// constructSubrangeDIE - Construct subrange DIE from DISubrange. -void DwarfDebug::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ - DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); - addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); - int64_t L = SR.getLo(); - int64_t H = SR.getHi(); - - // The L value defines the lower bounds which is typically zero for C/C++. The - // H value is the upper bounds. Values are 64 bit. H - L + 1 is the size - // of the array. If L > H then do not emit DW_AT_lower_bound and - // DW_AT_upper_bound attributes. If L is zero and H is also zero then the - // array has one element and in such case do not emit lower bound. - - if (L > H) { - Buffer.addChild(DW_Subrange); - return; - } - if (L) - addSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); - addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); - Buffer.addChild(DW_Subrange); -} - -/// constructArrayTypeDIE - Construct array type DIE from DICompositeType. -void DwarfDebug::constructArrayTypeDIE(DIE &Buffer, - DICompositeType *CTy) { - Buffer.setTag(dwarf::DW_TAG_array_type); - if (CTy->getTag() == dwarf::DW_TAG_vector_type) - addUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1); - - // Emit derived type. - addType(&Buffer, CTy->getTypeDerivedFrom()); - DIArray Elements = CTy->getTypeArray(); - - // Get an anonymous type for index type. - CompileUnit *TheCU = getCompileUnit(*CTy); - DIE *IdxTy = TheCU->getIndexTyDie(); - if (!IdxTy) { - // Construct an anonymous type for index type. - IdxTy = new DIE(dwarf::DW_TAG_base_type); - addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t)); - addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - dwarf::DW_ATE_signed); - TheCU->addDie(IdxTy); - TheCU->setIndexTyDie(IdxTy); - } - - // Add subranges to array type. - for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Element = Elements.getElement(i); - if (Element.getTag() == dwarf::DW_TAG_subrange_type) - constructSubrangeDIE(Buffer, DISubrange(Element), IdxTy); - } -} - -/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. -DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator ETy) { - DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); - StringRef Name = ETy.getName(); - addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - int64_t Value = ETy.getEnumValue(); - addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); - return Enumerator; -} - /// getRealLinkageName - If special LLVM prefix that is used to inform the asm /// printer to not emit usual symbol prefix before the symbol name is used then /// return linkage name after skipping this special LLVM prefix. @@ -1213,84 +314,6 @@ return LinkageName; } -/// createMemberDIE - Create new member DIE. -DIE *DwarfDebug::createMemberDIE(DIDerivedType DT) { - DIE *MemberDie = new DIE(DT.getTag()); - StringRef Name = DT.getName(); - if (!Name.empty()) - addString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - - addType(MemberDie, DT.getTypeDerivedFrom()); - - addSourceLine(MemberDie, DT); - - DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); - addUInt(MemLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - - uint64_t Size = DT.getSizeInBits(); - uint64_t FieldSize = DT.getOriginalTypeSize(); - - if (Size != FieldSize) { - // Handle bitfield. - addUInt(MemberDie, dwarf::DW_AT_byte_size, 0, DT.getOriginalTypeSize()>>3); - addUInt(MemberDie, dwarf::DW_AT_bit_size, 0, DT.getSizeInBits()); - - uint64_t Offset = DT.getOffsetInBits(); - uint64_t AlignMask = ~(DT.getAlignInBits() - 1); - uint64_t HiMark = (Offset + FieldSize) & AlignMask; - uint64_t FieldOffset = (HiMark - FieldSize); - Offset -= FieldOffset; - - // Maybe we need to work from the other end. - if (Asm->getTargetData().isLittleEndian()) - Offset = FieldSize - (Offset + Size); - addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); - - // Here WD_AT_data_member_location points to the anonymous - // field that includes this bit field. - addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, FieldOffset >> 3); - - } else - // This is not a bitfield. - addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3); - - if (DT.getTag() == dwarf::DW_TAG_inheritance - && DT.isVirtual()) { - - // For C++, virtual base classes are not at fixed offset. Use following - // expression to extract appropriate offset from vtable. - // BaseAddr = ObAddr + *((*ObAddr) - Offset) - - DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock(); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits()); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - - addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, - VBaseLocationDie); - } else - addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); - - if (DT.isProtected()) - addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_protected); - else if (DT.isPrivate()) - addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_private); - // Otherwise C++ member and base classes are considered public. - else if (DT.getCompileUnit().getLanguage() == dwarf::DW_LANG_C_plus_plus) - addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, - dwarf::DW_ACCESS_public); - if (DT.isVirtual()) - addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, - dwarf::DW_VIRTUALITY_virtual); - return MemberDie; -} - /// createSubprogramDIE - Create new DIE using SP. DIE *DwarfDebug::createSubprogramDIE(DISubprogram SP) { CompileUnit *SPCU = getCompileUnit(SP); @@ -1301,42 +324,43 @@ SPDie = new DIE(dwarf::DW_TAG_subprogram); // Constructors and operators for anonymous aggregates do not have names. if (!SP.getName().empty()) - addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName()); + SPCU->addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + SP.getName()); StringRef LinkageName = SP.getLinkageName(); if (!LinkageName.empty()) - addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, - getRealLinkageName(LinkageName)); + SPCU->addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, + getRealLinkageName(LinkageName)); - addSourceLine(SPDie, SP); + SPCU->addSourceLine(SPDie, SP); if (SP.isPrototyped()) - addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); - + SPCU->addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + // Add Return Type. DICompositeType SPTy = SP.getType(); DIArray Args = SPTy.getTypeArray(); unsigned SPTag = SPTy.getTag(); if (Args.getNumElements() == 0 || SPTag != dwarf::DW_TAG_subroutine_type) - addType(SPDie, SPTy); + SPCU->addType(SPDie, SPTy); else - addType(SPDie, DIType(Args.getElement(0))); + SPCU->addType(SPDie, DIType(Args.getElement(0))); unsigned VK = SP.getVirtuality(); if (VK) { - addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK); - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - addUInt(Block, 0, dwarf::DW_FORM_udata, SP.getVirtualIndex()); - addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block); + SPCU->addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK); + DIEBlock *Block = SPCU->getDIEBlock(); + SPCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + SPCU->addUInt(Block, 0, dwarf::DW_FORM_udata, SP.getVirtualIndex()); + SPCU->addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block); ContainingTypeMap.insert(std::make_pair(SPDie, SP.getContainingType())); } if (!SP.isDefinition()) { - addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); - + SPCU->addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + // Add arguments. Do not add arguments for subprogram definition. They will // be handled while processing variables. DICompositeType SPTy = SP.getType(); @@ -1347,34 +371,34 @@ for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); DIType ATy = DIType(DIType(Args.getElement(i))); - addType(Arg, ATy); + SPCU->addType(Arg, ATy); if (ATy.isArtificial()) - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); SPDie->addChild(Arg); } } if (SP.isArtificial()) - addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(SPDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); if (!SP.isLocalToUnit()) - addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); if (SP.isOptimized()) - addUInt(SPDie, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); if (unsigned isa = Asm->getISAEncoding()) { - addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); + SPCU->addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); } // Add function template parameters. - addTemplateParams(*SPDie, SP.getTemplateParams()); + SPCU->addTemplateParams(*SPDie, SP.getTemplateParams()); // DW_TAG_inlined_subroutine may refer to this DIE. SPCU->insertDIE(SP, SPDie); // Add to context owner. - addToContextOwner(SPDie, SP.getContext()); + SPCU->addToContextOwner(SPDie, SP.getContext()); return SPDie; } @@ -1438,7 +462,7 @@ if (SP.isDefinition() && !SP.getContext().isCompileUnit() && !SP.getContext().isFile() && !isSubprogramContext(SP.getContext())) { - addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + SPCU-> addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); // Add arguments. DICompositeType SPTy = SP.getType(); @@ -1448,33 +472,33 @@ for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); DIType ATy = DIType(DIType(Args.getElement(i))); - addType(Arg, ATy); + SPCU->addType(Arg, ATy); if (ATy.isArtificial()) - addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + SPCU->addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); SPDie->addChild(Arg); } DIE *SPDeclDie = SPDie; SPDie = new DIE(dwarf::DW_TAG_subprogram); - addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, - SPDeclDie); + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, + SPDeclDie); SPCU->addDie(SPDie); } // Pick up abstract subprogram DIE. if (DIE *AbsSPDIE = AbstractSPDies.lookup(SPNode)) { SPDie = new DIE(dwarf::DW_TAG_subprogram); - addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, - dwarf::DW_FORM_ref4, AbsSPDIE); + SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, AbsSPDIE); SPCU->addDie(SPDie); } - addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); - addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, - Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); + SPCU->addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_begin", Asm->getFunctionNumber())); + SPCU->addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("func_end", Asm->getFunctionNumber())); const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); - addAddress(SPDie, dwarf::DW_AT_frame_base, Location); + SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location); return SPDie; } @@ -1491,13 +515,14 @@ if (Ranges.empty()) return 0; + CompileUnit *TheCU = getCompileUnit(Scope->getScopeNode()); SmallVector::const_iterator RI = Ranges.begin(); if (Ranges.size() > 1) { // .debug_range section has not been laid out yet. Emit offset in // .debug_range as a uint, size 4, for now. emitDIE will handle // DW_AT_ranges appropriately. - addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize()); + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, + DebugRangeSymbols.size() * Asm->getTargetData().getPointerSize()); for (SmallVector::const_iterator RI = Ranges.begin(), RE = Ranges.end(); RI != RE; ++RI) { DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); @@ -1516,8 +541,8 @@ assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); assert(End->isDefined() && "Invalid end label for an inlined scope!"); - addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start); - addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, Start); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, End); return ScopeDIE; } @@ -1557,11 +582,11 @@ CompileUnit *TheCU = getCompileUnit(InlinedSP); DIE *OriginDIE = TheCU->getDIE(InlinedSP); assert(OriginDIE && "Unable to find Origin DIE!"); - addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, - dwarf::DW_FORM_ref4, OriginDIE); + TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, OriginDIE); - addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel); - addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, StartLabel); + TheCU->addLabel(ScopeDIE, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr, EndLabel); InlinedSubprogramDIEs.insert(OriginDIE); @@ -1577,8 +602,8 @@ I->second.push_back(std::make_pair(StartLabel, ScopeDIE)); DILocation DL(Scope->getInlinedAt()); - addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, TheCU->getID()); - addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber()); + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, 0, TheCU->getID()); + TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, 0, DL.getLineNumber()); return ScopeDIE; } @@ -1607,7 +632,7 @@ // Define variable debug information entry. DIE *VariableDie = new DIE(Tag); - + CompileUnit *TheCU = getCompileUnit(DV->getVariable()); DIE *AbsDIE = NULL; DenseMap::iterator V2AVI = VarToAbstractVarMap.find(DV); @@ -1615,20 +640,20 @@ AbsDIE = V2AVI->second->getDIE(); if (AbsDIE) - addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, - dwarf::DW_FORM_ref4, AbsDIE); + TheCU->addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, + dwarf::DW_FORM_ref4, AbsDIE); else { - addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); - addSourceLine(VariableDie, DV->getVariable()); + TheCU->addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + TheCU->addSourceLine(VariableDie, DV->getVariable()); // Add variable type. - addType(VariableDie, DV->getType()); + TheCU->addType(VariableDie, DV->getType()); } if (Tag == dwarf::DW_TAG_formal_parameter && DV->getType().isArtificial()) - addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + TheCU->addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); else if (DIVariable(DV->getVariable()).isArtificial()) - addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); + TheCU->addUInt(VariableDie, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); if (Scope->isAbstractScope()) { DV->setDIE(VariableDie); @@ -1639,7 +664,7 @@ unsigned Offset = DV->getDotDebugLocOffset(); if (Offset != ~0U) { - addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4, + TheCU->addLabel(VariableDie, dwarf::DW_AT_location, dwarf::DW_FORM_data4, Asm->GetTempSymbol("debug_loc", Offset)); DV->setDIE(VariableDie); UseDotDebugLocEntry.insert(VariableDie); @@ -1659,20 +684,20 @@ const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); if (DVInsn->getOperand(1).isImm() && TRI->getFrameRegister(*Asm->MF) == RegOp.getReg()) { - addVariableAddress(DV, VariableDie, DVInsn->getOperand(1).getImm()); + TheCU->addVariableAddress(DV, VariableDie, DVInsn->getOperand(1).getImm()); updated = true; } else - updated = addRegisterAddress(VariableDie, RegOp); + updated = TheCU->addRegisterAddress(VariableDie, RegOp); } else if (DVInsn->getOperand(0).isImm()) - updated = addConstantValue(VariableDie, DVInsn->getOperand(0)); + updated = TheCU->addConstantValue(VariableDie, DVInsn->getOperand(0)); else if (DVInsn->getOperand(0).isFPImm()) updated = - addConstantFPValue(VariableDie, DVInsn->getOperand(0)); + TheCU->addConstantFPValue(VariableDie, DVInsn->getOperand(0)); } else { MachineLocation Location = Asm->getDebugValueLocation(DVInsn); if (Location.getReg()) { - addAddress(VariableDie, dwarf::DW_AT_location, Location); + TheCU->addAddress(VariableDie, dwarf::DW_AT_location, Location); updated = true; } } @@ -1689,14 +714,14 @@ // .. else use frame index, if available. int FI = 0; if (findVariableFrameIndex(DV, &FI)) - addVariableAddress(DV, VariableDie, FI); + TheCU->addVariableAddress(DV, VariableDie, FI); DV->setDIE(VariableDie); return VariableDie; } -void DwarfDebug::addPubTypes(DISubprogram SP) { +void CompileUnit::addPubTypes(DISubprogram SP) { DICompositeType SPTy = SP.getType(); unsigned SPTag = SPTy.getTag(); if (SPTag != dwarf::DW_TAG_subroutine_type) @@ -1710,9 +735,8 @@ DICompositeType CATy = getDICompositeType(ATy); if (DIDescriptor(CATy).Verify() && !CATy.getName().empty() && !CATy.isForwardDecl()) { - CompileUnit *TheCU = getCompileUnit(CATy); - if (DIEEntry *Entry = TheCU->getDIEEntry(CATy)) - TheCU->addGlobalType(CATy.getName(), Entry->getEntry()); + if (DIEEntry *Entry = getDIEEntry(CATy)) + addGlobalType(CATy.getName(), Entry->getEntry()); } } } @@ -1770,7 +794,7 @@ ScopeDIE->addChild(*I); if (DS.isSubprogram()) - addPubTypes(DISubprogram(DS)); + getCompileUnit(DS)->addPubTypes(DISubprogram(DS)); return ScopeDIE; } @@ -1810,13 +834,12 @@ } /// getOrCreateNameSpace - Create a DIE for DINameSpace. -DIE *DwarfDebug::getOrCreateNameSpace(DINameSpace NS) { - CompileUnit *TheCU = getCompileUnit(NS); - DIE *NDie = TheCU->getDIE(NS); +DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) { + DIE *NDie = getDIE(NS); if (NDie) return NDie; NDie = new DIE(dwarf::DW_TAG_namespace); - TheCU->insertDIE(NS, NDie); + insertDIE(NS, NDie); if (!NS.getName().empty()) addString(NDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, NS.getName()); addSourceLine(NDie, NS); @@ -1833,37 +856,37 @@ unsigned ID = GetOrCreateSourceID(FN, Dir); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, - DIUnit.getProducer()); - addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - DIUnit.getLanguage()); - addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); + CompileUnit *NewCU = new CompileUnit(ID, Die, Asm, this); + NewCU->addString(Die, dwarf::DW_AT_producer, dwarf::DW_FORM_string, + DIUnit.getProducer()); + NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + DIUnit.getLanguage()); + NewCU->addString(Die, dwarf::DW_AT_name, dwarf::DW_FORM_string, FN); // Use DW_AT_entry_pc instead of DW_AT_low_pc/DW_AT_high_pc pair. This // simplifies debug range entries. - addUInt(Die, dwarf::DW_AT_entry_pc, dwarf::DW_FORM_addr, 0); + NewCU->addUInt(Die, dwarf::DW_AT_entry_pc, dwarf::DW_FORM_addr, 0); // DW_AT_stmt_list is a offset of line number information for this // compile unit in debug_line section. if (Asm->MAI->doesDwarfUsesAbsoluteLabelForStmtList()) - addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_addr, - Asm->GetTempSymbol("section_line")); + NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_addr, + Asm->GetTempSymbol("section_line")); else - addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); + NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); if (!Dir.empty()) - addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir); + NewCU->addString(Die, dwarf::DW_AT_comp_dir, dwarf::DW_FORM_string, Dir); if (DIUnit.isOptimized()) - addUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); + NewCU->addUInt(Die, dwarf::DW_AT_APPLE_optimized, dwarf::DW_FORM_flag, 1); StringRef Flags = DIUnit.getFlags(); if (!Flags.empty()) - addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags); - + NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, dwarf::DW_FORM_string, Flags); + unsigned RVer = DIUnit.getRunTimeVersion(); if (RVer) - addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, + NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, dwarf::DW_FORM_data1, RVer); - CompileUnit *NewCU = new CompileUnit(ID, Die); if (!FirstCU) FirstCU = NewCU; CUMap.insert(std::make_pair(N, NewCU)); @@ -1959,14 +982,15 @@ bool isGlobalVariable = GV.getGlobal() != NULL; // Add name. - addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, - GV.getDisplayName()); + TheCU->addString(VariableDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, + GV.getDisplayName()); StringRef LinkageName = GV.getLinkageName(); if (!LinkageName.empty() && isGlobalVariable) - addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string, - getRealLinkageName(LinkageName)); + TheCU->addString(VariableDIE, dwarf::DW_AT_MIPS_linkage_name, + dwarf::DW_FORM_string, + getRealLinkageName(LinkageName)); // Add type. - addType(VariableDIE, GTy); + TheCU->addType(VariableDIE, GTy); if (GTy.isCompositeType() && !GTy.getName().empty() && !GTy.isForwardDecl()) { DIEEntry *Entry = TheCU->getDIEEntry(GTy); @@ -1975,22 +999,22 @@ } // Add scoping info. if (!GV.isLocalToUnit()) { - addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + TheCU->addUInt(VariableDIE, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); // Expose as global. TheCU->addGlobal(GV.getName(), VariableDIE); } // Add line number info. - addSourceLine(VariableDIE, GV); + TheCU->addSourceLine(VariableDIE, GV); // Add to map. TheCU->insertDIE(N, VariableDIE); // Add to context owner. DIDescriptor GVContext = GV.getContext(); - addToContextOwner(VariableDIE, GVContext); + TheCU->addToContextOwner(VariableDIE, GVContext); // Add location. if (isGlobalVariable) { DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - addLabel(Block, 0, dwarf::DW_FORM_udata, + TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata, Asm->Mang->getSymbol(GV.getGlobal())); // Do not create specification DIE if context is either compile unit // or a subprogram. @@ -1998,28 +1022,28 @@ !GVContext.isFile() && !isSubprogramContext(GVContext)) { // Create specification DIE. DIE *VariableSpecDIE = new DIE(dwarf::DW_TAG_variable); - addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, + TheCU->addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4, VariableDIE); - addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); - addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + TheCU->addBlock(VariableSpecDIE, dwarf::DW_AT_location, 0, Block); + TheCU->addUInt(VariableDIE, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); TheCU->addDie(VariableSpecDIE); } else { - addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); + TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); } } else if (ConstantInt *CI = dyn_cast_or_null(GV.getConstant())) - addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy)); + TheCU->addConstantValue(VariableDIE, CI, isUnsignedDIType(GTy)); else if (const ConstantExpr *CE = getMergedGlobalExpr(N->getOperand(11))) { // GV is a merged global. DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); - addLabel(Block, 0, dwarf::DW_FORM_udata, - Asm->Mang->getSymbol(cast(CE->getOperand(0)))); + TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); + TheCU->addLabel(Block, 0, dwarf::DW_FORM_udata, + Asm->Mang->getSymbol(cast(CE->getOperand(0)))); ConstantInt *CII = cast(CE->getOperand(2)); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - addUInt(Block, 0, dwarf::DW_FORM_udata, CII->getZExtValue()); - addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); + TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + TheCU->addUInt(Block, 0, dwarf::DW_FORM_udata, CII->getZExtValue()); + TheCU->addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + TheCU->addBlock(VariableDIE, dwarf::DW_AT_location, 0, Block); } return; @@ -2045,7 +1069,7 @@ TheCU->insertDIE(N, SubprogramDie); // Add to context owner. - addToContextOwner(SubprogramDie, SP.getContext()); + TheCU->addToContextOwner(SubprogramDie, SP.getContext()); // Expose as global. TheCU->addGlobal(SP.getName(), SubprogramDie); @@ -2100,12 +1124,16 @@ //getOrCreateTypeDIE if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.enum")) - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) - getOrCreateTypeDIE(DIType(NMD->getOperand(i))); + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIType Ty(NMD->getOperand(i)); + getCompileUnit(Ty)->getOrCreateTypeDIE(Ty); + } if (NamedMDNode *NMD = M->getNamedMetadata("llvm.dbg.ty")) - for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) - getOrCreateTypeDIE(DIType(NMD->getOperand(i))); + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + DIType Ty(NMD->getOperand(i)); + getCompileUnit(Ty)->getOrCreateTypeDIE(Ty); + } // Prime section data. SectionMap.insert(Asm->getObjFileLowering().getTextSection()); @@ -2156,7 +1184,7 @@ for (SmallPtrSet::iterator AI = InlinedSubprogramDIEs.begin(), AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) { DIE *ISP = *AI; - addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); + FirstCU->addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined); } for (DenseMap::iterator CI = ContainingTypeMap.begin(), @@ -2166,7 +1194,8 @@ if (!N) continue; DIE *NDie = getCompileUnit(N)->getDIE(N); if (!NDie) continue; - addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie); + getCompileUnit(N)->addDIEEntry(SPDie, dwarf::DW_AT_containing_type, + dwarf::DW_FORM_ref4, NDie); } // Standard sections final addresses. @@ -3021,8 +2050,9 @@ DIE *CurFnDIE = constructScopeDIE(CurrentFnDbgScope); if (!DisableFramePointerElim(*MF)) - addUInt(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr, - dwarf::DW_FORM_flag, 1); + getCompileUnit(CurrentFnDbgScope->getScopeNode())->addUInt(CurFnDIE, + dwarf::DW_AT_APPLE_omit_frame_ptr, + dwarf::DW_FORM_flag, 1); DebugFrames.push_back(FunctionDebugFrameInfo(Asm->getFunctionNumber(), Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h?rev=129402&r1=129401&r2=129402&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h Tue Apr 12 17:53:02 2011 @@ -16,6 +16,7 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineLocation.h" +#include "llvm/Analysis/DebugInfo.h" #include "DIE.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -39,21 +40,6 @@ class DIE; class DIEBlock; class DIEEntry; -class DIArray; -class DIEnumerator; -class DIDescriptor; -class DIVariable; -class DIGlobal; -class DIGlobalVariable; -class DISubprogram; -class DIBasicType; -class DIDerivedType; -class DIType; -class DINameSpace; -class DISubrange; -class DICompositeType; -class DITemplateTypeParameter; -class DITemplateValueParameter; //===----------------------------------------------------------------------===// /// SrcLineInfo - This class is used to record source line correspondence. @@ -96,6 +82,43 @@ } } DotDebugLocEntry; +//===----------------------------------------------------------------------===// +/// DbgVariable - This class is used to track local variable information. +/// +class DbgVariable { + DIVariable Var; // Variable Descriptor. + DIE *TheDIE; // Variable DIE. + unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. +public: + // AbsVar may be NULL. + DbgVariable(DIVariable V) : Var(V), TheDIE(0), DotDebugLocOffset(~0U) {} + + // Accessors. + DIVariable getVariable() const { return Var; } + void setDIE(DIE *D) { TheDIE = D; } + DIE *getDIE() const { return TheDIE; } + void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } + unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } + StringRef getName() const { return Var.getName(); } + unsigned getTag() const { return Var.getTag(); } + bool variableHasComplexAddress() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.hasComplexAddress(); + } + bool isBlockByrefVariable() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.isBlockByrefVariable(); + } + unsigned getNumAddrElements() const { + assert(Var.Verify() && "Invalid complex DbgVariable!"); + return Var.getNumAddrElements(); + } + uint64_t getAddrElement(unsigned i) const { + return Var.getAddrElement(i); + } + DIType getType() const; +}; + class DwarfDebug { /// Asm - Target of Dwarf emission. AsmPrinter *Asm; @@ -122,12 +145,6 @@ /// id mapped to a unique id. StringMap SourceIdMap; - /// DIEBlocks - A list of all the DIEBlocks in use. - std::vector DIEBlocks; - - // DIEValueAllocator - All DIEValues are allocated through this allocator. - BumpPtrAllocator DIEValueAllocator; - /// StringPool - A String->Symbol mapping of strings used by indirect /// references. StringMap > StringPool; @@ -244,6 +261,9 @@ std::vector DebugFrames; + // DIEValueAllocator - All DIEValues are allocated through this allocator. + BumpPtrAllocator DIEValueAllocator; + // Section Symbols: these are assembler temporary labels that are emitted at // the beginning of each supported dwarf section. These are used to form // section offsets and are created by EmitSectionLabels. @@ -252,149 +272,12 @@ MCSymbol *DwarfDebugLocSectionSym; MCSymbol *FunctionBeginSym, *FunctionEndSym; - DIEInteger *DIEIntegerOne; - private: /// assignAbbrevNumber - Define a unique number for the abbreviation. /// void assignAbbrevNumber(DIEAbbrev &Abbrev); - /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug - /// information entry. - DIEEntry *createDIEEntry(DIE *Entry); - - /// addUInt - Add an unsigned integer attribute data and value. - /// - void addUInt(DIE *Die, unsigned Attribute, unsigned Form, uint64_t Integer); - - /// addSInt - Add an signed integer attribute data and value. - /// - void addSInt(DIE *Die, unsigned Attribute, unsigned Form, int64_t Integer); - - /// addString - Add a string attribute data and value. - /// - void addString(DIE *Die, unsigned Attribute, unsigned Form, - const StringRef Str); - - /// addLabel - Add a Dwarf label attribute data and value. - /// - void addLabel(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Label); - - /// addDelta - Add a label delta attribute data and value. - /// - void addDelta(DIE *Die, unsigned Attribute, unsigned Form, - const MCSymbol *Hi, const MCSymbol *Lo); - - /// addDIEEntry - Add a DIE attribute data and value. - /// - void addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, DIE *Entry); - - /// addBlock - Add block data. - /// - void addBlock(DIE *Die, unsigned Attribute, unsigned Form, DIEBlock *Block); - - /// addSourceLine - Add location information to specified debug information - /// entry. - void addSourceLine(DIE *Die, DIVariable V); - void addSourceLine(DIE *Die, DIGlobalVariable G); - void addSourceLine(DIE *Die, DISubprogram SP); - void addSourceLine(DIE *Die, DIType Ty); - void addSourceLine(DIE *Die, DINameSpace NS); - - /// addAddress - Add an address attribute to a die based on the location - /// provided. - void addAddress(DIE *Die, unsigned Attribute, - const MachineLocation &Location); - - /// addRegisterAddress - Add register location entry in variable DIE. - bool addRegisterAddress(DIE *Die, const MachineOperand &MO); - - /// addConstantValue - Add constant value entry in variable DIE. - bool addConstantValue(DIE *Die, const MachineOperand &MO); - bool addConstantValue(DIE *Die, ConstantInt *CI, bool Unsigned); - - /// addConstantFPValue - Add constant value entry in variable DIE. - bool addConstantFPValue(DIE *Die, const MachineOperand &MO); - - /// addTemplateParams - Add template parameters in buffer. - void addTemplateParams(DIE &Buffer, DIArray TParams); - - /// addComplexAddress - Start with the address based on the location provided, - /// and generate the DWARF information necessary to find the actual variable - /// (navigating the extra location information encoded in the type) based on - /// the starting location. Add the DWARF information to the die. - /// - void addComplexAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, - const MachineLocation &Location); - - // FIXME: Should be reformulated in terms of addComplexAddress. - /// addBlockByrefAddress - Start with the address based on the location - /// provided, and generate the DWARF information necessary to find the - /// actual Block variable (navigating the Block struct) based on the - /// starting location. Add the DWARF information to the die. Obsolete, - /// please use addComplexAddress instead. - /// - void addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute, - const MachineLocation &Location); - - /// addVariableAddress - Add DW_AT_location attribute for a DbgVariable based - /// on provided frame index. - void addVariableAddress(DbgVariable *&DV, DIE *Die, int64_t FI); - - /// addToContextOwner - Add Die into the list of its context owner's children. - void addToContextOwner(DIE *Die, DIDescriptor Context); - - /// addType - Add a new type attribute to the specified entity. - void addType(DIE *Entity, DIType Ty); - - - /// getOrCreateNameSpace - Create a DIE for DINameSpace. - DIE *getOrCreateNameSpace(DINameSpace NS); - - /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the - /// given DIType. - DIE *getOrCreateTypeDIE(DIType Ty); - - /// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE - /// for the given DITemplateTypeParameter. - DIE *getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP); - - /// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE - /// for the given DITemplateValueParameter. - DIE *getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TVP); - - void addPubTypes(DISubprogram SP); - - /// constructTypeDIE - Construct basic type die from DIBasicType. - void constructTypeDIE(DIE &Buffer, - DIBasicType BTy); - - /// constructTypeDIE - Construct derived type die from DIDerivedType. - void constructTypeDIE(DIE &Buffer, - DIDerivedType DTy); - - /// constructTypeDIE - Construct type DIE from DICompositeType. - void constructTypeDIE(DIE &Buffer, - DICompositeType CTy); - - /// constructSubrangeDIE - Construct subrange DIE from DISubrange. - void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); - - /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. - void constructArrayTypeDIE(DIE &Buffer, - DICompositeType *CTy); - - /// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. - DIE *constructEnumTypeDIE(DIEnumerator ETy); - - /// createMemberDIE - Create new member DIE. - DIE *createMemberDIE(DIDerivedType DT); - - /// createSubprogramDIE - Create new DIE using SP. - DIE *createSubprogramDIE(DISubprogram SP); - /// getOrCreateDbgScope - Create DbgScope for the scope. DbgScope *getOrCreateDbgScope(const MDNode *Scope, const MDNode *InlinedAt); @@ -509,11 +392,6 @@ /// inlining instance. void emitDebugInlineInfo(); - /// GetOrCreateSourceID - Look up the source id with the given directory and - /// source file names. If none currently exists, create a new id and insert it - /// in the SourceIds map. - unsigned GetOrCreateSourceID(StringRef DirName, StringRef FullName); - /// constructCompileUnit - Create new CompileUnit for the given /// metadata node with tag DW_TAG_compile_unit. void constructCompileUnit(const MDNode *N); @@ -609,6 +487,14 @@ /// endInstruction - Prcess end of an instruction. void endInstruction(const MachineInstr *MI); + + /// GetOrCreateSourceID - Look up the source id with the given directory and + /// source file names. If none currently exists, create a new id and insert it + /// in the SourceIds map. + unsigned GetOrCreateSourceID(StringRef DirName, StringRef FullName); + + /// createSubprogramDIE - Create new DIE using SP. + DIE *createSubprogramDIE(DISubprogram SP); }; } // End of namespace llvm From isanbard at gmail.com Tue Apr 12 17:59:27 2011 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 12 Apr 2011 22:59:27 -0000 Subject: [llvm-commits] [llvm] r129403 - in /llvm/trunk: include/llvm/IntrinsicsX86.td lib/Target/X86/X86InstrInfo.cpp lib/Target/X86/X86InstrSSE.td lib/Transforms/InstCombine/InstCombineCalls.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp lib/VMCore/AutoUpgrade.cpp test/Assembler/AutoUpgradeIntrinsics.ll test/CodeGen/X86/avx-intrinsics-x86.ll Message-ID: <20110412225927.D42952A6C12D@llvm.org> Author: void Date: Tue Apr 12 17:59:27 2011 New Revision: 129403 URL: http://llvm.org/viewvc/llvm-project?rev=129403&view=rev Log: Revert r129401 for now. Clang is using the old way of doing things. Modified: llvm/trunk/include/llvm/IntrinsicsX86.td llvm/trunk/lib/Target/X86/X86InstrInfo.cpp llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp llvm/trunk/lib/VMCore/AutoUpgrade.cpp llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll Modified: llvm/trunk/include/llvm/IntrinsicsX86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IntrinsicsX86.td?rev=129403&r1=129402&r2=129403&view=diff ============================================================================== --- llvm/trunk/include/llvm/IntrinsicsX86.td (original) +++ llvm/trunk/include/llvm/IntrinsicsX86.td Tue Apr 12 17:59:27 2011 @@ -138,6 +138,12 @@ llvm_x86mmx_ty], [IntrNoMem]>; } +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_loadu_ps : GCCBuiltin<"__builtin_ia32_loadups">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + // SIMD store ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">, @@ -446,6 +452,14 @@ Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>; } +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_loadu_pd : GCCBuiltin<"__builtin_ia32_loadupd">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem]>; + def int_x86_sse2_loadu_dq : GCCBuiltin<"__builtin_ia32_loaddqu">, + Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; +} + // SIMD store ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">, Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=129403&r1=129402&r2=129403&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue Apr 12 17:59:27 2011 @@ -916,6 +916,7 @@ case X86::MOVSDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: + case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MMX_MOVD64rm: @@ -2844,9 +2845,11 @@ case X86::FsMOVAPDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: + case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: + case X86::MOVDQUrm_Int: break; } switch (Opc2) { @@ -2866,9 +2869,11 @@ case X86::FsMOVAPDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: + case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: + case X86::MOVDQUrm_Int: break; } Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=129403&r1=129402&r2=129403&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Tue Apr 12 17:59:27 2011 @@ -329,6 +329,15 @@ // Intrinsic forms of MOVUPS/D load and store let isAsmParserOnly = 0 in { + let canFoldAsLoad = 1, isReMaterializable = 1 in + def VMOVUPSrm_Int : VPSI<0x10, MRMSrcMem, (outs VR128:$dst), + (ins f128mem:$src), + "movups\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>, VEX; + def VMOVUPDrm_Int : VPDI<0x10, MRMSrcMem, (outs VR128:$dst), + (ins f128mem:$src), + "movupd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>, VEX; def VMOVUPSmr_Int : VPSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movups\t{$src, $dst|$dst, $src}", @@ -338,6 +347,13 @@ "movupd\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>, VEX; } +let canFoldAsLoad = 1, isReMaterializable = 1 in +def MOVUPSrm_Int : PSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movups\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>; +def MOVUPDrm_Int : PDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), + "movupd\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>; def MOVUPSmr_Int : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movups\t{$src, $dst|$dst, $src}", @@ -2213,12 +2229,22 @@ // Intrinsic forms of MOVDQU load and store let isAsmParserOnly = 0 in { +let canFoldAsLoad = 1 in +def VMOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "vmovdqu\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, + XS, VEX, Requires<[HasAVX]>; def VMOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "vmovdqu\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, XS, VEX, Requires<[HasAVX]>; } +let canFoldAsLoad = 1 in +def MOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), + "movdqu\t{$src, $dst|$dst, $src}", + [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, + XS, Requires<[HasSSE2]>; def MOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "movdqu\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=129403&r1=129402&r2=129403&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original) +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Tue Apr 12 17:59:27 2011 @@ -537,7 +537,11 @@ break; case Intrinsic::ppc_altivec_lvx: case Intrinsic::ppc_altivec_lvxl: - // Turn PPC lvx -> load if the pointer is known aligned. + case Intrinsic::x86_sse_loadu_ps: + case Intrinsic::x86_sse2_loadu_pd: + case Intrinsic::x86_sse2_loadu_dq: + // Turn PPC lvx -> load if the pointer is known aligned. + // Turn X86 loadups -> load if the pointer is known aligned. if (getOrEnforceKnownAlignment(II->getArgOperand(0), 16, TD) >= 16) { Value *Ptr = Builder->CreateBitCast(II->getArgOperand(0), PointerType::getUnqual(II->getType())); Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=129403&r1=129402&r2=129403&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Tue Apr 12 17:59:27 2011 @@ -572,6 +572,9 @@ switch (II->getIntrinsicID()) { default: break; case Intrinsic::prefetch: + case Intrinsic::x86_sse2_loadu_dq: + case Intrinsic::x86_sse2_loadu_pd: + case Intrinsic::x86_sse_loadu_ps: case Intrinsic::x86_sse_storeu_ps: case Intrinsic::x86_sse2_storeu_pd: case Intrinsic::x86_sse2_storeu_dq: Modified: llvm/trunk/lib/VMCore/AutoUpgrade.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AutoUpgrade.cpp?rev=129403&r1=129402&r2=129403&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/AutoUpgrade.cpp (original) +++ llvm/trunk/lib/VMCore/AutoUpgrade.cpp Tue Apr 12 17:59:27 2011 @@ -527,12 +527,6 @@ // or 0. NewFn = 0; return true; - } else if (Name.compare(5, 16, "x86.sse.loadu.ps", 16) == 0 || - Name.compare(5, 17, "x86.sse2.loadu.dq", 17) == 0 || - Name.compare(5, 17, "x86.sse2.loadu.pd", 17) == 0) { - // Calls to these instructions are transformed into unaligned loads. - NewFn = 0; - return true; } else if (Name.compare(5, 17, "x86.ssse3.pshuf.w", 17) == 0) { // This is an SSE/MMX instruction. const Type *X86_MMXTy = VectorType::getX86_MMXTy(FTy->getContext()); @@ -952,29 +946,7 @@ // Remove upgraded instruction. CI->eraseFromParent(); - - } else if (F->getName() == "llvm.x86.sse.loadu.ps" || - F->getName() == "llvm.x86.sse2.loadu.dq" || - F->getName() == "llvm.x86.sse2.loadu.pd") { - // Convert to a native, unaligned load. - const Type *VecTy = CI->getType(); - const Type *IntTy = IntegerType::get(C, 128); - IRBuilder<> Builder(C); - Builder.SetInsertPoint(CI->getParent(), CI); - - Value *BC = Builder.CreateBitCast(CI->getArgOperand(0), - PointerType::getUnqual(IntTy), - "cast"); - LoadInst *LI = Builder.CreateLoad(BC, CI->getName()); - LI->setAlignment(1); // Unaligned load. - BC = Builder.CreateBitCast(LI, VecTy, "new.cast"); - - // Fix up all the uses with our new load. - if (!CI->use_empty()) - CI->replaceAllUsesWith(BC); - - // Remove intrinsic. - CI->eraseFromParent(); + } else { llvm_unreachable("Unknown function for CallInst upgrade."); } Modified: llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll?rev=129403&r1=129402&r2=129403&view=diff ============================================================================== --- llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll (original) +++ llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll Tue Apr 12 17:59:27 2011 @@ -7,8 +7,6 @@ ; RUN: llvm-as < %s | llvm-dis | \ ; RUN: not grep {llvm\\.bswap\\.i\[0-9\]*\\.i\[0-9\]*} ; RUN: llvm-as < %s | llvm-dis | \ -; RUN: not grep {llvm\\.x86\\.sse2\\.loadu} -; RUN: llvm-as < %s | llvm-dis | \ ; RUN: grep {llvm\\.x86\\.mmx\\.ps} | grep {x86_mmx} | count 16 declare i32 @llvm.ctpop.i28(i28 %val) @@ -81,13 +79,3 @@ %r2 = call <1 x i64> @llvm.x86.mmx.psrl.q( <1 x i64> %A, <2 x i32> %B ) ; <<1 x i64>> [#uses=0] ret void } - -declare <4 x float> @llvm.x86.sse.loadu.ps(i8*) nounwind readnone -declare <16 x i8> @llvm.x86.sse2.loadu.dq(i8*) nounwind readnone -declare <2 x double> @llvm.x86.sse2.loadu.pd(double*) nounwind readnone -define void @test_loadu(i8* %a, double* %b) { - %v0 = call <4 x float> @llvm.x86.sse.loadu.ps(i8* %a) - %v1 = call <16 x i8> @llvm.x86.sse2.loadu.dq(i8* %a) - %v2 = call <2 x double> @llvm.x86.sse2.loadu.pd(double* %b) - ret void -} Modified: llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll?rev=129403&r1=129402&r2=129403&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll Tue Apr 12 17:59:27 2011 @@ -247,7 +247,7 @@ define <16 x i8> @test_x86_sse2_loadu_dq(i8* %a0) { ; CHECK: movl - ; CHECK: vmovups + ; CHECK: vmovdqu %res = call <16 x i8> @llvm.x86.sse2.loadu.dq(i8* %a0) ; <<16 x i8>> [#uses=1] ret <16 x i8> %res } @@ -256,7 +256,7 @@ define <2 x double> @test_x86_sse2_loadu_pd(i8* %a0) { ; CHECK: movl - ; CHECK: vmovups + ; CHECK: vmovupd %res = call <2 x double> @llvm.x86.sse2.loadu.pd(i8* %a0) ; <<2 x double>> [#uses=1] ret <2 x double> %res } From gohman at apple.com Tue Apr 12 18:05:59 2011 From: gohman at apple.com (Dan Gohman) Date: Tue, 12 Apr 2011 23:05:59 -0000 Subject: [llvm-commits] [llvm] r129404 - /llvm/trunk/docs/LangRef.html Message-ID: <20110412230559.E734A2A6C12D@llvm.org> Author: djg Date: Tue Apr 12 18:05:59 2011 New Revision: 129404 URL: http://llvm.org/viewvc/llvm-project?rev=129404&view=rev Log: Fix a hole in the definition of "dependence" used by trap values. Trap values are also transmitted through branches which cause side effects to be skipped altogether. Modified: llvm/trunk/docs/LangRef.html Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=129404&r1=129403&r2=129404&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Tue Apr 12 18:05:59 2011 @@ -2371,6 +2371,11 @@ is always executed when control transfers to one of the successors, and may not be executed when control is transfered to another. +
    • Additionally, an instruction also control-depends on a terminator + instruction if the set of instructions it otherwise depends on would be + different if the terminator had transfered control to a different + successor.
    • +
    • Dependence is transitive.
    • @@ -2413,8 +2418,23 @@ ; control-dependent on %cmp, so this ; always results in a trap value. - volatile store i32 0, i32* @g ; %end is control-equivalent to %entry - ; so this is defined (ignoring earlier + volatile store i32 0, i32* @g ; This would depend on the store in %true + ; if %cmp is true, or the store in %entry + ; otherwise, so this is undefined behavior. + + %br i1 %cmp, %second_true, %second_end + ; The same branch again, but this time the + ; true block doesn't have side effects. + +second_true: + ; No side effects! + br label %end + +second_end: + volatile store i32 0, i32* @g ; This time, the instruction always depends + ; on the store in %end. Also, it is + ; control-equivalent to %end, so this is + ; well- defined (again, ignoring earlier ; undefined behavior in this example). From dpatel at apple.com Tue Apr 12 18:09:06 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 12 Apr 2011 23:09:06 -0000 Subject: [llvm-commits] [llvm] r129405 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Message-ID: <20110412230906.3C7232A6C12D@llvm.org> Author: dpatel Date: Tue Apr 12 18:09:06 2011 New Revision: 129405 URL: http://llvm.org/viewvc/llvm-project?rev=129405&view=rev Log: Do not reuse parameter name. Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h?rev=129405&r1=129404&r2=129405&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h Tue Apr 12 18:09:06 2011 @@ -68,7 +68,7 @@ std::vector DIEBlocks; public: - CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *D); + CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *DW); ~CompileUnit(); // Accessors. From dpatel at apple.com Tue Apr 12 18:10:47 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 12 Apr 2011 23:10:47 -0000 Subject: [llvm-commits] [llvm] r129406 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Message-ID: <20110412231047.8AF432A6C12D@llvm.org> Author: dpatel Date: Tue Apr 12 18:10:47 2011 New Revision: 129406 URL: http://llvm.org/viewvc/llvm-project?rev=129406&view=rev Log: Simplify. There is no need to use static variable. Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=129406&r1=129405&r2=129406&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Tue Apr 12 18:10:47 2011 @@ -2206,17 +2206,15 @@ /// computeSizeAndOffsets - Compute the size and offset of all the DIEs. /// void DwarfDebug::computeSizeAndOffsets() { - unsigned PrevOffset = 0; for (DenseMap::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { // Compute size of compile unit header. - static unsigned Offset = PrevOffset + + unsigned Offset = sizeof(int32_t) + // Length of Compilation Unit Info sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section sizeof(int8_t); // Pointer Size (in bytes) computeSizeAndOffset(I->second->getCUDie(), Offset, true); - PrevOffset = Offset; } } From geek4civic at gmail.com Tue Apr 12 18:25:03 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Wed, 13 Apr 2011 08:25:03 +0900 Subject: [llvm-commits] [PATCH] lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp: [PR9581] Fix FP precision issue on mingw. It also reverts r129199. Message-ID: FIXME: It is for i686-mingw32 for now, though, potentially the issue might be on x87-based hosts with PC64. FIXME: [PR6907] Use llvm/Support/FEnv.h. On clang++, is unavailable due to handling of #include_next. --- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 33 ++++++++++++++++++---- 1 files changed, 27 insertions(+), 6 deletions(-) -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-lib-CodeGen-SelectionDAG-SelectionDAGBuilder.cpp.patch.txt Type: text/x-patch Size: 2193 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110413/fbbfe326/attachment.bin From dpatel at apple.com Tue Apr 12 18:21:44 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 12 Apr 2011 23:21:44 -0000 Subject: [llvm-commits] [llvm] r129407 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Message-ID: <20110412232144.A2B442A6C12D@llvm.org> Author: dpatel Date: Tue Apr 12 18:21:44 2011 New Revision: 129407 URL: http://llvm.org/viewvc/llvm-project?rev=129407&view=rev Log: I missed this new file in previous commit. Added: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Added: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp?rev=129407&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp (added) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp Tue Apr 12 18:21:44 2011 @@ -0,0 +1,973 @@ +//===-- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Unit ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf compile unit. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "dwarfdebug" + +#include "DwarfCompileUnit.h" +#include "DwarfDebug.h" +#include "llvm/Constants.h" +#include "llvm/Analysis/DIBuilder.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/ADT/APFloat.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +/// CompileUnit - Compile unit constructor. +CompileUnit::CompileUnit(unsigned I, DIE *D, AsmPrinter *A, DwarfDebug *DW) + : ID(I), CUDie(D), Asm(A), DD(DW), IndexTyDie(0) { + DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); +} + +/// ~CompileUnit - Destructor for compile unit. +CompileUnit::~CompileUnit() { + for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) + DIEBlocks[j]->~DIEBlock(); +} + +/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug +/// information entry. +DIEEntry *CompileUnit::createDIEEntry(DIE *Entry) { + DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry); + return Value; +} + +/// addUInt - Add an unsigned integer attribute data and value. +/// +void CompileUnit::addUInt(DIE *Die, unsigned Attribute, + unsigned Form, uint64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(false, Integer); + DIEValue *Value = Integer == 1 ? + DIEIntegerOne : new (DIEValueAllocator) DIEInteger(Integer); + Die->addValue(Attribute, Form, Value); +} + +/// addSInt - Add an signed integer attribute data and value. +/// +void CompileUnit::addSInt(DIE *Die, unsigned Attribute, + unsigned Form, int64_t Integer) { + if (!Form) Form = DIEInteger::BestForm(true, Integer); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer); + Die->addValue(Attribute, Form, Value); +} + +/// addString - Add a string attribute data and value. DIEString only +/// keeps string reference. +void CompileUnit::addString(DIE *Die, unsigned Attribute, unsigned Form, + StringRef String) { + DIEValue *Value = new (DIEValueAllocator) DIEString(String); + Die->addValue(Attribute, Form, Value); +} + +/// addLabel - Add a Dwarf label attribute data and value. +/// +void CompileUnit::addLabel(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Label) { + DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); + Die->addValue(Attribute, Form, Value); +} + +/// addDelta - Add a label delta attribute data and value. +/// +void CompileUnit::addDelta(DIE *Die, unsigned Attribute, unsigned Form, + const MCSymbol *Hi, const MCSymbol *Lo) { + DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); + Die->addValue(Attribute, Form, Value); +} + +/// addDIEEntry - Add a DIE attribute data and value. +/// +void CompileUnit::addDIEEntry(DIE *Die, unsigned Attribute, unsigned Form, + DIE *Entry) { + Die->addValue(Attribute, Form, createDIEEntry(Entry)); +} + + +/// addBlock - Add block data. +/// +void CompileUnit::addBlock(DIE *Die, unsigned Attribute, unsigned Form, + DIEBlock *Block) { + Block->ComputeSize(Asm); + DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. + Die->addValue(Attribute, Block->BestForm(), Block); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DIVariable V) { + // Verify variable. + if (!V.Verify()) + return; + + unsigned Line = V.getLineNumber(); + if (Line == 0) + return; + unsigned FileID = DD->GetOrCreateSourceID(V.getContext().getFilename(), + V.getContext().getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { + // Verify global variable. + if (!G.Verify()) + return; + + unsigned Line = G.getLineNumber(); + if (Line == 0) + return; + unsigned FileID = DD->GetOrCreateSourceID(G.getContext().getFilename(), + G.getContext().getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DISubprogram SP) { + // Verify subprogram. + if (!SP.Verify()) + return; + // If the line number is 0, don't add it. + if (SP.getLineNumber() == 0) + return; + + unsigned Line = SP.getLineNumber(); + if (!SP.getContext().Verify()) + return; + unsigned FileID = DD->GetOrCreateSourceID(SP.getFilename(), SP.getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DIType Ty) { + // Verify type. + if (!Ty.Verify()) + return; + + unsigned Line = Ty.getLineNumber(); + if (Line == 0 || !Ty.getContext().Verify()) + return; + unsigned FileID = DD->GetOrCreateSourceID(Ty.getFilename(), Ty.getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addSourceLine - Add location information to specified debug information +/// entry. +void CompileUnit::addSourceLine(DIE *Die, DINameSpace NS) { + // Verify namespace. + if (!NS.Verify()) + return; + + unsigned Line = NS.getLineNumber(); + if (Line == 0) + return; + StringRef FN = NS.getFilename(); + + unsigned FileID = DD->GetOrCreateSourceID(FN, NS.getDirectory()); + assert(FileID && "Invalid file id"); + addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID); + addUInt(Die, dwarf::DW_AT_decl_line, 0, Line); +} + +/// addVariableAddress - Add DW_AT_location attribute for a DbgVariable based +/// on provided frame index. +void CompileUnit::addVariableAddress(DbgVariable *&DV, DIE *Die, int64_t FI) { + MachineLocation Location; + unsigned FrameReg; + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); + Location.set(FrameReg, Offset); + + if (DV->variableHasComplexAddress()) + addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); + else if (DV->isBlockByrefVariable()) + addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); + else + addAddress(Die, dwarf::DW_AT_location, Location); +} + +/// addComplexAddress - Start with the address based on the location provided, +/// and generate the DWARF information necessary to find the actual variable +/// given the extra address information encoded in the DIVariable, starting from +/// the starting location. Add the DWARF information to the die. +/// +void CompileUnit::addComplexAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + DIType Ty = DV->getType(); + + // Decode the original location, and use that as the start of the byref + // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + for (unsigned i = 0, N = DV->getNumAddrElements(); i < N; ++i) { + uint64_t Element = DV->getAddrElement(i); + + if (Element == DIBuilder::OpPlus) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, DV->getAddrElement(++i)); + } else if (Element == DIBuilder::OpDeref) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + } else llvm_unreachable("unknown DIBuilder Opcode"); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/* Byref variables, in Blocks, are declared by the programmer as "SomeType + VarName;", but the compiler creates a __Block_byref_x_VarName struct, and + gives the variable VarName either the struct, or a pointer to the struct, as + its type. This is necessary for various behind-the-scenes things the + compiler needs to do with by-reference variables in Blocks. + + However, as far as the original *programmer* is concerned, the variable + should still have type 'SomeType', as originally declared. + + The function getBlockByrefType dives into the __Block_byref_x_VarName + struct to find the original type of the variable, which is then assigned to + the variable's Debug Information Entry as its real type. So far, so good. + However now the debugger will expect the variable VarName to have the type + SomeType. So we need the location attribute for the variable to be an + expression that explains to the debugger how to navigate through the + pointers and struct to find the actual variable of type SomeType. + + The following function does just that. We start by getting + the "normal" location for the variable. This will be the location + of either the struct __Block_byref_x_VarName or the pointer to the + struct __Block_byref_x_VarName. + + The struct will look something like: + + struct __Block_byref_x_VarName { + ... + struct __Block_byref_x_VarName *forwarding; + ... + SomeType VarName; + ... + }; + + If we are given the struct directly (as our starting point) we + need to tell the debugger to: + + 1). Add the offset of the forwarding field. + + 2). Follow that pointer to get the real __Block_byref_x_VarName + struct to use (the real one may have been copied onto the heap). + + 3). Add the offset for the field VarName, to find the actual variable. + + If we started with a pointer to the struct, then we need to + dereference that pointer first, before the other steps. + Translating this into DWARF ops, we will need to append the following + to the current location description for the variable: + + DW_OP_deref -- optional, if we start with a pointer + DW_OP_plus_uconst + DW_OP_deref + DW_OP_plus_uconst + + That is what this function does. */ + +/// addBlockByrefAddress - Start with the address based on the location +/// provided, and generate the DWARF information necessary to find the +/// actual Block variable (navigating the Block struct) based on the +/// starting location. Add the DWARF information to the die. For +/// more information, read large comment just above here. +/// +void CompileUnit::addBlockByrefAddress(DbgVariable *&DV, DIE *Die, + unsigned Attribute, + const MachineLocation &Location) { + DIType Ty = DV->getType(); + DIType TmpTy = Ty; + unsigned Tag = Ty.getTag(); + bool isPointer = false; + + StringRef varName = DV->getName(); + + if (Tag == dwarf::DW_TAG_pointer_type) { + DIDerivedType DTy = DIDerivedType(Ty); + TmpTy = DTy.getTypeDerivedFrom(); + isPointer = true; + } + + DICompositeType blockStruct = DICompositeType(TmpTy); + + // Find the __forwarding field and the variable field in the __Block_byref + // struct. + DIArray Fields = blockStruct.getTypeArray(); + DIDescriptor varField = DIDescriptor(); + DIDescriptor forwardingField = DIDescriptor(); + + for (unsigned i = 0, N = Fields.getNumElements(); i < N; ++i) { + DIDescriptor Element = Fields.getElement(i); + DIDerivedType DT = DIDerivedType(Element); + StringRef fieldName = DT.getName(); + if (fieldName == "__forwarding") + forwardingField = Element; + else if (fieldName == varName) + varField = Element; + } + + // Get the offsets for the forwarding field and the variable field. + unsigned forwardingFieldOffset = + DIDerivedType(forwardingField).getOffsetInBits() >> 3; + unsigned varFieldOffset = + DIDerivedType(varField).getOffsetInBits() >> 3; + + // Decode the original location, and use that as the start of the byref + // variable's location. + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + if (Location.isReg()) { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + // If we started with a pointer to the __Block_byref... struct, then + // the first thing we need to do is dereference the pointer (DW_OP_deref). + if (isPointer) + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Next add the offset for the '__forwarding' field: + // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in + // adding the offset if it's 0. + if (forwardingFieldOffset > 0) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, forwardingFieldOffset); + } + + // Now dereference the __forwarding field to get to the real __Block_byref + // struct: DW_OP_deref. + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + // Now that we've got the real __Block_byref... struct, add the offset + // for the variable's field to get to the location of the actual variable: + // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. + if (varFieldOffset > 0) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Block, 0, dwarf::DW_FORM_udata, varFieldOffset); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, 0, Block); +} + +/// addAddress - Add an address attribute to a die based on the location +/// provided. +void CompileUnit::addAddress(DIE *Die, unsigned Attribute, + const MachineLocation &Location) { + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + unsigned Reg = RI->getDwarfRegNum(Location.getReg(), false); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + if (RI->getFrameRegister(*Asm->MF) == Location.getReg() + && Location.getOffset()) { + // If variable offset is based in frame register then use fbreg. + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg); + addSInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + addBlock(Die, Attribute, 0, Block); + return; + } + + if (Location.isReg()) { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + Reg); + } else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + } else { + if (Reg < 32) { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_breg0 + Reg); + } else { + addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_bregx); + addUInt(Block, 0, dwarf::DW_FORM_udata, Reg); + } + + addUInt(Block, 0, dwarf::DW_FORM_sdata, Location.getOffset()); + } + + addBlock(Die, Attribute, 0, Block); +} + +/// addRegisterAddress - Add register location entry in variable DIE. +bool CompileUnit::addRegisterAddress(DIE *Die, const MachineOperand &MO) { + assert (MO.isReg() && "Invalid machine operand!"); + if (!MO.getReg()) + return false; + MachineLocation Location; + Location.set(MO.getReg()); + addAddress(Die, dwarf::DW_AT_location, Location); + return true; +} + +/// addConstantValue - Add constant value entry in variable DIE. +bool CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO) { + assert (MO.isImm() && "Invalid machine operand!"); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + unsigned Imm = MO.getImm(); + addUInt(Block, 0, dwarf::DW_FORM_udata, Imm); + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addConstantFPValue - Add constant value entry in variable DIE. +bool CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { + assert (MO.isFPImm() && "Invalid machine operand!"); + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + APFloat FPImm = MO.getFPImm()->getValueAPF(); + + // Get the raw data form of the floating point. + const APInt FltVal = FPImm.bitcastToAPInt(); + const char *FltPtr = (const char*)FltVal.getRawData(); + + int NumBytes = FltVal.getBitWidth() / 8; // 8 bits per byte. + bool LittleEndian = Asm->getTargetData().isLittleEndian(); + int Incr = (LittleEndian ? 1 : -1); + int Start = (LittleEndian ? 0 : NumBytes - 1); + int Stop = (LittleEndian ? NumBytes : -1); + + // Output the constant to DWARF one byte at a time. + for (; Start != Stop; Start += Incr) + addUInt(Block, 0, dwarf::DW_FORM_data1, + (unsigned char)0xFF & FltPtr[Start]); + + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addConstantValue - Add constant value entry in variable DIE. +bool CompileUnit::addConstantValue(DIE *Die, ConstantInt *CI, + bool Unsigned) { + if (CI->getBitWidth() <= 64) { + if (Unsigned) + addUInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, + CI->getZExtValue()); + else + addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, + CI->getSExtValue()); + return true; + } + + DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + + // Get the raw data form of the large APInt. + const APInt Val = CI->getValue(); + const char *Ptr = (const char*)Val.getRawData(); + + int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte. + bool LittleEndian = Asm->getTargetData().isLittleEndian(); + int Incr = (LittleEndian ? 1 : -1); + int Start = (LittleEndian ? 0 : NumBytes - 1); + int Stop = (LittleEndian ? NumBytes : -1); + + // Output the constant to DWARF one byte at a time. + for (; Start != Stop; Start += Incr) + addUInt(Block, 0, dwarf::DW_FORM_data1, + (unsigned char)0xFF & Ptr[Start]); + + addBlock(Die, dwarf::DW_AT_const_value, 0, Block); + return true; +} + +/// addTemplateParams - Add template parameters in buffer. +void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) { + // Add template parameters. + for (unsigned i = 0, e = TParams.getNumElements(); i != e; ++i) { + DIDescriptor Element = TParams.getElement(i); + if (Element.isTemplateTypeParameter()) + Buffer.addChild(getOrCreateTemplateTypeParameterDIE( + DITemplateTypeParameter(Element))); + else if (Element.isTemplateValueParameter()) + Buffer.addChild(getOrCreateTemplateValueParameterDIE( + DITemplateValueParameter(Element))); + } + +} +/// addToContextOwner - Add Die into the list of its context owner's children. +void CompileUnit::addToContextOwner(DIE *Die, DIDescriptor Context) { + if (Context.isType()) { + DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context)); + ContextDIE->addChild(Die); + } else if (Context.isNameSpace()) { + DIE *ContextDIE = getOrCreateNameSpace(DINameSpace(Context)); + ContextDIE->addChild(Die); + } else if (Context.isSubprogram()) { + DIE *ContextDIE = DD->createSubprogramDIE(DISubprogram(Context)); + ContextDIE->addChild(Die); + } else if (DIE *ContextDIE = getDIE(Context)) + ContextDIE->addChild(Die); + else + addDie(Die); +} + +/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the +/// given DIType. +DIE *CompileUnit::getOrCreateTypeDIE(DIType Ty) { + DIE *TyDIE = getDIE(Ty); + if (TyDIE) + return TyDIE; + + // Create new type. + TyDIE = new DIE(dwarf::DW_TAG_base_type); + insertDIE(Ty, TyDIE); + if (Ty.isBasicType()) + constructTypeDIE(*TyDIE, DIBasicType(Ty)); + else if (Ty.isCompositeType()) + constructTypeDIE(*TyDIE, DICompositeType(Ty)); + else { + assert(Ty.isDerivedType() && "Unknown kind of DIType"); + constructTypeDIE(*TyDIE, DIDerivedType(Ty)); + } + + addToContextOwner(TyDIE, Ty.getContext()); + return TyDIE; +} + +/// addType - Add a new type attribute to the specified entity. +void CompileUnit::addType(DIE *Entity, DIType Ty) { + if (!Ty.Verify()) + return; + + // Check for pre-existence. + DIEEntry *Entry = getDIEEntry(Ty); + // If it exists then use the existing value. + if (Entry) { + Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); + return; + } + + // Construct type. + DIE *Buffer = getOrCreateTypeDIE(Ty); + + // Set up proxy. + Entry = createDIEEntry(Buffer); + insertDIEEntry(Ty, Entry); + + Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry); +} + +/// constructTypeDIE - Construct basic type die from DIBasicType. +void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { + // Get core information. + StringRef Name = BTy.getName(); + Buffer.setTag(dwarf::DW_TAG_base_type); + addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + BTy.getEncoding()); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + uint64_t Size = BTy.getSizeInBits() >> 3; + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); +} + +/// constructTypeDIE - Construct derived type die from DIDerivedType. +void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { + // Get core information. + StringRef Name = DTy.getName(); + uint64_t Size = DTy.getSizeInBits() >> 3; + unsigned Tag = DTy.getTag(); + + // FIXME - Workaround for templates. + if (Tag == dwarf::DW_TAG_inheritance) Tag = dwarf::DW_TAG_reference_type; + + Buffer.setTag(Tag); + + // Map to main type, void will not have a type. + DIType FromTy = DTy.getTypeDerivedFrom(); + addType(&Buffer, FromTy); + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + + // Add source line info if available and TyDesc is not a forward declaration. + if (!DTy.isForwardDecl()) + addSourceLine(&Buffer, DTy); +} + +/// constructTypeDIE - Construct type DIE from DICompositeType. +void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { + // Get core information. + StringRef Name = CTy.getName(); + + uint64_t Size = CTy.getSizeInBits() >> 3; + unsigned Tag = CTy.getTag(); + Buffer.setTag(Tag); + + switch (Tag) { + case dwarf::DW_TAG_vector_type: + case dwarf::DW_TAG_array_type: + constructArrayTypeDIE(Buffer, &CTy); + break; + case dwarf::DW_TAG_enumeration_type: { + DIArray Elements = CTy.getTypeArray(); + + // Add enumerators to enumeration type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIE *ElemDie = NULL; + DIDescriptor Enum(Elements.getElement(i)); + if (Enum.isEnumerator()) { + ElemDie = constructEnumTypeDIE(DIEnumerator(Enum)); + Buffer.addChild(ElemDie); + } + } + } + break; + case dwarf::DW_TAG_subroutine_type: { + // Add return type. + DIArray Elements = CTy.getTypeArray(); + DIDescriptor RTy = Elements.getElement(0); + addType(&Buffer, DIType(RTy)); + + bool isPrototyped = true; + // Add arguments. + for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Ty = Elements.getElement(i); + if (Ty.isUnspecifiedParameter()) { + DIE *Arg = new DIE(dwarf::DW_TAG_unspecified_parameters); + Buffer.addChild(Arg); + isPrototyped = false; + } else { + DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter); + addType(Arg, DIType(Ty)); + Buffer.addChild(Arg); + } + } + // Add prototype flag. + if (isPrototyped) + addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1); + } + break; + case dwarf::DW_TAG_structure_type: + case dwarf::DW_TAG_union_type: + case dwarf::DW_TAG_class_type: { + // Add elements to structure type. + DIArray Elements = CTy.getTypeArray(); + + // A forward struct declared type may not have elements available. + unsigned N = Elements.getNumElements(); + if (N == 0) + break; + + // Add elements to structure type. + for (unsigned i = 0; i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + DIE *ElemDie = NULL; + if (Element.isSubprogram()) { + DISubprogram SP(Element); + ElemDie = DD->createSubprogramDIE(DISubprogram(Element)); + if (SP.isProtected()) + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_protected); + else if (SP.isPrivate()) + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_private); + else + addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_public); + if (SP.isExplicit()) + addUInt(ElemDie, dwarf::DW_AT_explicit, dwarf::DW_FORM_flag, 1); + } + else if (Element.isVariable()) { + DIVariable DV(Element); + ElemDie = new DIE(dwarf::DW_TAG_variable); + addString(ElemDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, + DV.getName()); + addType(ElemDie, DV.getType()); + addUInt(ElemDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + addUInt(ElemDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1); + addSourceLine(ElemDie, DV); + } else if (Element.isDerivedType()) + ElemDie = createMemberDIE(DIDerivedType(Element)); + else + continue; + Buffer.addChild(ElemDie); + } + + if (CTy.isAppleBlockExtension()) + addUInt(&Buffer, dwarf::DW_AT_APPLE_block, dwarf::DW_FORM_flag, 1); + + unsigned RLang = CTy.getRunTimeLang(); + if (RLang) + addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, + dwarf::DW_FORM_data1, RLang); + + DICompositeType ContainingType = CTy.getContainingType(); + if (DIDescriptor(ContainingType).isCompositeType()) + addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, + getOrCreateTypeDIE(DIType(ContainingType))); + else { + DIDescriptor Context = CTy.getContext(); + addToContextOwner(&Buffer, Context); + } + + if (Tag == dwarf::DW_TAG_class_type) + addTemplateParams(Buffer, CTy.getTemplateParams()); + + break; + } + default: + break; + } + + // Add name if not anonymous or intermediate type. + if (!Name.empty()) + addString(&Buffer, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type + || Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type) + { + // Add size if non-zero (derived types might be zero-sized.) + if (Size) + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, Size); + else { + // Add zero size if it is not a forward declaration. + if (CTy.isForwardDecl()) + addUInt(&Buffer, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1); + else + addUInt(&Buffer, dwarf::DW_AT_byte_size, 0, 0); + } + + // Add source line info if available. + if (!CTy.isForwardDecl()) + addSourceLine(&Buffer, CTy); + } +} + +/// getOrCreateTemplateTypeParameterDIE - Find existing DIE or create new DIE +/// for the given DITemplateTypeParameter. +DIE * +CompileUnit::getOrCreateTemplateTypeParameterDIE(DITemplateTypeParameter TP) { + DIE *ParamDIE = getDIE(TP); + if (ParamDIE) + return ParamDIE; + + ParamDIE = new DIE(dwarf::DW_TAG_template_type_parameter); + addType(ParamDIE, TP.getType()); + addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TP.getName()); + return ParamDIE; +} + +/// getOrCreateTemplateValueParameterDIE - Find existing DIE or create new DIE +/// for the given DITemplateValueParameter. +DIE * +CompileUnit::getOrCreateTemplateValueParameterDIE(DITemplateValueParameter TPV) { + DIE *ParamDIE = getDIE(TPV); + if (ParamDIE) + return ParamDIE; + + ParamDIE = new DIE(dwarf::DW_TAG_template_value_parameter); + addType(ParamDIE, TPV.getType()); + if (!TPV.getName().empty()) + addString(ParamDIE, dwarf::DW_AT_name, dwarf::DW_FORM_string, TPV.getName()); + addUInt(ParamDIE, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, + TPV.getValue()); + return ParamDIE; +} + +/// constructSubrangeDIE - Construct subrange DIE from DISubrange. +void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){ + DIE *DW_Subrange = new DIE(dwarf::DW_TAG_subrange_type); + addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy); + int64_t L = SR.getLo(); + int64_t H = SR.getHi(); + + // The L value defines the lower bounds which is typically zero for C/C++. The + // H value is the upper bounds. Values are 64 bit. H - L + 1 is the size + // of the array. If L > H then do not emit DW_AT_lower_bound and + // DW_AT_upper_bound attributes. If L is zero and H is also zero then the + // array has one element and in such case do not emit lower bound. + + if (L > H) { + Buffer.addChild(DW_Subrange); + return; + } + if (L) + addSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L); + addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H); + Buffer.addChild(DW_Subrange); +} + +/// constructArrayTypeDIE - Construct array type DIE from DICompositeType. +void CompileUnit::constructArrayTypeDIE(DIE &Buffer, + DICompositeType *CTy) { + Buffer.setTag(dwarf::DW_TAG_array_type); + if (CTy->getTag() == dwarf::DW_TAG_vector_type) + addUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1); + + // Emit derived type. + addType(&Buffer, CTy->getTypeDerivedFrom()); + DIArray Elements = CTy->getTypeArray(); + + // Get an anonymous type for index type. + DIE *IdxTy = getIndexTyDie(); + if (!IdxTy) { + // Construct an anonymous type for index type. + IdxTy = new DIE(dwarf::DW_TAG_base_type); + addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t)); + addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + dwarf::DW_ATE_signed); + addDie(IdxTy); + setIndexTyDie(IdxTy); + } + + // Add subranges to array type. + for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { + DIDescriptor Element = Elements.getElement(i); + if (Element.getTag() == dwarf::DW_TAG_subrange_type) + constructSubrangeDIE(Buffer, DISubrange(Element), IdxTy); + } +} + +/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator. +DIE *CompileUnit::constructEnumTypeDIE(DIEnumerator ETy) { + DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator); + StringRef Name = ETy.getName(); + addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + int64_t Value = ETy.getEnumValue(); + addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); + return Enumerator; +} + +/// createMemberDIE - Create new member DIE. +DIE *CompileUnit::createMemberDIE(DIDerivedType DT) { + DIE *MemberDie = new DIE(DT.getTag()); + StringRef Name = DT.getName(); + if (!Name.empty()) + addString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name); + + addType(MemberDie, DT.getTypeDerivedFrom()); + + addSourceLine(MemberDie, DT); + + DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); + addUInt(MemLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + + uint64_t Size = DT.getSizeInBits(); + uint64_t FieldSize = DT.getOriginalTypeSize(); + + if (Size != FieldSize) { + // Handle bitfield. + addUInt(MemberDie, dwarf::DW_AT_byte_size, 0, DT.getOriginalTypeSize()>>3); + addUInt(MemberDie, dwarf::DW_AT_bit_size, 0, DT.getSizeInBits()); + + uint64_t Offset = DT.getOffsetInBits(); + uint64_t AlignMask = ~(DT.getAlignInBits() - 1); + uint64_t HiMark = (Offset + FieldSize) & AlignMask; + uint64_t FieldOffset = (HiMark - FieldSize); + Offset -= FieldOffset; + + // Maybe we need to work from the other end. + if (Asm->getTargetData().isLittleEndian()) + Offset = FieldSize - (Offset + Size); + addUInt(MemberDie, dwarf::DW_AT_bit_offset, 0, Offset); + + // Here WD_AT_data_member_location points to the anonymous + // field that includes this bit field. + addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, FieldOffset >> 3); + + } else + // This is not a bitfield. + addUInt(MemLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits() >> 3); + + if (DT.getTag() == dwarf::DW_TAG_inheritance + && DT.isVirtual()) { + + // For C++, virtual base classes are not at fixed offset. Use following + // expression to extract appropriate offset from vtable. + // BaseAddr = ObAddr + *((*ObAddr) - Offset) + + DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock(); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_udata, DT.getOffsetInBits()); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(VBaseLocationDie, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, + VBaseLocationDie); + } else + addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie); + + if (DT.isProtected()) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_protected); + else if (DT.isPrivate()) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_private); + // Otherwise C++ member and base classes are considered public. + else if (DT.getCompileUnit().getLanguage() == dwarf::DW_LANG_C_plus_plus) + addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag, + dwarf::DW_ACCESS_public); + if (DT.isVirtual()) + addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, + dwarf::DW_VIRTUALITY_virtual); + return MemberDie; +} From rafael.espindola at gmail.com Tue Apr 12 18:26:22 2011 From: rafael.espindola at gmail.com (=?ISO-8859-1?Q?Rafael_=C1vila_de_Esp=EDndola?=) Date: Tue, 12 Apr 2011 19:26:22 -0400 Subject: [llvm-commits] [llvm] r129402 - in /llvm/trunk/lib/CodeGen/AsmPrinter: CMakeLists.txt DwarfCompileUnit.h DwarfDebug.cpp DwarfDebug.h In-Reply-To: <20110412225302.E703D2A6C12D@llvm.org> References: <20110412225302.E703D2A6C12D@llvm.org> Message-ID: <4DA4DF9E.4090905@gmail.com> On 2011-04-12 18:53, Devang Patel wrote: > Author: dpatel > Date: Tue Apr 12 17:53:02 2011 > New Revision: 129402 > > URL: http://llvm.org/viewvc/llvm-project?rev=129402&view=rev > Log: > This mechanical patch moves type handling into CompileUnit from DwarfDebug. In case of multiple compile unit in one object file, each compile unit is responsible for its own set of type entries anyway. This refactoring makes this obvious. > > Modified: > llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt > llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h > llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp > llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h DwarfCompileUnit.cpp is missing. Cheers, Rafael From echristo at apple.com Tue Apr 12 18:23:14 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 12 Apr 2011 23:23:14 -0000 Subject: [llvm-commits] [llvm] r129408 - in /llvm/trunk: lib/CodeGen/RegAllocFast.cpp test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll Message-ID: <20110412232315.0023A2A6C12D@llvm.org> Author: echristo Date: Tue Apr 12 18:23:14 2011 New Revision: 129408 URL: http://llvm.org/viewvc/llvm-project?rev=129408&view=rev Log: Fix a bug where we were counting the alias sets as completely used registers for fast allocation. Fixes rdar://9207598 Added: llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocFast.cpp?rev=129408&r1=129407&r2=129408&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocFast.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocFast.cpp Tue Apr 12 18:23:14 2011 @@ -442,8 +442,6 @@ unsigned Cost = 0; for (const unsigned *AS = TRI->getAliasSet(PhysReg); unsigned Alias = *AS; ++AS) { - if (UsedInInstr.test(Alias)) - return spillImpossible; switch (unsigned VirtReg = PhysRegState[Alias]) { case regDisabled: break; Added: llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll?rev=129408&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll (added) +++ llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll Tue Apr 12 18:23:14 2011 @@ -0,0 +1,15 @@ +; RUN: llc < %s -O0 -verify-machineinstrs -regalloc=fast +; Previously we'd crash as out of registers on this input by clobbering all of +; the aliases. +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32" +target triple = "thumbv7-apple-darwin10.0.0" + +define void @_Z8TestCasev() nounwind ssp { +entry: + %a = alloca float, align 4 + %tmp = load float* %a, align 4 + call void asm sideeffect "", "w,~{s0},~{s16}"(float %tmp) nounwind, !srcloc !0 + ret void +} + +!0 = metadata !{i32 109} From dpatel at apple.com Tue Apr 12 18:28:16 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 12 Apr 2011 16:28:16 -0700 Subject: [llvm-commits] [llvm] r129402 - in /llvm/trunk/lib/CodeGen/AsmPrinter: CMakeLists.txt DwarfCompileUnit.h DwarfDebug.cpp DwarfDebug.h In-Reply-To: <4DA4DF9E.4090905@gmail.com> References: <20110412225302.E703D2A6C12D@llvm.org> <4DA4DF9E.4090905@gmail.com> Message-ID: On Apr 12, 2011, at 4:26 PM, Rafael ?vila de Esp?ndola wrote: > On 2011-04-12 18:53, Devang Patel wrote: >> Author: dpatel >> Date: Tue Apr 12 17:53:02 2011 >> New Revision: 129402 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=129402&view=rev >> Log: >> This mechanical patch moves type handling into CompileUnit from DwarfDebug. In case of multiple compile unit in one object file, each compile unit is responsible for its own set of type entries anyway. This refactoring makes this obvious. >> >> Modified: >> llvm/trunk/lib/CodeGen/AsmPrinter/CMakeLists.txt >> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h >> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp >> llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.h > > > DwarfCompileUnit.cpp is missing. Oops. svn add'ed in r129407. - Devang From stoklund at 2pi.dk Tue Apr 12 18:27:48 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 12 Apr 2011 23:27:48 -0000 Subject: [llvm-commits] [llvm] r129409 - in /llvm/trunk/lib/Target/ARM: ARMInstrInfo.td ARMInstrThumb2.td Message-ID: <20110412232748.C4F3C2A6C12D@llvm.org> Author: stoklund Date: Tue Apr 12 18:27:48 2011 New Revision: 129409 URL: http://llvm.org/viewvc/llvm-project?rev=129409&view=rev Log: Add @earlyclobber constraints to the writeback register of all ARM store instructions. The ARMARM specifies these instructions as unpredictable when storing the writeback register. This shouldn't affect code generation much since storing a pointer to itself is quite rare. Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=129409&r1=129408&r2=129409&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Apr 12 18:27:48 2011 @@ -1802,41 +1802,47 @@ def STR_PRE : AI2stridx<0, 1, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), IndexModePre, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + "str", "\t$Rt, [$Rn, $offset]!", + "$Rn = $Rn_wb, at earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (pre_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; def STR_POST : AI2stridx<0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), IndexModePost, StFrm, IIC_iStore_ru, - "str", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + "str", "\t$Rt, [$Rn], $offset", + "$Rn = $Rn_wb, at earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (post_store GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; def STRB_PRE : AI2stridx<1, 1, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), IndexModePre, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + "strb", "\t$Rt, [$Rn, $offset]!", + "$Rn = $Rn_wb, at earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (pre_truncsti8 GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; def STRB_POST: AI2stridx<1, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am2offset:$offset), IndexModePost, StFrm, IIC_iStore_bh_ru, - "strb", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + "strb", "\t$Rt, [$Rn], $offset", + "$Rn = $Rn_wb, at earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (post_truncsti8 GPR:$Rt, GPR:$Rn, am2offset:$offset))]>; def STRH_PRE : AI3stridx<0b1011, 0, 1, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), IndexModePre, StMiscFrm, IIC_iStore_ru, - "strh", "\t$Rt, [$Rn, $offset]!", "$Rn = $Rn_wb", + "strh", "\t$Rt, [$Rn, $offset]!", + "$Rn = $Rn_wb, at earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (pre_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>; def STRH_POST: AI3stridx<0b1011, 0, 0, (outs GPR:$Rn_wb), (ins GPR:$Rt, GPR:$Rn, am3offset:$offset), IndexModePost, StMiscFrm, IIC_iStore_bh_ru, - "strh", "\t$Rt, [$Rn], $offset", "$Rn = $Rn_wb", + "strh", "\t$Rt, [$Rn], $offset", + "$Rn = $Rn_wb, at earlyclobber $Rn_wb", [(set GPR:$Rn_wb, (post_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>; Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=129409&r1=129408&r2=129409&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Apr 12 18:27:48 2011 @@ -1423,42 +1423,48 @@ def t2STR_PRE : T2Iidxldst<0, 0b10, 0, 1, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_iu, - "str", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb", + "str", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb, at earlyclobber $base_wb", [(set GPR:$base_wb, (pre_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STR_POST : T2Iidxldst<0, 0b10, 0, 0, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_iu, - "str", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb", + "str", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb, at earlyclobber $base_wb", [(set GPR:$base_wb, (post_store GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRH_PRE : T2Iidxldst<0, 0b01, 0, 1, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_iu, - "strh", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb", + "strh", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb, at earlyclobber $base_wb", [(set GPR:$base_wb, (pre_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRH_POST : T2Iidxldst<0, 0b01, 0, 0, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu, - "strh", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb", + "strh", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb, at earlyclobber $base_wb", [(set GPR:$base_wb, (post_truncsti16 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRB_PRE : T2Iidxldst<0, 0b00, 0, 1, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePre, IIC_iStore_bh_iu, - "strb", "\t$Rt, [$Rn, $addr]!", "$Rn = $base_wb", + "strb", "\t$Rt, [$Rn, $addr]!", + "$Rn = $base_wb, at earlyclobber $base_wb", [(set GPR:$base_wb, (pre_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; def t2STRB_POST : T2Iidxldst<0, 0b00, 0, 0, (outs GPR:$base_wb), (ins GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr), AddrModeT2_i8, IndexModePost, IIC_iStore_bh_iu, - "strb", "\t$Rt, [$Rn], $addr", "$Rn = $base_wb", + "strb", "\t$Rt, [$Rn], $addr", + "$Rn = $base_wb, at earlyclobber $base_wb", [(set GPR:$base_wb, (post_truncsti8 GPR:$Rt, GPR:$Rn, t2am_imm8_offset:$addr))]>; From johnny.chen at apple.com Tue Apr 12 18:31:00 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Tue, 12 Apr 2011 23:31:00 -0000 Subject: [llvm-commits] [llvm] r129411 - in /llvm/trunk: lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt Message-ID: <20110412233100.893A42A6C12D@llvm.org> Author: johnny Date: Tue Apr 12 18:31:00 2011 New Revision: 129411 URL: http://llvm.org/viewvc/llvm-project?rev=129411&view=rev Log: Add sanity check for Ld/St Dual forms of Thumb2 instructions. rdar://problem/9273947 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129411&r1=129410&r2=129411&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Tue Apr 12 18:31:00 2011 @@ -1275,6 +1275,35 @@ && OpInfo[3].RegClass < 0 && "Expect >= 4 operands and first 3 as reg operands"); + // Thumnb allows for specifying Rt and Rt2, unlike ARM (which has Rt2==Rt+1). + unsigned Rt = decodeRd(insn); + unsigned Rt2 = decodeRs(insn); + unsigned Rn = decodeRn(insn); + + // Some sanity checking first. + + // A8.6.67 LDRD (literal) has its W bit as (0). + if (Opcode == ARM::t2LDRDi8 || Opcode == ARM::t2LDRD_PRE || Opcode == ARM::t2LDRD_POST) { + if (Rn == 15 && slice(insn, 21, 21) != 0) + return false; + } else { + // For Dual Store, PC cannot be used as the base register. + if (Rn == 15) { + DEBUG(errs() << "if n == 15 then UNPREDICTABLE\n"); + return false; + } + } + if (Rt == Rt2) { + DEBUG(errs() << "if t == t2 then UNPREDICTABLE\n"); + return false; + } + if (Opcode != ARM::t2LDRDi8 && Opcode != ARM::t2STRDi8) { + if (Rn == Rt || Rn == Rt2) { + DEBUG(errs() << "if wback && (n == t || n == t2) then UNPREDICTABLE\n"); + return false; + } + } + // Add the operands. unsigned RegClassPair = OpInfo[0].RegClass; unsigned RegClassBase = OpInfo[2].RegClass; Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt?rev=129411&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt Tue Apr 12 18:31:00 2011 @@ -0,0 +1,13 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=1930 Name=t2LDRD_PRE Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 0| 1: 0: 0: 1| 1: 1: 1: 1| 1: 1: 1: 1| 1: 1: 1: 0| 1: 0: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| +# ------------------------------------------------------------------------------------------------- +# +# A8.6.66 LDRD (immediate) +# if Rn = '1111' then SEE LDRD (literal) +# A8.6.67 LDRD (literal) +# Inst{21} = 0 +0xff 0xe9 0x0 0xeb Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt?rev=129411&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt Tue Apr 12 18:31:00 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=2124 Name=t2STRD_PRE Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 0| 1: 0: 0: 1| 1: 1: 1: 0| 0: 1: 0: 0| 0: 1: 0: 0| 0: 1: 1: 0| 0: 0: 0: 0| 0: 0: 1: 0| +# ------------------------------------------------------------------------------------------------- +# +# if wback && (n == t || n == t2) then UNPREDICTABLE +0xe4 0xe9 0x02 0x46 From rafael.espindola at gmail.com Tue Apr 12 18:59:07 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Tue, 12 Apr 2011 23:59:07 -0000 Subject: [llvm-commits] [llvm] r129413 - in /llvm/trunk: include/llvm/MC/MCStreamer.h lib/MC/MCAsmStreamer.cpp lib/MC/MCParser/AsmParser.cpp lib/MC/MCStreamer.cpp Message-ID: <20110412235907.7D3972A6C12D@llvm.org> Author: rafael Date: Tue Apr 12 18:59:07 2011 New Revision: 129413 URL: http://llvm.org/viewvc/llvm-project?rev=129413&view=rev Log: Be consistent about being virtual and returning void in the cfi methods. Implement the ones that were missing in the asm streamer. Modified: llvm/trunk/include/llvm/MC/MCStreamer.h llvm/trunk/lib/MC/MCAsmStreamer.cpp llvm/trunk/lib/MC/MCParser/AsmParser.cpp llvm/trunk/lib/MC/MCStreamer.cpp Modified: llvm/trunk/include/llvm/MC/MCStreamer.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=129413&r1=129412&r2=129413&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCStreamer.h (original) +++ llvm/trunk/include/llvm/MC/MCStreamer.h Tue Apr 12 18:59:07 2011 @@ -435,20 +435,19 @@ void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, int PointerSize); - virtual bool EmitCFIStartProc(); - virtual bool EmitCFIEndProc(); - virtual bool EmitCFIDefCfa(int64_t Register, int64_t Offset); - virtual bool EmitCFIDefCfaOffset(int64_t Offset); - virtual bool EmitCFIDefCfaRegister(int64_t Register); - virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); - virtual bool EmitCFIPersonality(const MCSymbol *Sym, - unsigned Encoding); - virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); - virtual bool EmitCFIRememberState(); - virtual bool EmitCFIRestoreState(); - void EmitCFISameValue(int64_t Register); - void EmitCFIRelOffset(int64_t Register, int64_t Offset); - void EmitCFIAdjustCfaOffset(int64_t Adjustment); + virtual void EmitCFIStartProc(); + virtual void EmitCFIEndProc(); + virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual void EmitCFIDefCfaOffset(int64_t Offset); + virtual void EmitCFIDefCfaRegister(int64_t Register); + virtual void EmitCFIOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIRememberState(); + virtual void EmitCFIRestoreState(); + virtual void EmitCFISameValue(int64_t Register); + virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); /// EmitInstruction - Emit the given @p Instruction into the current /// section. Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=129413&r1=129412&r2=129413&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original) +++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Tue Apr 12 18:59:07 2011 @@ -184,13 +184,19 @@ unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator); - virtual bool EmitCFIStartProc(); - virtual bool EmitCFIEndProc(); - virtual bool EmitCFIDefCfaOffset(int64_t Offset); - virtual bool EmitCFIDefCfaRegister(int64_t Register); - virtual bool EmitCFIOffset(int64_t Register, int64_t Offset); - virtual bool EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); - virtual bool EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIStartProc(); + virtual void EmitCFIEndProc(); + virtual void EmitCFIDefCfa(int64_t Register, int64_t Offset); + virtual void EmitCFIDefCfaOffset(int64_t Offset); + virtual void EmitCFIDefCfaRegister(int64_t Register); + virtual void EmitCFIOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFILsda(const MCSymbol *Sym, unsigned Encoding); + virtual void EmitCFIRememberState(); + virtual void EmitCFIRestoreState(); + virtual void EmitCFISameValue(int64_t Register); + virtual void EmitCFIRelOffset(int64_t Register, int64_t Offset); + virtual void EmitCFIAdjustCfaOffset(int64_t Adjustment); virtual void EmitFnStart(); virtual void EmitFnEnd(); @@ -714,75 +720,93 @@ EmitEOL(); } -bool MCAsmStreamer::EmitCFIStartProc() { - if (this->MCStreamer::EmitCFIStartProc()) - return true; +void MCAsmStreamer::EmitCFIStartProc() { + MCStreamer::EmitCFIStartProc(); OS << "\t.cfi_startproc"; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIEndProc() { - if (this->MCStreamer::EmitCFIEndProc()) - return true; +void MCAsmStreamer::EmitCFIEndProc() { + MCStreamer::EmitCFIEndProc(); OS << "\t.cfi_endproc"; EmitEOL(); +} - return false; +void MCAsmStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { + abort(); } -bool MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { - if (this->MCStreamer::EmitCFIDefCfaOffset(Offset)) - return true; +void MCAsmStreamer::EmitCFIDefCfaOffset(int64_t Offset) { + MCStreamer::EmitCFIDefCfaOffset(Offset); OS << "\t.cfi_def_cfa_offset " << Offset; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { - if (this->MCStreamer::EmitCFIDefCfaRegister(Register)) - return true; +void MCAsmStreamer::EmitCFIDefCfaRegister(int64_t Register) { + MCStreamer::EmitCFIDefCfaRegister(Register); OS << "\t.cfi_def_cfa_register " << Register; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { - if (this->MCStreamer::EmitCFIOffset(Register, Offset)) - return true; +void MCAsmStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { + this->MCStreamer::EmitCFIOffset(Register, Offset); OS << "\t.cfi_offset " << Register << ", " << Offset; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, +void MCAsmStreamer::EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) { - if (this->MCStreamer::EmitCFIPersonality(Sym, Encoding)) - return true; + MCStreamer::EmitCFIPersonality(Sym, Encoding); OS << "\t.cfi_personality " << Encoding << ", " << *Sym; EmitEOL(); - - return false; } -bool MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { - if (this->MCStreamer::EmitCFILsda(Sym, Encoding)) - return true; +void MCAsmStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { + MCStreamer::EmitCFILsda(Sym, Encoding); OS << "\t.cfi_lsda " << Encoding << ", " << *Sym; EmitEOL(); +} - return false; +void MCAsmStreamer::EmitCFIRememberState() { + MCStreamer::EmitCFIRememberState(); + + OS << "\t.cfi_remember_state"; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFIRestoreState() { + MCStreamer::EmitCFIRestoreState(); + + OS << "\t.cfi_restore_state"; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFISameValue(int64_t Register) { + MCStreamer::EmitCFISameValue(Register); + + OS << "\t.cfi_same_value " << Register; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { + MCStreamer::EmitCFIRelOffset(Register, Offset); + + OS << "\t.cfi_rel_offset " << Register << ", " << Offset; + EmitEOL(); +} + +void MCAsmStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { + MCStreamer::EmitCFIAdjustCfaOffset(Adjustment); + + OS << "\t.cfi_adjust_cfa_offset " << Adjustment; + EmitEOL(); } void MCAsmStreamer::AddEncodingComment(const MCInst &Inst) { Modified: llvm/trunk/lib/MC/MCParser/AsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/AsmParser.cpp?rev=129413&r1=129412&r2=129413&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp (original) +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp Tue Apr 12 18:59:07 2011 @@ -2269,13 +2269,15 @@ /// ::= .cfi_startproc bool GenericAsmParser::ParseDirectiveCFIStartProc(StringRef, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIStartProc(); + getStreamer().EmitCFIStartProc(); + return false; } /// ParseDirectiveCFIEndProc /// ::= .cfi_endproc bool GenericAsmParser::ParseDirectiveCFIEndProc(StringRef, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIEndProc(); + getStreamer().EmitCFIEndProc(); + return false; } /// ParseRegisterOrRegisterNumber - parse register name or number. @@ -2310,7 +2312,8 @@ if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIDefCfa(Register, Offset); + getStreamer().EmitCFIDefCfa(Register, Offset); + return false; } /// ParseDirectiveCFIDefCfaOffset @@ -2321,7 +2324,8 @@ if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIDefCfaOffset(Offset); + getStreamer().EmitCFIDefCfaOffset(Offset); + return false; } /// ParseDirectiveCFIAdjustCfaOffset @@ -2344,7 +2348,8 @@ if (ParseRegisterOrRegisterNumber(Register, DirectiveLoc)) return true; - return getStreamer().EmitCFIDefCfaRegister(Register); + getStreamer().EmitCFIDefCfaRegister(Register); + return false; } /// ParseDirectiveCFIOffset @@ -2363,7 +2368,8 @@ if (getParser().ParseAbsoluteExpression(Offset)) return true; - return getStreamer().EmitCFIOffset(Register, Offset); + getStreamer().EmitCFIOffset(Register, Offset); + return false; } /// ParseDirectiveCFIRelOffset @@ -2434,25 +2440,28 @@ MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); if (IDVal == ".cfi_personality") - return getStreamer().EmitCFIPersonality(Sym, Encoding); + getStreamer().EmitCFIPersonality(Sym, Encoding); else { assert(IDVal == ".cfi_lsda"); - return getStreamer().EmitCFILsda(Sym, Encoding); + getStreamer().EmitCFILsda(Sym, Encoding); } + return false; } /// ParseDirectiveCFIRememberState /// ::= .cfi_remember_state bool GenericAsmParser::ParseDirectiveCFIRememberState(StringRef IDVal, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIRememberState(); + getStreamer().EmitCFIRememberState(); + return false; } /// ParseDirectiveCFIRestoreState /// ::= .cfi_remember_state bool GenericAsmParser::ParseDirectiveCFIRestoreState(StringRef IDVal, SMLoc DirectiveLoc) { - return getStreamer().EmitCFIRestoreState(); + getStreamer().EmitCFIRestoreState(); + return false; } /// ParseDirectiveCFISameValue Modified: llvm/trunk/lib/MC/MCStreamer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=129413&r1=129412&r2=129413&view=diff ============================================================================== --- llvm/trunk/lib/MC/MCStreamer.cpp (original) +++ llvm/trunk/lib/MC/MCStreamer.cpp Tue Apr 12 18:59:07 2011 @@ -152,28 +152,24 @@ report_fatal_error("No open frame"); } -bool MCStreamer::EmitCFIStartProc() { +void MCStreamer::EmitCFIStartProc() { MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); - if (CurFrame && !CurFrame->End) { + if (CurFrame && !CurFrame->End) report_fatal_error("Starting a frame before finishing the previous one!"); - return true; - } MCDwarfFrameInfo Frame; Frame.Begin = getContext().CreateTempSymbol(); EmitLabel(Frame.Begin); FrameInfos.push_back(Frame); - return false; } -bool MCStreamer::EmitCFIEndProc() { +void MCStreamer::EmitCFIEndProc() { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); CurFrame->End = getContext().CreateTempSymbol(); EmitLabel(CurFrame->End); - return false; } -bool MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { +void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); @@ -182,10 +178,9 @@ MachineLocation Source(Register, -Offset); MCCFIInstruction Instruction(Label, Dest, Source); CurFrame->Instructions.push_back(Instruction); - return false; } -bool MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { +void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); @@ -194,7 +189,6 @@ MachineLocation Source(MachineLocation::VirtualFP, -Offset); MCCFIInstruction Instruction(Label, Dest, Source); CurFrame->Instructions.push_back(Instruction); - return false; } void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { @@ -208,7 +202,7 @@ CurFrame->Instructions.push_back(Instruction); } -bool MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { +void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); @@ -217,10 +211,9 @@ MachineLocation Source(MachineLocation::VirtualFP); MCCFIInstruction Instruction(Label, Dest, Source); CurFrame->Instructions.push_back(Instruction); - return false; } -bool MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { +void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); @@ -229,7 +222,6 @@ MachineLocation Source(Register, Offset); MCCFIInstruction Instruction(Label, Dest, Source); CurFrame->Instructions.push_back(Instruction); - return false; } void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { @@ -243,34 +235,31 @@ CurFrame->Instructions.push_back(Instruction); } -bool MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, +void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, unsigned Encoding) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); CurFrame->Personality = Sym; CurFrame->PersonalityEncoding = Encoding; - return false; } -bool MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { +void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); CurFrame->Lsda = Sym; CurFrame->LsdaEncoding = Encoding; - return false; } -bool MCStreamer::EmitCFIRememberState() { +void MCStreamer::EmitCFIRememberState() { EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); MCSymbol *Label = getContext().CreateTempSymbol(); EmitLabel(Label); MCCFIInstruction Instruction(MCCFIInstruction::Remember, Label); CurFrame->Instructions.push_back(Instruction); - return false; } -bool MCStreamer::EmitCFIRestoreState() { +void MCStreamer::EmitCFIRestoreState() { // FIXME: Error if there is no matching cfi_remember_state. EnsureValidFrame(); MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); @@ -278,7 +267,6 @@ EmitLabel(Label); MCCFIInstruction Instruction(MCCFIInstruction::Restore, Label); CurFrame->Instructions.push_back(Instruction); - return false; } void MCStreamer::EmitCFISameValue(int64_t Register) { From echristo at apple.com Tue Apr 12 19:20:59 2011 From: echristo at apple.com (Eric Christopher) Date: Wed, 13 Apr 2011 00:20:59 -0000 Subject: [llvm-commits] [llvm] r129417 - in /llvm/trunk: lib/CodeGen/RegAllocFast.cpp test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll Message-ID: <20110413002059.4BEC52A6C12E@llvm.org> Author: echristo Date: Tue Apr 12 19:20:59 2011 New Revision: 129417 URL: http://llvm.org/viewvc/llvm-project?rev=129417&view=rev Log: Temporarily revert r129408 to see if it brings the bots back. Removed: llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp Modified: llvm/trunk/lib/CodeGen/RegAllocFast.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocFast.cpp?rev=129417&r1=129416&r2=129417&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocFast.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocFast.cpp Tue Apr 12 19:20:59 2011 @@ -442,6 +442,8 @@ unsigned Cost = 0; for (const unsigned *AS = TRI->getAliasSet(PhysReg); unsigned Alias = *AS; ++AS) { + if (UsedInInstr.test(Alias)) + return spillImpossible; switch (unsigned VirtReg = PhysRegState[Alias]) { case regDisabled: break; Removed: llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll?rev=129416&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll (original) +++ llvm/trunk/test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll (removed) @@ -1,15 +0,0 @@ -; RUN: llc < %s -O0 -verify-machineinstrs -regalloc=fast -; Previously we'd crash as out of registers on this input by clobbering all of -; the aliases. -target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32" -target triple = "thumbv7-apple-darwin10.0.0" - -define void @_Z8TestCasev() nounwind ssp { -entry: - %a = alloca float, align 4 - %tmp = load float* %a, align 4 - call void asm sideeffect "", "w,~{s0},~{s16}"(float %tmp) nounwind, !srcloc !0 - ret void -} - -!0 = metadata !{i32 109} From clattner at apple.com Tue Apr 12 19:36:15 2011 From: clattner at apple.com (Chris Lattner) Date: Tue, 12 Apr 2011 17:36:15 -0700 Subject: [llvm-commits] [llvm] r129384 - /llvm/trunk/runtime/libprofile/LineProfiling.c In-Reply-To: <20110412200650.9C0682A6C12D@llvm.org> References: <20110412200650.9C0682A6C12D@llvm.org> Message-ID: <3ADC664C-E0C1-4E04-859C-C70460A228A5@apple.com> On Apr 12, 2011, at 1:06 PM, Nick Lewycky wrote: > Author: nicholas > Date: Tue Apr 12 15:06:50 2011 > New Revision: 129384 > > URL: http://llvm.org/viewvc/llvm-project?rev=129384&view=rev > Log: > Print our uint64_t with the more portable (C99 and C++0x) %PRIu64 format > specifier. Uh, I'm pretty sure that isn't more portable. Why not just cast it to (unsigned long long) and print with %ull? -Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110412/fa743a24/attachment.html From evan.cheng at apple.com Tue Apr 12 19:35:47 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Wed, 13 Apr 2011 00:35:47 -0000 Subject: [llvm-commits] [llvm-gcc-4.2] r129418 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Message-ID: <20110413003547.45E602A6C12D@llvm.org> Author: evancheng Date: Tue Apr 12 19:35:47 2011 New Revision: 129418 URL: http://llvm.org/viewvc/llvm-project?rev=129418&view=rev Log: Try to unbreak mingw buildbots. Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Modified: llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp?rev=129418&r1=129417&r2=129418&view=diff ============================================================================== --- llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp (original) +++ llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp Tue Apr 12 19:35:47 2011 @@ -74,9 +74,11 @@ // These are defined in c-common.c. The weak symbols are for linking non-c // compilers. +#ifndef __MINGW32__ int flag_no_builtin __attribute__ ((__weak__)) = 0; int builtin_function_disabled_p(const char *name) __attribute__ ((__weak__)); int builtin_function_disabled_p(const char *name) { return 0; } +#endif } // Non-zero if bytecode from PCH is successfully read. @@ -681,6 +683,7 @@ // Disable (partially) loop idiom pass with -fno-builtin*. TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(TheModule->getTargetTriple())); +#ifndef __MINGW32__ if (flag_no_builtin) TLI->disableAllFunctions(); else { @@ -688,6 +691,9 @@ TLI->setUnavailable(LibFunc::memset); if (builtin_function_disabled_p("memcpy")) TLI->setUnavailable(LibFunc::memcpy); +#else + TLI->disableAllFunctions(); +#endif } PerFunctionPasses->add(TLI); @@ -765,6 +771,7 @@ // Disable (partially) loop idiom pass with -fno-builtin*. TargetLibraryInfo *TLI = new TargetLibraryInfo(Triple(TheModule->getTargetTriple())); +#ifndef __MINGW32__ if (flag_no_builtin) TLI->disableAllFunctions(); else { @@ -773,6 +780,9 @@ if (builtin_function_disabled_p("memcpy")) TLI->setUnavailable(LibFunc::memcpy); } +#else + TLI->disableAllFunctions(); +#endif PerModulePasses->add(TLI); bool HasPerModulePasses = false; From isanbard at gmail.com Tue Apr 12 19:36:11 2011 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 13 Apr 2011 00:36:11 -0000 Subject: [llvm-commits] [llvm] r129419 - in /llvm/trunk: include/llvm/IntrinsicsX86.td lib/Target/X86/X86InstrInfo.cpp lib/Target/X86/X86InstrSSE.td lib/Transforms/InstCombine/InstCombineCalls.cpp lib/Transforms/Scalar/LoopStrengthReduce.cpp lib/VMCore/AutoUpgrade.cpp test/Assembler/AutoUpgradeIntrinsics.ll test/CodeGen/X86/avx-intrinsics-x86.ll Message-ID: <20110413003611.F26F22A6C12D@llvm.org> Author: void Date: Tue Apr 12 19:36:11 2011 New Revision: 129419 URL: http://llvm.org/viewvc/llvm-project?rev=129419&view=rev Log: Reapply r129401 with patch for clang. Modified: llvm/trunk/include/llvm/IntrinsicsX86.td llvm/trunk/lib/Target/X86/X86InstrInfo.cpp llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp llvm/trunk/lib/VMCore/AutoUpgrade.cpp llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll Modified: llvm/trunk/include/llvm/IntrinsicsX86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IntrinsicsX86.td?rev=129419&r1=129418&r2=129419&view=diff ============================================================================== --- llvm/trunk/include/llvm/IntrinsicsX86.td (original) +++ llvm/trunk/include/llvm/IntrinsicsX86.td Tue Apr 12 19:36:11 2011 @@ -138,12 +138,6 @@ llvm_x86mmx_ty], [IntrNoMem]>; } -// SIMD load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse_loadu_ps : GCCBuiltin<"__builtin_ia32_loadups">, - Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty], [IntrReadMem]>; -} - // SIMD store ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">, @@ -452,14 +446,6 @@ Intrinsic<[llvm_v2f64_ty], [llvm_x86mmx_ty], [IntrNoMem]>; } -// SIMD load ops -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_sse2_loadu_pd : GCCBuiltin<"__builtin_ia32_loadupd">, - Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadMem]>; - def int_x86_sse2_loadu_dq : GCCBuiltin<"__builtin_ia32_loaddqu">, - Intrinsic<[llvm_v16i8_ty], [llvm_ptr_ty], [IntrReadMem]>; -} - // SIMD store ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">, Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=129419&r1=129418&r2=129419&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Tue Apr 12 19:36:11 2011 @@ -916,7 +916,6 @@ case X86::MOVSDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MMX_MOVD64rm: @@ -2845,11 +2844,9 @@ case X86::FsMOVAPDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: - case X86::MOVDQUrm_Int: break; } switch (Opc2) { @@ -2869,11 +2866,9 @@ case X86::FsMOVAPDrm: case X86::MOVAPSrm: case X86::MOVUPSrm: - case X86::MOVUPSrm_Int: case X86::MOVAPDrm: case X86::MOVDQArm: case X86::MOVDQUrm: - case X86::MOVDQUrm_Int: break; } Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=129419&r1=129418&r2=129419&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Tue Apr 12 19:36:11 2011 @@ -329,15 +329,6 @@ // Intrinsic forms of MOVUPS/D load and store let isAsmParserOnly = 0 in { - let canFoldAsLoad = 1, isReMaterializable = 1 in - def VMOVUPSrm_Int : VPSI<0x10, MRMSrcMem, (outs VR128:$dst), - (ins f128mem:$src), - "movups\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>, VEX; - def VMOVUPDrm_Int : VPDI<0x10, MRMSrcMem, (outs VR128:$dst), - (ins f128mem:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>, VEX; def VMOVUPSmr_Int : VPSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movups\t{$src, $dst|$dst, $src}", @@ -347,13 +338,6 @@ "movupd\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_pd addr:$dst, VR128:$src)]>, VEX; } -let canFoldAsLoad = 1, isReMaterializable = 1 in -def MOVUPSrm_Int : PSI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "movups\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse_loadu_ps addr:$src))]>; -def MOVUPDrm_Int : PDI<0x10, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), - "movupd\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_pd addr:$src))]>; def MOVUPSmr_Int : PSI<0x11, MRMDestMem, (outs), (ins f128mem:$dst, VR128:$src), "movups\t{$src, $dst|$dst, $src}", @@ -2229,22 +2213,12 @@ // Intrinsic forms of MOVDQU load and store let isAsmParserOnly = 0 in { -let canFoldAsLoad = 1 in -def VMOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "vmovdqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, - XS, VEX, Requires<[HasAVX]>; def VMOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "vmovdqu\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, XS, VEX, Requires<[HasAVX]>; } -let canFoldAsLoad = 1 in -def MOVDQUrm_Int : I<0x6F, MRMSrcMem, (outs VR128:$dst), (ins i128mem:$src), - "movdqu\t{$src, $dst|$dst, $src}", - [(set VR128:$dst, (int_x86_sse2_loadu_dq addr:$src))]>, - XS, Requires<[HasSSE2]>; def MOVDQUmr_Int : I<0x7F, MRMDestMem, (outs), (ins i128mem:$dst, VR128:$src), "movdqu\t{$src, $dst|$dst, $src}", [(int_x86_sse2_storeu_dq addr:$dst, VR128:$src)]>, Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp?rev=129419&r1=129418&r2=129419&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp (original) +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp Tue Apr 12 19:36:11 2011 @@ -537,11 +537,7 @@ break; case Intrinsic::ppc_altivec_lvx: case Intrinsic::ppc_altivec_lvxl: - case Intrinsic::x86_sse_loadu_ps: - case Intrinsic::x86_sse2_loadu_pd: - case Intrinsic::x86_sse2_loadu_dq: - // Turn PPC lvx -> load if the pointer is known aligned. - // Turn X86 loadups -> load if the pointer is known aligned. + // Turn PPC lvx -> load if the pointer is known aligned. if (getOrEnforceKnownAlignment(II->getArgOperand(0), 16, TD) >= 16) { Value *Ptr = Builder->CreateBitCast(II->getArgOperand(0), PointerType::getUnqual(II->getType())); Modified: llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp?rev=129419&r1=129418&r2=129419&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp Tue Apr 12 19:36:11 2011 @@ -572,9 +572,6 @@ switch (II->getIntrinsicID()) { default: break; case Intrinsic::prefetch: - case Intrinsic::x86_sse2_loadu_dq: - case Intrinsic::x86_sse2_loadu_pd: - case Intrinsic::x86_sse_loadu_ps: case Intrinsic::x86_sse_storeu_ps: case Intrinsic::x86_sse2_storeu_pd: case Intrinsic::x86_sse2_storeu_dq: Modified: llvm/trunk/lib/VMCore/AutoUpgrade.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AutoUpgrade.cpp?rev=129419&r1=129418&r2=129419&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/AutoUpgrade.cpp (original) +++ llvm/trunk/lib/VMCore/AutoUpgrade.cpp Tue Apr 12 19:36:11 2011 @@ -527,6 +527,12 @@ // or 0. NewFn = 0; return true; + } else if (Name.compare(5, 16, "x86.sse.loadu.ps", 16) == 0 || + Name.compare(5, 17, "x86.sse2.loadu.dq", 17) == 0 || + Name.compare(5, 17, "x86.sse2.loadu.pd", 17) == 0) { + // Calls to these instructions are transformed into unaligned loads. + NewFn = 0; + return true; } else if (Name.compare(5, 17, "x86.ssse3.pshuf.w", 17) == 0) { // This is an SSE/MMX instruction. const Type *X86_MMXTy = VectorType::getX86_MMXTy(FTy->getContext()); @@ -946,7 +952,29 @@ // Remove upgraded instruction. CI->eraseFromParent(); - + + } else if (F->getName() == "llvm.x86.sse.loadu.ps" || + F->getName() == "llvm.x86.sse2.loadu.dq" || + F->getName() == "llvm.x86.sse2.loadu.pd") { + // Convert to a native, unaligned load. + const Type *VecTy = CI->getType(); + const Type *IntTy = IntegerType::get(C, 128); + IRBuilder<> Builder(C); + Builder.SetInsertPoint(CI->getParent(), CI); + + Value *BC = Builder.CreateBitCast(CI->getArgOperand(0), + PointerType::getUnqual(IntTy), + "cast"); + LoadInst *LI = Builder.CreateLoad(BC, CI->getName()); + LI->setAlignment(1); // Unaligned load. + BC = Builder.CreateBitCast(LI, VecTy, "new.cast"); + + // Fix up all the uses with our new load. + if (!CI->use_empty()) + CI->replaceAllUsesWith(BC); + + // Remove intrinsic. + CI->eraseFromParent(); } else { llvm_unreachable("Unknown function for CallInst upgrade."); } Modified: llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll?rev=129419&r1=129418&r2=129419&view=diff ============================================================================== --- llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll (original) +++ llvm/trunk/test/Assembler/AutoUpgradeIntrinsics.ll Tue Apr 12 19:36:11 2011 @@ -7,6 +7,8 @@ ; RUN: llvm-as < %s | llvm-dis | \ ; RUN: not grep {llvm\\.bswap\\.i\[0-9\]*\\.i\[0-9\]*} ; RUN: llvm-as < %s | llvm-dis | \ +; RUN: not grep {llvm\\.x86\\.sse2\\.loadu} +; RUN: llvm-as < %s | llvm-dis | \ ; RUN: grep {llvm\\.x86\\.mmx\\.ps} | grep {x86_mmx} | count 16 declare i32 @llvm.ctpop.i28(i28 %val) @@ -79,3 +81,13 @@ %r2 = call <1 x i64> @llvm.x86.mmx.psrl.q( <1 x i64> %A, <2 x i32> %B ) ; <<1 x i64>> [#uses=0] ret void } + +declare <4 x float> @llvm.x86.sse.loadu.ps(i8*) nounwind readnone +declare <16 x i8> @llvm.x86.sse2.loadu.dq(i8*) nounwind readnone +declare <2 x double> @llvm.x86.sse2.loadu.pd(double*) nounwind readnone +define void @test_loadu(i8* %a, double* %b) { + %v0 = call <4 x float> @llvm.x86.sse.loadu.ps(i8* %a) + %v1 = call <16 x i8> @llvm.x86.sse2.loadu.dq(i8* %a) + %v2 = call <2 x double> @llvm.x86.sse2.loadu.pd(double* %b) + ret void +} Modified: llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll?rev=129419&r1=129418&r2=129419&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll Tue Apr 12 19:36:11 2011 @@ -247,7 +247,7 @@ define <16 x i8> @test_x86_sse2_loadu_dq(i8* %a0) { ; CHECK: movl - ; CHECK: vmovdqu + ; CHECK: vmovups %res = call <16 x i8> @llvm.x86.sse2.loadu.dq(i8* %a0) ; <<16 x i8>> [#uses=1] ret <16 x i8> %res } @@ -256,7 +256,7 @@ define <2 x double> @test_x86_sse2_loadu_pd(i8* %a0) { ; CHECK: movl - ; CHECK: vmovupd + ; CHECK: vmovups %res = call <2 x double> @llvm.x86.sse2.loadu.pd(i8* %a0) ; <<2 x double>> [#uses=1] ret <2 x double> %res } From atrick at apple.com Tue Apr 12 19:38:32 2011 From: atrick at apple.com (Andrew Trick) Date: Wed, 13 Apr 2011 00:38:32 -0000 Subject: [llvm-commits] [llvm] r129421 - in /llvm/trunk: include/llvm/Target/TargetInstrItineraries.h lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp test/CodeGen/ARM/memcpy-inline.ll test/CodeGen/ARM/neon_div.ll test/CodeGen/ARM/va_arg.ll test/CodeGen/ARM/vfp.ll test/CodeGen/Mips/o32_cc_vararg.ll test/CodeGen/Thumb2/thumb2-uxtb.ll Message-ID: <20110413003832.ADA2A2A6C12D@llvm.org> Author: atrick Date: Tue Apr 12 19:38:32 2011 New Revision: 129421 URL: http://llvm.org/viewvc/llvm-project?rev=129421&view=rev Log: Recommit r129383. PreRA scheduler heuristic fixes: VRegCycle, TokenFactor latency. Additional fixes: Do something reasonable for subtargets with generic itineraries by handle node latency the same as for an empty itinerary. Now nodes default to unit latency unless an itinerary explicitly specifies a zero cycle stage or it is a TokenFactor chain. Original fixes: UnitsSharePred was a source of randomness in the scheduler: node priority depended on the queue data structure. I rewrote the recent VRegCycle heuristics to completely replace the old heuristic without any randomness. To make the ndoe latency adjustments work, I also needed to do something a little more reasonable with TokenFactor. I gave it zero latency to its consumers and always schedule it as low as possible. Modified: llvm/trunk/include/llvm/Target/TargetInstrItineraries.h llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll llvm/trunk/test/CodeGen/ARM/neon_div.ll llvm/trunk/test/CodeGen/ARM/va_arg.ll llvm/trunk/test/CodeGen/ARM/vfp.ll llvm/trunk/test/CodeGen/Mips/o32_cc_vararg.ll llvm/trunk/test/CodeGen/Thumb2/thumb2-uxtb.ll Modified: llvm/trunk/include/llvm/Target/TargetInstrItineraries.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrItineraries.h?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetInstrItineraries.h (original) +++ llvm/trunk/include/llvm/Target/TargetInstrItineraries.h Tue Apr 12 19:38:32 2011 @@ -155,9 +155,13 @@ /// in the itinerary. /// unsigned getStageLatency(unsigned ItinClassIndx) const { - // If the target doesn't provide itinerary information, use a - // simple non-zero default value for all instructions. - if (isEmpty()) + // If the target doesn't provide itinerary information, use a simple + // non-zero default value for all instructions. Some target's provide a + // dummy (Generic) itinerary which should be handled as if it's itinerary is + // empty. We identify this by looking for a reference to stage zero (invalid + // stage). This is different from beginStage == endState != 0, which could + // be used for zero-latency pseudo ops. + if (isEmpty() || Itineraries[ItinClassIndx].FirstStage == 0) return 1; // Calculate the maximum completion time for any stage. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Tue Apr 12 19:38:32 2011 @@ -102,11 +102,11 @@ #ifndef NDEBUG namespace { // For sched=list-ilp, Count the number of times each factor comes into play. - enum { FactPressureDiff, FactRegUses, FactHeight, FactDepth, FactStatic, - FactOther, NumFactors }; + enum { FactPressureDiff, FactRegUses, FactStall, FactHeight, FactDepth, + FactStatic, FactOther, NumFactors }; } static const char *FactorName[NumFactors] = -{"PressureDiff", "RegUses", "Height", "Depth","Static", "Other"}; +{"PressureDiff", "RegUses", "Stall", "Height", "Depth","Static", "Other"}; static int FactorCount[NumFactors]; #endif //!NDEBUG @@ -463,6 +463,13 @@ if (DisableSchedCycles) return; + // FIXME: Nodes such as CopyFromReg probably should not advance the current + // cycle. Otherwise, we can wrongly mask real stalls. If the non-machine node + // has predecessors the cycle will be advanced when they are scheduled. + // But given the crude nature of modeling latency though such nodes, we + // currently need to treat these nodes like real instructions. + // if (!SU->getNode() || !SU->getNode()->isMachineOpcode()) return; + unsigned ReadyCycle = isBottomUp ? SU->getHeight() : SU->getDepth(); // Bump CurCycle to account for latency. We assume the latency of other @@ -533,6 +540,8 @@ } } +static void resetVRegCycle(SUnit *SU); + /// ScheduleNodeBottomUp - Add the node to the schedule. Decrement the pending /// count of its predecessors. If a predecessor pending count is zero, add it to /// the Available queue. @@ -542,7 +551,8 @@ #ifndef NDEBUG if (CurCycle < SU->getHeight()) - DEBUG(dbgs() << " Height [" << SU->getHeight() << "] pipeline stall!\n"); + DEBUG(dbgs() << " Height [" << SU->getHeight() + << "] pipeline stall!\n"); #endif // FIXME: Do not modify node height. It may interfere with @@ -559,7 +569,7 @@ AvailableQueue->ScheduledNode(SU); // If HazardRec is disabled, and each inst counts as one cycle, then - // advance CurCycle before ReleasePredecessors to avoid useles pushed to + // advance CurCycle before ReleasePredecessors to avoid useless pushes to // PendingQueue for schedulers that implement HasReadyFilter. if (!HazardRec->isEnabled() && AvgIPC < 2) AdvanceToCycle(CurCycle + 1); @@ -580,20 +590,25 @@ } } + resetVRegCycle(SU); + SU->isScheduled = true; // Conditions under which the scheduler should eagerly advance the cycle: // (1) No available instructions // (2) All pipelines full, so available instructions must have hazards. // - // If HazardRec is disabled, the cycle was advanced earlier. + // If HazardRec is disabled, the cycle was pre-advanced before calling + // ReleasePredecessors. In that case, IssueCount should remain 0. // // Check AvailableQueue after ReleasePredecessors in case of zero latency. - ++IssueCount; - if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) - || (!HazardRec->isEnabled() && AvgIPC > 1 && IssueCount == AvgIPC) - || AvailableQueue->empty()) - AdvanceToCycle(CurCycle + 1); + if (HazardRec->isEnabled() || AvgIPC > 1) { + if (SU->getNode() && SU->getNode()->isMachineOpcode()) + ++IssueCount; + if ((HazardRec->isEnabled() && HazardRec->atIssueLimit()) + || (!HazardRec->isEnabled() && IssueCount == AvgIPC)) + AdvanceToCycle(CurCycle + 1); + } } /// CapturePred - This does the opposite of ReleasePred. Since SU is being @@ -1220,7 +1235,7 @@ // priority. If it is not ready put it back. Schedule the node. Sequence.reserve(SUnits.size()); while (!AvailableQueue->empty()) { - DEBUG(dbgs() << "\n*** Examining Available\n"; + DEBUG(dbgs() << "\nExamining Available:\n"; AvailableQueue->dump(this)); // Pick the best node to schedule taking all constraints into @@ -1661,17 +1676,6 @@ CalcNodeSethiUllmanNumber(&(*SUnits)[i], SethiUllmanNumbers); } -void RegReductionPQBase::initNodes(std::vector &sunits) { - SUnits = &sunits; - // Add pseudo dependency edges for two-address nodes. - AddPseudoTwoAddrDeps(); - // Reroute edges to nodes with multiple uses. - if (!TracksRegPressure) - PrescheduleNodesWithMultipleUses(); - // Calculate node priorities. - CalculateSethiUllmanNumbers(); -} - void RegReductionPQBase::addNode(const SUnit *SU) { unsigned SUSize = SethiUllmanNumbers.size(); if (SUnits->size() > SUSize) @@ -2008,7 +2012,29 @@ return Scratches; } -/// hasOnlyLiveOutUse - Return true if SU has a single value successor that is a +/// hasOnlyLiveInOpers - Return true if SU has only value predecessors that are +/// CopyFromReg from a virtual register. +static bool hasOnlyLiveInOpers(const SUnit *SU) { + bool RetVal = false; + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); + I != E; ++I) { + if (I->isCtrl()) continue; + const SUnit *PredSU = I->getSUnit(); + if (PredSU->getNode() && + PredSU->getNode()->getOpcode() == ISD::CopyFromReg) { + unsigned Reg = + cast(PredSU->getNode()->getOperand(1))->getReg(); + if (TargetRegisterInfo::isVirtualRegister(Reg)) { + RetVal = true; + continue; + } + } + return false; + } + return RetVal; +} + +/// hasOnlyLiveOutUses - Return true if SU has only value successors that are /// CopyToReg to a virtual register. This SU def is probably a liveout and /// it has no other use. It should be scheduled closer to the terminator. static bool hasOnlyLiveOutUses(const SUnit *SU) { @@ -2030,62 +2056,71 @@ return RetVal; } -/// UnitsSharePred - Return true if the two scheduling units share a common -/// data predecessor. -static bool UnitsSharePred(const SUnit *left, const SUnit *right) { - SmallSet Preds; - for (SUnit::const_pred_iterator I = left->Preds.begin(),E = left->Preds.end(); +// Set isVRegCycle for a node with only live in opers and live out uses. Also +// set isVRegCycle for its CopyFromReg operands. +// +// This is only relevant for single-block loops, in which case the VRegCycle +// node is likely an induction variable in which the operand and target virtual +// registers should be coalesced (e.g. pre/post increment values). Setting the +// isVRegCycle flag helps the scheduler prioritize other uses of the same +// CopyFromReg so that this node becomes the virtual register "kill". This +// avoids interference between the values live in and out of the block and +// eliminates a copy inside the loop. +static void initVRegCycle(SUnit *SU) { + if (DisableSchedVRegCycle) + return; + + if (!hasOnlyLiveInOpers(SU) || !hasOnlyLiveOutUses(SU)) + return; + + DEBUG(dbgs() << "VRegCycle: SU(" << SU->NodeNum << ")\n"); + + SU->isVRegCycle = true; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end(); I != E; ++I) { - if (I->isCtrl()) continue; // ignore chain preds - Preds.insert(I->getSUnit()); + if (I->isCtrl()) continue; + I->getSUnit()->isVRegCycle = true; } - for (SUnit::const_pred_iterator I = right->Preds.begin(),E = right->Preds.end(); +} + +// After scheduling the definition of a VRegCycle, clear the isVRegCycle flag of +// CopyFromReg operands. We should no longer penalize other uses of this VReg. +static void resetVRegCycle(SUnit *SU) { + if (!SU->isVRegCycle) + return; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); I != E; ++I) { if (I->isCtrl()) continue; // ignore chain preds - if (Preds.count(I->getSUnit())) - return true; + SUnit *PredSU = I->getSUnit(); + if (PredSU->isVRegCycle) { + assert(PredSU->getNode()->getOpcode() == ISD::CopyFromReg && + "VRegCycle def must be CopyFromReg"); + I->getSUnit()->isVRegCycle = 0; + } } - return false; } -// Return true if the virtual register defined by VRCycleSU may interfere with -// VRUseSU. -// -// Note: We may consider two SU's that use the same value live into a loop as -// interferng even though the value is not an induction variable. This is an -// unfortunate consequence of scheduling on the selection DAG. -static bool checkVRegCycleInterference(const SUnit *VRCycleSU, - const SUnit *VRUseSU) { - for (SUnit::const_pred_iterator I = VRCycleSU->Preds.begin(), - E = VRCycleSU->Preds.end(); I != E; ++I) { +// Return true if this SUnit uses a CopyFromReg node marked as a VRegCycle. This +// means a node that defines the VRegCycle has not been scheduled yet. +static bool hasVRegCycleUse(const SUnit *SU) { + // If this SU also defines the VReg, don't hoist it as a "use". + if (SU->isVRegCycle) + return false; + + for (SUnit::const_pred_iterator I = SU->Preds.begin(),E = SU->Preds.end(); + I != E; ++I) { if (I->isCtrl()) continue; // ignore chain preds - SDNode *InNode = I->getSUnit()->getNode(); - if (!InNode || InNode->getOpcode() != ISD::CopyFromReg) - continue; - for (SUnit::const_pred_iterator II = VRUseSU->Preds.begin(), - EE = VRUseSU->Preds.end(); II != EE; ++II) { - if (II->getSUnit() == I->getSUnit()) - return true; + if (I->getSUnit()->isVRegCycle && + I->getSUnit()->getNode()->getOpcode() == ISD::CopyFromReg) { + DEBUG(dbgs() << " VReg cycle use: SU (" << SU->NodeNum << ")\n"); + return true; } } return false; } -// Compare the VRegCycle properties of the nodes. -// Return -1 if left has higher priority, 1 if right has higher priority. -// Return 0 if priority is equivalent. -static int BUCompareVRegCycle(const SUnit *left, const SUnit *right) { - if (left->isVRegCycle && !right->isVRegCycle) { - if (checkVRegCycleInterference(left, right)) - return -1; - } - else if (!left->isVRegCycle && right->isVRegCycle) { - if (checkVRegCycleInterference(right, left)) - return 1; - } - return 0; -} - // Check for either a dependence (latency) or resource (hazard) stall. // // Note: The ScheduleHazardRecognizer interface requires a non-const SU. @@ -2101,23 +2136,12 @@ // Return 0 if latency-based priority is equivalent. static int BUCompareLatency(SUnit *left, SUnit *right, bool checkPref, RegReductionPQBase *SPQ) { - // If the two nodes share an operand and one of them has a single - // use that is a live out copy, favor the one that is live out. Otherwise - // it will be difficult to eliminate the copy if the instruction is a - // loop induction variable update. e.g. - // BB: - // sub r1, r3, #1 - // str r0, [r2, r3] - // mov r3, r1 - // cmp - // bne BB - bool SharePred = UnitsSharePred(left, right); - // FIXME: Only adjust if BB is a loop back edge. - // FIXME: What's the cost of a copy? - int LBonus = (SharePred && hasOnlyLiveOutUses(left)) ? 1 : 0; - int RBonus = (SharePred && hasOnlyLiveOutUses(right)) ? 1 : 0; - int LHeight = (int)left->getHeight() - LBonus; - int RHeight = (int)right->getHeight() - RBonus; + // Scheduling an instruction that uses a VReg whose postincrement has not yet + // been scheduled will induce a copy. Model this as an extra cycle of latency. + int LPenalty = hasVRegCycleUse(left) ? 1 : 0; + int RPenalty = hasVRegCycleUse(right) ? 1 : 0; + int LHeight = (int)left->getHeight() + LPenalty; + int RHeight = (int)right->getHeight() + RPenalty; bool LStall = (!checkPref || left->SchedulingPref == Sched::Latency) && BUHasStall(left, LHeight, SPQ); @@ -2128,36 +2152,47 @@ // If scheduling either one of the node will cause a pipeline stall, sort // them according to their height. if (LStall) { - if (!RStall) + if (!RStall) { + DEBUG(++FactorCount[FactStall]); return 1; - if (LHeight != RHeight) + } + if (LHeight != RHeight) { + DEBUG(++FactorCount[FactStall]); return LHeight > RHeight ? 1 : -1; - } else if (RStall) + } + } else if (RStall) { + DEBUG(++FactorCount[FactStall]); return -1; + } // If either node is scheduling for latency, sort them by height/depth // and latency. if (!checkPref || (left->SchedulingPref == Sched::Latency || right->SchedulingPref == Sched::Latency)) { if (DisableSchedCycles) { - if (LHeight != RHeight) + if (LHeight != RHeight) { + DEBUG(++FactorCount[FactHeight]); return LHeight > RHeight ? 1 : -1; + } } else { // If neither instruction stalls (!LStall && !RStall) then // its height is already covered so only its depth matters. We also reach // this if both stall but have the same height. - unsigned LDepth = left->getDepth(); - unsigned RDepth = right->getDepth(); + int LDepth = left->getDepth() - LPenalty; + int RDepth = right->getDepth() - RPenalty; if (LDepth != RDepth) { + DEBUG(++FactorCount[FactDepth]); DEBUG(dbgs() << " Comparing latency of SU (" << left->NodeNum << ") depth " << LDepth << " vs SU (" << right->NodeNum << ") depth " << RDepth << "\n"); return LDepth < RDepth ? 1 : -1; } } - if (left->Latency != right->Latency) + if (left->Latency != right->Latency) { + DEBUG(++FactorCount[FactOther]); return left->Latency > right->Latency ? 1 : -1; + } } return 0; } @@ -2169,7 +2204,19 @@ DEBUG(++FactorCount[FactStatic]); return LPriority > RPriority; } - DEBUG(++FactorCount[FactOther]); + else if(LPriority == 0) { + // Schedule zero-latency TokenFactor below any other special + // nodes. The alternative may be to avoid artificially boosting the + // TokenFactor's height when it is scheduled, but we currently rely on an + // instruction's final height to equal the cycle in which it is scheduled, + // so heights are monotonically increasing. + unsigned LOpc = left->getNode() ? left->getNode()->getOpcode() : 0; + unsigned ROpc = right->getNode() ? right->getNode()->getOpcode() : 0; + if (LOpc == ISD::TokenFactor) + return false; + if (ROpc == ISD::TokenFactor) + return true; + } // Try schedule def + use closer when Sethi-Ullman numbers are the same. // e.g. @@ -2190,14 +2237,18 @@ // This creates more short live intervals. unsigned LDist = closestSucc(left); unsigned RDist = closestSucc(right); - if (LDist != RDist) + if (LDist != RDist) { + DEBUG(++FactorCount[FactOther]); return LDist < RDist; + } // How many registers becomes live when the node is scheduled. unsigned LScratch = calcMaxScratches(left); unsigned RScratch = calcMaxScratches(right); - if (LScratch != RScratch) + if (LScratch != RScratch) { + DEBUG(++FactorCount[FactOther]); return LScratch > RScratch; + } if (!DisableSchedCycles) { int result = BUCompareLatency(left, right, false /*checkPref*/, SPQ); @@ -2205,15 +2256,20 @@ return result > 0; } else { - if (left->getHeight() != right->getHeight()) + if (left->getHeight() != right->getHeight()) { + DEBUG(++FactorCount[FactHeight]); return left->getHeight() > right->getHeight(); + } - if (left->getDepth() != right->getDepth()) + if (left->getDepth() != right->getDepth()) { + DEBUG(++FactorCount[FactDepth]); return left->getDepth() < right->getDepth(); + } } assert(left->NodeQueueId && right->NodeQueueId && "NodeQueueId cannot be zero"); + DEBUG(++FactorCount[FactOther]); return (left->NodeQueueId > right->NodeQueueId); } @@ -2264,24 +2320,22 @@ // Avoid causing spills. If register pressure is high, schedule for // register pressure reduction. if (LHigh && !RHigh) { + DEBUG(++FactorCount[FactPressureDiff]); DEBUG(dbgs() << " pressure SU(" << left->NodeNum << ") > SU(" << right->NodeNum << ")\n"); return true; } else if (!LHigh && RHigh) { + DEBUG(++FactorCount[FactPressureDiff]); DEBUG(dbgs() << " pressure SU(" << right->NodeNum << ") > SU(" << left->NodeNum << ")\n"); return false; } - int result = 0; - if (!DisableSchedVRegCycle) { - result = BUCompareVRegCycle(left, right); - } - if (result == 0 && !LHigh && !RHigh) { - result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); + if (!LHigh && !RHigh) { + int result = BUCompareLatency(left, right, true /*checkPref*/, SPQ); + if (result != 0) + return result > 0; } - if (result != 0) - return result > 0; return BURRSort(left, right, SPQ); } @@ -2347,12 +2401,6 @@ if (RReduce && !LReduce) return true; } - if (!DisableSchedVRegCycle) { - int result = BUCompareVRegCycle(left, right); - if (result != 0) - return result > 0; - } - if (!DisableSchedLiveUses && (LLiveUses != RLiveUses)) { DEBUG(dbgs() << "Live uses SU(" << left->NodeNum << "): " << LLiveUses << " != SU(" << right->NodeNum << "): " << RLiveUses << "\n"); @@ -2391,6 +2439,24 @@ return BURRSort(left, right, SPQ); } +void RegReductionPQBase::initNodes(std::vector &sunits) { + SUnits = &sunits; + // Add pseudo dependency edges for two-address nodes. + AddPseudoTwoAddrDeps(); + // Reroute edges to nodes with multiple uses. + if (!TracksRegPressure) + PrescheduleNodesWithMultipleUses(); + // Calculate node priorities. + CalculateSethiUllmanNumbers(); + + // For single block loops, mark nodes that look like canonical IV increments. + if (scheduleDAG->BB->isSuccessor(scheduleDAG->BB)) { + for (unsigned i = 0, e = sunits.size(); i != e; ++i) { + initVRegCycle(&sunits[i]); + } + } +} + //===----------------------------------------------------------------------===// // Preschedule for Register Pressure //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Tue Apr 12 19:38:32 2011 @@ -342,10 +342,6 @@ assert(N->getNodeId() == -1 && "Node already inserted!"); N->setNodeId(NodeSUnit->NodeNum); - // Set isVRegCycle if the node operands are live into and value is live out - // of a single block loop. - InitVRegCycleFlag(NodeSUnit); - // Compute NumRegDefsLeft. This must be done before AddSchedEdges. InitNumRegDefsLeft(NodeSUnit); @@ -417,6 +413,10 @@ // If this is a ctrl dep, latency is 1. unsigned OpLatency = isChain ? 1 : OpSU->Latency; + // Special-case TokenFactor chains as zero-latency. + if(isChain && OpN->getOpcode() == ISD::TokenFactor) + OpLatency = 0; + const SDep &dep = SDep(OpSU, isChain ? SDep::Order : SDep::Data, OpLatency, PhysReg); if (!isChain && !UnitLatencies) { @@ -512,47 +512,6 @@ } } -// Set isVRegCycle if this node's single use is CopyToReg and its only active -// data operands are CopyFromReg. -// -// This is only relevant for single-block loops, in which case the VRegCycle -// node is likely an induction variable in which the operand and target virtual -// registers should be coalesced (e.g. pre/post increment values). Setting the -// isVRegCycle flag helps the scheduler prioritize other uses of the same -// CopyFromReg so that this node becomes the virtual register "kill". This -// avoids interference between the values live in and out of the block and -// eliminates a copy inside the loop. -void ScheduleDAGSDNodes::InitVRegCycleFlag(SUnit *SU) { - if (!BB->isSuccessor(BB)) - return; - - SDNode *N = SU->getNode(); - if (N->getGluedNode()) - return; - - if (!N->hasOneUse() || N->use_begin()->getOpcode() != ISD::CopyToReg) - return; - - bool FoundLiveIn = false; - for (SDNode::op_iterator OI = N->op_begin(), E = N->op_end(); OI != E; ++OI) { - EVT OpVT = OI->getValueType(); - assert(OpVT != MVT::Glue && "Glued nodes should be in same sunit!"); - - if (OpVT == MVT::Other) - continue; // ignore chain operands - - if (isPassiveNode(OI->getNode())) - continue; // ignore constants and such - - if (OI->getNode()->getOpcode() != ISD::CopyFromReg) - return; - - FoundLiveIn = true; - } - if (FoundLiveIn) - SU->isVRegCycle = true; -} - void ScheduleDAGSDNodes::InitNumRegDefsLeft(SUnit *SU) { assert(SU->NumRegDefsLeft == 0 && "expect a new node"); for (RegDefIter I(SU, this); I.IsValid(); I.Advance()) { @@ -562,6 +521,16 @@ } void ScheduleDAGSDNodes::ComputeLatency(SUnit *SU) { + SDNode *N = SU->getNode(); + + // TokenFactor operands are considered zero latency, and some schedulers + // (e.g. Top-Down list) may rely on the fact that operand latency is nonzero + // whenever node latency is nonzero. + if (N && N->getOpcode() == ISD::TokenFactor) { + SU->Latency = 0; + return; + } + // Check to see if the scheduler cares about latencies. if (ForceUnitLatencies()) { SU->Latency = 1; @@ -569,7 +538,6 @@ } if (!InstrItins || InstrItins->isEmpty()) { - SDNode *N = SU->getNode(); if (N && N->isMachineOpcode() && TII->isHighLatencyDef(N->getMachineOpcode())) SU->Latency = HighLatencyCycles; Modified: llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll (original) +++ llvm/trunk/test/CodeGen/ARM/memcpy-inline.ll Tue Apr 12 19:38:32 2011 @@ -1,10 +1,8 @@ -; RUN: llc < %s -mtriple=arm-apple-darwin -regalloc=linearscan -disable-post-ra | FileCheck %s -; RUN: llc < %s -mtriple=arm-apple-darwin -regalloc=basic -disable-post-ra | FileCheck %s +; RUN: llc < %s -mtriple=thumbv7-apple-darwin -regalloc=linearscan -disable-post-ra | FileCheck %s ; The ARM magic hinting works best with linear scan. -; CHECK: ldmia -; CHECK: stmia -; CHECK: ldrh +; CHECK: ldrd +; CHECK: strd ; CHECK: ldrb %struct.x = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 } Modified: llvm/trunk/test/CodeGen/ARM/neon_div.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/neon_div.ll?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/neon_div.ll (original) +++ llvm/trunk/test/CodeGen/ARM/neon_div.ll Tue Apr 12 19:38:32 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=arm -mattr=+neon | FileCheck %s +; RUN: llc < %s -march=arm -mattr=+neon -pre-RA-sched=source | FileCheck %s define <8 x i8> @sdivi8(<8 x i8>* %A, <8 x i8>* %B) nounwind { ;CHECK: vrecpe.f32 Modified: llvm/trunk/test/CodeGen/ARM/va_arg.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/va_arg.ll?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/va_arg.ll (original) +++ llvm/trunk/test/CodeGen/ARM/va_arg.ll Tue Apr 12 19:38:32 2011 @@ -1,10 +1,10 @@ -; RUN: llc < %s -mtriple=armv7-none-linux-gnueabi | FileCheck %s +; RUN: llc < %s -mtriple=armv7-none-linux-gnueabi -pre-RA-sched=source | FileCheck %s ; Test that we correctly align elements when using va_arg ; CHECK: test1: ; CHECK-NOT: bfc -; CHECK: add r0, r0, #7 -; CHECK: bfc r0, #0, #3 +; CHECK: add [[REG:(r[0-9]+)|(lr)]], {{(r[0-9]+)|(lr)}}, #7 +; CHECK: bfc [[REG]], #0, #3 ; CHECK-NOT: bfc define i64 @test1(i32 %i, ...) nounwind optsize { @@ -19,8 +19,8 @@ ; CHECK: test2: ; CHECK-NOT: bfc -; CHECK: add r0, r0, #7 -; CHECK: bfc r0, #0, #3 +; CHECK: add [[REG:(r[0-9]+)|(lr)]], {{(r[0-9]+)|(lr)}}, #7 +; CHECK: bfc [[REG]], #0, #3 ; CHECK-NOT: bfc ; CHECK: bx lr Modified: llvm/trunk/test/CodeGen/ARM/vfp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vfp.ll?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/vfp.ll (original) +++ llvm/trunk/test/CodeGen/ARM/vfp.ll Tue Apr 12 19:38:32 2011 @@ -40,8 +40,8 @@ define void @test_ext_round(float* %P, double* %D) { ;CHECK: test_ext_round: %a = load float* %P ; [#uses=1] -;CHECK: vcvt.f32.f64 ;CHECK: vcvt.f64.f32 +;CHECK: vcvt.f32.f64 %b = fpext float %a to double ; [#uses=1] %A = load double* %D ; [#uses=1] %B = fptrunc double %A to float ; [#uses=1] Modified: llvm/trunk/test/CodeGen/Mips/o32_cc_vararg.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/o32_cc_vararg.ll?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/Mips/o32_cc_vararg.ll (original) +++ llvm/trunk/test/CodeGen/Mips/o32_cc_vararg.ll Tue Apr 12 19:38:32 2011 @@ -1,12 +1,12 @@ -; RUN: llc -march=mipsel -mcpu=mips2 < %s | FileCheck %s -; RUN: llc -march=mipsel -mcpu=mips2 < %s -regalloc=basic | FileCheck %s +; RUN: llc -march=mipsel -mcpu=mips2 -pre-RA-sched=source < %s | FileCheck %s +; RUN: llc -march=mipsel -mcpu=mips2 -pre-RA-sched=source < %s -regalloc=basic | FileCheck %s ; All test functions do the same thing - they return the first variable ; argument. -; All CHECK's do the same thing - they check whether variable arguments from -; registers are placed on correct stack locations, and whether the first +; All CHECK's do the same thing - they check whether variable arguments from +; registers are placed on correct stack locations, and whether the first ; variable argument is returned from the correct stack location. @@ -31,14 +31,14 @@ ; CHECK: va1: ; CHECK: addiu $sp, $sp, -32 -; CHECK: sw $5, 36($sp) -; CHECK: sw $6, 40($sp) ; CHECK: sw $7, 44($sp) +; CHECK: sw $6, 40($sp) +; CHECK: sw $5, 36($sp) ; CHECK: lw $2, 36($sp) } -; check whether the variable double argument will be accessed from the 8-byte -; aligned location (i.e. whether the address is computed by adding 7 and +; check whether the variable double argument will be accessed from the 8-byte +; aligned location (i.e. whether the address is computed by adding 7 and ; clearing lower 3 bits) define double @va2(i32 %a, ...) nounwind { entry: @@ -57,10 +57,10 @@ ; CHECK: va2: ; CHECK: addiu $sp, $sp, -40 -; CHECK: addiu $[[R0:[0-9]+]], $sp, 44 -; CHECK: sw $5, 44($sp) -; CHECK: sw $6, 48($sp) ; CHECK: sw $7, 52($sp) +; CHECK: sw $6, 48($sp) +; CHECK: sw $5, 44($sp) +; CHECK: addiu $[[R0:[0-9]+]], $sp, 44 ; CHECK: addiu $[[R1:[0-9]+]], $[[R0]], 7 ; CHECK: addiu $[[R2:[0-9]+]], $zero, -8 ; CHECK: and $[[R3:[0-9]+]], $[[R1]], $[[R2]] @@ -85,8 +85,8 @@ ; CHECK: va3: ; CHECK: addiu $sp, $sp, -40 -; CHECK: sw $6, 48($sp) ; CHECK: sw $7, 52($sp) +; CHECK: sw $6, 48($sp) ; CHECK: lw $2, 48($sp) } @@ -108,8 +108,8 @@ ; CHECK: va4: ; CHECK: addiu $sp, $sp, -48 -; CHECK: sw $6, 56($sp) ; CHECK: sw $7, 60($sp) +; CHECK: sw $6, 56($sp) ; CHECK: addiu $[[R0:[0-9]+]], $sp, 56 ; CHECK: addiu $[[R1:[0-9]+]], $[[R0]], 7 ; CHECK: addiu $[[R2:[0-9]+]], $zero, -8 Modified: llvm/trunk/test/CodeGen/Thumb2/thumb2-uxtb.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/thumb2-uxtb.ll?rev=129421&r1=129420&r2=129421&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/Thumb2/thumb2-uxtb.ll (original) +++ llvm/trunk/test/CodeGen/Thumb2/thumb2-uxtb.ll Tue Apr 12 19:38:32 2011 @@ -128,9 +128,9 @@ ; ARMv7M: test10 ; ARMv7M: mov.w r1, #16253176 +; ARMv7M: mov.w r2, #458759 ; ARMv7M: and.w r0, r1, r0, lsr #7 -; ARMv7M: mov.w r1, #458759 -; ARMv7M: and.w r1, r1, r0, lsr #5 +; ARMv7M: and.w r1, r2, r0, lsr #5 ; ARMv7M: orrs r0, r1 %tmp1 = lshr i32 %p0, 7 ; [#uses=1] %tmp2 = and i32 %tmp1, 16253176 ; [#uses=2] From nicholas at mxc.ca Tue Apr 12 20:05:45 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Wed, 13 Apr 2011 01:05:45 -0000 Subject: [llvm-commits] [llvm] r129423 - /llvm/trunk/runtime/libprofile/LineProfiling.c Message-ID: <20110413010545.C2AF92A6C12D@llvm.org> Author: nicholas Date: Tue Apr 12 20:05:45 2011 New Revision: 129423 URL: http://llvm.org/viewvc/llvm-project?rev=129423&view=rev Log: Use %ull here. Modified: llvm/trunk/runtime/libprofile/LineProfiling.c Modified: llvm/trunk/runtime/libprofile/LineProfiling.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129423&r1=129422&r2=129423&view=diff ============================================================================== --- llvm/trunk/runtime/libprofile/LineProfiling.c (original) +++ llvm/trunk/runtime/libprofile/LineProfiling.c Tue Apr 12 20:05:45 2011 @@ -31,7 +31,8 @@ void llvm_prof_linectr_emit_counter(const char *dir, const char *file, uint32_t line, uint32_t column, uint64_t *counter) { - printf("%s/%s:%u:%u %" PRIu64 "\n", dir, file, line, column, *counter); + printf("%s/%s:%u:%u %ull\n", dir, file, line, column, + (unsigned long long)(*counter)); } void llvm_prof_linectr_end_file() { From nlewycky at google.com Tue Apr 12 20:19:29 2011 From: nlewycky at google.com (Nick Lewycky) Date: Tue, 12 Apr 2011 18:19:29 -0700 Subject: [llvm-commits] [llvm] r129384 - /llvm/trunk/runtime/libprofile/LineProfiling.c In-Reply-To: <3ADC664C-E0C1-4E04-859C-C70460A228A5@apple.com> References: <20110412200650.9C0682A6C12D@llvm.org> <3ADC664C-E0C1-4E04-859C-C70460A228A5@apple.com> Message-ID: On 12 April 2011 17:36, Chris Lattner wrote: > > On Apr 12, 2011, at 1:06 PM, Nick Lewycky wrote: > > Author: nicholas > Date: Tue Apr 12 15:06:50 2011 > New Revision: 129384 > > URL: http://llvm.org/viewvc/llvm-project?rev=129384&view=rev > Log: > Print our uint64_t with the more portable (C99 and C++0x) %PRIu64 format > specifier. > > > Uh, I'm pretty sure that isn't more portable. Why not just cast it to > (unsigned long long) and print with %ull? > Sure why not. This is all just placeholder code anyways. Done! > > -Chris > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110412/2b76d033/attachment.html From cdavis at mymail.mines.edu Tue Apr 12 20:55:46 2011 From: cdavis at mymail.mines.edu (Charles Davis) Date: Tue, 12 Apr 2011 19:55:46 -0600 Subject: [llvm-commits] [llvm] r129423 - /llvm/trunk/runtime/libprofile/LineProfiling.c In-Reply-To: <20110413010545.C2AF92A6C12D@llvm.org> References: <20110413010545.C2AF92A6C12D@llvm.org> Message-ID: <4DA502A2.5040101@mymail.mines.edu> On 4/12/11 7:05 PM, Nick Lewycky wrote: > Author: nicholas > Date: Tue Apr 12 20:05:45 2011 > New Revision: 129423 > > URL: http://llvm.org/viewvc/llvm-project?rev=129423&view=rev > Log: > Use %ull here. Uh, I think you want %llu. Chip From clattner at apple.com Tue Apr 12 22:59:14 2011 From: clattner at apple.com (Chris Lattner) Date: Tue, 12 Apr 2011 20:59:14 -0700 Subject: [llvm-commits] [PATCH] lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp: [PR9581] Fix FP precision issue on mingw. It also reverts r129199. In-Reply-To: References: Message-ID: On Apr 12, 2011, at 4:25 PM, NAKAMURA Takumi wrote: > FIXME: It is for i686-mingw32 for now, though, potentially the issue > might be on x87-based hosts with PC64. > > FIXME: [PR6907] Use llvm/Support/FEnv.h. On clang++, is > unavailable due to handling of #include_next. Hi Takumi, I could stomache putting volatile on a couple of computations, but I just can't handle the inline asm. Is there a better way? -Chris From zwarich at apple.com Wed Apr 13 01:03:16 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Wed, 13 Apr 2011 06:03:16 -0000 Subject: [llvm-commits] [llvm] r129428 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll Message-ID: <20110413060316.4882B2A6C12D@llvm.org> Author: zwarich Date: Wed Apr 13 01:03:16 2011 New Revision: 129428 URL: http://llvm.org/viewvc/llvm-project?rev=129428&view=rev Log: If a global variable has a specified alignment that is less than the preferred alignment for its type, use the minimum of the specified alignment and the ABI alignment. This fixes . Added: llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll Modified: llvm/trunk/lib/Target/TargetData.cpp Modified: llvm/trunk/lib/Target/TargetData.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetData.cpp?rev=129428&r1=129427&r2=129428&view=diff ============================================================================== --- llvm/trunk/lib/Target/TargetData.cpp (original) +++ llvm/trunk/lib/Target/TargetData.cpp Wed Apr 13 01:03:16 2011 @@ -617,8 +617,12 @@ unsigned TargetData::getPreferredAlignment(const GlobalVariable *GV) const { const Type *ElemType = GV->getType()->getElementType(); unsigned Alignment = getPrefTypeAlignment(ElemType); - if (GV->getAlignment() > Alignment) - Alignment = GV->getAlignment(); + unsigned GVAlignment = GV->getAlignment(); + if (GVAlignment >= Alignment) { + Alignment = GVAlignment; + } else if (GVAlignment != 0) { + Alignment = std::min(GVAlignment, getABITypeAlignment(ElemType)); + } if (GV->hasInitializer()) { if (Alignment < 16) { Added: llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll?rev=129428&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll (added) +++ llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll Wed Apr 13 01:03:16 2011 @@ -0,0 +1,9 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32" +target triple = "thumbv7-apple-darwin10.0.0" + +; CHECK: align 2 + at .strA = linker_private unnamed_addr constant [4 x i8] c"bar\00" +; CHECK-NOT: align + at .strB = linker_private unnamed_addr constant [4 x i8] c"foo\00", align 1 + at .strC = linker_private unnamed_addr constant [4 x i8] c"baz\00", section "__TEXT,__cstring,cstring_literals", align 1 From zwarich at apple.com Wed Apr 13 01:39:16 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Wed, 13 Apr 2011 06:39:16 -0000 Subject: [llvm-commits] [llvm] r129429 - in /llvm/trunk/lib/Target/ARM: ARMBaseInstrInfo.cpp ARMBaseInstrInfo.h Message-ID: <20110413063916.483F62A6C12D@llvm.org> Author: zwarich Date: Wed Apr 13 01:39:16 2011 New Revision: 129429 URL: http://llvm.org/viewvc/llvm-project?rev=129429&view=rev Log: Fix a typo. Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=129429&r1=129428&r2=129429&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Wed Apr 13 01:39:16 2011 @@ -1270,19 +1270,19 @@ } bool ARMBaseInstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, - unsigned NumCyles, + unsigned NumCycles, unsigned ExtraPredCycles, float Probability, float Confidence) const { - if (!NumCyles) + if (!NumCycles) return false; // Attempt to estimate the relative costs of predication versus branching. - float UnpredCost = Probability * NumCyles; + float UnpredCost = Probability * NumCycles; UnpredCost += 1.0; // The branch itself UnpredCost += (1.0 - Confidence) * Subtarget.getMispredictionPenalty(); - return (float)(NumCyles + ExtraPredCycles) < UnpredCost; + return (float)(NumCycles + ExtraPredCycles) < UnpredCost; } bool ARMBaseInstrInfo:: Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=129429&r1=129428&r2=129429&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original) +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Wed Apr 13 01:39:16 2011 @@ -307,7 +307,7 @@ const MachineFunction &MF) const; virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, - unsigned NumCyles, unsigned ExtraPredCycles, + unsigned NumCycles, unsigned ExtraPredCycles, float Prob, float Confidence) const; virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB, @@ -317,10 +317,10 @@ float Probability, float Confidence) const; virtual bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, - unsigned NumCyles, + unsigned NumCycles, float Probability, float Confidence) const { - return NumCyles == 1; + return NumCycles == 1; } /// AnalyzeCompare - For a comparison instruction, return the source register From baldrick at free.fr Wed Apr 13 02:25:24 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 13 Apr 2011 09:25:24 +0200 Subject: [llvm-commits] [llvm-gcc-4.2] r129344 - /llvm-gcc-4.2/trunk/gcc/llvm-backend.cpp In-Reply-To: References: <20110412021741.C5BB52A6C12D@llvm.org> <4DA40199.4050302@free.fr> Message-ID: <4DA54FE4.3000605@free.fr> Hi Evan, > I can't verify this. But hopefully r129382 would fix it. that seems to have done the trick - thanks! Ciao, Duncan. From baldrick at free.fr Wed Apr 13 02:42:02 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 13 Apr 2011 09:42:02 +0200 Subject: [llvm-commits] [llvm] r129428 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll In-Reply-To: <20110413060316.4882B2A6C12D@llvm.org> References: <20110413060316.4882B2A6C12D@llvm.org> Message-ID: <4DA553CA.5000500@free.fr> Hi Cameron, > If a global variable has a specified alignment that is less than the preferred > alignment for its type, use the minimum of the specified alignment and the ABI > alignment. This fixes. if the ABI alignment is 1, the preferred alignment is 4 and someone asks for an alignment of 2 then you give them an alignment of 1. Isn't it wrong to ever use an alignment less than was explicitly asked for by the user? Are you sure you don't want to use the maximum of the ABI and the specified alignment? Ciao, Duncan. From zwarich at apple.com Wed Apr 13 02:45:47 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Wed, 13 Apr 2011 00:45:47 -0700 Subject: [llvm-commits] [llvm] r129428 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll In-Reply-To: <4DA553CA.5000500@free.fr> References: <20110413060316.4882B2A6C12D@llvm.org> <4DA553CA.5000500@free.fr> Message-ID: On 2011-04-13, at 12:42 AM, Duncan Sands wrote: > Hi Cameron, > >> If a global variable has a specified alignment that is less than the preferred >> alignment for its type, use the minimum of the specified alignment and the ABI >> alignment. This fixes. > > if the ABI alignment is 1, the preferred alignment is 4 and someone asks for an > alignment of 2 then you give them an alignment of 1. Isn't it wrong to ever > use an alignment less than was explicitly asked for by the user? Are you sure > you don't want to use the maximum of the ABI and the specified alignment? Yeah, of course I wanted the maximum. I'll fix that. Thanks, Cameron From geek4civic at gmail.com Wed Apr 13 03:07:25 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Wed, 13 Apr 2011 17:07:25 +0900 Subject: [llvm-commits] [PATCH 1/3] autoconf: Add checking ELM_Callback decl for mingw32 and mingw-w64. Message-ID: --- autoconf/configure.ac | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-) --- config.h.in is included in latter patch. configure is omitted. ...Takumi -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-autoconf-Add-checking-ELM_Callback-decl-for-ming.patch.txt Type: text/x-patch Size: 1063 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110413/8c658827/attachment.bin From geek4civic at gmail.com Wed Apr 13 03:08:00 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Wed, 13 Apr 2011 17:08:00 +0900 Subject: [llvm-commits] [PATCH 2/3] cmake/config-ix.cmake: Add checking ELM_Callback decl for win32. Message-ID: --- cmake/config-ix.cmake | 13 +++++++++++++ 1 files changed, 13 insertions(+), 0 deletions(-) -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-cmake-config-ix.cmake-Add-checking-ELM_Callback-.patch.txt Type: text/x-patch Size: 804 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110413/bcd75229/attachment.bin From geek4civic at gmail.com Wed Apr 13 03:11:12 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Wed, 13 Apr 2011 17:11:12 +0900 Subject: [llvm-commits] [PATCH 3/3] Windows/DynamicLibrary.inc: Clean up ELM_Callback. Message-ID: --- include/llvm/Config/config.h.cmake | 3 ++ include/llvm/Config/config.h.in | 3 ++ lib/Support/Windows/DynamicLibrary.inc | 33 +------------------------------ 3 files changed, 8 insertions(+), 31 deletions(-) --- Thus, we can eliminate much of conditions. Checked on mingw32(configure and cmake), msvs10, and x86_64-w64-mingw32-g++. (not i686-w64-mingw32 yet) ...Takumi -------------- next part -------------- A non-text attachment was scrubbed... Name: 0003-Windows-DynamicLibrary.inc-Clean-up-ELM_Callback.patch.txt Type: text/x-patch Size: 2730 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110413/c4e9ca6d/attachment-0001.bin From zwarich at apple.com Wed Apr 13 04:02:43 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Wed, 13 Apr 2011 09:02:43 -0000 Subject: [llvm-commits] [llvm] r129432 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll Message-ID: <20110413090243.62B2F2A6C12D@llvm.org> Author: zwarich Date: Wed Apr 13 04:02:43 2011 New Revision: 129432 URL: http://llvm.org/viewvc/llvm-project?rev=129432&view=rev Log: Fix an obvious problem with an alignment computation. AsmPrinter actually does the max itself, so it is not easy to write a test case for this, but I added a test case that would fail if the code in AsmPrinter were removed. Modified: llvm/trunk/lib/Target/TargetData.cpp llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll Modified: llvm/trunk/lib/Target/TargetData.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetData.cpp?rev=129432&r1=129431&r2=129432&view=diff ============================================================================== --- llvm/trunk/lib/Target/TargetData.cpp (original) +++ llvm/trunk/lib/Target/TargetData.cpp Wed Apr 13 04:02:43 2011 @@ -621,7 +621,7 @@ if (GVAlignment >= Alignment) { Alignment = GVAlignment; } else if (GVAlignment != 0) { - Alignment = std::min(GVAlignment, getABITypeAlignment(ElemType)); + Alignment = std::max(GVAlignment, getABITypeAlignment(ElemType)); } if (GV->hasInitializer()) { Modified: llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll?rev=129432&r1=129431&r2=129432&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll (original) +++ llvm/trunk/test/CodeGen/ARM/2011-04-12-AlignBug.ll Wed Apr 13 04:02:43 2011 @@ -2,6 +2,8 @@ target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:64-v128:32:128-a0:0:32-n32" target triple = "thumbv7-apple-darwin10.0.0" +; CHECK: align 3 + at .v = linker_private unnamed_addr constant <4 x i32> , align 8 ; CHECK: align 2 @.strA = linker_private unnamed_addr constant [4 x i8] c"bar\00" ; CHECK-NOT: align From baldrick at free.fr Wed Apr 13 04:31:42 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 13 Apr 2011 11:31:42 +0200 Subject: [llvm-commits] [llvm] r129432 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll In-Reply-To: <20110413090243.62B2F2A6C12D@llvm.org> References: <20110413090243.62B2F2A6C12D@llvm.org> Message-ID: <4DA56D7E.2060009@free.fr> Hi Cameron, > +; CHECK: align 3 shouldn't alignment be a power of 2? Ciao, Duncan. From zwarich at apple.com Wed Apr 13 04:39:32 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Wed, 13 Apr 2011 02:39:32 -0700 Subject: [llvm-commits] [llvm] r129432 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll In-Reply-To: <4DA56D7E.2060009@free.fr> References: <20110413090243.62B2F2A6C12D@llvm.org> <4DA56D7E.2060009@free.fr> Message-ID: <012DC650-E434-44E6-94FE-D5856269BFF3@apple.com> On 2011-04-13, at 2:31 AM, Duncan Sands wrote: > Hi Cameron, > >> +; CHECK: align 3 > > shouldn't alignment be a power of 2? The align assembler directive on ARM uses the number of leading 0 bits of the address, not the byte alignment. Cameron From jay.foad at gmail.com Wed Apr 13 07:46:01 2011 From: jay.foad at gmail.com (Jay Foad) Date: Wed, 13 Apr 2011 12:46:01 -0000 Subject: [llvm-commits] [llvm] r129435 - in /llvm/trunk: include/llvm/CodeGen/JITCodeEmitter.h lib/ExecutionEngine/JIT/JITEmitter.cpp Message-ID: <20110413124601.82E202A6C12D@llvm.org> Author: foad Date: Wed Apr 13 07:46:01 2011 New Revision: 129435 URL: http://llvm.org/viewvc/llvm-project?rev=129435&view=rev Log: Like the coding standards say, do not use "using namespace std". Modified: llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Modified: llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h?rev=129435&r1=129434&r2=129435&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h (original) +++ llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h Wed Apr 13 07:46:01 2011 @@ -23,8 +23,6 @@ #include "llvm/CodeGen/MachineCodeEmitter.h" #include "llvm/ADT/DenseMap.h" -using namespace std; - namespace llvm { class MachineBasicBlock; Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=129435&r1=129434&r2=129435&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Wed Apr 13 07:46:01 2011 @@ -128,7 +128,7 @@ return GlobalToIndirectSymMap; } - pair LookupFunctionFromCallSite( + std::pair LookupFunctionFromCallSite( const MutexGuard &locked, void *CallSite) const { assert(locked.holds(TheJIT->lock)); @@ -646,7 +646,7 @@ // The address given to us for the stub may not be exactly right, it might // be a little bit after the stub. As such, use upper_bound to find it. - pair I = + std::pair I = JR->state.LookupFunctionFromCallSite(locked, Stub); F = I.second; ActualPtr = I.first; From jay.foad at gmail.com Wed Apr 13 07:50:47 2011 From: jay.foad at gmail.com (Jay Foad) Date: Wed, 13 Apr 2011 12:50:47 -0000 Subject: [llvm-commits] [llvm] r129436 - /llvm/trunk/include/llvm/ADT/ArrayRef.h Message-ID: <20110413125047.821962A6C12D@llvm.org> Author: foad Date: Wed Apr 13 07:50:47 2011 New Revision: 129436 URL: http://llvm.org/viewvc/llvm-project?rev=129436&view=rev Log: Fix typo in comment. Modified: llvm/trunk/include/llvm/ADT/ArrayRef.h Modified: llvm/trunk/include/llvm/ADT/ArrayRef.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ArrayRef.h?rev=129436&r1=129435&r2=129436&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/ArrayRef.h (original) +++ llvm/trunk/include/llvm/ADT/ArrayRef.h Wed Apr 13 07:50:47 2011 @@ -22,8 +22,8 @@ /// /// This class does not own the underlying data, it is expected to be used in /// situations where the data resides in some other buffer, whose lifetime - /// extends past that of the StringRef. For this reason, it is not in general - /// safe to store a ArrayRef. + /// extends past that of the ArrayRef. For this reason, it is not in general + /// safe to store an ArrayRef. /// /// This is intended to be trivially copyable, so it should be passed by /// value. From jay.foad at gmail.com Wed Apr 13 08:03:56 2011 From: jay.foad at gmail.com (Jay Foad) Date: Wed, 13 Apr 2011 13:03:56 -0000 Subject: [llvm-commits] [llvm] r129437 - /llvm/trunk/docs/CodeGenerator.html Message-ID: <20110413130357.095E92A6C12D@llvm.org> Author: foad Date: Wed Apr 13 08:03:56 2011 New Revision: 129437 URL: http://llvm.org/viewvc/llvm-project?rev=129437&view=rev Log: Fix typo. Modified: llvm/trunk/docs/CodeGenerator.html Modified: llvm/trunk/docs/CodeGenerator.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CodeGenerator.html?rev=129437&r1=129436&r2=129437&view=diff ============================================================================== --- llvm/trunk/docs/CodeGenerator.html (original) +++ llvm/trunk/docs/CodeGenerator.html Wed Apr 13 08:03:56 2011 @@ -770,7 +770,7 @@ like label names, machine instructions, and sections in the object file. The code in this layer is used for a number of important purposes: the tail end of the code generator uses it to write a .s or .o file, and it is also used by the -llvm-mc tool to implement standalone machine codeassemblers and disassemblers. +llvm-mc tool to implement standalone machine code assemblers and disassemblers.

      From zwarich at apple.com Wed Apr 13 08:49:56 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Wed, 13 Apr 2011 06:49:56 -0700 Subject: [llvm-commits] [llvm] r129432 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll In-Reply-To: References: <20110413090243.62B2F2A6C12D@llvm.org> <4DA56D7E.2060009@free.fr> <012DC650-E434-44E6-94FE-D5856269BFF3@apple.com> Message-ID: <84388DE7-7C33-499D-B8E1-8E1E65086CC3@apple.com> On 2011-04-13, at 3:51 AM, Renato Golin wrote: > On 13 April 2011 10:39, Cameron Zwarich wrote: >>> shouldn't alignment be a power of 2? >> >> The align assembler directive on ARM uses the number of leading 0 bits of the address, not the byte alignment. > > AFAIK .align is an alias to .balign and it should indeed be a power of > 2, as it is the byte alignment of the data to follow. I have no idea about the history here, but LLVM is definitely using leading zeros in this test and all of the other ARM alignment tests, which is probably based on what the GNU assembler does: http://sourceware.org/binutils/docs/as/Align.html Presumedly the GNU assembler is basing its behaviour on what some earlier popular ARM assembler did. Cameron From jay.foad at gmail.com Wed Apr 13 08:46:01 2011 From: jay.foad at gmail.com (Jay Foad) Date: Wed, 13 Apr 2011 13:46:01 -0000 Subject: [llvm-commits] [llvm] r129439 - in /llvm/trunk: include/llvm/Constants.h lib/Bitcode/Reader/BitcodeReader.cpp lib/VMCore/Constants.cpp Message-ID: <20110413134601.84A882A6C12D@llvm.org> Author: foad Date: Wed Apr 13 08:46:01 2011 New Revision: 129439 URL: http://llvm.org/viewvc/llvm-project?rev=129439&view=rev Log: PR9214: Convert ConstantExpr::getWithOperands() to use ArrayRef. Modified: llvm/trunk/include/llvm/Constants.h llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp llvm/trunk/lib/VMCore/Constants.cpp Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=129439&r1=129438&r2=129439&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Wed Apr 13 08:46:01 2011 @@ -897,10 +897,7 @@ /// getWithOperands - This returns the current constant expression with the /// operands replaced with the specified values. The specified operands must /// match count and type with the existing ones. - Constant *getWithOperands(const std::vector &Ops) const { - return getWithOperands(&Ops[0], (unsigned)Ops.size()); - } - Constant *getWithOperands(Constant *const *Ops, unsigned NumOps) const; + Constant *getWithOperands(llvm::ArrayRef Ops) const; virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=129439&r1=129438&r2=129439&view=diff ============================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original) +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Wed Apr 13 08:46:01 2011 @@ -301,8 +301,7 @@ NewC = ConstantVector::get(NewOps); } else { assert(isa(UserC) && "Must be a ConstantExpr."); - NewC = cast(UserC)->getWithOperands(&NewOps[0], - NewOps.size()); + NewC = cast(UserC)->getWithOperands(NewOps); } UserC->replaceAllUsesWith(NewC); Modified: llvm/trunk/lib/VMCore/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Constants.cpp?rev=129439&r1=129438&r2=129439&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Constants.cpp (original) +++ llvm/trunk/lib/VMCore/Constants.cpp Wed Apr 13 08:46:01 2011 @@ -855,10 +855,10 @@ /// operands replaced with the specified values. The specified operands must /// match count and type with the existing ones. Constant *ConstantExpr:: -getWithOperands(Constant *const *Ops, unsigned NumOps) const { - assert(NumOps == getNumOperands() && "Operand count mismatch!"); +getWithOperands(llvm::ArrayRef Ops) const { + assert(Ops.size() == getNumOperands() && "Operand count mismatch!"); bool AnyChange = false; - for (unsigned i = 0; i != NumOps; ++i) { + for (unsigned i = 0; i != Ops.size(); ++i) { assert(Ops[i]->getType() == getOperand(i)->getType() && "Operand type mismatch!"); AnyChange |= Ops[i] != getOperand(i); @@ -890,8 +890,8 @@ return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); case Instruction::GetElementPtr: return cast(this)->isInBounds() ? - ConstantExpr::getInBoundsGetElementPtr(Ops[0], &Ops[1], NumOps-1) : - ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], NumOps-1); + ConstantExpr::getInBoundsGetElementPtr(Ops[0], &Ops[1], Ops.size()-1) : + ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], Ops.size()-1); case Instruction::ICmp: case Instruction::FCmp: return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]); From jay.foad at gmail.com Wed Apr 13 08:48:09 2011 From: jay.foad at gmail.com (Jay Foad) Date: Wed, 13 Apr 2011 13:48:09 -0000 Subject: [llvm-commits] [llvm] r129440 - /llvm/trunk/include/llvm/Constants.h Message-ID: <20110413134809.74C4F2A6C12D@llvm.org> Author: foad Date: Wed Apr 13 08:48:09 2011 New Revision: 129440 URL: http://llvm.org/viewvc/llvm-project?rev=129440&view=rev Log: Fix a comment. Modified: llvm/trunk/include/llvm/Constants.h Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=129440&r1=129439&r2=129440&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Wed Apr 13 08:48:09 2011 @@ -841,7 +841,7 @@ static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS); static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS); - /// Getelementptr form. std::vector is only accepted for convenience: + /// Getelementptr form. Value* is only accepted for convenience; /// all elements must be Constant's. /// static Constant *getGetElementPtr(Constant *C, From ofv at wanadoo.es Wed Apr 13 09:07:03 2011 From: ofv at wanadoo.es (=?utf-8?Q?=C3=93scar_Fuentes?=) Date: Wed, 13 Apr 2011 16:07:03 +0200 Subject: [llvm-commits] [PATCH 2/3] cmake/config-ix.cmake: Add checking ELM_Callback decl for win32. In-Reply-To: (NAKAMURA Takumi's message of "Wed, 13 Apr 2011 17:08:00 +0900") References: Message-ID: <87mxjudz3s.fsf@wanadoo.es> Hello Takumi. The patch looks formally ok. Some comments on style follow... NAKAMURA Takumi writes: > --- > cmake/config-ix.cmake | 13 +++++++++++++ > 1 files changed, 13 insertions(+), 0 deletions(-) > > diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake > index e446853..c2263ec 100755 > --- a/cmake/config-ix.cmake > +++ b/cmake/config-ix.cmake > @@ -366,6 +366,19 @@ else( MSVC ) > set(LTDL_DLOPEN_DEPLIBS 0) # TODO > endif( MSVC ) > > +if( PURE_WINDOWS ) > + CHECK_CXX_SOURCE_COMPILES("#include Start with the opening `"" and then follow on the next line, so all the code gets the same indentation: > + CHECK_CXX_SOURCE_COMPILES(" > + #include > + #include > + extern \"C\" void foo(PENUMLOADED_MODULES_CALLBACK); > + extern \"C\" void foo(BOOL(CALLBACK*)(PCSTR,ULONG_PTR,ULONG,PVOID)); > + int main(){return 0;}" HAVE_ELMCB_PCSTR) Please put the result variable on its own line, so it stands out from the chunk of code. > + if( HAVE_ELMCB_PCSTR ) > + set(WIN32_ELMCB_PCSTR "PCSTR") > + else( HAVE_ELMCB_PCSTR ) > + set(WIN32_ELMCB_PCSTR "PSTR") > + endif( HAVE_ELMCB_PCSTR ) Repeating the `if' condition in the `endif' and `else' makes the code look noisy and gives no gain when the `if' is right there a few lines up. This is easier to read: > + if( HAVE_ELMCB_PCSTR ) > + set(WIN32_ELMCB_PCSTR "PCSTR") > + else() > + set(WIN32_ELMCB_PCSTR "PSTR") > + endif() Once the `endif' is separated from the `if' by a sufficient number of lines, repeating the condition starts to make sense, although I don't mind if it is omitted: > +endif( PURE_WINDOWS ) > + > # FIXME: Signal handler return type, currently hardcoded to 'void' > set(RETSIGTYPE void) > From jay.foad at gmail.com Wed Apr 13 09:39:42 2011 From: jay.foad at gmail.com (Jay Foad) Date: Wed, 13 Apr 2011 14:39:42 -0000 Subject: [llvm-commits] [llvm] r129441 - in /llvm/trunk: include/llvm/Constants.h lib/VMCore/Constants.cpp Message-ID: <20110413143942.784662A6C12D@llvm.org> Author: foad Date: Wed Apr 13 09:39:42 2011 New Revision: 129441 URL: http://llvm.org/viewvc/llvm-project?rev=129441&view=rev Log: Remove some redundant llvm:: prefixes. Modified: llvm/trunk/include/llvm/Constants.h llvm/trunk/lib/VMCore/Constants.cpp Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=129441&r1=129440&r2=129441&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Wed Apr 13 09:39:42 2011 @@ -897,7 +897,7 @@ /// getWithOperands - This returns the current constant expression with the /// operands replaced with the specified values. The specified operands must /// match count and type with the existing ones. - Constant *getWithOperands(llvm::ArrayRef Ops) const; + Constant *getWithOperands(ArrayRef Ops) const; virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); Modified: llvm/trunk/lib/VMCore/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Constants.cpp?rev=129441&r1=129440&r2=129441&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Constants.cpp (original) +++ llvm/trunk/lib/VMCore/Constants.cpp Wed Apr 13 09:39:42 2011 @@ -855,7 +855,7 @@ /// operands replaced with the specified values. The specified operands must /// match count and type with the existing ones. Constant *ConstantExpr:: -getWithOperands(llvm::ArrayRef Ops) const { +getWithOperands(ArrayRef Ops) const { assert(Ops.size() == getNumOperands() && "Operand count mismatch!"); bool AnyChange = false; for (unsigned i = 0; i != Ops.size(); ++i) { From stoklund at 2pi.dk Wed Apr 13 10:00:11 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Wed, 13 Apr 2011 15:00:11 -0000 Subject: [llvm-commits] [llvm] r129442 - in /llvm/trunk/lib/CodeGen: RegAllocGreedy.cpp SplitKit.cpp SplitKit.h Message-ID: <20110413150011.EA68E2A6C12D@llvm.org> Author: stoklund Date: Wed Apr 13 10:00:11 2011 New Revision: 129442 URL: http://llvm.org/viewvc/llvm-project?rev=129442&view=rev Log: Stop using dead function. Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp llvm/trunk/lib/CodeGen/SplitKit.cpp llvm/trunk/lib/CodeGen/SplitKit.h Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp?rev=129442&r1=129441&r2=129442&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Wed Apr 13 10:00:11 2011 @@ -843,8 +843,6 @@ SE->enterIntvAtEnd(*MBB); } - SE->closeIntv(); - // FIXME: Should we be more aggressive about splitting the stack region into // per-block segments? The current approach allows the stack region to // separate into connected components. Some components may be allocatable. @@ -1171,7 +1169,6 @@ SlotIndex SegStart = SE->enterIntvBefore(Uses[BestBefore]); SlotIndex SegStop = SE->leaveIntvAfter(Uses[BestAfter]); SE->useIntv(SegStart, SegStop); - SE->closeIntv(); SE->finish(); setStage(NewVRegs.begin(), NewVRegs.end(), RS_Local); ++NumLocalSplits; Modified: llvm/trunk/lib/CodeGen/SplitKit.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.cpp?rev=129442&r1=129441&r2=129442&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SplitKit.cpp (original) +++ llvm/trunk/lib/CodeGen/SplitKit.cpp Wed Apr 13 10:00:11 2011 @@ -558,8 +558,6 @@ /// Create a new virtual register and live interval. unsigned SplitEditor::openIntv() { - assert(!OpenIdx && "Previous LI not closed before openIntv"); - // Create the complement as index 0. if (Edit->empty()) Edit->create(LIS, VRM); @@ -696,13 +694,6 @@ DEBUG(dump()); } -/// closeIntv - Indicate that we are done editing the currently open -/// LiveInterval, and ranges can be trimmed. -void SplitEditor::closeIntv() { - assert(OpenIdx && "openIntv not called before closeIntv"); - OpenIdx = 0; -} - /// transferSimpleValues - Transfer all simply defined values to the new live /// ranges. /// Values that were rematerialized or that have multiple defs are left alone. @@ -846,7 +837,6 @@ } void SplitEditor::finish() { - assert(OpenIdx == 0 && "Previous LI not closed before rewrite"); ++NumFinished; // At this point, the live intervals in Edit contain VNInfos corresponding to @@ -948,7 +938,6 @@ useIntv(SegStart, SegStop); overlapIntv(SegStop, BI.LastUse); } - closeIntv(); } /// splitSingleBlocks - Split CurLI into a separate live interval inside each Modified: llvm/trunk/lib/CodeGen/SplitKit.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SplitKit.h?rev=129442&r1=129441&r2=129442&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SplitKit.h (original) +++ llvm/trunk/lib/CodeGen/SplitKit.h Wed Apr 13 10:00:11 2011 @@ -337,10 +337,6 @@ /// void overlapIntv(SlotIndex Start, SlotIndex End); - /// closeIntv - Indicate that we are done editing the currently open - /// LiveInterval, and ranges can be trimmed. - void closeIntv(); - /// finish - after all the new live ranges have been created, compute the /// remaining live range, and rewrite instructions to use the new registers. void finish(); From jay.foad at gmail.com Wed Apr 13 10:22:40 2011 From: jay.foad at gmail.com (Jay Foad) Date: Wed, 13 Apr 2011 15:22:40 -0000 Subject: [llvm-commits] [llvm] r129443 - in /llvm/trunk: include/llvm/Constants.h lib/Analysis/Lint.cpp lib/VMCore/AsmWriter.cpp lib/VMCore/Constants.cpp lib/VMCore/ConstantsContext.h Message-ID: <20110413152240.99D432A6C12D@llvm.org> Author: foad Date: Wed Apr 13 10:22:40 2011 New Revision: 129443 URL: http://llvm.org/viewvc/llvm-project?rev=129443&view=rev Log: PR9214: Convert ConstantExpr::getIndices() to return an ArrayRef, plus related tweaks to ExprMapKeyType. Modified: llvm/trunk/include/llvm/Constants.h llvm/trunk/lib/Analysis/Lint.cpp llvm/trunk/lib/VMCore/AsmWriter.cpp llvm/trunk/lib/VMCore/Constants.cpp llvm/trunk/lib/VMCore/ConstantsContext.h Modified: llvm/trunk/include/llvm/Constants.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=129443&r1=129442&r2=129443&view=diff ============================================================================== --- llvm/trunk/include/llvm/Constants.h (original) +++ llvm/trunk/include/llvm/Constants.h Wed Apr 13 10:22:40 2011 @@ -885,7 +885,7 @@ /// getIndices - Assert that this is an insertvalue or exactvalue /// expression and return the list of indices. - const SmallVector &getIndices() const; + ArrayRef getIndices() const; /// getOpcodeName - Return a string representation for an opcode. const char *getOpcodeName() const; Modified: llvm/trunk/lib/Analysis/Lint.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/Lint.cpp?rev=129443&r1=129442&r2=129443&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/Lint.cpp (original) +++ llvm/trunk/lib/Analysis/Lint.cpp Wed Apr 13 10:22:40 2011 @@ -606,7 +606,7 @@ Type::getInt64Ty(V->getContext()))) return findValueImpl(CE->getOperand(0), OffsetOk, Visited); } else if (CE->getOpcode() == Instruction::ExtractValue) { - const SmallVector &Indices = CE->getIndices(); + ArrayRef Indices = CE->getIndices(); if (Value *W = FindInsertedValue(CE->getOperand(0), Indices.begin(), Indices.end())) Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AsmWriter.cpp?rev=129443&r1=129442&r2=129443&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/AsmWriter.cpp (original) +++ llvm/trunk/lib/VMCore/AsmWriter.cpp Wed Apr 13 10:22:40 2011 @@ -1075,7 +1075,7 @@ } if (CE->hasIndices()) { - const SmallVector &Indices = CE->getIndices(); + ArrayRef Indices = CE->getIndices(); for (unsigned i = 0, e = Indices.size(); i != e; ++i) Out << ", " << Indices[i]; } Modified: llvm/trunk/lib/VMCore/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Constants.cpp?rev=129443&r1=129442&r2=129443&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Constants.cpp (original) +++ llvm/trunk/lib/VMCore/Constants.cpp Wed Apr 13 10:22:40 2011 @@ -771,7 +771,7 @@ getOpcode() == Instruction::InsertValue; } -const SmallVector &ConstantExpr::getIndices() const { +ArrayRef ConstantExpr::getIndices() const { if (const ExtractValueConstantExpr *EVCE = dyn_cast(this)) return EVCE->Indices; @@ -2151,7 +2151,7 @@ Constant *Agg = getOperand(0); if (Agg == From) Agg = To; - const SmallVector &Indices = getIndices(); + ArrayRef Indices = getIndices(); Replacement = ConstantExpr::getExtractValue(Agg, &Indices[0], Indices.size()); } else if (getOpcode() == Instruction::InsertValue) { @@ -2160,7 +2160,7 @@ if (Agg == From) Agg = To; if (Val == From) Val = To; - const SmallVector &Indices = getIndices(); + ArrayRef Indices = getIndices(); Replacement = ConstantExpr::getInsertValue(Agg, Val, &Indices[0], Indices.size()); } else if (isCast()) { Modified: llvm/trunk/lib/VMCore/ConstantsContext.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/ConstantsContext.h?rev=129443&r1=129442&r2=129443&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/ConstantsContext.h (original) +++ llvm/trunk/lib/VMCore/ConstantsContext.h Wed Apr 13 10:22:40 2011 @@ -301,20 +301,18 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value) struct ExprMapKeyType { - typedef SmallVector IndexList; - ExprMapKeyType(unsigned opc, - const std::vector &ops, + ArrayRef ops, unsigned short flags = 0, unsigned short optionalflags = 0, - const IndexList &inds = IndexList()) + ArrayRef inds = ArrayRef()) : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags), - operands(ops), indices(inds) {} + operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {} uint8_t opcode; uint8_t subclassoptionaldata; uint16_t subclassdata; std::vector operands; - IndexList indices; + SmallVector indices; bool operator==(const ExprMapKeyType& that) const { return this->opcode == that.opcode && this->subclassdata == that.subclassdata && @@ -465,7 +463,7 @@ CE->isCompare() ? CE->getPredicate() : 0, CE->getRawSubclassOptionalData(), CE->hasIndices() ? - CE->getIndices() : SmallVector()); + CE->getIndices() : ArrayRef()); } }; From ofv at wanadoo.es Wed Apr 13 10:25:31 2011 From: ofv at wanadoo.es (Oscar Fuentes) Date: Wed, 13 Apr 2011 15:25:31 -0000 Subject: [llvm-commits] [llvm] r129444 - /llvm/trunk/cmake/modules/LLVMConfig.cmake.in Message-ID: <20110413152532.022932A6C12D@llvm.org> Author: ofv Date: Wed Apr 13 10:25:31 2011 New Revision: 129444 URL: http://llvm.org/viewvc/llvm-project?rev=129444&view=rev Log: Export LLVM_TARGETS_WITH_JIT in LLVMConfig.cmake.in. Without this, component names such as "engine" do not expand to "jit" and hence to the native target libraries for external users. Thanks to arrowdodger for reporting and diagnosing the problem. Modified: llvm/trunk/cmake/modules/LLVMConfig.cmake.in Modified: llvm/trunk/cmake/modules/LLVMConfig.cmake.in URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/LLVMConfig.cmake.in?rev=129444&r1=129443&r2=129444&view=diff ============================================================================== --- llvm/trunk/cmake/modules/LLVMConfig.cmake.in (original) +++ llvm/trunk/cmake/modules/LLVMConfig.cmake.in Wed Apr 13 10:25:31 2011 @@ -10,6 +10,8 @@ set(LLVM_TARGETS_TO_BUILD @LLVM_TARGETS_TO_BUILD@) +set(LLVM_TARGETS_WITH_JIT @LLVM_TARGETS_WITH_JIT@) + set(TARGET_TRIPLE "@TARGET_TRIPLE@") set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@) From grosbach at apple.com Wed Apr 13 10:28:10 2011 From: grosbach at apple.com (Jim Grosbach) Date: Wed, 13 Apr 2011 15:28:10 -0000 Subject: [llvm-commits] [llvm] r129445 - /llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.cpp Message-ID: <20110413152810.E19132A6C12D@llvm.org> Author: grosbach Date: Wed Apr 13 10:28:10 2011 New Revision: 129445 URL: http://llvm.org/viewvc/llvm-project?rev=129445&view=rev Log: MCJIT relocation resolution. Modified: llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.cpp Modified: llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.cpp?rev=129445&r1=129444&r2=129445&view=diff ============================================================================== --- llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.cpp (original) +++ llvm/trunk/lib/ExecutionEngine/MCJIT/MCJIT.cpp Wed Apr 13 10:28:10 2011 @@ -93,6 +93,8 @@ Buffer.size())); if (Dyld.loadObject(MB)) report_fatal_error(Dyld.getErrorString()); + // Resolve any relocations. + Dyld.resolveRelocations(); } MCJIT::~MCJIT() { From grosbach at apple.com Wed Apr 13 10:38:30 2011 From: grosbach at apple.com (Jim Grosbach) Date: Wed, 13 Apr 2011 15:38:30 -0000 Subject: [llvm-commits] [llvm] r129446 - /llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Message-ID: <20110413153830.C7DB12A6C12D@llvm.org> Author: grosbach Date: Wed Apr 13 10:38:30 2011 New Revision: 129446 URL: http://llvm.org/viewvc/llvm-project?rev=129446&view=rev Log: Allow user-specified program entry point for llvm-rtdyld. Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp?rev=129446&r1=129445&r2=129446&view=diff ============================================================================== --- llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp (original) +++ llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Wed Apr 13 10:38:30 2011 @@ -38,6 +38,11 @@ "Load, link, and execute the inputs."), clEnumValEnd)); +static cl::opt +EntryPoint("entry", + cl::desc("Function to call as entry point."), + cl::init("_main")); + /* *** */ // A trivial memory manager that doesn't do anything fancy, just uses the @@ -93,10 +98,10 @@ // Resolve all the relocations we can. Dyld.resolveRelocations(); - // Get the address of "_main". - void *MainAddress = Dyld.getSymbolAddress("_main"); + // Get the address of the entry point (_main by default). + void *MainAddress = Dyld.getSymbolAddress(EntryPoint); if (MainAddress == 0) - return Error("no definition for '_main'"); + return Error("no definition for '" + EntryPoint + "'"); // Invalidate the instruction cache for each loaded function. for (unsigned i = 0, e = MemMgr->FunctionMemory.size(); i != e; ++i) { From rafael.espindola at gmail.com Wed Apr 13 10:44:58 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Wed, 13 Apr 2011 15:44:58 -0000 Subject: [llvm-commits] [llvm] r129447 - in /llvm/trunk: include/llvm-c/Transforms/Scalar.h lib/Transforms/Scalar/Scalar.cpp Message-ID: <20110413154458.5DE2F2A6C12D@llvm.org> Author: rafael Date: Wed Apr 13 10:44:58 2011 New Revision: 129447 URL: http://llvm.org/viewvc/llvm-project?rev=129447&view=rev Log: Add the alias analysis to the C api. Modified: llvm/trunk/include/llvm-c/Transforms/Scalar.h llvm/trunk/lib/Transforms/Scalar/Scalar.cpp Modified: llvm/trunk/include/llvm-c/Transforms/Scalar.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Transforms/Scalar.h?rev=129447&r1=129446&r2=129447&view=diff ============================================================================== --- llvm/trunk/include/llvm-c/Transforms/Scalar.h (original) +++ llvm/trunk/include/llvm-c/Transforms/Scalar.h Wed Apr 13 10:44:58 2011 @@ -107,6 +107,13 @@ /** See llvm::createEarlyCSEPass function */ void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM); +/** See llvm::createTypeBasedAliasAnalysisPass function */ +void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); + +/** See llvm::createBasicAliasAnalysisPass function */ +void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); + + #ifdef __cplusplus } #endif /* defined(__cplusplus) */ Modified: llvm/trunk/lib/Transforms/Scalar/Scalar.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/Scalar.cpp?rev=129447&r1=129446&r2=129447&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/Scalar.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/Scalar.cpp Wed Apr 13 10:44:58 2011 @@ -17,6 +17,7 @@ #include "llvm-c/Initialization.h" #include "llvm/InitializePasses.h" #include "llvm/PassManager.h" +#include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Target/TargetData.h" #include "llvm/Transforms/Scalar.h" @@ -173,3 +174,11 @@ void LLVMAddEarlyCSEPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createEarlyCSEPass()); } + +void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createTypeBasedAliasAnalysisPass()); +} + +void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createBasicAliasAnalysisPass()); +} From grosbach at apple.com Wed Apr 13 10:49:40 2011 From: grosbach at apple.com (Jim Grosbach) Date: Wed, 13 Apr 2011 15:49:40 -0000 Subject: [llvm-commits] [llvm] r129448 - /llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Message-ID: <20110413154940.E6A762A6C12D@llvm.org> Author: grosbach Date: Wed Apr 13 10:49:40 2011 New Revision: 129448 URL: http://llvm.org/viewvc/llvm-project?rev=129448&view=rev Log: Load multiple object files and link them via RuntimeDyld in llvm-rtdyld. Relocations between the object modules are properly resolved, as in the following trivial example: $ cat t.c int foo(); int main() { return foo(); } $ cat foo.c int foo() { return 65; } $ clang -c t.c -fno-asynchronous-unwind-tables $ clang -c foo.c -fno-asynchronous-unwind-tables $ llvm-rtdyld t.o foo.o ; echo $? loaded '_main' at: 0x10015c000 65 Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Modified: llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp?rev=129448&r1=129447&r2=129448&view=diff ============================================================================== --- llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp (original) +++ llvm/trunk/tools/llvm-rtdyld/llvm-rtdyld.cpp Wed Apr 13 10:49:40 2011 @@ -24,8 +24,9 @@ using namespace llvm; using namespace llvm::object; -static cl::opt -InputFile(cl::Positional, cl::desc(""), cl::init("-")); +static cl::list +InputFileList(cl::Positional, cl::ZeroOrMore, + cl::desc("")); enum ActionType { AC_Execute @@ -82,22 +83,31 @@ /* *** */ static int executeInput() { - // Load the input memory buffer. - OwningPtr InputBuffer; - if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFile, InputBuffer)) - return Error("unable to read input: '" + ec.message() + "'"); - // Instantiate a dynamic linker. TrivialMemoryManager *MemMgr = new TrivialMemoryManager; RuntimeDyld Dyld(MemMgr); - // Load the object file into it. - if (Dyld.loadObject(InputBuffer.take())) { - return Error(Dyld.getErrorString()); + // If we don't have any input files, read from stdin. + if (!InputFileList.size()) + InputFileList.push_back("-"); + for(unsigned i = 0, e = InputFileList.size(); i != e; ++i) { + // Load the input memory buffer. + OwningPtr InputBuffer; + if (error_code ec = MemoryBuffer::getFileOrSTDIN(InputFileList[i], + InputBuffer)) + return Error("unable to read input: '" + ec.message() + "'"); + + // Load the object file into it. + if (Dyld.loadObject(InputBuffer.take())) { + return Error(Dyld.getErrorString()); + } } + // Resolve all the relocations we can. Dyld.resolveRelocations(); + // FIXME: Error out if there are unresolved relocations. + // Get the address of the entry point (_main by default). void *MainAddress = Dyld.getSymbolAddress(EntryPoint); if (MainAddress == 0) @@ -113,14 +123,14 @@ return Error("unable to mark function executable: '" + ErrorStr + "'"); } - // Dispatch to _main(). - errs() << "loaded '_main' at: " << (void*)MainAddress << "\n"; + errs() << "loaded '" << EntryPoint << "' at: " << (void*)MainAddress << "\n"; int (*Main)(int, const char**) = (int(*)(int,const char**)) uintptr_t(MainAddress); const char **Argv = new const char*[2]; - Argv[0] = InputFile.c_str(); + // Use the name of the first input object module as argv[0] for the target. + Argv[0] = InputFileList[0].c_str(); Argv[1] = 0; return Main(1, Argv); } From renato.golin at arm.com Wed Apr 13 05:51:44 2011 From: renato.golin at arm.com (Renato Golin) Date: Wed, 13 Apr 2011 11:51:44 +0100 Subject: [llvm-commits] [llvm] r129432 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll In-Reply-To: <012DC650-E434-44E6-94FE-D5856269BFF3@apple.com> References: <20110413090243.62B2F2A6C12D@llvm.org> <4DA56D7E.2060009@free.fr> <012DC650-E434-44E6-94FE-D5856269BFF3@apple.com> Message-ID: On 13 April 2011 10:39, Cameron Zwarich wrote: >> shouldn't alignment be a power of 2? > > The align assembler directive on ARM uses the number of leading 0 bits of the address, not the byte alignment. AFAIK .align is an alias to .balign and it should indeed be a power of 2, as it is the byte alignment of the data to follow. Unless this is not what you're looking for, obviously. Anyway, you should be more verbose in the CHECK, to make sure you don't match against possible comments or other text in the assembly output. cheers, --renato From rengolin at systemcall.org Wed Apr 13 09:30:44 2011 From: rengolin at systemcall.org (Renato Golin) Date: Wed, 13 Apr 2011 15:30:44 +0100 Subject: [llvm-commits] [llvm] r129432 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/ARM/2011-04-12-AlignBug.ll In-Reply-To: <84388DE7-7C33-499D-B8E1-8E1E65086CC3@apple.com> References: <20110413090243.62B2F2A6C12D@llvm.org> <4DA56D7E.2060009@free.fr> <012DC650-E434-44E6-94FE-D5856269BFF3@apple.com> <84388DE7-7C33-499D-B8E1-8E1E65086CC3@apple.com> Message-ID: On 13 April 2011 14:49, Cameron Zwarich wrote: > I have no idea about the history here, but LLVM is definitely using leading zeros in this test and all of the other ARM alignment tests, which is probably based on what the GNU assembler does: > > http://sourceware.org/binutils/docs/as/Align.html Hi Cameron, Gosh, that's weird... ;) I suggest LLVM to use .balign instead: http://sourceware.org/binutils/docs/as/Balign.html since it's standard (and sane) for all platforms. cheers, --renato From jgu222 at gmail.com Wed Apr 13 11:15:29 2011 From: jgu222 at gmail.com (Junjie Gu) Date: Wed, 13 Apr 2011 16:15:29 -0000 Subject: [llvm-commits] [llvm] r129449 - in /llvm/trunk: include/llvm/Transforms/Scalar.h lib/Transforms/Scalar/LoopUnrollPass.cpp Message-ID: <20110413161529.3CCB72A6C12D@llvm.org> Author: jugu Date: Wed Apr 13 11:15:29 2011 New Revision: 129449 URL: http://llvm.org/viewvc/llvm-project?rev=129449&view=rev Log: Passing unroll parameters (unroll-count, threshold, and partial unroll) via LoopUnroll class's ctor. Doing so will allow multiple context with different loop unroll parameters to run. This is a minor change and no effect on existing application. Modified: llvm/trunk/include/llvm/Transforms/Scalar.h llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Modified: llvm/trunk/include/llvm/Transforms/Scalar.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=129449&r1=129448&r2=129449&view=diff ============================================================================== --- llvm/trunk/include/llvm/Transforms/Scalar.h (original) +++ llvm/trunk/include/llvm/Transforms/Scalar.h Wed Apr 13 11:15:29 2011 @@ -128,7 +128,7 @@ // // LoopUnroll - This pass is a simple loop unrolling pass. // -Pass *createLoopUnrollPass(); +Pass *createLoopUnrollPass(int Threshold = -1, int Count = -1, int AllowPartial = -1); //===----------------------------------------------------------------------===// // Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=129449&r1=129448&r2=129449&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Wed Apr 13 11:15:29 2011 @@ -43,7 +43,13 @@ class LoopUnroll : public LoopPass { public: static char ID; // Pass ID, replacement for typeid - LoopUnroll() : LoopPass(ID) { + LoopUnroll(int T = -1, int C = -1, int P = -1) : LoopPass(ID) { + CurrentThreshold = (T == -1) ? UnrollThreshold : T; + CurrentCount = (C == -1) ? UnrollCount : C; + CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P; + + UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0); + initializeLoopUnrollPass(*PassRegistry::getPassRegistry()); } @@ -56,7 +62,10 @@ // explicit -unroll-threshold). static const unsigned OptSizeUnrollThreshold = 50; + unsigned CurrentCount; unsigned CurrentThreshold; + bool CurrentAllowPartial; + bool UserThreshold; // CurrentThreshold is user-specified. bool runOnLoop(Loop *L, LPPassManager &LPM); @@ -87,7 +96,9 @@ INITIALIZE_PASS_DEPENDENCY(LCSSA) INITIALIZE_PASS_END(LoopUnroll, "loop-unroll", "Unroll loops", false, false) -Pass *llvm::createLoopUnrollPass() { return new LoopUnroll(); } +Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) { + return new LoopUnroll(); +} /// ApproximateLoopSize - Approximate the size of the loop. static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) { @@ -119,14 +130,14 @@ // from UnrollThreshold, it is overridden to a smaller value if the current // function is marked as optimize-for-size, and the unroll threshold was // not user specified. - CurrentThreshold = UnrollThreshold; - if (Header->getParent()->hasFnAttr(Attribute::OptimizeForSize) && - UnrollThreshold.getNumOccurrences() == 0) - CurrentThreshold = OptSizeUnrollThreshold; + unsigned Threshold = CurrentThreshold; + if (!UserThreshold && + Header->getParent()->hasFnAttr(Attribute::OptimizeForSize)) + Threshold = OptSizeUnrollThreshold; // Find trip count unsigned TripCount = L->getSmallConstantTripCount(); - unsigned Count = UnrollCount; + unsigned Count = CurrentCount; // Automatically select an unroll count. if (Count == 0) { @@ -140,7 +151,7 @@ } // Enforce the threshold. - if (CurrentThreshold != NoThreshold) { + if (Threshold != NoThreshold) { unsigned NumInlineCandidates; unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates); DEBUG(dbgs() << " Loop Size = " << LoopSize << "\n"); @@ -149,16 +160,16 @@ return false; } uint64_t Size = (uint64_t)LoopSize*Count; - if (TripCount != 1 && Size > CurrentThreshold) { + if (TripCount != 1 && Size > Threshold) { DEBUG(dbgs() << " Too large to fully unroll with count: " << Count - << " because size: " << Size << ">" << CurrentThreshold << "\n"); - if (!UnrollAllowPartial) { + << " because size: " << Size << ">" << Threshold << "\n"); + if (!CurrentAllowPartial) { DEBUG(dbgs() << " will not try to unroll partially because " << "-unroll-allow-partial not given\n"); return false; } // Reduce unroll count to be modulo of TripCount for partial unrolling - Count = CurrentThreshold / LoopSize; + Count = Threshold / LoopSize; while (Count != 0 && TripCount%Count != 0) { Count--; } From eli.friedman at gmail.com Wed Apr 13 11:24:11 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 13 Apr 2011 09:24:11 -0700 Subject: [llvm-commits] [llvm] r129449 - in /llvm/trunk: include/llvm/Transforms/Scalar.h lib/Transforms/Scalar/LoopUnrollPass.cpp In-Reply-To: <20110413161529.3CCB72A6C12D@llvm.org> References: <20110413161529.3CCB72A6C12D@llvm.org> Message-ID: On Wed, Apr 13, 2011 at 9:15 AM, Junjie Gu wrote: > Author: jugu > Date: Wed Apr 13 11:15:29 2011 > New Revision: 129449 > > URL: http://llvm.org/viewvc/llvm-project?rev=129449&view=rev > Log: > Passing unroll parameters (unroll-count, threshold, and partial unroll) via LoopUnroll class's ctor. Doing so > will allow multiple context with different loop unroll parameters to run. ?This is a minor change and no effect > on existing application. > > > Modified: > ? ?llvm/trunk/include/llvm/Transforms/Scalar.h > ? ?llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp > > Modified: llvm/trunk/include/llvm/Transforms/Scalar.h > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=129449&r1=129448&r2=129449&view=diff > ============================================================================== > --- llvm/trunk/include/llvm/Transforms/Scalar.h (original) > +++ llvm/trunk/include/llvm/Transforms/Scalar.h Wed Apr 13 11:15:29 2011 > @@ -128,7 +128,7 @@ > ?// > ?// LoopUnroll - This pass is a simple loop unrolling pass. > ?// > -Pass *createLoopUnrollPass(); > +Pass *createLoopUnrollPass(int Threshold = -1, int Count = -1, int AllowPartial = -1); > > ?//===----------------------------------------------------------------------===// > ?// > > Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=129449&r1=129448&r2=129449&view=diff > ============================================================================== > --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Wed Apr 13 11:15:29 2011 > @@ -43,7 +43,13 @@ > ? class LoopUnroll : public LoopPass { > ? public: > ? ? static char ID; // Pass ID, replacement for typeid > - ? ?LoopUnroll() : LoopPass(ID) { > + ? ?LoopUnroll(int T = -1, int C = -1, ?int P = -1) : LoopPass(ID) { > + ? ? ?CurrentThreshold = (T == -1) ? UnrollThreshold : T; > + ? ? ?CurrentCount = (C == -1) ? UnrollCount : C; > + ? ? ?CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P; > + > + ? ? ?UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0); > + > ? ? ? initializeLoopUnrollPass(*PassRegistry::getPassRegistry()); > ? ? } > > @@ -56,7 +62,10 @@ > ? ? // explicit -unroll-threshold). > ? ? static const unsigned OptSizeUnrollThreshold = 50; > > + ? ?unsigned CurrentCount; > ? ? unsigned CurrentThreshold; > + ? ?bool ? ? CurrentAllowPartial; > + ? ?bool ? ? UserThreshold; ? ? ? ?// CurrentThreshold is user-specified. > > ? ? bool runOnLoop(Loop *L, LPPassManager &LPM); > > @@ -87,7 +96,9 @@ > ?INITIALIZE_PASS_DEPENDENCY(LCSSA) > ?INITIALIZE_PASS_END(LoopUnroll, "loop-unroll", "Unroll loops", false, false) > > -Pass *llvm::createLoopUnrollPass() { return new LoopUnroll(); } > +Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) { > + ?return new LoopUnroll(); > +} You added the arguments, and they're ignored? -Eli > ?/// ApproximateLoopSize - Approximate the size of the loop. > ?static unsigned ApproximateLoopSize(const Loop *L, unsigned &NumCalls) { > @@ -119,14 +130,14 @@ > ? // from UnrollThreshold, it is overridden to a smaller value if the current > ? // function is marked as optimize-for-size, and the unroll threshold was > ? // not user specified. > - ?CurrentThreshold = UnrollThreshold; > - ?if (Header->getParent()->hasFnAttr(Attribute::OptimizeForSize) && > - ? ? ?UnrollThreshold.getNumOccurrences() == 0) > - ? ?CurrentThreshold = OptSizeUnrollThreshold; > + ?unsigned Threshold = CurrentThreshold; > + ?if (!UserThreshold && > + ? ? ?Header->getParent()->hasFnAttr(Attribute::OptimizeForSize)) > + ? ?Threshold = OptSizeUnrollThreshold; > > ? // Find trip count > ? unsigned TripCount = L->getSmallConstantTripCount(); > - ?unsigned Count = UnrollCount; > + ?unsigned Count = CurrentCount; > > ? // Automatically select an unroll count. > ? if (Count == 0) { > @@ -140,7 +151,7 @@ > ? } > > ? // Enforce the threshold. > - ?if (CurrentThreshold != NoThreshold) { > + ?if (Threshold != NoThreshold) { > ? ? unsigned NumInlineCandidates; > ? ? unsigned LoopSize = ApproximateLoopSize(L, NumInlineCandidates); > ? ? DEBUG(dbgs() << " ?Loop Size = " << LoopSize << "\n"); > @@ -149,16 +160,16 @@ > ? ? ? return false; > ? ? } > ? ? uint64_t Size = (uint64_t)LoopSize*Count; > - ? ?if (TripCount != 1 && Size > CurrentThreshold) { > + ? ?if (TripCount != 1 && Size > Threshold) { > ? ? ? DEBUG(dbgs() << " ?Too large to fully unroll with count: " << Count > - ? ? ? ? ? ?<< " because size: " << Size << ">" << CurrentThreshold << "\n"); > - ? ? ?if (!UnrollAllowPartial) { > + ? ? ? ? ? ?<< " because size: " << Size << ">" << Threshold << "\n"); > + ? ? ?if (!CurrentAllowPartial) { > ? ? ? ? DEBUG(dbgs() << " ?will not try to unroll partially because " > ? ? ? ? ? ? ? << "-unroll-allow-partial not given\n"); > ? ? ? ? return false; > ? ? ? } > ? ? ? // Reduce unroll count to be modulo of TripCount for partial unrolling > - ? ? ?Count = CurrentThreshold / LoopSize; > + ? ? ?Count = Threshold / LoopSize; > ? ? ? while (Count != 0 && TripCount%Count != 0) { > ? ? ? ? Count--; > ? ? ? } > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From jgu222 at gmail.com Wed Apr 13 11:45:49 2011 From: jgu222 at gmail.com (Junjie Gu) Date: Wed, 13 Apr 2011 16:45:49 -0000 Subject: [llvm-commits] [llvm] r129450 - /llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Message-ID: <20110413164549.D38932A6C12D@llvm.org> Author: jugu Date: Wed Apr 13 11:45:49 2011 New Revision: 129450 URL: http://llvm.org/viewvc/llvm-project?rev=129450&view=rev Log: Fixed the revision 129449. Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=129450&r1=129449&r2=129450&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Wed Apr 13 11:45:49 2011 @@ -97,7 +97,7 @@ INITIALIZE_PASS_END(LoopUnroll, "loop-unroll", "Unroll loops", false, false) Pass *llvm::createLoopUnrollPass(int Threshold, int Count, int AllowPartial) { - return new LoopUnroll(); + return new LoopUnroll(Threshold, Count, AllowPartial); } /// ApproximateLoopSize - Approximate the size of the loop. From johnny.chen at apple.com Wed Apr 13 11:56:08 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Apr 2011 16:56:08 -0000 Subject: [llvm-commits] [llvm] r129451 - /llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Message-ID: <20110413165608.ED91F2A6C12D@llvm.org> Author: johnny Date: Wed Apr 13 11:56:08 2011 New Revision: 129451 URL: http://llvm.org/viewvc/llvm-project?rev=129451&view=rev Log: Forgot to add this change for http://llvm.org/viewvc/llvm-project?view=rev&revision=129387. Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=129451&r1=129450&r2=129451&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Wed Apr 13 11:56:08 2011 @@ -1497,20 +1497,20 @@ // ldrd / strd pre / post variants // For disassembly only. -def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs GPR:$Rt, GPR:$Rt2), +def t2LDRD_PRE : T2Ii8s4<1, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2), (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru, "ldrd", "\t$Rt, $Rt2, [$base, $imm]!", []>; -def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs GPR:$Rt, GPR:$Rt2), +def t2LDRD_POST : T2Ii8s4<0, 1, 1, (outs rGPR:$Rt, rGPR:$Rt2), (ins GPR:$base, t2am_imm8s4_offset:$imm), IIC_iLoad_d_ru, "ldrd", "\t$Rt, $Rt2, [$base], $imm", []>; def t2STRD_PRE : T2Ii8s4<1, 1, 0, (outs), - (ins GPR:$Rt, GPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), + (ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base, $imm]!", []>; def t2STRD_POST : T2Ii8s4<0, 1, 0, (outs), - (ins GPR:$Rt, GPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), + (ins rGPR:$Rt, rGPR:$Rt2, GPR:$base, t2am_imm8s4_offset:$imm), IIC_iStore_d_ru, "strd", "\t$Rt, $Rt2, [$base], $imm", []>; // T2Ipl (Preload Data/Instruction) signals the memory system of possible future From johnny.chen at apple.com Wed Apr 13 12:51:02 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Apr 2011 17:51:02 -0000 Subject: [llvm-commits] [llvm] r129456 - in /llvm/trunk: lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110413175102.EF53B2A6C12D@llvm.org> Author: johnny Date: Wed Apr 13 12:51:02 2011 New Revision: 129456 URL: http://llvm.org/viewvc/llvm-project?rev=129456&view=rev Log: Fix a bug where for t2MOVCCi disassembly, the TIED_TO register operand was not properly handled. rdar://problem/9276427 Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129456&r1=129455&r2=129456&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Wed Apr 13 12:51:02 2011 @@ -1470,7 +1470,8 @@ static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - const TargetOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; + const TargetInstrDesc &TID = ARMInsts[Opcode]; + const TargetOperandInfo *OpInfo = TID.OpInfo; unsigned &OpIdx = NumOpsAdded; OpIdx = 0; @@ -1497,8 +1498,15 @@ DEBUG(errs()<<"Thumb2 encoding error: d==15 for DPModImm 2-reg instr.\n"); return false; } - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID, - decodeRn(insn)))); + int Idx; + if ((Idx = TID.getOperandConstraint(OpIdx, TOI::TIED_TO)) != -1) { + // The reg operand is tied to the first reg operand. + MI.addOperand(MI.getOperand(Idx)); + } else { + // Add second reg operand. + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID, + decodeRn(insn)))); + } ++OpIdx; } Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129456&r1=129455&r2=129456&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Wed Apr 13 12:51:02 2011 @@ -241,3 +241,6 @@ # CHECK: rfedb lr 0x1e 0xe8 0x00 0xc0 + +# CHECK: mov.w r3, #4294967295 +0x4f 0xf0 0xff 0x33 From nicholas at mxc.ca Wed Apr 13 13:46:22 2011 From: nicholas at mxc.ca (Nick Lewycky) Date: Wed, 13 Apr 2011 18:46:22 -0000 Subject: [llvm-commits] [llvm] r129457 - /llvm/trunk/include/llvm/Support/DebugLoc.h Message-ID: <20110413184622.850DB2A6C12D@llvm.org> Author: nicholas Date: Wed Apr 13 13:46:22 2011 New Revision: 129457 URL: http://llvm.org/viewvc/llvm-project?rev=129457&view=rev Log: Use positive values since the value type is unsigned. Fixes a warning on the llvm-gcc-native-mingw32 builder. Modified: llvm/trunk/include/llvm/Support/DebugLoc.h Modified: llvm/trunk/include/llvm/Support/DebugLoc.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/DebugLoc.h?rev=129457&r1=129456&r2=129457&view=diff ============================================================================== --- llvm/trunk/include/llvm/Support/DebugLoc.h (original) +++ llvm/trunk/include/llvm/Support/DebugLoc.h Wed Apr 13 13:46:22 2011 @@ -31,7 +31,7 @@ /// not equal to the tombstone key or DebugLoc(). static DebugLoc getEmptyKey() { DebugLoc DL; - DL.LineCol = -1; + DL.LineCol = 1; return DL; } @@ -39,7 +39,7 @@ /// is not equal to the empty key or DebugLoc(). static DebugLoc getTombstoneKey() { DebugLoc DL; - DL.LineCol = -2; + DL.LineCol = 2; return DL; } From baldrick at free.fr Wed Apr 13 13:55:33 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 13 Apr 2011 18:55:33 -0000 Subject: [llvm-commits] [dragonegg] r129458 - /dragonegg/trunk/include/dragonegg/Internals.h Message-ID: <20110413185533.2761D2A6C12C@llvm.org> Author: baldrick Date: Wed Apr 13 13:55:32 2011 New Revision: 129458 URL: http://llvm.org/viewvc/llvm-project?rev=129458&view=rev Log: Declare DieAbjectly as being noreturn to get rid of some warnings. Modified: dragonegg/trunk/include/dragonegg/Internals.h Modified: dragonegg/trunk/include/dragonegg/Internals.h URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Internals.h?rev=129458&r1=129457&r2=129458&view=diff ============================================================================== --- dragonegg/trunk/include/dragonegg/Internals.h (original) +++ dragonegg/trunk/include/dragonegg/Internals.h Wed Apr 13 13:55:32 2011 @@ -112,14 +112,16 @@ /// DieAbjectly - An unrecoverable fatal error occurred - throw in the towel, /// give up the ghost, quit miserably. -inline void DieAbjectly(const char *Message) { +inline void LLVM_ATTRIBUTE_NORETURN DieAbjectly(const char *Message) { llvm_unreachable(Message); } -inline void DieAbjectly(const char *Message, union gimple_statement_d *stmt) { +inline void LLVM_ATTRIBUTE_NORETURN DieAbjectly(const char *Message, + union gimple_statement_d *stmt){ if (stmt) debug_gimple_stmt(stmt); DieAbjectly(Message); } -inline void DieAbjectly(const char *Message, union tree_node *exp) { +inline void LLVM_ATTRIBUTE_NORETURN DieAbjectly(const char *Message, + union tree_node *exp) { if (exp) debug_tree(exp); DieAbjectly(Message); } From baldrick at free.fr Wed Apr 13 14:01:39 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 13 Apr 2011 19:01:39 -0000 Subject: [llvm-commits] [dragonegg] r129459 - /dragonegg/trunk/src/Convert.cpp Message-ID: <20110413190139.360372A6C12C@llvm.org> Author: baldrick Date: Wed Apr 13 14:01:39 2011 New Revision: 129459 URL: http://llvm.org/viewvc/llvm-project?rev=129459&view=rev Log: Fix PR9664: confusion between in-memory type and in-register type. Modified: dragonegg/trunk/src/Convert.cpp Modified: dragonegg/trunk/src/Convert.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=129459&r1=129458&r2=129459&view=diff ============================================================================== --- dragonegg/trunk/src/Convert.cpp (original) +++ dragonegg/trunk/src/Convert.cpp Wed Apr 13 14:01:39 2011 @@ -5828,7 +5828,7 @@ // The result can be of a different pointer type even if we didn't advance it. Ref.Ptr = UselesslyTypeConvert(Ref.Ptr, - GetRegType(TREE_TYPE(exp))->getPointerTo()); + ConvertType(TREE_TYPE(exp))->getPointerTo()); return Ref; } From baldrick at free.fr Wed Apr 13 14:14:46 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 13 Apr 2011 19:14:46 -0000 Subject: [llvm-commits] [dragonegg] r129460 - /dragonegg/trunk/src/Convert.cpp Message-ID: <20110413191446.7DF1E2A6C12C@llvm.org> Author: baldrick Date: Wed Apr 13 14:14:46 2011 New Revision: 129460 URL: http://llvm.org/viewvc/llvm-project?rev=129460&view=rev Log: Add a description of what TARGET_MEM_REF computes. Modified: dragonegg/trunk/src/Convert.cpp Modified: dragonegg/trunk/src/Convert.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=129460&r1=129459&r2=129460&view=diff ============================================================================== --- dragonegg/trunk/src/Convert.cpp (original) +++ dragonegg/trunk/src/Convert.cpp Wed Apr 13 14:14:46 2011 @@ -5791,6 +5791,8 @@ LValue TreeToLLVM::EmitLV_TARGET_MEM_REF(tree exp) { // TODO: Take the address space into account. // TODO: Improve the alignment estimate. + + // The address is &symbol + base + index * step + offset. struct mem_address addr; get_address_description (exp, &addr); From dpatel at apple.com Wed Apr 13 14:41:17 2011 From: dpatel at apple.com (Devang Patel) Date: Wed, 13 Apr 2011 19:41:17 -0000 Subject: [llvm-commits] [llvm] r129461 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Message-ID: <20110413194117.A2FEF2A6C12C@llvm.org> Author: dpatel Date: Wed Apr 13 14:41:17 2011 New Revision: 129461 URL: http://llvm.org/viewvc/llvm-project?rev=129461&view=rev Log: Remove extra bytes that were added for gdb. We do not have good poiner to understand actual reason behind this fixme. Spot checking suggest that newer gdb does not need this. Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp?rev=129461&r1=129460&r2=129461&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Wed Apr 13 14:41:17 2011 @@ -2375,8 +2375,7 @@ unsigned ContentSize = Die->getSize() + sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section - sizeof(int8_t) + // Pointer Size (in bytes) - sizeof(int32_t); // FIXME - extra pad for gdb bug. + sizeof(int8_t); // Pointer Size (in bytes) Asm->OutStreamer.AddComment("Length of Compilation Unit Info"); Asm->EmitInt32(ContentSize); @@ -2389,12 +2388,6 @@ Asm->EmitInt8(Asm->getTargetData().getPointerSize()); emitDIE(Die); - // FIXME - extra padding for gdb bug. - Asm->OutStreamer.AddComment("4 extra padding bytes for GDB"); - Asm->EmitInt8(0); - Asm->EmitInt8(0); - Asm->EmitInt8(0); - Asm->EmitInt8(0); Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("info_end", TheCU->getID())); } } From johnny.chen at apple.com Wed Apr 13 14:46:06 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Apr 2011 19:46:06 -0000 Subject: [llvm-commits] [llvm] r129462 - in /llvm/trunk: lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt Message-ID: <20110413194606.257DC2A6C12C@llvm.org> Author: johnny Date: Wed Apr 13 14:46:05 2011 New Revision: 129462 URL: http://llvm.org/viewvc/llvm-project?rev=129462&view=rev Log: Check the corner cases for t2LDRSHi12 correctly and mark invalid encodings as such. rdar://problem/9276651 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129462&r1=129461&r2=129462&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Wed Apr 13 14:46:05 2011 @@ -1920,6 +1920,38 @@ DEBUG(errs() << "if t == 13 then UNPREDICTABLE\n"); return true; } + // A6.3.8 Load halfword, memory hints + const StringRef Name = ARMInsts[Opcode].Name; + if (Name.startswith("t2LDRH") || Name.startswith("t2LDRSH")) { + if (WB) { + if (R0 == R1) { + // A8.6.82 LDRSH (immediate) Encoding T2 + DEBUG(errs() << "if WB && n == t then UNPREDICTABLE\n"); + return true; + } + if (R0 == 15 && slice(insn, 10, 8) == 3) { + // A8.6.82 LDRSH (immediate) Encoding T2 (errata markup 8.0) + DEBUG(errs() << "if t == 15 && PUW == '011' then UNPREDICTABLE\n"); + return true; + } + } else { + if (Opcode == ARM::t2LDRHi8 || Opcode == ARM::t2LDRSHi8) { + if (R0 == 15 && slice(insn, 10, 8) == 4) { + // A8.6.82 LDRSH (immediate) Encoding T2 + DEBUG(errs() << "if Rt == '1111' and PUW == '100' then SEE" + << " \"Unallocated memory hints\"\n"); + return true; + } + } else { + if (R0 == 15) { + // A8.6.82 LDRSH (immediate) Encoding T1 + DEBUG(errs() << "if Rt == '1111' then SEE" + << " \"Unallocated memory hints\"\n"); + return true; + } + } + } + } } else { if (WB && R0 == R1) { DEBUG(errs() << "if wback && n == t then UNPREDICTABLE\n"); @@ -1998,7 +2030,7 @@ bool Imm12 = !ThreeReg && slice(insn, 23, 23) == 1; // ARMInstrThumb2.td // Build the register operands, followed by the immediate. - unsigned R0, R1, R2 = 0; + unsigned R0 = 0, R1 = 0, R2 = 0; unsigned Rd = decodeRd(insn); int Imm = 0; Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt?rev=129462&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt Wed Apr 13 14:46:05 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=1953 Name=t2LDRSHi12 Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 1| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 1: 1| 1: 1: 1: 1| 1: 0: 0: 0| 1: 1: 0: 1| 1: 1: 1: 1| +# ------------------------------------------------------------------------------------------------- +# +# if Rt = '1111' then SEE "Unallocated memory hints" +0xb3 0xf9 0xdf 0xf8 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt?rev=129462&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt Wed Apr 13 14:46:05 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=1954 Name=t2LDRSHi8 Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 1| 1: 0: 0: 1| 0: 0: 1: 1| 0: 1: 0: 1| 1: 1: 1: 1| 1: 1: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0| +# ------------------------------------------------------------------------------------------------- +# +# if Rt == '1111' and PUW == '100' then SEE "Unallocated memory hints" +0x35 0xf9 0x00 0xfc From dpatel at apple.com Wed Apr 13 14:47:41 2011 From: dpatel at apple.com (Devang Patel) Date: Wed, 13 Apr 2011 19:47:41 -0000 Subject: [llvm-commits] [llvm] r129463 - /llvm/trunk/lib/VMCore/DebugInfoProbe.cpp Message-ID: <20110413194741.5CF9E2A6C12C@llvm.org> Author: dpatel Date: Wed Apr 13 14:47:41 2011 New Revision: 129463 URL: http://llvm.org/viewvc/llvm-project?rev=129463&view=rev Log: Fix debug message. Modified: llvm/trunk/lib/VMCore/DebugInfoProbe.cpp Modified: llvm/trunk/lib/VMCore/DebugInfoProbe.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/DebugInfoProbe.cpp?rev=129463&r1=129462&r2=129463&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/DebugInfoProbe.cpp (original) +++ llvm/trunk/lib/VMCore/DebugInfoProbe.cpp Wed Apr 13 14:47:41 2011 @@ -135,7 +135,9 @@ E = LineNos.end(); I != E; ++I) { unsigned LineNo = *I; if (LineNos2.count(LineNo) == 0) { - DEBUG(dbgs() << "DebugInfoProbe: Losing dbg info intrinsic at line " << LineNo << "\n"); + DEBUG(dbgs() + << "DebugInfoProbe: Losing dbg info for source line " + << LineNo << "\n"); ++NumDbgLineLost; } } From gkistanova at gmail.com Wed Apr 13 15:31:32 2011 From: gkistanova at gmail.com (Galina Kistanova) Date: Wed, 13 Apr 2011 13:31:32 -0700 Subject: [llvm-commits] Few builds fail since yesterday Message-ID: Hello, Just short notice that several builds fail since yesterday. The fist failing builds for them: http://google1.osuosl.org:8011/builders/llvm-gcc-x86_64-darwin10-self-mingw32/builds/3274 http://google1.osuosl.org:8011/builders/build-self-4-mingw32/builds/2288 http://google1.osuosl.org:8011/builders/llvm-gcc-build-x86_64-darwin10-x-mingw32-x-armeabi/builds/778 http://google1.osuosl.org:8011/builders/llvm-gcc-native-mingw32/builds/1382 http://google1.osuosl.org:8011/builders/llvm-gcc-native-mingw32-win7/builds/1609 http://google1.osuosl.org:8011/builders/llvm-gcc-mingw32-cross-arm-linux-gnueabi-hard-float/builds/654 Thanks Galina From zwarich at apple.com Wed Apr 13 15:36:04 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Wed, 13 Apr 2011 20:36:04 -0000 Subject: [llvm-commits] [llvm] r129466 - in /llvm/trunk: lib/Target/TargetData.cpp test/CodeGen/X86/alignment.ll test/CodeGen/X86/unaligned-load.ll Message-ID: <20110413203604.9D78F2A6C12C@llvm.org> Author: zwarich Date: Wed Apr 13 15:36:04 2011 New Revision: 129466 URL: http://llvm.org/viewvc/llvm-project?rev=129466&view=rev Log: Fix a regression caused by r102515 where explicit alignment on globals is ignored. There was a test to catch this, but it was just blindly updated in a large change. This fixes another part of . Modified: llvm/trunk/lib/Target/TargetData.cpp llvm/trunk/test/CodeGen/X86/alignment.ll llvm/trunk/test/CodeGen/X86/unaligned-load.ll Modified: llvm/trunk/lib/Target/TargetData.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetData.cpp?rev=129466&r1=129465&r2=129466&view=diff ============================================================================== --- llvm/trunk/lib/Target/TargetData.cpp (original) +++ llvm/trunk/lib/Target/TargetData.cpp Wed Apr 13 15:36:04 2011 @@ -624,7 +624,7 @@ Alignment = std::max(GVAlignment, getABITypeAlignment(ElemType)); } - if (GV->hasInitializer()) { + if (GV->hasInitializer() && GVAlignment == 0) { if (Alignment < 16) { // If the global is not external, see if it is large. If so, give it a // larger alignment. Modified: llvm/trunk/test/CodeGen/X86/alignment.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/alignment.ll?rev=129466&r1=129465&r2=129466&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/alignment.ll (original) +++ llvm/trunk/test/CodeGen/X86/alignment.ll Wed Apr 13 15:36:04 2011 @@ -6,7 +6,7 @@ ; CHECK: .bss ; CHECK: .globl GlobalA -; CHECK: .align 16 +; CHECK: .align 8 ; CHECK: GlobalA: ; CHECK: .zero 384 @@ -15,12 +15,12 @@ ; PR6921 @GlobalB = common global { [384 x i8] } zeroinitializer, align 8 -; CHECK: .comm GlobalB,384,16 +; CHECK: .comm GlobalB,384,8 @GlobalC = common global { [384 x i8] } zeroinitializer, align 2 -; CHECK: .comm GlobalC,384,16 +; CHECK: .comm GlobalC,384,2 Modified: llvm/trunk/test/CodeGen/X86/unaligned-load.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/unaligned-load.ll?rev=129466&r1=129465&r2=129466&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/unaligned-load.ll (original) +++ llvm/trunk/test/CodeGen/X86/unaligned-load.ll Wed Apr 13 15:36:04 2011 @@ -29,8 +29,8 @@ declare void @llvm.memcpy.i64(i8* nocapture, i8* nocapture, i64, i32) nounwind ; CORE2: .section -; CORE2: .align 4 +; CORE2: .align 3 ; CORE2-NEXT: _.str1: ; CORE2-NEXT: .asciz "DHRYSTONE PROGRAM, SOME STRING" -; CORE2: .align 4 +; CORE2: .align 3 ; CORE2-NEXT: _.str3: From benny.kra at googlemail.com Wed Apr 13 15:41:43 2011 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Wed, 13 Apr 2011 20:41:43 -0000 Subject: [llvm-commits] [llvm] r129467 - /llvm/trunk/runtime/libprofile/LineProfiling.c Message-ID: <20110413204143.6F58E2A6C12C@llvm.org> Author: d0k Date: Wed Apr 13 15:41:43 2011 New Revision: 129467 URL: http://llvm.org/viewvc/llvm-project?rev=129467&view=rev Log: Fix format string warning. Modified: llvm/trunk/runtime/libprofile/LineProfiling.c Modified: llvm/trunk/runtime/libprofile/LineProfiling.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/runtime/libprofile/LineProfiling.c?rev=129467&r1=129466&r2=129467&view=diff ============================================================================== --- llvm/trunk/runtime/libprofile/LineProfiling.c (original) +++ llvm/trunk/runtime/libprofile/LineProfiling.c Wed Apr 13 15:41:43 2011 @@ -31,7 +31,7 @@ void llvm_prof_linectr_emit_counter(const char *dir, const char *file, uint32_t line, uint32_t column, uint64_t *counter) { - printf("%s/%s:%u:%u %ull\n", dir, file, line, column, + printf("%s/%s:%u:%u %llu\n", dir, file, line, column, (unsigned long long)(*counter)); } From zwarich at apple.com Wed Apr 13 16:01:19 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Wed, 13 Apr 2011 21:01:19 -0000 Subject: [llvm-commits] [llvm] r129468 - in /llvm/trunk: lib/Target/ARM/ARMISelLowering.cpp test/CodeGen/ARM/vbsl-constant.ll Message-ID: <20110413210119.8BAD02A6C12E@llvm.org> Author: zwarich Date: Wed Apr 13 16:01:19 2011 New Revision: 129468 URL: http://llvm.org/viewvc/llvm-project?rev=129468&view=rev Log: Fix a typo in an ARM-specific DAG combine. This fixes . Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp llvm/trunk/test/CodeGen/ARM/vbsl-constant.ll Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=129468&r1=129467&r2=129468&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Wed Apr 13 16:01:19 2011 @@ -5474,7 +5474,7 @@ EVT CanonicalVT = VT.is128BitVector() ? MVT::v4i32 : MVT::v2i32; SDValue Result = DAG.getNode(ARMISD::VBSL, dl, CanonicalVT, N0->getOperand(1), N0->getOperand(0), - N1->getOperand(1)); + N1->getOperand(0)); return DAG.getNode(ISD::BITCAST, dl, VT, Result); } } Modified: llvm/trunk/test/CodeGen/ARM/vbsl-constant.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vbsl-constant.ll?rev=129468&r1=129467&r2=129468&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/vbsl-constant.ll (original) +++ llvm/trunk/test/CodeGen/ARM/vbsl-constant.ll Wed Apr 13 16:01:19 2011 @@ -2,6 +2,8 @@ define <8 x i8> @v_bsli8(<8 x i8>* %A, <8 x i8>* %B, <8 x i8>* %C) nounwind { ;CHECK: v_bsli8: +;CHECK: vldr.64 +;CHECK: vldr.64 ;CHECK: vbsl %tmp1 = load <8 x i8>* %A %tmp2 = load <8 x i8>* %B @@ -14,6 +16,8 @@ define <4 x i16> @v_bsli16(<4 x i16>* %A, <4 x i16>* %B, <4 x i16>* %C) nounwind { ;CHECK: v_bsli16: +;CHECK: vldr.64 +;CHECK: vldr.64 ;CHECK: vbsl %tmp1 = load <4 x i16>* %A %tmp2 = load <4 x i16>* %B @@ -26,6 +30,8 @@ define <2 x i32> @v_bsli32(<2 x i32>* %A, <2 x i32>* %B, <2 x i32>* %C) nounwind { ;CHECK: v_bsli32: +;CHECK: vldr.64 +;CHECK: vldr.64 ;CHECK: vbsl %tmp1 = load <2 x i32>* %A %tmp2 = load <2 x i32>* %B @@ -38,6 +44,9 @@ define <1 x i64> @v_bsli64(<1 x i64>* %A, <1 x i64>* %B, <1 x i64>* %C) nounwind { ;CHECK: v_bsli64: +;CHECK: vldr.64 +;CHECK: vldr.64 +;CHECK: vldr.64 ;CHECK: vbsl %tmp1 = load <1 x i64>* %A %tmp2 = load <1 x i64>* %B @@ -50,6 +59,8 @@ define <16 x i8> @v_bslQi8(<16 x i8>* %A, <16 x i8>* %B, <16 x i8>* %C) nounwind { ;CHECK: v_bslQi8: +;CHECK: vldmia +;CHECK: vldmia ;CHECK: vbsl %tmp1 = load <16 x i8>* %A %tmp2 = load <16 x i8>* %B @@ -62,6 +73,8 @@ define <8 x i16> @v_bslQi16(<8 x i16>* %A, <8 x i16>* %B, <8 x i16>* %C) nounwind { ;CHECK: v_bslQi16: +;CHECK: vldmia +;CHECK: vldmia ;CHECK: vbsl %tmp1 = load <8 x i16>* %A %tmp2 = load <8 x i16>* %B @@ -74,6 +87,8 @@ define <4 x i32> @v_bslQi32(<4 x i32>* %A, <4 x i32>* %B, <4 x i32>* %C) nounwind { ;CHECK: v_bslQi32: +;CHECK: vldmia +;CHECK: vldmia ;CHECK: vbsl %tmp1 = load <4 x i32>* %A %tmp2 = load <4 x i32>* %B @@ -86,6 +101,9 @@ define <2 x i64> @v_bslQi64(<2 x i64>* %A, <2 x i64>* %B, <2 x i64>* %C) nounwind { ;CHECK: v_bslQi64: +;CHECK: vldmia +;CHECK: vldmia +;CHECK: vldmia ;CHECK: vbsl %tmp1 = load <2 x i64>* %A %tmp2 = load <2 x i64>* %B From johnny.chen at apple.com Wed Apr 13 16:04:32 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Apr 2011 21:04:32 -0000 Subject: [llvm-commits] [llvm] r129469 - in /llvm/trunk: lib/Target/ARM/ARMInstrThumb2.td lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt Message-ID: <20110413210433.02BE22A6C12E@llvm.org> Author: johnny Date: Wed Apr 13 16:04:32 2011 New Revision: 129469 URL: http://llvm.org/viewvc/llvm-project?rev=129469&view=rev Log: The LDR*T/STR*T (unpriviledged load/store) operations don't take SP or PC as Rt. rdar://problem/9279440 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=129469&r1=129468&r2=129469&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Wed Apr 13 16:04:32 2011 @@ -1381,7 +1381,7 @@ // for disassembly only. // Ref: A8.6.57 LDR (immediate, Thumb) Encoding T4 class T2IldT type, string opc, InstrItinClass ii> - : T2Ii8<(outs GPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, + : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, "\t$Rt, $addr", []> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; @@ -1472,7 +1472,7 @@ // only. // Ref: A8.6.193 STR (immediate, Thumb) Encoding T4 class T2IstT type, string opc, InstrItinClass ii> - : T2Ii8<(outs GPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, + : T2Ii8<(outs rGPR:$Rt), (ins t2addrmode_imm8:$addr), ii, opc, "\t$Rt, $addr", []> { let Inst{31-27} = 0b11111; let Inst{26-25} = 0b00; Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129469&r1=129468&r2=129469&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Wed Apr 13 16:04:32 2011 @@ -1909,6 +1909,8 @@ // Inst{22-21} encodes the data item transferred for load/store. // For single word, it is encoded as ob10. bool Word = (slice(insn, 22, 21) == 2); + bool Half = (slice(insn, 22, 21) == 1); + bool Byte = (slice(insn, 22, 21) == 0); if (UseRm && BadReg(R2)) { DEBUG(errs() << "if BadReg(m) then UNPREDICTABLE\n"); @@ -1920,9 +1922,15 @@ DEBUG(errs() << "if t == 13 then UNPREDICTABLE\n"); return true; } + if (Byte) { + if (WB && R0 == 15 && slice(insn, 10, 8) == 3) { + // A8.6.78 LDRSB (immediate) Encoding T2 (errata markup 8.0) + DEBUG(errs() << "if t == 15 && PUW == '011' then UNPREDICTABLE\n"); + return true; + } + } // A6.3.8 Load halfword, memory hints - const StringRef Name = ARMInsts[Opcode].Name; - if (Name.startswith("t2LDRH") || Name.startswith("t2LDRSH")) { + if (Half) { if (WB) { if (R0 == R1) { // A8.6.82 LDRSH (immediate) Encoding T2 @@ -2021,8 +2029,8 @@ OpIdx = 0; assert(NumOps >= 3 && - OpInfo[0].RegClass == ARM::GPRRegClassID && - OpInfo[1].RegClass == ARM::GPRRegClassID && + OpInfo[0].RegClass > 0 && + OpInfo[1].RegClass > 0 && "Expect >= 3 operands and first two as reg operands"); bool ThreeReg = (OpInfo[2].RegClass > 0); @@ -2061,10 +2069,10 @@ Imm = decodeImm8(insn); } - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, R0))); ++OpIdx; - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, + MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, R1))); ++OpIdx; Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt?rev=129469&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt Wed Apr 13 16:04:32 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=1922 Name=t2LDRBT Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 1| 1: 0: 0: 0| 0: 0: 0: 1| 0: 0: 0: 0| 1: 1: 1: 1| 1: 1: 1: 0| 0: 0: 0: 0| 0: 0: 1: 1| +# ------------------------------------------------------------------------------------------------- +# +# The unpriviledged Load/Store cannot have SP or PC as Rt. +0x10 0xf8 0x3 0xfe From johnny.chen at apple.com Wed Apr 13 16:35:49 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Apr 2011 21:35:49 -0000 Subject: [llvm-commits] [llvm] r129471 - in /llvm/trunk: lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110413213549.E77A32A6C12C@llvm.org> Author: johnny Date: Wed Apr 13 16:35:49 2011 New Revision: 129471 URL: http://llvm.org/viewvc/llvm-project?rev=129471&view=rev Log: Check for unallocated instruction encodings when disassembling Thumb Branch instructions (tBcc and t2Bcc). rdar://problem/9280470 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=129471&r1=129470&r2=129471&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Wed Apr 13 16:35:49 2011 @@ -3625,11 +3625,17 @@ // like ARM. // // A8.6.16 B - if (Name == "t2Bcc") - MI.addOperand(MCOperand::CreateImm(CondCode(slice(insn, 25, 22)))); - else if (Name == "tBcc") - MI.addOperand(MCOperand::CreateImm(CondCode(slice(insn, 11, 8)))); - else + // Check for undefined encodings. + unsigned cond; + if (Name == "t2Bcc") { + if ((cond = slice(insn, 25, 22)) >= 14) + return false; + MI.addOperand(MCOperand::CreateImm(CondCode(cond))); + } else if (Name == "tBcc") { + if ((cond = slice(insn, 11, 8)) == 14) + return false; + MI.addOperand(MCOperand::CreateImm(CondCode(cond))); + } else MI.addOperand(MCOperand::CreateImm(ARMCC::AL)); } else { // ARM instructions get their condition field from Inst{31-28}. Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt?rev=129471&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt Wed Apr 13 16:35:49 2011 @@ -0,0 +1,11 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=1894 Name=t2Bcc Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 1| 0: 1: 1: 1| 1: 0: 1: 0| 1: 1: 1: 1| 1: 0: 0: 0| 1: 0: 1: 1| 0: 1: 0: 0| 0: 1: 0: 0| +# ------------------------------------------------------------------------------------------------- +# +# A8.6.16 B +# if cond<3:1> == '111' then SEE "Related Encodings" +0xaf 0xf7 0x44 0x8b Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129471&r1=129470&r2=129471&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Wed Apr 13 16:35:49 2011 @@ -9,8 +9,8 @@ # CHECK: b #30 0x0f 0xe0 -# CHECK: b.w #-16 -0xff 0xf7 0xf8 0xaf +# CHECK: bgt.w #-16 +0x3f 0xf7 0xf8 0xaf # CHECK: bfi r2, r10, #0, #1 0x6a 0xf3 0x00 0x02 From wangmp at apple.com Wed Apr 13 16:40:02 2011 From: wangmp at apple.com (Mon P Wang) Date: Wed, 13 Apr 2011 21:40:02 -0000 Subject: [llvm-commits] [llvm] r129472 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/vector_promote.ll Message-ID: <20110413214002.89C1D2A6C12C@llvm.org> Author: wangmp Date: Wed Apr 13 16:40:02 2011 New Revision: 129472 URL: http://llvm.org/viewvc/llvm-project?rev=129472&view=rev Log: Vectors with different number of elements of the same element type can have the same allocation size but different primitive sizes(e.g., <3xi32> and <4xi32>). When ScalarRepl promotes them, it can't use a bit cast but should use a shuffle vector instead. Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=129472&r1=129471&r2=129472&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Wed Apr 13 16:40:02 2011 @@ -690,15 +690,45 @@ ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, uint64_t Offset, IRBuilder<> &Builder) { // If the load is of the whole new alloca, no conversion is needed. - if (FromVal->getType() == ToType && Offset == 0) + const Type *FromType = FromVal->getType(); + if (FromType == ToType && Offset == 0) return FromVal; // If the result alloca is a vector type, this is either an element // access or a bitcast to another vector type of the same size. - if (const VectorType *VTy = dyn_cast(FromVal->getType())) { + if (const VectorType *VTy = dyn_cast(FromType)) { unsigned ToTypeSize = TD.getTypeAllocSize(ToType); - if (ToTypeSize == AllocaSize) - return Builder.CreateBitCast(FromVal, ToType, "tmp"); + if (ToTypeSize == AllocaSize) { + if (FromType->getPrimitiveSizeInBits() == + ToType->getPrimitiveSizeInBits()) + return Builder.CreateBitCast(FromVal, ToType, "tmp"); + else { + // Vectors with the same element type can have the same allocation + // size but different primitive sizes (e.g., <3 x i32> and <4 x i32>) + // In this case, use a shuffle vector instead of a bit cast. + const VectorType *ToVTy = dyn_cast(ToType); + assert(ToVTy && (ToVTy->getElementType() == VTy->getElementType()) && + "Vectors must have the same element type"); + LLVMContext &Context = FromVal->getContext(); + Value *UnV = UndefValue::get(FromType); + unsigned numEltsFrom = VTy->getNumElements(); + unsigned numEltsTo = ToVTy->getNumElements(); + + SmallVector Args; + unsigned minNumElts = std::min(numEltsFrom, numEltsTo); + unsigned i; + for (i=0; i != minNumElts; ++i) + Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); + + if (i < numEltsTo) { + Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); + for (; i != numEltsTo; ++i) + Args.push_back(UnC); + } + Constant *Mask = ConstantVector::get(Args); + return Builder.CreateShuffleVector(FromVal, UnV, Mask, "tmpV"); + } + } if (ToType->isVectorTy()) { assert(isPowerOf2_64(AllocaSize / ToTypeSize) && @@ -837,8 +867,36 @@ // Changing the whole vector with memset or with an access of a different // vector type? - if (ValSize == VecSize) - return Builder.CreateBitCast(SV, AllocaType, "tmp"); + if (ValSize == VecSize) { + if (VTy->getPrimitiveSizeInBits() == + SV->getType()->getPrimitiveSizeInBits()) + return Builder.CreateBitCast(SV, AllocaType, "tmp"); + else { + // Vectors with the same element type can have the same allocation + // size but different primitive sizes (e.g., <3 x i32> and <4 x i32>) + // In this case, use a shuffle vector instead of a bit cast. + const VectorType *SVVTy = dyn_cast(SV->getType()); + assert(SVVTy && (SVVTy->getElementType() == VTy->getElementType()) && + "Vectors must have the same element type"); + Value *UnV = UndefValue::get(SVVTy); + unsigned numEltsFrom = SVVTy->getNumElements(); + unsigned numEltsTo = VTy->getNumElements(); + + SmallVector Args; + unsigned minNumElts = std::min(numEltsFrom, numEltsTo); + unsigned i; + for (i=0; i != minNumElts; ++i) + Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); + + if (i < numEltsTo) { + Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); + for (; i != numEltsTo; ++i) + Args.push_back(UnC); + } + Constant *Mask = ConstantVector::get(Args); + return Builder.CreateShuffleVector(SV, UnV, Mask, "tmpV"); + } + } if (SV->getType()->isVectorTy() && isPowerOf2_64(VecSize / ValSize)) { assert(Offset == 0 && "Can't insert a value of a smaller vector type at " Modified: llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll?rev=129472&r1=129471&r2=129472&view=diff ============================================================================== --- llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll (original) +++ llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll Wed Apr 13 16:40:02 2011 @@ -202,3 +202,49 @@ ; CHECK-NOT: alloca ; CHECK: bitcast <4 x float> %x to i128 } + +define <3 x float> @test14(<3 x float> %x) { +entry: + %x.addr = alloca <3 x float>, align 16 + %r = alloca <3 x i32>, align 16 + %extractVec = shufflevector <3 x float> %x, <3 x float> undef, <4 x i32> + %storetmp = bitcast <3 x float>* %x.addr to <4 x float>* + store <4 x float> %extractVec, <4 x float>* %storetmp, align 16 + %tmp = load <3 x float>* %x.addr, align 16 + %cmp = fcmp une <3 x float> %tmp, zeroinitializer + %sext = sext <3 x i1> %cmp to <3 x i32> + %and = and <3 x i32> , %sext + %extractVec1 = shufflevector <3 x i32> %and, <3 x i32> undef, <4 x i32> + %storetmp2 = bitcast <3 x i32>* %r to <4 x i32>* + store <4 x i32> %extractVec1, <4 x i32>* %storetmp2, align 16 + %tmp3 = load <3 x i32>* %r, align 16 + %0 = bitcast <3 x i32> %tmp3 to <3 x float> + %tmp4 = load <3 x float>* %x.addr, align 16 + ret <3 x float> %tmp4 +; CHECK: @test14 +; CHECK-NOT: alloca +; CHECK: shufflevector <4 x i32> %extractVec1, <4 x i32> undef, <3 x i32> +} + +define void @test15(<3 x i64>* sret %agg.result, <3 x i64> %x, <3 x i64> %min) { +entry: + %x.addr = alloca <3 x i64>, align 32 + %min.addr = alloca <3 x i64>, align 32 + %extractVec = shufflevector <3 x i64> %x, <3 x i64> undef, <4 x i32> + %storetmp = bitcast <3 x i64>* %x.addr to <4 x i64>* + store <4 x i64> %extractVec, <4 x i64>* %storetmp, align 32 + %extractVec1 = shufflevector <3 x i64> %min, <3 x i64> undef, <4 x i32> + %storetmp2 = bitcast <3 x i64>* %min.addr to <4 x i64>* + store <4 x i64> %extractVec1, <4 x i64>* %storetmp2, align 32 + %tmp = load <3 x i64>* %x.addr + %tmp5 = extractelement <3 x i64> %tmp, i32 0 + %tmp11 = insertelement <3 x i64> %tmp, i64 %tmp5, i32 0 + store <3 x i64> %tmp11, <3 x i64>* %x.addr + %tmp30 = load <3 x i64>* %x.addr, align 32 + store <3 x i64> %tmp30, <3 x i64>* %agg.result + ret void +; CHECK: @test15 +; CHECK-NOT: alloca +; CHECK: shufflevector <4 x i64> %tmpV2, <4 x i64> undef, <3 x i32> +} + From johnny.chen at apple.com Wed Apr 13 16:59:01 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Wed, 13 Apr 2011 21:59:01 -0000 Subject: [llvm-commits] [llvm] r129480 - in /llvm/trunk: lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110413215901.D448D2A6C12C@llvm.org> Author: johnny Date: Wed Apr 13 16:59:01 2011 New Revision: 129480 URL: http://llvm.org/viewvc/llvm-project?rev=129480&view=rev Log: Thumb disassembler did not handle tBRIND (indirect branch) properly. rdar://problem/9280370 Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129480&r1=129479&r2=129480&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Wed Apr 13 16:59:01 2011 @@ -479,6 +479,7 @@ // tBX_RET: 0 operand // tBX_RET_vararg: Rm // tBLXr_r9: Rm +// tBRIND: Rm static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { @@ -486,14 +487,17 @@ if (NumOps == 0) return true; - // BX/BLX has 1 reg operand: Rm. - if (Opcode == ARM::tBLXr_r9 || Opcode == ARM::tBX_Rm) { - // Handling the two predicate operands before the reg operand. - if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps)) - return false; + // BX/BLX/tBRIND (indirect branch, i.e, mov pc, Rm) has 1 reg operand: Rm. + if (Opcode==ARM::tBLXr_r9 || Opcode==ARM::tBX_Rm || Opcode==ARM::tBRIND) { + if (Opcode != ARM::tBRIND) { + // Handling the two predicate operands before the reg operand. + if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps)) + return false; + NumOpsAdded += 2; + } MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, getT1Rm(insn)))); - NumOpsAdded = 3; + NumOpsAdded += 1; return true; } Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129480&r1=129479&r2=129480&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Wed Apr 13 16:59:01 2011 @@ -244,3 +244,6 @@ # CHECK: mov.w r3, #4294967295 0x4f 0xf0 0xff 0x33 + +# CHECK: mov pc, sp +0xef 0x46 From resistor at mac.com Wed Apr 13 18:22:23 2011 From: resistor at mac.com (Owen Anderson) Date: Wed, 13 Apr 2011 23:22:23 -0000 Subject: [llvm-commits] [llvm] r129484 - /llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Message-ID: <20110413232223.CCAB82A6C12C@llvm.org> Author: resistor Date: Wed Apr 13 18:22:23 2011 New Revision: 129484 URL: http://llvm.org/viewvc/llvm-project?rev=129484&view=rev Log: During post-legalization DAG combining, be careful to only create shifts where the RHS is of the legal type for the new operation. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=129484&r1=129483&r2=129484&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Wed Apr 13 18:22:23 2011 @@ -1678,6 +1678,13 @@ ConstantSDNode *ShAmt = dyn_cast(In.getOperand(1)); if (!ShAmt) break; + SDValue Shift = In.getOperand(1); + if (TLO.LegalTypes()) { + uint64_t ShVal = ShAmt->getZExtValue(); + Shift = + TLO.DAG.getConstant(ShVal, getShiftAmountTy(Op.getValueType())); + } + APInt HighBits = APInt::getHighBitsSet(OperandBitWidth, OperandBitWidth - BitWidth); HighBits = HighBits.lshr(ShAmt->getZExtValue()).trunc(BitWidth); @@ -1691,7 +1698,7 @@ return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::SRL, dl, Op.getValueType(), NewTrunc, - In.getOperand(1))); + Shift)); } break; } From isanbard at gmail.com Wed Apr 13 18:36:21 2011 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 13 Apr 2011 23:36:21 -0000 Subject: [llvm-commits] [llvm] r129485 - in /llvm/trunk: include/llvm/Target/Target.td lib/Target/X86/X86InstrInfo.td utils/TableGen/AsmWriterEmitter.cpp Message-ID: <20110413233621.DA8CE2A6C12C@llvm.org> Author: void Date: Wed Apr 13 18:36:21 2011 New Revision: 129485 URL: http://llvm.org/viewvc/llvm-project?rev=129485&view=rev Log: Add an option to not print the alias of an instruction. It defaults to "print the alias". Modified: llvm/trunk/include/llvm/Target/Target.td llvm/trunk/lib/Target/X86/X86InstrInfo.td llvm/trunk/utils/TableGen/AsmWriterEmitter.cpp Modified: llvm/trunk/include/llvm/Target/Target.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=129485&r1=129484&r2=129485&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/Target.td (original) +++ llvm/trunk/include/llvm/Target/Target.td Wed Apr 13 18:36:21 2011 @@ -591,9 +591,10 @@ /// InstAlias - This defines an alternate assembly syntax that is allowed to /// match an instruction that has a different (more canonical) assembly /// representation. -class InstAlias { +class InstAlias { string AsmString = Asm; // The .s format to match the instruction with. dag ResultInst = Result; // The MCInst to generate. + bit EmitAlias = Emit; // Emit the alias instead of what's aliased. // Predicates - Predicates that must be true for this to match. list Predicates = []; Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=129485&r1=129484&r2=129485&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Wed Apr 13 18:36:21 2011 @@ -1534,8 +1534,10 @@ def : InstAlias<"movq $imm, $reg", (MOV64ri GR64:$reg, i64imm:$imm)>; // Match 'movq GR64, MMX' as an alias for movd. -def : InstAlias<"movq $src, $dst", (MMX_MOVD64to64rr VR64:$dst, GR64:$src)>; -def : InstAlias<"movq $src, $dst", (MMX_MOVD64from64rr GR64:$dst, VR64:$src)>; +def : InstAlias<"movq $src, $dst", + (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0b0>; +def : InstAlias<"movq $src, $dst", + (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0b0>; // movsd with no operands (as opposed to the SSE scalar move of a double) is an // alias for movsl. (as in rep; movsd) Modified: llvm/trunk/utils/TableGen/AsmWriterEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/AsmWriterEmitter.cpp?rev=129485&r1=129484&r2=129485&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/AsmWriterEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/AsmWriterEmitter.cpp Wed Apr 13 18:36:21 2011 @@ -840,6 +840,8 @@ I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); const Record *R = *I; + if (!R->getValueAsBit("EmitAlias")) + continue; // We were told not to emit the alias, but to emit the aliasee. const DagInit *DI = R->getValueAsDag("ResultInst"); const DefInit *Op = dynamic_cast(DI->getOperator()); AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); From eli.friedman at gmail.com Wed Apr 13 19:18:57 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 13 Apr 2011 17:18:57 -0700 Subject: [llvm-commits] [llvm] r129472 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/vector_promote.ll In-Reply-To: <20110413214002.89C1D2A6C12C@llvm.org> References: <20110413214002.89C1D2A6C12C@llvm.org> Message-ID: On Wed, Apr 13, 2011 at 2:40 PM, Mon P Wang wrote: > Author: wangmp > Date: Wed Apr 13 16:40:02 2011 > New Revision: 129472 > > URL: http://llvm.org/viewvc/llvm-project?rev=129472&view=rev > Log: > Vectors with different number of elements of the same element type can have > the same allocation size but different primitive sizes(e.g., <3xi32> and > <4xi32>). ?When ScalarRepl promotes them, it can't use a bit cast but > should use a shuffle vector instead. > > Modified: > ? ?llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp > ? ?llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll > > Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=129472&r1=129471&r2=129472&view=diff > ============================================================================== > --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) > +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Wed Apr 13 16:40:02 2011 > @@ -690,15 +690,45 @@ > ?ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, > ? ? ? ? ? ? ? ? ? ? ? ? ? ?uint64_t Offset, IRBuilder<> &Builder) { > ? // If the load is of the whole new alloca, no conversion is needed. > - ?if (FromVal->getType() == ToType && Offset == 0) > + ?const Type *FromType = FromVal->getType(); > + ?if (FromType == ToType && Offset == 0) > ? ? return FromVal; > > ? // If the result alloca is a vector type, this is either an element > ? // access or a bitcast to another vector type of the same size. > - ?if (const VectorType *VTy = dyn_cast(FromVal->getType())) { > + ?if (const VectorType *VTy = dyn_cast(FromType)) { > ? ? unsigned ToTypeSize = TD.getTypeAllocSize(ToType); > - ? ?if (ToTypeSize == AllocaSize) > - ? ? ?return Builder.CreateBitCast(FromVal, ToType, "tmp"); > + ? ?if (ToTypeSize == AllocaSize) { > + ? ? ?if (FromType->getPrimitiveSizeInBits() == > + ? ? ? ? ?ToType->getPrimitiveSizeInBits()) > + ? ? ? ?return Builder.CreateBitCast(FromVal, ToType, "tmp"); > + ? ? ?else { > + ? ? ? ?// Vectors with the same element type can have the same allocation > + ? ? ? ?// size but different primitive sizes (e.g., <3 x i32> and <4 x i32>) > + ? ? ? ?// In this case, use a shuffle vector instead of a bit cast. > + ? ? ? ?const VectorType *ToVTy = dyn_cast(ToType); > + ? ? ? ?assert(ToVTy && (ToVTy->getElementType() == VTy->getElementType()) && > + ? ? ? ? ? ? ? "Vectors must have the same element type"); > + ? ? ? ?LLVMContext &Context = FromVal->getContext(); > + ? ? ? ?Value *UnV = UndefValue::get(FromType); > + ? ? ? ?unsigned numEltsFrom = VTy->getNumElements(); > + ? ? ? ?unsigned numEltsTo = ToVTy->getNumElements(); > + > + ? ? ? ?SmallVector Args; > + ? ? ? ?unsigned minNumElts = std::min(numEltsFrom, numEltsTo); > + ? ? ? ?unsigned i; > + ? ? ? ?for (i=0; i != minNumElts; ++i) > + ? ? ? ? ?Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); > + > + ? ? ? ?if (i < numEltsTo) { > + ? ? ? ? ?Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); > + ? ? ? ? ?for (; i != numEltsTo; ++i) > + ? ? ? ? ? ?Args.push_back(UnC); > + ? ? ? ?} > + ? ? ? ?Constant *Mask = ConstantVector::get(Args); > + ? ? ? ?return Builder.CreateShuffleVector(FromVal, UnV, Mask, "tmpV"); > + ? ? ?} > + ? ?} > > ? ? if (ToType->isVectorTy()) { > ? ? ? assert(isPowerOf2_64(AllocaSize / ToTypeSize) && > @@ -837,8 +867,36 @@ > > ? ? // Changing the whole vector with memset or with an access of a different > ? ? // vector type? > - ? ?if (ValSize == VecSize) > - ? ? ?return Builder.CreateBitCast(SV, AllocaType, "tmp"); > + ? ?if (ValSize == VecSize) { > + ? ? ?if (VTy->getPrimitiveSizeInBits() == > + ? ? ? ? ?SV->getType()->getPrimitiveSizeInBits()) > + ? ? ? ?return Builder.CreateBitCast(SV, AllocaType, "tmp"); > + ? ? ?else { > + ? ? ? ?// Vectors with the same element type can have the same allocation > + ? ? ? ?// size but different primitive sizes (e.g., <3 x i32> and <4 x i32>) > + ? ? ? ?// In this case, use a shuffle vector instead of a bit cast. > + ? ? ? ?const VectorType *SVVTy = dyn_cast(SV->getType()); > + ? ? ? ?assert(SVVTy && (SVVTy->getElementType() == VTy->getElementType()) && > + ? ? ? ? ? ? ? "Vectors must have the same element type"); > + ? ? ? ?Value *UnV = UndefValue::get(SVVTy); > + ? ? ? ?unsigned numEltsFrom = SVVTy->getNumElements(); > + ? ? ? ?unsigned numEltsTo = VTy->getNumElements(); > + > + ? ? ? ?SmallVector Args; > + ? ? ? ?unsigned minNumElts = std::min(numEltsFrom, numEltsTo); > + ? ? ? ?unsigned i; > + ? ? ? ?for (i=0; i != minNumElts; ++i) > + ? ? ? ? ?Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); > + > + ? ? ? ?if (i < numEltsTo) { > + ? ? ? ? ?Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); > + ? ? ? ? ?for (; i != numEltsTo; ++i) > + ? ? ? ? ? ?Args.push_back(UnC); > + ? ? ? ?} > + ? ? ? ?Constant *Mask = ConstantVector::get(Args); > + ? ? ? ?return Builder.CreateShuffleVector(SV, UnV, Mask, "tmpV"); > + ? ? ?} > + ? ?} > > ? ? if (SV->getType()->isVectorTy() && isPowerOf2_64(VecSize / ValSize)) { > ? ? ? assert(Offset == 0 && "Can't insert a value of a smaller vector type at " Can you refactor the duplicated code into a helper routine? -Eli > Modified: llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll?rev=129472&r1=129471&r2=129472&view=diff > ============================================================================== > --- llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll (original) > +++ llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll Wed Apr 13 16:40:02 2011 > @@ -202,3 +202,49 @@ > ?; CHECK-NOT: alloca > ?; CHECK: bitcast <4 x float> %x to i128 > ?} > + > +define <3 x float> @test14(<3 x float> %x) ?{ > +entry: > + ?%x.addr = alloca <3 x float>, align 16 > + ?%r = alloca <3 x i32>, align 16 > + ?%extractVec = shufflevector <3 x float> %x, <3 x float> undef, <4 x i32> > + ?%storetmp = bitcast <3 x float>* %x.addr to <4 x float>* > + ?store <4 x float> %extractVec, <4 x float>* %storetmp, align 16 > + ?%tmp = load <3 x float>* %x.addr, align 16 > + ?%cmp = fcmp une <3 x float> %tmp, zeroinitializer > + ?%sext = sext <3 x i1> %cmp to <3 x i32> > + ?%and = and <3 x i32> , %sext > + ?%extractVec1 = shufflevector <3 x i32> %and, <3 x i32> undef, <4 x i32> > + ?%storetmp2 = bitcast <3 x i32>* %r to <4 x i32>* > + ?store <4 x i32> %extractVec1, <4 x i32>* %storetmp2, align 16 > + ?%tmp3 = load <3 x i32>* %r, align 16 > + ?%0 = bitcast <3 x i32> %tmp3 to <3 x float> > + ?%tmp4 = load <3 x float>* %x.addr, align 16 > + ?ret <3 x float> %tmp4 > +; CHECK: @test14 > +; CHECK-NOT: alloca > +; CHECK: shufflevector <4 x i32> %extractVec1, <4 x i32> undef, <3 x i32> > +} > + > +define void @test15(<3 x i64>* sret %agg.result, <3 x i64> %x, <3 x i64> %min) { > +entry: > + ?%x.addr = alloca <3 x i64>, align 32 > + ?%min.addr = alloca <3 x i64>, align 32 > + ?%extractVec = shufflevector <3 x i64> %x, <3 x i64> undef, <4 x i32> > + ?%storetmp = bitcast <3 x i64>* %x.addr to <4 x i64>* > + ?store <4 x i64> %extractVec, <4 x i64>* %storetmp, align 32 > + ?%extractVec1 = shufflevector <3 x i64> %min, <3 x i64> undef, <4 x i32> > + ?%storetmp2 = bitcast <3 x i64>* %min.addr to <4 x i64>* > + ?store <4 x i64> %extractVec1, <4 x i64>* %storetmp2, align 32 > + ?%tmp = load <3 x i64>* %x.addr > + ?%tmp5 = extractelement <3 x i64> %tmp, i32 0 > + ?%tmp11 = insertelement <3 x i64> %tmp, i64 %tmp5, i32 0 > + ?store <3 x i64> %tmp11, <3 x i64>* %x.addr > + ?%tmp30 = load <3 x i64>* %x.addr, align 32 > + ?store <3 x i64> %tmp30, <3 x i64>* %agg.result > + ?ret void > +; CHECK: @test15 > +; CHECK-NOT: alloca > +; CHECK: shufflevector <4 x i64> %tmpV2, <4 x i64> undef, <3 x i32> > +} > + > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From kledzik at apple.com Wed Apr 13 19:39:01 2011 From: kledzik at apple.com (Nick Kledzik) Date: Thu, 14 Apr 2011 00:39:01 -0000 Subject: [llvm-commits] [compiler-rt] r129487 - /compiler-rt/trunk/make/platform/darwin_bni.mk Message-ID: <20110414003901.53B0B2A6C12C@llvm.org> Author: kledzik Date: Wed Apr 13 19:39:01 2011 New Revision: 129487 URL: http://llvm.org/viewvc/llvm-project?rev=129487&view=rev Log: enable CC.Release to be used always Modified: compiler-rt/trunk/make/platform/darwin_bni.mk Modified: compiler-rt/trunk/make/platform/darwin_bni.mk URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/make/platform/darwin_bni.mk?rev=129487&r1=129486&r2=129487&view=diff ============================================================================== --- compiler-rt/trunk/make/platform/darwin_bni.mk (original) +++ compiler-rt/trunk/make/platform/darwin_bni.mk Wed Apr 13 19:39:01 2011 @@ -9,6 +9,8 @@ UniversalArchs := $(RC_ARCHS) ifeq (,$(SDKROOT)) + CC.Release := $(CC) + CC.Static := $(CC) else CC.Release := /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/cc CC.Static := /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/cc From kledzik at apple.com Wed Apr 13 19:40:21 2011 From: kledzik at apple.com (Nick Kledzik) Date: Thu, 14 Apr 2011 00:40:21 -0000 Subject: [llvm-commits] [compiler-rt] r129489 - /compiler-rt/trunk/lib/apple_versioning.c Message-ID: <20110414004021.229C52A6C12C@llvm.org> Author: kledzik Date: Wed Apr 13 19:40:20 2011 New Revision: 129489 URL: http://llvm.org/viewvc/llvm-project?rev=129489&view=rev Log: don't add version info for static library Modified: compiler-rt/trunk/lib/apple_versioning.c Modified: compiler-rt/trunk/lib/apple_versioning.c URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/apple_versioning.c?rev=129489&r1=129488&r2=129489&view=diff ============================================================================== --- compiler-rt/trunk/lib/apple_versioning.c (original) +++ compiler-rt/trunk/lib/apple_versioning.c Wed Apr 13 19:40:20 2011 @@ -143,7 +143,7 @@ NOT_HERE_BEFORE_10_6(__trampoline_setup) #endif /* __ppc__ */ -#if __arm__ +#if __arm__ && __DYNAMIC__ #define NOT_HERE_UNTIL_AFTER_4_3(sym) \ extern const char sym##_tmp1 __asm("$ld$hide$os3.0$_" #sym ); \ __attribute__((visibility("default"))) const char sym##_tmp1 = 0; \ @@ -278,7 +278,7 @@ NOT_HERE_UNTIL_AFTER_4_3(__divmodsi4) NOT_HERE_UNTIL_AFTER_4_3(__udivmodsi4) -#endif +#endif // __arm__ && __DYNAMIC__ From kledzik at apple.com Wed Apr 13 19:45:02 2011 From: kledzik at apple.com (Nick Kledzik) Date: Thu, 14 Apr 2011 00:45:02 -0000 Subject: [llvm-commits] [compiler-rt] r129492 - /compiler-rt/trunk/make/AppleBI.mk Message-ID: <20110414004502.267B72A6C12C@llvm.org> Author: kledzik Date: Wed Apr 13 19:45:01 2011 New Revision: 129492 URL: http://llvm.org/viewvc/llvm-project?rev=129492&view=rev Log: install an archive for dyld and fix missing -static Modified: compiler-rt/trunk/make/AppleBI.mk Modified: compiler-rt/trunk/make/AppleBI.mk URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/make/AppleBI.mk?rev=129492&r1=129491&r2=129492&view=diff ============================================================================== --- compiler-rt/trunk/make/AppleBI.mk (original) +++ compiler-rt/trunk/make/AppleBI.mk Wed Apr 13 19:45:01 2011 @@ -19,8 +19,8 @@ INSTALL_TARGET = install-iOS CFLAGS.Release.armv6 := $(CFLAGS) -Wall -Os -fomit-frame-pointer -g -isysroot $(SDKROOT) CFLAGS.Release.armv7 := $(CFLAGS) -Wall -Os -fomit-frame-pointer -g -isysroot $(SDKROOT) - CFLAGS.Static.armv6 := $(CFLAGS) -Wall -Os -fomit-frame-pointer -g -isysroot $(SDKROOT) - CFLAGS.Static.armv7 := $(CFLAGS) -Wall -Os -fomit-frame-pointer -g -isysroot $(SDKROOT) + CFLAGS.Static.armv6 := $(CFLAGS) -Wall -Os -fomit-frame-pointer -g -isysroot $(SDKROOT) -static + CFLAGS.Static.armv7 := $(CFLAGS) -Wall -Os -fomit-frame-pointer -g -isysroot $(SDKROOT) -static LD_OTHER_FLAGS = -Wl,-alias_list,$(SRCROOT)/lib/arm/softfloat-alias.list -isysroot $(SDKROOT) endif @@ -43,7 +43,11 @@ install: $(INSTALL_TARGET) # Copy results to DSTROOT. -install-MacOSX : $(SYMROOT)/libcompiler_rt.dylib +install-MacOSX : $(SYMROOT)/libcompiler_rt.dylib \ + $(SYMROOT)/libcompiler_rt-dyld.a + mkdir -p $(DSTROOT)/usr/local/lib/dyld + cp $(SYMROOT)/libcompiler_rt-dyld.a \ + $(DSTROOT)/usr/local/lib/dyld/libcompiler_rt.a mkdir -p $(DSTROOT)/usr/lib/system strip -S $(SYMROOT)/libcompiler_rt.dylib \ -o $(DSTROOT)/usr/lib/system/libcompiler_rt.dylib @@ -70,10 +74,14 @@ # Copy results to DSTROOT. install-iOS: $(SYMROOT)/libcompiler_rt-static.a \ + $(SYMROOT)/libcompiler_rt-dyld.a \ $(SYMROOT)/libcompiler_rt.dylib mkdir -p $(DSTROOT)/usr/local/lib cp $(SYMROOT)/libcompiler_rt-static.a \ $(DSTROOT)/usr/local/lib/libcompiler_rt-static.a + mkdir -p $(DSTROOT)/usr/local/lib/dyld + cp $(SYMROOT)/libcompiler_rt-dyld.a \ + $(DSTROOT)/usr/local/lib/dyld/libcompiler_rt.a mkdir -p $(DSTROOT)/usr/lib/system strip -S $(SYMROOT)/libcompiler_rt.dylib \ -o $(DSTROOT)/usr/lib/system/libcompiler_rt.dylib @@ -84,3 +92,16 @@ $(OBJROOT)/darwin_bni/Static/$(arch)/libcompiler_rt.a) lipo -create $^ -o $@ +# rule to make each archive slice for dyld +$(OBJROOT)/libcompiler_rt-dyld-%.a : $(OBJROOT)/darwin_bni/Release/%/libcompiler_rt.a + cp $^ $@ + ar -d $@ apple_versioning.o + ar -d $@ gcc_personality_v0.o + ar -d $@ eprintf.o + ranlib $@ + +# rule to make make archive for dyld +$(SYMROOT)/libcompiler_rt-dyld.a : $(foreach arch,$(RC_ARCHS), \ + $(OBJROOT)/libcompiler_rt-dyld-$(arch).a) + lipo -create $^ -o $@ + From kledzik at apple.com Wed Apr 13 19:47:01 2011 From: kledzik at apple.com (Nick Kledzik) Date: Thu, 14 Apr 2011 00:47:01 -0000 Subject: [llvm-commits] [compiler-rt] r129494 - /compiler-rt/tags/Apple/Libcompiler_rt-16/ Message-ID: <20110414004701.D7EF02A6C12C@llvm.org> Author: kledzik Date: Wed Apr 13 19:47:01 2011 New Revision: 129494 URL: http://llvm.org/viewvc/llvm-project?rev=129494&view=rev Log: Libcompiler_rt-16 Added: compiler-rt/tags/Apple/Libcompiler_rt-16/ - copied from r129493, compiler-rt/trunk/ From isanbard at gmail.com Wed Apr 13 20:11:51 2011 From: isanbard at gmail.com (Bill Wendling) Date: Thu, 14 Apr 2011 01:11:51 -0000 Subject: [llvm-commits] [llvm] r129497 - in /llvm/trunk: lib/Target/X86/ lib/Target/X86/InstPrinter/ test/CodeGen/X86/ test/MC/X86/ Message-ID: <20110414011151.BBACC2A6C12C@llvm.org> Author: void Date: Wed Apr 13 20:11:51 2011 New Revision: 129497 URL: http://llvm.org/viewvc/llvm-project?rev=129497&view=rev Log: Have the X86 back-end emit the alias instead of what's being aliased. In most cases, it's much nicer and more informative reading the alias. Modified: llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp llvm/trunk/lib/Target/X86/X86InstrInfo.td llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll llvm/trunk/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll llvm/trunk/test/CodeGen/X86/anyext.ll llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll llvm/trunk/test/CodeGen/X86/bool-zext.ll llvm/trunk/test/CodeGen/X86/cmov.ll llvm/trunk/test/CodeGen/X86/cmp.ll llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll llvm/trunk/test/CodeGen/X86/fp-stack-compare.ll llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll llvm/trunk/test/CodeGen/X86/h-registers-0.ll llvm/trunk/test/CodeGen/X86/h-registers-2.ll llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll llvm/trunk/test/CodeGen/X86/pr3366.ll llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll llvm/trunk/test/CodeGen/X86/promote-i16.ll llvm/trunk/test/CodeGen/X86/select.ll llvm/trunk/test/CodeGen/X86/setcc.ll llvm/trunk/test/CodeGen/X86/sext-ret-val.ll llvm/trunk/test/CodeGen/X86/sext-subreg.ll llvm/trunk/test/CodeGen/X86/shl_elim.ll llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll llvm/trunk/test/CodeGen/X86/vshift-4.ll llvm/trunk/test/CodeGen/X86/widen_conv-2.ll llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll llvm/trunk/test/MC/X86/x86-32.s llvm/trunk/test/MC/X86/x86-64.s Modified: llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp (original) +++ llvm/trunk/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp Wed Apr 13 20:11:51 2011 @@ -42,7 +42,8 @@ } void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) { - printInstruction(MI, OS); + if (printAliasInstr(MI, OS)) + printInstruction(MI, OS); // If verbose assembly is enabled, we can print some informative comments. if (CommentStream) Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Wed Apr 13 20:11:51 2011 @@ -1437,7 +1437,7 @@ // Various unary fpstack operations default to operating on on ST1. // For example, "fxch" -> "fxch %st(1)" -def : InstAlias<"faddp", (ADD_FPrST0 ST1)>; +def : InstAlias<"faddp", (ADD_FPrST0 ST1), 0>; def : InstAlias<"fsubp", (SUBR_FPrST0 ST1)>; def : InstAlias<"fsubrp", (SUB_FPrST0 ST1)>; def : InstAlias<"fmulp", (MUL_FPrST0 ST1)>; @@ -1455,13 +1455,15 @@ // For example, "fadd %st(4), %st(0)" -> "fadd %st(4)". We also disambiguate // instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with // gas. -multiclass FpUnaryAlias { - def : InstAlias; - def : InstAlias; +multiclass FpUnaryAlias { + def : InstAlias; + def : InstAlias; } defm : FpUnaryAlias<"fadd", ADD_FST0r>; -defm : FpUnaryAlias<"faddp", ADD_FPrST0>; +defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; defm : FpUnaryAlias<"fsub", SUB_FST0r>; defm : FpUnaryAlias<"fsubp", SUBR_FPrST0>; defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; @@ -1472,8 +1474,8 @@ defm : FpUnaryAlias<"fdivp", DIVR_FPrST0>; defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; defm : FpUnaryAlias<"fdivrp", DIV_FPrST0>; -defm : FpUnaryAlias<"fcomi", COM_FIr>; -defm : FpUnaryAlias<"fucomi", UCOM_FIr>; +defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; +defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; defm : FpUnaryAlias<"fcompi", COM_FIPr>; defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; @@ -1481,7 +1483,7 @@ // Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they // commute. We also allow fdiv[r]p/fsubrp even though they don't commute, // solely because gas supports it. -def : InstAlias<"faddp %st(0), $op", (ADD_FPrST0 RST:$op)>; +def : InstAlias<"faddp %st(0), $op", (ADD_FPrST0 RST:$op), 0>; def : InstAlias<"fmulp %st(0), $op", (MUL_FPrST0 RST:$op)>; def : InstAlias<"fsubrp %st(0), $op", (SUB_FPrST0 RST:$op)>; def : InstAlias<"fdivp %st(0), $op", (DIVR_FPrST0 RST:$op)>; @@ -1535,9 +1537,9 @@ // Match 'movq GR64, MMX' as an alias for movd. def : InstAlias<"movq $src, $dst", - (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0b0>; + (MMX_MOVD64to64rr VR64:$dst, GR64:$src), 0>; def : InstAlias<"movq $src, $dst", - (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0b0>; + (MMX_MOVD64from64rr GR64:$dst, VR64:$src), 0>; // movsd with no operands (as opposed to the SSE scalar move of a double) is an // alias for movsl. (as in rep; movsd) Modified: llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll (original) +++ llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll Wed Apr 13 20:11:51 2011 @@ -1,6 +1,6 @@ ; RUN: llc < %s -march=x86-64 > %t ; RUN: grep movb %t | count 2 -; RUN: grep {movzb\[wl\]} %t +; RUN: grep {movzx} %t define void @handle_vector_size_attribute() nounwind { Modified: llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll (original) +++ llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll Wed Apr 13 20:11:51 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 | grep {movsbl} +; RUN: llc < %s -march=x86 | grep {movsx} @X = global i32 0 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll (original) +++ llvm/trunk/test/CodeGen/X86/2007-09-27-LDIntrinsics.ll Wed Apr 13 20:11:51 2011 @@ -22,8 +22,8 @@ ; CHECK: bar: ; CHECK: fldt 4(%esp) ; CHECK-NEXT: fld %st(0) -; CHECK-NEXT: fmul %st(1) -; CHECK-NEXT: fmulp %st(1) +; CHECK-NEXT: fmul %st(1), %st(0) +; CHECK-NEXT: fmulp ; CHECK-NEXT: ret } Modified: llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll (original) +++ llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll Wed Apr 13 20:11:51 2011 @@ -1,9 +1,10 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin | grep movzbl +; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s define i32 @foo(<4 x float> %a, <4 x float> %b) nounwind { entry: - tail call i32 @llvm.x86.sse.ucomige.ss( <4 x float> %a, <4 x float> %b ) nounwind readnone - ret i32 %0 +; CHECK: movzx + tail call i32 @llvm.x86.sse.ucomige.ss( <4 x float> %a, <4 x float> %b ) nounwind readnone + ret i32 %0 } declare i32 @llvm.x86.sse.ucomige.ss(<4 x float>, <4 x float>) nounwind readnone Modified: llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll (original) +++ llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll Wed Apr 13 20:11:51 2011 @@ -1,9 +1,8 @@ -; RUN: llc < %s -march=x86 -mattr=+mmx,+sse2 > %t1 -; RUN: grep movzwl %t1 | count 2 -; RUN: grep movzbl %t1 | count 2 -; RUN: grep movd %t1 | count 4 +; RUN: llc < %s -march=x86 -mattr=+mmx,+sse2 | FileCheck %s define <4 x i16> @a(i32* %x1) nounwind { +; CHECK: movzx +; CHECK-NEXT: movd %x2 = load i32* %x1 %x3 = lshr i32 %x2, 1 %x = trunc i32 %x3 to i16 @@ -12,6 +11,8 @@ } define <8 x i16> @b(i32* %x1) nounwind { +; CHECK: movzx +; CHECK-NEXT: movd %x2 = load i32* %x1 %x3 = lshr i32 %x2, 1 %x = trunc i32 %x3 to i16 @@ -20,6 +21,8 @@ } define <8 x i8> @c(i32* %x1) nounwind { +; CHECK: movzx +; CHECK-NEXT: movd %x2 = load i32* %x1 %x3 = lshr i32 %x2, 1 %x = trunc i32 %x3 to i8 @@ -28,6 +31,8 @@ } define <16 x i8> @d(i32* %x1) nounwind { +; CHECK: movzx +; CHECK-NEXT: movd %x2 = load i32* %x1 %x3 = lshr i32 %x2, 1 %x = trunc i32 %x3 to i8 Modified: llvm/trunk/test/CodeGen/X86/anyext.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/anyext.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/anyext.ll (original) +++ llvm/trunk/test/CodeGen/X86/anyext.ll Wed Apr 13 20:11:51 2011 @@ -1,8 +1,10 @@ -; RUN: llc < %s -march=x86-64 | grep movzbl | count 2 +; RUN: llc < %s -march=x86-64 | FileCheck %s -; Use movzbl to avoid partial-register updates. +; Use movzbl (aliased as movzx) to avoid partial-register updates. define i32 @foo(i32 %p, i8 zeroext %x) nounwind { +; CHECK: movzx %dil, %eax +; CHECK: movzx %al, %eax %q = trunc i32 %p to i8 %r = udiv i8 %q, %x %s = zext i8 %r to i32 Modified: llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll Wed Apr 13 20:11:51 2011 @@ -75,7 +75,7 @@ define i32 @test_x86_sse2_comieq_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.comieq.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -85,7 +85,7 @@ define i32 @test_x86_sse2_comige_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: setae - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.comige.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -95,7 +95,7 @@ define i32 @test_x86_sse2_comigt_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.comigt.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -105,7 +105,7 @@ define i32 @test_x86_sse2_comile_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: setbe - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.comile.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -125,7 +125,7 @@ define i32 @test_x86_sse2_comineq_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: setne - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.comineq.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -786,7 +786,7 @@ define i32 @test_x86_sse2_ucomieq_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.ucomieq.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -796,7 +796,7 @@ define i32 @test_x86_sse2_ucomige_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: setae - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.ucomige.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -806,7 +806,7 @@ define i32 @test_x86_sse2_ucomigt_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.ucomigt.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -816,7 +816,7 @@ define i32 @test_x86_sse2_ucomile_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: setbe - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.ucomile.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -835,7 +835,7 @@ define i32 @test_x86_sse2_ucomineq_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: setne - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse2.ucomineq.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -1192,7 +1192,7 @@ define i32 @test_x86_sse41_ptestnzc(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vptest ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse41.ptestnzc(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1202,7 +1202,7 @@ define i32 @test_x86_sse41_ptestz(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vptest ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse41.ptestz(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1414,7 +1414,7 @@ define i32 @test_x86_sse_comieq_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.comieq.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1424,7 +1424,7 @@ define i32 @test_x86_sse_comige_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: setae - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.comige.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1434,7 +1434,7 @@ define i32 @test_x86_sse_comigt_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.comigt.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1444,7 +1444,7 @@ define i32 @test_x86_sse_comile_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: setbe - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.comile.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1463,7 +1463,7 @@ define i32 @test_x86_sse_comineq_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: setne - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.comineq.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1655,7 +1655,7 @@ define i32 @test_x86_sse_ucomieq_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.ucomieq.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1665,7 +1665,7 @@ define i32 @test_x86_sse_ucomige_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: setae - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.ucomige.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1675,7 +1675,7 @@ define i32 @test_x86_sse_ucomigt_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.ucomigt.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1685,7 +1685,7 @@ define i32 @test_x86_sse_ucomile_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: setbe - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.ucomile.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1704,7 +1704,7 @@ define i32 @test_x86_sse_ucomineq_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: setne - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.sse.ucomineq.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -2179,7 +2179,7 @@ define i32 @test_x86_avx_ptestnzc_256(<4 x i64> %a0, <4 x i64> %a1) { ; CHECK: vptest ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.ptestnzc.256(<4 x i64> %a0, <4 x i64> %a1) ; [#uses=1] ret i32 %res } @@ -2189,7 +2189,7 @@ define i32 @test_x86_avx_ptestz_256(<4 x i64> %a0, <4 x i64> %a1) { ; CHECK: vptest ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.ptestz.256(<4 x i64> %a0, <4 x i64> %a1) ; [#uses=1] ret i32 %res } @@ -2483,7 +2483,7 @@ define i32 @test_x86_avx_vtestnzc_pd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vtestpd ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.vtestnzc.pd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -2493,7 +2493,7 @@ define i32 @test_x86_avx_vtestnzc_pd_256(<4 x double> %a0, <4 x double> %a1) { ; CHECK: vtestpd ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.vtestnzc.pd.256(<4 x double> %a0, <4 x double> %a1) ; [#uses=1] ret i32 %res } @@ -2503,7 +2503,7 @@ define i32 @test_x86_avx_vtestnzc_ps(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vtestps ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.vtestnzc.ps(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -2513,7 +2513,7 @@ define i32 @test_x86_avx_vtestnzc_ps_256(<8 x float> %a0, <8 x float> %a1) { ; CHECK: vtestps ; CHECK: seta - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.vtestnzc.ps.256(<8 x float> %a0, <8 x float> %a1) ; [#uses=1] ret i32 %res } @@ -2523,7 +2523,7 @@ define i32 @test_x86_avx_vtestz_pd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vtestpd ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.vtestz.pd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -2533,7 +2533,7 @@ define i32 @test_x86_avx_vtestz_pd_256(<4 x double> %a0, <4 x double> %a1) { ; CHECK: vtestpd ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.vtestz.pd.256(<4 x double> %a0, <4 x double> %a1) ; [#uses=1] ret i32 %res } @@ -2543,7 +2543,7 @@ define i32 @test_x86_avx_vtestz_ps(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vtestps ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.vtestz.ps(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -2553,7 +2553,7 @@ define i32 @test_x86_avx_vtestz_ps_256(<8 x float> %a0, <8 x float> %a1) { ; CHECK: vtestps ; CHECK: sete - ; CHECK: movzbl + ; CHECK: movzx %res = call i32 @llvm.x86.avx.vtestz.ps.256(<8 x float> %a0, <8 x float> %a1) ; [#uses=1] ret i32 %res } Modified: llvm/trunk/test/CodeGen/X86/bool-zext.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/bool-zext.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/bool-zext.ll (original) +++ llvm/trunk/test/CodeGen/X86/bool-zext.ll Wed Apr 13 20:11:51 2011 @@ -1,7 +1,7 @@ ; RUN: llc < %s -march=x86-64 | FileCheck %s ; CHECK: @bar1 -; CHECK: movzbl +; CHECK: movzx ; CHECK: callq define void @bar1(i1 zeroext %v1) nounwind ssp { entry: @@ -11,7 +11,7 @@ } ; CHECK: @bar2 -; CHECK-NOT: movzbl +; CHECK-NOT: movzx ; CHECK: callq define void @bar2(i8 zeroext %v1) nounwind ssp { entry: @@ -22,7 +22,7 @@ ; CHECK: @bar3 ; CHECK: callq -; CHECK-NOT: movzbl +; CHECK-NOT: movzx ; CHECK-NOT: and ; CHECK: ret define zeroext i1 @bar3() nounwind ssp { Modified: llvm/trunk/test/CodeGen/X86/cmov.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cmov.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/cmov.ll (original) +++ llvm/trunk/test/CodeGen/X86/cmov.ll Wed Apr 13 20:11:51 2011 @@ -121,7 +121,7 @@ entry: ; CHECK: test5: ; CHECK: setg %al -; CHECK: movzbl %al, %eax +; CHECK: movzx %al, %eax ; CHECK: orl $-2, %eax ; CHECK: ret @@ -135,7 +135,7 @@ entry: ; CHECK: test6: ; CHECK: setl %al -; CHECK: movzbl %al, %eax +; CHECK: movzx %al, %eax ; CHECK: leal 4(%rax,%rax,8), %eax ; CHECK: ret %0 = load i32* %P, align 4 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/cmp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cmp.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/cmp.ll (original) +++ llvm/trunk/test/CodeGen/X86/cmp.ll Wed Apr 13 20:11:51 2011 @@ -38,7 +38,7 @@ ; CHECK: test3: ; CHECK: testq %rdi, %rdi ; CHECK: sete %al -; CHECK: movzbl %al, %eax +; CHECK: movzx %al, %eax ; CHECK: ret } @@ -49,7 +49,7 @@ ; CHECK: test4: ; CHECK: testq %rdi, %rdi ; CHECK: setle %al -; CHECK: movzbl %al, %eax +; CHECK: movzx %al, %eax ; CHECK: ret } Modified: llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll (original) +++ llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll Wed Apr 13 20:11:51 2011 @@ -14,7 +14,7 @@ ; X32: ret ; X64: test1: -; X64: movslq %e[[A0:di|cx]], %rax +; X64: movsx %e[[A0:di|cx]], %rax ; X64: movl (%r[[A1:si|dx]],%rax,4), %eax ; X64: ret @@ -81,7 +81,7 @@ %v11 = add i64 %B, %v10 ret i64 %v11 ; X64: test5: -; X64: movslq %e[[A1]], %rax +; X64: movsx %e[[A1]], %rax ; X64-NEXT: movq (%r[[A0]],%rax), %rax ; X64-NEXT: addq %{{rdx|r8}}, %rax ; X64-NEXT: ret Modified: llvm/trunk/test/CodeGen/X86/fp-stack-compare.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fp-stack-compare.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/fp-stack-compare.ll (original) +++ llvm/trunk/test/CodeGen/X86/fp-stack-compare.ll Wed Apr 13 20:11:51 2011 @@ -1,11 +1,11 @@ -; RUN: llc < %s -march=x86 -mcpu=i386 | grep {fucompi.*st.\[12\]} +; RUN: llc < %s -march=x86 -mcpu=i386 | FileCheck %s ; PR1012 define float @foo(float* %col.2.0) { - %tmp = load float* %col.2.0 ; [#uses=3] - %tmp16 = fcmp olt float %tmp, 0.000000e+00 ; [#uses=1] - %tmp20 = fsub float -0.000000e+00, %tmp ; [#uses=1] - %iftmp.2.0 = select i1 %tmp16, float %tmp20, float %tmp ; [#uses=1] - ret float %iftmp.2.0 +; CHECK: fucompi + %tmp = load float* %col.2.0 + %tmp16 = fcmp olt float %tmp, 0.000000e+00 + %tmp20 = fsub float -0.000000e+00, %tmp + %iftmp.2.0 = select i1 %tmp16, float %tmp20, float %tmp + ret float %iftmp.2.0 } - Modified: llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll (original) +++ llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll Wed Apr 13 20:11:51 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 | grep {movzbl %\[abcd\]h,} | count 7 +; RUN: llc < %s -march=x86 | grep {movzx %\[abcd\]h,} | count 7 ; Use h-register extract and zero-extend. Modified: llvm/trunk/test/CodeGen/X86/h-registers-0.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/h-registers-0.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/h-registers-0.ll (original) +++ llvm/trunk/test/CodeGen/X86/h-registers-0.ll Wed Apr 13 20:11:51 2011 @@ -70,7 +70,7 @@ ; WIN64: movzbl %ch, %eax ; X86-32: qux64: -; X86-32: movzbl %ah, %eax +; X86-32: movzx %ah, %eax %t0 = lshr i64 %x, 8 %t1 = and i64 %t0, 255 ret i64 %t1 @@ -85,7 +85,7 @@ ; WIN64: movzbl %ch, %eax ; X86-32: qux32: -; X86-32: movzbl %ah, %eax +; X86-32: movzx %ah, %eax %t0 = lshr i32 %x, 8 %t1 = and i32 %t0, 255 ret i32 %t1 @@ -100,7 +100,7 @@ ; WIN64: movzbl %ch, %eax ; X86-32: qux16: -; X86-32: movzbl %ah, %eax +; X86-32: movzx %ah, %eax %t0 = lshr i16 %x, 8 ret i16 %t0 } Modified: llvm/trunk/test/CodeGen/X86/h-registers-2.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/h-registers-2.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/h-registers-2.ll (original) +++ llvm/trunk/test/CodeGen/X86/h-registers-2.ll Wed Apr 13 20:11:51 2011 @@ -1,5 +1,5 @@ ; RUN: llc < %s -march=x86 > %t -; RUN: grep {movzbl %\[abcd\]h,} %t | count 1 +; RUN: grep {movzx %\[abcd\]h,} %t | count 1 ; RUN: grep {shll \$3,} %t | count 1 ; Use an h register, but don't omit the explicit shift for Modified: llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll (original) +++ llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll Wed Apr 13 20:11:51 2011 @@ -1,5 +1,5 @@ ; PR2094 -; RUN: llc < %s -march=x86-64 | grep movslq +; RUN: llc < %s -march=x86-64 | grep movsx ; RUN: llc < %s -march=x86-64 | grep addps ; RUN: llc < %s -march=x86-64 | grep paddd ; RUN: llc < %s -march=x86-64 | not grep movq Modified: llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll (original) +++ llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll Wed Apr 13 20:11:51 2011 @@ -1,6 +1,6 @@ ; RUN: llc < %s -march=x86-64 > %t ; RUN: grep and %t | count 6 -; RUN: grep movzb %t | count 6 +; RUN: grep movzx %t | count 6 ; RUN: grep sar %t | count 12 ; Don't optimize away zext-inreg and sext-inreg on the loop induction Modified: llvm/trunk/test/CodeGen/X86/pr3366.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pr3366.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/pr3366.ll (original) +++ llvm/trunk/test/CodeGen/X86/pr3366.ll Wed Apr 13 20:11:51 2011 @@ -1,6 +1,7 @@ -; RUN: llc < %s -march=x86 -disable-cgp-branch-opts | grep movzbl +; RUN: llc < %s -march=x86 -disable-cgp-branch-opts | FileCheck %s ; PR3366 +; CHECK: movzx define void @_ada_c34002a() nounwind { entry: %0 = load i8* null, align 1 Modified: llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll (original) +++ llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll Wed Apr 13 20:11:51 2011 @@ -7,7 +7,7 @@ ; ISel doesn't yet know how to eliminate this extra zero-extend. But until ; it knows how to do so safely, it shouldn;t eliminate it. ; CHECK: movzbl (%rdi), %eax -; CHECK: movzwl %ax, %eax +; CHECK: movzx %ax, %eax define i64 @_ZL5matchPKtPKhiR9MatchData(i8* %tmp13) nounwind { entry: Modified: llvm/trunk/test/CodeGen/X86/promote-i16.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/promote-i16.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/promote-i16.ll (original) +++ llvm/trunk/test/CodeGen/X86/promote-i16.ll Wed Apr 13 20:11:51 2011 @@ -4,8 +4,8 @@ entry: ; CHECK: foo: ; CHECK: movzwl 4(%esp), %eax -; CHECK: xorl $21998, %eax -; CHECK: movswl %ax, %eax +; CHECK: xorl $21998, %eax +; CHECK: movsx %ax, %eax %0 = xor i16 %x, 21998 ret i16 %0 } Modified: llvm/trunk/test/CodeGen/X86/select.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/select.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/select.ll (original) +++ llvm/trunk/test/CodeGen/X86/select.ll Wed Apr 13 20:11:51 2011 @@ -30,7 +30,7 @@ ret i32 0 ; CHECK: test2: ; CHECK: movnew -; CHECK: movswl +; CHECK: movsx } declare i1 @return_false() Modified: llvm/trunk/test/CodeGen/X86/setcc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/setcc.ll (original) +++ llvm/trunk/test/CodeGen/X86/setcc.ll Wed Apr 13 20:11:51 2011 @@ -8,7 +8,7 @@ entry: ; CHECK: t1: ; CHECK: seta %al -; CHECK: movzbl %al, %eax +; CHECK: movzx %al, %eax ; CHECK: shll $5, %eax %0 = icmp ugt i16 %x, 26 ; [#uses=1] %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/sext-ret-val.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/sext-ret-val.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/sext-ret-val.ll (original) +++ llvm/trunk/test/CodeGen/X86/sext-ret-val.ll Wed Apr 13 20:11:51 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 | grep movzbl | count 1 +; RUN: llc < %s -march=x86 | grep movzx | count 1 ; rdar://6699246 define signext i8 @t1(i8* %A) nounwind readnone ssp { Modified: llvm/trunk/test/CodeGen/X86/sext-subreg.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/sext-subreg.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/sext-subreg.ll (original) +++ llvm/trunk/test/CodeGen/X86/sext-subreg.ll Wed Apr 13 20:11:51 2011 @@ -3,7 +3,7 @@ define i64 @t(i64 %A, i64 %B, i32* %P, i64 *%P2) nounwind { ; CHECK: t: -; CHECK: movslq %e{{.*}}, %rax +; CHECK: movsx %e{{.*}}, %rax ; CHECK: movq %rax ; CHECK: movl %eax %C = add i64 %A, %B Modified: llvm/trunk/test/CodeGen/X86/shl_elim.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/shl_elim.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/shl_elim.ll (original) +++ llvm/trunk/test/CodeGen/X86/shl_elim.ll Wed Apr 13 20:11:51 2011 @@ -1,6 +1,6 @@ ; RUN: llc < %s -march=x86 | grep {movl 8(.esp), %eax} ; RUN: llc < %s -march=x86 | grep {shrl .eax} -; RUN: llc < %s -march=x86 | grep {movswl .ax, .eax} +; RUN: llc < %s -march=x86 | grep {movsx .ax, .eax} define i32 @test1(i64 %a) nounwind { %tmp29 = lshr i64 %a, 24 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll (original) +++ llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll Wed Apr 13 20:11:51 2011 @@ -9,6 +9,6 @@ ; CHECK: a: ; CHECK: mull ; CHECK: seto %al -; CHECK: movzbl %al, %eax +; CHECK: movzx %al, %eax ; CHECK: ret } Modified: llvm/trunk/test/CodeGen/X86/vshift-4.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vshift-4.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vshift-4.ll (original) +++ llvm/trunk/test/CodeGen/X86/vshift-4.ll Wed Apr 13 20:11:51 2011 @@ -57,7 +57,7 @@ define void @shift3a(<8 x i16> %val, <8 x i16>* %dst, <8 x i16> %amt) nounwind { entry: ; CHECK: shift3a: -; CHECK: movzwl +; CHECK: movzx ; CHECK: psllw %shamt = shufflevector <8 x i16> %amt, <8 x i16> undef, <8 x i32> %shl = shl <8 x i16> %val, %shamt Modified: llvm/trunk/test/CodeGen/X86/widen_conv-2.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/widen_conv-2.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/widen_conv-2.ll (original) +++ llvm/trunk/test/CodeGen/X86/widen_conv-2.ll Wed Apr 13 20:11:51 2011 @@ -1,6 +1,6 @@ ; RUN: llc < %s -march=x86 -mattr=+sse42 | FileCheck %s -; CHECK: movswl -; CHECK: movswl +; CHECK: movsx +; CHECK: movsx ; sign extension v2i32 to v2i16 Modified: llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll (original) +++ llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll Wed Apr 13 20:11:51 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s | grep movswl +; RUN: llc < %s | grep movsx target datalayout = "e-p:64:64" target triple = "x86_64-apple-darwin8" Modified: llvm/trunk/test/MC/X86/x86-32.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/x86-32.s?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/MC/X86/x86-32.s (original) +++ llvm/trunk/test/MC/X86/x86-32.s Wed Apr 13 20:11:51 2011 @@ -613,11 +613,11 @@ // CHECK: encoding: [0xd5,0x01] aad $1 -// CHECK: aad $10 +// CHECK: aad // CHECK: encoding: [0xd5,0x0a] aad $0xA -// CHECK: aad $10 +// CHECK: aad // CHECK: encoding: [0xd5,0x0a] aad @@ -625,11 +625,11 @@ // CHECK: encoding: [0xd4,0x02] aam $2 -// CHECK: aam $10 +// CHECK: aam // CHECK: encoding: [0xd4,0x0a] aam $0xA -// CHECK: aam $10 +// CHECK: aam // CHECK: encoding: [0xd4,0x0a] aam @@ -725,7 +725,7 @@ // CHECK: encoding: [0xdf,0xf2] fcompi %st(2) -// CHECK: fcompi %st(1) +// CHECK: fcompi // CHECK: encoding: [0xdf,0xf1] fcompi @@ -737,7 +737,7 @@ // CHECK: encoding: [0xdf,0xea] fucompi %st(2) -// CHECK: fucompi %st(1) +// CHECK: fucompi // CHECK: encoding: [0xdf,0xe9] fucompi @@ -866,9 +866,9 @@ movsw %ds:(%esi), %es:(%edi) movsw (%esi), %es:(%edi) -// CHECK: movsl # encoding: [0xa5] -// CHECK: movsl -// CHECK: movsl +// CHECK: movsd # encoding: [0xa5] +// CHECK: movsd +// CHECK: movsd movsl movsl %ds:(%esi), %es:(%edi) movsl (%esi), %es:(%edi) Modified: llvm/trunk/test/MC/X86/x86-64.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/x86-64.s?rev=129497&r1=129496&r2=129497&view=diff ============================================================================== --- llvm/trunk/test/MC/X86/x86-64.s (original) +++ llvm/trunk/test/MC/X86/x86-64.s Wed Apr 13 20:11:51 2011 @@ -112,12 +112,12 @@ // rdar://8470918 smovb // CHECK: movsb smovw // CHECK: movsw -smovl // CHECK: movsl +smovl // CHECK: movsd smovq // CHECK: movsq // rdar://8456361 // CHECK: rep -// CHECK: movsl +// CHECK: movsd rep movsd // CHECK: rep @@ -232,10 +232,10 @@ // rdar://8407928 // CHECK: inb $127, %al -// CHECK: inw %dx, %ax +// CHECK: inw %dx // CHECK: outb %al, $127 -// CHECK: outw %ax, %dx -// CHECK: inl %dx, %eax +// CHECK: outw %dx +// CHECK: inl %dx inb $0x7f inw %dx outb $0x7f @@ -244,12 +244,12 @@ // PR8114 -// CHECK: outb %al, %dx -// CHECK: outb %al, %dx -// CHECK: outw %ax, %dx -// CHECK: outw %ax, %dx -// CHECK: outl %eax, %dx -// CHECK: outl %eax, %dx +// CHECK: outb %dx +// CHECK: outb %dx +// CHECK: outw %dx +// CHECK: outw %dx +// CHECK: outl %dx +// CHECK: outl %dx out %al, (%dx) outb %al, (%dx) @@ -258,12 +258,12 @@ out %eax, (%dx) outl %eax, (%dx) -// CHECK: inb %dx, %al -// CHECK: inb %dx, %al -// CHECK: inw %dx, %ax -// CHECK: inw %dx, %ax -// CHECK: inl %dx, %eax -// CHECK: inl %dx, %eax +// CHECK: inb %dx +// CHECK: inb %dx +// CHECK: inw %dx +// CHECK: inw %dx +// CHECK: inl %dx +// CHECK: inl %dx in (%dx), %al inb (%dx), %al @@ -274,16 +274,16 @@ // rdar://8431422 -// CHECK: fxch %st(1) -// CHECK: fucom %st(1) -// CHECK: fucomp %st(1) -// CHECK: faddp %st(1) +// CHECK: fxch +// CHECK: fucom +// CHECK: fucomp +// CHECK: faddp // CHECK: faddp %st(0) -// CHECK: fsubp %st(1) -// CHECK: fsubrp %st(1) -// CHECK: fmulp %st(1) -// CHECK: fdivp %st(1) -// CHECK: fdivrp %st(1) +// CHECK: fsubp +// CHECK: fsubrp +// CHECK: fmulp +// CHECK: fdivp +// CHECK: fdivrp fxch fucom @@ -296,11 +296,11 @@ fdivp fdivrp -// CHECK: fcomi %st(1) +// CHECK: fcomi // CHECK: fcomi %st(2) -// CHECK: fucomi %st(1) -// CHECK: fucomi %st(2) -// CHECK: fucomi %st(2) +// CHECK: fucomi +// CHECK: fucomi %st(2) +// CHECK: fucomi %st(2) fcomi fcomi %st(2) @@ -604,7 +604,7 @@ // CHECK: encoding: [0x48,0xa5] movsl -// CHECK: movsl +// CHECK: movsd // CHECK: encoding: [0xa5] stosq @@ -681,65 +681,65 @@ // CHECK: encoding: [0x48,0x0f,0xba,0xe2,0x01] //rdar://8017633 -// CHECK: movzbl %al, %esi +// CHECK: movzx %al, %esi // CHECK: encoding: [0x0f,0xb6,0xf0] movzx %al, %esi -// CHECK: movzbq %al, %rsi +// CHECK: movzx %al, %rsi // CHECK: encoding: [0x48,0x0f,0xb6,0xf0] movzx %al, %rsi -// CHECK: movsbw %al, %ax +// CHECK: movsx %al, %ax // CHECK: encoding: [0x66,0x0f,0xbe,0xc0] -movsx %al, %ax + movsx %al, %ax -// CHECK: movsbl %al, %eax +// CHECK: movsx %al, %eax // CHECK: encoding: [0x0f,0xbe,0xc0] -movsx %al, %eax + movsx %al, %eax -// CHECK: movswl %ax, %eax +// CHECK: movsx %ax, %eax // CHECK: encoding: [0x0f,0xbf,0xc0] -movsx %ax, %eax + movsx %ax, %eax -// CHECK: movsbq %bl, %rax +// CHECK: movsx %bl, %rax // CHECK: encoding: [0x48,0x0f,0xbe,0xc3] -movsx %bl, %rax + movsx %bl, %rax -// CHECK: movswq %cx, %rax +// CHECK: movsx %cx, %rax // CHECK: encoding: [0x48,0x0f,0xbf,0xc1] -movsx %cx, %rax + movsx %cx, %rax -// CHECK: movslq %edi, %rax +// CHECK: movsx %edi, %rax // CHECK: encoding: [0x48,0x63,0xc7] -movsx %edi, %rax + movsx %edi, %rax -// CHECK: movzbw %al, %ax +// CHECK: movzx %al, %ax // CHECK: encoding: [0x66,0x0f,0xb6,0xc0] -movzx %al, %ax + movzx %al, %ax -// CHECK: movzbl %al, %eax +// CHECK: movzx %al, %eax // CHECK: encoding: [0x0f,0xb6,0xc0] -movzx %al, %eax + movzx %al, %eax -// CHECK: movzwl %ax, %eax +// CHECK: movzx %ax, %eax // CHECK: encoding: [0x0f,0xb7,0xc0] -movzx %ax, %eax + movzx %ax, %eax -// CHECK: movzbq %bl, %rax +// CHECK: movzx %bl, %rax // CHECK: encoding: [0x48,0x0f,0xb6,0xc3] -movzx %bl, %rax + movzx %bl, %rax -// CHECK: movzwq %cx, %rax +// CHECK: movzx %cx, %rax // CHECK: encoding: [0x48,0x0f,0xb7,0xc1] -movzx %cx, %rax + movzx %cx, %rax // CHECK: movsbw (%rax), %ax // CHECK: encoding: [0x66,0x0f,0xbe,0x00] -movsx (%rax), %ax + movsx (%rax), %ax // CHECK: movzbw (%rax), %ax // CHECK: encoding: [0x66,0x0f,0xb6,0x00] -movzx (%rax), %ax + movzx (%rax), %ax // rdar://7873482 @@ -790,7 +790,7 @@ rep movsl // CHECK: rep // CHECK: encoding: [0xf3] -// CHECK: movsl +// CHECK: movsd // CHECK: encoding: [0xa5] @@ -1027,9 +1027,9 @@ movsw %ds:(%rsi), %es:(%rdi) movsw (%rsi), %es:(%rdi) -// CHECK: movsl # encoding: [0xa5] -// CHECK: movsl -// CHECK: movsl +// CHECK: movsd # encoding: [0xa5] +// CHECK: movsd +// CHECK: movsd movsl movsl %ds:(%rsi), %es:(%rdi) movsl (%rsi), %es:(%rdi) From echristo at apple.com Wed Apr 13 20:38:30 2011 From: echristo at apple.com (Eric Christopher) Date: Wed, 13 Apr 2011 18:38:30 -0700 Subject: [llvm-commits] [llvm] r129497 - in /llvm/trunk: lib/Target/X86/ lib/Target/X86/InstPrinter/ test/CodeGen/X86/ test/MC/X86/ In-Reply-To: <20110414011151.BBACC2A6C12C@llvm.org> References: <20110414011151.BBACC2A6C12C@llvm.org> Message-ID: Awesome. One thing... On Apr 13, 2011, at 6:11 PM, Bill Wendling wrote: > void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) { > - printInstruction(MI, OS); > + if (printAliasInstr(MI, OS)) > + printInstruction(MI, OS); This looks... awkward? -eric From gohman at apple.com Wed Apr 13 20:38:49 2011 From: gohman at apple.com (Dan Gohman) Date: Wed, 13 Apr 2011 18:38:49 -0700 Subject: [llvm-commits] [llvm] r129497 - in /llvm/trunk: lib/Target/X86/ lib/Target/X86/InstPrinter/ test/CodeGen/X86/ test/MC/X86/ In-Reply-To: <20110414011151.BBACC2A6C12C@llvm.org> References: <20110414011151.BBACC2A6C12C@llvm.org> Message-ID: <94B5EB5F-D681-4907-A0BE-C718E2D55AD4@apple.com> On Apr 13, 2011, at 6:11 PM, Bill Wendling wrote: > Author: void > Date: Wed Apr 13 20:11:51 2011 > New Revision: 129497 > > URL: http://llvm.org/viewvc/llvm-project?rev=129497&view=rev > Log: > Have the X86 back-end emit the alias instead of what's being aliased. In most > cases, it's much nicer and more informative reading the alias. Hi Bill, movzbl, movsbl, and friends are nicer than movzx and movsx in the AT&T syntax because AT&T syntax uses suffixes rather than implicit typing for just about everything else. Dan From isanbard at gmail.com Wed Apr 13 20:43:20 2011 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 13 Apr 2011 18:43:20 -0700 Subject: [llvm-commits] [llvm] r129497 - in /llvm/trunk: lib/Target/X86/ lib/Target/X86/InstPrinter/ test/CodeGen/X86/ test/MC/X86/ In-Reply-To: References: <20110414011151.BBACC2A6C12C@llvm.org> Message-ID: <1B9F1F5D-5149-4CB4-BD63-73B98F6412A4@gmail.com> On Apr 13, 2011, at 6:38 PM, Eric Christopher wrote: > Awesome. > > One thing... > > On Apr 13, 2011, at 6:11 PM, Bill Wendling wrote: > >> void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) { >> - printInstruction(MI, OS); >> + if (printAliasInstr(MI, OS)) >> + printInstruction(MI, OS); > > This looks... awkward? > Maybe...but it's similar to the style used in the parser where a function that returns 'true' didn't succeed in doing what it was supposed to do (like parse a statement or something). I'm open to ideas, though. :) -bw From isanbard at gmail.com Wed Apr 13 20:43:32 2011 From: isanbard at gmail.com (Bill Wendling) Date: Wed, 13 Apr 2011 18:43:32 -0700 Subject: [llvm-commits] [llvm] r129497 - in /llvm/trunk: lib/Target/X86/ lib/Target/X86/InstPrinter/ test/CodeGen/X86/ test/MC/X86/ In-Reply-To: <94B5EB5F-D681-4907-A0BE-C718E2D55AD4@apple.com> References: <20110414011151.BBACC2A6C12C@llvm.org> <94B5EB5F-D681-4907-A0BE-C718E2D55AD4@apple.com> Message-ID: On Apr 13, 2011, at 6:38 PM, Dan Gohman wrote: > > On Apr 13, 2011, at 6:11 PM, Bill Wendling wrote: > >> Author: void >> Date: Wed Apr 13 20:11:51 2011 >> New Revision: 129497 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=129497&view=rev >> Log: >> Have the X86 back-end emit the alias instead of what's being aliased. In most >> cases, it's much nicer and more informative reading the alias. > > Hi Bill, > > movzbl, movsbl, and friends are nicer than movzx and movsx > in the AT&T syntax because AT&T syntax uses suffixes rather > than implicit typing for just about everything else. > Hrm...Okay. I'll change them back. -bw From echristo at apple.com Wed Apr 13 20:47:44 2011 From: echristo at apple.com (Eric Christopher) Date: Wed, 13 Apr 2011 18:47:44 -0700 Subject: [llvm-commits] [llvm] r129497 - in /llvm/trunk: lib/Target/X86/ lib/Target/X86/InstPrinter/ test/CodeGen/X86/ test/MC/X86/ In-Reply-To: <1B9F1F5D-5149-4CB4-BD63-73B98F6412A4@gmail.com> References: <20110414011151.BBACC2A6C12C@llvm.org> <1B9F1F5D-5149-4CB4-BD63-73B98F6412A4@gmail.com> Message-ID: On Apr 13, 2011, at 6:43 PM, Bill Wendling wrote: > On Apr 13, 2011, at 6:38 PM, Eric Christopher wrote: > >> Awesome. >> >> One thing... >> >> On Apr 13, 2011, at 6:11 PM, Bill Wendling wrote: >> >>> void X86ATTInstPrinter::printInst(const MCInst *MI, raw_ostream &OS) { >>> - printInstruction(MI, OS); >>> + if (printAliasInstr(MI, OS)) >>> + printInstruction(MI, OS); >> >> This looks... awkward? >> > Maybe...but it's similar to the style used in the parser where a function that returns 'true' didn't succeed in doing what it was supposed to do (like parse a statement or something). > > I'm open to ideas, though. :) ... *shudder* I'll think on it ;) -eric From isanbard at gmail.com Wed Apr 13 20:46:37 2011 From: isanbard at gmail.com (Bill Wendling) Date: Thu, 14 Apr 2011 01:46:37 -0000 Subject: [llvm-commits] [llvm] r129498 - in /llvm/trunk: lib/Target/X86/ test/CodeGen/X86/ test/MC/X86/ Message-ID: <20110414014638.097A12A6C12C@llvm.org> Author: void Date: Wed Apr 13 20:46:37 2011 New Revision: 129498 URL: http://llvm.org/viewvc/llvm-project?rev=129498&view=rev Log: As Dan pointed out, movzbl, movsbl, and friends are nicer than their alias (movzx/movsx) because they give more information. Revert that part of the patch. Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll llvm/trunk/test/CodeGen/X86/anyext.ll llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll llvm/trunk/test/CodeGen/X86/bool-zext.ll llvm/trunk/test/CodeGen/X86/cmov.ll llvm/trunk/test/CodeGen/X86/cmp.ll llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll llvm/trunk/test/CodeGen/X86/h-registers-0.ll llvm/trunk/test/CodeGen/X86/h-registers-2.ll llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll llvm/trunk/test/CodeGen/X86/pr3366.ll llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll llvm/trunk/test/CodeGen/X86/promote-i16.ll llvm/trunk/test/CodeGen/X86/select.ll llvm/trunk/test/CodeGen/X86/setcc.ll llvm/trunk/test/CodeGen/X86/sext-ret-val.ll llvm/trunk/test/CodeGen/X86/sext-subreg.ll llvm/trunk/test/CodeGen/X86/shl_elim.ll llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll llvm/trunk/test/CodeGen/X86/vshift-4.ll llvm/trunk/test/CodeGen/X86/widen_conv-2.ll llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll llvm/trunk/test/MC/X86/x86-64.s Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.td?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.td Wed Apr 13 20:46:37 2011 @@ -1546,21 +1546,21 @@ def : InstAlias<"movsd", (MOVSD)>; // movsx aliases -def : InstAlias<"movsx $src, $dst", (MOVSX16rr8W GR16:$dst, GR8:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX16rm8W GR16:$dst, i8mem:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX32rr8 GR32:$dst, GR8:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX32rr16 GR32:$dst, GR16:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX64rr8 GR64:$dst, GR8:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX64rr16 GR64:$dst, GR16:$src)>; -def : InstAlias<"movsx $src, $dst", (MOVSX64rr32 GR64:$dst, GR32:$src)>; +def : InstAlias<"movsx $src, $dst", (MOVSX16rr8W GR16:$dst, GR8:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX16rm8W GR16:$dst, i8mem:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX32rr8 GR32:$dst, GR8:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX32rr16 GR32:$dst, GR16:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX64rr8 GR64:$dst, GR8:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX64rr16 GR64:$dst, GR16:$src), 0>; +def : InstAlias<"movsx $src, $dst", (MOVSX64rr32 GR64:$dst, GR32:$src), 0>; // movzx aliases -def : InstAlias<"movzx $src, $dst", (MOVZX16rr8W GR16:$dst, GR8:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX16rm8W GR16:$dst, i8mem:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX32rr8 GR32:$dst, GR8:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX32rr16 GR32:$dst, GR16:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX64rr8_Q GR64:$dst, GR8:$src)>; -def : InstAlias<"movzx $src, $dst", (MOVZX64rr16_Q GR64:$dst, GR16:$src)>; +def : InstAlias<"movzx $src, $dst", (MOVZX16rr8W GR16:$dst, GR8:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX16rm8W GR16:$dst, i8mem:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX32rr8 GR32:$dst, GR8:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX32rr16 GR32:$dst, GR16:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX64rr8_Q GR64:$dst, GR8:$src), 0>; +def : InstAlias<"movzx $src, $dst", (MOVZX64rr16_Q GR64:$dst, GR16:$src), 0>; // Note: No GR32->GR64 movzx form. // outb %dx -> outb %al, %dx Modified: llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll (original) +++ llvm/trunk/test/CodeGen/X86/2006-11-17-IllegalMove.ll Wed Apr 13 20:46:37 2011 @@ -1,6 +1,6 @@ ; RUN: llc < %s -march=x86-64 > %t ; RUN: grep movb %t | count 2 -; RUN: grep {movzx} %t +; RUN: grep {movzb\[wl\]} %t define void @handle_vector_size_attribute() nounwind { Modified: llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll (original) +++ llvm/trunk/test/CodeGen/X86/2007-08-10-SignExtSubreg.ll Wed Apr 13 20:46:37 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 | grep {movsx} +; RUN: llc < %s -march=x86 | grep {movsbl} @X = global i32 0 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll (original) +++ llvm/trunk/test/CodeGen/X86/2008-08-17-UComiCodeGenBug.ll Wed Apr 13 20:46:37 2011 @@ -1,10 +1,9 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-apple-darwin | grep movzbl define i32 @foo(<4 x float> %a, <4 x float> %b) nounwind { entry: -; CHECK: movzx - tail call i32 @llvm.x86.sse.ucomige.ss( <4 x float> %a, <4 x float> %b ) nounwind readnone - ret i32 %0 + tail call i32 @llvm.x86.sse.ucomige.ss( <4 x float> %a, <4 x float> %b ) nounwind readnone + ret i32 %0 } declare i32 @llvm.x86.sse.ucomige.ss(<4 x float>, <4 x float>) nounwind readnone Modified: llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll (original) +++ llvm/trunk/test/CodeGen/X86/2009-06-05-VZextByteShort.ll Wed Apr 13 20:46:37 2011 @@ -1,8 +1,9 @@ -; RUN: llc < %s -march=x86 -mattr=+mmx,+sse2 | FileCheck %s +; RUN: llc < %s -march=x86 -mattr=+mmx,+sse2 > %t1 +; RUN: grep movzwl %t1 | count 2 +; RUN: grep movzbl %t1 | count 2 +; RUN: grep movd %t1 | count 4 define <4 x i16> @a(i32* %x1) nounwind { -; CHECK: movzx -; CHECK-NEXT: movd %x2 = load i32* %x1 %x3 = lshr i32 %x2, 1 %x = trunc i32 %x3 to i16 @@ -11,8 +12,6 @@ } define <8 x i16> @b(i32* %x1) nounwind { -; CHECK: movzx -; CHECK-NEXT: movd %x2 = load i32* %x1 %x3 = lshr i32 %x2, 1 %x = trunc i32 %x3 to i16 @@ -21,8 +20,6 @@ } define <8 x i8> @c(i32* %x1) nounwind { -; CHECK: movzx -; CHECK-NEXT: movd %x2 = load i32* %x1 %x3 = lshr i32 %x2, 1 %x = trunc i32 %x3 to i8 @@ -31,8 +28,6 @@ } define <16 x i8> @d(i32* %x1) nounwind { -; CHECK: movzx -; CHECK-NEXT: movd %x2 = load i32* %x1 %x3 = lshr i32 %x2, 1 %x = trunc i32 %x3 to i8 Modified: llvm/trunk/test/CodeGen/X86/anyext.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/anyext.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/anyext.ll (original) +++ llvm/trunk/test/CodeGen/X86/anyext.ll Wed Apr 13 20:46:37 2011 @@ -1,10 +1,8 @@ -; RUN: llc < %s -march=x86-64 | FileCheck %s +; RUN: llc < %s -march=x86-64 | grep movzbl | count 2 -; Use movzbl (aliased as movzx) to avoid partial-register updates. +; Use movzbl to avoid partial-register updates. define i32 @foo(i32 %p, i8 zeroext %x) nounwind { -; CHECK: movzx %dil, %eax -; CHECK: movzx %al, %eax %q = trunc i32 %p to i8 %r = udiv i8 %q, %x %s = zext i8 %r to i32 Modified: llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-intrinsics-x86.ll Wed Apr 13 20:46:37 2011 @@ -75,7 +75,7 @@ define i32 @test_x86_sse2_comieq_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.comieq.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -85,7 +85,7 @@ define i32 @test_x86_sse2_comige_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: setae - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.comige.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -95,7 +95,7 @@ define i32 @test_x86_sse2_comigt_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.comigt.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -105,7 +105,7 @@ define i32 @test_x86_sse2_comile_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: setbe - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.comile.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -125,7 +125,7 @@ define i32 @test_x86_sse2_comineq_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vcomisd ; CHECK: setne - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.comineq.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -786,7 +786,7 @@ define i32 @test_x86_sse2_ucomieq_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.ucomieq.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -796,7 +796,7 @@ define i32 @test_x86_sse2_ucomige_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: setae - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.ucomige.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -806,7 +806,7 @@ define i32 @test_x86_sse2_ucomigt_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.ucomigt.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -816,7 +816,7 @@ define i32 @test_x86_sse2_ucomile_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: setbe - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.ucomile.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -835,7 +835,7 @@ define i32 @test_x86_sse2_ucomineq_sd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vucomisd ; CHECK: setne - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse2.ucomineq.sd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -1192,7 +1192,7 @@ define i32 @test_x86_sse41_ptestnzc(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vptest ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse41.ptestnzc(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1202,7 +1202,7 @@ define i32 @test_x86_sse41_ptestz(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vptest ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse41.ptestz(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1414,7 +1414,7 @@ define i32 @test_x86_sse_comieq_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.comieq.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1424,7 +1424,7 @@ define i32 @test_x86_sse_comige_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: setae - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.comige.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1434,7 +1434,7 @@ define i32 @test_x86_sse_comigt_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.comigt.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1444,7 +1444,7 @@ define i32 @test_x86_sse_comile_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: setbe - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.comile.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1463,7 +1463,7 @@ define i32 @test_x86_sse_comineq_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vcomiss ; CHECK: setne - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.comineq.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1655,7 +1655,7 @@ define i32 @test_x86_sse_ucomieq_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.ucomieq.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1665,7 +1665,7 @@ define i32 @test_x86_sse_ucomige_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: setae - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.ucomige.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1675,7 +1675,7 @@ define i32 @test_x86_sse_ucomigt_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.ucomigt.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1685,7 +1685,7 @@ define i32 @test_x86_sse_ucomile_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: setbe - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.ucomile.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -1704,7 +1704,7 @@ define i32 @test_x86_sse_ucomineq_ss(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vucomiss ; CHECK: setne - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.sse.ucomineq.ss(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -2179,7 +2179,7 @@ define i32 @test_x86_avx_ptestnzc_256(<4 x i64> %a0, <4 x i64> %a1) { ; CHECK: vptest ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.ptestnzc.256(<4 x i64> %a0, <4 x i64> %a1) ; [#uses=1] ret i32 %res } @@ -2189,7 +2189,7 @@ define i32 @test_x86_avx_ptestz_256(<4 x i64> %a0, <4 x i64> %a1) { ; CHECK: vptest ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.ptestz.256(<4 x i64> %a0, <4 x i64> %a1) ; [#uses=1] ret i32 %res } @@ -2483,7 +2483,7 @@ define i32 @test_x86_avx_vtestnzc_pd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vtestpd ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.vtestnzc.pd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -2493,7 +2493,7 @@ define i32 @test_x86_avx_vtestnzc_pd_256(<4 x double> %a0, <4 x double> %a1) { ; CHECK: vtestpd ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.vtestnzc.pd.256(<4 x double> %a0, <4 x double> %a1) ; [#uses=1] ret i32 %res } @@ -2503,7 +2503,7 @@ define i32 @test_x86_avx_vtestnzc_ps(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vtestps ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.vtestnzc.ps(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -2513,7 +2513,7 @@ define i32 @test_x86_avx_vtestnzc_ps_256(<8 x float> %a0, <8 x float> %a1) { ; CHECK: vtestps ; CHECK: seta - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.vtestnzc.ps.256(<8 x float> %a0, <8 x float> %a1) ; [#uses=1] ret i32 %res } @@ -2523,7 +2523,7 @@ define i32 @test_x86_avx_vtestz_pd(<2 x double> %a0, <2 x double> %a1) { ; CHECK: vtestpd ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.vtestz.pd(<2 x double> %a0, <2 x double> %a1) ; [#uses=1] ret i32 %res } @@ -2533,7 +2533,7 @@ define i32 @test_x86_avx_vtestz_pd_256(<4 x double> %a0, <4 x double> %a1) { ; CHECK: vtestpd ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.vtestz.pd.256(<4 x double> %a0, <4 x double> %a1) ; [#uses=1] ret i32 %res } @@ -2543,7 +2543,7 @@ define i32 @test_x86_avx_vtestz_ps(<4 x float> %a0, <4 x float> %a1) { ; CHECK: vtestps ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.vtestz.ps(<4 x float> %a0, <4 x float> %a1) ; [#uses=1] ret i32 %res } @@ -2553,7 +2553,7 @@ define i32 @test_x86_avx_vtestz_ps_256(<8 x float> %a0, <8 x float> %a1) { ; CHECK: vtestps ; CHECK: sete - ; CHECK: movzx + ; CHECK: movzbl %res = call i32 @llvm.x86.avx.vtestz.ps.256(<8 x float> %a0, <8 x float> %a1) ; [#uses=1] ret i32 %res } Modified: llvm/trunk/test/CodeGen/X86/bool-zext.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/bool-zext.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/bool-zext.ll (original) +++ llvm/trunk/test/CodeGen/X86/bool-zext.ll Wed Apr 13 20:46:37 2011 @@ -1,7 +1,7 @@ ; RUN: llc < %s -march=x86-64 | FileCheck %s ; CHECK: @bar1 -; CHECK: movzx +; CHECK: movzbl ; CHECK: callq define void @bar1(i1 zeroext %v1) nounwind ssp { entry: @@ -11,7 +11,7 @@ } ; CHECK: @bar2 -; CHECK-NOT: movzx +; CHECK-NOT: movzbl ; CHECK: callq define void @bar2(i8 zeroext %v1) nounwind ssp { entry: @@ -22,7 +22,7 @@ ; CHECK: @bar3 ; CHECK: callq -; CHECK-NOT: movzx +; CHECK-NOT: movzbl ; CHECK-NOT: and ; CHECK: ret define zeroext i1 @bar3() nounwind ssp { Modified: llvm/trunk/test/CodeGen/X86/cmov.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cmov.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/cmov.ll (original) +++ llvm/trunk/test/CodeGen/X86/cmov.ll Wed Apr 13 20:46:37 2011 @@ -121,7 +121,7 @@ entry: ; CHECK: test5: ; CHECK: setg %al -; CHECK: movzx %al, %eax +; CHECK: movzbl %al, %eax ; CHECK: orl $-2, %eax ; CHECK: ret @@ -135,7 +135,7 @@ entry: ; CHECK: test6: ; CHECK: setl %al -; CHECK: movzx %al, %eax +; CHECK: movzbl %al, %eax ; CHECK: leal 4(%rax,%rax,8), %eax ; CHECK: ret %0 = load i32* %P, align 4 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/cmp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/cmp.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/cmp.ll (original) +++ llvm/trunk/test/CodeGen/X86/cmp.ll Wed Apr 13 20:46:37 2011 @@ -38,7 +38,7 @@ ; CHECK: test3: ; CHECK: testq %rdi, %rdi ; CHECK: sete %al -; CHECK: movzx %al, %eax +; CHECK: movzbl %al, %eax ; CHECK: ret } @@ -49,7 +49,7 @@ ; CHECK: test4: ; CHECK: testq %rdi, %rdi ; CHECK: setle %al -; CHECK: movzx %al, %eax +; CHECK: movzbl %al, %eax ; CHECK: ret } Modified: llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll (original) +++ llvm/trunk/test/CodeGen/X86/fast-isel-gep.ll Wed Apr 13 20:46:37 2011 @@ -14,7 +14,7 @@ ; X32: ret ; X64: test1: -; X64: movsx %e[[A0:di|cx]], %rax +; X64: movslq %e[[A0:di|cx]], %rax ; X64: movl (%r[[A1:si|dx]],%rax,4), %eax ; X64: ret @@ -81,7 +81,7 @@ %v11 = add i64 %B, %v10 ret i64 %v11 ; X64: test5: -; X64: movsx %e[[A1]], %rax +; X64: movslq %e[[A1]], %rax ; X64-NEXT: movq (%r[[A0]],%rax), %rax ; X64-NEXT: addq %{{rdx|r8}}, %rax ; X64-NEXT: ret Modified: llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll (original) +++ llvm/trunk/test/CodeGen/X86/h-register-addressing-32.ll Wed Apr 13 20:46:37 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 | grep {movzx %\[abcd\]h,} | count 7 +; RUN: llc < %s -march=x86 | grep {movzbl %\[abcd\]h,} | count 7 ; Use h-register extract and zero-extend. Modified: llvm/trunk/test/CodeGen/X86/h-registers-0.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/h-registers-0.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/h-registers-0.ll (original) +++ llvm/trunk/test/CodeGen/X86/h-registers-0.ll Wed Apr 13 20:46:37 2011 @@ -70,7 +70,7 @@ ; WIN64: movzbl %ch, %eax ; X86-32: qux64: -; X86-32: movzx %ah, %eax +; X86-32: movzbl %ah, %eax %t0 = lshr i64 %x, 8 %t1 = and i64 %t0, 255 ret i64 %t1 @@ -85,7 +85,7 @@ ; WIN64: movzbl %ch, %eax ; X86-32: qux32: -; X86-32: movzx %ah, %eax +; X86-32: movzbl %ah, %eax %t0 = lshr i32 %x, 8 %t1 = and i32 %t0, 255 ret i32 %t1 @@ -100,7 +100,7 @@ ; WIN64: movzbl %ch, %eax ; X86-32: qux16: -; X86-32: movzx %ah, %eax +; X86-32: movzbl %ah, %eax %t0 = lshr i16 %x, 8 ret i16 %t0 } Modified: llvm/trunk/test/CodeGen/X86/h-registers-2.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/h-registers-2.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/h-registers-2.ll (original) +++ llvm/trunk/test/CodeGen/X86/h-registers-2.ll Wed Apr 13 20:46:37 2011 @@ -1,5 +1,5 @@ ; RUN: llc < %s -march=x86 > %t -; RUN: grep {movzx %\[abcd\]h,} %t | count 1 +; RUN: grep {movzbl %\[abcd\]h,} %t | count 1 ; RUN: grep {shll \$3,} %t | count 1 ; Use an h register, but don't omit the explicit shift for Modified: llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll (original) +++ llvm/trunk/test/CodeGen/X86/inline-asm-mrv.ll Wed Apr 13 20:46:37 2011 @@ -1,5 +1,5 @@ ; PR2094 -; RUN: llc < %s -march=x86-64 | grep movsx +; RUN: llc < %s -march=x86-64 | grep movslq ; RUN: llc < %s -march=x86-64 | grep addps ; RUN: llc < %s -march=x86-64 | grep paddd ; RUN: llc < %s -march=x86-64 | not grep movq Modified: llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll (original) +++ llvm/trunk/test/CodeGen/X86/masked-iv-unsafe.ll Wed Apr 13 20:46:37 2011 @@ -1,6 +1,6 @@ ; RUN: llc < %s -march=x86-64 > %t ; RUN: grep and %t | count 6 -; RUN: grep movzx %t | count 6 +; RUN: grep movzb %t | count 6 ; RUN: grep sar %t | count 12 ; Don't optimize away zext-inreg and sext-inreg on the loop induction Modified: llvm/trunk/test/CodeGen/X86/pr3366.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pr3366.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/pr3366.ll (original) +++ llvm/trunk/test/CodeGen/X86/pr3366.ll Wed Apr 13 20:46:37 2011 @@ -1,7 +1,6 @@ -; RUN: llc < %s -march=x86 -disable-cgp-branch-opts | FileCheck %s +; RUN: llc < %s -march=x86 -disable-cgp-branch-opts | grep movzbl ; PR3366 -; CHECK: movzx define void @_ada_c34002a() nounwind { entry: %0 = load i8* null, align 1 Modified: llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll (original) +++ llvm/trunk/test/CodeGen/X86/promote-assert-zext.ll Wed Apr 13 20:46:37 2011 @@ -7,7 +7,7 @@ ; ISel doesn't yet know how to eliminate this extra zero-extend. But until ; it knows how to do so safely, it shouldn;t eliminate it. ; CHECK: movzbl (%rdi), %eax -; CHECK: movzx %ax, %eax +; CHECK: movzwl %ax, %eax define i64 @_ZL5matchPKtPKhiR9MatchData(i8* %tmp13) nounwind { entry: Modified: llvm/trunk/test/CodeGen/X86/promote-i16.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/promote-i16.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/promote-i16.ll (original) +++ llvm/trunk/test/CodeGen/X86/promote-i16.ll Wed Apr 13 20:46:37 2011 @@ -4,8 +4,8 @@ entry: ; CHECK: foo: ; CHECK: movzwl 4(%esp), %eax -; CHECK: xorl $21998, %eax -; CHECK: movsx %ax, %eax +; CHECK: xorl $21998, %eax +; CHECK: movswl %ax, %eax %0 = xor i16 %x, 21998 ret i16 %0 } Modified: llvm/trunk/test/CodeGen/X86/select.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/select.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/select.ll (original) +++ llvm/trunk/test/CodeGen/X86/select.ll Wed Apr 13 20:46:37 2011 @@ -30,7 +30,7 @@ ret i32 0 ; CHECK: test2: ; CHECK: movnew -; CHECK: movsx +; CHECK: movswl } declare i1 @return_false() Modified: llvm/trunk/test/CodeGen/X86/setcc.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/setcc.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/setcc.ll (original) +++ llvm/trunk/test/CodeGen/X86/setcc.ll Wed Apr 13 20:46:37 2011 @@ -8,7 +8,7 @@ entry: ; CHECK: t1: ; CHECK: seta %al -; CHECK: movzx %al, %eax +; CHECK: movzbl %al, %eax ; CHECK: shll $5, %eax %0 = icmp ugt i16 %x, 26 ; [#uses=1] %iftmp.1.0 = select i1 %0, i16 32, i16 0 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/sext-ret-val.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/sext-ret-val.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/sext-ret-val.ll (original) +++ llvm/trunk/test/CodeGen/X86/sext-ret-val.ll Wed Apr 13 20:46:37 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s -march=x86 | grep movzx | count 1 +; RUN: llc < %s -march=x86 | grep movzbl | count 1 ; rdar://6699246 define signext i8 @t1(i8* %A) nounwind readnone ssp { Modified: llvm/trunk/test/CodeGen/X86/sext-subreg.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/sext-subreg.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/sext-subreg.ll (original) +++ llvm/trunk/test/CodeGen/X86/sext-subreg.ll Wed Apr 13 20:46:37 2011 @@ -3,7 +3,7 @@ define i64 @t(i64 %A, i64 %B, i32* %P, i64 *%P2) nounwind { ; CHECK: t: -; CHECK: movsx %e{{.*}}, %rax +; CHECK: movslq %e{{.*}}, %rax ; CHECK: movq %rax ; CHECK: movl %eax %C = add i64 %A, %B Modified: llvm/trunk/test/CodeGen/X86/shl_elim.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/shl_elim.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/shl_elim.ll (original) +++ llvm/trunk/test/CodeGen/X86/shl_elim.ll Wed Apr 13 20:46:37 2011 @@ -1,6 +1,6 @@ ; RUN: llc < %s -march=x86 | grep {movl 8(.esp), %eax} ; RUN: llc < %s -march=x86 | grep {shrl .eax} -; RUN: llc < %s -march=x86 | grep {movsx .ax, .eax} +; RUN: llc < %s -march=x86 | grep {movswl .ax, .eax} define i32 @test1(i64 %a) nounwind { %tmp29 = lshr i64 %a, 24 ; [#uses=1] Modified: llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll (original) +++ llvm/trunk/test/CodeGen/X86/umul-with-overflow.ll Wed Apr 13 20:46:37 2011 @@ -9,6 +9,6 @@ ; CHECK: a: ; CHECK: mull ; CHECK: seto %al -; CHECK: movzx %al, %eax +; CHECK: movzbl %al, %eax ; CHECK: ret } Modified: llvm/trunk/test/CodeGen/X86/vshift-4.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vshift-4.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vshift-4.ll (original) +++ llvm/trunk/test/CodeGen/X86/vshift-4.ll Wed Apr 13 20:46:37 2011 @@ -57,7 +57,7 @@ define void @shift3a(<8 x i16> %val, <8 x i16>* %dst, <8 x i16> %amt) nounwind { entry: ; CHECK: shift3a: -; CHECK: movzx +; CHECK: movzwl ; CHECK: psllw %shamt = shufflevector <8 x i16> %amt, <8 x i16> undef, <8 x i32> %shl = shl <8 x i16> %val, %shamt Modified: llvm/trunk/test/CodeGen/X86/widen_conv-2.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/widen_conv-2.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/widen_conv-2.ll (original) +++ llvm/trunk/test/CodeGen/X86/widen_conv-2.ll Wed Apr 13 20:46:37 2011 @@ -1,6 +1,6 @@ ; RUN: llc < %s -march=x86 -mattr=+sse42 | FileCheck %s -; CHECK: movsx -; CHECK: movsx +; CHECK: movswl +; CHECK: movswl ; sign extension v2i32 to v2i16 Modified: llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll (original) +++ llvm/trunk/test/CodeGen/X86/x86-64-shortint.ll Wed Apr 13 20:46:37 2011 @@ -1,4 +1,4 @@ -; RUN: llc < %s | grep movsx +; RUN: llc < %s | grep movswl target datalayout = "e-p:64:64" target triple = "x86_64-apple-darwin8" Modified: llvm/trunk/test/MC/X86/x86-64.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/X86/x86-64.s?rev=129498&r1=129497&r2=129498&view=diff ============================================================================== --- llvm/trunk/test/MC/X86/x86-64.s (original) +++ llvm/trunk/test/MC/X86/x86-64.s Wed Apr 13 20:46:37 2011 @@ -681,65 +681,65 @@ // CHECK: encoding: [0x48,0x0f,0xba,0xe2,0x01] //rdar://8017633 -// CHECK: movzx %al, %esi +// CHECK: movzbl %al, %esi // CHECK: encoding: [0x0f,0xb6,0xf0] movzx %al, %esi -// CHECK: movzx %al, %rsi +// CHECK: movzbq %al, %rsi // CHECK: encoding: [0x48,0x0f,0xb6,0xf0] movzx %al, %rsi -// CHECK: movsx %al, %ax +// CHECK: movsbw %al, %ax // CHECK: encoding: [0x66,0x0f,0xbe,0xc0] - movsx %al, %ax +movsx %al, %ax -// CHECK: movsx %al, %eax +// CHECK: movsbl %al, %eax // CHECK: encoding: [0x0f,0xbe,0xc0] - movsx %al, %eax +movsx %al, %eax -// CHECK: movsx %ax, %eax +// CHECK: movswl %ax, %eax // CHECK: encoding: [0x0f,0xbf,0xc0] - movsx %ax, %eax +movsx %ax, %eax -// CHECK: movsx %bl, %rax +// CHECK: movsbq %bl, %rax // CHECK: encoding: [0x48,0x0f,0xbe,0xc3] - movsx %bl, %rax +movsx %bl, %rax -// CHECK: movsx %cx, %rax +// CHECK: movswq %cx, %rax // CHECK: encoding: [0x48,0x0f,0xbf,0xc1] - movsx %cx, %rax +movsx %cx, %rax -// CHECK: movsx %edi, %rax +// CHECK: movslq %edi, %rax // CHECK: encoding: [0x48,0x63,0xc7] - movsx %edi, %rax +movsx %edi, %rax -// CHECK: movzx %al, %ax +// CHECK: movzbw %al, %ax // CHECK: encoding: [0x66,0x0f,0xb6,0xc0] - movzx %al, %ax +movzx %al, %ax -// CHECK: movzx %al, %eax +// CHECK: movzbl %al, %eax // CHECK: encoding: [0x0f,0xb6,0xc0] - movzx %al, %eax +movzx %al, %eax -// CHECK: movzx %ax, %eax +// CHECK: movzwl %ax, %eax // CHECK: encoding: [0x0f,0xb7,0xc0] - movzx %ax, %eax +movzx %ax, %eax -// CHECK: movzx %bl, %rax +// CHECK: movzbq %bl, %rax // CHECK: encoding: [0x48,0x0f,0xb6,0xc3] - movzx %bl, %rax +movzx %bl, %rax -// CHECK: movzx %cx, %rax +// CHECK: movzwq %cx, %rax // CHECK: encoding: [0x48,0x0f,0xb7,0xc1] - movzx %cx, %rax +movzx %cx, %rax // CHECK: movsbw (%rax), %ax // CHECK: encoding: [0x66,0x0f,0xbe,0x00] - movsx (%rax), %ax +movsx (%rax), %ax // CHECK: movzbw (%rax), %ax // CHECK: encoding: [0x66,0x0f,0xb6,0x00] - movzx (%rax), %ax +movzx (%rax), %ax // rdar://7873482 From sabre at nondot.org Wed Apr 13 21:27:25 2011 From: sabre at nondot.org (Chris Lattner) Date: Thu, 14 Apr 2011 02:27:25 -0000 Subject: [llvm-commits] [llvm] r129501 - /llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Message-ID: <20110414022725.DF2C52A6C12C@llvm.org> Author: lattner Date: Wed Apr 13 21:27:25 2011 New Revision: 129501 URL: http://llvm.org/viewvc/llvm-project?rev=129501&view=rev Log: fix a couple -Wsign-compare warnings. Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=129501&r1=129500&r2=129501&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Wed Apr 13 21:27:25 2011 @@ -44,8 +44,8 @@ public: static char ID; // Pass ID, replacement for typeid LoopUnroll(int T = -1, int C = -1, int P = -1) : LoopPass(ID) { - CurrentThreshold = (T == -1) ? UnrollThreshold : T; - CurrentCount = (C == -1) ? UnrollCount : C; + CurrentThreshold = (T == -1) ? UnrollThreshold : unsigned(T); + CurrentCount = (C == -1) ? UnrollCount : unsigned(C); CurrentAllowPartial = (P == -1) ? UnrollAllowPartial : (bool)P; UserThreshold = (T != -1) || (UnrollThreshold.getNumOccurrences() > 0); From sabre at nondot.org Wed Apr 13 21:44:53 2011 From: sabre at nondot.org (Chris Lattner) Date: Thu, 14 Apr 2011 02:44:53 -0000 Subject: [llvm-commits] [llvm] r129502 - /llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Message-ID: <20110414024453.43D222A6C12C@llvm.org> Author: lattner Date: Wed Apr 13 21:44:53 2011 New Revision: 129502 URL: http://llvm.org/viewvc/llvm-project?rev=129502&view=rev Log: rework FoldBranchToCommonDest to exit earlier when there is a bonus instruction around, reducing work. Greatly simplify handling of debug instructions. There is no need to build up a vector of them and then move them into the one predecessor if we're processing a block. Instead just rescan the block and *copy* them into the pred. If a block gets merged into multiple preds, this will retain more debug info. Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=129502&r1=129501&r2=129502&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Wed Apr 13 21:44:53 2011 @@ -1411,16 +1411,13 @@ Cond->getParent() != BB || !Cond->hasOneUse()) return false; - SmallVector DbgValues; // Only allow this if the condition is a simple instruction that can be // executed unconditionally. It must be in the same block as the branch, and // must be at the front of the block. BasicBlock::iterator FrontIt = BB->front(); + // Ignore dbg intrinsics. - while (DbgInfoIntrinsic *DBI = dyn_cast(FrontIt)) { - DbgValues.push_back(DBI); - ++FrontIt; - } + while (isa(FrontIt)) ++FrontIt; // Allow a single instruction to be hoisted in addition to the compare // that feeds the branch. We later ensure that any values that _it_ uses @@ -1432,12 +1429,9 @@ FrontIt->isSafeToSpeculativelyExecute()) { BonusInst = &*FrontIt; ++FrontIt; - } - - // Ignore dbg intrinsics. - while (DbgInfoIntrinsic *DBI = dyn_cast(FrontIt)) { - DbgValues.push_back(DBI); - ++FrontIt; + + // Ignore dbg intrinsics. + while (isa(FrontIt)) ++FrontIt; } // Only a single bonus inst is allowed. @@ -1446,15 +1440,12 @@ // Make sure the instruction after the condition is the cond branch. BasicBlock::iterator CondIt = Cond; ++CondIt; + // Ingore dbg intrinsics. - while(DbgInfoIntrinsic *DBI = dyn_cast(CondIt)) { - DbgValues.push_back(DBI); - ++CondIt; - } - if (&*CondIt != BI) { - assert (!isa(CondIt) && "Hey do not forget debug info!"); + while (isa(CondIt)) ++CondIt; + + if (&*CondIt != BI) return false; - } // Cond is known to be a compare or binary operator. Check to make sure that // neither operand is a potentially-trapping constant expression. @@ -1465,7 +1456,6 @@ if (CE->canTrap()) return false; - // Finally, don't infinitely unroll conditional loops. BasicBlock *TrueDest = BI->getSuccessor(0); BasicBlock *FalseDest = BI->getSuccessor(1); @@ -1479,10 +1469,24 @@ // Check that we have two conditional branches. If there is a PHI node in // the common successor, verify that the same value flows in from both // blocks. - if (PBI == 0 || PBI->isUnconditional() || - !SafeToMergeTerminators(BI, PBI)) + if (PBI == 0 || PBI->isUnconditional() || !SafeToMergeTerminators(BI, PBI)) continue; + // Determine if the two branches share a common destination. + Instruction::BinaryOps Opc; + bool InvertPredCond = false; + + if (PBI->getSuccessor(0) == TrueDest) + Opc = Instruction::Or; + else if (PBI->getSuccessor(1) == FalseDest) + Opc = Instruction::And; + else if (PBI->getSuccessor(0) == FalseDest) + Opc = Instruction::And, InvertPredCond = true; + else if (PBI->getSuccessor(1) == TrueDest) + Opc = Instruction::Or, InvertPredCond = true; + else + continue; + // Ensure that any values used in the bonus instruction are also used // by the terminator of the predecessor. This means that those values // must already have been resolved, so we won't be inhibiting the @@ -1520,20 +1524,6 @@ if (!UsedValues.empty()) return false; } - - Instruction::BinaryOps Opc; - bool InvertPredCond = false; - - if (PBI->getSuccessor(0) == TrueDest) - Opc = Instruction::Or; - else if (PBI->getSuccessor(1) == FalseDest) - Opc = Instruction::And; - else if (PBI->getSuccessor(0) == FalseDest) - Opc = Instruction::And, InvertPredCond = true; - else if (PBI->getSuccessor(1) == TrueDest) - Opc = Instruction::Or, InvertPredCond = true; - else - continue; DEBUG(dbgs() << "FOLDING BRANCH TO COMMON DEST:\n" << *PBI << *BB); @@ -1585,10 +1575,11 @@ PBI->setSuccessor(1, FalseDest); } - // Move dbg value intrinsics in PredBlock. - for (SmallVector::iterator DBI = DbgValues.begin(), - DBE = DbgValues.end(); DBI != DBE; ++DBI) - (*DBI)->moveBefore(PBI); + // Copy any debug value intrinsics into the end of PredBlock. + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) + if (isa(*I)) + I->clone()->insertBefore(PBI); + return true; } return false; From wangmp at apple.com Wed Apr 13 22:58:29 2011 From: wangmp at apple.com (Mon Ping Wang) Date: Wed, 13 Apr 2011 20:58:29 -0700 Subject: [llvm-commits] [llvm] r129472 - in /llvm/trunk: lib/Transforms/Scalar/ScalarReplAggregates.cpp test/Transforms/ScalarRepl/vector_promote.ll In-Reply-To: References: <20110413214002.89C1D2A6C12C@llvm.org> Message-ID: <9920C2B9-59C9-469B-A9DD-C9DDD75D6223@apple.com> Hi, That sounds like a good idea. I'll do that. -- Mon Ping On Apr 13, 2011, at 5:18 PM, Eli Friedman wrote: > On Wed, Apr 13, 2011 at 2:40 PM, Mon P Wang wrote: >> Author: wangmp >> Date: Wed Apr 13 16:40:02 2011 >> New Revision: 129472 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=129472&view=rev >> Log: >> Vectors with different number of elements of the same element type can have >> the same allocation size but different primitive sizes(e.g., <3xi32> and >> <4xi32>). When ScalarRepl promotes them, it can't use a bit cast but >> should use a shuffle vector instead. >> >> Modified: >> llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp >> llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll >> >> Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=129472&r1=129471&r2=129472&view=diff >> ============================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) >> +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Wed Apr 13 16:40:02 2011 >> @@ -690,15 +690,45 @@ >> ConvertScalar_ExtractValue(Value *FromVal, const Type *ToType, >> uint64_t Offset, IRBuilder<> &Builder) { >> // If the load is of the whole new alloca, no conversion is needed. >> - if (FromVal->getType() == ToType && Offset == 0) >> + const Type *FromType = FromVal->getType(); >> + if (FromType == ToType && Offset == 0) >> return FromVal; >> >> // If the result alloca is a vector type, this is either an element >> // access or a bitcast to another vector type of the same size. >> - if (const VectorType *VTy = dyn_cast(FromVal->getType())) { >> + if (const VectorType *VTy = dyn_cast(FromType)) { >> unsigned ToTypeSize = TD.getTypeAllocSize(ToType); >> - if (ToTypeSize == AllocaSize) >> - return Builder.CreateBitCast(FromVal, ToType, "tmp"); >> + if (ToTypeSize == AllocaSize) { >> + if (FromType->getPrimitiveSizeInBits() == >> + ToType->getPrimitiveSizeInBits()) >> + return Builder.CreateBitCast(FromVal, ToType, "tmp"); >> + else { >> + // Vectors with the same element type can have the same allocation >> + // size but different primitive sizes (e.g., <3 x i32> and <4 x i32>) >> + // In this case, use a shuffle vector instead of a bit cast. >> + const VectorType *ToVTy = dyn_cast(ToType); >> + assert(ToVTy && (ToVTy->getElementType() == VTy->getElementType()) && >> + "Vectors must have the same element type"); >> + LLVMContext &Context = FromVal->getContext(); >> + Value *UnV = UndefValue::get(FromType); >> + unsigned numEltsFrom = VTy->getNumElements(); >> + unsigned numEltsTo = ToVTy->getNumElements(); >> + >> + SmallVector Args; >> + unsigned minNumElts = std::min(numEltsFrom, numEltsTo); >> + unsigned i; >> + for (i=0; i != minNumElts; ++i) >> + Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); >> + >> + if (i < numEltsTo) { >> + Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); >> + for (; i != numEltsTo; ++i) >> + Args.push_back(UnC); >> + } >> + Constant *Mask = ConstantVector::get(Args); >> + return Builder.CreateShuffleVector(FromVal, UnV, Mask, "tmpV"); >> + } >> + } >> >> if (ToType->isVectorTy()) { >> assert(isPowerOf2_64(AllocaSize / ToTypeSize) && >> @@ -837,8 +867,36 @@ >> >> // Changing the whole vector with memset or with an access of a different >> // vector type? >> - if (ValSize == VecSize) >> - return Builder.CreateBitCast(SV, AllocaType, "tmp"); >> + if (ValSize == VecSize) { >> + if (VTy->getPrimitiveSizeInBits() == >> + SV->getType()->getPrimitiveSizeInBits()) >> + return Builder.CreateBitCast(SV, AllocaType, "tmp"); >> + else { >> + // Vectors with the same element type can have the same allocation >> + // size but different primitive sizes (e.g., <3 x i32> and <4 x i32>) >> + // In this case, use a shuffle vector instead of a bit cast. >> + const VectorType *SVVTy = dyn_cast(SV->getType()); >> + assert(SVVTy && (SVVTy->getElementType() == VTy->getElementType()) && >> + "Vectors must have the same element type"); >> + Value *UnV = UndefValue::get(SVVTy); >> + unsigned numEltsFrom = SVVTy->getNumElements(); >> + unsigned numEltsTo = VTy->getNumElements(); >> + >> + SmallVector Args; >> + unsigned minNumElts = std::min(numEltsFrom, numEltsTo); >> + unsigned i; >> + for (i=0; i != minNumElts; ++i) >> + Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); >> + >> + if (i < numEltsTo) { >> + Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); >> + for (; i != numEltsTo; ++i) >> + Args.push_back(UnC); >> + } >> + Constant *Mask = ConstantVector::get(Args); >> + return Builder.CreateShuffleVector(SV, UnV, Mask, "tmpV"); >> + } >> + } >> >> if (SV->getType()->isVectorTy() && isPowerOf2_64(VecSize / ValSize)) { >> assert(Offset == 0 && "Can't insert a value of a smaller vector type at " > > Can you refactor the duplicated code into a helper routine? > > -Eli > >> Modified: llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll?rev=129472&r1=129471&r2=129472&view=diff >> ============================================================================== >> --- llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll (original) >> +++ llvm/trunk/test/Transforms/ScalarRepl/vector_promote.ll Wed Apr 13 16:40:02 2011 >> @@ -202,3 +202,49 @@ >> ; CHECK-NOT: alloca >> ; CHECK: bitcast <4 x float> %x to i128 >> } >> + >> +define <3 x float> @test14(<3 x float> %x) { >> +entry: >> + %x.addr = alloca <3 x float>, align 16 >> + %r = alloca <3 x i32>, align 16 >> + %extractVec = shufflevector <3 x float> %x, <3 x float> undef, <4 x i32> >> + %storetmp = bitcast <3 x float>* %x.addr to <4 x float>* >> + store <4 x float> %extractVec, <4 x float>* %storetmp, align 16 >> + %tmp = load <3 x float>* %x.addr, align 16 >> + %cmp = fcmp une <3 x float> %tmp, zeroinitializer >> + %sext = sext <3 x i1> %cmp to <3 x i32> >> + %and = and <3 x i32> , %sext >> + %extractVec1 = shufflevector <3 x i32> %and, <3 x i32> undef, <4 x i32> >> + %storetmp2 = bitcast <3 x i32>* %r to <4 x i32>* >> + store <4 x i32> %extractVec1, <4 x i32>* %storetmp2, align 16 >> + %tmp3 = load <3 x i32>* %r, align 16 >> + %0 = bitcast <3 x i32> %tmp3 to <3 x float> >> + %tmp4 = load <3 x float>* %x.addr, align 16 >> + ret <3 x float> %tmp4 >> +; CHECK: @test14 >> +; CHECK-NOT: alloca >> +; CHECK: shufflevector <4 x i32> %extractVec1, <4 x i32> undef, <3 x i32> >> +} >> + >> +define void @test15(<3 x i64>* sret %agg.result, <3 x i64> %x, <3 x i64> %min) { >> +entry: >> + %x.addr = alloca <3 x i64>, align 32 >> + %min.addr = alloca <3 x i64>, align 32 >> + %extractVec = shufflevector <3 x i64> %x, <3 x i64> undef, <4 x i32> >> + %storetmp = bitcast <3 x i64>* %x.addr to <4 x i64>* >> + store <4 x i64> %extractVec, <4 x i64>* %storetmp, align 32 >> + %extractVec1 = shufflevector <3 x i64> %min, <3 x i64> undef, <4 x i32> >> + %storetmp2 = bitcast <3 x i64>* %min.addr to <4 x i64>* >> + store <4 x i64> %extractVec1, <4 x i64>* %storetmp2, align 32 >> + %tmp = load <3 x i64>* %x.addr >> + %tmp5 = extractelement <3 x i64> %tmp, i32 0 >> + %tmp11 = insertelement <3 x i64> %tmp, i64 %tmp5, i32 0 >> + store <3 x i64> %tmp11, <3 x i64>* %x.addr >> + %tmp30 = load <3 x i64>* %x.addr, align 32 >> + store <3 x i64> %tmp30, <3 x i64>* %agg.result >> + ret void >> +; CHECK: @test15 >> +; CHECK-NOT: alloca >> +; CHECK: shufflevector <4 x i64> %tmpV2, <4 x i64> undef, <3 x i32> >> +} >> + >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> From sabre at nondot.org Wed Apr 13 23:12:47 2011 From: sabre at nondot.org (Chris Lattner) Date: Thu, 14 Apr 2011 04:12:47 -0000 Subject: [llvm-commits] [llvm] r129503 - /llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Message-ID: <20110414041247.9401D2A6C12C@llvm.org> Author: lattner Date: Wed Apr 13 23:12:47 2011 New Revision: 129503 URL: http://llvm.org/viewvc/llvm-project?rev=129503&view=rev Log: sink a call into its only use. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=129503&r1=129502&r2=129503&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Wed Apr 13 23:12:47 2011 @@ -1849,7 +1849,6 @@ ISD::CondCode Cond, bool foldBooleans, DAGCombinerInfo &DCI, DebugLoc dl) const { SelectionDAG &DAG = DCI.DAG; - LLVMContext &Context = *DAG.getContext(); // These setcc operations always fold. switch (Cond) { @@ -1956,7 +1955,7 @@ } } if (bestWidth) { - EVT newVT = EVT::getIntegerVT(Context, bestWidth); + EVT newVT = EVT::getIntegerVT(*DAG.getContext(), bestWidth); if (newVT.isRound()) { EVT PtrType = Lod->getOperand(1).getValueType(); SDValue Ptr = Lod->getBasePtr(); From sabre at nondot.org Wed Apr 13 23:21:42 2011 From: sabre at nondot.org (Chris Lattner) Date: Thu, 14 Apr 2011 04:21:42 -0000 Subject: [llvm-commits] [llvm] r129504 - /llvm/trunk/lib/Target/README.txt Message-ID: <20110414042142.BA8E32A6C12C@llvm.org> Author: lattner Date: Wed Apr 13 23:21:42 2011 New Revision: 129504 URL: http://llvm.org/viewvc/llvm-project?rev=129504&view=rev Log: add a minor missed dag combine that is blocking mid-level optimization improvements, that will lead to fixing PR6627. Modified: llvm/trunk/lib/Target/README.txt Modified: llvm/trunk/lib/Target/README.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/README.txt?rev=129504&r1=129503&r2=129504&view=diff ============================================================================== --- llvm/trunk/lib/Target/README.txt (original) +++ llvm/trunk/lib/Target/README.txt Wed Apr 13 23:21:42 2011 @@ -2258,3 +2258,79 @@ icmp transform. //===---------------------------------------------------------------------===// + +These functions: +int foo(int *X) { + if ((*X & 255) == 47) + bar(); +} +int foo2(int X) { + if ((X & 255) == 47) + bar(); +} + +codegen to: + + movzbl (%rdi), %eax + cmpl $47, %eax + jne LBB0_2 + +and: + movzbl %dil, %eax + cmpl $47, %eax + jne LBB1_2 + +If a dag combine shrunk the compare to a byte compare, then we'd fold the load +in the first example, and eliminate the movzbl in the second, saving a register. +This can be a target independent dag combine that works on ISD::SETCC, it would +catch this before the legalize ops pass. + +//===---------------------------------------------------------------------===// + +We should optimize this: + + %tmp = load i16* %arrayidx, align 4, !tbaa !0 + %A = trunc i16 %tmp to i8 + %cmp = icmp eq i8 %A, 127 + %B.mask = and i16 %tmp, -256 + %cmp7 = icmp eq i16 %B.mask, 17664 + %or.cond = and i1 %cmp, %cmp7 + br i1 %or.cond, label %land.lhs.true9, label %if.end + +into: + + %tmp = load i16* %arrayidx, align 4, !tbaa !0 + %0 = icmp eq i16 %tmp, 17791 + br i1 %0, label %land.lhs.true9, label %if.end + +with this patch: +Index: InstCombine/InstCombineCompares.cpp +=================================================================== +--- InstCombine/InstCombineCompares.cpp (revision 129500) ++++ InstCombine/InstCombineCompares.cpp (working copy) +@@ -2506,6 +2506,18 @@ + return &I; + } + } ++ ++ // Transform "icmp eq (trunc X), cst" to "icmp (and X, mask), cst" ++ if (Op0->hasOneUse() && match(Op0, m_Trunc(m_Value(A))) && ++ isa(Op1)) { ++ APInt MaskV = APInt::getLowBitsSet(A->getType()->getPrimitiveSizeInBits(), ++ Op0->getType()->getPrimitiveSizeInBits()); ++ Value *Mask = ++ Builder->CreateAnd(A, ConstantInt::get(A->getContext(), MaskV)); ++ return new ICmpInst(I.getPredicate(), Mask, ++ ConstantExpr::getZExt(cast(Op1), ++ Mask->getType())); ++ } + } + + { + + +but we can't do that until the dag combine above is added. Not having this +is blocking resolving PR6627. + +//===---------------------------------------------------------------------===// + From liu205 at illinois.edu Wed Apr 13 23:38:03 2011 From: liu205 at illinois.edu (Shaosu Liu) Date: Thu, 14 Apr 2011 04:38:03 -0000 Subject: [llvm-commits] [poolalloc] r129506 - /poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp Message-ID: <20110414043803.754A62A6C12C@llvm.org> Author: liu205 Date: Wed Apr 13 23:38:03 2011 New Revision: 129506 URL: http://llvm.org/viewvc/llvm-project?rev=129506&view=rev Log: added pool allocfor pool_ functions including memchr, memccpy,strcspn, strspn, strcasecmp,strncascmp,strncmp,strcmp Modified: poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp Modified: poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp?rev=129506&r1=129505&r2=129506&view=diff ============================================================================== --- poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp (original) +++ poolalloc/trunk/lib/PoolAllocate/PoolAllocate.cpp Wed Apr 13 23:38:03 2011 @@ -1568,6 +1568,7 @@ void PoolAllocate::InitializeCStdLibPoolArgs() { CStdLibPoolArgs.GetOrCreateValue("pool_strcpy", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_strncpy", 2); CStdLibPoolArgs.GetOrCreateValue("pool_strlen", 1); CStdLibPoolArgs.GetOrCreateValue("pool_strchr", 1); CStdLibPoolArgs.GetOrCreateValue("pool_strrchr", 1); @@ -1575,6 +1576,16 @@ CStdLibPoolArgs.GetOrCreateValue("pool_strncat", 2); CStdLibPoolArgs.GetOrCreateValue("pool_strstr", 2); CStdLibPoolArgs.GetOrCreateValue("pool_strpbrk", 2); + + CStdLibPoolArgs.GetOrCreateValue("pool_strcmp", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_strncmp", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_memcmp", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_strcasecmp", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_strncasecmp", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_strspn", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_strcspn", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_memccpy", 2); + CStdLibPoolArgs.GetOrCreateValue("pool_memchr", 1); //CStdLibPoolArgs.GetOrCreateValue("pool_strtok", 2); //CStdLibPoolArgs.GetOrCreateValue("pool_strtok_r", 2); //CStdLibPoolArgs.GetOrCreateValue("pool_strspn", 2); From atrick at apple.com Thu Apr 14 00:05:36 2011 From: atrick at apple.com (Andrew Trick) Date: Thu, 14 Apr 2011 05:05:36 -0000 Subject: [llvm-commits] [llvm] r129507 - /llvm/trunk/docs/CommandGuide/bugpoint.pod Message-ID: <20110414050536.803162A6C12C@llvm.org> Author: atrick Date: Thu Apr 14 00:05:36 2011 New Revision: 129507 URL: http://llvm.org/viewvc/llvm-project?rev=129507&view=rev Log: Documented bugpoint --compile-custom --compile-command. I've used it a few times to reduce unit tests and gotten one request for information on it. It's not easy to use correctly because bugpoint doesn't tell you when you're doing it wrong. Modified: llvm/trunk/docs/CommandGuide/bugpoint.pod Modified: llvm/trunk/docs/CommandGuide/bugpoint.pod URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/bugpoint.pod?rev=129507&r1=129506&r2=129507&view=diff ============================================================================== --- llvm/trunk/docs/CommandGuide/bugpoint.pod (original) +++ llvm/trunk/docs/CommandGuide/bugpoint.pod Thu Apr 14 00:05:36 2011 @@ -21,7 +21,7 @@ =head1 OPTIONS -=over +=over =item B<--additional-so> F @@ -87,7 +87,7 @@ =item B<-find-bugs> Continually randomize the specified passes and run them on the test program -until a bug is found or the user kills B. +until a bug is found or the user kills B. =item B<-help> @@ -147,6 +147,20 @@ B<--safe-custom> options to execute the bitcode testcase. This can be useful for cross-compilation. +=item B<--compile-command> I + +This option defines the command to use with the B<--compile-custom> +option to compile the bitcode testcase. This can be useful for +testing compiler output without running any link or execute stages. To +generate a reduced unit test, you may add CHECK directives to the +testcase and pass the name of a compile-command script in this form: + + llc "$@" + not FileCheck [bugpoint input file].ll < bugpoint-test-program.s + +This script will "fail" as long as FileCheck passes. So the result +will be the minimum bitcode that passes FileCheck. + =item B<--safe-path> I This option defines the path to the command to execute with the From atrick at apple.com Thu Apr 14 00:15:06 2011 From: atrick at apple.com (Andrew Trick) Date: Thu, 14 Apr 2011 05:15:06 -0000 Subject: [llvm-commits] [llvm] r129508 - in /llvm/trunk: include/llvm/CodeGen/ScheduleDAG.h lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp test/CodeGen/X86/2011-04-13-SchedCmpJmp.ll test/CodeGen/X86/lsr-loop-exit-cond.ll test/CodeGen/X86/pr2659.ll test/CodeGen/X86/tail-opts.ll test/CodeGen/X86/test-nofold.ll Message-ID: <20110414051506.D35AA2A6C12C@llvm.org> Author: atrick Date: Thu Apr 14 00:15:06 2011 New Revision: 129508 URL: http://llvm.org/viewvc/llvm-project?rev=129508&view=rev Log: In the pre-RA scheduler, maintain cmp+br proximity. This is done by pushing physical register definitions close to their use, which happens to handle flag definitions if they're not glued to the branch. This seems to be generally a good thing though, so I didn't need to add a target hook yet. The primary motivation is to generate code closer to what people expect and rule out missed opportunity from enabling macro-op fusion. As a side benefit, we get several 2-5% gains on x86 benchmarks. There is one regression: SingleSource/Benchmarks/Shootout/lists slows down be -10%. But this is an independent scheduler bug that will be tracked separately. See rdar://problem/9283108. Incidentally, pre-RA scheduling is only half the solution. Fixing the later passes is tracked by: [pre-RA-sched] on x86, attempt to schedule CMP/TEST adjacent with condition jump Fixes: Scheduler unnecessary break of cmp/jump fusion Added: llvm/trunk/test/CodeGen/X86/2011-04-13-SchedCmpJmp.ll Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp llvm/trunk/test/CodeGen/X86/lsr-loop-exit-cond.ll llvm/trunk/test/CodeGen/X86/pr2659.ll llvm/trunk/test/CodeGen/X86/tail-opts.ll llvm/trunk/test/CodeGen/X86/test-nofold.ll Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=129508&r1=129507&r2=129508&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Thu Apr 14 00:15:06 2011 @@ -260,6 +260,7 @@ bool isAvailable : 1; // True once available. bool isScheduled : 1; // True once scheduled. bool isScheduleHigh : 1; // True if preferable to schedule high. + bool isScheduleLow : 1; // True if preferable to schedule low. bool isCloned : 1; // True if this node has been cloned. Sched::Preference SchedulingPref; // Scheduling preference. @@ -282,7 +283,7 @@ isVRegCycle(false), isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isCloned(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -296,7 +297,7 @@ isVRegCycle(false), isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isCloned(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -309,7 +310,7 @@ isVRegCycle(false), isCall(false), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), - isScheduleHigh(false), isCloned(false), + isScheduleHigh(false), isScheduleLow(false), isCloned(false), SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=129508&r1=129507&r2=129508&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Thu Apr 14 00:15:06 2011 @@ -71,6 +71,7 @@ cl::desc("Disable cycle-level precision during preRA scheduling")); // Temporary sched=list-ilp flags until the heuristics are robust. +// Some options are also available under sched=list-hybrid. static cl::opt DisableSchedRegPressure( "disable-sched-reg-pressure", cl::Hidden, cl::init(false), cl::desc("Disable regpressure priority in sched=list-ilp")); @@ -80,6 +81,9 @@ static cl::opt DisableSchedVRegCycle( "disable-sched-vrcycle", cl::Hidden, cl::init(false), cl::desc("Disable virtual register cycle interference checks")); +static cl::opt DisableSchedPhysRegJoin( + "disable-sched-physreg-join", cl::Hidden, cl::init(false), + cl::desc("Disable physreg def-use affinity")); static cl::opt DisableSchedStalls( "disable-sched-stalls", cl::Hidden, cl::init(true), cl::desc("Disable no-stall priority in sched=list-ilp")); @@ -1638,6 +1642,20 @@ // Static Node Priority for Register Pressure Reduction //===----------------------------------------------------------------------===// +// Check for special nodes that bypass scheduling heuristics. +// Currently this pushes TokenFactor nodes down, but may be used for other +// pseudo-ops as well. +// +// Return -1 to schedule right above left, 1 for left above right. +// Return 0 if no bias exists. +static int checkSpecialNodes(const SUnit *left, const SUnit *right) { + bool LSchedLow = left->isScheduleLow; + bool RSchedLow = right->isScheduleLow; + if (LSchedLow != RSchedLow) + return LSchedLow < RSchedLow ? 1 : -1; + return 0; +} + /// CalcNodeSethiUllmanNumber - Compute Sethi Ullman number. /// Smaller number is the higher priority. static unsigned @@ -2198,25 +2216,32 @@ } static bool BURRSort(SUnit *left, SUnit *right, RegReductionPQBase *SPQ) { + // Schedule physical register definitions close to their use. This is + // motivated by microarchitectures that can fuse cmp+jump macro-ops. But as + // long as shortening physreg live ranges is generally good, we can defer + // creating a subtarget hook. + if (!DisableSchedPhysRegJoin) { + bool LHasPhysReg = left->hasPhysRegDefs; + bool RHasPhysReg = right->hasPhysRegDefs; + if (LHasPhysReg != RHasPhysReg) { + DEBUG(++FactorCount[FactRegUses]); + #ifndef NDEBUG + const char *PhysRegMsg[] = {" has no physreg", " defines a physreg"}; + #endif + DEBUG(dbgs() << " SU (" << left->NodeNum << ") " + << PhysRegMsg[LHasPhysReg] << " SU(" << right->NodeNum << ") " + << PhysRegMsg[RHasPhysReg] << "\n"); + return LHasPhysReg < RHasPhysReg; + } + } + + // Prioritize by Seith-Ulmann number and push CopyToReg nodes down. unsigned LPriority = SPQ->getNodePriority(left); unsigned RPriority = SPQ->getNodePriority(right); if (LPriority != RPriority) { DEBUG(++FactorCount[FactStatic]); return LPriority > RPriority; } - else if(LPriority == 0) { - // Schedule zero-latency TokenFactor below any other special - // nodes. The alternative may be to avoid artificially boosting the - // TokenFactor's height when it is scheduled, but we currently rely on an - // instruction's final height to equal the cycle in which it is scheduled, - // so heights are monotonically increasing. - unsigned LOpc = left->getNode() ? left->getNode()->getOpcode() : 0; - unsigned ROpc = right->getNode() ? right->getNode()->getOpcode() : 0; - if (LOpc == ISD::TokenFactor) - return false; - if (ROpc == ISD::TokenFactor) - return true; - } // Try schedule def + use closer when Sethi-Ullman numbers are the same. // e.g. @@ -2275,11 +2300,17 @@ // Bottom up bool bu_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res > 0; + return BURRSort(left, right, SPQ); } // Source order, otherwise bottom up. bool src_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res > 0; + unsigned LOrder = SPQ->getNodeOrdering(left); unsigned ROrder = SPQ->getNodeOrdering(right); @@ -2311,6 +2342,9 @@ // Return true if right should be scheduled with higher priority than left. bool hybrid_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res > 0; + if (left->isCall || right->isCall) // No way to compute latency of calls. return BURRSort(left, right, SPQ); @@ -2376,6 +2410,9 @@ // list-ilp is currently an experimental scheduler that allows various // heuristics to be enabled prior to the normal register reduction logic. bool ilp_ls_rr_sort::operator()(SUnit *left, SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res > 0; + if (left->isCall || right->isCall) // No way to compute latency of calls. return BURRSort(left, right, SPQ); @@ -2734,6 +2771,9 @@ // Top down bool td_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const { + if (int res = checkSpecialNodes(left, right)) + return res < 0; + unsigned LPriority = SPQ->getNodePriority(left); unsigned RPriority = SPQ->getNodePriority(right); bool LIsTarget = left->getNode() && left->getNode()->isMachineOpcode(); Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp?rev=129508&r1=129507&r2=129508&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp Thu Apr 14 00:15:06 2011 @@ -87,6 +87,8 @@ SU->isCommutable = Old->isCommutable; SU->hasPhysRegDefs = Old->hasPhysRegDefs; SU->hasPhysRegClobbers = Old->hasPhysRegClobbers; + SU->isScheduleHigh = Old->isScheduleHigh; + SU->isScheduleLow = Old->isScheduleLow; SU->SchedulingPref = Old->SchedulingPref; Old->isCloned = true; return SU; @@ -335,6 +337,12 @@ if (!HasGlueUse) break; } + // Schedule zero-latency TokenFactor below any nodes that may increase the + // schedule height. Otherwise, ancestors of the TokenFactor may appear to + // have false stalls. + if (NI->getOpcode() == ISD::TokenFactor) + NodeSUnit->isScheduleLow = true; + // If there are glue operands involved, N is now the bottom-most node // of the sequence of nodes that are glued together. // Update the SUnit. Added: llvm/trunk/test/CodeGen/X86/2011-04-13-SchedCmpJmp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2011-04-13-SchedCmpJmp.ll?rev=129508&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2011-04-13-SchedCmpJmp.ll (added) +++ llvm/trunk/test/CodeGen/X86/2011-04-13-SchedCmpJmp.ll Thu Apr 14 00:15:06 2011 @@ -0,0 +1,65 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=yonah | FileCheck %s +; Reduced from JavaScriptCore + +%"class.JSC::CodeLocationCall" = type { [8 x i8] } +%"class.JSC::JSGlobalData" = type { [4 x i8] } +%"class.JSC::FunctionPtr" = type { i8* } +%"class.JSC::Structure" = type { [4 x i8] } +%"class.JSC::UString" = type { i8* } +%"class.JSC::JSString" = type { [16 x i8], i32, %"class.JSC::UString", i32 } + +declare hidden fastcc void @_ZN3JSCL23returnToThrowTrampolineEPNS_12JSGlobalDataENS_16ReturnAddressPtrERS2_(%"class.JSC::JSGlobalData"* nocapture, i8*, %"class.JSC::FunctionPtr"* nocapture) nounwind noinline ssp + +; Avoid hoisting the test above loads or copies +; CHECK: %entry +; CHECK: cmpq +; CHECK-NOT: mov +; CHECK: jb +define i32 @cti_op_eq(i8** nocapture %args) nounwind ssp { +entry: + %0 = load i8** null, align 8 + %tmp13 = bitcast i8* %0 to %"class.JSC::CodeLocationCall"* + %tobool.i.i.i = icmp ugt i8* undef, inttoptr (i64 281474976710655 to i8*) + %or.cond.i = and i1 %tobool.i.i.i, undef + br i1 %or.cond.i, label %if.then.i, label %if.end.i + +if.then.i: ; preds = %entry + br i1 undef, label %if.then.i.i.i, label %_ZN3JSC7JSValue19equalSlowCaseInlineEPNS_9ExecStateES0_S0_.exit + +if.then.i.i.i: ; preds = %if.then.i + %conv.i.i.i.i = trunc i64 undef to i32 + br label %_ZN3JSC7JSValue19equalSlowCaseInlineEPNS_9ExecStateES0_S0_.exit + +if.end.i: ; preds = %entry + br i1 undef, label %land.rhs.i121.i, label %_ZNK3JSC7JSValue8isStringEv.exit122.i + +land.rhs.i121.i: ; preds = %if.end.i + %tmp.i.i117.i = load %"class.JSC::Structure"** undef, align 8 + br label %_ZNK3JSC7JSValue8isStringEv.exit122.i + +_ZNK3JSC7JSValue8isStringEv.exit122.i: ; preds = %land.rhs.i121.i, %if.end.i + %brmerge.i = or i1 undef, false + %or.cond = or i1 false, %brmerge.i + br i1 %or.cond, label %_ZN3JSC7JSValue19equalSlowCaseInlineEPNS_9ExecStateES0_S0_.exit, label %if.then.i92.i + +if.then.i92.i: ; preds = %_ZNK3JSC7JSValue8isStringEv.exit122.i + tail call void @_ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE(%"class.JSC::JSString"* undef, %"class.JSC::CodeLocationCall"* %tmp13) nounwind + unreachable + +_ZN3JSC7JSValue19equalSlowCaseInlineEPNS_9ExecStateES0_S0_.exit: ; preds = %_ZNK3JSC7JSValue8isStringEv.exit122.i, %if.then.i.i.i, %if.then.i + + %1 = load i8** undef, align 8 + br i1 undef, label %do.end39, label %do.body27 + +do.body27: ; preds = %_ZN3JSC7JSValue19equalSlowCaseInlineEPNS_9ExecStateES0_S0_.exit + %tmp30 = bitcast i8* %1 to %"class.JSC::JSGlobalData"* + %2 = getelementptr inbounds i8** %args, i64 -1 + %3 = bitcast i8** %2 to %"class.JSC::FunctionPtr"* + tail call fastcc void @_ZN3JSCL23returnToThrowTrampolineEPNS_12JSGlobalDataENS_16ReturnAddressPtrERS2_(%"class.JSC::JSGlobalData"* %tmp30, i8* undef, %"class.JSC::FunctionPtr"* %3) + unreachable + +do.end39: ; preds = %_ZN3JSC7JSValue19equalSlowCaseInlineEPNS_9ExecStateES0_S0_.exit + ret i32 undef +} + +declare void @_ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE(%"class.JSC::JSString"*, %"class.JSC::CodeLocationCall"*) Modified: llvm/trunk/test/CodeGen/X86/lsr-loop-exit-cond.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lsr-loop-exit-cond.ll?rev=129508&r1=129507&r2=129508&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/lsr-loop-exit-cond.ll (original) +++ llvm/trunk/test/CodeGen/X86/lsr-loop-exit-cond.ll Thu Apr 14 00:15:06 2011 @@ -1,4 +1,3 @@ -; XFAIL: * ; RUN: llc -march=x86-64 < %s | FileCheck %s ; CHECK: decq Modified: llvm/trunk/test/CodeGen/X86/pr2659.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/pr2659.ll?rev=129508&r1=129507&r2=129508&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/pr2659.ll (original) +++ llvm/trunk/test/CodeGen/X86/pr2659.ll Thu Apr 14 00:15:06 2011 @@ -18,7 +18,8 @@ ; CHECK: movl $1 ; CHECK-NOT: xorl ; CHECK-NOT: movl -; CHECK-NEXT: je +; CHECK-NOT: LBB +; CHECK: je ifthen: ; preds = %entry ret i32 0 Modified: llvm/trunk/test/CodeGen/X86/tail-opts.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/tail-opts.ll?rev=129508&r1=129507&r2=129508&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/tail-opts.ll (original) +++ llvm/trunk/test/CodeGen/X86/tail-opts.ll Thu Apr 14 00:15:06 2011 @@ -109,15 +109,15 @@ ; CHECK: dont_merge_oddly: ; CHECK-NOT: ret -; CHECK: ucomiss %xmm1, %xmm2 +; CHECK: ucomiss %xmm{{[0-2]}}, %xmm{{[0-2]}} ; CHECK-NEXT: jbe .LBB2_3 -; CHECK-NEXT: ucomiss %xmm0, %xmm1 +; CHECK-NEXT: ucomiss %xmm{{[0-2]}}, %xmm{{[0-2]}} ; CHECK-NEXT: ja .LBB2_4 ; CHECK-NEXT: .LBB2_2: ; CHECK-NEXT: movb $1, %al ; CHECK-NEXT: ret ; CHECK-NEXT: .LBB2_3: -; CHECK-NEXT: ucomiss %xmm0, %xmm2 +; CHECK-NEXT: ucomiss %xmm{{[0-2]}}, %xmm{{[0-2]}} ; CHECK-NEXT: jbe .LBB2_2 ; CHECK-NEXT: .LBB2_4: ; CHECK-NEXT: xorb %al, %al Modified: llvm/trunk/test/CodeGen/X86/test-nofold.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/test-nofold.ll?rev=129508&r1=129507&r2=129508&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/test-nofold.ll (original) +++ llvm/trunk/test/CodeGen/X86/test-nofold.ll Thu Apr 14 00:15:06 2011 @@ -2,10 +2,10 @@ ; rdar://5752025 ; We want: -; CHECK: movl 4(%esp), %ecx -; CHECK-NEXT: andl $15, %ecx -; CHECK-NEXT: movl $42, %eax -; CHECK-NEXT: cmovel %ecx, %eax +; CHECK: movl $42, %ecx +; CHECK-NEXT: movl 4(%esp), %eax +; CHECK-NEXT: andl $15, %eax +; CHECK-NEXT: cmovnel %ecx, %eax ; CHECK-NEXT: ret ; ; We don't want: From jay.foad at gmail.com Thu Apr 14 02:56:20 2011 From: jay.foad at gmail.com (Jay Foad) Date: Thu, 14 Apr 2011 08:56:20 +0100 Subject: [llvm-commits] [PATCH] share code between StringRef and ArrayRef Message-ID: This patch removes a bit of code from StringRef by making it derive from ArrayRef. Comments? OK to commit? The savings aren't huge, so I'm not particularly wedded to the patch. Incidentally, I didn't touch StringRef::front(), back() or operator[](), because they return char, whereas the ArrayRef implementations would return const char &. My C++ isn't good enough to work out whether that's an important difference or not. ArrayRef.h | 2 +- StringRef.h | 39 +++++++-------------------------------- 2 files changed, 8 insertions(+), 33 deletions(-) Thanks, Jay. -------------- next part -------------- A non-text attachment was scrubbed... Name: stringref.diff Type: text/x-patch Size: 2999 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110414/f79e974c/attachment.bin From wangmp at apple.com Thu Apr 14 03:04:01 2011 From: wangmp at apple.com (Mon P Wang) Date: Thu, 14 Apr 2011 08:04:01 -0000 Subject: [llvm-commits] [llvm] r129509 - /llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Message-ID: <20110414080401.7E4302A6C12D@llvm.org> Author: wangmp Date: Thu Apr 14 03:04:01 2011 New Revision: 129509 URL: http://llvm.org/viewvc/llvm-project?rev=129509&view=rev Log: Cleanup r129472 by using a utility routine as suggested by Eli. Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=129509&r1=129508&r2=129509&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Thu Apr 14 03:04:01 2011 @@ -676,6 +676,37 @@ llvm_unreachable("Invalid type for a partial vector access of an alloca!"); } +/// CreateShuffleVectorCast - Creates a shuffle vector to convert one vector +/// to another vector of the same element type which has the same allocation +/// size but different primitive sizes (e.g. <3 x i32> and <4 x i32>). +static Value *CreateShuffleVectorCast(Value *FromVal, const Type *ToType, + IRBuilder<> &Builder) { + const Type *FromType = FromVal->getType(); + const VectorType *FromVTy = dyn_cast(FromType); + const VectorType *ToVTy = dyn_cast(ToType); + assert(FromVTy && ToVTy && + (ToVTy->getElementType() == FromVTy->getElementType()) && + "Vectors must have the same element type"); + LLVMContext &Context = FromVal->getContext(); + Value *UnV = UndefValue::get(FromType); + unsigned numEltsFrom = FromVTy->getNumElements(); + unsigned numEltsTo = ToVTy->getNumElements(); + + SmallVector Args; + unsigned minNumElts = std::min(numEltsFrom, numEltsTo); + unsigned i; + for (i=0; i != minNumElts; ++i) + Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); + + if (i < numEltsTo) { + Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); + for (; i != numEltsTo; ++i) + Args.push_back(UnC); + } + Constant *Mask = ConstantVector::get(Args); + return Builder.CreateShuffleVector(FromVal, UnV, Mask, "tmpV"); +} + /// ConvertScalar_ExtractValue - Extract a value of type ToType from an integer /// or vector value FromVal, extracting the bits from the offset specified by /// Offset. This returns the value, which is of type ToType. @@ -699,35 +730,15 @@ if (const VectorType *VTy = dyn_cast(FromType)) { unsigned ToTypeSize = TD.getTypeAllocSize(ToType); if (ToTypeSize == AllocaSize) { + // If the two types have the same primitive size, use a bit cast. + // Otherwise, it is two vectors with the same element type that has + // the same allocation size but different number of elements so use + // a shuffle vector. if (FromType->getPrimitiveSizeInBits() == ToType->getPrimitiveSizeInBits()) return Builder.CreateBitCast(FromVal, ToType, "tmp"); - else { - // Vectors with the same element type can have the same allocation - // size but different primitive sizes (e.g., <3 x i32> and <4 x i32>) - // In this case, use a shuffle vector instead of a bit cast. - const VectorType *ToVTy = dyn_cast(ToType); - assert(ToVTy && (ToVTy->getElementType() == VTy->getElementType()) && - "Vectors must have the same element type"); - LLVMContext &Context = FromVal->getContext(); - Value *UnV = UndefValue::get(FromType); - unsigned numEltsFrom = VTy->getNumElements(); - unsigned numEltsTo = ToVTy->getNumElements(); - - SmallVector Args; - unsigned minNumElts = std::min(numEltsFrom, numEltsTo); - unsigned i; - for (i=0; i != minNumElts; ++i) - Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); - - if (i < numEltsTo) { - Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); - for (; i != numEltsTo; ++i) - Args.push_back(UnC); - } - Constant *Mask = ConstantVector::get(Args); - return Builder.CreateShuffleVector(FromVal, UnV, Mask, "tmpV"); - } + else + return CreateShuffleVectorCast(FromVal, ToType, Builder); } if (ToType->isVectorTy()) { @@ -868,34 +879,15 @@ // Changing the whole vector with memset or with an access of a different // vector type? if (ValSize == VecSize) { + // If the two types have the same primitive size, use a bit cast. + // Otherwise, it is two vectors with the same element type that has + // the same allocation size but different number of elements so use + // a shuffle vector. if (VTy->getPrimitiveSizeInBits() == SV->getType()->getPrimitiveSizeInBits()) return Builder.CreateBitCast(SV, AllocaType, "tmp"); - else { - // Vectors with the same element type can have the same allocation - // size but different primitive sizes (e.g., <3 x i32> and <4 x i32>) - // In this case, use a shuffle vector instead of a bit cast. - const VectorType *SVVTy = dyn_cast(SV->getType()); - assert(SVVTy && (SVVTy->getElementType() == VTy->getElementType()) && - "Vectors must have the same element type"); - Value *UnV = UndefValue::get(SVVTy); - unsigned numEltsFrom = SVVTy->getNumElements(); - unsigned numEltsTo = VTy->getNumElements(); - - SmallVector Args; - unsigned minNumElts = std::min(numEltsFrom, numEltsTo); - unsigned i; - for (i=0; i != minNumElts; ++i) - Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); - - if (i < numEltsTo) { - Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); - for (; i != numEltsTo; ++i) - Args.push_back(UnC); - } - Constant *Mask = ConstantVector::get(Args); - return Builder.CreateShuffleVector(SV, UnV, Mask, "tmpV"); - } + else + return CreateShuffleVectorCast(SV, VTy, Builder); } if (SV->getType()->isVectorTy() && isPowerOf2_64(VecSize / ValSize)) { From baldrick at free.fr Thu Apr 14 04:24:17 2011 From: baldrick at free.fr (Duncan Sands) Date: Thu, 14 Apr 2011 09:24:17 -0000 Subject: [llvm-commits] [dragonegg] r129510 - in /dragonegg/trunk: include/dragonegg/Internals.h src/Constants.cpp src/Types.cpp Message-ID: <20110414092417.EF00A2A6C12C@llvm.org> Author: baldrick Date: Thu Apr 14 04:24:17 2011 New Revision: 129510 URL: http://llvm.org/viewvc/llvm-project?rev=129510&view=rev Log: Do not make use of a C++0x long long integer constant (pedantic). Modified: dragonegg/trunk/include/dragonegg/Internals.h dragonegg/trunk/src/Constants.cpp dragonegg/trunk/src/Types.cpp Modified: dragonegg/trunk/include/dragonegg/Internals.h URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Internals.h?rev=129510&r1=129509&r2=129510&view=diff ============================================================================== --- dragonegg/trunk/include/dragonegg/Internals.h (original) +++ dragonegg/trunk/include/dragonegg/Internals.h Thu Apr 14 04:24:17 2011 @@ -299,8 +299,10 @@ /// start of the record by a constant amount which is not humongously big. extern bool OffsetIsLLVMCompatible(tree_node *field_decl); -/// ArrayLengthOf - Returns the length of the given gcc array type, or ~0ULL if -/// the array has variable or unknown length. +#define NO_LENGTH (~(uint64_t)0) + +/// ArrayLengthOf - Returns the length of the given gcc array type, or NO_LENGTH +/// if the array has variable or unknown length. extern uint64_t ArrayLengthOf(tree_node *type); /// isBitfield - Returns whether to treat the specified field as a bitfield. Modified: dragonegg/trunk/src/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Constants.cpp?rev=129510&r1=129509&r2=129510&view=diff ============================================================================== --- dragonegg/trunk/src/Constants.cpp (original) +++ dragonegg/trunk/src/Constants.cpp Thu Apr 14 04:24:17 2011 @@ -629,7 +629,7 @@ // given for it. uint64_t TypeElts = TREE_CODE(init_type) == ARRAY_TYPE ? ArrayLengthOf(init_type) : TYPE_VECTOR_SUBPARTS(init_type); - if (TypeElts != ~0ULL) + if (TypeElts != NO_LENGTH) Elts.resize(TypeElts); // If GCC indices into the array need adjusting to make them zero indexed then Modified: dragonegg/trunk/src/Types.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Types.cpp?rev=129510&r1=129509&r2=129510&view=diff ============================================================================== --- dragonegg/trunk/src/Types.cpp (original) +++ dragonegg/trunk/src/Types.cpp Thu Apr 14 04:24:17 2011 @@ -50,10 +50,6 @@ #include "tree.h" } -// NoLength - Special value used to indicate that an array has variable or -// unknown length. -static const uint64_t NoLength = ~(uint64_t)0; - static LLVMContext &Context = getGlobalContext(); //===----------------------------------------------------------------------===// @@ -200,14 +196,14 @@ // Type Conversion Utilities //===----------------------------------------------------------------------===// -/// ArrayLengthOf - Returns the length of the given gcc array type, or NoLength +/// ArrayLengthOf - Returns the length of the given gcc array type, or NO_LENGTH /// if the array has variable or unknown length. uint64_t ArrayLengthOf(tree type) { assert(TREE_CODE(type) == ARRAY_TYPE && "Only for array types!"); tree range = array_type_nelts(type); // The number of elements minus one. // Bail out if the array has variable or unknown length. if (!isInt64(range, false)) - return NoLength; + return NO_LENGTH; int64_t Range = getInt64(range, false); return Range < 0 ? 0 : 1 + (uint64_t)Range; } @@ -568,7 +564,7 @@ case ARRAY_TYPE: { uint64_t NumElts = ArrayLengthOf(type); - if (NumElts == NoLength) + if (NumElts == NO_LENGTH) return true; unsigned EltSizeBits = getInt64(TYPE_SIZE(TREE_TYPE(type)), true); @@ -824,7 +820,7 @@ const Type *ElementTy = ConvertType(TREE_TYPE(type)); uint64_t NumElements = ArrayLengthOf(type); - if (NumElements == NoLength) // Variable length array? + if (NumElements == NO_LENGTH) // Variable length array? NumElements = 0; // Create the array type. From baldrick at free.fr Thu Apr 14 04:52:41 2011 From: baldrick at free.fr (Duncan Sands) Date: Thu, 14 Apr 2011 09:52:41 -0000 Subject: [llvm-commits] [dragonegg] r129511 - in /dragonegg/trunk: include/dragonegg/Internals.h src/Convert.cpp Message-ID: <20110414095241.E43DB2A6C12C@llvm.org> Author: baldrick Date: Thu Apr 14 04:52:41 2011 New Revision: 129511 URL: http://llvm.org/viewvc/llvm-project?rev=129511&view=rev Log: Rename GetRegType to getRegType. Modified: dragonegg/trunk/include/dragonegg/Internals.h dragonegg/trunk/src/Convert.cpp Modified: dragonegg/trunk/include/dragonegg/Internals.h URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Internals.h?rev=129511&r1=129510&r2=129511&view=diff ============================================================================== --- dragonegg/trunk/include/dragonegg/Internals.h (original) +++ dragonegg/trunk/include/dragonegg/Internals.h Thu Apr 14 04:52:41 2011 @@ -200,7 +200,7 @@ TypeConverter() : ConvertingStruct(false) {} /// ConvertType - Returns the LLVM type to use for memory that holds a value - /// of the given GCC type (GetRegType should be used for values in registers). + /// of the given GCC type (getRegType should be used for values in registers). const Type *ConvertType(tree_node *type); /// GCCTypeOverlapsWithLLVMTypePadding - Return true if the specified GCC type @@ -237,7 +237,7 @@ extern TypeConverter *TheTypeConverter; /// ConvertType - Returns the LLVM type to use for memory that holds a value -/// of the given GCC type (GetRegType should be used for values in registers). +/// of the given GCC type (getRegType should be used for values in registers). inline const Type *ConvertType(tree_node *type) { return TheTypeConverter->ConvertType(type); } @@ -649,15 +649,15 @@ //===---------- EmitReg* - Convert register expression to LLVM ----------===// - /// GetRegType - Returns the LLVM type to use for registers that hold a value + /// getRegType - Returns the LLVM type to use for registers that hold a value /// of the scalar GCC type 'type'. All of the EmitReg* routines use this to /// determine the LLVM type to return. - const Type *GetRegType(tree_node *type); + const Type *getRegType(tree_node *type); /// UselesslyTypeConvert - The useless_type_conversion_p predicate implicitly /// defines the GCC middle-end type system. For scalar GCC types inner_type /// and outer_type, if 'useless_type_conversion_p(outer_type, inner_type)' is - /// true then the corresponding LLVM inner and outer types (see GetRegType) + /// true then the corresponding LLVM inner and outer types (see getRegType) /// are equal except possibly if they are both pointer types (casts to 'void*' /// are considered useless for example) or types derived from pointer types /// (vector types with pointer element type are the only possibility here). @@ -841,14 +841,14 @@ Constant *EmitVectorRegisterConstant(tree_node *reg); /// Mem2Reg - Convert a value of in-memory type (that given by ConvertType) - /// to in-register type (that given by GetRegType). TODO: Eliminate these + /// to in-register type (that given by getRegType). TODO: Eliminate these /// methods: "memory" values should never be held in registers. Currently /// this is mainly used for marshalling function parameters and return values, /// but that should be completely independent of the reg vs mem value logic. Value *Mem2Reg(Value *V, tree_node *type, LLVMBuilder &Builder); Constant *Mem2Reg(Constant *C, tree_node *type, TargetFolder &Folder); - /// Reg2Mem - Convert a value of in-register type (that given by GetRegType) + /// Reg2Mem - Convert a value of in-register type (that given by getRegType) /// to in-memory type (that given by ConvertType). TODO: Eliminate this /// method: "memory" values should never be held in registers. Currently /// this is mainly used for marshalling function parameters and return values, @@ -863,13 +863,13 @@ /// LoadRegisterFromMemory - Loads a value of the given scalar GCC type from /// the memory location pointed to by Loc. Takes care of adjusting for any /// differences between in-memory and in-register types (the returned value - /// is of in-register type, as returned by GetRegType). + /// is of in-register type, as returned by getRegType). Value *LoadRegisterFromMemory(MemRef Loc, tree_node *type, LLVMBuilder &Builder); /// StoreRegisterToMemory - Stores the given value to the memory pointed to by /// Loc. Takes care of adjusting for any differences between the value's type - /// (which is the in-register type given by GetRegType) and the in-memory type. + /// (which is the in-register type given by getRegType) and the in-memory type. void StoreRegisterToMemory(Value *V, MemRef Loc, tree_node *type, LLVMBuilder &Builder); Modified: dragonegg/trunk/src/Convert.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=129511&r1=129510&r2=129511&view=diff ============================================================================== --- dragonegg/trunk/src/Convert.cpp (original) +++ dragonegg/trunk/src/Convert.cpp Thu Apr 14 04:52:41 2011 @@ -1096,7 +1096,7 @@ continue; // Create the LLVM phi node. - const Type *Ty = GetRegType(TREE_TYPE(gimple_phi_result(gcc_phi))); + const Type *Ty = getRegType(TREE_TYPE(gimple_phi_result(gcc_phi))); PHINode *PHI = Builder.CreatePHI(Ty, gimple_phi_num_args(gcc_phi)); // The phi defines the associated ssa name. @@ -2371,7 +2371,7 @@ } } - return Builder.CreateIntCast(Result, GetRegType(TREE_TYPE(exp)), + return Builder.CreateIntCast(Result, getRegType(TREE_TYPE(exp)), /*isSigned*/!TYPE_UNSIGNED(TREE_TYPE(exp))); } } @@ -3042,7 +3042,7 @@ va_end(ops); const Type *RetTy = TREE_CODE(ret_type) == VOID_TYPE ? - Type::getVoidTy(Context) : GetRegType(ret_type); + Type::getVoidTy(Context) : getRegType(ret_type); // The LLVM argument types. std::vector ArgTys; @@ -3098,7 +3098,7 @@ /// that copies the value out of the specified register. Value *TreeToLLVM::EmitReadOfRegisterVariable(tree decl) { const Type *MemTy = ConvertType(TREE_TYPE(decl)); - const Type *RegTy = GetRegType(TREE_TYPE(decl)); + const Type *RegTy = getRegType(TREE_TYPE(decl)); // If there was an error, return something bogus. if (ValidateRegisterVariable(decl)) @@ -4690,7 +4690,7 @@ // Then type cast the result of the "ceil" call. tree type = gimple_call_return_type(stmt); - const Type *RetTy = GetRegType(type); + const Type *RetTy = getRegType(type); return TYPE_UNSIGNED(type) ? Builder.CreateFPToUI(Call, RetTy) : Builder.CreateFPToSI(Call, RetTy); } @@ -4709,7 +4709,7 @@ // Then type cast the result of the "floor" call. tree type = gimple_call_return_type(stmt); - const Type *RetTy = GetRegType(type); + const Type *RetTy = getRegType(type); return TYPE_UNSIGNED(type) ? Builder.CreateFPToUI(Call, RetTy) : Builder.CreateFPToSI(Call, RetTy); } @@ -5849,7 +5849,7 @@ Value *TreeToLLVM::EmitMinInvariant(tree reg) { Value *V = (TREE_CODE(reg) == ADDR_EXPR) ? EmitInvariantAddress(reg) : EmitRegisterConstant(reg); - assert(V->getType() == GetRegType(TREE_TYPE(reg)) && + assert(V->getType() == getRegType(TREE_TYPE(reg)) && "Gimple min invariant has wrong type!"); return V; } @@ -5892,7 +5892,7 @@ if (SavedInsertBB != EntryBlock) Builder.SetInsertPoint(SavedInsertBB, SavedInsertPoint); - assert(Address->getType() == GetRegType(TREE_TYPE(addr)) && + assert(Address->getType() == getRegType(TREE_TYPE(addr)) && "Invariant address has wrong type!"); return Address; } @@ -5974,7 +5974,7 @@ // The destination can be a pointer, integer or floating point type so we need // a generalized cast here - const Type *Ty = GetRegType(TREE_TYPE(reg)); + const Type *Ty = getRegType(TREE_TYPE(reg)); Instruction::CastOps opcode = CastInst::getCastOpcode(CI, false, Ty, !TYPE_UNSIGNED(TREE_TYPE(reg))); return TheFolder->CreateCast(opcode, CI, Ty); @@ -6037,7 +6037,7 @@ // The constant may have pretty much any type, for example it could be a bunch // of bytes. Extract the vector elements from the constant. tree elt_type = TREE_TYPE (TREE_TYPE (reg)); - const Type *EltTy = GetRegType(elt_type); + const Type *EltTy = getRegType(elt_type); unsigned NumElts = TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg)); // Get the spacing between consecutive vector elements. Obtain this from the // GCC type in case the LLVM type is something funky like i1. @@ -6054,7 +6054,7 @@ // If there are no elements then immediately return the default value for a // small speedup. if (!TREE_VECTOR_CST_ELTS(reg)) - return getDefaultValue(GetRegType(TREE_TYPE(reg))); + return getDefaultValue(getRegType(TREE_TYPE(reg))); // Convert the elements. SmallVector Elts; @@ -6064,7 +6064,7 @@ // If there weren't enough elements then set the rest of the vector to the // default value. if (Elts.size() < TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg))) { - Constant *Default = getDefaultValue(GetRegType(TREE_TYPE(TREE_TYPE(reg)))); + Constant *Default = getDefaultValue(getRegType(TREE_TYPE(TREE_TYPE(reg)))); Elts.append(TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg)) - Elts.size(), Default); } @@ -6072,10 +6072,10 @@ } /// Mem2Reg - Convert a value of in-memory type (that given by ConvertType) -/// to in-register type (that given by GetRegType). +/// to in-register type (that given by getRegType). Value *TreeToLLVM::Mem2Reg(Value *V, tree type, LLVMBuilder &Builder) { const Type *MemTy = V->getType(); - const Type *RegTy = GetRegType(type); + const Type *RegTy = getRegType(type); assert(MemTy == ConvertType(type) && "Not of memory type!"); if (MemTy == RegTy) @@ -6087,7 +6087,7 @@ } Constant *TreeToLLVM::Mem2Reg(Constant *C, tree type, TargetFolder &Folder) { const Type *MemTy = C->getType(); - const Type *RegTy = GetRegType(type); + const Type *RegTy = getRegType(type); assert(MemTy == ConvertType(type) && "Not of memory type!"); if (MemTy == RegTy) @@ -6098,12 +6098,12 @@ return Folder.CreateIntCast(C, RegTy, /*isSigned*/!TYPE_UNSIGNED(type)); } -/// Reg2Mem - Convert a value of in-register type (that given by GetRegType) +/// Reg2Mem - Convert a value of in-register type (that given by getRegType) /// to in-memory type (that given by ConvertType). Value *TreeToLLVM::Reg2Mem(Value *V, tree type, LLVMBuilder &Builder) { const Type *RegTy = V->getType(); const Type *MemTy = ConvertType(type); - assert(RegTy == GetRegType(type) && "Not of register type!"); + assert(RegTy == getRegType(type) && "Not of register type!"); if (RegTy == MemTy) return V; @@ -6116,7 +6116,7 @@ /// LoadRegisterFromMemory - Loads a value of the given scalar GCC type from /// the memory location pointed to by Loc. Takes care of adjusting for any /// differences between in-memory and in-register types (the returned value -/// is of in-register type, as returned by GetRegType). +/// is of in-register type, as returned by getRegType). Value *TreeToLLVM::LoadRegisterFromMemory(MemRef Loc, tree type, LLVMBuilder &Builder) { const Type *MemTy = ConvertType(type); @@ -6128,7 +6128,7 @@ /// StoreRegisterToMemory - Stores the given value to the memory pointed to by /// Loc. Takes care of adjusting for any differences between the value's type -/// (which is the in-register type given by GetRegType) and the in-memory type. +/// (which is the in-register type given by getRegType) and the in-memory type. void TreeToLLVM::StoreRegisterToMemory(Value *V, MemRef Loc, tree type, LLVMBuilder &Builder) { const Type *MemTy = ConvertType(type); @@ -6143,10 +6143,10 @@ // ... EmitReg* - Convert register expression to LLVM... //===----------------------------------------------------------------------===// -/// GetRegType - Returns the LLVM type to use for registers that hold a value +/// getRegType - Returns the LLVM type to use for registers that hold a value /// of the scalar GCC type 'type'. All of the EmitReg* routines use this to /// determine the LLVM type to return. -const Type *TreeToLLVM::GetRegType(tree type) { +const Type *TreeToLLVM::getRegType(tree type) { assert(!AGGREGATE_TYPE_P(type) && "Registers must have a scalar type!"); assert(TREE_CODE(type) != VOID_TYPE && "Registers cannot have void type!"); @@ -6180,7 +6180,7 @@ // If we already found the definition of the SSA name, return it. if (Value *ExistingValue = SSANames[reg]) { - assert(ExistingValue->getType() == GetRegType(TREE_TYPE(reg)) && + assert(ExistingValue->getType() == getRegType(TREE_TYPE(reg)) && "SSA name has wrong type!"); if (!isSSAPlaceholder(ExistingValue)) return ExistingValue; @@ -6190,7 +6190,7 @@ if (!SSA_NAME_IS_DEFAULT_DEF(reg)) { if (Value *ExistingValue = SSANames[reg]) return ExistingValue; // The type was sanity checked above. - return SSANames[reg] = GetSSAPlaceholder(GetRegType(TREE_TYPE(reg))); + return SSANames[reg] = GetSSAPlaceholder(getRegType(TREE_TYPE(reg))); } // This SSA name is the default definition for the underlying symbol. @@ -6202,7 +6202,7 @@ // If the variable is itself an ssa name, use its LLVM value. if (TREE_CODE (var) == SSA_NAME) { Value *Val = EmitReg_SSA_NAME(var); - assert(Val->getType() == GetRegType(TREE_TYPE(reg)) && + assert(Val->getType() == getRegType(TREE_TYPE(reg)) && "SSA name has wrong type!"); return DefineSSAName(reg, Val); } @@ -6212,7 +6212,7 @@ // variable in the function is a read operation, and refers to the value // read, it has an undefined value except for PARM_DECLs. if (TREE_CODE(var) != PARM_DECL) - return DefineSSAName(reg, UndefValue::get(GetRegType(TREE_TYPE(reg)))); + return DefineSSAName(reg, UndefValue::get(getRegType(TREE_TYPE(reg)))); // Read the initial value of the parameter and associate it with the ssa name. assert(DECL_LOCAL_IF_SET(var) && "Parameter not laid out?"); @@ -6274,7 +6274,7 @@ Value *TreeToLLVM::EmitReg_CONVERT_EXPR(tree type, tree op) { return CastToAnyType(EmitRegister(op), !TYPE_UNSIGNED(TREE_TYPE(op)), - GetRegType(type), !TYPE_UNSIGNED(type)); + getRegType(type), !TYPE_UNSIGNED(type)); } Value *TreeToLLVM::EmitReg_NEGATE_EXPR(tree op) { @@ -6306,7 +6306,7 @@ V = Builder.CreateICmpNE(V, Constant::getNullValue(V->getType()), "toBool"); V = Builder.CreateNot(V, V->getName()+"not"); - return Builder.CreateIntCast(V, GetRegType(type), /*isSigned*/false); + return Builder.CreateIntCast(V, getRegType(type), /*isSigned*/false); } // Comparisons. @@ -6402,7 +6402,7 @@ Value *LHS = EmitRegister(op0); Value *RHS = EmitRegister(op1); - const Type *Ty = GetRegType(type); + const Type *Ty = getRegType(type); // The LHS, RHS and Ty could be integer, floating or pointer typed. We need // to convert the LHS and RHS into the destination type before doing the @@ -6447,7 +6447,7 @@ // Or the two together to return them. Value *Merge = Builder.CreateOr(V1, V2); - return Builder.CreateIntCast(Merge, GetRegType(type), /*isSigned*/false); + return Builder.CreateIntCast(Merge, getRegType(type), /*isSigned*/false); } Value *TreeToLLVM::EmitReg_ShiftOp(tree op0, tree op1, unsigned Opc) { @@ -6474,7 +6474,7 @@ "toBool"); Value *Res = Builder.CreateBinOp((Instruction::BinaryOps)Opc, LHS, RHS); - return Builder.CreateZExt(Res, GetRegType(type)); + return Builder.CreateZExt(Res, getRegType(type)); } Value *TreeToLLVM::EmitReg_CEIL_DIV_EXPR(tree type, tree op0, tree op1) { @@ -6486,7 +6486,7 @@ // LHS CDiv RHS = (LHS - Sign(RHS)) Div RHS + 1 // otherwise. - const Type *Ty = GetRegType(type); + const Type *Ty = getRegType(type); Constant *Zero = ConstantInt::get(Ty, 0); Constant *One = ConstantInt::get(Ty, 1); Constant *MinusOne = Constant::getAllOnesValue(Ty); @@ -6574,7 +6574,7 @@ // same sign, so FDiv is the same as Div. return Builder.CreateUDiv(LHS, RHS, "fdiv"); - const Type *Ty = GetRegType(type); + const Type *Ty = getRegType(type); Constant *Zero = ConstantInt::get(Ty, 0); Constant *One = ConstantInt::get(Ty, 1); Constant *MinusOne = Constant::getAllOnesValue(Ty); @@ -6621,7 +6621,7 @@ // LHS and RHS values must have the same sign if their type is unsigned. return Builder.CreateURem(LHS, RHS); - const Type *Ty = GetRegType(type); + const Type *Ty = getRegType(type); Constant *Zero = ConstantInt::get(Ty, 0); // The two possible values for Mod. @@ -6730,7 +6730,7 @@ Builder.CreateInBoundsGEP(Ptr, Idx) : Builder.CreateGEP(Ptr, Idx); // The result may be of a different pointer type. - return UselesslyTypeConvert(GEP, GetRegType(type)); + return UselesslyTypeConvert(GEP, getRegType(type)); } Value *TreeToLLVM::EmitReg_RDIV_EXPR(tree op0, tree op1) { @@ -6780,7 +6780,7 @@ // required to ensure correct results. The details depend on whether // we are doing signed or unsigned arithmetic. - const Type *Ty = GetRegType(type); + const Type *Ty = getRegType(type); Constant *Zero = ConstantInt::get(Ty, 0); Constant *Two = ConstantInt::get(Ty, 2); @@ -7659,7 +7659,7 @@ EmitAggregate(retval, DestLoc); } else { Value *Val = Builder.CreateBitCast(EmitRegister(retval), - GetRegType(TREE_TYPE(result))); + getRegType(TREE_TYPE(result))); StoreRegisterToMemory(Val, DestLoc, TREE_TYPE(result), Builder); } } @@ -7744,7 +7744,7 @@ // EmitAssignSingleRHS. if (get_gimple_rhs_class(gimple_expr_code(stmt)) == GIMPLE_SINGLE_RHS) { Value *RHS = EmitAssignSingleRHS(gimple_assign_rhs1(stmt)); - assert(RHS->getType() == GetRegType(TREE_TYPE(gimple_assign_rhs1(stmt))) && + assert(RHS->getType() == getRegType(TREE_TYPE(gimple_assign_rhs1(stmt))) && "RHS has wrong type!"); return RHS; } @@ -7795,7 +7795,7 @@ case UNLT_EXPR: case UNORDERED_EXPR: // The GCC result may be of any integer type. - RHS = Builder.CreateZExt(EmitCompare(rhs1, rhs2, code), GetRegType(type)); + RHS = Builder.CreateZExt(EmitCompare(rhs1, rhs2, code), getRegType(type)); break; // Binary expressions. @@ -7861,7 +7861,7 @@ RHS = EmitReg_TruthOp(type, rhs1, rhs2, Instruction::Xor); break; } - assert(RHS->getType() == GetRegType(type) && "RHS has wrong type!"); + assert(RHS->getType() == getRegType(type) && "RHS has wrong type!"); return RHS; } @@ -7959,7 +7959,7 @@ /// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS. void TreeToLLVM::WriteScalarToLHS(tree lhs, Value *RHS) { // Perform a useless type conversion (useless_type_conversion_p). - RHS = UselesslyTypeConvert(RHS, GetRegType(TREE_TYPE(lhs))); + RHS = UselesslyTypeConvert(RHS, getRegType(TREE_TYPE(lhs))); // If this is the definition of an ssa name, record it in the SSANames map. if (TREE_CODE(lhs) == SSA_NAME) { From baldrick at free.fr Thu Apr 14 05:49:13 2011 From: baldrick at free.fr (Duncan Sands) Date: Thu, 14 Apr 2011 10:49:13 -0000 Subject: [llvm-commits] [dragonegg] r129512 - in /dragonegg/trunk/src: Convert.cpp Types.cpp Message-ID: <20110414104913.235BD2A6C12C@llvm.org> Author: baldrick Date: Thu Apr 14 05:49:12 2011 New Revision: 129512 URL: http://llvm.org/viewvc/llvm-project?rev=129512&view=rev Log: Move getRegType into Types.cpp. Modified: dragonegg/trunk/src/Convert.cpp dragonegg/trunk/src/Types.cpp Modified: dragonegg/trunk/src/Convert.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=129512&r1=129511&r2=129512&view=diff ============================================================================== --- dragonegg/trunk/src/Convert.cpp (original) +++ dragonegg/trunk/src/Convert.cpp Thu Apr 14 05:49:12 2011 @@ -6143,22 +6143,6 @@ // ... EmitReg* - Convert register expression to LLVM... //===----------------------------------------------------------------------===// -/// getRegType - Returns the LLVM type to use for registers that hold a value -/// of the scalar GCC type 'type'. All of the EmitReg* routines use this to -/// determine the LLVM type to return. -const Type *TreeToLLVM::getRegType(tree type) { - assert(!AGGREGATE_TYPE_P(type) && "Registers must have a scalar type!"); - assert(TREE_CODE(type) != VOID_TYPE && "Registers cannot have void type!"); - - // For integral types, convert based on the type precision. - if (TREE_CODE(type) == BOOLEAN_TYPE || TREE_CODE(type) == ENUMERAL_TYPE || - TREE_CODE(type) == INTEGER_TYPE) - return IntegerType::get(Context, TYPE_PRECISION(type)); - - // Otherwise, return the type used to represent memory. - return ConvertType(type); -} - /// EmitMemory - Convert the specified gimple register or local constant of /// register type to an LLVM value with in-memory type (given by ConvertType). Value *TreeToLLVM::EmitMemory(tree reg) { Modified: dragonegg/trunk/src/Types.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Types.cpp?rev=129512&r1=129511&r2=129512&view=diff ============================================================================== --- dragonegg/trunk/src/Types.cpp (original) +++ dragonegg/trunk/src/Types.cpp Thu Apr 14 05:49:12 2011 @@ -648,6 +648,23 @@ // Main Type Conversion Routines //===----------------------------------------------------------------------===// +/// getRegType - Returns the LLVM type to use for registers that hold a value +/// of the scalar GCC type 'type'. All of the EmitReg* routines use this to +/// determine the LLVM type to return. +const Type *TreeToLLVM::getRegType(tree type) { + assert(!AGGREGATE_TYPE_P(type) && "Registers must have a scalar type!"); + assert(TREE_CODE(type) != VOID_TYPE && "Registers cannot have void type!"); + + // For integral types, convert based on the type precision. + if (TREE_CODE(type) == BOOLEAN_TYPE || TREE_CODE(type) == ENUMERAL_TYPE || + TREE_CODE(type) == INTEGER_TYPE) + return IntegerType::get(Context, TYPE_PRECISION(type)); + + // Otherwise, return the type used to represent memory. + return ConvertType(type); +} + + const Type *TypeConverter::ConvertType(tree type) { if (type == error_mark_node) return Type::getInt32Ty(Context); From jay.foad at gmail.com Thu Apr 14 06:13:53 2011 From: jay.foad at gmail.com (Jay Foad) Date: Thu, 14 Apr 2011 12:13:53 +0100 Subject: [llvm-commits] [PATCH] PR9214: convert InvokeInst API to use ArrayRef Message-ID: See http://llvm.org/bugs/show_bug.cgi?id=9214 The bugs says: > Various LLVM APIs (such as the Constant*::get APIs, the > GetElementPtrInst::Create methods, IRBuilder CreateGEP method, etc) that take > multiple input values take std::vectors, and some now also can take a pointer > to the start of an array and a count (for use with SmallVector). The new > ArrayRef class subsumes both of these uses and is more convenient to use. I had a look at the "IRBuilder CreateGEP method", and noticed that there are several Instructions that could take ArrayRefs where they currently take a pair of RandomAccessIterators, both in their own constructors and Create() methods, and in the corresponding IRBuilder API to create them. The Instructions in question are: CallInst InvokeInst GetElementPtrInst InsertValueInst ExtractValueInst This patch just converts InvokeInst, because I thought it would be the easiest one to start with. I'm concerned about the amount of churn it causes. It touches more or less every place that creates an InvokeInst. I expect there to be way more churn with more common Instructions like CallInst and GetElementPtrInst. Do we really want to cause this pain for all clients of the LLVM APIs? Thanks, Jay. -------------- next part -------------- A non-text attachment was scrubbed... Name: arrayref-invokeinst Type: application/octet-stream Size: 20145 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110414/dfd215b9/attachment.obj From benny.kra at googlemail.com Thu Apr 14 07:35:08 2011 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Thu, 14 Apr 2011 14:35:08 +0200 Subject: [llvm-commits] [cfe-commits] [PATCH] share code between StringRef and ArrayRef In-Reply-To: References: Message-ID: On 14.04.2011, at 09:56, Jay Foad wrote: > This patch removes a bit of code from StringRef by making it derive > from ArrayRef. > > Comments? OK to commit? The savings aren't huge, so I'm not > particularly wedded to the patch. Hi Jay, Have you checked the compile time impact of this? StringRef.h is included everywhere and ArrayRef.h pulls in Smallvector and Vector which are both big headers. I don't think this is worth it. > > Incidentally, I didn't touch StringRef::front(), back() or > operator[](), because they return char, whereas the ArrayRef > implementations would return const char &. My C++ isn't good enough to > work out whether that's an important difference or not. > > ArrayRef.h | 2 +- > StringRef.h | 39 +++++++-------------------------------- > 2 files changed, 8 insertions(+), 33 deletions(-) > > Thanks, > Jay. > > _______________________________________________ > cfe-commits mailing list > cfe-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits From bigcheesegs at gmail.com Thu Apr 14 09:33:37 2011 From: bigcheesegs at gmail.com (Michael J. Spencer) Date: Thu, 14 Apr 2011 14:33:37 -0000 Subject: [llvm-commits] [llvm] r129517 - in /llvm/trunk: include/llvm/IntrinsicsX86.td lib/Target/X86/X86.td Message-ID: <20110414143337.0C5F72A6C12C@llvm.org> Author: mspencer Date: Thu Apr 14 09:33:36 2011 New Revision: 129517 URL: http://llvm.org/viewvc/llvm-project?rev=129517&view=rev Log: Fix whitespace and tabs. Modified: llvm/trunk/include/llvm/IntrinsicsX86.td llvm/trunk/lib/Target/X86/X86.td Modified: llvm/trunk/include/llvm/IntrinsicsX86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IntrinsicsX86.td?rev=129517&r1=129516&r2=129517&view=diff ============================================================================== --- llvm/trunk/include/llvm/IntrinsicsX86.td (original) +++ llvm/trunk/include/llvm/IntrinsicsX86.td Thu Apr 14 09:33:36 2011 @@ -907,68 +907,68 @@ // String/text processing ops. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse42_pcmpistrm128 : GCCBuiltin<"__builtin_ia32_pcmpistrm128">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistri128 : GCCBuiltin<"__builtin_ia32_pcmpistri128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistria128 : GCCBuiltin<"__builtin_ia32_pcmpistria128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistric128 : GCCBuiltin<"__builtin_ia32_pcmpistric128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistrio128 : GCCBuiltin<"__builtin_ia32_pcmpistrio128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistris128 : GCCBuiltin<"__builtin_ia32_pcmpistris128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpistriz128 : GCCBuiltin<"__builtin_ia32_pcmpistriz128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestrm128 : GCCBuiltin<"__builtin_ia32_pcmpestrm128">, - Intrinsic<[llvm_v16i8_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestri128 : GCCBuiltin<"__builtin_ia32_pcmpestri128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestria128 : GCCBuiltin<"__builtin_ia32_pcmpestria128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestric128 : GCCBuiltin<"__builtin_ia32_pcmpestric128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestrio128 : GCCBuiltin<"__builtin_ia32_pcmpestrio128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestris128 : GCCBuiltin<"__builtin_ia32_pcmpestris128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; def int_x86_sse42_pcmpestriz128 : GCCBuiltin<"__builtin_ia32_pcmpestriz128">, - Intrinsic<[llvm_i32_ty], - [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, - llvm_i8_ty], - [IntrNoMem]>; + Intrinsic<[llvm_i32_ty], + [llvm_v16i8_ty, llvm_i32_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i8_ty], + [IntrNoMem]>; } //===----------------------------------------------------------------------===// @@ -1557,14 +1557,14 @@ Intrinsic<[], [llvm_ptrx86mmx_ty, llvm_x86mmx_ty], []>; def int_x86_mmx_palignr_b : GCCBuiltin<"__builtin_ia32_palignr">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_mmx_pextr_w : GCCBuiltin<"__builtin_ia32_vec_ext_v4hi">, - Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], + Intrinsic<[llvm_i32_ty], [llvm_x86mmx_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_mmx_pinsr_w : GCCBuiltin<"__builtin_ia32_vec_set_v4hi">, - Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; } Modified: llvm/trunk/lib/Target/X86/X86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.td?rev=129517&r1=129516&r2=129517&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86.td (original) +++ llvm/trunk/lib/Target/X86/X86.td Thu Apr 14 09:33:36 2011 @@ -1,10 +1,10 @@ //===- X86.td - Target definition file for the Intel X86 ---*- tablegen -*-===// -// +// // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -// +// //===----------------------------------------------------------------------===// // // This is a target description file for the Intel i386 architecture, refered to @@ -32,7 +32,7 @@ def FeatureSSE1 : SubtargetFeature<"sse", "X86SSELevel", "SSE1", "Enable SSE instructions", // SSE codegen depends on cmovs, and all - // SSE1+ processors support them. + // SSE1+ processors support them. [FeatureMMX, FeatureCMOV]>; def FeatureSSE2 : SubtargetFeature<"sse2", "X86SSELevel", "SSE2", "Enable SSE2 instructions", From rafael.espindola at gmail.com Thu Apr 14 10:18:53 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Thu, 14 Apr 2011 15:18:53 -0000 Subject: [llvm-commits] [llvm] r129518 - in /llvm/trunk: include/llvm/CodeGen/AsmPrinter.h lib/CodeGen/AsmPrinter/AsmPrinter.cpp lib/CodeGen/AsmPrinter/DwarfCFIException.cpp lib/Target/TargetLoweringObjectFile.cpp lib/Target/X86/X86FrameLowering.cpp lib/Target/X86/X86MCAsmInfo.cpp test/CodeGen/X86/2007-05-05-Personality.ll test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll test/CodeGen/X86/aliases.ll Message-ID: <20110414151853.E935E2A6C12C@llvm.org> Author: rafael Date: Thu Apr 14 10:18:53 2011 New Revision: 129518 URL: http://llvm.org/viewvc/llvm-project?rev=129518&view=rev Log: Change ELF systems to use CFI for producing the EH tables. This reduces the size of the clang binary in Debug builds from 690MB to 679MB. Removed: llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll Modified: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp llvm/trunk/lib/Target/X86/X86FrameLowering.cpp llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll llvm/trunk/test/CodeGen/X86/aliases.ll Modified: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/AsmPrinter.h?rev=129518&r1=129517&r2=129518&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h (original) +++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h Thu Apr 14 10:18:53 2011 @@ -183,6 +183,8 @@ /// function. void EmitFunctionBody(); + void emitPrologLabel(const MachineInstr &MI); + /// EmitConstantPool - Print to the current output stream assembly /// representations of the constants in the constant pool MCP. This is /// used to print out constants which have been "spilled to memory" by Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=129518&r1=129517&r2=129518&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Thu Apr 14 10:18:53 2011 @@ -33,6 +33,7 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" @@ -624,6 +625,45 @@ return true; } +void AsmPrinter::emitPrologLabel(const MachineInstr &MI) { + MCSymbol *Label = MI.getOperand(0).getMCSymbol(); + if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI) { + OutStreamer.EmitLabel(Label); + return; + } + + const MachineFunction &MF = *MI.getParent()->getParent(); + MachineModuleInfo &MMI = MF.getMMI(); + std::vector &Moves = MMI.getFrameMoves(); + const MachineMove *Move = NULL; + for (std::vector::iterator I = Moves.begin(), + E = Moves.end(); I != E; ++I) { + if (I->getLabel() == Label) { + Move = &*I; + break; + } + } + assert(Move); + + const MachineLocation &Dst = Move->getDestination(); + const MachineLocation &Src = Move->getSource(); + const TargetAsmInfo &AsmInfo = OutContext.getTargetAsmInfo(); + if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { + if (Src.getReg() == MachineLocation::VirtualFP) + OutStreamer.EmitCFIDefCfaOffset(-Src.getOffset()); + else { + unsigned Reg = AsmInfo.getDwarfRegNum(Src.getReg(), true); + OutStreamer.EmitCFIDefCfa(Reg, -Src.getOffset()); + } + } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { + unsigned Reg = AsmInfo.getDwarfRegNum(Dst.getReg(), true); + OutStreamer.EmitCFIDefCfaRegister(Reg); + } else { + unsigned Reg = AsmInfo.getDwarfRegNum(Src.getReg(), true); + OutStreamer.EmitCFIOffset(Reg, -Dst.getOffset()); + } +} + /// EmitFunctionBody - This method emits the body and trailer for a /// function. void AsmPrinter::EmitFunctionBody() { @@ -660,6 +700,9 @@ switch (II->getOpcode()) { case TargetOpcode::PROLOG_LABEL: + emitPrologLabel(*II); + break; + case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol()); Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp?rev=129518&r1=129517&r2=129518&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp Thu Apr 14 10:18:53 2011 @@ -32,6 +32,7 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -60,11 +61,16 @@ // Begin eh frame section. Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); + if ((PerEncoding & 0x70) != dwarf::DW_EH_PE_pcrel) + return; + // Emit references to all used personality functions const std::vector &Personalities = MMI->getPersonalities(); for (size_t i = 0, e = Personalities.size(); i != e; ++i) { Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("personality", i)); - Asm->EmitReference(Personalities[i], PerEncoding); + const MCSymbol *Sym = Asm->Mang->getSymbol(Personalities[i]); + unsigned Size = Asm->TM.getTargetData()->getPointerSize(); + Asm->OutStreamer.EmitSymbolValue(Sym, Size); } } @@ -87,17 +93,9 @@ shouldEmitTableModule |= shouldEmitTable; - if (shouldEmitMoves) { - const TargetFrameLowering *TFL = Asm->TM.getFrameLowering(); + if (shouldEmitMoves || shouldEmitTable) Asm->OutStreamer.EmitCFIStartProc(); - // Indicate locations of general callee saved registers in frame. - std::vector Moves; - TFL->getInitialFrameState(Moves); - Asm->EmitCFIFrameMoves(Moves); - Asm->EmitCFIFrameMoves(MMI->getFrameMoves()); - } - if (!shouldEmitTable) return; @@ -112,11 +110,25 @@ // Indicate personality routine, if any. unsigned PerEncoding = TLOF.getPersonalityEncoding(); - if (PerEncoding != dwarf::DW_EH_PE_omit && - MMI->getPersonalities()[MMI->getPersonalityIndex()]) - Asm->OutStreamer.EmitCFIPersonality(Asm->GetTempSymbol("personality", - MMI->getPersonalityIndex()), - PerEncoding); + const Function *Per = MMI->getPersonalities()[MMI->getPersonalityIndex()]; + if (PerEncoding == dwarf::DW_EH_PE_omit || !Per) + return; + + const MCSymbol *Sym; + switch (PerEncoding & 0x70) { + default: + report_fatal_error("We do not support this DWARF encoding yet!"); + case dwarf::DW_EH_PE_absptr: { + Sym = Asm->Mang->getSymbol(Per); + break; + } + case dwarf::DW_EH_PE_pcrel: { + Sym = Asm->GetTempSymbol("personality", + MMI->getPersonalityIndex()); + break; + } + } + Asm->OutStreamer.EmitCFIPersonality(Sym, PerEncoding); } /// EndFunction - Gather and emit post-function exception information. Modified: llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp?rev=129518&r1=129517&r2=129518&view=diff ============================================================================== --- llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp (original) +++ llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp Thu Apr 14 10:18:53 2011 @@ -314,7 +314,7 @@ MCStreamer &Streamer) const { const MCExpr *Res = MCSymbolRefExpr::Create(Sym, getContext()); - switch (Encoding & 0xF0) { + switch (Encoding & 0x70) { default: report_fatal_error("We do not support this DWARF encoding yet!"); case dwarf::DW_EH_PE_absptr: Modified: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=129518&r1=129517&r2=129518&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp Thu Apr 14 10:18:53 2011 @@ -22,6 +22,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/CommandLine.h" @@ -476,6 +477,15 @@ .addReg(StackPtr); if (needsFrameMoves) { + const MCAsmInfo &MAI = MMI.getContext().getAsmInfo(); + if (MAI.getExceptionHandlingType() == ExceptionHandling::DwarfCFI) { + MCSymbol *FrameLabel0 = MMI.getContext().CreateTempSymbol(); + BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel0); + MachineLocation FPSrc0(FramePtr); + MachineLocation FPDst0(FramePtr, -2 * stackGrowth); + Moves.push_back(MachineMove(FrameLabel0, FPDst0, FPSrc0)); + } + // Mark effective beginning of when frame pointer becomes valid. MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel); @@ -615,7 +625,7 @@ emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII, *RegInfo); - if ((NumBytes || PushedRegs) && needsFrameMoves) { + if (( (!HasFP && NumBytes) || PushedRegs) && needsFrameMoves) { // Mark end of stack pointer adjustment. MCSymbol *Label = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label); Modified: llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp?rev=129518&r1=129517&r2=129518&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp Thu Apr 14 10:18:53 2011 @@ -89,7 +89,9 @@ SupportsDebugInformation = true; // Exceptions handling - ExceptionsType = ExceptionHandling::DwarfTable; + ExceptionsType = ExceptionHandling::DwarfCFI; + + DwarfRequiresFrameSection = false; // OpenBSD has buggy support for .quad in 32-bit mode, just split into two // .words. Modified: llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll?rev=129518&r1=129517&r2=129518&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll (original) +++ llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll Thu Apr 14 10:18:53 2011 @@ -1,4 +1,7 @@ -; RUN: llc < %s -mtriple=i686-pc-linux-gnu -o - | grep zPL +; RUN: llc < %s -mtriple=i686-pc-linux-gnu -o - | FileCheck %s + +; CHECK: .cfi_lsda 0, .Lexception0 +; CHECK: .cfi_personality 0, __gnat_eh_personality @error = external global i8 ; [#uses=2] Removed: llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll?rev=129517&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll (original) +++ llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll (removed) @@ -1,12 +0,0 @@ -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu | grep ^.L_Z1fv.eh -; RUN: llc < %s -march=x86 -mtriple=i686-unknown-linux-gnu | grep ^.L_Z1fv.eh -; RUN: llc < %s -march=x86-64 -mtriple=x86_64-apple-darwin9 | grep ^__Z1fv.eh -; RUN: llc < %s -march=x86 -mtriple=i386-apple-darwin9 | grep ^__Z1fv.eh - -define void @_Z1fv() { -entry: - br label %return - -return: - ret void -} Modified: llvm/trunk/test/CodeGen/X86/aliases.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/aliases.ll?rev=129518&r1=129517&r2=129518&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/aliases.ll (original) +++ llvm/trunk/test/CodeGen/X86/aliases.ll Thu Apr 14 10:18:53 2011 @@ -1,6 +1,4 @@ ; RUN: llc < %s -mtriple=i686-pc-linux-gnu -asm-verbose=false -o %t -; RUN: grep { = } %t | count 16 -; RUN: grep set %t | count 18 ; RUN: grep globl %t | count 6 ; RUN: grep weak %t | count 1 ; RUN: grep hidden %t | count 1 From daniel at zuster.org Thu Apr 14 10:21:17 2011 From: daniel at zuster.org (Daniel Dunbar) Date: Thu, 14 Apr 2011 15:21:17 -0000 Subject: [llvm-commits] [llvm] r129519 - /llvm/trunk/test/FrontendC/cstring-align.c Message-ID: <20110414152117.186962A6C12C@llvm.org> Author: ddunbar Date: Thu Apr 14 10:21:16 2011 New Revision: 129519 URL: http://llvm.org/viewvc/llvm-project?rev=129519&view=rev Log: tests: Remove a FrontendC test which is no longer valid. Removed: llvm/trunk/test/FrontendC/cstring-align.c Removed: llvm/trunk/test/FrontendC/cstring-align.c URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/FrontendC/cstring-align.c?rev=129518&view=auto ============================================================================== --- llvm/trunk/test/FrontendC/cstring-align.c (original) +++ llvm/trunk/test/FrontendC/cstring-align.c (removed) @@ -1,11 +0,0 @@ -// RUN: %llvmgcc %s -S -Os -o - | llc -march=x86 -mtriple=i386-apple-darwin10 | FileCheck %s - -extern void func(const char *, const char *); - -void long_function_name() { - func("%s: the function name", __func__); -} - -// CHECK: .align 4 -// CHECK: ___func__. -// CHECK: .asciz "long_function_name" From clattner at apple.com Thu Apr 14 10:36:43 2011 From: clattner at apple.com (Chris Lattner) Date: Thu, 14 Apr 2011 08:36:43 -0700 Subject: [llvm-commits] [cfe-commits] [PATCH] share code between StringRef and ArrayRef In-Reply-To: References: Message-ID: <96F69282-ADC3-4822-BB93-F50119D65710@apple.com> On Apr 14, 2011, at 5:35 AM, Benjamin Kramer wrote: On 14.04.2011, at 09:56, Jay Foad wrote: > >> This patch removes a bit of code from StringRef by making it derive >> from ArrayRef. >> >> Comments? OK to commit? The savings aren't huge, so I'm not >> particularly wedded to the patch. > > Hi Jay, > > Have you checked the compile time impact of this? StringRef.h is included everywhere and ArrayRef.h pulls in Smallvector and Vector which are both big headers. I don't think this is worth it. Yeah, I tend to agree. I don't think it's worth it.. -Chris From clattner at apple.com Thu Apr 14 10:49:33 2011 From: clattner at apple.com (Chris Lattner) Date: Thu, 14 Apr 2011 08:49:33 -0700 Subject: [llvm-commits] [llvm] r129509 - /llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp In-Reply-To: <20110414080401.7E4302A6C12D@llvm.org> References: <20110414080401.7E4302A6C12D@llvm.org> Message-ID: <61AF85B6-48F9-48D0-9B0F-6023B5BDC2B6@apple.com> On Apr 14, 2011, at 1:04 AM, Mon P Wang wrote: > Author: wangmp > Date: Thu Apr 14 03:04:01 2011 > New Revision: 129509 > > URL: http://llvm.org/viewvc/llvm-project?rev=129509&view=rev > Log: > Cleanup r129472 by using a utility routine as suggested by Eli. Thanks Mon Ping, some more minor nits :) > +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Thu Apr 14 03:04:01 2011 > @@ -676,6 +676,37 @@ > llvm_unreachable("Invalid type for a partial vector access of an alloca!"); > } > > +/// CreateShuffleVectorCast - Creates a shuffle vector to convert one vector > +/// to another vector of the same element type which has the same allocation > +/// size but different primitive sizes (e.g. <3 x i32> and <4 x i32>). > +static Value *CreateShuffleVectorCast(Value *FromVal, const Type *ToType, > + IRBuilder<> &Builder) { > + const Type *FromType = FromVal->getType(); > + const VectorType *FromVTy = dyn_cast(FromType); > + const VectorType *ToVTy = dyn_cast(ToType); > + assert(FromVTy && ToVTy && > + (ToVTy->getElementType() == FromVTy->getElementType()) && > + "Vectors must have the same element type"); Instead of using dyn_cast + assert(!null), please just use cast<> > + LLVMContext &Context = FromVal->getContext(); > + Value *UnV = UndefValue::get(FromType); > + unsigned numEltsFrom = FromVTy->getNumElements(); > + unsigned numEltsTo = ToVTy->getNumElements(); > + > + SmallVector Args; > + unsigned minNumElts = std::min(numEltsFrom, numEltsTo); > + unsigned i; > + for (i=0; i != minNumElts; ++i) > + Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); You can use Builder.getInt32Ty() to simplify the code, or Builder.getInt32(i) to simplify it even more. -Chris From clattner at apple.com Thu Apr 14 11:01:27 2011 From: clattner at apple.com (Chris Lattner) Date: Thu, 14 Apr 2011 09:01:27 -0700 Subject: [llvm-commits] [PATCH] PR9214: convert InvokeInst API to use ArrayRef In-Reply-To: References: Message-ID: <1E25632F-A356-4A42-B4DA-5551AAC15214@apple.com> On Apr 14, 2011, at 4:13 AM, Jay Foad wrote: > See http://llvm.org/bugs/show_bug.cgi?id=9214 > > The bugs says: > >> Various LLVM APIs (such as the Constant*::get APIs, the >> GetElementPtrInst::Create methods, IRBuilder CreateGEP method, etc) that take >> multiple input values take std::vectors, and some now also can take a pointer >> to the start of an array and a count (for use with SmallVector). The new >> ArrayRef class subsumes both of these uses and is more convenient to use. > > I had a look at the "IRBuilder CreateGEP method", and noticed that > there are several Instructions that could take ArrayRefs where they > currently take a pair of RandomAccessIterators, both in their own > constructors and Create() methods, and in the corresponding IRBuilder > API to create them. The Instructions in question are: > > CallInst > InvokeInst > GetElementPtrInst > InsertValueInst > ExtractValueInst > > This patch just converts InvokeInst, because I thought it would be the > easiest one to start with. Great, makes sense. > I'm concerned about the amount of churn it causes. It touches more or > less every place that creates an InvokeInst. I expect there to be way > more churn with more common Instructions like CallInst and > GetElementPtrInst. Do we really want to cause this pain for all > clients of the LLVM APIs? I think that this is clearly the right thing to do for the APIs, and we don't worry about client churn. In terms of making your life easier, it is probably best to a) introduce a new ArrayRef overload, b) convert clients to use it (including clang etc) then c) remove the old overloads. Thanks for working on this Jay! -Chris From resistor at mac.com Thu Apr 14 12:30:49 2011 From: resistor at mac.com (Owen Anderson) Date: Thu, 14 Apr 2011 17:30:49 -0000 Subject: [llvm-commits] [llvm] r129522 - /llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Message-ID: <20110414173049.C965D2A6C12C@llvm.org> Author: resistor Date: Thu Apr 14 12:30:49 2011 New Revision: 129522 URL: http://llvm.org/viewvc/llvm-project?rev=129522&view=rev Log: Fix another instance of the DAG combiner not using the correct type for the RHS of a shift. Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=129522&r1=129521&r2=129522&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original) +++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Thu Apr 14 12:30:49 2011 @@ -3323,8 +3323,10 @@ return DAG.getUNDEF(VT); if (!LegalTypes || TLI.isTypeDesirableForOp(ISD::SRL, SmallVT)) { + uint64_t ShiftAmt = N1C->getZExtValue(); SDValue SmallShift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), SmallVT, - N0.getOperand(0), N1); + N0.getOperand(0), + DAG.getConstant(ShiftAmt, getShiftAmountTy(SmallVT))); AddToWorkList(SmallShift.getNode()); return DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), VT, SmallShift); } @@ -6264,7 +6266,7 @@ Ptr, ST->getPointerInfo(), ST->isVolatile(), ST->isNonTemporal(), OrigAlign); } - + // Turn 'store undef, Ptr' -> nothing. if (Value.getOpcode() == ISD::UNDEF && ST->isUnindexed()) return Chain; @@ -6303,7 +6305,7 @@ Ptr, ST->getPointerInfo(), ST->isVolatile(), ST->isNonTemporal(), ST->getAlignment()); } - + if (!ST->isVolatile() && TLI.isOperationLegalOrCustom(ISD::STORE, MVT::i32)) { // Many FP stores are not made apparent until after legalize, e.g. for From atrick at apple.com Thu Apr 14 13:42:22 2011 From: atrick at apple.com (Andrew Trick) Date: Thu, 14 Apr 2011 18:42:22 -0000 Subject: [llvm-commits] [test-suite] r129526 - /test-suite/trunk/Makefile.rules Message-ID: <20110414184222.6C4DC2A6C12C@llvm.org> Author: atrick Date: Thu Apr 14 13:42:22 2011 New Revision: 129526 URL: http://llvm.org/viewvc/llvm-project?rev=129526&view=rev Log: whitespace Modified: test-suite/trunk/Makefile.rules Modified: test-suite/trunk/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.rules?rev=129526&r1=129525&r2=129526&view=diff ============================================================================== --- test-suite/trunk/Makefile.rules (original) +++ test-suite/trunk/Makefile.rules Thu Apr 14 13:42:22 2011 @@ -4,7 +4,7 @@ # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# #===------------------------------------------------------------------------===# # # This file is included by all of the LLVM makefiles. This file defines common @@ -15,8 +15,8 @@ # The following functionality can be set by setting incoming variables. # The variable $(LEVEL) *must* be set: # -# 1. LEVEL - The level of the current subdirectory from the top of the -# MagicStats view. This level should be expressed as a path, for +# 1. LEVEL - The level of the current subdirectory from the top of the +# MagicStats view. This level should be expressed as a path, for # example, ../.. for two levels deep. # # 2. DIRS - A list of subdirectories to be built. Fake targets are set up @@ -29,7 +29,7 @@ # built, which are then built in any order. # # 4. Source - If specified, this sets the source code filenames. If this -# is not set, it defaults to be all of the .cpp, .c, .y, and .l files +# is not set, it defaults to be all of the .cpp, .c, .y, and .l files # in the current directory. Also, if you want to build files in addition # to the local files, you can use the ExtraSource variable # @@ -50,7 +50,7 @@ # placed. # # For building, -# LLVM, LLVM_SRC_ROOT = PROJ_SRC_ROOT +# LLVM, LLVM_SRC_ROOT = PROJ_SRC_ROOT # #===-----------------------------------------------------------------------==== @@ -61,8 +61,8 @@ ########################################################################### # Default Targets: -# The following targets are the standard top level targets for -# building. +# The following targets are the standard top level targets for +# building. ########################################################################### # Ensure people re-run configure when it gets updated @@ -100,19 +100,19 @@ # Print out the directories used for building prdirs:: - @${ECHO} "Build Source Root: " $(PROJ_SRC_ROOT) - @${ECHO} "Build Source Dir : " $(PROJ_SRC_DIR) - @${ECHO} "Build Object Root: " $(PROJ_OBJ_ROOT) - @${ECHO} "Build Object Dir : " $(PROJ_OBJ_DIR) - @${ECHO} "LLVM Source Root: " $(LLVM_SRC_ROOT) - @${ECHO} "LLVM Object Root: " $(LLVM_OBJ_ROOT) - @${ECHO} "CONFIGURATION : " $(CONFIGURATION) + @${ECHO} "Build Source Root: " $(PROJ_SRC_ROOT) + @${ECHO} "Build Source Dir : " $(PROJ_SRC_DIR) + @${ECHO} "Build Object Root: " $(PROJ_OBJ_ROOT) + @${ECHO} "Build Object Dir : " $(PROJ_OBJ_DIR) + @${ECHO} "LLVM Source Root: " $(LLVM_SRC_ROOT) + @${ECHO} "LLVM Object Root: " $(LLVM_OBJ_ROOT) + @${ECHO} "CONFIGURATION : " $(CONFIGURATION) ########################################################################### # Suffixes and implicit rules: -# Empty out the list of suffixes, generate a list that is only -# used by this Makefile, and cancel useless implicit rules. This -# will hopefully speed up compilation a little bit. +# Empty out the list of suffixes, generate a list that is only +# used by this Makefile, and cancel useless implicit rules. This +# will hopefully speed up compilation a little bit. ########################################################################### .SUFFIXES: .SUFFIXES: .c .cpp .h .hpp .y .l @@ -129,12 +129,12 @@ ########################################################################### # Miscellaneous paths and commands: -# This section defines various configuration macros, such as where -# to find burg, tblgen, and libtool. +# This section defines various configuration macros, such as where +# to find burg, tblgen, and libtool. ########################################################################### #-------------------------------------------------------------------- -# Variables derived from configuration options... +# Variables derived from configuration options... #-------------------------------------------------------------------- ifeq ($(ENABLE_PROFILING),1) @@ -190,11 +190,11 @@ ########################################################################### # Library Locations: -# These variables describe various library locations: +# These variables describe various library locations: # -# DEST* = Location of where libraries that are built will be placed. -# LLVM* = Location of LLVM libraries used for linking. -# PROJ* = Location of previously built libraries used for linking. +# DEST* = Location of where libraries that are built will be placed. +# LLVM* = Location of LLVM libraries used for linking. +# PROJ* = Location of previously built libraries used for linking. ########################################################################### # Libraries that are being built @@ -218,11 +218,11 @@ ########################################################################### # Tool Locations -# These variables describe various tool locations: +# These variables describe various tool locations: # -# DEST* = Location of where tools that are built will be placed. -# LLVM* = Location of LLVM tools used for building. -# PROJ* = Location of previously built tools used for linking. +# DEST* = Location of where tools that are built will be placed. +# LLVM* = Location of LLVM tools used for building. +# PROJ* = Location of previously built tools used for linking. ########################################################################### DESTTOOLDEBUG := $(PROJ_OBJ_ROOT)/Debug/bin @@ -297,8 +297,8 @@ ########################################################################### # Miscellaneous paths and commands (part deux): -# This section defines various configuration macros, such as where -# to find burg, tblgen, and libtool. +# This section defines various configuration macros, such as where +# to find burg, tblgen, and libtool. ########################################################################### #-------------------------------------------------------------------------- @@ -307,7 +307,7 @@ LLVMAS := $(LLVMTOOLCURRENT)/llvm-as$(EXEEXT) # LLVM Tool Definitions (LLVMGCC, LLVMGXX, LLVMAS are provided by -# Makefile.rules) +# Makefile.rules) LLI = $(LLVMTOOLCURRENT)/lli$(EXEEXT) LLC = $(LLVMTOOLCURRENT)/llc$(EXEEXT) LLVMLD = $(LLVMTOOLCURRENT)/llvm-ld$(EXEEXT) @@ -456,7 +456,7 @@ # # Link final executable -# (Note that we always link with the C++ compiler). +# (Note that we always link with the C++ compiler). # Link := $(LIBTOOL) --tag=CXX --mode=link $(CXX) @@ -470,9 +470,9 @@ # are passed to the linker *before* the USEDLIBS options are passed. # e.g. usage TOOLLINKOPTSB = -L/home/xxx/lib ifdef TOOLLINKOPTSB -LinkG := $(LinkG) $(TOOLLINKOPTSB) -LinkO := $(LinkO) $(TOOLLINKOPTSB) -LinkP := $(LinkP) $(TOOLLINKOPTSB) +LinkG := $(LinkG) $(TOOLLINKOPTSB) +LinkO := $(LinkO) $(TOOLLINKOPTSB) +LinkP := $(LinkP) $(TOOLLINKOPTSB) endif # Create one .o file from a bunch of .o files... @@ -490,8 +490,8 @@ endif # Create dependency file from CPP file, send to stdout. -Depend := $(CXX) -MM -I$(LEVEL)/include $(CPPFLAGS) -DependC := $(CC) -MM -I$(LEVEL)/include $(CPPFLAGS) +Depend := $(CXX) -MM -I$(LEVEL)/include $(CPPFLAGS) +DependC := $(CC) -MM -I$(LEVEL)/include $(CPPFLAGS) # Archive a bunch of .o files into a .a file... AR = $(AR_PATH) cr @@ -501,7 +501,7 @@ # Source includes all of the cpp files, and objects are derived from the # source files... # The local Makefile can list other Source files via ExtraSource = ... -# +# ifndef Source Source := $(notdir $(ExtraSource) $(wildcard $(SourceDir)/*.cpp \ $(SourceDir)/*.cc $(SourceDir)/*.c $(SourceDir)/*.y \ @@ -531,14 +531,14 @@ ifdef DIRS all install clean test bytecode native stripped-bytecode install-bytecode:: - $(VERB) for dir in ${DIRS}; do \ - if [ ! -f $$dir/Makefile ]; \ - then \ - $(MKDIR) $$dir; \ - cp $(SourceDir)/$$dir/Makefile $$dir/Makefile; \ - fi; \ - ($(MAKE) -C $$dir $@ $(MFLAGS)) || exit 1; \ - done + $(VERB) for dir in ${DIRS}; do \ + if [ ! -f $$dir/Makefile ]; \ + then \ + $(MKDIR) $$dir; \ + cp $(SourceDir)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ $(MFLAGS)) || exit 1; \ + done endif # Handle PARALLEL_DIRS @@ -554,28 +554,28 @@ %/.makeall %/.makeinstall %/.makeclean %/.maketest %/.makebytecode \ %/.makestripped-bytecode %/.makeinstall-bytecode %/.makenative: - $(VERB) if [ ! -f $(@D)/Makefile ]; \ - then \ - $(MKDIR) $(@D); \ - cp $(SourceDir)/$(@D)/Makefile $(@D)/Makefile; \ - fi; \ - $(MAKE) -C $(@D) $(subst $(@D)/.make,,$@) $(MFLAGS) + $(VERB) if [ ! -f $(@D)/Makefile ]; \ + then \ + $(MKDIR) $(@D); \ + cp $(SourceDir)/$(@D)/Makefile $(@D)/Makefile; \ + fi; \ + $(MAKE) -C $(@D) $(subst $(@D)/.make,,$@) $(MFLAGS) endif # Handle directories that may or may not exist ifdef OPTIONAL_DIRS all install clean test bytecode stripped-bytecode install-bytecode:: - $(VERB) for dir in ${OPTIONAL_DIRS}; do \ - if [ -d $(SourceDir)/$$dir ]; \ - then\ - if [ ! -f $$dir/Makefile ]; \ - then \ - $(MKDIR) $$dir; \ - cp $(SourceDir)/$$dir/Makefile $$dir/Makefile; \ - fi; \ - ($(MAKE) -C$$dir $@ $(MFLAGS)) || exit 1; \ - fi \ - done + $(VERB) for dir in ${OPTIONAL_DIRS}; do \ + if [ -d $(SourceDir)/$$dir ]; \ + then\ + if [ ! -f $$dir/Makefile ]; \ + then \ + $(MKDIR) $$dir; \ + cp $(SourceDir)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C$$dir $@ $(MFLAGS)) || exit 1; \ + fi \ + done endif #--------------------------------------------------------- @@ -585,13 +585,13 @@ install:: install-config-files $(sysconfdir): - $(MKDIR) $(sysconfdir) + $(MKDIR) $(sysconfdir) install-config-files: $(sysconfdir) $(CONFIG_FILES) - $(VERB)$(ECHO) Installing Configuration Files To $(sysconfdir) - $(VERB)for file in $(CONFIG_FILES); do \ - $(INSTALL) $(SourceDir)/$${file} $(sysconfdir) ; \ - done + $(VERB)$(ECHO) Installing Configuration Files To $(sysconfdir) + $(VERB)for file in $(CONFIG_FILES); do \ + $(INSTALL) $(SourceDir)/$${file} $(sysconfdir) ; \ + done endif ########################################################################### @@ -614,7 +614,7 @@ # Install rule for making bytecode library directory if it does not exist. # Trigger this by making libraries that need to be installed here depend on it. $(DESTDIR)$(bytecode_libdir): - $(MKDIR) $@ + $(MKDIR) $@ ifdef LIBRARYNAME @@ -638,7 +638,7 @@ #-------------------------------------------------------------------- # Library Targets -# Modify the top level targets to build the desired libraries. +# Modify the top level targets to build the desired libraries. #-------------------------------------------------------------------- # dynamic target builds a shared object version of the library... @@ -647,8 +647,8 @@ install-bytecode-library:: $(DESTDIR)$(bytecode_libdir)/lib$(LIBRARYNAME).bc $(DESTDIR)$(bytecode_libdir)/lib$(LIBRARYNAME).bc: $(LIBNAME_BC) $(DESTDIR)$(bytecode_libdir) - @${ECHO} ======= Installing $(LIBRARYNAME) bytecode library ======= - $(VERB)cp $< $@ + @${ECHO} ======= Installing $(LIBRARYNAME) bytecode library ======= + $(VERB)cp $< $@ # Does the library want a .o version built? ifndef DONT_BUILD_RELINKED @@ -680,89 +680,89 @@ # Rule for building bytecode libraries. $(LIBNAME_BC): $(ObjectsBC) $(LibSubDirs) $(DESTLIBBYTECODE)/.dir - @${ECHO} Linking $(LIBRARYNAME) bytecode library - $(VERB) $(LinkBCLib) -o $@ $(ObjectsBC) $(LibSubDirs) $(LibLinkOpts) - @${ECHO} ======= Finished building $(LIBRARYNAME) bytecode library ======= + @${ECHO} Linking $(LIBRARYNAME) bytecode library + $(VERB) $(LinkBCLib) -o $@ $(ObjectsBC) $(LibSubDirs) $(LibLinkOpts) + @${ECHO} ======= Finished building $(LIBRARYNAME) bytecode library ======= # # Rules for building dynamically linked libraries. # $(LIBNAME_O): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir - @${ECHO} Linking $(LIBRARYNAME) dynamic release library - $(VERB) $(Link) -o $@ $(ObjectsO) $(LibSubDirs) $(LibLinkOpts) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) - @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic release library ======= + @${ECHO} Linking $(LIBRARYNAME) dynamic release library + $(VERB) $(Link) -o $@ $(ObjectsO) $(LibSubDirs) $(LibLinkOpts) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) + @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic release library ======= $(LIBNAME_P): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir - @${ECHO} Linking $(LIBRARYNAME) dynamic profile library - $(VERB) $(Link) -o $@ $(ObjectsP) $(LibSubDirs) $(LibLinkOpts) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) - @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic profile library ======= + @${ECHO} Linking $(LIBRARYNAME) dynamic profile library + $(VERB) $(Link) -o $@ $(ObjectsP) $(LibSubDirs) $(LibLinkOpts) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) + @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic profile library ======= $(LIBNAME_G): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir - @${ECHO} Linking $(LIBRARYNAME) dynamic debug library - $(VERB) $(Link) -o $@ $(ObjectsG) $(LibSubDirs) $(LibLinkOpts) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) - @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic debug library ======= + @${ECHO} Linking $(LIBRARYNAME) dynamic debug library + $(VERB) $(Link) -o $@ $(ObjectsG) $(LibSubDirs) $(LibLinkOpts) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) + @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic debug library ======= install-dynamic-library: $(LIBNAME_CUR) - $(MKDIR) $(DESTDIR)$(libdir) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_CUR) $(DESTDIR)$(libdir)/lib$(LIBRARYNAME)$(SHLIBEXT) - $(VERB) $(LIBTOOL) --finish $(DESTDIR)$(libdir) + $(MKDIR) $(DESTDIR)$(libdir) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_CUR) $(DESTDIR)$(libdir)/lib$(LIBRARYNAME)$(SHLIBEXT) + $(VERB) $(LIBTOOL) --finish $(DESTDIR)$(libdir) # # Rules for building static archive libraries. # $(LIBNAME_AO): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir - @${ECHO} Linking $(LIBRARYNAME) archive release library - $(VERB)$(RM) -f $@ - $(VERB) $(Link) -03 -o $@ $(ObjectsO) $(LibSubDirs) -static - @${ECHO} Finished building $(LIBRARYNAME) archive release library ======= + @${ECHO} Linking $(LIBRARYNAME) archive release library + $(VERB)$(RM) -f $@ + $(VERB) $(Link) -03 -o $@ $(ObjectsO) $(LibSubDirs) -static + @${ECHO} Finished building $(LIBRARYNAME) archive release library ======= $(LIBNAME_AP): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir - @${ECHO} Linking $(LIBRARYNAME) archive profile library - @$(RM) -f $@ - $(VERB) $(Link) -03 $(PROFILE) -o $@ $(ObjectsP) $(LibSubDirs) -static - @${ECHO} ======= Finished building $(LIBRARYNAME) archive profile library ======= + @${ECHO} Linking $(LIBRARYNAME) archive profile library + @$(RM) -f $@ + $(VERB) $(Link) -03 $(PROFILE) -o $@ $(ObjectsP) $(LibSubDirs) -static + @${ECHO} ======= Finished building $(LIBRARYNAME) archive profile library ======= $(LIBNAME_AG): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir - @${ECHO} Linking $(LIBRARYNAME) archive debug library - @$(RM) -f $@ - $(VERB) $(Link) -g $(STRIP) -o $@ $(ObjectsG) $(LibSubDirs) -static - @${ECHO} ======= Finished building $(LIBRARYNAME) archive debug library ======= + @${ECHO} Linking $(LIBRARYNAME) archive debug library + @$(RM) -f $@ + $(VERB) $(Link) -g $(STRIP) -o $@ $(ObjectsG) $(LibSubDirs) -static + @${ECHO} ======= Finished building $(LIBRARYNAME) archive debug library ======= install-archive-library: $(LIBNAME_ACUR) - $(MKDIR) $(DESTDIR)$(libdir) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_ACUR) $(DESTDIR)$(libdir)/lib$(LIBRARYNAME).a + $(MKDIR) $(DESTDIR)$(libdir) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_ACUR) $(DESTDIR)$(libdir)/lib$(LIBRARYNAME).a # # Rules for building .o libraries. # -# JTC: -# Note that for this special case, we specify the actual object files -# instead of their libtool counterparts. This is because libtool -# doesn't want to generate a reloadable object file unless it is given -# .o files explicitly. +# JTC: +# Note that for this special case, we specify the actual object files +# instead of their libtool counterparts. This is because libtool +# doesn't want to generate a reloadable object file unless it is given +# .o files explicitly. # -# Note that we're making an assumption here: If we build a .lo file, -# its corresponding .o file will be placed in the same directory. +# Note that we're making an assumption here: If we build a .lo file, +# its corresponding .o file will be placed in the same directory. # -# I think that is safe. +# I think that is safe. # $(LIBNAME_OBJO): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir - @${ECHO} "Linking `basename $@`" - $(VERB) $(Relink) -o $@ $(RObjectsO) $(LibSubDirs) + @${ECHO} "Linking `basename $@`" + $(VERB) $(Relink) -o $@ $(RObjectsO) $(LibSubDirs) $(LIBNAME_OBJP): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir - @${ECHO} "Linking `basename $@`" - $(VERB) $(Relink) -o $@ $(RObjectsP) $(LibSubDirs) + @${ECHO} "Linking `basename $@`" + $(VERB) $(Relink) -o $@ $(RObjectsP) $(LibSubDirs) $(LIBNAME_OBJG): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir - @${ECHO} "Linking `basename $@`" - $(VERB) $(Relink) -o $@ $(RObjectsG) $(LibSubDirs) + @${ECHO} "Linking `basename $@`" + $(VERB) $(Relink) -o $@ $(RObjectsG) $(LibSubDirs) install-single-object-library: $(LIBNAME_OBJCUR) - $(MKDIR) $(DESTDIR)$(libdir) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_OBJCUR) $(DESTDIR)$(libdir)/$(LIBRARYNAME).o + $(MKDIR) $(DESTDIR)$(libdir) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_OBJCUR) $(DESTDIR)$(libdir)/$(LIBRARYNAME).o endif @@ -821,8 +821,8 @@ # # Libtool link options: -# Ensure that all binaries have their symbols exported so that they can -# by dlsym'ed. +# Ensure that all binaries have their symbols exported so that they can +# by dlsym'ed. # LINK_OPTS := -export-dynamic $(TOOLLINKOPTS) @@ -838,27 +838,27 @@ all:: $(TOOLEXENAMES) clean:: - $(VERB) $(RM) -f $(TOOLEXENAMES) + $(VERB) $(RM) -f $(TOOLEXENAMES) $(TOOLEXENAME_G): $(ObjectsG) $(USED_LIB_PATHS_G) $(LLVM_LIB_PATHS_G) $(DESTTOOLDEBUG)/.dir - @${ECHO} Linking $(TOOLNAME) debug executable $(STRIP_WARN_MSG) - $(VERB) $(LinkG) -o $@ $(ObjectsG) $(LIB_OPTS_G) $(LINK_OPTS) $(LIBS) - @${ECHO} ======= Finished building $(TOOLNAME) debug executable $(STRIP_WARN_MSG) ======= + @${ECHO} Linking $(TOOLNAME) debug executable $(STRIP_WARN_MSG) + $(VERB) $(LinkG) -o $@ $(ObjectsG) $(LIB_OPTS_G) $(LINK_OPTS) $(LIBS) + @${ECHO} ======= Finished building $(TOOLNAME) debug executable $(STRIP_WARN_MSG) ======= $(TOOLEXENAME_O): $(ObjectsO) $(USED_LIB_PATHS_O) $(LLVM_LIB_PATHS_O) $(DESTTOOLRELEASE)/.dir - @${ECHO} Linking $(TOOLNAME) release executable - $(VERB) $(LinkO) -o $@ $(ObjectsO) $(LIB_OPTS_O) $(LINK_OPTS) $(LIBS) - @${ECHO} ======= Finished building $(TOOLNAME) release executable ======= + @${ECHO} Linking $(TOOLNAME) release executable + $(VERB) $(LinkO) -o $@ $(ObjectsO) $(LIB_OPTS_O) $(LINK_OPTS) $(LIBS) + @${ECHO} ======= Finished building $(TOOLNAME) release executable ======= $(TOOLEXENAME_P): $(ObjectsP) $(USED_LIB_PATHS_P) $(LLVM_LIB_PATHS_P) $(DESTTOOLPROFILE)/.dir - @${ECHO} Linking $(TOOLNAME) profile executable - $(VERB) $(LinkP) -o $@ $(ObjectsP) $(LIB_OPTS_P) $(LINK_OPTS) $(LIBS) - @${ECHO} ======= Finished building $(TOOLNAME) profile executable ======= + @${ECHO} Linking $(TOOLNAME) profile executable + $(VERB) $(LinkP) -o $@ $(ObjectsP) $(LIB_OPTS_P) $(LINK_OPTS) $(LIBS) + @${ECHO} ======= Finished building $(TOOLNAME) profile executable ======= install:: $(TOOLEXENAMES) - @${ECHO} Installing $(TOOLEXENAMES) to $(DESTDIR)$(bindir) - $(VERB)$(MKDIR) $(DESTDIR)$(bindir) - $(VERB)$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) -c -m 0755 $(TOOLEXENAMES) $(DESTDIR)$(bindir)/$(TOOLNAME) + @${ECHO} Installing $(TOOLEXENAMES) to $(DESTDIR)$(bindir) + $(VERB)$(MKDIR) $(DESTDIR)$(bindir) + $(VERB)$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) -c -m 0755 $(TOOLEXENAMES) $(DESTDIR)$(bindir)/$(TOOLNAME) endif @@ -869,31 +869,31 @@ # Create .lo files in the ObjectFiles directory from the .cpp and .c files... $(PROJ_OBJ_DIR)/Release/%.lo: %.cpp $(PROJ_OBJ_DIR)/Release/.dir - $(CompileO) $< -o $@ + $(CompileO) $< -o $@ $(PROJ_OBJ_DIR)/Release/%.lo: %.c $(PROJ_OBJ_DIR)/Release/.dir - $(CompileCO) $< -o $@ + $(CompileCO) $< -o $@ $(PROJ_OBJ_DIR)/Profile/%.lo: %.cpp $(PROJ_OBJ_DIR)/Profile/.dir - $(CompileP) $< -o $@ + $(CompileP) $< -o $@ $(PROJ_OBJ_DIR)/Profile/%.lo: %.c $(PROJ_OBJ_DIR)/Profile/.dir - $(CompileCP) $< -o $@ + $(CompileCP) $< -o $@ $(PROJ_OBJ_DIR)/Debug/%.lo: %.cpp $(PROJ_OBJ_DIR)/Debug/.dir - $(CompileG) $< -o $@ + $(CompileG) $< -o $@ -$(PROJ_OBJ_DIR)/Debug/%.lo: %.c $(PROJ_OBJ_DIR)/Debug/.dir - $(CompileCG) $< -o $@ +$(PROJ_OBJ_DIR)/Debug/%.lo: %.c $(PROJ_OBJ_DIR)/Debug/.dir + $(CompileCG) $< -o $@ $(PROJ_OBJ_DIR)/BytecodeObj/%.bc: %.cpp $(PROJ_OBJ_DIR)/BytecodeObj/.dir $(LCC_PROGRAMS) - $(LCXX) $(CPPFLAGS) -c $< -o $@ + $(LCXX) $(CPPFLAGS) -c $< -o $@ $(PROJ_OBJ_DIR)/BytecodeObj/%.bc: %.c $(PROJ_OBJ_DIR)/BytecodeObj/.dir $(LCC_PROGRAMS) - $(LCC) $(CPPFLAGS) -c $< -o $@ + $(LCC) $(CPPFLAGS) -c $< -o $@ $(PROJ_OBJ_DIR)/BytecodeObj/%.bc: %.ll $(PROJ_OBJ_DIR)/BytecodeObj/.dir $(LLVMAS) - $(LLVMAS) $< -o $@ + $(LLVMAS) $< -o $@ # @@ -914,40 +914,40 @@ # FIXME. (f.e. char Buffer[10000] ) # %.cpp: %.l - @${ECHO} Flexing $< - $(VERB) $(FLEX) -t $< | \ + @${ECHO} Flexing $< + $(VERB) $(FLEX) -t $< | \ $(SED) '/^find_rule/d' | \ $(SED) 's/void yyunput/inline void yyunput/' | \ $(SED) 's/void \*yy_flex_realloc/inline void *yy_flex_realloc/' | \ $(SED) 's/#define YY_BUF_SIZE 16384/#define YY_BUF_SIZE (16384*64)/' \ > $@.tmp - $(VERB) cmp -s $@ $@.tmp > /dev/null || ${MV} -f $@.tmp $@ - @# remove the output of flex if it didn't get moved over... - @rm -f $@.tmp + $(VERB) cmp -s $@ $@.tmp > /dev/null || ${MV} -f $@.tmp $@ + @# remove the output of flex if it didn't get moved over... + @rm -f $@.tmp # Rule for building the bison parsers... %.c: %.y # Cancel built-in rules for yacc %.h: %.y # Cancel built-in rules for yacc %.cpp %.h : %.y - @${ECHO} "Bisoning `basename $<`" - $(VERB) $(BISON) -v -d -p $( /dev/null || ${MV} -f $*.tab.c $*.cpp - $(VERB) cmp -s $*.tab.h $*.h > /dev/null || ${MV} -f $*.tab.h $*.h - @# If the files were not updated, don't leave them lying around... - @rm -f $*.tab.c $*.tab.h + @${ECHO} "Bisoning `basename $<`" + $(VERB) $(BISON) -v -d -p $( /dev/null || ${MV} -f $*.tab.c $*.cpp + $(VERB) cmp -s $*.tab.h $*.h > /dev/null || ${MV} -f $*.tab.h $*.h + @# If the files were not updated, don't leave them lying around... + @rm -f $*.tab.c $*.tab.h # To create the directories... %/.dir: - $(VERB) ${MKDIR} $* > /dev/null - @$(DATE) > $@ + $(VERB) ${MKDIR} $* > /dev/null + @$(DATE) > $@ # To create postscript files from dot files... ifneq ($(DOT),false) %.ps: %.dot - ${DOT} -Tps < $< > $@ + ${DOT} -Tps < $< > $@ else %.ps: %.dot - ${ECHO} "Cannot build $@: The program dot is not installed" + ${ECHO} "Cannot build $@: The program dot is not installed" endif # @@ -959,19 +959,19 @@ # 'make clean' nukes the tree clean:: - $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/Debug $(PROJ_OBJ_DIR)/Release - $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/Profile $(PROJ_OBJ_DIR)/Depend - $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/BytecodeObj - $(VERB) $(RM) -f core core.[0-9][0-9]* *.o *.d *~ *.flc + $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/Debug $(PROJ_OBJ_DIR)/Release + $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/Profile $(PROJ_OBJ_DIR)/Depend + $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/BytecodeObj + $(VERB) $(RM) -f core core.[0-9][0-9]* *.o *.d *~ *.flc ifneq ($(strip $(SHLIBEXT)),) # Extra paranoia - make real sure SHLIBEXT is set - $(VERB) $(RM) -f *$(SHLIBEXT) + $(VERB) $(RM) -f *$(SHLIBEXT) endif - $(VERB) $(RM) -f $(LEX_OUTPUT) $(YACC_OUTPUT) + $(VERB) $(RM) -f $(LEX_OUTPUT) $(YACC_OUTPUT) ########################################################################### # C/C++ Dependencies -# Define variables and rules that generate header file dependencies -# from C/C++ source files. +# Define variables and rules that generate header file dependencies +# from C/C++ source files. ########################################################################### ifndef DISABLE_AUTO_DEPENDENCIES @@ -984,30 +984,30 @@ # Create dependencies for the *.cpp files... $(PROJ_OBJ_DIR)/Depend/%.d: %.cpp $(PROJ_OBJ_DIR)/Depend/.dir - $(VERB) $(Depend) $< | $(SED) 's|\.o:|\.lo:|' | $(SED) 's|$*\.lo *|$(PROJ_OBJ_DIR)/Release/& $(PROJ_OBJ_DIR)/Profile/& $(PROJ_OBJ_DIR)/Debug/& $(PROJ_OBJ_DIR)/Depend/$(@F)|g' > $@ + $(VERB) $(Depend) $< | $(SED) 's|\.o:|\.lo:|' | $(SED) 's|$*\.lo *|$(PROJ_OBJ_DIR)/Release/& $(PROJ_OBJ_DIR)/Profile/& $(PROJ_OBJ_DIR)/Debug/& $(PROJ_OBJ_DIR)/Depend/$(@F)|g' > $@ # Create dependencies for the *.c files... $(PROJ_OBJ_DIR)/Depend/%.d: %.c $(PROJ_OBJ_DIR)/Depend/.dir - $(VERB) $(DependC) -o $@ $< | $(SED) 's|\.o:|\.lo:|' | $(SED) 's|$*\.lo *|$(PROJ_OBJ_DIR)/Release/& $(PROJ_OBJ_DIR)/Profile/& $(PROJ_OBJ_DIR)/Debug/& $(PROJ_OBJ_DIR)/Depend/$(@F)|g' > $@ + $(VERB) $(DependC) -o $@ $< | $(SED) 's|\.o:|\.lo:|' | $(SED) 's|$*\.lo *|$(PROJ_OBJ_DIR)/Release/& $(PROJ_OBJ_DIR)/Profile/& $(PROJ_OBJ_DIR)/Debug/& $(PROJ_OBJ_DIR)/Depend/$(@F)|g' > $@ # # Autoconf Dependencies. # ifeq ($(HAS_LLVM),1) $(LLVM_OBJ_ROOT)/config.status:: $(LLVM_SRC_ROOT)/configure - @${ECHO} "****************************************************************" - @${ECHO} " You need to re-run $(LLVM_SRC_ROOT)/configure" - @${ECHO} " in directory $(LLVM_OBJ_ROOT)" - @${ECHO} "****************************************************************" - $(VERB) exit 1 + @${ECHO} "****************************************************************" + @${ECHO} " You need to re-run $(LLVM_SRC_ROOT)/configure" + @${ECHO} " in directory $(LLVM_OBJ_ROOT)" + @${ECHO} "****************************************************************" + $(VERB) exit 1 endif # If the Makefile in the source tree has been updated, copy it over into the # build tree. Makefile :: $(PROJ_SRC_DIR)/Makefile - @${ECHO} "===== Updating Makefile from source dir: `dirname $<` =====" - $(MKDIR) $(@D) - cp -f $< $@ + @${ECHO} "===== Updating Makefile from source dir: `dirname $<` =====" + $(MKDIR) $(@D) + cp -f $< $@ # # Include dependencies generated from C/C++ source files, but not if we @@ -1027,4 +1027,4 @@ # General debugging rule, use 'make dbg-print-XXX' to print the # definition, value and origin of XXX. make-print-%: - $(error PRINT: $(value $*) = "$($*)" (from $(origin $*))) + $(error PRINT: $(value $*) = "$($*)" (from $(origin $*))) From sabre at nondot.org Thu Apr 14 13:47:18 2011 From: sabre at nondot.org (Chris Lattner) Date: Thu, 14 Apr 2011 18:47:18 -0000 Subject: [llvm-commits] [llvm] r129527 - /llvm/trunk/lib/Target/X86/README.txt Message-ID: <20110414184718.E23D62A6C12C@llvm.org> Author: lattner Date: Thu Apr 14 13:47:18 2011 New Revision: 129527 URL: http://llvm.org/viewvc/llvm-project?rev=129527&view=rev Log: move PR9661 out to here. Modified: llvm/trunk/lib/Target/X86/README.txt Modified: llvm/trunk/lib/Target/X86/README.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/README.txt?rev=129527&r1=129526&r2=129527&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/README.txt (original) +++ llvm/trunk/lib/Target/X86/README.txt Thu Apr 14 13:47:18 2011 @@ -2016,3 +2016,27 @@ We could save an instruction here by commuting the addss. //===---------------------------------------------------------------------===// + +This (from PR9661): + +float clamp_float(float a) { + if (a > 1.0f) + return 1.0f; + else if (a < 0.0f) + return 0.0f; + else + return a; +} + +Could compile to: + +clamp_float: # @clamp_float + movss .LCPI0_0(%rip), %xmm1 + minss %xmm1, %xmm0 + pxor %xmm1, %xmm1 + maxss %xmm1, %xmm0 + ret + +with -ffast-math. + +//===---------------------------------------------------------------------===// From atrick at apple.com Thu Apr 14 13:49:16 2011 From: atrick at apple.com (Andrew Trick) Date: Thu, 14 Apr 2011 18:49:16 -0000 Subject: [llvm-commits] [test-suite] r129528 - /test-suite/trunk/Makefile.rules Message-ID: <20110414184916.D97D22A6C12C@llvm.org> Author: atrick Date: Thu Apr 14 13:49:16 2011 New Revision: 129528 URL: http://llvm.org/viewvc/llvm-project?rev=129528&view=rev Log: Oops. I used the wrong whitespace script for a Makefile! Modified: test-suite/trunk/Makefile.rules Modified: test-suite/trunk/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.rules?rev=129528&r1=129527&r2=129528&view=diff ============================================================================== --- test-suite/trunk/Makefile.rules (original) +++ test-suite/trunk/Makefile.rules Thu Apr 14 13:49:16 2011 @@ -4,7 +4,7 @@ # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# #===------------------------------------------------------------------------===# # # This file is included by all of the LLVM makefiles. This file defines common @@ -15,8 +15,8 @@ # The following functionality can be set by setting incoming variables. # The variable $(LEVEL) *must* be set: # -# 1. LEVEL - The level of the current subdirectory from the top of the -# MagicStats view. This level should be expressed as a path, for +# 1. LEVEL - The level of the current subdirectory from the top of the +# MagicStats view. This level should be expressed as a path, for # example, ../.. for two levels deep. # # 2. DIRS - A list of subdirectories to be built. Fake targets are set up @@ -29,7 +29,7 @@ # built, which are then built in any order. # # 4. Source - If specified, this sets the source code filenames. If this -# is not set, it defaults to be all of the .cpp, .c, .y, and .l files +# is not set, it defaults to be all of the .cpp, .c, .y, and .l files # in the current directory. Also, if you want to build files in addition # to the local files, you can use the ExtraSource variable # @@ -50,7 +50,7 @@ # placed. # # For building, -# LLVM, LLVM_SRC_ROOT = PROJ_SRC_ROOT +# LLVM, LLVM_SRC_ROOT = PROJ_SRC_ROOT # #===-----------------------------------------------------------------------==== @@ -61,8 +61,8 @@ ########################################################################### # Default Targets: -# The following targets are the standard top level targets for -# building. +# The following targets are the standard top level targets for +# building. ########################################################################### # Ensure people re-run configure when it gets updated @@ -100,19 +100,19 @@ # Print out the directories used for building prdirs:: - @${ECHO} "Build Source Root: " $(PROJ_SRC_ROOT) - @${ECHO} "Build Source Dir : " $(PROJ_SRC_DIR) - @${ECHO} "Build Object Root: " $(PROJ_OBJ_ROOT) - @${ECHO} "Build Object Dir : " $(PROJ_OBJ_DIR) - @${ECHO} "LLVM Source Root: " $(LLVM_SRC_ROOT) - @${ECHO} "LLVM Object Root: " $(LLVM_OBJ_ROOT) - @${ECHO} "CONFIGURATION : " $(CONFIGURATION) + @${ECHO} "Build Source Root: " $(PROJ_SRC_ROOT) + @${ECHO} "Build Source Dir : " $(PROJ_SRC_DIR) + @${ECHO} "Build Object Root: " $(PROJ_OBJ_ROOT) + @${ECHO} "Build Object Dir : " $(PROJ_OBJ_DIR) + @${ECHO} "LLVM Source Root: " $(LLVM_SRC_ROOT) + @${ECHO} "LLVM Object Root: " $(LLVM_OBJ_ROOT) + @${ECHO} "CONFIGURATION : " $(CONFIGURATION) ########################################################################### # Suffixes and implicit rules: -# Empty out the list of suffixes, generate a list that is only -# used by this Makefile, and cancel useless implicit rules. This -# will hopefully speed up compilation a little bit. +# Empty out the list of suffixes, generate a list that is only +# used by this Makefile, and cancel useless implicit rules. This +# will hopefully speed up compilation a little bit. ########################################################################### .SUFFIXES: .SUFFIXES: .c .cpp .h .hpp .y .l @@ -129,12 +129,12 @@ ########################################################################### # Miscellaneous paths and commands: -# This section defines various configuration macros, such as where -# to find burg, tblgen, and libtool. +# This section defines various configuration macros, such as where +# to find burg, tblgen, and libtool. ########################################################################### #-------------------------------------------------------------------- -# Variables derived from configuration options... +# Variables derived from configuration options... #-------------------------------------------------------------------- ifeq ($(ENABLE_PROFILING),1) @@ -190,11 +190,11 @@ ########################################################################### # Library Locations: -# These variables describe various library locations: +# These variables describe various library locations: # -# DEST* = Location of where libraries that are built will be placed. -# LLVM* = Location of LLVM libraries used for linking. -# PROJ* = Location of previously built libraries used for linking. +# DEST* = Location of where libraries that are built will be placed. +# LLVM* = Location of LLVM libraries used for linking. +# PROJ* = Location of previously built libraries used for linking. ########################################################################### # Libraries that are being built @@ -218,11 +218,11 @@ ########################################################################### # Tool Locations -# These variables describe various tool locations: +# These variables describe various tool locations: # -# DEST* = Location of where tools that are built will be placed. -# LLVM* = Location of LLVM tools used for building. -# PROJ* = Location of previously built tools used for linking. +# DEST* = Location of where tools that are built will be placed. +# LLVM* = Location of LLVM tools used for building. +# PROJ* = Location of previously built tools used for linking. ########################################################################### DESTTOOLDEBUG := $(PROJ_OBJ_ROOT)/Debug/bin @@ -297,8 +297,8 @@ ########################################################################### # Miscellaneous paths and commands (part deux): -# This section defines various configuration macros, such as where -# to find burg, tblgen, and libtool. +# This section defines various configuration macros, such as where +# to find burg, tblgen, and libtool. ########################################################################### #-------------------------------------------------------------------------- @@ -307,7 +307,7 @@ LLVMAS := $(LLVMTOOLCURRENT)/llvm-as$(EXEEXT) # LLVM Tool Definitions (LLVMGCC, LLVMGXX, LLVMAS are provided by -# Makefile.rules) +# Makefile.rules) LLI = $(LLVMTOOLCURRENT)/lli$(EXEEXT) LLC = $(LLVMTOOLCURRENT)/llc$(EXEEXT) LLVMLD = $(LLVMTOOLCURRENT)/llvm-ld$(EXEEXT) @@ -456,7 +456,7 @@ # # Link final executable -# (Note that we always link with the C++ compiler). +# (Note that we always link with the C++ compiler). # Link := $(LIBTOOL) --tag=CXX --mode=link $(CXX) @@ -470,9 +470,9 @@ # are passed to the linker *before* the USEDLIBS options are passed. # e.g. usage TOOLLINKOPTSB = -L/home/xxx/lib ifdef TOOLLINKOPTSB -LinkG := $(LinkG) $(TOOLLINKOPTSB) -LinkO := $(LinkO) $(TOOLLINKOPTSB) -LinkP := $(LinkP) $(TOOLLINKOPTSB) +LinkG := $(LinkG) $(TOOLLINKOPTSB) +LinkO := $(LinkO) $(TOOLLINKOPTSB) +LinkP := $(LinkP) $(TOOLLINKOPTSB) endif # Create one .o file from a bunch of .o files... @@ -490,8 +490,8 @@ endif # Create dependency file from CPP file, send to stdout. -Depend := $(CXX) -MM -I$(LEVEL)/include $(CPPFLAGS) -DependC := $(CC) -MM -I$(LEVEL)/include $(CPPFLAGS) +Depend := $(CXX) -MM -I$(LEVEL)/include $(CPPFLAGS) +DependC := $(CC) -MM -I$(LEVEL)/include $(CPPFLAGS) # Archive a bunch of .o files into a .a file... AR = $(AR_PATH) cr @@ -501,7 +501,7 @@ # Source includes all of the cpp files, and objects are derived from the # source files... # The local Makefile can list other Source files via ExtraSource = ... -# +# ifndef Source Source := $(notdir $(ExtraSource) $(wildcard $(SourceDir)/*.cpp \ $(SourceDir)/*.cc $(SourceDir)/*.c $(SourceDir)/*.y \ @@ -531,14 +531,14 @@ ifdef DIRS all install clean test bytecode native stripped-bytecode install-bytecode:: - $(VERB) for dir in ${DIRS}; do \ - if [ ! -f $$dir/Makefile ]; \ - then \ - $(MKDIR) $$dir; \ - cp $(SourceDir)/$$dir/Makefile $$dir/Makefile; \ - fi; \ - ($(MAKE) -C $$dir $@ $(MFLAGS)) || exit 1; \ - done + $(VERB) for dir in ${DIRS}; do \ + if [ ! -f $$dir/Makefile ]; \ + then \ + $(MKDIR) $$dir; \ + cp $(SourceDir)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C $$dir $@ $(MFLAGS)) || exit 1; \ + done endif # Handle PARALLEL_DIRS @@ -554,28 +554,28 @@ %/.makeall %/.makeinstall %/.makeclean %/.maketest %/.makebytecode \ %/.makestripped-bytecode %/.makeinstall-bytecode %/.makenative: - $(VERB) if [ ! -f $(@D)/Makefile ]; \ - then \ - $(MKDIR) $(@D); \ - cp $(SourceDir)/$(@D)/Makefile $(@D)/Makefile; \ - fi; \ - $(MAKE) -C $(@D) $(subst $(@D)/.make,,$@) $(MFLAGS) + $(VERB) if [ ! -f $(@D)/Makefile ]; \ + then \ + $(MKDIR) $(@D); \ + cp $(SourceDir)/$(@D)/Makefile $(@D)/Makefile; \ + fi; \ + $(MAKE) -C $(@D) $(subst $(@D)/.make,,$@) $(MFLAGS) endif # Handle directories that may or may not exist ifdef OPTIONAL_DIRS all install clean test bytecode stripped-bytecode install-bytecode:: - $(VERB) for dir in ${OPTIONAL_DIRS}; do \ - if [ -d $(SourceDir)/$$dir ]; \ - then\ - if [ ! -f $$dir/Makefile ]; \ - then \ - $(MKDIR) $$dir; \ - cp $(SourceDir)/$$dir/Makefile $$dir/Makefile; \ - fi; \ - ($(MAKE) -C$$dir $@ $(MFLAGS)) || exit 1; \ - fi \ - done + $(VERB) for dir in ${OPTIONAL_DIRS}; do \ + if [ -d $(SourceDir)/$$dir ]; \ + then\ + if [ ! -f $$dir/Makefile ]; \ + then \ + $(MKDIR) $$dir; \ + cp $(SourceDir)/$$dir/Makefile $$dir/Makefile; \ + fi; \ + ($(MAKE) -C$$dir $@ $(MFLAGS)) || exit 1; \ + fi \ + done endif #--------------------------------------------------------- @@ -585,13 +585,13 @@ install:: install-config-files $(sysconfdir): - $(MKDIR) $(sysconfdir) + $(MKDIR) $(sysconfdir) install-config-files: $(sysconfdir) $(CONFIG_FILES) - $(VERB)$(ECHO) Installing Configuration Files To $(sysconfdir) - $(VERB)for file in $(CONFIG_FILES); do \ - $(INSTALL) $(SourceDir)/$${file} $(sysconfdir) ; \ - done + $(VERB)$(ECHO) Installing Configuration Files To $(sysconfdir) + $(VERB)for file in $(CONFIG_FILES); do \ + $(INSTALL) $(SourceDir)/$${file} $(sysconfdir) ; \ + done endif ########################################################################### @@ -614,7 +614,7 @@ # Install rule for making bytecode library directory if it does not exist. # Trigger this by making libraries that need to be installed here depend on it. $(DESTDIR)$(bytecode_libdir): - $(MKDIR) $@ + $(MKDIR) $@ ifdef LIBRARYNAME @@ -638,7 +638,7 @@ #-------------------------------------------------------------------- # Library Targets -# Modify the top level targets to build the desired libraries. +# Modify the top level targets to build the desired libraries. #-------------------------------------------------------------------- # dynamic target builds a shared object version of the library... @@ -647,8 +647,8 @@ install-bytecode-library:: $(DESTDIR)$(bytecode_libdir)/lib$(LIBRARYNAME).bc $(DESTDIR)$(bytecode_libdir)/lib$(LIBRARYNAME).bc: $(LIBNAME_BC) $(DESTDIR)$(bytecode_libdir) - @${ECHO} ======= Installing $(LIBRARYNAME) bytecode library ======= - $(VERB)cp $< $@ + @${ECHO} ======= Installing $(LIBRARYNAME) bytecode library ======= + $(VERB)cp $< $@ # Does the library want a .o version built? ifndef DONT_BUILD_RELINKED @@ -680,89 +680,89 @@ # Rule for building bytecode libraries. $(LIBNAME_BC): $(ObjectsBC) $(LibSubDirs) $(DESTLIBBYTECODE)/.dir - @${ECHO} Linking $(LIBRARYNAME) bytecode library - $(VERB) $(LinkBCLib) -o $@ $(ObjectsBC) $(LibSubDirs) $(LibLinkOpts) - @${ECHO} ======= Finished building $(LIBRARYNAME) bytecode library ======= + @${ECHO} Linking $(LIBRARYNAME) bytecode library + $(VERB) $(LinkBCLib) -o $@ $(ObjectsBC) $(LibSubDirs) $(LibLinkOpts) + @${ECHO} ======= Finished building $(LIBRARYNAME) bytecode library ======= # # Rules for building dynamically linked libraries. # $(LIBNAME_O): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir - @${ECHO} Linking $(LIBRARYNAME) dynamic release library - $(VERB) $(Link) -o $@ $(ObjectsO) $(LibSubDirs) $(LibLinkOpts) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) - @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic release library ======= + @${ECHO} Linking $(LIBRARYNAME) dynamic release library + $(VERB) $(Link) -o $@ $(ObjectsO) $(LibSubDirs) $(LibLinkOpts) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) + @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic release library ======= $(LIBNAME_P): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir - @${ECHO} Linking $(LIBRARYNAME) dynamic profile library - $(VERB) $(Link) -o $@ $(ObjectsP) $(LibSubDirs) $(LibLinkOpts) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) - @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic profile library ======= + @${ECHO} Linking $(LIBRARYNAME) dynamic profile library + $(VERB) $(Link) -o $@ $(ObjectsP) $(LibSubDirs) $(LibLinkOpts) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) + @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic profile library ======= $(LIBNAME_G): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir - @${ECHO} Linking $(LIBRARYNAME) dynamic debug library - $(VERB) $(Link) -o $@ $(ObjectsG) $(LibSubDirs) $(LibLinkOpts) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) - @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic debug library ======= + @${ECHO} Linking $(LIBRARYNAME) dynamic debug library + $(VERB) $(Link) -o $@ $(ObjectsG) $(LibSubDirs) $(LibLinkOpts) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $@ $(DESTLIBCURRENT) + @${ECHO} ======= Finished building $(LIBRARYNAME) dynamic debug library ======= install-dynamic-library: $(LIBNAME_CUR) - $(MKDIR) $(DESTDIR)$(libdir) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_CUR) $(DESTDIR)$(libdir)/lib$(LIBRARYNAME)$(SHLIBEXT) - $(VERB) $(LIBTOOL) --finish $(DESTDIR)$(libdir) + $(MKDIR) $(DESTDIR)$(libdir) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_CUR) $(DESTDIR)$(libdir)/lib$(LIBRARYNAME)$(SHLIBEXT) + $(VERB) $(LIBTOOL) --finish $(DESTDIR)$(libdir) # # Rules for building static archive libraries. # $(LIBNAME_AO): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir - @${ECHO} Linking $(LIBRARYNAME) archive release library - $(VERB)$(RM) -f $@ - $(VERB) $(Link) -03 -o $@ $(ObjectsO) $(LibSubDirs) -static - @${ECHO} Finished building $(LIBRARYNAME) archive release library ======= + @${ECHO} Linking $(LIBRARYNAME) archive release library + $(VERB)$(RM) -f $@ + $(VERB) $(Link) -03 -o $@ $(ObjectsO) $(LibSubDirs) -static + @${ECHO} Finished building $(LIBRARYNAME) archive release library ======= $(LIBNAME_AP): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir - @${ECHO} Linking $(LIBRARYNAME) archive profile library - @$(RM) -f $@ - $(VERB) $(Link) -03 $(PROFILE) -o $@ $(ObjectsP) $(LibSubDirs) -static - @${ECHO} ======= Finished building $(LIBRARYNAME) archive profile library ======= + @${ECHO} Linking $(LIBRARYNAME) archive profile library + @$(RM) -f $@ + $(VERB) $(Link) -03 $(PROFILE) -o $@ $(ObjectsP) $(LibSubDirs) -static + @${ECHO} ======= Finished building $(LIBRARYNAME) archive profile library ======= $(LIBNAME_AG): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir - @${ECHO} Linking $(LIBRARYNAME) archive debug library - @$(RM) -f $@ - $(VERB) $(Link) -g $(STRIP) -o $@ $(ObjectsG) $(LibSubDirs) -static - @${ECHO} ======= Finished building $(LIBRARYNAME) archive debug library ======= + @${ECHO} Linking $(LIBRARYNAME) archive debug library + @$(RM) -f $@ + $(VERB) $(Link) -g $(STRIP) -o $@ $(ObjectsG) $(LibSubDirs) -static + @${ECHO} ======= Finished building $(LIBRARYNAME) archive debug library ======= install-archive-library: $(LIBNAME_ACUR) - $(MKDIR) $(DESTDIR)$(libdir) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_ACUR) $(DESTDIR)$(libdir)/lib$(LIBRARYNAME).a + $(MKDIR) $(DESTDIR)$(libdir) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_ACUR) $(DESTDIR)$(libdir)/lib$(LIBRARYNAME).a # # Rules for building .o libraries. # -# JTC: -# Note that for this special case, we specify the actual object files -# instead of their libtool counterparts. This is because libtool -# doesn't want to generate a reloadable object file unless it is given -# .o files explicitly. +# JTC: +# Note that for this special case, we specify the actual object files +# instead of their libtool counterparts. This is because libtool +# doesn't want to generate a reloadable object file unless it is given +# .o files explicitly. # -# Note that we're making an assumption here: If we build a .lo file, -# its corresponding .o file will be placed in the same directory. +# Note that we're making an assumption here: If we build a .lo file, +# its corresponding .o file will be placed in the same directory. # -# I think that is safe. +# I think that is safe. # $(LIBNAME_OBJO): $(ObjectsO) $(LibSubDirs) $(DESTLIBRELEASE)/.dir - @${ECHO} "Linking `basename $@`" - $(VERB) $(Relink) -o $@ $(RObjectsO) $(LibSubDirs) + @${ECHO} "Linking `basename $@`" + $(VERB) $(Relink) -o $@ $(RObjectsO) $(LibSubDirs) $(LIBNAME_OBJP): $(ObjectsP) $(LibSubDirs) $(DESTLIBPROFILE)/.dir - @${ECHO} "Linking `basename $@`" - $(VERB) $(Relink) -o $@ $(RObjectsP) $(LibSubDirs) + @${ECHO} "Linking `basename $@`" + $(VERB) $(Relink) -o $@ $(RObjectsP) $(LibSubDirs) $(LIBNAME_OBJG): $(ObjectsG) $(LibSubDirs) $(DESTLIBDEBUG)/.dir - @${ECHO} "Linking `basename $@`" - $(VERB) $(Relink) -o $@ $(RObjectsG) $(LibSubDirs) + @${ECHO} "Linking `basename $@`" + $(VERB) $(Relink) -o $@ $(RObjectsG) $(LibSubDirs) install-single-object-library: $(LIBNAME_OBJCUR) - $(MKDIR) $(DESTDIR)$(libdir) - $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_OBJCUR) $(DESTDIR)$(libdir)/$(LIBRARYNAME).o + $(MKDIR) $(DESTDIR)$(libdir) + $(VERB) $(LIBTOOL) --mode=install $(INSTALL) $(LIBNAME_OBJCUR) $(DESTDIR)$(libdir)/$(LIBRARYNAME).o endif @@ -821,8 +821,8 @@ # # Libtool link options: -# Ensure that all binaries have their symbols exported so that they can -# by dlsym'ed. +# Ensure that all binaries have their symbols exported so that they can +# by dlsym'ed. # LINK_OPTS := -export-dynamic $(TOOLLINKOPTS) @@ -838,27 +838,27 @@ all:: $(TOOLEXENAMES) clean:: - $(VERB) $(RM) -f $(TOOLEXENAMES) + $(VERB) $(RM) -f $(TOOLEXENAMES) $(TOOLEXENAME_G): $(ObjectsG) $(USED_LIB_PATHS_G) $(LLVM_LIB_PATHS_G) $(DESTTOOLDEBUG)/.dir - @${ECHO} Linking $(TOOLNAME) debug executable $(STRIP_WARN_MSG) - $(VERB) $(LinkG) -o $@ $(ObjectsG) $(LIB_OPTS_G) $(LINK_OPTS) $(LIBS) - @${ECHO} ======= Finished building $(TOOLNAME) debug executable $(STRIP_WARN_MSG) ======= + @${ECHO} Linking $(TOOLNAME) debug executable $(STRIP_WARN_MSG) + $(VERB) $(LinkG) -o $@ $(ObjectsG) $(LIB_OPTS_G) $(LINK_OPTS) $(LIBS) + @${ECHO} ======= Finished building $(TOOLNAME) debug executable $(STRIP_WARN_MSG) ======= $(TOOLEXENAME_O): $(ObjectsO) $(USED_LIB_PATHS_O) $(LLVM_LIB_PATHS_O) $(DESTTOOLRELEASE)/.dir - @${ECHO} Linking $(TOOLNAME) release executable - $(VERB) $(LinkO) -o $@ $(ObjectsO) $(LIB_OPTS_O) $(LINK_OPTS) $(LIBS) - @${ECHO} ======= Finished building $(TOOLNAME) release executable ======= + @${ECHO} Linking $(TOOLNAME) release executable + $(VERB) $(LinkO) -o $@ $(ObjectsO) $(LIB_OPTS_O) $(LINK_OPTS) $(LIBS) + @${ECHO} ======= Finished building $(TOOLNAME) release executable ======= $(TOOLEXENAME_P): $(ObjectsP) $(USED_LIB_PATHS_P) $(LLVM_LIB_PATHS_P) $(DESTTOOLPROFILE)/.dir - @${ECHO} Linking $(TOOLNAME) profile executable - $(VERB) $(LinkP) -o $@ $(ObjectsP) $(LIB_OPTS_P) $(LINK_OPTS) $(LIBS) - @${ECHO} ======= Finished building $(TOOLNAME) profile executable ======= + @${ECHO} Linking $(TOOLNAME) profile executable + $(VERB) $(LinkP) -o $@ $(ObjectsP) $(LIB_OPTS_P) $(LINK_OPTS) $(LIBS) + @${ECHO} ======= Finished building $(TOOLNAME) profile executable ======= install:: $(TOOLEXENAMES) - @${ECHO} Installing $(TOOLEXENAMES) to $(DESTDIR)$(bindir) - $(VERB)$(MKDIR) $(DESTDIR)$(bindir) - $(VERB)$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) -c -m 0755 $(TOOLEXENAMES) $(DESTDIR)$(bindir)/$(TOOLNAME) + @${ECHO} Installing $(TOOLEXENAMES) to $(DESTDIR)$(bindir) + $(VERB)$(MKDIR) $(DESTDIR)$(bindir) + $(VERB)$(LIBTOOL) --mode=install $(INSTALL_PROGRAM) -c -m 0755 $(TOOLEXENAMES) $(DESTDIR)$(bindir)/$(TOOLNAME) endif @@ -869,31 +869,31 @@ # Create .lo files in the ObjectFiles directory from the .cpp and .c files... $(PROJ_OBJ_DIR)/Release/%.lo: %.cpp $(PROJ_OBJ_DIR)/Release/.dir - $(CompileO) $< -o $@ + $(CompileO) $< -o $@ $(PROJ_OBJ_DIR)/Release/%.lo: %.c $(PROJ_OBJ_DIR)/Release/.dir - $(CompileCO) $< -o $@ + $(CompileCO) $< -o $@ $(PROJ_OBJ_DIR)/Profile/%.lo: %.cpp $(PROJ_OBJ_DIR)/Profile/.dir - $(CompileP) $< -o $@ + $(CompileP) $< -o $@ $(PROJ_OBJ_DIR)/Profile/%.lo: %.c $(PROJ_OBJ_DIR)/Profile/.dir - $(CompileCP) $< -o $@ + $(CompileCP) $< -o $@ $(PROJ_OBJ_DIR)/Debug/%.lo: %.cpp $(PROJ_OBJ_DIR)/Debug/.dir - $(CompileG) $< -o $@ + $(CompileG) $< -o $@ -$(PROJ_OBJ_DIR)/Debug/%.lo: %.c $(PROJ_OBJ_DIR)/Debug/.dir - $(CompileCG) $< -o $@ +$(PROJ_OBJ_DIR)/Debug/%.lo: %.c $(PROJ_OBJ_DIR)/Debug/.dir + $(CompileCG) $< -o $@ $(PROJ_OBJ_DIR)/BytecodeObj/%.bc: %.cpp $(PROJ_OBJ_DIR)/BytecodeObj/.dir $(LCC_PROGRAMS) - $(LCXX) $(CPPFLAGS) -c $< -o $@ + $(LCXX) $(CPPFLAGS) -c $< -o $@ $(PROJ_OBJ_DIR)/BytecodeObj/%.bc: %.c $(PROJ_OBJ_DIR)/BytecodeObj/.dir $(LCC_PROGRAMS) - $(LCC) $(CPPFLAGS) -c $< -o $@ + $(LCC) $(CPPFLAGS) -c $< -o $@ $(PROJ_OBJ_DIR)/BytecodeObj/%.bc: %.ll $(PROJ_OBJ_DIR)/BytecodeObj/.dir $(LLVMAS) - $(LLVMAS) $< -o $@ + $(LLVMAS) $< -o $@ # @@ -914,40 +914,40 @@ # FIXME. (f.e. char Buffer[10000] ) # %.cpp: %.l - @${ECHO} Flexing $< - $(VERB) $(FLEX) -t $< | \ + @${ECHO} Flexing $< + $(VERB) $(FLEX) -t $< | \ $(SED) '/^find_rule/d' | \ $(SED) 's/void yyunput/inline void yyunput/' | \ $(SED) 's/void \*yy_flex_realloc/inline void *yy_flex_realloc/' | \ $(SED) 's/#define YY_BUF_SIZE 16384/#define YY_BUF_SIZE (16384*64)/' \ > $@.tmp - $(VERB) cmp -s $@ $@.tmp > /dev/null || ${MV} -f $@.tmp $@ - @# remove the output of flex if it didn't get moved over... - @rm -f $@.tmp + $(VERB) cmp -s $@ $@.tmp > /dev/null || ${MV} -f $@.tmp $@ + @# remove the output of flex if it didn't get moved over... + @rm -f $@.tmp # Rule for building the bison parsers... %.c: %.y # Cancel built-in rules for yacc %.h: %.y # Cancel built-in rules for yacc %.cpp %.h : %.y - @${ECHO} "Bisoning `basename $<`" - $(VERB) $(BISON) -v -d -p $( /dev/null || ${MV} -f $*.tab.c $*.cpp - $(VERB) cmp -s $*.tab.h $*.h > /dev/null || ${MV} -f $*.tab.h $*.h - @# If the files were not updated, don't leave them lying around... - @rm -f $*.tab.c $*.tab.h + @${ECHO} "Bisoning `basename $<`" + $(VERB) $(BISON) -v -d -p $( /dev/null || ${MV} -f $*.tab.c $*.cpp + $(VERB) cmp -s $*.tab.h $*.h > /dev/null || ${MV} -f $*.tab.h $*.h + @# If the files were not updated, don't leave them lying around... + @rm -f $*.tab.c $*.tab.h # To create the directories... %/.dir: - $(VERB) ${MKDIR} $* > /dev/null - @$(DATE) > $@ + $(VERB) ${MKDIR} $* > /dev/null + @$(DATE) > $@ # To create postscript files from dot files... ifneq ($(DOT),false) %.ps: %.dot - ${DOT} -Tps < $< > $@ + ${DOT} -Tps < $< > $@ else %.ps: %.dot - ${ECHO} "Cannot build $@: The program dot is not installed" + ${ECHO} "Cannot build $@: The program dot is not installed" endif # @@ -959,19 +959,19 @@ # 'make clean' nukes the tree clean:: - $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/Debug $(PROJ_OBJ_DIR)/Release - $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/Profile $(PROJ_OBJ_DIR)/Depend - $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/BytecodeObj - $(VERB) $(RM) -f core core.[0-9][0-9]* *.o *.d *~ *.flc + $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/Debug $(PROJ_OBJ_DIR)/Release + $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/Profile $(PROJ_OBJ_DIR)/Depend + $(VERB) $(RM) -rf $(PROJ_OBJ_DIR)/BytecodeObj + $(VERB) $(RM) -f core core.[0-9][0-9]* *.o *.d *~ *.flc ifneq ($(strip $(SHLIBEXT)),) # Extra paranoia - make real sure SHLIBEXT is set - $(VERB) $(RM) -f *$(SHLIBEXT) + $(VERB) $(RM) -f *$(SHLIBEXT) endif - $(VERB) $(RM) -f $(LEX_OUTPUT) $(YACC_OUTPUT) + $(VERB) $(RM) -f $(LEX_OUTPUT) $(YACC_OUTPUT) ########################################################################### # C/C++ Dependencies -# Define variables and rules that generate header file dependencies -# from C/C++ source files. +# Define variables and rules that generate header file dependencies +# from C/C++ source files. ########################################################################### ifndef DISABLE_AUTO_DEPENDENCIES @@ -984,30 +984,30 @@ # Create dependencies for the *.cpp files... $(PROJ_OBJ_DIR)/Depend/%.d: %.cpp $(PROJ_OBJ_DIR)/Depend/.dir - $(VERB) $(Depend) $< | $(SED) 's|\.o:|\.lo:|' | $(SED) 's|$*\.lo *|$(PROJ_OBJ_DIR)/Release/& $(PROJ_OBJ_DIR)/Profile/& $(PROJ_OBJ_DIR)/Debug/& $(PROJ_OBJ_DIR)/Depend/$(@F)|g' > $@ + $(VERB) $(Depend) $< | $(SED) 's|\.o:|\.lo:|' | $(SED) 's|$*\.lo *|$(PROJ_OBJ_DIR)/Release/& $(PROJ_OBJ_DIR)/Profile/& $(PROJ_OBJ_DIR)/Debug/& $(PROJ_OBJ_DIR)/Depend/$(@F)|g' > $@ # Create dependencies for the *.c files... $(PROJ_OBJ_DIR)/Depend/%.d: %.c $(PROJ_OBJ_DIR)/Depend/.dir - $(VERB) $(DependC) -o $@ $< | $(SED) 's|\.o:|\.lo:|' | $(SED) 's|$*\.lo *|$(PROJ_OBJ_DIR)/Release/& $(PROJ_OBJ_DIR)/Profile/& $(PROJ_OBJ_DIR)/Debug/& $(PROJ_OBJ_DIR)/Depend/$(@F)|g' > $@ + $(VERB) $(DependC) -o $@ $< | $(SED) 's|\.o:|\.lo:|' | $(SED) 's|$*\.lo *|$(PROJ_OBJ_DIR)/Release/& $(PROJ_OBJ_DIR)/Profile/& $(PROJ_OBJ_DIR)/Debug/& $(PROJ_OBJ_DIR)/Depend/$(@F)|g' > $@ # # Autoconf Dependencies. # ifeq ($(HAS_LLVM),1) $(LLVM_OBJ_ROOT)/config.status:: $(LLVM_SRC_ROOT)/configure - @${ECHO} "****************************************************************" - @${ECHO} " You need to re-run $(LLVM_SRC_ROOT)/configure" - @${ECHO} " in directory $(LLVM_OBJ_ROOT)" - @${ECHO} "****************************************************************" - $(VERB) exit 1 + @${ECHO} "****************************************************************" + @${ECHO} " You need to re-run $(LLVM_SRC_ROOT)/configure" + @${ECHO} " in directory $(LLVM_OBJ_ROOT)" + @${ECHO} "****************************************************************" + $(VERB) exit 1 endif # If the Makefile in the source tree has been updated, copy it over into the # build tree. Makefile :: $(PROJ_SRC_DIR)/Makefile - @${ECHO} "===== Updating Makefile from source dir: `dirname $<` =====" - $(MKDIR) $(@D) - cp -f $< $@ + @${ECHO} "===== Updating Makefile from source dir: `dirname $<` =====" + $(MKDIR) $(@D) + cp -f $< $@ # # Include dependencies generated from C/C++ source files, but not if we @@ -1027,4 +1027,4 @@ # General debugging rule, use 'make dbg-print-XXX' to print the # definition, value and origin of XXX. make-print-%: - $(error PRINT: $(value $*) = "$($*)" (from $(origin $*))) + $(error PRINT: $(value $*) = "$($*)" (from $(origin $*))) From atrick at apple.com Thu Apr 14 13:58:10 2011 From: atrick at apple.com (Andrew Trick) Date: Thu, 14 Apr 2011 18:58:10 -0000 Subject: [llvm-commits] [test-suite] r129529 - /test-suite/trunk/Makefile.programs Message-ID: <20110414185810.25A572A6C12C@llvm.org> Author: atrick Date: Thu Apr 14 13:58:09 2011 New Revision: 129529 URL: http://llvm.org/viewvc/llvm-project?rev=129529&view=rev Log: Proper whitespace removal. Modified: test-suite/trunk/Makefile.programs Modified: test-suite/trunk/Makefile.programs URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.programs?rev=129529&r1=129528&r2=129529&view=diff ============================================================================== --- test-suite/trunk/Makefile.programs (original) +++ test-suite/trunk/Makefile.programs Thu Apr 14 13:58:09 2011 @@ -44,7 +44,7 @@ .PRECIOUS: Output/%.llvm Output/%.native Output/%.simple Output/%.llc Output/%.llc.s .PRECIOUS: Output/%.cbe Output/%.cbe.c Output/%.llvm.bc Output/%.linked.bc -.PRECIOUS: Output/%.linked.optbeta.bc Output/%.llvm.optbeta.bc +.PRECIOUS: Output/%.linked.optbeta.bc Output/%.llvm.optbeta.bc PROGDIR = $(PROJ_SRC_ROOT) @@ -155,7 +155,7 @@ # Targets to build for the default target... # -# We will be working in the Output directory... +# We will be working in the Output directory... PREFIXED_PROGRAMS_TO_TEST := $(addprefix Output/,$(PROGRAMS_TO_TEST)) # Completed bytecode for a program @@ -196,7 +196,7 @@ # Build diffs from the output... .PRECIOUS: Output/%.diff-simple .PRECIOUS: Output/%.diff-lli Output/%.diff-jit Output/%.diff-opt-beta -.PRECIOUS: Output/%.diff-llc Output/%.diff-llc-beta Output/%.diff-cbe +.PRECIOUS: Output/%.diff-llc Output/%.diff-llc-beta Output/%.diff-cbe # Regardless of what other options are specified, build the program's bytecode @@ -256,11 +256,11 @@ #--enable-tail-merge endif ifeq ($(ARCH),Alpha) -LLCBETAOPTION := -sched=list-td +LLCBETAOPTION := -sched=list-td # -enable-alpha-FTOI -enable-alpha-intfpdiv endif ifeq ($(ARCH),IA64) -LLCBETAOPTION := -sched=simple +LLCBETAOPTION := -sched=simple endif ifeq ($(ARCH),x86_64) LLCBETAOPTION := -combiner-alias-analysis @@ -709,13 +709,13 @@ $(BUGPOINT_OPTIONS) $(BUGPOINT_TOOL_OPTIONS) $(BUGPOINT_ARGS) $(PROGRAMS_TO_TEST:%=Output/%.misopt.out): \ -Output/%.misopt.out: Output/%.linked.rbc $(LFINDMISOPT) +Output/%.misopt.out: Output/%.linked.rbc $(LFINDMISOPT) $(LFINDMISOPT) $< Output/$*.misopt "$(RUN_OPTIONS)" \ "$(STDIN_FILENAME)" > Output/$*.misopt.out 2>&1 clean:: - rm -f bugpoint-* - rm -f bugpoint.* + rm -f bugpoint-* + rm -f bugpoint.* rm -rf Output/misopt-* LIBPROFILESO = $(LLVM_OBJ_ROOT)/Debug/lib/libprofile_rt.so @@ -851,7 +851,7 @@ $(PROGRAMS_TO_TEST:%=Output/%.LOC.txt): \ Output/%.LOC.txt: $(SRCDIR)/%.LOC.txt Output/.dir cp $< $@ -else +else # Rules to support USE_REFERENCE_OUTPUT. ifdef USE_REFERENCE_OUTPUT From atrick at apple.com Thu Apr 14 14:04:12 2011 From: atrick at apple.com (Andrew Trick) Date: Thu, 14 Apr 2011 19:04:12 -0000 Subject: [llvm-commits] [test-suite] r129530 - in /test-suite/trunk: Makefile.programs Makefile.rules TEST.nightly.Makefile TEST.simple.Makefile Message-ID: <20110414190412.4AC302A6C12C@llvm.org> Author: atrick Date: Thu Apr 14 14:04:12 2011 New Revision: 129530 URL: http://llvm.org/viewvc/llvm-project?rev=129530&view=rev Log: Add a "make build" target to the test-suite. I use this as follows make -j8 build TEST=simple ... make TEST=simple ... This is the only reasonable way I've come up with for manual benchmarking. I'm checking in since others have asked for the feature. Modified: test-suite/trunk/Makefile.programs test-suite/trunk/Makefile.rules test-suite/trunk/TEST.nightly.Makefile test-suite/trunk/TEST.simple.Makefile Modified: test-suite/trunk/Makefile.programs URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.programs?rev=129530&r1=129529&r2=129530&view=diff ============================================================================== --- test-suite/trunk/Makefile.programs (original) +++ test-suite/trunk/Makefile.programs Thu Apr 14 14:04:12 2011 @@ -890,6 +890,10 @@ # test:: $(PROGRAMS_TO_TEST:%=test.$(TEST).%) +# Support building with the TEST= option without executing tests. +# Allows parallel builds to complete before running serial benchmarks. +build:: $(PROGRAMS_TO_TEST:%=build.$(TEST).%) + # AVAILABLE_TESTS - Compute the set of tests available for user help # TEST_FILES = $(wildcard $(PROGDIR)/TEST.*.Makefile) \ Modified: test-suite/trunk/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/Makefile.rules?rev=129530&r1=129529&r2=129530&view=diff ============================================================================== --- test-suite/trunk/Makefile.rules (original) +++ test-suite/trunk/Makefile.rules Thu Apr 14 14:04:12 2011 @@ -89,6 +89,9 @@ # Default for install is to at least build everything... install :: +# Default rule for build. It ensures everything has a build rule +build:: + # Default rule for test. It ensures everything has a test rule test:: @@ -125,7 +128,7 @@ # which are marked as Phony. # .PHONY: all dynamic bytecodelib install-bytecode-library -.PHONY: clean distclean install test bytecode native prdirs dbg +.PHONY: clean distclean install build test bytecode native prdirs dbg ########################################################################### # Miscellaneous paths and commands: @@ -530,7 +533,7 @@ #--------------------------------------------------------- ifdef DIRS -all install clean test bytecode native stripped-bytecode install-bytecode:: +all install clean build test bytecode native stripped-bytecode install-bytecode:: $(VERB) for dir in ${DIRS}; do \ if [ ! -f $$dir/Makefile ]; \ then \ @@ -545,6 +548,7 @@ ifdef PARALLEL_DIRS all :: $(addsuffix /.makeall , $(PARALLEL_DIRS)) install :: $(addsuffix /.makeinstall , $(PARALLEL_DIRS)) +build :: $(addsuffix /.makebuild , $(PARALLEL_DIRS)) clean :: $(addsuffix /.makeclean , $(PARALLEL_DIRS)) test :: $(addsuffix /.maketest , $(PARALLEL_DIRS)) bytecode :: $(addsuffix /.makebytecode, $(PARALLEL_DIRS)) @@ -552,7 +556,7 @@ stripped-bytecode :: $(addsuffix /.makestripped-bytecode, $(PARALLEL_DIRS)) install-bytecode :: $(addsuffix /.makeinstall-bytecode, $(PARALLEL_DIRS)) -%/.makeall %/.makeinstall %/.makeclean %/.maketest %/.makebytecode \ +%/.makeall %/.makeinstall %/.makeclean %/.makebuild %/.maketest %/.makebytecode \ %/.makestripped-bytecode %/.makeinstall-bytecode %/.makenative: $(VERB) if [ ! -f $(@D)/Makefile ]; \ then \ @@ -564,7 +568,7 @@ # Handle directories that may or may not exist ifdef OPTIONAL_DIRS -all install clean test bytecode stripped-bytecode install-bytecode:: +all install clean build test bytecode stripped-bytecode install-bytecode:: $(VERB) for dir in ${OPTIONAL_DIRS}; do \ if [ -d $(SourceDir)/$$dir ]; \ then\ Modified: test-suite/trunk/TEST.nightly.Makefile URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/TEST.nightly.Makefile?rev=129530&r1=129529&r2=129530&view=diff ============================================================================== --- test-suite/trunk/TEST.nightly.Makefile (original) +++ test-suite/trunk/TEST.nightly.Makefile Thu Apr 14 14:04:12 2011 @@ -149,3 +149,7 @@ $(PROGRAMS_TO_TEST:%=test.$(TEST).%): \ test.$(TEST).%: Output/%.$(TEST).report.txt @-cat $< + +$(PROGRAMS_TO_TEST:%=build.$(TEST).%): \ +build.$(TEST).%: Output/%.llc + @echo "Finished Building: $<" Modified: test-suite/trunk/TEST.simple.Makefile URL: http://llvm.org/viewvc/llvm-project/test-suite/trunk/TEST.simple.Makefile?rev=129530&r1=129529&r2=129530&view=diff ============================================================================== --- test-suite/trunk/TEST.simple.Makefile (original) +++ test-suite/trunk/TEST.simple.Makefile Thu Apr 14 14:04:12 2011 @@ -66,3 +66,7 @@ $(PROGRAMS_TO_TEST:%=test.$(TEST).%): \ test.$(TEST).%: Output/%.$(TEST).report.txt @-cat $< + +$(PROGRAMS_TO_TEST:%=build.$(TEST).%): \ +build.$(TEST).%: Output/%.simple + @echo "Finished Building: $<" From johnny.chen at apple.com Thu Apr 14 14:13:28 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Thu, 14 Apr 2011 19:13:28 -0000 Subject: [llvm-commits] [llvm] r129531 - in /llvm/trunk: lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110414191328.605FE2A6C12C@llvm.org> Author: johnny Date: Thu Apr 14 14:13:28 2011 New Revision: 129531 URL: http://llvm.org/viewvc/llvm-project?rev=129531&view=rev Log: Add sanity checkings for Thumb2 Load/Store Register Exclusive family of operations. Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=129531&r1=129530&r2=129531&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h Thu Apr 14 14:13:28 2011 @@ -1232,29 +1232,66 @@ bool isSW = (Opcode == ARM::t2LDREX || Opcode == ARM::t2STREX); bool isDW = (Opcode == ARM::t2LDREXD || Opcode == ARM::t2STREXD); + unsigned Rt = decodeRd(insn); + unsigned Rt2 = decodeRs(insn); // But note that this is Rd for t2STREX. + unsigned Rd = decodeRm(insn); + unsigned Rn = decodeRn(insn); + + // Some sanity checking first. + if (isStore) { + // if d == n || d == t then UNPREDICTABLE + // if d == n || d == t || d == t2 then UNPREDICTABLE + if (isDW) { + if (Rd == Rn || Rd == Rt || Rd == Rt2) { + DEBUG(errs() << "if d == n || d == t || d == t2 then UNPREDICTABLE\n"); + return false; + } + } else { + if (isSW) { + if (Rt2 == Rn || Rt2 == Rt) { + DEBUG(errs() << "if d == n || d == t then UNPREDICTABLE\n"); + return false; + } + } else { + if (Rd == Rn || Rd == Rt) { + DEBUG(errs() << "if d == n || d == t then UNPREDICTABLE\n"); + return false; + } + } + } + } else { + // Load + // A8.6.71 LDREXD + // if t == t2 then UNPREDICTABLE + if (isDW && Rt == Rt2) { + DEBUG(errs() << "if t == t2 then UNPREDICTABLE\n"); + return false; + } + } + // Add the destination operand for store. if (isStore) { MI.addOperand(MCOperand::CreateReg( getRegisterEnum(B, OpInfo[OpIdx].RegClass, - isSW ? decodeRs(insn) : decodeRm(insn)))); + isSW ? Rt2 : Rd))); ++OpIdx; } // Source operand for store and destination operand for load. MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeRd(insn)))); + Rt))); ++OpIdx; // Thumb2 doubleword complication: with an extra source/destination operand. if (isDW) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass, - decodeRs(insn)))); + Rt2))); ++OpIdx; } // Finally add the pointer operand. MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeRn(insn)))); + Rn))); ++OpIdx; return true; Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt?rev=129531&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt Thu Apr 14 14:13:28 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=1934 Name=t2LDREXD Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 0| 1: 0: 0: 0| 1: 1: 0: 1| 0: 0: 1: 0| 1: 0: 0: 0| 1: 0: 0: 0| 0: 1: 1: 1| 1: 1: 1: 1| +# ------------------------------------------------------------------------------------------------- +# +# if t == t2 then UNPREDICTABLE +0xd2 0xe8 0x7f 0x88 Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt?rev=129531&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt Thu Apr 14 14:13:28 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=2127 Name=t2STREXB Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 0| 1: 0: 0: 0| 1: 1: 0: 0| 0: 0: 1: 0| 1: 0: 0: 0| 1: 1: 1: 1| 0: 1: 0: 0| 0: 0: 1: 0| +# ------------------------------------------------------------------------------------------------- +# +# if d == n || d == t then UNPREDICTABLE +0xc2 0xe8 0x42 0x8f Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt?rev=129531&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt Thu Apr 14 14:13:28 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=2128 Name=t2STREXD Format=ARM_FORMAT_THUMBFRM(25) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 0| 1: 0: 0: 0| 1: 1: 0: 0| 0: 0: 1: 0| 0: 1: 1: 1| 1: 0: 0: 0| 0: 1: 1: 1| 1: 0: 0: 0| +# ------------------------------------------------------------------------------------------------- +# +# if d == n || d == t || d == t2 then UNPREDICTABLE +mc-input.txt:1:1: warning: invalid instruction encoding Modified: llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt?rev=129531&r1=129530&r2=129531&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Thu Apr 14 14:13:28 2011 @@ -158,6 +158,9 @@ # CHECK: ldrex r8, [r2] 0x52 0xe8 0x00 0x8f +# CHECK: ldrexd r8, r9, [r2] +0xd2 0xe8 0x7f 0x89 + # CHECK: strexd r1, r7, r8, [r2] 0xc2 0xe8 0x71 0x78 From wangmp at apple.com Thu Apr 14 14:20:42 2011 From: wangmp at apple.com (Mon P Wang) Date: Thu, 14 Apr 2011 19:20:42 -0000 Subject: [llvm-commits] [llvm] r129532 - /llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Message-ID: <20110414192042.4D1D62A6C12C@llvm.org> Author: wangmp Date: Thu Apr 14 14:20:42 2011 New Revision: 129532 URL: http://llvm.org/viewvc/llvm-project?rev=129532&view=rev Log: Cleanup r129509 based on comments by Chris Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=129532&r1=129531&r2=129532&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Thu Apr 14 14:20:42 2011 @@ -682,24 +682,23 @@ static Value *CreateShuffleVectorCast(Value *FromVal, const Type *ToType, IRBuilder<> &Builder) { const Type *FromType = FromVal->getType(); - const VectorType *FromVTy = dyn_cast(FromType); - const VectorType *ToVTy = dyn_cast(ToType); - assert(FromVTy && ToVTy && - (ToVTy->getElementType() == FromVTy->getElementType()) && + const VectorType *FromVTy = cast(FromType); + const VectorType *ToVTy = cast(ToType); + assert((ToVTy->getElementType() == FromVTy->getElementType()) && "Vectors must have the same element type"); - LLVMContext &Context = FromVal->getContext(); Value *UnV = UndefValue::get(FromType); unsigned numEltsFrom = FromVTy->getNumElements(); unsigned numEltsTo = ToVTy->getNumElements(); SmallVector Args; + const Type* Int32Ty = Builder.getInt32Ty(); unsigned minNumElts = std::min(numEltsFrom, numEltsTo); unsigned i; for (i=0; i != minNumElts; ++i) - Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); + Args.push_back(ConstantInt::get(Int32Ty, i)); if (i < numEltsTo) { - Constant* UnC = UndefValue::get(Type::getInt32Ty(Context)); + Constant* UnC = UndefValue::get(Int32Ty); for (; i != numEltsTo; ++i) Args.push_back(UnC); } From wangmp at apple.com Thu Apr 14 14:25:46 2011 From: wangmp at apple.com (Mon Ping Wang) Date: Thu, 14 Apr 2011 12:25:46 -0700 Subject: [llvm-commits] [llvm] r129509 - /llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp In-Reply-To: <61AF85B6-48F9-48D0-9B0F-6023B5BDC2B6@apple.com> References: <20110414080401.7E4302A6C12D@llvm.org> <61AF85B6-48F9-48D0-9B0F-6023B5BDC2B6@apple.com> Message-ID: Thanks for the comments. Fixed in r129532. -- Mon Ping On Apr 14, 2011, at 8:49 AM, Chris Lattner wrote: > On Apr 14, 2011, at 1:04 AM, Mon P Wang wrote: >> Author: wangmp >> Date: Thu Apr 14 03:04:01 2011 >> New Revision: 129509 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=129509&view=rev >> Log: >> Cleanup r129472 by using a utility routine as suggested by Eli. > > Thanks Mon Ping, some more minor nits :) > >> +++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Thu Apr 14 03:04:01 2011 >> @@ -676,6 +676,37 @@ >> llvm_unreachable("Invalid type for a partial vector access of an alloca!"); >> } >> >> +/// CreateShuffleVectorCast - Creates a shuffle vector to convert one vector >> +/// to another vector of the same element type which has the same allocation >> +/// size but different primitive sizes (e.g. <3 x i32> and <4 x i32>). >> +static Value *CreateShuffleVectorCast(Value *FromVal, const Type *ToType, >> + IRBuilder<> &Builder) { >> + const Type *FromType = FromVal->getType(); >> + const VectorType *FromVTy = dyn_cast(FromType); >> + const VectorType *ToVTy = dyn_cast(ToType); >> + assert(FromVTy && ToVTy && >> + (ToVTy->getElementType() == FromVTy->getElementType()) && >> + "Vectors must have the same element type"); > > Instead of using dyn_cast + assert(!null), please just use cast<> > >> + LLVMContext &Context = FromVal->getContext(); >> + Value *UnV = UndefValue::get(FromType); >> + unsigned numEltsFrom = FromVTy->getNumElements(); >> + unsigned numEltsTo = ToVTy->getNumElements(); >> + >> + SmallVector Args; >> + unsigned minNumElts = std::min(numEltsFrom, numEltsTo); >> + unsigned i; >> + for (i=0; i != minNumElts; ++i) >> + Args.push_back(ConstantInt::get(Type::getInt32Ty(Context), i)); > > You can use Builder.getInt32Ty() to simplify the code, or Builder.getInt32(i) to simplify it even more. > > -Chris From resistor at mac.com Thu Apr 14 16:35:50 2011 From: resistor at mac.com (Owen Anderson) Date: Thu, 14 Apr 2011 21:35:50 -0000 Subject: [llvm-commits] [llvm] r129538 - in /llvm/trunk: lib/Transforms/Scalar/JumpThreading.cpp test/Transforms/JumpThreading/2011-04-14-InfLoop.ll Message-ID: <20110414213550.DCD292A6C12C@llvm.org> Author: resistor Date: Thu Apr 14 16:35:50 2011 New Revision: 129538 URL: http://llvm.org/viewvc/llvm-project?rev=129538&view=rev Log: Fix an infinite alternation in JumpThreading where two transforms would repeatedly undo each other. The solution is to perform more aggressive constant folding to make one of the edges just folded away rather than trying to thread it. Fixes . Discovered with CSmith. Added: llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=129538&r1=129537&r2=129538&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original) +++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Thu Apr 14 16:35:50 2011 @@ -16,6 +16,7 @@ #include "llvm/IntrinsicInst.h" #include "llvm/LLVMContext.h" #include "llvm/Pass.h" +#include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/LazyValueInfo.h" #include "llvm/Analysis/Loads.h" @@ -170,9 +171,9 @@ Changed = true; continue; } - + BranchInst *BI = dyn_cast(BB->getTerminator()); - + // Can't thread an unconditional jump, but if the block is "almost // empty", we can replace uses of it with uses of the successor and make // this dead. @@ -608,7 +609,7 @@ static bool hasAddressTakenAndUsed(BasicBlock *BB) { if (!BB->hasAddressTaken()) return false; - + // If the block has its address taken, it may be a tree of dead constants // hanging off of it. These shouldn't keep the block alive. BlockAddress *BA = BlockAddress::get(BB); @@ -668,6 +669,17 @@ return false; // Must be an invoke. } + // Run constant folding to see if we can reduce the condition to a simple + // constant. + if (Instruction *I = dyn_cast(Condition)) { + Value *SimpleVal = ConstantFoldInstruction(I, TD); + if (SimpleVal) { + I->replaceAllUsesWith(SimpleVal); + I->eraseFromParent(); + Condition = SimpleVal; + } + } + // If the terminator is branching on an undef, we can pick any of the // successors to branch to. Let GetBestDestForJumpOnUndef decide. if (isa(Condition)) { Added: llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll?rev=129538&view=auto ============================================================================== --- llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll (added) +++ llvm/trunk/test/Transforms/JumpThreading/2011-04-14-InfLoop.ll Thu Apr 14 16:35:50 2011 @@ -0,0 +1,31 @@ +; RUN: opt -jump-threading < %s +; + +%0 = type <{ i64, i16, i64, i8, i8 }> + + at g_338 = external global %0, align 8 + +define void @func_1() nounwind ssp { +entry: + ret void + +for.cond1177: + %inc1187 = add nsw i32 0, 1 + %cmp1179 = icmp slt i32 %inc1187, 5 + br i1 %cmp1179, label %for.cond1177, label %land.rhs1320 + +land.rhs1320: + %tmp1324 = volatile load i64* getelementptr inbounds (%0* @g_338, i64 0, i32 2), align 1, !tbaa !0 + br label %if.end.i + +if.end.i: + %tobool.pr.i = phi i1 [ false, %if.end.i ], [ false, %land.rhs1320 ] + br i1 %tobool.pr.i, label %return, label %if.end.i + +return: + ret void +} + +!0 = metadata !{metadata !"long long", metadata !1} +!1 = metadata !{metadata !"omnipotent char", metadata !2} +!2 = metadata !{metadata !"Simple C/C++ TBAA", null} From lenny at Colorado.EDU Thu Apr 14 12:49:06 2011 From: lenny at Colorado.EDU (Lenny Maiorani) Date: Thu, 14 Apr 2011 11:49:06 -0600 Subject: [llvm-commits] [PATCH] review request: implementation of bounded StringRef::compare Message-ID: <4DA73392.5030809@colorado.edu> Implements StringRef::compare with bounds. It is behaves similarly to strncmp(). Unit tests also included. Please review. -Lenny -------------- next part -------------- A non-text attachment was scrubbed... Name: llvm-bounded-stringref-compare.diff Type: text/x-patch Size: 2530 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110414/d1ed3ecd/attachment.bin From eli.friedman at gmail.com Thu Apr 14 17:41:27 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Thu, 14 Apr 2011 22:41:27 -0000 Subject: [llvm-commits] [llvm] r129545 - in /llvm/trunk: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp test/Transforms/InstCombine/or.ll Message-ID: <20110414224127.790B82A6C12C@llvm.org> Author: efriedma Date: Thu Apr 14 17:41:27 2011 New Revision: 129545 URL: http://llvm.org/viewvc/llvm-project?rev=129545&view=rev Log: Add an instcombine for constructs like a | -(b != c); a select is more canonical, and generally leads to better code. Found while looking at an article about saturating arithmetic. Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp llvm/trunk/test/Transforms/InstCombine/or.ll Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp?rev=129545&r1=129544&r2=129545&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (original) +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp Thu Apr 14 17:41:27 2011 @@ -2003,7 +2003,14 @@ } } } - + + // or(sext(A), B) -> A ? -1 : B where A is an i1 + // or(A, sext(B)) -> B ? -1 : A where B is an i1 + if (match(Op0, m_SExt(m_Value(A))) && A->getType()->isIntegerTy(1)) + return SelectInst::Create(A, ConstantInt::getSigned(I.getType(), -1), Op1); + if (match(Op1, m_SExt(m_Value(A))) && A->getType()->isIntegerTy(1)) + return SelectInst::Create(A, ConstantInt::getSigned(I.getType(), -1), Op0); + // Note: If we've gotten to the point of visiting the outer OR, then the // inner one couldn't be simplified. If it was a constant, then it won't // be simplified by a later pass either, so we try swapping the inner/outer Modified: llvm/trunk/test/Transforms/InstCombine/or.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/or.ll?rev=129545&r1=129544&r2=129545&view=diff ============================================================================== --- llvm/trunk/test/Transforms/InstCombine/or.ll (original) +++ llvm/trunk/test/Transforms/InstCombine/or.ll Thu Apr 14 17:41:27 2011 @@ -390,3 +390,22 @@ ; CHECK-NEXT: ret i1 } +define i32 @test37(i32* %xp, i32 %y) { +; CHECK: @test37 +; CHECK: select i1 %tobool, i32 -1, i32 %x + %tobool = icmp ne i32 %y, 0 + %sext = sext i1 %tobool to i32 + %x = load i32* %xp + %or = or i32 %sext, %x + ret i32 %or +} + +define i32 @test38(i32* %xp, i32 %y) { +; CHECK: @test38 +; CHECK: select i1 %tobool, i32 -1, i32 %x + %tobool = icmp ne i32 %y, 0 + %sext = sext i1 %tobool to i32 + %x = load i32* %xp + %or = or i32 %x, %sext + ret i32 %or +} From fvbommel at gmail.com Thu Apr 14 18:11:39 2011 From: fvbommel at gmail.com (Frits van Bommel) Date: Fri, 15 Apr 2011 01:11:39 +0200 Subject: [llvm-commits] [llvm] r129545 - in /llvm/trunk: lib/Transforms/InstCombine/InstCombineAndOrXor.cpp test/Transforms/InstCombine/or.ll In-Reply-To: <20110414224127.790B82A6C12C@llvm.org> References: <20110414224127.790B82A6C12C@llvm.org> Message-ID: On Fri, Apr 15, 2011 at 12:41 AM, Eli Friedman wrote: > Add an instcombine for constructs like a | -(b != c); a select is more > canonical, and generally leads to better code. ?Found while looking at > an article about saturating arithmetic. You can also do '-cond & x' --> 'cond ? x : 0'. From evan.cheng at apple.com Thu Apr 14 18:27:44 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Thu, 14 Apr 2011 23:27:44 -0000 Subject: [llvm-commits] [llvm] r129548 - in /llvm/trunk: lib/Target/ARM/ARMInstrThumb.td test/CodeGen/Thumb/rev.ll Message-ID: <20110414232744.2FABA2A6C12C@llvm.org> Author: evancheng Date: Thu Apr 14 18:27:44 2011 New Revision: 129548 URL: http://llvm.org/viewvc/llvm-project?rev=129548&view=rev Log: Follow up on r127913. Fix Thumb revsh isel. rdar://9286766 Added: llvm/trunk/test/CodeGen/Thumb/rev.ll Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=129548&r1=129547&r2=129548&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Thu Apr 14 18:27:44 2011 @@ -1184,10 +1184,18 @@ "revsh", "\t$Rd, $Rm", [(set tGPR:$Rd, (sext_inreg - (or (srl (and tGPR:$Rm, 0xFF00), (i32 8)), + (or (srl tGPR:$Rm, (i32 8)), (shl tGPR:$Rm, (i32 8))), i16))]>, Requires<[IsThumb, IsThumb1Only, HasV6]>; +def : T1Pat<(sext_inreg (or (srl (and tGPR:$Rm, 0xFF00), (i32 8)), + (shl tGPR:$Rm, (i32 8))), i16), + (tREVSH tGPR:$Rm)>, + Requires<[IsThumb, IsThumb1Only, HasV6]>; + +def : T1Pat<(sra (bswap tGPR:$Rm), (i32 16)), (tREVSH tGPR:$Rm)>, + Requires<[IsThumb, IsThumb1Only, HasV6]>; + // Rotate right register def tROR : // A8.6.139 T1sItDPEncode<0b0111, (outs tGPR:$Rdn), (ins tGPR:$Rn, tGPR:$Rm), Added: llvm/trunk/test/CodeGen/Thumb/rev.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb/rev.ll?rev=129548&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/Thumb/rev.ll (added) +++ llvm/trunk/test/CodeGen/Thumb/rev.ll Thu Apr 14 18:27:44 2011 @@ -0,0 +1,56 @@ +; RUN: llc < %s -march=thumb -mattr=+v6 | FileCheck %s + +define i32 @test1(i32 %X) nounwind { +; CHECK: test1 +; CHECK: rev16 r0, r0 + %tmp1 = lshr i32 %X, 8 + %X15 = bitcast i32 %X to i32 + %tmp4 = shl i32 %X15, 8 + %tmp2 = and i32 %tmp1, 16711680 + %tmp5 = and i32 %tmp4, -16777216 + %tmp9 = and i32 %tmp1, 255 + %tmp13 = and i32 %tmp4, 65280 + %tmp6 = or i32 %tmp5, %tmp2 + %tmp10 = or i32 %tmp6, %tmp13 + %tmp14 = or i32 %tmp10, %tmp9 + ret i32 %tmp14 +} + +define i32 @test2(i32 %X) nounwind { +; CHECK: test2 +; CHECK: revsh r0, r0 + %tmp1 = lshr i32 %X, 8 + %tmp1.upgrd.1 = trunc i32 %tmp1 to i16 + %tmp3 = trunc i32 %X to i16 + %tmp2 = and i16 %tmp1.upgrd.1, 255 + %tmp4 = shl i16 %tmp3, 8 + %tmp5 = or i16 %tmp2, %tmp4 + %tmp5.upgrd.2 = sext i16 %tmp5 to i32 + ret i32 %tmp5.upgrd.2 +} + +; rdar://9147637 +define i32 @test3(i16 zeroext %a) nounwind { +entry: +; CHECK: test3: +; CHECK: revsh r0, r0 + %0 = tail call i16 @llvm.bswap.i16(i16 %a) + %1 = sext i16 %0 to i32 + ret i32 %1 +} + +declare i16 @llvm.bswap.i16(i16) nounwind readnone + +define i32 @test4(i16 zeroext %a) nounwind { +entry: +; CHECK: test4: +; CHECK: revsh r0, r0 + %conv = zext i16 %a to i32 + %shr9 = lshr i16 %a, 8 + %conv2 = zext i16 %shr9 to i32 + %shl = shl nuw nsw i32 %conv, 8 + %or = or i32 %conv2, %shl + %sext = shl i32 %or, 16 + %conv8 = ashr exact i32 %sext, 16 + ret i32 %conv8 +} From johnny.chen at apple.com Thu Apr 14 19:10:45 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 15 Apr 2011 00:10:45 -0000 Subject: [llvm-commits] [llvm] r129550 - in /llvm/trunk: lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt test/MC/Disassembler/ARM/neon-tests.txt Message-ID: <20110415001045.966BC2A6C12C@llvm.org> Author: johnny Date: Thu Apr 14 19:10:45 2011 New Revision: 129550 URL: http://llvm.org/viewvc/llvm-project?rev=129550&view=rev Log: The ARM disassembler did not handle the alignment correctly for VLD*DUP* instructions (single element or n-element structure to all lanes). Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=129550&r1=129549&r2=129550&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp Thu Apr 14 19:10:45 2011 @@ -2657,6 +2657,33 @@ // == 32 && Inst{6} == 1 --> DblSpaced = true if (Name.endswith("32") || Name.endswith("32_UPD")) DblSpaced = slice(insn, 6, 6) == 1; + } else if (Name.find("DUP") != std::string::npos) { + // Single element (or structure) to all lanes. + // Inst{9-8} encodes the number of element(s) in the structure, with: + // 0b00 (VLD1DUP) (for this, a bit makes sense only for data size 16 and 32. + // 0b01 (VLD2DUP) + // 0b10 (VLD3DUP) (for this, a bit must be encoded as 0) + // 0b11 (VLD4DUP) + // + // Inst{7-6} encodes the data size, with: + // 0b00 => 8, 0b01 => 16, 0b10 => 32 + // + // Inst{4} (the a bit) encodes the align action (0: standard alignment) + unsigned elem = slice(insn, 9, 8) + 1; + unsigned a = slice(insn, 4, 4); + if (elem != 3) { + // 0b11 is not a valid encoding for Inst{7-6}. + if (slice(insn, 7, 6) == 3) + return false; + unsigned data_size = 8 << slice(insn, 7, 6); + // For VLD1DUP, a bit makes sense only for data size of 16 and 32. + if (a && data_size == 8) + return false; + + // Now we can calculate the alignment! + if (a) + alignment = elem * data_size; + } } else { // Multiple n-element structures with type encoded as Inst{11-8}. // See, for example, A8.6.316 VLD4 (multiple 4-element structures). Added: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt?rev=129550&view=auto ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt (added) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt Thu Apr 14 19:10:45 2011 @@ -0,0 +1,10 @@ +# RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} + +# Opcode=737 Name=VLD1DUPq8_UPD Format=ARM_FORMAT_NLdSt(30) +# 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +# ------------------------------------------------------------------------------------------------- +# | 1: 1: 1: 1| 0: 1: 0: 0| 1: 0: 1: 0| 0: 0: 0: 0| 0: 0: 1: 1| 1: 1: 0: 0| 0: 0: 1: 1| 1: 1: 0: 1| +# ------------------------------------------------------------------------------------------------- +# +# 'a' == 1 and data_size == 8 is invalid +0x3d 0x3c 0xa0 0xf4 Modified: llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt?rev=129550&r1=129549&r2=129550&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt Thu Apr 14 19:10:45 2011 @@ -21,6 +21,12 @@ # CHECK: vld4.8 {d4, d6, d8, d10}, [r2] 0x0f 0x41 0x22 0xf4 +# CHECK: vld1.32 {d3[], d4[]}, [r0, :32]! +0xbd 0x3c 0xa0 0xf4 + +# CHECK: vld4.16 {d3[], d4[], d5[], d6[]}, [r0, :64]! +0x7d 0x3f 0xa0 0xf4 + # CHECK: vmov d0, d15 0x1f 0x01 0x2f 0xf2 From ahatanak at gmail.com Thu Apr 14 19:35:15 2011 From: ahatanak at gmail.com (Akira Hatanaka) Date: Thu, 14 Apr 2011 17:35:15 -0700 Subject: [llvm-commits] MIPS patch In-Reply-To: References: Message-ID: Made minor changes per discussion with Bruno. -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110414/b21c6a99/attachment.html -------------- next part -------------- A non-text attachment was scrubbed... Name: buildpairextractf64_2.patch Type: text/x-patch Size: 12265 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110414/b21c6a99/attachment.bin From bigcheesegs at gmail.com Thu Apr 14 19:32:42 2011 From: bigcheesegs at gmail.com (Michael J. Spencer) Date: Fri, 15 Apr 2011 00:32:42 -0000 Subject: [llvm-commits] [llvm] r129551 - in /llvm/trunk: include/llvm/IntrinsicsX86.td lib/Target/X86/X86.td lib/Target/X86/X86Instr3DNow.td test/CodeGen/X86/3dnow-intrinsics.ll Message-ID: <20110415003242.323532A6C12C@llvm.org> Author: mspencer Date: Thu Apr 14 19:32:41 2011 New Revision: 129551 URL: http://llvm.org/viewvc/llvm-project?rev=129551&view=rev Log: Add 3DNow! intrinsics. Added: llvm/trunk/test/CodeGen/X86/3dnow-intrinsics.ll Modified: llvm/trunk/include/llvm/IntrinsicsX86.td llvm/trunk/lib/Target/X86/X86.td llvm/trunk/lib/Target/X86/X86Instr3DNow.td Modified: llvm/trunk/include/llvm/IntrinsicsX86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IntrinsicsX86.td?rev=129551&r1=129550&r2=129551&view=diff ============================================================================== --- llvm/trunk/include/llvm/IntrinsicsX86.td (original) +++ llvm/trunk/include/llvm/IntrinsicsX86.td Thu Apr 14 19:32:41 2011 @@ -18,6 +18,83 @@ } //===----------------------------------------------------------------------===// +// 3DNow! + +let TargetPrefix = "x86" in { + def int_x86_3dnow_pavgusb : GCCBuiltin<"__builtin_ia32_pavgusb">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pf2id : GCCBuiltin<"__builtin_ia32_pf2id">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfacc : GCCBuiltin<"__builtin_ia32_pfacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfadd : GCCBuiltin<"__builtin_ia32_pfadd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpeq : GCCBuiltin<"__builtin_ia32_pfcmpeq">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpge : GCCBuiltin<"__builtin_ia32_pfcmpge">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfcmpgt : GCCBuiltin<"__builtin_ia32_pfcmpgt">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmax : GCCBuiltin<"__builtin_ia32_pfmax">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmin : GCCBuiltin<"__builtin_ia32_pfmin">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfmul : GCCBuiltin<"__builtin_ia32_pfmul">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrcp : GCCBuiltin<"__builtin_ia32_pfrcp">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfrcpit1 : GCCBuiltin<"__builtin_ia32_pfrcpit1">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrcpit2 : GCCBuiltin<"__builtin_ia32_pfrcpit2">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfrsqrt : GCCBuiltin<"__builtin_ia32_pfrsqrt">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pfrsqit1 : GCCBuiltin<"__builtin_ia32_pfrsqit1">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfsub : GCCBuiltin<"__builtin_ia32_pfsub">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pfsubr : GCCBuiltin<"__builtin_ia32_pfsubr">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnow_pi2fd : GCCBuiltin<"__builtin_ia32_pi2fd">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnow_pmulhrw : GCCBuiltin<"__builtin_ia32_pmulhrw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// 3DNow! extensions + +let TargetPrefix = "x86" in { + def int_x86_3dnowa_pf2iw : GCCBuiltin<"__builtin_ia32_pf2iw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnowa_pfnacc : GCCBuiltin<"__builtin_ia32_pfnacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnowa_pfpnacc : GCCBuiltin<"__builtin_ia32_pfpnacc">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty, llvm_x86mmx_ty], + [IntrNoMem]>; + def int_x86_3dnowa_pi2fw : GCCBuiltin<"__builtin_ia32_pi2fw">, + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; + def int_x86_3dnowa_pswapd : + Intrinsic<[llvm_x86mmx_ty], [llvm_x86mmx_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// // SSE1 // Arithmetic ops Modified: llvm/trunk/lib/Target/X86/X86.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86.td?rev=129551&r1=129550&r2=129551&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86.td (original) +++ llvm/trunk/lib/Target/X86/X86.td Thu Apr 14 19:32:41 2011 @@ -50,7 +50,8 @@ "Enable SSE 4.2 instructions", [FeatureSSE41, FeaturePOPCNT]>; def Feature3DNow : SubtargetFeature<"3dnow", "X863DNowLevel", "ThreeDNow", - "Enable 3DNow! instructions">; + "Enable 3DNow! instructions", + [FeatureMMX]>; def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", "Enable 3DNow! Athlon instructions", [Feature3DNow]>; @@ -125,10 +126,10 @@ FeatureAES, FeatureCLMUL]>; def : Proc<"k6", [FeatureMMX]>; -def : Proc<"k6-2", [FeatureMMX, Feature3DNow]>; -def : Proc<"k6-3", [FeatureMMX, Feature3DNow]>; -def : Proc<"athlon", [FeatureMMX, Feature3DNowA, FeatureSlowBTMem]>; -def : Proc<"athlon-tbird", [FeatureMMX, Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"k6-2", [Feature3DNow]>; +def : Proc<"k6-3", [Feature3DNow]>; +def : Proc<"athlon", [Feature3DNowA, FeatureSlowBTMem]>; +def : Proc<"athlon-tbird", [Feature3DNowA, FeatureSlowBTMem]>; def : Proc<"athlon-4", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; def : Proc<"athlon-xp", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; def : Proc<"athlon-mp", [FeatureSSE1, Feature3DNowA, FeatureSlowBTMem]>; @@ -156,8 +157,8 @@ Feature3DNowA]>; def : Proc<"winchip-c6", [FeatureMMX]>; -def : Proc<"winchip2", [FeatureMMX, Feature3DNow]>; -def : Proc<"c3", [FeatureMMX, Feature3DNow]>; +def : Proc<"winchip2", [Feature3DNow]>; +def : Proc<"c3", [Feature3DNow]>; def : Proc<"c3-2", [FeatureSSE1]>; //===----------------------------------------------------------------------===// Modified: llvm/trunk/lib/Target/X86/X86Instr3DNow.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86Instr3DNow.td?rev=129551&r1=129550&r2=129551&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86Instr3DNow.td (original) +++ llvm/trunk/lib/Target/X86/X86Instr3DNow.td Thu Apr 14 19:32:41 2011 @@ -12,66 +12,91 @@ // //===----------------------------------------------------------------------===// -// FIXME: We don't support any intrinsics for these instructions yet. +class I3DNow o, Format F, dag outs, dag ins, string asm, list pat> + : I, TB, Requires<[Has3DNow]> { +} -class I3DNow o, Format F, dag outs, dag ins, string asm, - list pattern> - : I, TB, Requires<[Has3DNow]> { +class I3DNow_binop o, Format F, dag ins, string Mnemonic, list pat> + : I3DNow, + Has3DNow0F0FOpcode { + // FIXME: The disassembler doesn't support Has3DNow0F0FOpcode yet. + let isAsmParserOnly = 1; + let Constraints = "$src1 = $dst"; } -class I3DNow_binop o, Format F, dag ins, string Mnemonic> - : I, - TB, Requires<[Has3DNow]>, Has3DNow0F0FOpcode { +class I3DNow_conv o, Format F, dag ins, string Mnemonic, list pat> + : I3DNow, + Has3DNow0F0FOpcode { // FIXME: The disassembler doesn't support Has3DNow0F0FOpcode yet. let isAsmParserOnly = 1; } +multiclass I3DNow_binop_rm opc, string Mn> { + def rr : I3DNow_binop; + def rm : I3DNow_binop; +} + +multiclass I3DNow_binop_rm_int opc, string Mn, string Ver = ""> { + def rr : I3DNow_binop( + !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, VR64:$src2))]>; + def rm : I3DNow_binop( + !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src1, + (bitconvert (load_mmx addr:$src2))))]>; +} + +multiclass I3DNow_conv_rm opc, string Mn> { + def rr : I3DNow_conv; + def rm : I3DNow_conv; +} + +multiclass I3DNow_conv_rm_int opc, string Mn, string Ver = ""> { + def rr : I3DNow_conv( + !strconcat("int_x86_3dnow", Ver, "_", Mn)) VR64:$src))]>; + def rm : I3DNow_conv( + !strconcat("int_x86_3dnow", Ver, "_", Mn)) + (bitconvert (load_mmx addr:$src))))]>; +} -let Constraints = "$src1 = $dst" in { - // MMXI_binop_rm_int - Simple MMX binary operator based on intrinsic. - // When this is cleaned up, remove the FIXME from X86RecognizableInstr.cpp. - multiclass I3DNow_binop_rm opc, string Mn> { - def rr : I3DNow_binop; - def rm : I3DNow_binop; - } -} - -defm PAVGUSB : I3DNow_binop_rm<0xBF, "pavgusb">; -defm PF2ID : I3DNow_binop_rm<0x1D, "pf2id">; -defm PFACC : I3DNow_binop_rm<0xAE, "pfacc">; -defm PFADD : I3DNow_binop_rm<0x9E, "pfadd">; -defm PFCMPEQ : I3DNow_binop_rm<0xB0, "pfcmpeq">; -defm PFCMPGE : I3DNow_binop_rm<0x90, "pfcmpge">; -defm PFCMPGT : I3DNow_binop_rm<0xA0, "pfcmpgt">; -defm PFMAX : I3DNow_binop_rm<0xA4, "pfmax">; -defm PFMIN : I3DNow_binop_rm<0x94, "pfmin">; -defm PFMUL : I3DNow_binop_rm<0xB4, "pfmul">; -defm PFRCP : I3DNow_binop_rm<0x96, "pfrcp">; -defm PFRCPIT1 : I3DNow_binop_rm<0xA6, "pfrcpit1">; -defm PFRCPIT2 : I3DNow_binop_rm<0xB6, "pfrcpit2">; -defm PFRSQIT1 : I3DNow_binop_rm<0xA7, "pfrsqit1">; -defm PFRSQRT : I3DNow_binop_rm<0x97, "pfrsqrt">; -defm PFSUB : I3DNow_binop_rm<0x9A, "pfsub">; -defm PFSUBR : I3DNow_binop_rm<0xAA, "pfsubr">; -defm PI2FD : I3DNow_binop_rm<0x0D, "pi2fd">; -defm PMULHRW : I3DNow_binop_rm<0xB7, "pmulhrw">; +defm PAVGUSB : I3DNow_binop_rm_int<0xBF, "pavgusb">; +defm PF2ID : I3DNow_conv_rm_int<0x1D, "pf2id">; +defm PFACC : I3DNow_binop_rm_int<0xAE, "pfacc">; +defm PFADD : I3DNow_binop_rm_int<0x9E, "pfadd">; +defm PFCMPEQ : I3DNow_binop_rm_int<0xB0, "pfcmpeq">; +defm PFCMPGE : I3DNow_binop_rm_int<0x90, "pfcmpge">; +defm PFCMPGT : I3DNow_binop_rm_int<0xA0, "pfcmpgt">; +defm PFMAX : I3DNow_binop_rm_int<0xA4, "pfmax">; +defm PFMIN : I3DNow_binop_rm_int<0x94, "pfmin">; +defm PFMUL : I3DNow_binop_rm_int<0xB4, "pfmul">; +defm PFRCP : I3DNow_conv_rm_int<0x96, "pfrcp">; +defm PFRCPIT1 : I3DNow_binop_rm_int<0xA6, "pfrcpit1">; +defm PFRCPIT2 : I3DNow_binop_rm_int<0xB6, "pfrcpit2">; +defm PFRSQIT1 : I3DNow_binop_rm_int<0xA7, "pfrsqit1">; +defm PFRSQRT : I3DNow_conv_rm_int<0x97, "pfrsqrt">; +defm PFSUB : I3DNow_binop_rm_int<0x9A, "pfsub">; +defm PFSUBR : I3DNow_binop_rm_int<0xAA, "pfsubr">; +defm PI2FD : I3DNow_conv_rm_int<0x0D, "pi2fd">; +defm PMULHRW : I3DNow_binop_rm_int<0xB7, "pmulhrw">; def FEMMS : I3DNow<0x0E, RawFrm, (outs), (ins), "femms", [(int_x86_mmx_femms)]>; def PREFETCH : I3DNow<0x0D, MRM0m, (outs), (ins i32mem:$addr), "prefetch $addr", []>; - + // FIXME: Diassembler gets a bogus decode conflict. -let isAsmParserOnly = 1 in { +let isAsmParserOnly = 1 in def PREFETCHW : I3DNow<0x0D, MRM1m, (outs), (ins i16mem:$addr), "prefetchw $addr", []>; -} // "3DNowA" instructions -defm PF2IW : I3DNow_binop_rm<0x1C, "pf2iw">; -defm PI2FW : I3DNow_binop_rm<0x0C, "pi2fw">; -defm PFNACC : I3DNow_binop_rm<0x8A, "pfnacc">; -defm PFPNACC : I3DNow_binop_rm<0x8E, "pfpnacc">; -defm PSWAPD : I3DNow_binop_rm<0xBB, "pswapd">; +defm PF2IW : I3DNow_conv_rm_int<0x1C, "pf2iw", "a">; +defm PI2FW : I3DNow_conv_rm_int<0x0C, "pi2fw", "a">; +defm PFNACC : I3DNow_binop_rm_int<0x8A, "pfnacc", "a">; +defm PFPNACC : I3DNow_binop_rm_int<0x8E, "pfpnacc", "a">; +defm PSWAPD : I3DNow_conv_rm_int<0xBB, "pswapd", "a">; Added: llvm/trunk/test/CodeGen/X86/3dnow-intrinsics.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/3dnow-intrinsics.ll?rev=129551&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/3dnow-intrinsics.ll (added) +++ llvm/trunk/test/CodeGen/X86/3dnow-intrinsics.ll Thu Apr 14 19:32:41 2011 @@ -0,0 +1,297 @@ +; RUN: llc < %s -march=x86 -mattr=+3dnow | FileCheck %s + +define <8 x i8> @test_pavgusb(x86_mmx %a.coerce, x86_mmx %b.coerce) nounwind readnone { +; CHECK: pavgusb +entry: + %0 = bitcast x86_mmx %a.coerce to <8 x i8> + %1 = bitcast x86_mmx %b.coerce to <8 x i8> + %2 = bitcast <8 x i8> %0 to x86_mmx + %3 = bitcast <8 x i8> %1 to x86_mmx + %4 = call x86_mmx @llvm.x86.3dnow.pavgusb(x86_mmx %2, x86_mmx %3) + %5 = bitcast x86_mmx %4 to <8 x i8> + ret <8 x i8> %5 +} + +declare x86_mmx @llvm.x86.3dnow.pavgusb(x86_mmx, x86_mmx) nounwind readnone + +define <2 x i32> @test_pf2id(<2 x float> %a) nounwind readnone { +; CHECK: pf2id +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = tail call x86_mmx @llvm.x86.3dnow.pf2id(x86_mmx %0) + %2 = bitcast x86_mmx %1 to <2 x i32> + ret <2 x i32> %2 +} + +declare x86_mmx @llvm.x86.3dnow.pf2id(x86_mmx) nounwind readnone + +define <2 x float> @test_pfacc(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfacc +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfacc(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfacc(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfadd(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfadd +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfadd(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfadd(x86_mmx, x86_mmx) nounwind readnone + +define <2 x i32> @test_pfcmpeq(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfcmpeq +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfcmpeq(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x i32> + ret <2 x i32> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfcmpeq(x86_mmx, x86_mmx) nounwind readnone + +define <2 x i32> @test_pfcmpge(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfcmpge +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfcmpge(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x i32> + ret <2 x i32> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfcmpge(x86_mmx, x86_mmx) nounwind readnone + +define <2 x i32> @test_pfcmpgt(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfcmpgt +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfcmpgt(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x i32> + ret <2 x i32> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfcmpgt(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfmax(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfmax +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfmax(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfmax(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfmin(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfmin +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfmin(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfmin(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfmul(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfmul +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfmul(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfmul(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfrcp(<2 x float> %a) nounwind readnone { +; CHECK: pfrcp +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = tail call x86_mmx @llvm.x86.3dnow.pfrcp(x86_mmx %0) + %2 = bitcast x86_mmx %1 to <2 x float> + ret <2 x float> %2 +} + +declare x86_mmx @llvm.x86.3dnow.pfrcp(x86_mmx) nounwind readnone + +define <2 x float> @test_pfrcpit1(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfrcpit1 +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfrcpit1(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfrcpit1(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfrcpit2(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfrcpit2 +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfrcpit2(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfrcpit2(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfrsqrt(<2 x float> %a) nounwind readnone { +; CHECK: pfrsqrt +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = tail call x86_mmx @llvm.x86.3dnow.pfrsqrt(x86_mmx %0) + %2 = bitcast x86_mmx %1 to <2 x float> + ret <2 x float> %2 +} + +declare x86_mmx @llvm.x86.3dnow.pfrsqrt(x86_mmx) nounwind readnone + +define <2 x float> @test_pfrsqit1(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfrsqit1 +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfrsqit1(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfrsqit1(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfsub(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfsub +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfsub(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfsub(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfsubr(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfsubr +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnow.pfsubr(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pfsubr(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pi2fd(x86_mmx %a.coerce) nounwind readnone { +; CHECK: pi2fd +entry: + %0 = bitcast x86_mmx %a.coerce to <2 x i32> + %1 = bitcast <2 x i32> %0 to x86_mmx + %2 = call x86_mmx @llvm.x86.3dnow.pi2fd(x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnow.pi2fd(x86_mmx) nounwind readnone + +define <4 x i16> @test_pmulhrw(x86_mmx %a.coerce, x86_mmx %b.coerce) nounwind readnone { +; CHECK: pmulhrw +entry: + %0 = bitcast x86_mmx %a.coerce to <4 x i16> + %1 = bitcast x86_mmx %b.coerce to <4 x i16> + %2 = bitcast <4 x i16> %0 to x86_mmx + %3 = bitcast <4 x i16> %1 to x86_mmx + %4 = call x86_mmx @llvm.x86.3dnow.pmulhrw(x86_mmx %2, x86_mmx %3) + %5 = bitcast x86_mmx %4 to <4 x i16> + ret <4 x i16> %5 +} + +declare x86_mmx @llvm.x86.3dnow.pmulhrw(x86_mmx, x86_mmx) nounwind readnone + +define <2 x i32> @test_pf2iw(<2 x float> %a) nounwind readnone { +; CHECK: pf2iw +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = tail call x86_mmx @llvm.x86.3dnowa.pf2iw(x86_mmx %0) + %2 = bitcast x86_mmx %1 to <2 x i32> + ret <2 x i32> %2 +} + +declare x86_mmx @llvm.x86.3dnowa.pf2iw(x86_mmx) nounwind readnone + +define <2 x float> @test_pfnacc(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfnacc +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnowa.pfnacc(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnowa.pfnacc(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pfpnacc(<2 x float> %a, <2 x float> %b) nounwind readnone { +; CHECK: pfpnacc +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = bitcast <2 x float> %b to x86_mmx + %2 = tail call x86_mmx @llvm.x86.3dnowa.pfpnacc(x86_mmx %0, x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnowa.pfpnacc(x86_mmx, x86_mmx) nounwind readnone + +define <2 x float> @test_pi2fw(x86_mmx %a.coerce) nounwind readnone { +; CHECK: pi2fw +entry: + %0 = bitcast x86_mmx %a.coerce to <2 x i32> + %1 = bitcast <2 x i32> %0 to x86_mmx + %2 = call x86_mmx @llvm.x86.3dnowa.pi2fw(x86_mmx %1) + %3 = bitcast x86_mmx %2 to <2 x float> + ret <2 x float> %3 +} + +declare x86_mmx @llvm.x86.3dnowa.pi2fw(x86_mmx) nounwind readnone + +define <2 x float> @test_pswapdsf(<2 x float> %a) nounwind readnone { +; CHECK: pswapd +entry: + %0 = bitcast <2 x float> %a to x86_mmx + %1 = tail call x86_mmx @llvm.x86.3dnowa.pswapd(x86_mmx %0) + %2 = bitcast x86_mmx %1 to <2 x float> + ret <2 x float> %2 +} + +define <2 x i32> @test_pswapdsi(<2 x i32> %a) nounwind readnone { +; CHECK: pswapd +entry: + %0 = bitcast <2 x i32> %a to x86_mmx + %1 = tail call x86_mmx @llvm.x86.3dnowa.pswapd(x86_mmx %0) + %2 = bitcast x86_mmx %1 to <2 x i32> + ret <2 x i32> %2 +} + +declare x86_mmx @llvm.x86.3dnowa.pswapd(x86_mmx) nounwind readnone From johnny.chen at apple.com Thu Apr 14 19:35:08 2011 From: johnny.chen at apple.com (Johnny Chen) Date: Fri, 15 Apr 2011 00:35:08 -0000 Subject: [llvm-commits] [llvm] r129552 - /llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Message-ID: <20110415003508.4A4572A6C12C@llvm.org> Author: johnny Date: Thu Apr 14 19:35:08 2011 New Revision: 129552 URL: http://llvm.org/viewvc/llvm-project?rev=129552&view=rev Log: For t2BFI, both Inst{26} and Inst{5} "should" be 0. Ref: I.1 Instruction encoding diagrams and pseudocode Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=129552&r1=129551&r2=129552&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Thu Apr 14 19:35:08 2011 @@ -2166,9 +2166,11 @@ [(set rGPR:$Rd, (ARMbfi rGPR:$src, rGPR:$Rn, bf_inv_mask_imm:$imm))]> { let Inst{31-27} = 0b11110; + let Inst{26} = 0; // should be 0. let Inst{25} = 1; let Inst{24-20} = 0b10110; let Inst{15} = 0; + let Inst{5} = 0; // should be 0. bits<10> imm; let msb{4-0} = imm{9-5}; @@ -2183,9 +2185,11 @@ IIC_iBITi, "bfi", "\t$Rd, $Rn, $lsbit, $width", []> { let Inst{31-27} = 0b11110; + let Inst{26} = 0; // should be 0. let Inst{25} = 1; let Inst{24-20} = 0b10110; let Inst{15} = 0; + let Inst{5} = 0; // should be 0. bits<5> lsbit; bits<5> width; From evan.cheng at apple.com Thu Apr 14 20:31:00 2011 From: evan.cheng at apple.com (Evan Cheng) Date: Fri, 15 Apr 2011 01:31:00 -0000 Subject: [llvm-commits] [llvm] r129556 - in /llvm/trunk: lib/Target/ARM/ARMISelLowering.cpp test/CodeGen/ARM/fcopysign.ll Message-ID: <20110415013100.6065F2A6C12C@llvm.org> Author: evancheng Date: Thu Apr 14 20:31:00 2011 New Revision: 129556 URL: http://llvm.org/viewvc/llvm-project?rev=129556&view=rev Log: Fix another fcopysign lowering bug. If src is f64 and destination is f32, don't forget to right shift the source by 32 first. rdar://9287902 Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp llvm/trunk/test/CodeGen/ARM/fcopysign.ll Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=129556&r1=129555&r2=129556&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Thu Apr 14 20:31:00 2011 @@ -2952,7 +2952,10 @@ Tmp1 = DAG.getNode(ARMISD::VSHL, dl, OpVT, DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1), DAG.getConstant(32, MVT::i32)); - } + } else if (VT == MVT::f32) + Tmp1 = DAG.getNode(ARMISD::VSHRu, dl, MVT::v1i64, + DAG.getNode(ISD::BITCAST, dl, MVT::v1i64, Tmp1), + DAG.getConstant(32, MVT::i32)); Tmp0 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp0); Tmp1 = DAG.getNode(ISD::BITCAST, dl, OpVT, Tmp1); Modified: llvm/trunk/test/CodeGen/ARM/fcopysign.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/fcopysign.ll?rev=129556&r1=129555&r2=129556&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/fcopysign.ll (original) +++ llvm/trunk/test/CodeGen/ARM/fcopysign.ll Thu Apr 14 20:31:00 2011 @@ -44,15 +44,32 @@ define i32 @test4() ssp { entry: ; SOFT: test4: -; SOFT: vcvt.f32.f64 s0, -; SOFT: vmov.i32 [[REG4:(d[0-9]+)]], #0x80000000 -; SOFT: vbic [[REG5:(d[0-9]+)]], d0, [[REG4]] -; SOFT: vorr d0, [[REG4]], [[REG5]] +; SOFT: vmov.f64 [[REG4:(d[0-9]+)]], #1.000000e+00 +; SOFT: vcvt.f32.f64 s0, [[REG4]] +; SOFT: vshr.u64 [[REG4]], [[REG4]], #32 +; SOFT: vmov.i32 [[REG5:(d[0-9]+)]], #0x80000000 +; SOFT: vbsl [[REG5]], [[REG4]], d0 %call80 = tail call double @copysign(double 1.000000e+00, double undef) %conv81 = fptrunc double %call80 to float %tmp88 = bitcast float %conv81 to i32 ret i32 %tmp88 } +; rdar://9287902 +define float @test5() nounwind { +entry: +; SOFT: test5: +; SOFT: vmov.i32 [[REG6:(d[0-9]+)]], #0x80000000 +; SOFT: vmov [[REG7:(d[0-9]+)]], r0, r1 +; SOFT: vshr.u64 [[REG7]], [[REG7]], #32 +; SOFT: vbsl [[REG6]], [[REG7]], + %0 = tail call double (...)* @bar() nounwind + %1 = fptrunc double %0 to float + %2 = tail call float @copysignf(float 5.000000e-01, float %1) nounwind readnone + %3 = fadd float %1, %2 + ret float %3 +} + +declare double @bar(...) declare double @copysign(double, double) nounwind declare float @copysignf(float, float) nounwind From geek4civic at gmail.com Thu Apr 14 21:53:24 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Fri, 15 Apr 2011 11:53:24 +0900 Subject: [llvm-commits] [llvm] r129518 - in /llvm/trunk: include/llvm/CodeGen/AsmPrinter.h lib/CodeGen/AsmPrinter/AsmPrinter.cpp lib/CodeGen/AsmPrinter/DwarfCFIException.cpp lib/Target/TargetLoweringObjectFile.cpp lib/Target/X86/X86FrameLowering.cpp lib/T Message-ID: Rafael, It seems you broke several buildbot tests. Could you investigate? Or may I revert yours? ...Takumi On Fri, Apr 15, 2011 at 12:18 AM, Rafael Espindola wrote: > Author: rafael > Date: Thu Apr 14 10:18:53 2011 > New Revision: 129518 > > URL: http://llvm.org/viewvc/llvm-project?rev=129518&view=rev > Log: > Change ELF systems to use CFI for producing the EH tables. This reduces the > size of the clang binary in Debug builds from 690MB to 679MB. > > Removed: > ? ?llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll > Modified: > ? ?llvm/trunk/include/llvm/CodeGen/AsmPrinter.h > ? ?llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp > ? ?llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp > ? ?llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp > ? ?llvm/trunk/lib/Target/X86/X86FrameLowering.cpp > ? ?llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp > ? ?llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll > ? ?llvm/trunk/test/CodeGen/X86/aliases.ll From geek4civic at gmail.com Thu Apr 14 22:35:57 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Fri, 15 Apr 2011 03:35:57 -0000 Subject: [llvm-commits] [llvm] r129557 - in /llvm/trunk: include/llvm/CodeGen/AsmPrinter.h lib/CodeGen/AsmPrinter/AsmPrinter.cpp lib/CodeGen/AsmPrinter/DwarfCFIException.cpp lib/Target/TargetLoweringObjectFile.cpp lib/Target/X86/X86FrameLowering.cpp lib/Target/X86/X86MCAsmInfo.cpp test/CodeGen/X86/2007-05-05-Personality.ll test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll test/CodeGen/X86/aliases.ll Message-ID: <20110415033558.06B632A6C12C@llvm.org> Author: chapuni Date: Thu Apr 14 22:35:57 2011 New Revision: 129557 URL: http://llvm.org/viewvc/llvm-project?rev=129557&view=rev Log: Revert r129518, "Change ELF systems to use CFI for producing the EH tables. This reduces the" It broke several builds. Added: llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll Modified: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp llvm/trunk/lib/Target/X86/X86FrameLowering.cpp llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll llvm/trunk/test/CodeGen/X86/aliases.ll Modified: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/AsmPrinter.h?rev=129557&r1=129556&r2=129557&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h (original) +++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h Thu Apr 14 22:35:57 2011 @@ -183,8 +183,6 @@ /// function. void EmitFunctionBody(); - void emitPrologLabel(const MachineInstr &MI); - /// EmitConstantPool - Print to the current output stream assembly /// representations of the constants in the constant pool MCP. This is /// used to print out constants which have been "spilled to memory" by Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=129557&r1=129556&r2=129557&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Thu Apr 14 22:35:57 2011 @@ -33,7 +33,6 @@ #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Target/Mangler.h" -#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" @@ -625,45 +624,6 @@ return true; } -void AsmPrinter::emitPrologLabel(const MachineInstr &MI) { - MCSymbol *Label = MI.getOperand(0).getMCSymbol(); - if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI) { - OutStreamer.EmitLabel(Label); - return; - } - - const MachineFunction &MF = *MI.getParent()->getParent(); - MachineModuleInfo &MMI = MF.getMMI(); - std::vector &Moves = MMI.getFrameMoves(); - const MachineMove *Move = NULL; - for (std::vector::iterator I = Moves.begin(), - E = Moves.end(); I != E; ++I) { - if (I->getLabel() == Label) { - Move = &*I; - break; - } - } - assert(Move); - - const MachineLocation &Dst = Move->getDestination(); - const MachineLocation &Src = Move->getSource(); - const TargetAsmInfo &AsmInfo = OutContext.getTargetAsmInfo(); - if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) { - if (Src.getReg() == MachineLocation::VirtualFP) - OutStreamer.EmitCFIDefCfaOffset(-Src.getOffset()); - else { - unsigned Reg = AsmInfo.getDwarfRegNum(Src.getReg(), true); - OutStreamer.EmitCFIDefCfa(Reg, -Src.getOffset()); - } - } else if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) { - unsigned Reg = AsmInfo.getDwarfRegNum(Dst.getReg(), true); - OutStreamer.EmitCFIDefCfaRegister(Reg); - } else { - unsigned Reg = AsmInfo.getDwarfRegNum(Src.getReg(), true); - OutStreamer.EmitCFIOffset(Reg, -Dst.getOffset()); - } -} - /// EmitFunctionBody - This method emits the body and trailer for a /// function. void AsmPrinter::EmitFunctionBody() { @@ -700,9 +660,6 @@ switch (II->getOpcode()) { case TargetOpcode::PROLOG_LABEL: - emitPrologLabel(*II); - break; - case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol()); Modified: llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp?rev=129557&r1=129556&r2=129557&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp Thu Apr 14 22:35:57 2011 @@ -32,7 +32,6 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Dwarf.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -61,16 +60,11 @@ // Begin eh frame section. Asm->OutStreamer.SwitchSection(TLOF.getEHFrameSection()); - if ((PerEncoding & 0x70) != dwarf::DW_EH_PE_pcrel) - return; - // Emit references to all used personality functions const std::vector &Personalities = MMI->getPersonalities(); for (size_t i = 0, e = Personalities.size(); i != e; ++i) { Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("personality", i)); - const MCSymbol *Sym = Asm->Mang->getSymbol(Personalities[i]); - unsigned Size = Asm->TM.getTargetData()->getPointerSize(); - Asm->OutStreamer.EmitSymbolValue(Sym, Size); + Asm->EmitReference(Personalities[i], PerEncoding); } } @@ -93,9 +87,17 @@ shouldEmitTableModule |= shouldEmitTable; - if (shouldEmitMoves || shouldEmitTable) + if (shouldEmitMoves) { + const TargetFrameLowering *TFL = Asm->TM.getFrameLowering(); Asm->OutStreamer.EmitCFIStartProc(); + // Indicate locations of general callee saved registers in frame. + std::vector Moves; + TFL->getInitialFrameState(Moves); + Asm->EmitCFIFrameMoves(Moves); + Asm->EmitCFIFrameMoves(MMI->getFrameMoves()); + } + if (!shouldEmitTable) return; @@ -110,25 +112,11 @@ // Indicate personality routine, if any. unsigned PerEncoding = TLOF.getPersonalityEncoding(); - const Function *Per = MMI->getPersonalities()[MMI->getPersonalityIndex()]; - if (PerEncoding == dwarf::DW_EH_PE_omit || !Per) - return; - - const MCSymbol *Sym; - switch (PerEncoding & 0x70) { - default: - report_fatal_error("We do not support this DWARF encoding yet!"); - case dwarf::DW_EH_PE_absptr: { - Sym = Asm->Mang->getSymbol(Per); - break; - } - case dwarf::DW_EH_PE_pcrel: { - Sym = Asm->GetTempSymbol("personality", - MMI->getPersonalityIndex()); - break; - } - } - Asm->OutStreamer.EmitCFIPersonality(Sym, PerEncoding); + if (PerEncoding != dwarf::DW_EH_PE_omit && + MMI->getPersonalities()[MMI->getPersonalityIndex()]) + Asm->OutStreamer.EmitCFIPersonality(Asm->GetTempSymbol("personality", + MMI->getPersonalityIndex()), + PerEncoding); } /// EndFunction - Gather and emit post-function exception information. Modified: llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp?rev=129557&r1=129556&r2=129557&view=diff ============================================================================== --- llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp (original) +++ llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp Thu Apr 14 22:35:57 2011 @@ -314,7 +314,7 @@ MCStreamer &Streamer) const { const MCExpr *Res = MCSymbolRefExpr::Create(Sym, getContext()); - switch (Encoding & 0x70) { + switch (Encoding & 0xF0) { default: report_fatal_error("We do not support this DWARF encoding yet!"); case dwarf::DW_EH_PE_absptr: Modified: llvm/trunk/lib/Target/X86/X86FrameLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FrameLowering.cpp?rev=129557&r1=129556&r2=129557&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86FrameLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86FrameLowering.cpp Thu Apr 14 22:35:57 2011 @@ -22,7 +22,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/MC/MCAsmInfo.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/CommandLine.h" @@ -477,15 +476,6 @@ .addReg(StackPtr); if (needsFrameMoves) { - const MCAsmInfo &MAI = MMI.getContext().getAsmInfo(); - if (MAI.getExceptionHandlingType() == ExceptionHandling::DwarfCFI) { - MCSymbol *FrameLabel0 = MMI.getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel0); - MachineLocation FPSrc0(FramePtr); - MachineLocation FPDst0(FramePtr, -2 * stackGrowth); - Moves.push_back(MachineMove(FrameLabel0, FPDst0, FPSrc0)); - } - // Mark effective beginning of when frame pointer becomes valid. MCSymbol *FrameLabel = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(FrameLabel); @@ -625,7 +615,7 @@ emitSPUpdate(MBB, MBBI, StackPtr, -(int64_t)NumBytes, Is64Bit, TII, *RegInfo); - if (( (!HasFP && NumBytes) || PushedRegs) && needsFrameMoves) { + if ((NumBytes || PushedRegs) && needsFrameMoves) { // Mark end of stack pointer adjustment. MCSymbol *Label = MMI.getContext().CreateTempSymbol(); BuildMI(MBB, MBBI, DL, TII.get(X86::PROLOG_LABEL)).addSym(Label); Modified: llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp?rev=129557&r1=129556&r2=129557&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86MCAsmInfo.cpp Thu Apr 14 22:35:57 2011 @@ -89,9 +89,7 @@ SupportsDebugInformation = true; // Exceptions handling - ExceptionsType = ExceptionHandling::DwarfCFI; - - DwarfRequiresFrameSection = false; + ExceptionsType = ExceptionHandling::DwarfTable; // OpenBSD has buggy support for .quad in 32-bit mode, just split into two // .words. Modified: llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll?rev=129557&r1=129556&r2=129557&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll (original) +++ llvm/trunk/test/CodeGen/X86/2007-05-05-Personality.ll Thu Apr 14 22:35:57 2011 @@ -1,7 +1,4 @@ -; RUN: llc < %s -mtriple=i686-pc-linux-gnu -o - | FileCheck %s - -; CHECK: .cfi_lsda 0, .Lexception0 -; CHECK: .cfi_personality 0, __gnat_eh_personality +; RUN: llc < %s -mtriple=i686-pc-linux-gnu -o - | grep zPL @error = external global i8 ; [#uses=2] Added: llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll?rev=129557&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll (added) +++ llvm/trunk/test/CodeGen/X86/2008-12-12-PrivateEHSymbol.ll Thu Apr 14 22:35:57 2011 @@ -0,0 +1,12 @@ +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-unknown-linux-gnu | grep ^.L_Z1fv.eh +; RUN: llc < %s -march=x86 -mtriple=i686-unknown-linux-gnu | grep ^.L_Z1fv.eh +; RUN: llc < %s -march=x86-64 -mtriple=x86_64-apple-darwin9 | grep ^__Z1fv.eh +; RUN: llc < %s -march=x86 -mtriple=i386-apple-darwin9 | grep ^__Z1fv.eh + +define void @_Z1fv() { +entry: + br label %return + +return: + ret void +} Modified: llvm/trunk/test/CodeGen/X86/aliases.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/aliases.ll?rev=129557&r1=129556&r2=129557&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/aliases.ll (original) +++ llvm/trunk/test/CodeGen/X86/aliases.ll Thu Apr 14 22:35:57 2011 @@ -1,4 +1,6 @@ ; RUN: llc < %s -mtriple=i686-pc-linux-gnu -asm-verbose=false -o %t +; RUN: grep { = } %t | count 16 +; RUN: grep set %t | count 18 ; RUN: grep globl %t | count 6 ; RUN: grep weak %t | count 1 ; RUN: grep hidden %t | count 1 From clattner at apple.com Fri Apr 15 00:20:01 2011 From: clattner at apple.com (Chris Lattner) Date: Thu, 14 Apr 2011 22:20:01 -0700 Subject: [llvm-commits] MIPS patch In-Reply-To: References: Message-ID: <4DD6846B-2942-4116-BC3C-A0225CC00E30@apple.com> On Apr 14, 2011, at 5:35 PM, Akira Hatanaka wrote: > Made minor changes per discussion with Bruno. Do you really need another pass to do this? Why not just handle this during mc inst lowering? +++ lib/Target/Mips/MipsExpandPseudoInstrs.cpp (revision 0) @@ -0,0 +1,116 @@ +//===-- ExpandPseudoInstrs.cpp - Mips delay slot filler ---------------------===// +// +// The LLVM Compiler Infrastructure +// Please correct the filename and comment and make sure the line fits 80 columns. -Chris From sabre at nondot.org Fri Apr 15 00:18:48 2011 From: sabre at nondot.org (Chris Lattner) Date: Fri, 15 Apr 2011 05:18:48 -0000 Subject: [llvm-commits] [llvm] r129558 - in /llvm/trunk: ./ autoconf/m4/ cmake/modules/ docs/ docs/CommandGuide/ docs/HistoricalNotes/ examples/ExceptionDemo/ include/llvm-c/ include/llvm/ include/llvm/ADT/ include/llvm/Analysis/ include/llvm/Bitcode/ include/llvm/CodeGen/ include/llvm/ExecutionEngine/ include/llvm/MC/ include/llvm/Support/ include/llvm/Target/ include/llvm/Transforms/Utils/ lib/Analysis/ lib/Analysis/IPA/ lib/Bitcode/Writer/ lib/CodeGen/ lib/CodeGen/AsmPrinter/ lib/CodeGen/SelectionDAG/ lib/ExecutionEngine/JIT... Message-ID: <20110415051851.D42A62A6C12C@llvm.org> Author: lattner Date: Fri Apr 15 00:18:47 2011 New Revision: 129558 URL: http://llvm.org/viewvc/llvm-project?rev=129558&view=rev Log: Fix a ton of comment typos found by codespell. Patch by Luis Felipe Strano Moraes! Modified: llvm/trunk/CMakeLists.txt llvm/trunk/Makefile.rules llvm/trunk/autoconf/m4/libtool.m4 llvm/trunk/autoconf/m4/ltdl.m4 llvm/trunk/cmake/modules/LLVM-Config.cmake llvm/trunk/configure llvm/trunk/docs/CommandGuide/llvm-bcanalyzer.pod llvm/trunk/docs/CompilerDriver.html llvm/trunk/docs/ExceptionHandling.html llvm/trunk/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt llvm/trunk/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt llvm/trunk/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt llvm/trunk/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt llvm/trunk/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt llvm/trunk/docs/HistoricalNotes/2002-05-12-InstListChange.txt llvm/trunk/docs/LangRef.html llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp llvm/trunk/include/llvm-c/Disassembler.h llvm/trunk/include/llvm-c/lto.h llvm/trunk/include/llvm/ADT/StringExtras.h llvm/trunk/include/llvm/ADT/ilist.h llvm/trunk/include/llvm/Analysis/InlineCost.h llvm/trunk/include/llvm/Analysis/RegionInfo.h llvm/trunk/include/llvm/Analysis/RegionIterator.h llvm/trunk/include/llvm/Analysis/RegionPass.h llvm/trunk/include/llvm/Bitcode/Archive.h llvm/trunk/include/llvm/CodeGen/ISDOpcodes.h llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h llvm/trunk/include/llvm/CodeGen/SelectionDAG.h llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h llvm/trunk/include/llvm/GlobalVariable.h llvm/trunk/include/llvm/Instructions.h llvm/trunk/include/llvm/MC/MCAsmLayout.h llvm/trunk/include/llvm/MC/MCAssembler.h llvm/trunk/include/llvm/Pass.h llvm/trunk/include/llvm/Support/GraphWriter.h llvm/trunk/include/llvm/Support/PrettyStackTrace.h llvm/trunk/include/llvm/Support/Program.h llvm/trunk/include/llvm/Support/Regex.h llvm/trunk/include/llvm/Support/Signals.h llvm/trunk/include/llvm/Support/TimeValue.h llvm/trunk/include/llvm/Target/TargetInstrInfo.h llvm/trunk/include/llvm/Target/TargetLowering.h llvm/trunk/include/llvm/Transforms/Utils/Cloning.h llvm/trunk/include/llvm/TypeSymbolTable.h llvm/trunk/lib/Analysis/BasicAliasAnalysis.cpp llvm/trunk/lib/Analysis/IPA/GlobalsModRef.cpp llvm/trunk/lib/Analysis/InlineCost.cpp llvm/trunk/lib/Analysis/PathNumbering.cpp llvm/trunk/lib/Analysis/PathProfileVerifier.cpp llvm/trunk/lib/Analysis/ProfileEstimatorPass.cpp llvm/trunk/lib/Analysis/ProfileInfo.cpp llvm/trunk/lib/Analysis/ScalarEvolution.cpp llvm/trunk/lib/Analysis/TypeBasedAliasAnalysis.cpp llvm/trunk/lib/Analysis/ValueTracking.cpp llvm/trunk/lib/Bitcode/Writer/ValueEnumerator.cpp llvm/trunk/lib/CodeGen/AggressiveAntiDepBreaker.cpp llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp llvm/trunk/lib/CodeGen/CodePlacementOpt.cpp llvm/trunk/lib/CodeGen/ELF.h llvm/trunk/lib/CodeGen/ELFWriter.cpp llvm/trunk/lib/CodeGen/ExpandISelPseudos.cpp llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp llvm/trunk/lib/CodeGen/LiveIntervalAnalysis.cpp llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp llvm/trunk/lib/CodeGen/README.txt llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp llvm/trunk/lib/CodeGen/RenderMachineFunction.cpp llvm/trunk/lib/CodeGen/ScheduleDAG.cpp llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp llvm/trunk/lib/CodeGen/ShrinkWrapping.cpp llvm/trunk/lib/CodeGen/StrongPHIElimination.cpp llvm/trunk/lib/CodeGen/VirtRegRewriter.cpp llvm/trunk/lib/ExecutionEngine/JIT/JIT.cpp llvm/trunk/lib/MC/MCDisassembler/Disassembler.cpp llvm/trunk/lib/MC/MCExpr.cpp llvm/trunk/lib/MC/MachObjectWriter.cpp llvm/trunk/lib/Support/APFloat.cpp llvm/trunk/lib/Support/APInt.cpp llvm/trunk/lib/Support/FileUtilities.cpp llvm/trunk/lib/Support/PrettyStackTrace.cpp llvm/trunk/lib/Support/Signals.cpp llvm/trunk/lib/Support/StringRef.cpp llvm/trunk/lib/Support/Unix/Program.inc llvm/trunk/lib/Support/Unix/Signals.inc llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h llvm/trunk/lib/Target/ARM/ARMBaseRegisterInfo.cpp llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp llvm/trunk/lib/Target/ARM/ARMInstrInfo.td llvm/trunk/lib/Target/ARM/ARMInstrThumb.td llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td llvm/trunk/lib/Target/ARM/ARMLoadStoreOptimizer.cpp llvm/trunk/lib/Target/ARM/ARMSelectionDAGInfo.cpp llvm/trunk/lib/Target/Alpha/Alpha.td llvm/trunk/lib/Target/Alpha/AlphaISelLowering.cpp llvm/trunk/lib/Target/Alpha/AlphaInstrInfo.td llvm/trunk/lib/Target/Alpha/README.txt llvm/trunk/lib/Target/Blackfin/BlackfinISelLowering.cpp llvm/trunk/lib/Target/CellSPU/SPU64InstrInfo.td llvm/trunk/lib/Target/CellSPU/SPUISelLowering.cpp llvm/trunk/lib/Target/MBlaze/MBlazeISelLowering.cpp llvm/trunk/lib/Target/MBlaze/MBlazeSchedule3.td llvm/trunk/lib/Target/MSP430/MSP430ISelLowering.cpp llvm/trunk/lib/Target/Mips/Mips.td llvm/trunk/lib/Target/Mips/MipsFrameLowering.cpp llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp llvm/trunk/lib/Target/Mips/MipsInstrFPU.td llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp llvm/trunk/lib/Target/Sparc/SparcISelLowering.cpp llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp llvm/trunk/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h llvm/trunk/lib/Target/X86/README-X86-64.txt llvm/trunk/lib/Target/X86/README.txt llvm/trunk/lib/Target/X86/X86.td llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp llvm/trunk/lib/Target/X86/X86FrameLowering.cpp llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86InstrArithmetic.td llvm/trunk/lib/Target/X86/X86InstrInfo.cpp llvm/trunk/lib/Target/X86/X86InstrInfo.h llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp llvm/trunk/lib/Target/X86/X86RegisterInfo.cpp llvm/trunk/lib/Target/X86/X86SelectionDAGInfo.cpp llvm/trunk/lib/Target/XCore/XCoreISelLowering.cpp llvm/trunk/lib/Transforms/IPO/ArgumentPromotion.cpp llvm/trunk/lib/Transforms/IPO/DeadArgumentElimination.cpp llvm/trunk/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp llvm/trunk/lib/Transforms/InstCombine/InstCombinePHI.cpp llvm/trunk/lib/Transforms/Instrumentation/PathProfiling.cpp llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp llvm/trunk/lib/Transforms/Scalar/LoopStrengthReduce.cpp llvm/trunk/lib/Transforms/Scalar/MemCpyOptimizer.cpp llvm/trunk/lib/Transforms/Scalar/Reg2Mem.cpp llvm/trunk/lib/Transforms/Scalar/SCCP.cpp llvm/trunk/lib/Transforms/Scalar/TailRecursionElimination.cpp llvm/trunk/lib/Transforms/Utils/BreakCriticalEdges.cpp llvm/trunk/lib/Transforms/Utils/CodeExtractor.cpp llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp llvm/trunk/lib/Transforms/Utils/LowerSwitch.cpp llvm/trunk/lib/VMCore/ConstantFold.cpp llvm/trunk/lib/VMCore/LLVMContextImpl.h llvm/trunk/lib/VMCore/PassManager.cpp llvm/trunk/lib/VMCore/PassRegistry.cpp llvm/trunk/lib/VMCore/TypesContext.h llvm/trunk/projects/sample/autoconf/configure.ac llvm/trunk/runtime/libprofile/OptimalEdgeProfiling.c llvm/trunk/runtime/libprofile/PathProfiling.c llvm/trunk/test/DebugInfo/2010-04-13-PubType.ll llvm/trunk/test/FrontendC/2006-05-01-AppleAlignmentPragma.c llvm/trunk/test/FrontendC/2010-07-27-MinNoFoldConst.c llvm/trunk/test/MC/MachO/darwin-x86_64-diff-relocs.s llvm/trunk/test/TableGen/TargetInstrInfo.td llvm/trunk/test/Transforms/ConstProp/2002-05-03-NotOperator.ll llvm/trunk/test/Transforms/ConstProp/basictest.ll llvm/trunk/test/Transforms/ConstProp/logicaltest.ll llvm/trunk/test/Transforms/ConstProp/phi.ll llvm/trunk/test/Transforms/InstCombine/and-or-not.ll llvm/trunk/test/Transforms/SCCP/apint-basictest.ll llvm/trunk/test/Transforms/SCCP/apint-basictest2.ll llvm/trunk/test/Transforms/SCCP/apint-basictest3.ll llvm/trunk/test/Transforms/SCCP/apint-basictest4.ll llvm/trunk/test/Transforms/ScalarRepl/2008-06-05-loadstore-agg.ll llvm/trunk/tools/llvm-diff/DifferenceEngine.cpp llvm/trunk/tools/llvmc/doc/LLVMC-Reference.rst llvm/trunk/tools/llvmc/src/Base.td.in llvm/trunk/tools/lto/lto.cpp llvm/trunk/utils/DSAextract.py llvm/trunk/utils/KillTheDoctor/KillTheDoctor.cpp llvm/trunk/utils/NewNightlyTest.pl llvm/trunk/utils/TableGen/ARMDecoderEmitter.cpp llvm/trunk/utils/TableGen/AsmMatcherEmitter.cpp llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp llvm/trunk/utils/TableGen/OptParserEmitter.cpp llvm/trunk/utils/TableGen/X86DisassemblerTables.h llvm/trunk/utils/buildit/GNUmakefile llvm/trunk/utils/lit/setup.py llvm/trunk/utils/unittest/googletest/gtest-filepath.cc llvm/trunk/utils/unittest/googletest/gtest.cc llvm/trunk/utils/unittest/googletest/include/gtest/internal/gtest-filepath.h Modified: llvm/trunk/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/CMakeLists.txt?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/CMakeLists.txt (original) +++ llvm/trunk/CMakeLists.txt Fri Apr 15 00:18:47 2011 @@ -154,7 +154,7 @@ option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON) endif() -# All options refered to from HandleLLVMOptions have to be specified +# All options referred to from HandleLLVMOptions have to be specified # BEFORE this include, otherwise options will not be correctly set on # first cmake run include(config-ix) Modified: llvm/trunk/Makefile.rules URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/Makefile.rules?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/Makefile.rules (original) +++ llvm/trunk/Makefile.rules Fri Apr 15 00:18:47 2011 @@ -2024,7 +2024,7 @@ $(Verb) cd $(PROJ_OBJ_ROOT) ; $(ZIP) -rq $(DistZip) $(DistName) dist :: $(DistTarGZip) $(DistTarBZ2) $(DistZip) - $(Echo) ===== DISTRIBUTION PACKAGING SUCESSFUL ===== + $(Echo) ===== DISTRIBUTION PACKAGING SUCCESSFUL ===== DistCheckDir := $(PROJ_OBJ_ROOT)/_distcheckdir Modified: llvm/trunk/autoconf/m4/libtool.m4 URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/autoconf/m4/libtool.m4?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/autoconf/m4/libtool.m4 (original) +++ llvm/trunk/autoconf/m4/libtool.m4 Fri Apr 15 00:18:47 2011 @@ -1118,7 +1118,7 @@ test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then - # We can hardcode non-existant directories. + # We can hardcode non-existent directories. if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library Modified: llvm/trunk/autoconf/m4/ltdl.m4 URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/autoconf/m4/ltdl.m4?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/autoconf/m4/ltdl.m4 (original) +++ llvm/trunk/autoconf/m4/ltdl.m4 Fri Apr 15 00:18:47 2011 @@ -156,7 +156,7 @@ osf[[1234]]*) # dlopen did load deplibs (at least at 4.x), but until the 5.x series, # it did *not* use an RPATH in a shared library to find objects the - # library depends on, so we explictly say `no'. + # library depends on, so we explicitly say `no'. libltdl_cv_sys_dlopen_deplibs=no ;; osf5.0|osf5.0a|osf5.1) Modified: llvm/trunk/cmake/modules/LLVM-Config.cmake URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/modules/LLVM-Config.cmake?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/cmake/modules/LLVM-Config.cmake (original) +++ llvm/trunk/cmake/modules/LLVM-Config.cmake Fri Apr 15 00:18:47 2011 @@ -135,7 +135,7 @@ string(TOUPPER "${c}" capitalized) list(FIND capitalized_libs LLVM${capitalized} lib_idx) if( lib_idx LESS 0 ) - # The component is unkown. Maybe is an ommitted target? + # The component is unknown. Maybe is an omitted target? is_llvm_target_library(${c} iltl_result) if( NOT iltl_result ) message(FATAL_ERROR "Library `${c}' not found in list of llvm libraries.") Modified: llvm/trunk/configure URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/configure?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/configure (original) +++ llvm/trunk/configure Fri Apr 15 00:18:47 2011 @@ -11723,7 +11723,7 @@ osf[1234]*) # dlopen did load deplibs (at least at 4.x), but until the 5.x series, # it did *not* use an RPATH in a shared library to find objects the - # library depends on, so we explictly say `no'. + # library depends on, so we explicitly say `no'. libltdl_cv_sys_dlopen_deplibs=no ;; osf5.0|osf5.0a|osf5.1) Modified: llvm/trunk/docs/CommandGuide/llvm-bcanalyzer.pod URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CommandGuide/llvm-bcanalyzer.pod?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/CommandGuide/llvm-bcanalyzer.pod (original) +++ llvm/trunk/docs/CommandGuide/llvm-bcanalyzer.pod Fri Apr 15 00:18:47 2011 @@ -268,7 +268,7 @@ =item B -The average number of bytes consumed by the instructions in the funtion. This +The average number of bytes consumed by the instructions in the function. This value is computed by dividing Instruction Size by Instructions. =item B Modified: llvm/trunk/docs/CompilerDriver.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/CompilerDriver.html?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/CompilerDriver.html (original) +++ llvm/trunk/docs/CompilerDriver.html Fri Apr 15 00:18:47 2011 @@ -308,13 +308,13 @@ -std=c99. It is also allowed to use spaces instead of the equality sign: -std c99. At most one occurrence is allowed.

    • parameter_list_option - same as the above, but more than one option -occurence is allowed.
    • +occurrence is allowed.
    • prefix_option - same as the parameter_option, but the option name and argument do not have to be separated. Example: -ofile. This can be also specified as -o file; however, -o=file will be parsed incorrectly (=file will be interpreted as option value). At most one occurrence is allowed.
    • -
    • prefix_list_option - same as the above, but more than one occurence of +
    • prefix_list_option - same as the above, but more than one occurrence of the option is allowed; example: -lm -lpthread.
    • alias_option - a special option type for creating aliases. Unlike other option types, aliases are not allowed to have any properties besides the Modified: llvm/trunk/docs/ExceptionHandling.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ExceptionHandling.html?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/ExceptionHandling.html (original) +++ llvm/trunk/docs/ExceptionHandling.html Fri Apr 15 00:18:47 2011 @@ -507,7 +507,7 @@ style exception handling. The single parameter is a pointer to a buffer populated by llvm.eh.sjlj.setjmp. The frame pointer and stack pointer - are restored from the buffer, then control is transfered to the + are restored from the buffer, then control is transferred to the destination address.

      Modified: llvm/trunk/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt (original) +++ llvm/trunk/docs/HistoricalNotes/2000-11-18-EarlyDesignIdeasResp.txt Fri Apr 15 00:18:47 2011 @@ -60,11 +60,11 @@ Yup, I think that this makes a lot of sense. I am still intrigued, however, by the prospect of a minimally allocated VM representation... I -think that it could have definate advantages for certain applications +think that it could have definite advantages for certain applications (think very small machines, like PDAs). I don't, however, think that our initial implementations should focus on this. :) -Here are some other auxilliary goals that I think we should consider: +Here are some other auxiliary goals that I think we should consider: 1. Primary goal: Support a high performance dynamic compilation system. This means that we have an "ideal" division of labor between Modified: llvm/trunk/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt (original) +++ llvm/trunk/docs/HistoricalNotes/2000-12-06-MeetingSummary.txt Fri Apr 15 00:18:47 2011 @@ -40,7 +40,7 @@ packaged with the bytecodes themselves. As a conceptual implementation idea, we could include an immediate dominator number for each basic block in the LLVM bytecode program. Basic blocks could be numbered according - to the order of occurance in the bytecode representation. + to the order of occurrence in the bytecode representation. 2. Including loop header and body information. This would facilitate detection of intervals and natural loops. Modified: llvm/trunk/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt (original) +++ llvm/trunk/docs/HistoricalNotes/2001-02-06-TypeNotationDebateResp4.txt Fri Apr 15 00:18:47 2011 @@ -39,7 +39,7 @@ Very true. If you're implementing an object oriented language, however, remember that you have to do all the pointer to member function stuff -yourself.... so everytime you invoke a virtual method one is involved +yourself.... so every time you invoke a virtual method one is involved (instead of having C++ hide it for you behind "syntactic sugar"). > And the old array syntax: Modified: llvm/trunk/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt (original) +++ llvm/trunk/docs/HistoricalNotes/2001-02-09-AdveCommentsResponse.txt Fri Apr 15 00:18:47 2011 @@ -18,7 +18,7 @@ Very true. We should discuss this more, but my reasoning is more of a consistency argument. There are VERY few instructions that can have all -of the types eliminated, and doing so when available unnecesarily makes +of the types eliminated, and doing so when available unnecessarily makes the language more difficult to handle. Especially when you see 'int %this' and 'bool %that' all over the place, I think it would be disorienting to see: @@ -44,7 +44,7 @@ No. This was something I was debating for a while, and didn't really feel strongly about either way. It is common to switch on other types in HLL's -(for example signed int's are particually common), but in this case, all +(for example signed int's are particularly common), but in this case, all that will be added is an additional 'cast' instruction. I removed that from the spec. @@ -160,7 +160,7 @@ > I agree that we need a static data space. Otherwise, emulating global > data gets unnecessarily complex. -Definately. Also a later item though. :) +Definitely. Also a later item though. :) > We once talked about adding a symbolic thread-id field to each > .. Modified: llvm/trunk/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt (original) +++ llvm/trunk/docs/HistoricalNotes/2001-06-01-GCCOptimizations2.txt Fri Apr 15 00:18:47 2011 @@ -42,7 +42,7 @@ > optimization (step 16 in your list). Do you have a breakdown of that? Not really. The irritating part of GCC is that it mixes it all up and -doesn't have a clean seperation of concerns. A lot of the "back end +doesn't have a clean separation of concerns. A lot of the "back end optimization" happens right along with other data optimizations (ie, CSE of machine specific things). Modified: llvm/trunk/docs/HistoricalNotes/2002-05-12-InstListChange.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/HistoricalNotes/2002-05-12-InstListChange.txt?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/HistoricalNotes/2002-05-12-InstListChange.txt (original) +++ llvm/trunk/docs/HistoricalNotes/2002-05-12-InstListChange.txt Fri Apr 15 00:18:47 2011 @@ -17,7 +17,7 @@ linear search of the basic block the instruction is contained in... just to insert an instruction before another instruction, or to delete an instruction! This complicates algorithms that should be very simple (like -simple constant propogation), because they aren't actually sparse anymore, +simple constant propagation), because they aren't actually sparse anymore, they have to traverse basic blocks to remove constant propogated instructions. Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Fri Apr 15 00:18:47 2011 @@ -2369,11 +2369,11 @@ terminator instruction if the terminator instruction has multiple successors and the instruction is always executed when control transfers to one of the successors, and - may not be executed when control is transfered to another.
    • + may not be executed when control is transferred to another.
    • Additionally, an instruction also control-depends on a terminator instruction if the set of instructions it otherwise depends on would be - different if the terminator had transfered control to a different + different if the terminator had transferred control to a different successor.
    • Dependence is transitive.
    • Modified: llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp (original) +++ llvm/trunk/examples/ExceptionDemo/ExceptionDemo.cpp Fri Apr 15 00:18:47 2011 @@ -1577,7 +1577,7 @@ typedef void (*OurExceptionThrowFunctType) (int32_t typeToThrow); /// This is a test harness which runs test by executing generated -/// function with a type info type to throw. Harness wraps the excecution +/// 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. /// This demo program expects this to be a JIT instance for demo Modified: llvm/trunk/include/llvm-c/Disassembler.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Disassembler.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm-c/Disassembler.h (original) +++ llvm/trunk/include/llvm-c/Disassembler.h Fri Apr 15 00:18:47 2011 @@ -31,7 +31,7 @@ * the call back in the DisInfo parameter. The instruction containing operand * is at the PC parameter. For some instruction sets, there can be more than * one operand with symbolic information. To determine the symbolic operand - * infomation for each operand, the bytes for the specific operand in the + * information for each operand, the bytes for the specific operand in the * instruction are specified by the Offset parameter and its byte widith is the * size parameter. For instructions sets with fixed widths and one symbolic * operand per instruction, the Offset parameter will be zero and Size parameter @@ -109,7 +109,7 @@ * Create a disassembler for the TripleName. Symbolic disassembly is supported * by passing a block of information in the DisInfo parameter and specifing the * TagType and call back functions as described above. These can all be passed - * as NULL. If successfull this returns a disassembler context if not it + * as NULL. If successful this returns a disassembler context if not it * returns NULL. */ extern LLVMDisasmContextRef @@ -127,7 +127,7 @@ /** * Disassmble a single instruction using the disassembler context specified in - * the parameter DC. The bytes of the instuction are specified in the parameter + * the parameter DC. The bytes of the instruction are specified in the parameter * Bytes, and contains at least BytesSize number of bytes. The instruction is * at the address specified by the PC parameter. If a valid instruction can be * disassembled its string is returned indirectly in OutString which whos size Modified: llvm/trunk/include/llvm-c/lto.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/lto.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm-c/lto.h (original) +++ llvm/trunk/include/llvm-c/lto.h Fri Apr 15 00:18:47 2011 @@ -72,7 +72,7 @@ /** - * Returns the last error string or NULL if last operation was sucessful. + * Returns the last error string or NULL if last operation was successful. */ extern const char* lto_get_error_message(void); @@ -263,7 +263,7 @@ /** * Generates code for all added modules into one native object file. - * On sucess returns a pointer to a generated mach-o/ELF buffer and + * On success returns a pointer to a generated mach-o/ELF buffer and * length set to the buffer size. The buffer is owned by the * lto_code_gen_t and will be freed when lto_codegen_dispose() * is called, or lto_codegen_compile() is called again. Modified: llvm/trunk/include/llvm/ADT/StringExtras.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/StringExtras.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/StringExtras.h (original) +++ llvm/trunk/include/llvm/ADT/StringExtras.h Fri Apr 15 00:18:47 2011 @@ -153,7 +153,7 @@ SmallVectorImpl &OutFragments, StringRef Delimiters = " \t\n\v\f\r"); -/// HashString - Hash funtion for strings. +/// HashString - Hash function for strings. /// /// This is the Bernstein hash function. // Modified: llvm/trunk/include/llvm/ADT/ilist.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ilist.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/ADT/ilist.h (original) +++ llvm/trunk/include/llvm/ADT/ilist.h Fri Apr 15 00:18:47 2011 @@ -289,7 +289,7 @@ //===----------------------------------------------------------------------===// // /// iplist - The subset of list functionality that can safely be used on nodes -/// of polymorphic types, i.e. a heterogenous list with a common base class that +/// of polymorphic types, i.e. a heterogeneous list with a common base class that /// holds the next/prev pointers. The only state of the list itself is a single /// pointer to the head of the list. /// Modified: llvm/trunk/include/llvm/Analysis/InlineCost.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/InlineCost.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/InlineCost.h (original) +++ llvm/trunk/include/llvm/Analysis/InlineCost.h Fri Apr 15 00:18:47 2011 @@ -43,7 +43,7 @@ /// InlineCost - Represent the cost of inlining a function. This /// supports special values for functions which should "always" or /// "never" be inlined. Otherwise, the cost represents a unitless - /// amount; smaller values increase the likelyhood of the function + /// amount; smaller values increase the likelihood of the function /// being inlined. class InlineCost { enum Kind { Modified: llvm/trunk/include/llvm/Analysis/RegionInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/RegionInfo.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/RegionInfo.h (original) +++ llvm/trunk/include/llvm/Analysis/RegionInfo.h Fri Apr 15 00:18:47 2011 @@ -146,7 +146,7 @@ /// two connections to the remaining graph. It can be used to analyze or /// optimize parts of the control flow graph. /// -/// A simple Region is connected to the remaing graph by just two +/// A simple Region is connected to the remaining graph by just two /// edges. One edge entering the Region and another one leaving the Region. /// /// An extended Region (or just Region) is a subgraph that can be @@ -443,7 +443,7 @@ /// @brief Move all direct child nodes of this Region to another Region. /// - /// @param To The Region the child nodes will be transfered to. + /// @param To The Region the child nodes will be transferred to. void transferChildrenTo(Region *To); /// @brief Verify if the region is a correct region. Modified: llvm/trunk/include/llvm/Analysis/RegionIterator.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/RegionIterator.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/RegionIterator.h (original) +++ llvm/trunk/include/llvm/Analysis/RegionIterator.h Fri Apr 15 00:18:47 2011 @@ -20,7 +20,7 @@ namespace llvm { //===----------------------------------------------------------------------===// -/// @brief Hierachical RegionNode successor iterator. +/// @brief Hierarchical RegionNode successor iterator. /// /// This iterator iterates over all successors of a RegionNode. /// Modified: llvm/trunk/include/llvm/Analysis/RegionPass.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/RegionPass.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/RegionPass.h (original) +++ llvm/trunk/include/llvm/Analysis/RegionPass.h Fri Apr 15 00:18:47 2011 @@ -54,7 +54,7 @@ /// @brief Get a pass to print the LLVM IR in the region. /// /// @param O The ouput stream to print the Region. - /// @param Banner The banner to seperate different printed passes. + /// @param Banner The banner to separate different printed passes. /// /// @return The pass to print the LLVM IR in the region. Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const; Modified: llvm/trunk/include/llvm/Bitcode/Archive.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/Archive.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/Bitcode/Archive.h (original) +++ llvm/trunk/include/llvm/Bitcode/Archive.h Fri Apr 15 00:18:47 2011 @@ -435,7 +435,7 @@ /// to determine just enough information to create an ArchiveMember object /// which is then inserted into the Archive object's ilist at the location /// given by \p where. - /// @returns true if an error occured, false otherwise + /// @returns true if an error occurred, false otherwise /// @brief Add a file to the archive. bool addFileBefore( const sys::Path& filename, ///< The file to be added Modified: llvm/trunk/include/llvm/CodeGen/ISDOpcodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ISDOpcodes.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ISDOpcodes.h (original) +++ llvm/trunk/include/llvm/CodeGen/ISDOpcodes.h Fri Apr 15 00:18:47 2011 @@ -219,7 +219,7 @@ // RESULT, BOOL = [SU]ADDO(LHS, RHS) - Overflow-aware nodes for addition. // These nodes take two operands: the normal LHS and RHS to the add. They // produce two results: the normal result of the add, and a boolean that - // indicates if an overflow occured (*not* a flag, because it may be stored + // indicates if an overflow occurred (*not* a flag, because it may be stored // to memory, etc.). If the type of the boolean is not i1 then the high // bits conform to getBooleanContents. // These nodes are generated from the llvm.[su]add.with.overflow intrinsics. Modified: llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h (original) +++ llvm/trunk/include/llvm/CodeGen/JITCodeEmitter.h Fri Apr 15 00:18:47 2011 @@ -36,7 +36,7 @@ class Function; /// JITCodeEmitter - This class defines two sorts of methods: those for -/// emitting the actual bytes of machine code, and those for emitting auxillary +/// emitting the actual bytes of machine code, and those for emitting auxiliary /// structures, such as jump tables, relocations, etc. /// /// Emission of machine code is complicated by the fact that we don't (in Modified: llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h (original) +++ llvm/trunk/include/llvm/CodeGen/MachineCodeEmitter.h Fri Apr 15 00:18:47 2011 @@ -34,7 +34,7 @@ class MCSymbol; /// MachineCodeEmitter - This class defines two sorts of methods: those for -/// emitting the actual bytes of machine code, and those for emitting auxillary +/// emitting the actual bytes of machine code, and those for emitting auxiliary /// structures, such as jump tables, relocations, etc. /// /// Emission of machine code is complicated by the fact that we don't (in @@ -54,7 +54,7 @@ /// allocated for this code buffer. uint8_t *BufferBegin, *BufferEnd; /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting - /// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If + /// code. This is guaranteed to be in the range [BufferBegin,BufferEnd]. If /// this pointer is at BufferEnd, it will never move due to code emission, and /// all code emission requests will be ignored (this is the buffer overflow /// condition). Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Fri Apr 15 00:18:47 2011 @@ -692,11 +692,11 @@ /// will create a cycle. bool WillCreateCycle(SUnit *SU, SUnit *TargetSU); - /// AddPred - Updates the topological ordering to accomodate an edge + /// AddPred - Updates the topological ordering to accommodate an edge /// to be added from SUnit X to SUnit Y. void AddPred(SUnit *Y, SUnit *X); - /// RemovePred - Updates the topological ordering to accomodate an + /// RemovePred - Updates the topological ordering to accommodate an /// an edge to be removed from the specified node N from the predecessors /// of the current node M. void RemovePred(SUnit *M, SUnit *N); Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Fri Apr 15 00:18:47 2011 @@ -829,7 +829,7 @@ /// These functions only replace all existing uses. It's possible that as /// these replacements are being performed, CSE may cause the From node /// to be given new uses. These new uses of From are left in place, and - /// not automatically transfered to To. + /// not automatically transferred to To. /// void ReplaceAllUsesWith(SDValue From, SDValue Op, DAGUpdateListener *UpdateListener = 0); Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGISel.h Fri Apr 15 00:18:47 2011 @@ -258,7 +258,7 @@ } virtual SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) { - assert(0 && "Tblgen shoudl generate this!"); + assert(0 && "Tblgen should generate this!"); return SDValue(); } Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original) +++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Fri Apr 15 00:18:47 2011 @@ -838,7 +838,7 @@ /// HandleSDNode - This class is used to form a handle around another node that -/// is persistant and is updated across invocations of replaceAllUsesWith on its +/// is persistent and is updated across invocations of replaceAllUsesWith on its /// operand. This node should be directly created by end-users and not added to /// the AllNodes list. class HandleSDNode : public SDNode { Modified: llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h (original) +++ llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h Fri Apr 15 00:18:47 2011 @@ -94,7 +94,7 @@ /// const MCSection *TLSBSSSection; // Defaults to ".tbss". - /// TLSTLVSection - Section for thread local structure infomation. + /// TLSTLVSection - Section for thread local structure information. /// Contains the source code name of the variable, visibility and a pointer /// to the initial value (.tdata or .tbss). const MCSection *TLSTLVSection; // Defaults to ".tlv". Modified: llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h (original) +++ llvm/trunk/include/llvm/ExecutionEngine/ExecutionEngine.h Fri Apr 15 00:18:47 2011 @@ -185,7 +185,7 @@ /// \param GVsWithCode - Allocating globals with code breaks /// freeMachineCodeForFunction and is probably unsafe and bad for performance. /// However, we have clients who depend on this behavior, so we must support - /// it. Eventually, when we're willing to break some backwards compatability, + /// it. Eventually, when we're willing to break some backwards compatibility, /// this flag should be flipped to false, so that by default /// freeMachineCodeForFunction works. static ExecutionEngine *create(Module *M, Modified: llvm/trunk/include/llvm/GlobalVariable.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/GlobalVariable.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/GlobalVariable.h (original) +++ llvm/trunk/include/llvm/GlobalVariable.h Fri Apr 15 00:18:47 2011 @@ -12,7 +12,7 @@ // // Global variables are constant pointers that refer to hunks of space that are // allocated by either the VM, or by the linker in a static compiler. A global -// variable may have an intial value, which is copied into the executables .data +// variable may have an initial value, which is copied into the executables .data // area. Global Constants are required to have initializers. // //===----------------------------------------------------------------------===// Modified: llvm/trunk/include/llvm/Instructions.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instructions.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/Instructions.h (original) +++ llvm/trunk/include/llvm/Instructions.h Fri Apr 15 00:18:47 2011 @@ -584,7 +584,7 @@ /// @brief Represent an integer comparison operator. class ICmpInst: public CmpInst { protected: - /// @brief Clone an indentical ICmpInst + /// @brief Clone an identical ICmpInst virtual ICmpInst *clone_impl() const; public: /// @brief Constructor with insert-before-instruction semantics. @@ -735,7 +735,7 @@ /// @brief Represents a floating point comparison operator. class FCmpInst: public CmpInst { protected: - /// @brief Clone an indentical FCmpInst + /// @brief Clone an identical FCmpInst virtual FCmpInst *clone_impl() const; public: /// @brief Constructor with insert-before-instruction semantics. Modified: llvm/trunk/include/llvm/MC/MCAsmLayout.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAsmLayout.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCAsmLayout.h (original) +++ llvm/trunk/include/llvm/MC/MCAsmLayout.h Fri Apr 15 00:18:47 2011 @@ -36,8 +36,8 @@ /// List of sections in layout order. llvm::SmallVector SectionOrder; - /// The last fragment which was layed out, or 0 if nothing has been layed - /// out. Fragments are always layed out in order, so all fragments with a + /// The last fragment which was laid out, or 0 if nothing has been laid + /// out. Fragments are always laid out in order, so all fragments with a /// lower ordinal will be up to date. mutable DenseMap LastValidFragment; @@ -58,7 +58,7 @@ void Invalidate(MCFragment *F); /// \brief Perform layout for a single fragment, assuming that the previous - /// fragment has already been layed out correctly, and the parent section has + /// fragment has already been laid out correctly, and the parent section has /// been initialized. void LayoutFragment(MCFragment *Fragment); Modified: llvm/trunk/include/llvm/MC/MCAssembler.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAssembler.h?rev=129558&r1=129557&r2=129558&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCAssembler.h (ori