From atrick at apple.com Mon Aug 8 00:47:02 2011 From: atrick at apple.com (Andrew Trick) Date: Sun, 07 Aug 2011 22:47:02 -0700 Subject: [llvm-commits] [llvm] r137013 - in /llvm/trunk: lib/Analysis/ScalarEvolution.cpp lib/Transforms/Scalar/IndVarSimplify.cpp test/Transforms/IndVarSimplify/iv-fold.ll In-Reply-To: <4E3DADAF.5060109@mxc.ca> References: <20110806070037.4DEC02A6C12C@llvm.org> <4E3DADAF.5060109@mxc.ca> Message-ID: <738FE80B-9C4B-4577-83F5-B7160E175D7A@apple.com> On Aug 6, 2011, at 2:10 PM, Nick Lewycky wrote: > Andrew Trick wrote: >> Author: atrick >> Date: Sat Aug 6 02:00:37 2011 >> New Revision: 137013 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=137013&view=rev >> Log: >> Made SCEV's UDiv expressions more canonical. When dividing a >> recurrence, the initial values low bits can sometimes be ignored. >> >> To take advantage of this, added FoldIVUser to IndVarSimplify to fold >> an IV operand into a udiv/lshr if the operator doesn't affect the >> result. >> >> -indvars -disable-iv-rewrite now transforms >> >> i = phi i4 >> i1 = i0 + 1 >> idx = i1>> (2 or more) >> i4 = i + 4 >> >> into >> >> i = phi i4 >> idx = i0>> ... >> i4 = i + 4 > > Clever! Is this something that instcombine or something else would not have gotten anyways? ValueTracking can match simple loop phis. That allows InstCombine to handle obvious cases. But InstCombine no longer runs immediately after loop opts, which can expose these redundancies. I think Chris would like loop opts to clean up after themselves. And I think it makes sense to apply induction variable simplification after any loop opt that effectively creates a new loop. I'll try to land a patch tomorrow that does it after partial unroll. Also, more generally I think that optimizations that need to know about loop recurrence should make use of ScalarEvolution. Fix problems, make improvements in one place. > Is there any hope of applying the same trick to sdivs? SCEV only understands udiv. Though I'm not sure off hand why it couldn't be done. Andy >> >> Added: >> llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll >> Modified: >> llvm/trunk/lib/Analysis/ScalarEvolution.cpp >> llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp >> >> Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=137013&r1=137012&r2=137013&view=diff >> ============================================================================== >> --- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original) >> +++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Sat Aug 6 02:00:37 2011 >> @@ -2051,12 +2051,13 @@ >> ++MaxShiftAmt; >> IntegerType *ExtTy = >> IntegerType::get(getContext(), getTypeSizeInBits(Ty) + MaxShiftAmt); >> - // {X,+,N}/C --> {X/C,+,N/C} if safe and N/C can be folded. >> if (const SCEVAddRecExpr *AR = dyn_cast(LHS)) >> if (const SCEVConstant *Step = >> - dyn_cast(AR->getStepRecurrence(*this))) >> - if (!Step->getValue()->getValue() >> - .urem(RHSC->getValue()->getValue())&& >> + dyn_cast(AR->getStepRecurrence(*this))) { >> + // {X,+,N}/C --> {X/C,+,N/C} if safe and N/C can be folded. >> + const APInt&StepInt = Step->getValue()->getValue(); >> + const APInt&DivInt = RHSC->getValue()->getValue(); >> + if (!StepInt.urem(DivInt)&& >> getZeroExtendExpr(AR, ExtTy) == >> getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy), >> getZeroExtendExpr(Step, ExtTy), >> @@ -2067,6 +2068,22 @@ >> return getAddRecExpr(Operands, AR->getLoop(), >> SCEV::FlagNW); >> } >> + /// Get a canonical UDivExpr for a recurrence. >> + /// {X,+,N}/C => {Y,+,N}/C where Y=X-(X%N). Safe when C%N=0. > > "//" not "///" so that this isn't a doxy-comment. > > Nick > >> + // We can currently only fold X%N if X is constant. >> + const SCEVConstant *StartC = dyn_cast(AR->getStart()); >> + if (StartC&& !DivInt.urem(StepInt)&& >> + getZeroExtendExpr(AR, ExtTy) == >> + getAddRecExpr(getZeroExtendExpr(AR->getStart(), ExtTy), >> + getZeroExtendExpr(Step, ExtTy), >> + AR->getLoop(), SCEV::FlagAnyWrap)) { >> + const APInt&StartInt = StartC->getValue()->getValue(); >> + const APInt&StartRem = StartInt.urem(StepInt); >> + if (StartRem != 0) >> + LHS = getAddRecExpr(getConstant(StartInt - StartRem), Step, >> + AR->getLoop(), SCEV::FlagNW); >> + } >> + } >> // (A*B)/C --> A*(B/C) if safe and B/C can be folded. >> if (const SCEVMulExpr *M = dyn_cast(LHS)) { >> SmallVector Operands; >> >> Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=137013&r1=137012&r2=137013&view=diff >> ============================================================================== >> --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original) >> +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Sat Aug 6 02:00:37 2011 >> @@ -70,6 +70,7 @@ >> STATISTIC(NumReplaced , "Number of exit values replaced"); >> STATISTIC(NumLFTR , "Number of loop exit tests replaced"); >> STATISTIC(NumElimIdentity, "Number of IV identities eliminated"); >> +STATISTIC(NumElimOperand, "Number of IV operands folded into a use"); >> STATISTIC(NumElimExt , "Number of IV sign/zero extends eliminated"); >> STATISTIC(NumElimRem , "Number of IV remainder operations eliminated"); >> STATISTIC(NumElimCmp , "Number of IV comparisons eliminated"); >> @@ -142,6 +143,8 @@ >> Value *IVOperand, >> bool IsSigned); >> >> + bool FoldIVUser(Instruction *UseInst, Instruction *IVOperand); >> + >> void SimplifyCongruentIVs(Loop *L); >> >> void RewriteIVExpressions(Loop *L, SCEVExpander&Rewriter); >> @@ -1298,6 +1301,66 @@ >> return true; >> } >> >> +/// FoldIVUser - Fold an IV operand into its use. This removes increments of an >> +/// aligned IV when used by a instruction that ignores the low bits. >> +bool IndVarSimplify::FoldIVUser(Instruction *UseInst, Instruction *IVOperand) { >> + Value *IVSrc = 0; >> + unsigned OperIdx = 0; >> + const SCEV *FoldedExpr = 0; >> + switch (UseInst->getOpcode()) { >> + default: >> + return false; >> + case Instruction::UDiv: >> + case Instruction::LShr: >> + // We're only interested in the case where we know something about >> + // the numerator and have a constant denominator. >> + if (IVOperand != UseInst->getOperand(OperIdx) || >> + !isa(UseInst->getOperand(1))) >> + return false; >> + >> + // Attempt to fold a binary operator with constant operand. >> + // e.g. ((I + 1)>> 2) => I>> 2 >> + if (IVOperand->getNumOperands() != 2 || >> + !isa(IVOperand->getOperand(1))) >> + return false; >> + >> + IVSrc = IVOperand->getOperand(0); >> + // IVSrc must be the (SCEVable) IV, since the other operand is const. >> + assert(SE->isSCEVable(IVSrc->getType())&& "Expect SCEVable IV operand"); >> + >> + ConstantInt *D = cast(UseInst->getOperand(1)); >> + if (UseInst->getOpcode() == Instruction::LShr) { >> + // Get a constant for the divisor. See createSCEV. >> + uint32_t BitWidth = cast(UseInst->getType())->getBitWidth(); >> + if (D->getValue().uge(BitWidth)) >> + return false; >> + >> + D = ConstantInt::get(UseInst->getContext(), >> + APInt(BitWidth, 1).shl(D->getZExtValue())); >> + } >> + FoldedExpr = SE->getUDivExpr(SE->getSCEV(IVSrc), SE->getSCEV(D)); >> + } >> + // We have something that might fold it's operand. Compare SCEVs. >> + if (!SE->isSCEVable(UseInst->getType())) >> + return false; >> + >> + // Bypass the operand if SCEV can prove it has no effect. >> + if (SE->getSCEV(UseInst) != FoldedExpr) >> + return false; >> + >> + DEBUG(dbgs()<< "INDVARS: Eliminated IV operand: "<< *IVOperand >> +<< " -> "<< *UseInst<< '\n'); >> + >> + UseInst->setOperand(OperIdx, IVSrc); >> + assert(SE->getSCEV(UseInst) == FoldedExpr&& "bad SCEV with folded oper"); >> + >> + ++NumElimOperand; >> + Changed = true; >> + if (IVOperand->use_empty()) >> + DeadInsts.push_back(IVOperand); >> + return true; >> +} >> + >> /// pushIVUsers - Add all uses of Def to the current IV's worklist. >> /// >> static void pushIVUsers( >> @@ -1394,6 +1457,8 @@ >> // Bypass back edges to avoid extra work. >> if (UseOper.first == CurrIV) continue; >> >> + FoldIVUser(UseOper.first, UseOper.second); >> + >> if (EliminateIVUser(UseOper.first, UseOper.second)) { >> pushIVUsers(UseOper.second, Simplified, SimpleIVUsers); >> continue; >> >> Added: llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll?rev=137013&view=auto >> ============================================================================== >> --- llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll (added) >> +++ llvm/trunk/test/Transforms/IndVarSimplify/iv-fold.ll Sat Aug 6 02:00:37 2011 >> @@ -0,0 +1,56 @@ >> +; RUN: opt< %s -indvars -disable-iv-rewrite -S | FileCheck %s >> + >> +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n:32:64" >> + >> +; Indvars should be able to fold IV increments into shr when low bits are zero. >> +; >> +; CHECK: @foldIncShr >> +; CHECK: shr.1 = lshr i32 %0, 5 >> +define i32 @foldIncShr(i32* %bitmap, i32 %bit_addr, i32 %nbits) nounwind { >> +entry: >> + br label %while.body >> + >> +while.body: >> + %0 = phi i32 [ 0, %entry ], [ %inc.2, %while.body ] >> + %shr = lshr i32 %0, 5 >> + %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr >> + %tmp6 = load i32* %arrayidx, align 4 >> + %inc.1 = add i32 %0, 1 >> + %shr.1 = lshr i32 %inc.1, 5 >> + %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1 >> + %tmp6.1 = load i32* %arrayidx.1, align 4 >> + %inc.2 = add i32 %inc.1, 1 >> + %exitcond.3 = icmp eq i32 %inc.2, 128 >> + br i1 %exitcond.3, label %while.end, label %while.body >> + >> +while.end: >> + %r = add i32 %tmp6, %tmp6.1 >> + ret i32 %r >> +} >> + >> +; Invdars should not fold an increment into shr unless 2^shiftBits is >> +; a multiple of the recurrence step. >> +; >> +; CHECK: @noFoldIncShr >> +; CHECK: shr.1 = lshr i32 %inc.1, 5 >> +define i32 @noFoldIncShr(i32* %bitmap, i32 %bit_addr, i32 %nbits) nounwind { >> +entry: >> + br label %while.body >> + >> +while.body: >> + %0 = phi i32 [ 0, %entry ], [ %inc.3, %while.body ] >> + %shr = lshr i32 %0, 5 >> + %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr >> + %tmp6 = load i32* %arrayidx, align 4 >> + %inc.1 = add i32 %0, 1 >> + %shr.1 = lshr i32 %inc.1, 5 >> + %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1 >> + %tmp6.1 = load i32* %arrayidx.1, align 4 >> + %inc.3 = add i32 %inc.1, 2 >> + %exitcond.3 = icmp eq i32 %inc.3, 96 >> + br i1 %exitcond.3, label %while.end, label %while.body >> + >> +while.end: >> + %r = add i32 %tmp6, %tmp6.1 >> + ret i32 %r >> +} >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits >> > From clattner at apple.com Mon Aug 8 00:57:49 2011 From: clattner at apple.com (Chris Lattner) Date: Sun, 07 Aug 2011 22:57:49 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> Message-ID: <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> On Aug 7, 2011, at 7:38 PM, Bill Wendling wrote: > Ping? Sorry for the delay. It looks like you haven't updated the patch to match LangRef to know that clauses can't have multiple values. This makes it very hard to usefully review the patch, but here are some thoughts that are independent of that: +++ include/llvm/Instructions.h (working copy) +class LandingPadInst : public Instruction { + /// IsCleanup - True if the landingpad instruction is also a cleanup. + bool IsCleanup; This should be stored in "SubClassData" like the isVolatile bit on loads and stores are. Please move the Create functions and constructors out of line. LandingPadInst is overcomplicated (e.g. struct Index) by the grammar that you're implementing that isn't documented. @@ -2617,6 +2736,10 @@ Op<-1>() = reinterpret_cast(B); } + // getLandingPad - Get the landingpad instruction from the landing pad block + // (the unwind destination). + LandingPadInst *getLandingPad() const; Please use /// comments so doxygen picks it up. Please rename this to getLandingPadInst llvm::BasicBlock should probably get an "isLandingPad()" and getLandingPadInst() helper methods, which are isa<(getFirstNonPHI()) (and dyn_cast). +++ include/llvm-c/Core.h (working copy) +typedef enum { + LLVMCatch, /**< A catch clause */ + LLVMFilter /**< A filter clause */ +} LLVMLandingPadClauseTy; Like LLVMRealPredicate, you should mangle the enum name into the enumerators. In Verifier: @@ -1361,7 +1373,7 @@ Assert1(Ordering == Acquire || Ordering == Release || Ordering == AcquireRelease || Ordering == SequentiallyConsistent, "fence instructions may only have " - " acquire, release, acq_rel, or seq_cst ordering.", &FI); + "acquire, release, acq_rel, or seq_cst ordering.", &FI); visitInstruction(FI); } Please commit this separately. + // The landingpad instruction must be the first non-PHI instruction in the + // block. + BasicBlock::iterator I = BB->begin(), E = BB->end(); + while (I != E && isa(I)) + ++I; + Assert1(I != E && isa(I) && I == LPI, + "LandingPadInst not the first non-PHI instruction in the block.", + &LPI); Use "LPI->getParent()->getLandingPadInst() == &LPI) Unrelated, but noticed while reviewing the patch, the grammar in LangRef.html is actually: = landingpad personality + = landingpad personality cleanup * Please fix it. Please resend with the grammar fix. I can't review most of this patch without that, and the ripples through the rest of the code, fixed. Thanks Bill! -Chris From rjmccall at apple.com Mon Aug 8 01:34:40 2011 From: rjmccall at apple.com (John McCall) Date: Sun, 07 Aug 2011 23:34:40 -0700 Subject: [llvm-commits] [llvm] r136790 - /llvm/trunk/docs/LangRef.html In-Reply-To: <20110803171707.552712A6C12C@llvm.org> References: <20110803171707.552712A6C12C@llvm.org> Message-ID: On Aug 3, 2011, at 10:17 AM, Bill Wendling wrote: > Author: void > Date: Wed Aug 3 12:17:06 2011 > New Revision: 136790 > > URL: http://llvm.org/viewvc/llvm-project?rev=136790&view=rev > Log: > Explain how clauses are applied. > > 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=136790&r1=136789&r2=136790&view=diff > ============================================================================== > --- llvm/trunk/docs/LangRef.html (original) > +++ llvm/trunk/docs/LangRef.html Wed Aug 3 12:17:06 2011 > @@ -6025,6 +6025,10 @@ > calling conventions, how the personality function results are represented in > LLVM IR is target specific.

> > +

The clauses are applied in order from top to bottom. If two > + landingpad instructions are merged together through inlining, the > + clauses from the calling function are prepended to the list of clauses.

> + Appended, surely. John. From rjmccall at apple.com Mon Aug 8 01:37:37 2011 From: rjmccall at apple.com (John McCall) Date: Sun, 07 Aug 2011 23:37:37 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> Message-ID: On Aug 7, 2011, at 10:57 PM, Chris Lattner wrote: > On Aug 7, 2011, at 7:38 PM, Bill Wendling wrote: > >> Ping? > > Sorry for the delay. It looks like you haven't updated the patch to match LangRef to know that clauses can't have multiple values. Wait, I could've sworn I reviewed that. 'filter' has to take 0 to N values; there's really no way around it, because nesting is disjunctive and we need conjunction. The only way we can do it with exactly one value per clause is to require that value to be a ConstantArray ? although, come to think of it, that's doable, if ugly. John. From clattner at apple.com Mon Aug 8 01:58:10 2011 From: clattner at apple.com (Chris Lattner) Date: Sun, 07 Aug 2011 23:58:10 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> Message-ID: On Aug 7, 2011, at 11:37 PM, John McCall wrote: > On Aug 7, 2011, at 10:57 PM, Chris Lattner wrote: >> On Aug 7, 2011, at 7:38 PM, Bill Wendling wrote: >> >>> Ping? >> >> Sorry for the delay. It looks like you haven't updated the patch to match LangRef to know that clauses can't have multiple values. > > Wait, I could've sworn I reviewed that. 'filter' has to take 0 to N values; there's really no way around it, because nesting is disjunctive and we need conjunction. The only way we can do it with exactly one value per clause is to require that value to be a ConstantArray ? although, come to think of it, that's doable, if ugly. You're saying that "filter a, b, c" is not the same as "filter a, filter b, filter c"? -Chris From rjmccall at apple.com Mon Aug 8 02:03:46 2011 From: rjmccall at apple.com (John McCall) Date: Mon, 08 Aug 2011 00:03:46 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> Message-ID: <6FD46D53-5B96-4D3A-8BC0-A5C4EC8563B9@apple.com> On Aug 7, 2011, at 11:58 PM, Chris Lattner wrote: > > On Aug 7, 2011, at 11:37 PM, John McCall wrote: > >> On Aug 7, 2011, at 10:57 PM, Chris Lattner wrote: >>> On Aug 7, 2011, at 7:38 PM, Bill Wendling wrote: >>> >>>> Ping? >>> >>> Sorry for the delay. It looks like you haven't updated the patch to match LangRef to know that clauses can't have multiple values. >> >> Wait, I could've sworn I reviewed that. 'filter' has to take 0 to N values; there's really no way around it, because nesting is disjunctive and we need conjunction. The only way we can do it with exactly one value per clause is to require that value to be a ConstantArray ? although, come to think of it, that's doable, if ugly. > > You're saying that "filter a, b, c" is not the same as "filter a, filter b, filter c"? Correct. The first filters out exceptions they aren't a and aren't b and aren't c, and the second trips on exceptions if they aren't a, or they aren't b, or they aren't c. Combining filters is also impossible because of the semantics of std::unexpected, which is allowed to change the exception type to satisfy the filter. John. From isanbard at gmail.com Mon Aug 8 02:58:58 2011 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 08 Aug 2011 07:58:58 -0000 Subject: [llvm-commits] [llvm] r137040 - /llvm/trunk/docs/LangRef.html Message-ID: <20110808075859.418B72A6C12D@llvm.org> Author: void Date: Mon Aug 8 02:58:58 2011 New Revision: 137040 URL: http://llvm.org/viewvc/llvm-project?rev=137040&view=rev Log: Fix typo found by John. 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=137040&r1=137039&r2=137040&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Mon Aug 8 02:58:58 2011 @@ -6027,7 +6027,7 @@

The clauses are applied in order from top to bottom. If two landingpad instructions are merged together through inlining, the - clauses from the calling function are prepended to the list of clauses.

+ clauses from the calling function are appended to the list of clauses.

The landingpad instruction has several restrictions:

From wendling at apple.com Mon Aug 8 02:59:18 2011 From: wendling at apple.com (Bill Wendling) Date: Mon, 08 Aug 2011 00:59:18 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> Message-ID: <5964EA4C-F64F-4C8E-9124-2FEDAAAB43F1@apple.com> On Aug 7, 2011, at 10:57 PM, Chris Lattner wrote: > > On Aug 7, 2011, at 7:38 PM, Bill Wendling wrote: > >> Ping? > > Sorry for the delay. It looks like you haven't updated the patch to match LangRef to know that clauses can't have multiple values. This makes it very hard to usefully review the patch, but here are some thoughts that are independent of that: > I did make those changes. As John pointed out, the 'filter' clause must allow for multiple filter types on one filter. The 'catch' clauses though should be single catch type only. -bw From isanbard at gmail.com Mon Aug 8 03:00:24 2011 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 8 Aug 2011 01:00:24 -0700 Subject: [llvm-commits] [llvm] r136790 - /llvm/trunk/docs/LangRef.html In-Reply-To: References: <20110803171707.552712A6C12C@llvm.org> Message-ID: <2F38450D-486B-4752-B581-3BA012E610F5@gmail.com> Doh! Fixed. -bw On Aug 7, 2011, at 11:34 PM, John McCall wrote: > On Aug 3, 2011, at 10:17 AM, Bill Wendling wrote: >> Author: void >> Date: Wed Aug 3 12:17:06 2011 >> New Revision: 136790 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=136790&view=rev >> Log: >> Explain how clauses are applied. >> >> 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=136790&r1=136789&r2=136790&view=diff >> ============================================================================== >> --- llvm/trunk/docs/LangRef.html (original) >> +++ llvm/trunk/docs/LangRef.html Wed Aug 3 12:17:06 2011 >> @@ -6025,6 +6025,10 @@ >> calling conventions, how the personality function results are represented in >> LLVM IR is target specific.

>> >> +

The clauses are applied in order from top to bottom. If two >> + landingpad instructions are merged together through inlining, the >> + clauses from the calling function are prepended to the list of clauses.

>> + > > Appended, surely. > > John. > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From isanbard at gmail.com Mon Aug 8 03:02:48 2011 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 08 Aug 2011 08:02:48 -0000 Subject: [llvm-commits] [llvm] r137041 - /llvm/trunk/lib/VMCore/Verifier.cpp Message-ID: <20110808080248.A765D2A6C12D@llvm.org> Author: void Date: Mon Aug 8 03:02:48 2011 New Revision: 137041 URL: http://llvm.org/viewvc/llvm-project?rev=137041&view=rev Log: Remove unnecessary space. Modified: llvm/trunk/lib/VMCore/Verifier.cpp Modified: llvm/trunk/lib/VMCore/Verifier.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=137041&r1=137040&r2=137041&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Verifier.cpp (original) +++ llvm/trunk/lib/VMCore/Verifier.cpp Mon Aug 8 03:02:48 2011 @@ -1361,7 +1361,7 @@ Assert1(Ordering == Acquire || Ordering == Release || Ordering == AcquireRelease || Ordering == SequentiallyConsistent, "fence instructions may only have " - " acquire, release, acq_rel, or seq_cst ordering.", &FI); + "acquire, release, acq_rel, or seq_cst ordering.", &FI); visitInstruction(FI); } From isanbard at gmail.com Mon Aug 8 03:06:05 2011 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 08 Aug 2011 08:06:05 -0000 Subject: [llvm-commits] [llvm] r137042 - /llvm/trunk/docs/LangRef.html Message-ID: <20110808080605.C2B402A6C12D@llvm.org> Author: void Date: Mon Aug 8 03:06:05 2011 New Revision: 137042 URL: http://llvm.org/viewvc/llvm-project?rev=137042&view=rev Log: Clean up the grammar for the landingpad instruction. 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=137042&r1=137041&r2=137042&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Mon Aug 8 03:06:05 2011 @@ -5992,9 +5992,11 @@
Syntax:
-  <resultval> = landingpad <somety> personality <type> <pers_fn> cleanup? <clause>+
+  <resultval> = landingpad <somety> personality <type> <pers_fn> <clause>+
+  <resultval> = landingpad <somety> personality <type> <pers_fn> cleanup <clause>*
+
   <clause> := catch <type> <value>
-  <clause> := filter <type> <value>
+  <clause> := filter <type> <value> {, <type> <value>}*
 
Overview:
From wendling at apple.com Mon Aug 8 03:13:03 2011 From: wendling at apple.com (Bill Wendling) Date: Mon, 08 Aug 2011 01:13:03 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: <6FD46D53-5B96-4D3A-8BC0-A5C4EC8563B9@apple.com> References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> <6FD46D53-5B96-4D3A-8BC0-A5C4EC8563B9@apple.com> Message-ID: <4C521554-B45D-41FC-8A22-6A1EAFDC36C2@apple.com> On Aug 8, 2011, at 12:03 AM, John McCall wrote: > Correct. The first filters out exceptions they aren't a and aren't b and aren't c, and the second trips on exceptions if they aren't a, or they aren't b, or they aren't c. > > Combining filters is also impossible because of the semantics of std::unexpected, which is allowed to change the exception type to satisfy the filter. > Why does this prohibit combining filters? Or, I guess more to the point, what do you mean by combining the filters? Are you suggesting that we cannot inline a function with an exception specification into another function with a different exception specification? -bw From rjmccall at apple.com Mon Aug 8 03:25:53 2011 From: rjmccall at apple.com (John McCall) Date: Mon, 08 Aug 2011 01:25:53 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: <4C521554-B45D-41FC-8A22-6A1EAFDC36C2@apple.com> References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> <6FD46D53-5B96-4D3A-8BC0-A5C4EC8563B9@apple.com> <4C521554-B45D-41FC-8A22-6A1EAFDC36C2@apple.com> Message-ID: <7B4D9FCE-0960-4F0A-8513-8C71F567CC10@apple.com> On Aug 8, 2011, at 1:13 AM, Bill Wendling wrote: > On Aug 8, 2011, at 12:03 AM, John McCall wrote: >> Correct. The first filters out exceptions they aren't a and aren't b and aren't c, and the second trips on exceptions if they aren't a, or they aren't b, or they aren't c. >> >> Combining filters is also impossible because of the semantics of std::unexpected, which is allowed to change the exception type to satisfy the filter. >> > Why does this prohibit combining filters? Or, I guess more to the point, what do you mean by combining the filters? Are you suggesting that we cannot inline a function with an exception specification into another function with a different exception specification? No, that's not what I meant. What I mean is that, conceptually, filters always apply in the order that an exception would propagate through them, and there's a fallback mechanism for changing exception types, so while there are rules you can use to optimize filters, they're somewhat complex. Basically, it is legal to turn this: filter a, b filter a, b into this: filter a, b And it is legal to turn this: filter a filter a, b into this: filter a But it is not legal to turn this: filter a, b filter a into this: filter a Fortunately, you can just ignore all that for now. :) Just make sure that the representation is somehow capable of listing any number of exception types per filter, including zero. John. From rjmccall at apple.com Mon Aug 8 03:34:23 2011 From: rjmccall at apple.com (John McCall) Date: Mon, 08 Aug 2011 01:34:23 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: <6FD46D53-5B96-4D3A-8BC0-A5C4EC8563B9@apple.com> References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> <6FD46D53-5B96-4D3A-8BC0-A5C4EC8563B9@apple.com> Message-ID: On Aug 8, 2011, at 12:03 AM, John McCall wrote: > > On Aug 7, 2011, at 11:58 PM, Chris Lattner wrote: > >> >> On Aug 7, 2011, at 11:37 PM, John McCall wrote: >> >>> On Aug 7, 2011, at 10:57 PM, Chris Lattner wrote: >>>> On Aug 7, 2011, at 7:38 PM, Bill Wendling wrote: >>>> >>>>> Ping? >>>> >>>> Sorry for the delay. It looks like you haven't updated the patch to match LangRef to know that clauses can't have multiple values. >>> >>> Wait, I could've sworn I reviewed that. 'filter' has to take 0 to N values; there's really no way around it, because nesting is disjunctive and we need conjunction. The only way we can do it with exactly one value per clause is to require that value to be a ConstantArray ? although, come to think of it, that's doable, if ugly. >> >> You're saying that "filter a, b, c" is not the same as "filter a, filter b, filter c"? > > Correct. The first filters out exceptions they aren't a and aren't b and aren't c, and the second trips on exceptions if they aren't a, or they aren't b, or they aren't c. Sorry, grammar fail. An exception specificaiton which lists three types will result in a call to std::unexpected() if an exception is thrown which cannot be caught by any of those types. Three nested exception specifications listing one type each will result in a call to std::unexpected() if an exception is thrown which cannot be caught by each of those types individually. Additionally, std::unexpected() can substitute a new exception as long as it passes the tripped exception specification, so the semantics do require individually processing exception specifications unless the outer spec is at least as "forgiving" as the inner spec. John. From raghesh.a at gmail.com Mon Aug 8 03:34:16 2011 From: raghesh.a at gmail.com (Raghesh Aloor) Date: Mon, 08 Aug 2011 08:34:16 -0000 Subject: [llvm-commits] [polly] r137043 - /polly/trunk/lib/CodeGeneration.cpp Message-ID: <20110808083416.36FE42A6C12C@llvm.org> Author: raghesh Date: Mon Aug 8 03:34:16 2011 New Revision: 137043 URL: http://llvm.org/viewvc/llvm-project?rev=137043&view=rev Log: Memaccess: Some style changes Modified: polly/trunk/lib/CodeGeneration.cpp Modified: polly/trunk/lib/CodeGeneration.cpp URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CodeGeneration.cpp?rev=137043&r1=137042&r2=137043&view=diff ============================================================================== --- polly/trunk/lib/CodeGeneration.cpp (original) +++ polly/trunk/lib/CodeGeneration.cpp Mon Aug 8 03:34:16 2011 @@ -174,32 +174,32 @@ return Builder.CreateShuffleVector(vector, vector, splatVector); } - Value* getOperand(const Value *OldOperand, ValueMapT &BBMap, + Value* getOperand(const Value *oldOperand, ValueMapT &BBMap, ValueMapT *VectorMap = 0) { - const Instruction *OpInst = dyn_cast(OldOperand); + const Instruction *OpInst = dyn_cast(oldOperand); if (!OpInst) - return const_cast(OldOperand); + return const_cast(oldOperand); - if (VectorMap && VectorMap->count(OldOperand)) - return (*VectorMap)[OldOperand]; + if (VectorMap && VectorMap->count(oldOperand)) + return (*VectorMap)[oldOperand]; // IVS and Parameters. - if (VMap.count(OldOperand)) { - Value *NewOperand = VMap[OldOperand]; + if (VMap.count(oldOperand)) { + Value *NewOperand = VMap[oldOperand]; // Insert a cast if types are different - if (OldOperand->getType()->getScalarSizeInBits() + if (oldOperand->getType()->getScalarSizeInBits() < NewOperand->getType()->getScalarSizeInBits()) NewOperand = Builder.CreateTruncOrBitCast(NewOperand, - OldOperand->getType()); + oldOperand->getType()); return NewOperand; } // Instructions calculated in the current BB. - if (BBMap.count(OldOperand)) { - return BBMap[OldOperand]; + if (BBMap.count(oldOperand)) { + return BBMap[oldOperand]; } // Ignore instructions that are referencing ops in the old BB. These @@ -208,7 +208,7 @@ if (getRegion().contains(OpInst->getParent())) return NULL; - return const_cast(OldOperand); + return const_cast(oldOperand); } Type *getVectorPtrTy(const Value *V, int vectorWidth) { @@ -317,7 +317,7 @@ /// @brief Get the new operand address according to the changed access in /// JSCOP file. Value *getNewAccessOperand(isl_map *newAccessRelation, Value *baseAddr, - const Value *OldOperand, ValueMapT &BBMap) { + const Value *oldOperand, ValueMapT &BBMap) { unsigned accessIdx = 0; Value *newOperand = Builder.CreateStructGEP(baseAddr, accessIdx, "p_newarrayidx_"); @@ -327,14 +327,14 @@ /// @brief Generate the operand address Value *generateLocationAccessed(const Instruction *Inst, const Value *pointer, ValueMapT &BBMap ) { - MemoryAccess &Access = statement.getAccessFor(Inst); - isl_map *newAccessRelation = Access.getNewAccessFunction(); + MemoryAccess &access = statement.getAccessFor(Inst); + isl_map *newAccessRelation = access.getNewAccessFunction(); if (!newAccessRelation) { Value *newPointer = getOperand(pointer, BBMap); return newPointer; } - Value *baseAddr = const_cast(Access.getBaseAddr()); + Value *baseAddr = const_cast(access.getBaseAddr()); Value *newPointer = getNewAccessOperand(newAccessRelation, baseAddr, pointer, BBMap); return newPointer; From baldrick at free.fr Mon Aug 8 03:44:48 2011 From: baldrick at free.fr (Duncan Sands) Date: Mon, 08 Aug 2011 08:44:48 -0000 Subject: [llvm-commits] [dragonegg] r137044 - /dragonegg/trunk/src/Backend.cpp Message-ID: <20110808084448.88CEA2A6C12C@llvm.org> Author: baldrick Date: Mon Aug 8 03:44:48 2011 New Revision: 137044 URL: http://llvm.org/viewvc/llvm-project?rev=137044&view=rev Log: Output file-scope assembler at the same time as global variables and aliases. At this point the only remaining abuse of the LTO passes is for outputting same-body aliases. Modified: dragonegg/trunk/src/Backend.cpp Modified: dragonegg/trunk/src/Backend.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Backend.cpp?rev=137044&r1=137043&r2=137044&view=diff ============================================================================== --- dragonegg/trunk/src/Backend.cpp (original) +++ dragonegg/trunk/src/Backend.cpp Mon Aug 8 03:44:48 2011 @@ -1539,17 +1539,6 @@ 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_aliases - Convert same-body aliases and file-scope asm into LLVM IR. static void emit_aliases(cgraph_node_set set #if (GCC_MINOR > 5) @@ -1577,13 +1566,6 @@ 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_aliases - IPA pass that converts same-body aliases and file-scope @@ -1659,13 +1641,24 @@ }; -/// llvm_emit_globals - Output GCC global variables and aliases to the LLVM IR. +/// llvm_emit_globals - Output GCC global variables, aliases and asm's to the +/// LLVM IR. static void llvm_emit_globals(void * /*gcc_data*/, void * /*user_data*/) { if (errorcount || sorrycount) return; // Do not process broken code. InitializeBackend(); + // Emit any file-scope asms. + for (struct cgraph_asm_node *can = cgraph_asm_nodes; can; can = can->next) { + tree string = can->asm_str; + if (TREE_CODE(string) == ADDR_EXPR) + string = TREE_OPERAND(string, 0); + TheModule->appendModuleInlineAsm(TREE_STRING_POINTER (string)); + } + // Remove the asms so gcc doesn't waste time outputting them. + cgraph_asm_nodes = NULL; + // Output all externally visible global variables as well as any internal // variables explicitly marked with the 'used' attribute. Other internal // variables and aliases are output when their user is, or discarded if @@ -2215,7 +2208,7 @@ register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info); #endif - // Output GCC global variables and aliases to the LLVM IR. This needs to be + // Output GCC global variables, aliases and asm's to the IR. This needs to be // done before the compilation unit is finished, since aliases are no longer // available then. On the other hand it seems wise to output them after the // IPA passes have run, since these are the passes that modify globals. From wendling at apple.com Mon Aug 8 03:52:27 2011 From: wendling at apple.com (Bill Wendling) Date: Mon, 08 Aug 2011 01:52:27 -0700 Subject: [llvm-commits] [PATCH] Newest LandingPad Patch In-Reply-To: <7B4D9FCE-0960-4F0A-8513-8C71F567CC10@apple.com> References: <99EBDC10-2197-4007-9850-4E2E65720C59@apple.com> <5358F1C8-7FD5-420C-AFF6-C0EC2811060D@apple.com> <6FD46D53-5B96-4D3A-8BC0-A5C4EC8563B9@apple.com> <4C521554-B45D-41FC-8A22-6A1EAFDC36C2@apple.com> <7B4D9FCE-0960-4F0A-8513-8C71F567CC10@apple.com> Message-ID: On Aug 8, 2011, at 1:25 AM, John McCall wrote: > On Aug 8, 2011, at 1:13 AM, Bill Wendling wrote: >> On Aug 8, 2011, at 12:03 AM, John McCall wrote: >>> Correct. The first filters out exceptions they aren't a and aren't b and aren't c, and the second trips on exceptions if they aren't a, or they aren't b, or they aren't c. >>> >>> Combining filters is also impossible because of the semantics of std::unexpected, which is allowed to change the exception type to satisfy the filter. >>> >> Why does this prohibit combining filters? Or, I guess more to the point, what do you mean by combining the filters? Are you suggesting that we cannot inline a function with an exception specification into another function with a different exception specification? > > No, that's not what I meant. What I mean is that, conceptually, filters always apply in the order that an exception would propagate through them, and there's a fallback mechanism for changing exception types, so while there are rules you can use to optimize filters, they're somewhat complex. > > Basically, it is legal to turn this: > filter a, b > filter a, b > into this: > filter a, b > > And it is legal to turn this: > filter a > filter a, b > into this: > filter a > > But it is not legal to turn this: > filter a, b > filter a > into this: > filter a > > Fortunately, you can just ignore all that for now. :) Just make sure that the representation is somehow capable of listing any number of exception types per filter, including zero. > Okay, grand! Thanks for the clarification. I was hoping it wasn't what I wrote, because that would be brutal. :-) -bw From baldrick at free.fr Mon Aug 8 04:46:21 2011 From: baldrick at free.fr (Duncan Sands) Date: Mon, 08 Aug 2011 11:46:21 +0200 Subject: [llvm-commits] Newest LandingPad Patch In-Reply-To: <1D33093C-44C0-43BE-B5CD-9CF8F0907484@apple.com> References: <1D33093C-44C0-43BE-B5CD-9CF8F0907484@apple.com> Message-ID: <4E3FB06D.6080405@free.fr> Hi Bill, > + /// getPersonalityFn - Get the personality function associated with this > + /// landing pad. > + const Function *getPersonalityFn() const { > + return cast(getOperand(0)); > + } I think you should change this to return cast(getOperand(0)->stripPointerCasts()); That's because you can't avoid sometimes getting a bitcast here. For example, suppose you have two modules that both declare __gxx_personality_v0 and use it in a landingpad instruction, but they use a slightly different prototype for __gxx_personality_v0. When you link the bitcode from the two modules together, the prototype difference will be resolved by replacing one __gxx_personality_v0 with a bitcast of the other. This results in landingpad instructions with a bitcast of a function for the personality function operand, and then... boom! Likewise, you can't assume that typeinfos are global variables, you have to allow for the possibility that they are bitcasts of global variables. I didn't notice any place that assumes they are global variables, so hopefully everything is OK for them. > --- lib/VMCore/AsmWriter.cpp (revision 136744) > +++ lib/VMCore/AsmWriter.cpp (working copy) > @@ -1735,6 +1735,31 @@ > writeOperand(I.getOperand(1), true); > for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i) > Out << ", " << *i; > + } else if (const LandingPadInst *LPI = dyn_cast(&I)) { > + Out << ' '; > + TypePrinter.print(I.getType(), Out); > + Out << " personality "; > + writeOperand(LPI->getPersonalityFn(), true); Out << '\n'; If the personality operand was a bitcast then here you would fail to output the bitcast. You should probably just write out operand 0. > @@ -3513,6 +3514,57 @@ > return AteExtraComma ? InstExtraComma : InstNormal; > } > > +/// ParseLandingPad > +/// ::= 'landingpad' Type 'personality' TypeAndValue 'cleanup'? Clause+ > +/// Clause > +/// ::= 'catch' TypeAndValue > +/// ::= 'filter' TypeAndValue* > +bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { > + Type *Ty = 0; LocTy TyLoc; > + Value *PersFn; LocTy PersFnLoc; > + LocTy LPLoc = Lex.getLoc(); > + > + if (ParseType(Ty, TyLoc) || > + ParseToken(lltok::kw_personality, "expected 'personality'") || > + ParseTypeAndValue(PersFn, PersFnLoc, PFS)) > + return true; > + > + LandingPadInst *LP = LandingPadInst::Create(Ty, cast(PersFn), 0); Here you will blow up if the personality function is a bitcast. Also, you should probably write the parsing in such a way as to output a helpful message rather than crashing (as cast would) if someone provides invalid input. > + LP->setCleanup(EatIfPresent(lltok::kw_cleanup)); > + > + while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ > + if (Lex.getKind() == lltok::kw_catch) { > + ParseToken(lltok::kw_catch, "expected 'catch'"); > + > + Value *V; LocTy VLoc; > + if (ParseTypeAndValue(V, VLoc, PFS)) { > + delete LP; > + return true; > + } > + LP->addClause(LandingPadInst::Catch, cast(V)); This should probably output an error rather than crashing if V is not a constant. > + } else { > + ParseToken(lltok::kw_filter, "expected 'filter'"); > + SmallVector Filters; > + > + if (Lex.getKind() == lltok::Type) { > + do { > + Value *V; LocTy VLoc; > + if (ParseTypeAndValue(V, VLoc, PFS)) { > + delete LP; > + return true; > + } > + Filters.push_back(cast(V)); This should probably output an error rather than crashing if V is not a constant. > --- lib/Bitcode/Reader/BitcodeReader.cpp (revision 136744) > +++ lib/Bitcode/Reader/BitcodeReader.cpp (working copy) > @@ -2543,6 +2543,45 @@ > break; > } > > + case bitc::FUNC_CODE_INST_LANDINGPAD: { > + // LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?] > + unsigned Idx = 0; > + if (Record.size() < 4) > + return Error("Invalid LANDINGPAD record"); > + Type *Ty = getTypeByID(Record[Idx++]); > + if (!Ty) return Error("Invalid LANDINGPAD record"); > + Value *PersFn = 0; > + if (getValueTypePair(Record, Idx, NextValueNo, PersFn)) > + return Error("Invalid LANDINGPAD record"); > + > + bool IsCleanup = !!Record[Idx++]; > + unsigned NumClauses = Record[Idx++]; > + LandingPadInst *LP = LandingPadInst::Create(Ty, cast(PersFn), Kaboom if a bitcast of a function rather than a function. Here too you should probably try to output a message rather than crashing if you get some strange input. > Index: lib/Bitcode/Writer/BitcodeWriter.cpp > =================================================================== > --- lib/Bitcode/Writer/BitcodeWriter.cpp (revision 136744) > +++ lib/Bitcode/Writer/BitcodeWriter.cpp (working copy) > @@ -1166,6 +1166,26 @@ > break; > } > > + case Instruction::LandingPad: { > + const LandingPadInst &LP = cast(I); > + Code = bitc::FUNC_CODE_INST_LANDINGPAD; > + Vals.push_back(VE.getTypeID(LP.getType())); > + PushValueAndType(LP.getPersonalityFn(), InstID, Vals, VE); This would drop any bitcast on the personality function. Ciao, Duncan. From renato.golin at arm.com Mon Aug 8 04:58:24 2011 From: renato.golin at arm.com (Renato Golin) Date: Mon, 8 Aug 2011 10:58:24 +0100 Subject: [llvm-commits] [PATCH] ULEB FIXME in ARM back-end In-Reply-To: References: Message-ID: Ping? On 1 August 2011 13:20, Renato Golin wrote: > Hi all, > > I've been playing with a FIXME in the ARM back-end (to get more > acquainted) and one simple FIXME was an ULEB printing in the > AsmPrinter. > > According to the ARM EABI, both build attribute tag and value are > ULEBs and not chars as they were being emitted. Today, I don't know of > any attribute that would emit tags or values bigger than 127 but this > seamed like an easy start. > > The patch changes the emission of values to ULEB by storing all tags > and values in a typed list and emit later the right value, computing > the size as it goes. I've run all tests (including the build > attributes ones in ARM be) and it passes everything. > > There are three problems I see with this patch, but would like to know > from you what's the best way to solve them: > > ?1. It uses a local structure to hold both ULEB and String values in > order, but other MC structures will also emit ULEB in the near future > (we should make sure it does, at least), so this structure could > become a proper small class on a more visible place. > > ?2. It wastes memory since both number and string values are on every > item, but it's not possible to put StringRef in an union since > Stringref has non-trivial constructors. A solution is to use > polymorphism but that's too big for this tiny case. If we decide to > expose the class higher up, then it makes sense to do so. > > ?3. It's calculating the ULEB size in place, where other routines in > LLVM can do that (but are not accessible from this class). A > refactoring is in need to expose that routine to the intended > audience. > > If neither of those problems are relevant, or if they're just minor, > we can put other FIXMEs around. Otherwise, I'm open to suggestions. > > best, > --renato > -- cheers, --renato From baldrick at free.fr Mon Aug 8 07:23:30 2011 From: baldrick at free.fr (Duncan Sands) Date: Mon, 08 Aug 2011 12:23:30 -0000 Subject: [llvm-commits] [dragonegg] r137045 - in /dragonegg/trunk: include/dragonegg/cache.h src/Types.cpp src/cache.c Message-ID: <20110808122330.0D75F2A6C12C@llvm.org> Author: baldrick Date: Mon Aug 8 07:23:29 2011 New Revision: 137045 URL: http://llvm.org/viewvc/llvm-project?rev=137045&view=rev Log: Remove llvm_has_cached since it has no advantages over checking if llvm_get_cached returns a non-null value. Modified: dragonegg/trunk/include/dragonegg/cache.h dragonegg/trunk/src/Types.cpp dragonegg/trunk/src/cache.c Modified: dragonegg/trunk/include/dragonegg/cache.h URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/cache.h?rev=137045&r1=137044&r2=137045&view=diff ============================================================================== --- dragonegg/trunk/include/dragonegg/cache.h (original) +++ dragonegg/trunk/include/dragonegg/cache.h Mon Aug 8 07:23:29 2011 @@ -28,10 +28,6 @@ union tree_node; -/* llvm_has_cached - Returns whether a value has been associated with the - tree. */ -extern int llvm_has_cached(union tree_node *tree); - /* llvm_get_cached - Returns the value associated with the tree, or NULL. */ extern const void *llvm_get_cached(union tree_node *tree); Modified: dragonegg/trunk/src/Types.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Types.cpp?rev=137045&r1=137044&r2=137045&view=diff ============================================================================== --- dragonegg/trunk/src/Types.cpp (original) +++ dragonegg/trunk/src/Types.cpp Mon Aug 8 07:23:29 2011 @@ -338,8 +338,7 @@ } static bool llvm_has_type(tree Tr) { - assert(TYPE_P(Tr) && "Expected a gcc type!"); - return llvm_has_cached(Tr); + return llvm_get_type(Tr) != 0; } Modified: dragonegg/trunk/src/cache.c URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/cache.c?rev=137045&r1=137044&r2=137045&view=diff ============================================================================== --- dragonegg/trunk/src/cache.c (original) +++ dragonegg/trunk/src/cache.c Mon Aug 8 07:23:29 2011 @@ -55,18 +55,6 @@ #include "dragonegg/gt-cache-4.5.h" #endif -/* 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; From baldrick at free.fr Mon Aug 8 10:15:14 2011 From: baldrick at free.fr (Duncan Sands) Date: Mon, 08 Aug 2011 17:15:14 +0200 Subject: [llvm-commits] [Patch] DwarfEHPrepare for New EH In-Reply-To: References: Message-ID: <4E3FFD82.8090701@free.fr> Hi Bill, > This patch implements the small amount which needs to be done by the DwarfEHPrepare pass. What it does is takes the 'resume' instruction and converts it into a call to _Unwind_Resume. The SjLj changes will be done in the SjLj lowering pass. why do this in DwarfEHPrepare (which should be zapped in the long run I guess)? Shouldn't it be lowered in SelectionDAGBuilder like other instructions are? Also, it should probably be turned into a RESUME SDag Node, so that different targets can be different things with it (eg: ARM doesn't want _Unwind_Resume IIRC). Ciao, Duncan. From rafael.espindola at gmail.com Mon Aug 8 10:18:20 2011 From: rafael.espindola at gmail.com (=?ISO-8859-1?Q?Rafael_=C1vila_de_Esp=EDndola?=) Date: Mon, 08 Aug 2011 11:18:20 -0400 Subject: [llvm-commits] [llvm] r136954 - /llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp In-Reply-To: <20110805005303.677762A6C12C@llvm.org> References: <20110805005303.677762A6C12C@llvm.org> Message-ID: <4E3FFE3C.3090704@gmail.com> On 08/04/2011 08:53 PM, Jason W Kim wrote: > Author: jasonwkim > Date: Thu Aug 4 19:53:03 2011 > New Revision: 136954 > > URL: http://llvm.org/viewvc/llvm-project?rev=136954&view=rev > Log: > Fix http://llvm.org/bugs/show_bug.cgi?id=10583\n - test for 1 and 2 byte fixups to be added Thanks > Modified: > llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp > > Modified: llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp?rev=136954&r1=136953&r2=136954&view=diff > ============================================================================== > --- llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp (original) > +++ llvm/trunk/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp Thu Aug 4 19:53:03 2011 > @@ -94,21 +94,17 @@ > assert(Fixup.getOffset() + Size<= DataSize&& > "Invalid fixup offset!"); > > - // Check that the upper bits are either all 0 or all 1's > - switch (Size) { > - case 1: > - assert((isInt<8>(Value) || isUInt<8>(Value))&& > - "Value does not fit in a 1Byte Reloc"); > - break; > - case 2: > - assert((isInt<16>(Value) || isUInt<16>(Value))&& > - "Value does not fit in a 2Byte Reloc"); > - break; > - case 4: > - assert((isInt<32>(Value) || isUInt<32>(Value))&& > - "Value does not fit in a 4Byte Reloc"); > - break; > - } > + // Check that uppper bits are either all zeros or all ones. > + // Specifically ignore overflow/underflow as long as the leakage is > + // limited to the lower bits. This is to remain compatible with > + // other assemblers. > + > + const uint64_t Mask = ~0ULL; > + const uint64_t UpperV = (Value>> (Size * 8)); > + const uint64_t MaskF = (Mask>> (Size * 8)); > + assert(((Size == 8) || > + ((UpperV& MaskF) == 0ULL) || ((UpperV& MaskF) == MaskF))&& > + "Value does not fit in the Fixup field"); > > for (unsigned i = 0; i != Size; ++i) > Data[Fixup.getOffset() + i] = uint8_t(Value>> (i * 8)); > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From Micah.Villmow at amd.com Mon Aug 8 10:24:55 2011 From: Micah.Villmow at amd.com (Villmow, Micah) Date: Mon, 8 Aug 2011 10:24:55 -0500 Subject: [llvm-commits] [PATCH] Add Pattern ID Information In-Reply-To: <99124877-9AFB-42A0-8F86-60133AA0B9B7@apple.com> References: <0ea0e9376fbd37e5bfe8e726cd8e1820a2f951aa.1312408044.git.dag@cray.com> <89B29A49-519B-4B8D-A816-50793D3D2A5A@apple.com> <87oc05pae6.fsf@smith.obbligato.org> <89232ADE-1739-4151-9FA6-E3D7D8BC934F@2pi.dk> <871ux0puhr.fsf@smith.obbligato.org> <98EC6EBC-F059-4975-A12F-9BB5DCFB41EC@2pi.dk> <0A430C75-4EB9-41EC-9BA2-EC70BE7A1B60@2pi.dk> <99124877-9AFB-42A0-8F86-60133AA0B9B7@apple.com> Message-ID: > -----Original Message----- > From: Chris Lattner [mailto:clattner at apple.com] > Sent: Friday, August 05, 2011 5:30 PM > To: Jakob Stoklund Olesen > Cc: Villmow, Micah; Commit Messages and Patches for LLVM > Subject: Re: [llvm-commits] [PATCH] Add Pattern ID Information > > > On Aug 5, 2011, at 4:42 PM, Jakob Stoklund Olesen wrote: > > > > > On Aug 5, 2011, at 4:28 PM, Villmow, Micah wrote: > > > >>> You would be better off using an immediate operand to encode your > extra > >>> semantics. > >> [Villmow, Micah] That is not really feasible to add an extra operand > to > >> hundreds of instructions when there is already a location that store > the > >> 15 bits of information that is needed(8 in flags, 7 in > AsmPrinterFlags). > > > > You are of course free to do whatever you want in your own tree. I am > simply trying to steer you in a direction that will cause you less > grief when merging with trunk. > > Also, your argument is basically "we are knowingly do something that is > documented as a bad idea, because it is easier than fixing our code to > do the right thing". I'm not going to do it, but this makes me want to > go rip out asmprinter flags - it doesn't make me inclined to extend > them. > [Villmow, Micah] I'm not saying extend AsmPrinterFlags, I'm saying remove it and use the space that it was reserving to extend the 'Flags' field to 16 bits. I don't see this as the wrong approach as this is instruction information, not a new operand. I don't see a valid reason why I need to change my instructions by an extra operand just to work around an artificial limitation in LLVM. Having per instruction storage space is required to handle instructions that require information to be allocated dynamically and not at tablegen compile time. > -Chris From rafael.espindola at gmail.com Mon Aug 8 10:28:38 2011 From: rafael.espindola at gmail.com (=?ISO-8859-1?Q?Rafael_=C1vila_de_Esp=EDndola?=) Date: Mon, 08 Aug 2011 11:28:38 -0400 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> Message-ID: <4E4000A6.1070908@gmail.com> >> This assumes the operand is the low register of the pair, i.e. even. Is that guaranteed? > > No. > > We don't allocate even/odd pairs for 64-bit values. We don't even allocate consecutive registers. > > Without that constraint, I can't imagine a use for the 'H' modifier? True. I only tested with function arguments, so I missed this. Thanks for catching it. The attached patch handles only the R and Q constraints. Is it OK? > /jakob > Cheers, Rafael -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: arm-rq.patch Url: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/4b963865/attachment.pl From stoklund at 2pi.dk Mon Aug 8 10:59:39 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 08 Aug 2011 08:59:39 -0700 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: <4E4000A6.1070908@gmail.com> References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> <4E4000A6.1070908@gmail.com> Message-ID: <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> On Aug 8, 2011, at 8:28 AM, Rafael ?vila de Esp?ndola wrote: >>> This assumes the operand is the low register of the pair, i.e. even. Is that guaranteed? >> >> No. >> >> We don't allocate even/odd pairs for 64-bit values. We don't even allocate consecutive registers. >> >> Without that constraint, I can't imagine a use for the 'H' modifier? > > True. I only tested with function arguments, so I missed this. Thanks for catching it. > > The attached patch handles only the R and Q constraints. Is it OK? You are missing some error handling. You are accessing OpNum+1 without checking that it is part of the current asm operand. /jakob From aaron at aaronballman.com Mon Aug 8 08:10:48 2011 From: aaron at aaronballman.com (Aaron Ballman) Date: Mon, 8 Aug 2011 08:10:48 -0500 Subject: [llvm-commits] [PATCH] CrashRecoveryContext.cpp Win32 support Message-ID: Hello! I noticed there was a "fixme" listed in CrashRecoveryContext.cpp and that some Win32 support was needed. I believe this patch will solve the issue. I have tested it with Visual Studio 2010, and MinGW gcc 4.5.2 and the behavior is the same as what I get on OS X. I was unable to get the test suite to run in my environment (had all the prerequisites installed, followed the instructions on the site), so I've not been able to run this against the suite. One thing to note about this patch is that is only provides support for Windows XP and higher. Trying to support older versions of Windows is possible (Win2k and higher) but comes with more pitfalls (as noted in the comments). If you have any questions, please ask! ~Aaron -------------- next part -------------- A non-text attachment was scrubbed... Name: CrashRecoveryContext.diff Type: application/octet-stream Size: 5204 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/d1fbe81b/attachment-0001.obj From kristof.beyls at arm.com Mon Aug 8 08:54:56 2011 From: kristof.beyls at arm.com (Kristof Beyls) Date: Mon, 8 Aug 2011 14:54:56 +0100 Subject: [llvm-commits] [PATCH] Fix NOP encodings in ARM backend. Message-ID: <001001cc55d2$c1c4e020$454ea060$@beyls@arm.com> Hi, With the attached patch, I'm trying to fix a FIXME in the ARM backend. This patch fixes ARMAsmBackend::WriteNopData, so that it takes into account the version of the ARM architecture that is being targeted. For versions before ARMv6T2, there is no NOP instruction, and NOPs are encoded as MOV r0,r0 (in ARM mode) or MOV r8,r8 (in Thumb mode). For targets later than ARMv6T2, the encoding for the NOP instruction is created. I have a few questions about this patch: 1. To make sure that ARMAsmBackend::WriteNopData can figure out which ARM sub-target it compiles for, I had to adapt the Target::MCAsmBackendCtorTy to also pass on an MCSubtargetInfo argument. Is this the best way to get sub-target information to the ARMAsmBackend object? (this change results in a few function signature changes in the ARM, PowerPC, X86 and MBlaze backends). 2. It's hard to create test cases to test this properly, since I think that there is another bug in lib/MC/MCAssembler.cpp, where processing an alignment fragment results in calling ARMAsmBackend::WriteNopData, but without putting the ARMAsmBackend in the right ARM or Thumb state. Therefore, e.g. when processing an assembler file with .align directives in the middle of a Thumb code section, still ARM NOP encodings are generated instead of Thumb NOP encodings. Question 2a: Is it OK to write a FIXME to indicate this brokenness? Should I also file a bugzilla issue? Question 2b: Is it OK to leave that fix for a later, separate, patch? For that fix, it will be easier to create good test cases that will also test this patch. Thanks, Kristof PS. I'm cc-ing to the cfe-commits list because the change in Target::MCAsmBackendCtorTy requires 2 lines to change in Clang too, see attached file clang_arm_nop_encoding.patch. -------------- next part -------------- A non-text attachment was scrubbed... Name: llvm_arm_nop_encoding.patch Type: application/octet-stream Size: 15693 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/937ec169/attachment-0002.obj -------------- next part -------------- A non-text attachment was scrubbed... Name: clang_arm_nop_encoding.patch Type: application/octet-stream Size: 1154 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/937ec169/attachment-0003.obj From rafael.espindola at gmail.com Mon Aug 8 11:38:33 2011 From: rafael.espindola at gmail.com (=?ISO-8859-1?Q?Rafael_=C1vila_de_Esp=EDndola?=) Date: Mon, 08 Aug 2011 12:38:33 -0400 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> <4E4000A6.1070908@gmail.com> <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> Message-ID: <4E401109.1050203@gmail.com> > You are missing some error handling. You are accessing OpNum+1 > without checking that it is part of the current asm operand. The attached patch adds "RegOp >= MI->getNumOperands()" check. Is there a more specific check for asm operands? > /jakob > Thanks, Rafael -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: arm-rq.patch Url: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/6ac7c787/attachment.pl From stoklund at 2pi.dk Mon Aug 8 11:48:42 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 08 Aug 2011 09:48:42 -0700 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: <4E401109.1050203@gmail.com> References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> <4E4000A6.1070908@gmail.com> <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> <4E401109.1050203@gmail.com> Message-ID: On Aug 8, 2011, at 9:38 AM, Rafael ?vila de Esp?ndola wrote: > >> You are missing some error handling. You are accessing OpNum+1 >> without checking that it is part of the current asm operand. > > The attached patch adds "RegOp >= MI->getNumOperands()" check. Is there a more specific check for asm operands? Yes, each group of machine operands on an INLINEASM begin with an immediate describing the group. In this case, it is probably good enough to check that OpNum+1 exists and is a register. /jakob From renato.golin at arm.com Mon Aug 8 12:09:57 2011 From: renato.golin at arm.com (Renato Golin) Date: Mon, 08 Aug 2011 17:09:57 -0000 Subject: [llvm-commits] [www] r137048 - /www/trunk/devmtg/2011-09-16/index.html Message-ID: <20110808170957.82FDB2A6C12C@llvm.org> Author: rengolin Date: Mon Aug 8 12:09:57 2011 New Revision: 137048 URL: http://llvm.org/viewvc/llvm-project?rev=137048&view=rev Log: confirmed venue, schedule, time for euro-llvm 2011 Modified: www/trunk/devmtg/2011-09-16/index.html Modified: www/trunk/devmtg/2011-09-16/index.html URL: http://llvm.org/viewvc/llvm-project/www/trunk/devmtg/2011-09-16/index.html?rev=137048&r1=137047&r2=137048&view=diff ============================================================================== --- www/trunk/devmtg/2011-09-16/index.html (original) +++ www/trunk/devmtg/2011-09-16/index.html Mon Aug 8 12:09:57 2011 @@ -4,16 +4,16 @@
    -
  • What: The first European User Group Meeting. -
  • +
  • What: The first European User Group Meeting.
  • Why: To get acquainted, learn how LLVM is used, and exchange ideas.
  • -
  • When: On the afternoon of September 16th, 2011
  • -
  • Where: London, UK (venue to be defined yet) +
  • When: September 16th, 2011 from 12:00 ~ 19:30
  • +
  • Where: Hamilton House, Mabledon Place, London, UK, WC1H 9BD + (map)
-

SPONSORED BY: ARM Ltd.

+

SPONSORED BY: ARM Ltd.

This will be a half-day meeting for LLVM users to exchange ideas, expose new developments and generally strengthen the network of LLVM developers in and @@ -34,35 +34,128 @@

  • Current developments and the future of LLVM (MC, JIT, vectorisation, &c.)
  • -
    Organisation
    -

    We'll be discussing the organisation of the event on the main LLVM mailing list, and we welcome suggestions and help. The event will take place during the afternoon and we'll provide dinner and some beer at the end to complement the networking.

    -
    Registration:
    -

    Registration is via email (Euro-LLVM at arm.com), on a first-come-first-serve -basis, free of charge. Please, send your details (name, email, -company/institution). Attendance will be limited to about 60 people, -depending on the venue.

    - -
    Financial Support:
    - -

    At this time, we cannot be sure if there will be funding for active -contributors and students to attend the event. However, we are hopeful that -we will have company sponsorship to make this happen. Those who are funded -are required to present at the meeting and may have other requirements from -their sponsor (i.e. writing a blog post, etc).

    +

    We're still accepting registration via email (Euro-LLVM at arm.com), free of charge. +Please, send your details (name, email, company/institution). +Attendance will be limited to 60 people.

    If you need funding to attend the meeting, please tell us in your registration email (to Euro-LLVM at arm.com).

    -
    Agenda
    -

    TBD.

    +
    Tentative Agenda
    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    TimeMander HallSide Room #1Side Room #2
    + 12:00 + + Welcome and refreshments +
    + 13:00 + + Handling Multi-Versioning in LLVM: Code Tracking and Cloning
    + P. Clauss, A. Jimborean, V. Loechner +
      
    + 13:45 + + More Target Independent LLVM Bitcode
    + Jin-Gu Kang +
      
    + 14:30 + + Tea Break +Side sessionSide session
    + 15:15 + + Jet: A Language and Heterogeneous Compiler for Fluid Simulations
    + Dan Bailey +
      
    + 16:00 + + Status of the LLVM ARM back-end, Anton Korobeynikov +Implementing dynamic scopes in cling
    + Vassil Vassilev
     
    + 16:45 + + Lightning Talks +Side sessionSide session
    + 17:30 + + Tea Break +Side sessionSide session
    + 18:15 + + Dinner and wrap up +

    From renato.golin at arm.com Mon Aug 8 12:13:22 2011 From: renato.golin at arm.com (Renato Golin) Date: Mon, 08 Aug 2011 17:13:22 -0000 Subject: [llvm-commits] [www] r137049 - /www/trunk/devmtg/2011-09-16/index.html Message-ID: <20110808171322.42B4C2A6C12C@llvm.org> Author: rengolin Date: Mon Aug 8 12:13:22 2011 New Revision: 137049 URL: http://llvm.org/viewvc/llvm-project?rev=137049&view=rev Log: colour in last line, centered in header Modified: www/trunk/devmtg/2011-09-16/index.html Modified: www/trunk/devmtg/2011-09-16/index.html URL: http://llvm.org/viewvc/llvm-project/www/trunk/devmtg/2011-09-16/index.html?rev=137049&r1=137048&r2=137049&view=diff ============================================================================== --- www/trunk/devmtg/2011-09-16/index.html (original) +++ www/trunk/devmtg/2011-09-16/index.html Mon Aug 8 12:13:22 2011 @@ -53,7 +53,7 @@

    - + - + From stoklund at 2pi.dk Mon Aug 8 12:15:43 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 08 Aug 2011 17:15:43 -0000 Subject: [llvm-commits] [llvm] r137050 - in /llvm/trunk: lib/Target/X86/X86FloatingPoint.cpp test/CodeGen/X86/inline-asm-fpstack.ll Message-ID: <20110808171543.8623E2A6C12C@llvm.org> Author: stoklund Date: Mon Aug 8 12:15:43 2011 New Revision: 137050 URL: http://llvm.org/viewvc/llvm-project?rev=137050&view=rev Log: Don't clobber pending ST regs when FP regs are killed. X86FloatingPoint keeps track of pending ST registers for an upcoming inline asm instruction with fixed stack register constraints. It does this by remembering which FP register holds the value that should appear at a fixed stack position for the inline asm. When that FP register is killed before the inline asm, make sure to duplicate it to a scratch register, so the ST register still has a live FP reference. This could happen when the same FP register was copied to two ST registers, or when a spill instruction is inserted between the ST copy and the inline asm. This fixes PR10602. Modified: llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp llvm/trunk/test/CodeGen/X86/inline-asm-fpstack.ll Modified: llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp?rev=137050&r1=137049&r2=137050&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp (original) +++ llvm/trunk/lib/Target/X86/X86FloatingPoint.cpp Mon Aug 8 12:15:43 2011 @@ -260,6 +260,21 @@ BuildMI(*MBB, I, dl, TII->get(X86::LD_Frr)).addReg(STReg); } + /// duplicatePendingSTBeforeKill - The instruction at I is about to kill + /// RegNo. If any PendingST registers still need the RegNo value, duplicate + /// them to new scratch registers. + void duplicatePendingSTBeforeKill(unsigned RegNo, MachineInstr *I) { + for (unsigned i = 0; i != NumPendingSTs; ++i) { + if (PendingST[i] != RegNo) + continue; + unsigned SR = getScratchReg(); + DEBUG(dbgs() << "Duplicating pending ST" << i + << " in FP" << RegNo << " to FP" << SR << '\n'); + duplicateToTop(RegNo, SR, I); + PendingST[i] = SR; + } + } + /// popStackAfter - Pop the current value off of the top of the FP stack /// after the specified instruction. void popStackAfter(MachineBasicBlock::iterator &I); @@ -973,6 +988,9 @@ unsigned Reg = getFPReg(MI->getOperand(NumOps-1)); bool KillsSrc = MI->killsRegister(X86::FP0+Reg); + if (KillsSrc) + duplicatePendingSTBeforeKill(Reg, I); + // FISTP64m is strange because there isn't a non-popping versions. // If we have one _and_ we don't want to pop the operand, duplicate the value // on the stack instead of moving it. This ensure that popping the value is @@ -1036,6 +1054,7 @@ bool KillsSrc = MI->killsRegister(X86::FP0+Reg); if (KillsSrc) { + duplicatePendingSTBeforeKill(Reg, I); // If this is the last use of the source register, just make sure it's on // the top of the stack. moveToTop(Reg, I); @@ -1322,6 +1341,7 @@ // When the source is killed, allocate a scratch FP register. if (KillsSrc) { + duplicatePendingSTBeforeKill(SrcFP, I); unsigned Slot = getSlot(SrcFP); unsigned SR = getScratchReg(); PendingST[DstST] = SR; Modified: llvm/trunk/test/CodeGen/X86/inline-asm-fpstack.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inline-asm-fpstack.ll?rev=137050&r1=137049&r2=137050&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/inline-asm-fpstack.ll (original) +++ llvm/trunk/test/CodeGen/X86/inline-asm-fpstack.ll Mon Aug 8 12:15:43 2011 @@ -329,3 +329,14 @@ %asmresult = extractvalue %complex %0, 0 ret float %asmresult } + +; Pass the same value in two fixed stack slots. +; CHECK: PR10602 +; CHECK: flds LCPI +; CHECK: fld %st(0) +; CHECK: fcomi %st(1), %st(0) +define i32 @PR10602() nounwind ssp { +entry: + %0 = tail call i32 asm "fcomi $2, $1; pushf; pop $0", "=r,{st},{st(1)},~{dirflag},~{fpsr},~{flags}"(double 2.000000e+00, double 2.000000e+00) nounwind + ret i32 %0 +} From rafael.espindola at gmail.com Mon Aug 8 12:30:12 2011 From: rafael.espindola at gmail.com (=?ISO-8859-1?Q?Rafael_=C1vila_de_Esp=EDndola?=) Date: Mon, 08 Aug 2011 13:30:12 -0400 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> <4E4000A6.1070908@gmail.com> <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> <4E401109.1050203@gmail.com> Message-ID: <4E401D24.4060605@gmail.com> > Yes, each group of machine operands on an INLINEASM begin with an immediate describing the group. Cool. The attached patch uses InlineAsm::getNumOperandRegisters. is it ok. > In this case, it is probably good enough to check that OpNum+1 exists and is a register. The previous patch does that if you prefer it :-) > /jakob > Cheers, Rafael -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: arm-rq.patch Url: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/3e7a5b33/attachment.pl From echristo at apple.com Mon Aug 8 12:38:07 2011 From: echristo at apple.com (Eric Christopher) Date: Mon, 08 Aug 2011 10:38:07 -0700 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: <4E401D24.4060605@gmail.com> References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> <4E4000A6.1070908@gmail.com> <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> <4E401109.1050203@gmail.com> <4E401D24.4060605@gmail.com> Message-ID: Hi Rafael, On Aug 8, 2011, at 10:30 AM, Rafael ?vila de Esp?ndola wrote: > >> Yes, each group of machine operands on an INLINEASM begin with an immediate describing the group. > > Cool. The attached patch uses InlineAsm::getNumOperandRegisters. is it ok. > >> In this case, it is probably good enough to check that OpNum+1 exists and is a register. > > The previous patch does that if you prefer it :-) Sorry about the delay in responding, I've just returned from vacation. I have some concerns about this patch as is - basically I'm worried about subtle miscompiles based on how gcc does register allocation for multiple reg wide values versus how llvm does it. In the gcc case it will (as far as I know) assign consecutive registers for these sorts of values, but there's no guarantee that llvm will do this. This means that in the case of stm/ldm instructions with the 'Q' and 'R' modifiers that we'd get registers that weren't meant, leading to subtle problems that users would need to debug. When we get support for assigning values into consecutive registers this won't be a problem. What are your thoughts? -eric From dpatel at apple.com Mon Aug 8 13:22:10 2011 From: dpatel at apple.com (Devang Patel) Date: Mon, 08 Aug 2011 18:22:10 -0000 Subject: [llvm-commits] [llvm] r137056 - /llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Message-ID: <20110808182210.D37832A6C12C@llvm.org> Author: dpatel Date: Mon Aug 8 13:22:10 2011 New Revision: 137056 URL: http://llvm.org/viewvc/llvm-project?rev=137056&view=rev Log: Simplify by creating parent first. 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=137056&r1=137055&r2=137056&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp (original) +++ llvm/trunk/lib/CodeGen/AsmPrinter/DwarfDebug.cpp Mon Aug 8 13:22:10 2011 @@ -149,12 +149,14 @@ DbgScope(DbgScope *P, DIDescriptor D, const MDNode *I = 0) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(false), LastInsn(0), FirstInsn(0), - DFSIn(0), DFSOut(0), IndentLevel(0) {} + DFSIn(0), DFSOut(0), IndentLevel(0) { + if (Parent) + Parent->addScope(this); + } virtual ~DbgScope(); // Accessors. DbgScope *getParent() const { return Parent; } - void setParent(DbgScope *P) { Parent = P; } DIDescriptor getDesc() const { return Desc; } const MDNode *getInlinedAt() const { return InlinedAtLocation; } const MDNode *getScopeNode() const { return Desc; } @@ -421,11 +423,7 @@ DIDescriptor ParentDesc = DB.getContext(); Parent = getOrCreateAbstractScope(ParentDesc); } - AScope = new DbgScope(Parent, DIDescriptor(N), NULL); - - if (Parent) - Parent->addScope(AScope); AScope->setAbstractScope(); AbstractScopes[N] = AScope; if (DIDescriptor(N).isSubprogram()) @@ -1590,17 +1588,16 @@ /// getOrCreateRegularScope - Create regular DbgScope. DbgScope *DwarfDebug::getOrCreateRegularScope(MDNode *Scope) { DbgScope *WScope = DbgScopeMap.lookup(Scope); - if (WScope) + if (WScope) return WScope; - WScope = new DbgScope(NULL, DIDescriptor(Scope), NULL); + + DbgScope *Parent = NULL; + if (DIDescriptor(Scope).isLexicalBlock()) + Parent = getOrCreateDbgScope(DebugLoc::getFromDILexicalBlock(Scope)); + WScope = new DbgScope(Parent, DIDescriptor(Scope), NULL); DbgScopeMap.insert(std::make_pair(Scope, WScope)); - if (DIDescriptor(Scope).isLexicalBlock()) { - DbgScope *Parent = - getOrCreateDbgScope(DebugLoc::getFromDILexicalBlock(Scope)); - WScope->setParent(Parent); - Parent->addScope(WScope); - } else if (DIDescriptor(Scope).isSubprogram() - && DISubprogram(Scope).describes(Asm->MF->getFunction())) + if (!Parent && DIDescriptor(Scope).isSubprogram() + && DISubprogram(Scope).describes(Asm->MF->getFunction())) CurrentFnDbgScope = WScope; return WScope; @@ -1612,13 +1609,11 @@ if (InlinedScope) return InlinedScope; - InlinedScope = new DbgScope(NULL, DIDescriptor(Scope), InlinedAt); DebugLoc InlinedLoc = DebugLoc::getFromDILocation(InlinedAt); + InlinedScope = new DbgScope(getOrCreateDbgScope(InlinedLoc), + DIDescriptor(Scope), InlinedAt); InlinedDbgScopeMap[InlinedLoc] = InlinedScope; DbgScopeMap[InlinedAt] = InlinedScope; - DbgScope *Parent = getOrCreateDbgScope(InlinedLoc); - InlinedScope->setParent(Parent); - Parent->addScope(InlinedScope); return InlinedScope; } From benny.kra at googlemail.com Mon Aug 8 13:32:13 2011 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Mon, 08 Aug 2011 18:32:13 -0000 Subject: [llvm-commits] [llvm] r137057 - /llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Message-ID: <20110808183213.14C482A6C12C@llvm.org> Author: d0k Date: Mon Aug 8 13:32:12 2011 New Revision: 137057 URL: http://llvm.org/viewvc/llvm-project?rev=137057&view=rev Log: llvm-objdump: Use help of CFG to print assembly when --cfg is passed. This way we can avoid printing unreachable code (data). Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp?rev=137057&r1=137056&r2=137057&view=diff ============================================================================== --- llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp (original) +++ llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Mon Aug 8 13:32:12 2011 @@ -248,28 +248,57 @@ raw_ostream &DebugOut = nulls(); #endif - for (Index = Start; Index < End; Index += Size) { - MCInst Inst; - if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, DebugOut)) { - uint64_t addr; - if (error(i->getAddress(addr))) break; - outs() << format("%8x:\t", addr + Index); - DumpBytes(StringRef(Bytes.data() + Index, Size)); - IP->printInst(&Inst, outs()); - outs() << "\n"; - } else { - errs() << ToolName << ": warning: invalid instruction encoding\n"; - if (Size == 0) - Size = 1; // skip illegible bytes + if (!CFG) { + for (Index = Start; Index < End; Index += Size) { + MCInst Inst; + if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, + DebugOut)) { + uint64_t addr; + if (error(i->getAddress(addr))) break; + outs() << format("%8x:\t", addr + Index); + DumpBytes(StringRef(Bytes.data() + Index, Size)); + IP->printInst(&Inst, outs()); + outs() << "\n"; + } else { + errs() << ToolName << ": warning: invalid instruction encoding\n"; + if (Size == 0) + Size = 1; // skip illegible bytes + } } - } - if (CFG) { + } else { + // Create CFG and use it for disassembly. MCFunction f = MCFunction::createFunctionFromMC(Symbols[si].second, DisAsm.get(), memoryObject, Start, End, InstrInfo, DebugOut); + for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){ + bool hasPreds = false; + // Only print blocks that have predecessors. + // FIXME: Slow. + for (MCFunction::iterator pi = f.begin(), pe = f.end(); pi != pe; + ++pi) + if (pi->second.contains(&fi->second)) { + hasPreds = true; + break; + } + + if (!hasPreds && fi != f.begin()) + continue; + + for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie; + ++ii) { + uint64_t addr; + if (error(i->getAddress(addr))) break; + const MCDecodedInst &Inst = fi->second.getInsts()[ii]; + outs() << format("%8x:\t", addr + Inst.Address); + DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size)); + IP->printInst(&Inst.Inst, outs()); + outs() << '\n'; + } + } + // Start a new dot file. std::string Error; raw_fd_ostream Out((f.getName().str() + ".dot").c_str(), Error); From benny.kra at googlemail.com Mon Aug 8 13:41:34 2011 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Mon, 08 Aug 2011 18:41:34 -0000 Subject: [llvm-commits] [llvm] r137058 - /llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Message-ID: <20110808184134.92F742A6C12C@llvm.org> Author: d0k Date: Mon Aug 8 13:41:34 2011 New Revision: 137058 URL: http://llvm.org/viewvc/llvm-project?rev=137058&view=rev Log: llvm-objdump: disassembly enhancements - Indent simple loops - Print unreachable blocks as .byte directives Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp?rev=137058&r1=137057&r2=137058&view=diff ============================================================================== --- llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp (original) +++ llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Mon Aug 8 13:41:34 2011 @@ -284,8 +284,23 @@ break; } - if (!hasPreds && fi != f.begin()) + // Data block. + if (!hasPreds && fi != f.begin()) { + uint64_t End = llvm::next(fi) == fe ? SectSize : + llvm::next(fi)->first; + uint64_t addr; + if (error(i->getAddress(addr))) break; + outs() << "# " << End-fi->first << " bytes of data:\n"; + for (unsigned pos = fi->first; pos != End; ++pos) { + outs() << format("%8x:\t", addr + pos); + DumpBytes(StringRef(Bytes.data() + pos, 1)); + outs() << format("\t.byte 0x%02x\n", (uint8_t)Bytes[pos]); + } continue; + } + + if (fi->second.contains(&fi->second)) + outs() << "# Loop begin:\n"; for (unsigned ii = 0, ie = fi->second.getInsts().size(); ii != ie; ++ii) { @@ -294,6 +309,9 @@ const MCDecodedInst &Inst = fi->second.getInsts()[ii]; outs() << format("%8x:\t", addr + Inst.Address); DumpBytes(StringRef(Bytes.data() + Inst.Address, Inst.Size)); + // Simple loops. + if (fi->second.contains(&fi->second)) + outs() << '\t'; IP->printInst(&Inst.Inst, outs()); outs() << '\n'; } From nadav.rotem at intel.com Mon Aug 8 13:44:10 2011 From: nadav.rotem at intel.com (Rotem, Nadav) Date: Mon, 8 Aug 2011 21:44:10 +0300 Subject: [llvm-commits] [PATCH] Optimize trunc store Message-ID: <6594DDFF12B03D4E89690887C24869940296EB851B@hasmsx504.ger.corp.intel.com> Hi, Please review the attached patch. When performing a truncating store, it is sometimes possible to rearrange the data in-register prior to saving to memory. When we reorder the data in memory we prevent the need to save multiple scalars to memory, making a single regular store. 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 -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/8280c0d6/attachment.html -------------- next part -------------- A non-text attachment was scrubbed... Name: truncstore.diff Type: application/octet-stream Size: 5905 bytes Desc: truncstore.diff Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/8280c0d6/attachment.obj From benny.kra at googlemail.com Mon Aug 8 13:56:44 2011 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Mon, 08 Aug 2011 18:56:44 -0000 Subject: [llvm-commits] [llvm] r137059 - in /llvm/trunk: include/llvm/MC/MCInstrAnalysis.h include/llvm/Target/TargetRegistry.h lib/MC/MCInstrAnalysis.cpp lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp tools/llvm-objdump/MCFunction.cpp tools/llvm-objdump/MCFunction.h tools/llvm-objdump/llvm-objdump.cpp Message-ID: <20110808185644.A0F502A6C12C@llvm.org> Author: d0k Date: Mon Aug 8 13:56:44 2011 New Revision: 137059 URL: http://llvm.org/viewvc/llvm-project?rev=137059&view=rev Log: Add MCInstrAnalysis class. This allows the targets to specify own versions of MCInstrDescs functions. - Add overrides for ARM. - Teach llvm-objdump to use this instead of plain MCInstrDesc. Added: llvm/trunk/include/llvm/MC/MCInstrAnalysis.h llvm/trunk/lib/MC/MCInstrAnalysis.cpp Modified: llvm/trunk/include/llvm/Target/TargetRegistry.h llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp llvm/trunk/tools/llvm-objdump/MCFunction.cpp llvm/trunk/tools/llvm-objdump/MCFunction.h llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Added: llvm/trunk/include/llvm/MC/MCInstrAnalysis.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCInstrAnalysis.h?rev=137059&view=auto ============================================================================== --- llvm/trunk/include/llvm/MC/MCInstrAnalysis.h (added) +++ llvm/trunk/include/llvm/MC/MCInstrAnalysis.h Mon Aug 8 13:56:44 2011 @@ -0,0 +1,54 @@ +//===-- llvm/MC/MCInstrAnalysis.h - InstrDesc target hooks ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MCInstrAnalysis class which the MCTargetDescs can +// derive from to give additional information to MC. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" + +namespace llvm { + +class MCInstrAnalysis { +protected: + friend class Target; + const MCInstrInfo *Info; + + MCInstrAnalysis(const MCInstrInfo *Info) : Info(Info) {} +public: + virtual bool isBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isBranch(); + } + + virtual bool isConditionalBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isBranch(); + } + + virtual bool isUnconditionalBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isUnconditionalBranch(); + } + + virtual bool isIndirectBranch(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isIndirectBranch(); + } + + virtual bool isReturn(const MCInst &Inst) const { + return Info->get(Inst.getOpcode()).isReturn(); + } + + /// evaluateBranch - Given a branch instruction try to get the address the + /// branch targets. Otherwise return -1. + virtual uint64_t + evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size) const; +}; + +} Modified: llvm/trunk/include/llvm/Target/TargetRegistry.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetRegistry.h?rev=137059&r1=137058&r2=137059&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetRegistry.h (original) +++ llvm/trunk/include/llvm/Target/TargetRegistry.h Mon Aug 8 13:56:44 2011 @@ -20,6 +20,7 @@ #define LLVM_TARGET_TARGETREGISTRY_H #include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/ADT/Triple.h" #include #include @@ -74,6 +75,7 @@ Reloc::Model RM, CodeModel::Model CM); typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); + typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo*Info); typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT); typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT, StringRef CPU, @@ -147,6 +149,10 @@ /// if registered. MCInstrInfoCtorFnTy MCInstrInfoCtorFn; + /// MCInstrAnalysisCtorFn - Constructor function for this target's + /// MCInstrAnalysis, if registered. + MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn; + /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, /// if registered. MCRegInfoCtorFnTy MCRegInfoCtorFn; @@ -281,6 +287,14 @@ return MCInstrInfoCtorFn(); } + /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation. + /// + MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { + if (!MCInstrAnalysisCtorFn) + return new MCInstrAnalysis(Info); + return MCInstrAnalysisCtorFn(Info); + } + /// createMCRegInfo - Create a MCRegisterInfo implementation. /// MCRegisterInfo *createMCRegInfo(StringRef Triple) const { @@ -557,6 +571,15 @@ T.MCInstrInfoCtorFn = Fn; } + /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for + /// the given target. + static void RegisterMCInstrAnalysis(Target &T, + Target::MCInstrAnalysisCtorFnTy Fn) { + // Ignore duplicate registration. + if (!T.MCInstrAnalysisCtorFn) + T.MCInstrAnalysisCtorFn = Fn; + } + /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the /// given target. /// Added: llvm/trunk/lib/MC/MCInstrAnalysis.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCInstrAnalysis.cpp?rev=137059&view=auto ============================================================================== --- llvm/trunk/lib/MC/MCInstrAnalysis.cpp (added) +++ llvm/trunk/lib/MC/MCInstrAnalysis.cpp Mon Aug 8 13:56:44 2011 @@ -0,0 +1,20 @@ +//===-- MCInstrAnalysis.cpp - InstrDesc target hooks ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCInstrAnalysis.h" +using namespace llvm; + +uint64_t MCInstrAnalysis::evaluateBranch(const MCInst &Inst, uint64_t Addr, + uint64_t Size) const { + if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType != MCOI::OPERAND_PCREL) + return -1ULL; + + int64_t Imm = Inst.getOperand(0).getImm(); + return Addr+Size+Imm; +} Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp?rev=137059&r1=137058&r2=137059&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp (original) +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp Mon Aug 8 13:56:44 2011 @@ -13,6 +13,7 @@ #include "ARMMCTargetDesc.h" #include "ARMMCAsmInfo.h" +#include "ARMBaseInfo.h" #include "InstPrinter/ARMInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" @@ -159,6 +160,53 @@ return 0; } +namespace { + +class ARMMCInstrAnalysis : public MCInstrAnalysis { +public: + ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} + virtual bool isBranch(const MCInst &Inst) const { + // Don't flag "bx lr" as a branch. + return MCInstrAnalysis::isBranch(Inst) && (Inst.getOpcode() != ARM::BX || + Inst.getOperand(0).getReg() != ARM::LR); + } + + virtual bool isUnconditionalBranch(const MCInst &Inst) const { + // BCCs with the "always" predicate are unconditional branches. + if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) + return true; + return MCInstrAnalysis::isUnconditionalBranch(Inst); + } + + virtual bool isConditionalBranch(const MCInst &Inst) const { + // BCCs with the "always" predicate are unconditional branches. + if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL) + return false; + return MCInstrAnalysis::isConditionalBranch(Inst); + } + + virtual bool isReturn(const MCInst &Inst) const { + // Recognize "bx lr" as return. + return Inst.getOpcode() == ARM::BX && Inst.getOperand(0).getReg()==ARM::LR; + } + + uint64_t evaluateBranch(const MCInst &Inst, uint64_t Addr, + uint64_t Size) const { + // We only handle PCRel branches for now. + if (Info->get(Inst.getOpcode()).OpInfo[0].OperandType!=MCOI::OPERAND_PCREL) + return -1ULL; + + int64_t Imm = Inst.getOperand(0).getImm(); + // FIXME: This is not right for thumb. + return Addr+Imm+8; // In ARM mode the PC is always off by 8 bytes. + } +}; + +} + +static MCInstrAnalysis *createARMMCInstrAnalysis(const MCInstrInfo *Info) { + return new ARMMCInstrAnalysis(Info); +} // Force static initialization. extern "C" void LLVMInitializeARMTargetMC() { @@ -178,6 +226,11 @@ TargetRegistry::RegisterMCRegInfo(TheARMTarget, createARMMCRegisterInfo); TargetRegistry::RegisterMCRegInfo(TheThumbTarget, createARMMCRegisterInfo); + TargetRegistry::RegisterMCInstrAnalysis(TheARMTarget, + createARMMCInstrAnalysis); + TargetRegistry::RegisterMCInstrAnalysis(TheThumbTarget, + createARMMCInstrAnalysis); + // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(TheARMTarget, ARM_MC::createARMMCSubtargetInfo); Modified: llvm/trunk/tools/llvm-objdump/MCFunction.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/MCFunction.cpp?rev=137059&r1=137058&r2=137059&view=diff ============================================================================== --- llvm/trunk/tools/llvm-objdump/MCFunction.cpp (original) +++ llvm/trunk/tools/llvm-objdump/MCFunction.cpp Mon Aug 8 13:56:44 2011 @@ -17,6 +17,7 @@ #include "llvm/MC/MCDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/Support/MemoryObject.h" @@ -28,7 +29,7 @@ MCFunction MCFunction::createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm, const MemoryObject &Region, uint64_t Start, - uint64_t End, const MCInstrInfo *InstrInfo, + uint64_t End, const MCInstrAnalysis *Ana, raw_ostream &DebugOut) { std::set Splits; Splits.insert(Start); @@ -40,21 +41,17 @@ MCInst Inst; if (DisAsm->getInstruction(Inst, Size, Region, Index, DebugOut)) { - const MCInstrDesc &Desc = InstrInfo->get(Inst.getOpcode()); - if (Desc.isBranch()) { - if (Desc.OpInfo[0].OperandType == MCOI::OPERAND_PCREL) { - int64_t Imm = Inst.getOperand(0).getImm(); - // FIXME: Distinguish relocations from nop jumps. - if (Imm != 0) { - if (Index+Imm+Size >= End) { - Instructions.push_back(MCDecodedInst(Index, Size, Inst)); - continue; // Skip branches that leave the function. - } - Splits.insert(Index+Imm+Size); - } + if (Ana->isBranch(Inst)) { + uint64_t targ = Ana->evaluateBranch(Inst, Index, Size); + // FIXME: Distinguish relocations from nop jumps. + if (targ != -1ULL && (targ == Index+Size || targ >= End)) { + Instructions.push_back(MCDecodedInst(Index, Size, Inst)); + continue; // Skip branches that leave the function. } + if (targ != -1ULL) + Splits.insert(targ); Splits.insert(Index+Size); - } else if (Desc.isReturn()) { + } else if (Ana->isReturn(Inst)) { Splits.insert(Index+Size); } @@ -90,26 +87,22 @@ MCBasicBlock &BB = i->second; if (BB.getInsts().empty()) continue; const MCDecodedInst &Inst = BB.getInsts().back(); - const MCInstrDesc &Desc = InstrInfo->get(Inst.Inst.getOpcode()); - if (Desc.isBranch()) { - // PCRel branch, we know the destination. - if (Desc.OpInfo[0].OperandType == MCOI::OPERAND_PCREL) { - int64_t Imm = Inst.Inst.getOperand(0).getImm(); - if (Imm != 0) - BB.addSucc(&f.getBlockAtAddress(Inst.Address+Inst.Size+Imm)); - // Conditional branches can also fall through to the next block. - if (Desc.isConditionalBranch() && llvm::next(i) != e) - BB.addSucc(&llvm::next(i)->second); - } else { + if (Ana->isBranch(Inst.Inst)) { + uint64_t targ = Ana->evaluateBranch(Inst.Inst, Inst.Address, Inst.Size); + if (targ == -1ULL) { // Indirect branch. Bail and add all blocks of the function as a // successor. for (MCFunction::iterator i = f.begin(), e = f.end(); i != e; ++i) BB.addSucc(&i->second); - } + } else if (targ != Inst.Address+Inst.Size) + BB.addSucc(&f.getBlockAtAddress(targ)); + // Conditional branches can also fall through to the next block. + if (Ana->isConditionalBranch(Inst.Inst) && llvm::next(i) != e) + BB.addSucc(&llvm::next(i)->second); } else { // No branch. Fall through to the next block. - if (!Desc.isReturn() && llvm::next(i) != e) + if (!Ana->isReturn(Inst.Inst) && llvm::next(i) != e) BB.addSucc(&llvm::next(i)->second); } } Modified: llvm/trunk/tools/llvm-objdump/MCFunction.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/MCFunction.h?rev=137059&r1=137058&r2=137059&view=diff ============================================================================== --- llvm/trunk/tools/llvm-objdump/MCFunction.h (original) +++ llvm/trunk/tools/llvm-objdump/MCFunction.h Mon Aug 8 13:56:44 2011 @@ -20,7 +20,7 @@ namespace llvm { class MCDisassembler; -class MCInstrInfo; +class MCInstrAnalysis; class MemoryObject; class raw_ostream; @@ -68,7 +68,7 @@ static MCFunction createFunctionFromMC(StringRef Name, const MCDisassembler *DisAsm, const MemoryObject &Region, uint64_t Start, uint64_t End, - const MCInstrInfo *InstrInfo, raw_ostream &DebugOut); + const MCInstrAnalysis *Ana, raw_ostream &DebugOut); typedef MapTy::iterator iterator; iterator begin() { return Blocks.begin(); } Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp?rev=137059&r1=137058&r2=137059&view=diff ============================================================================== --- llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp (original) +++ llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Mon Aug 8 13:56:44 2011 @@ -165,6 +165,8 @@ return; } const MCInstrInfo *InstrInfo = TheTarget->createMCInstrInfo(); + OwningPtr + InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo)); outs() << '\n'; outs() << Filename @@ -270,8 +272,8 @@ // Create CFG and use it for disassembly. MCFunction f = MCFunction::createFunctionFromMC(Symbols[si].second, DisAsm.get(), - memoryObject, Start, End, InstrInfo, - DebugOut); + memoryObject, Start, End, + InstrAnalysis.get(), DebugOut); for (MCFunction::iterator fi = f.begin(), fe = f.end(); fi != fe; ++fi){ bool hasPreds = false; From rafael.espindola at gmail.com Mon Aug 8 14:01:55 2011 From: rafael.espindola at gmail.com (=?ISO-8859-1?Q?Rafael_=C1vila_de_Esp=EDndola?=) Date: Mon, 08 Aug 2011 15:01:55 -0400 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> <4E4000A6.1070908@gmail.com> <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> <4E401109.1050203@gmail.com> <4E401D24.4060605@gmail.com> Message-ID: <4E4032A3.4050608@gmail.com> > Sorry about the delay in responding, I've just returned from > vacation. np and welcome back! > I have some concerns about this patch as is - basically I'm worried > about subtle miscompiles based on how gcc does register allocation > for multiple reg wide values versus how llvm does it. In the gcc case > it will (as far as I know) assign consecutive registers for these > sorts of values, but there's no guarantee that llvm will do this. I think that is correct. When printing 'H' for example, gcc uses "REGNO (x) + 1". I could not find any other reference to those constraints, so it looks like gcc uses sequential registers unconditionally. > This means that in the case of stm/ldm instructions with the 'Q' and > 'R' modifiers that we'd get registers that weren't meant, leading to > subtle problems that users would need to debug. When we get support > for assigning values into consecutive registers this won't be a > problem. > > What are your thoughts? This is the first time I have seen these constraints, so I don't know how common they are and of those uses which ones assume sequential registers. I have attached the testcase where we have found this problem. In this particular case, we don't depend on the registers being sequential (but llvm does it anyway because it is an argument). How hard would it be to add the constraint that the registers have to be sequential? If doing it I would probably try it by creating a new pseudo reg class that alias the regular R registers and use those as operands to the inline asm. Is that what you had in mind? So, I guess this is a judgment call. The current patch allows us to handle some inline asm but causes us to miscompile others that we currently reject. > -eric Cheers, Rafael -------------- next part -------------- An embedded and charset-unspecified text was scrubbed... Name: test.c Url: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/955f3573/attachment.c From benny.kra at googlemail.com Mon Aug 8 14:09:02 2011 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Mon, 08 Aug 2011 19:09:02 -0000 Subject: [llvm-commits] [llvm] r137060 - in /llvm/trunk: include/llvm/MC/MCInstrAnalysis.h lib/MC/CMakeLists.txt Message-ID: <20110808190902.3C5C32A6C12C@llvm.org> Author: d0k Date: Mon Aug 8 14:09:02 2011 New Revision: 137060 URL: http://llvm.org/viewvc/llvm-project?rev=137060&view=rev Log: Pacify virtual dtor warnings and cmake buildbots. Modified: llvm/trunk/include/llvm/MC/MCInstrAnalysis.h llvm/trunk/lib/MC/CMakeLists.txt Modified: llvm/trunk/include/llvm/MC/MCInstrAnalysis.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCInstrAnalysis.h?rev=137060&r1=137059&r2=137060&view=diff ============================================================================== --- llvm/trunk/include/llvm/MC/MCInstrAnalysis.h (original) +++ llvm/trunk/include/llvm/MC/MCInstrAnalysis.h Mon Aug 8 14:09:02 2011 @@ -25,6 +25,8 @@ MCInstrAnalysis(const MCInstrInfo *Info) : Info(Info) {} public: + virtual ~MCInstrAnalysis() {} + virtual bool isBranch(const MCInst &Inst) const { return Info->get(Inst.getOpcode()).isBranch(); } Modified: llvm/trunk/lib/MC/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/CMakeLists.txt?rev=137060&r1=137059&r2=137060&view=diff ============================================================================== --- llvm/trunk/lib/MC/CMakeLists.txt (original) +++ llvm/trunk/lib/MC/CMakeLists.txt Mon Aug 8 14:09:02 2011 @@ -15,6 +15,7 @@ MCExpr.cpp MCInst.cpp MCInstPrinter.cpp + MCInstrAnalysis.cpp MCLabel.cpp MCDwarf.cpp MCLoggingStreamer.cpp From eli.friedman at gmail.com Mon Aug 8 14:49:37 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Mon, 08 Aug 2011 19:49:37 -0000 Subject: [llvm-commits] [llvm] r137061 - in /llvm/trunk: lib/Target/ARM/ARMInstrThumb2.td test/CodeGen/Thumb2/thumb2-sxt-uxt.ll Message-ID: <20110808194937.E4DB22A6C12C@llvm.org> Author: efriedma Date: Mon Aug 8 14:49:37 2011 New Revision: 137061 URL: http://llvm.org/viewvc/llvm-project?rev=137061&view=rev Log: Fix up the patterns for SXTB, SXTH, UXTB, and UXTH so that they are correctly active without HasT2ExtractPack. PR10611. Added: llvm/trunk/test/CodeGen/Thumb2/thumb2-sxt-uxt.ll 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=137061&r1=137060&r2=137061&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Aug 8 14:49:37 2011 @@ -977,7 +977,8 @@ class T2I_ext_rrot opcod, string opc, PatFrag opnode> : T2TwoReg<(outs rGPR:$Rd), (ins rGPR:$Rm, rot_imm:$rot), IIC_iEXTr, opc, ".w\t$Rd, $Rm$rot", - [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]> { + [(set rGPR:$Rd, (opnode (rotr rGPR:$Rm, rot_imm:$rot)))]>, + Requires<[IsThumb2]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0100; let Inst{22-20} = opcod; @@ -3407,9 +3408,9 @@ // SXT/UXT with no rotate let AddedComplexity = 16 in { def : T2Pat<(and rGPR:$Rm, 0x000000FF), (t2UXTB rGPR:$Rm, 0)>, - Requires<[HasT2ExtractPack, IsThumb2]>; + Requires<[IsThumb2]>; def : T2Pat<(and rGPR:$Rm, 0x0000FFFF), (t2UXTH rGPR:$Rm, 0)>, - Requires<[HasT2ExtractPack, IsThumb2]>; + Requires<[IsThumb2]>; def : T2Pat<(and rGPR:$Rm, 0x00FF00FF), (t2UXTB16 rGPR:$Rm, 0)>, Requires<[HasT2ExtractPack, IsThumb2]>; def : T2Pat<(add rGPR:$Rn, (and rGPR:$Rm, 0x00FF)), @@ -3421,9 +3422,9 @@ } def : T2Pat<(sext_inreg rGPR:$Src, i8), (t2SXTB rGPR:$Src, 0)>, - Requires<[HasT2ExtractPack, IsThumb2]>; + Requires<[IsThumb2]>; def : T2Pat<(sext_inreg rGPR:$Src, i16), (t2SXTH rGPR:$Src, 0)>, - Requires<[HasT2ExtractPack, IsThumb2]>; + Requires<[IsThumb2]>; def : T2Pat<(add rGPR:$Rn, (sext_inreg rGPR:$Rm, i8)), (t2SXTAB rGPR:$Rn, rGPR:$Rm, 0)>, Requires<[HasT2ExtractPack, IsThumb2]>; Added: llvm/trunk/test/CodeGen/Thumb2/thumb2-sxt-uxt.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Thumb2/thumb2-sxt-uxt.ll?rev=137061&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/Thumb2/thumb2-sxt-uxt.ll (added) +++ llvm/trunk/test/CodeGen/Thumb2/thumb2-sxt-uxt.ll Mon Aug 8 14:49:37 2011 @@ -0,0 +1,29 @@ +; RUN: llc < %s -march=thumb -mcpu=cortex-m3 | FileCheck %s + +define i32 @test1(i16 zeroext %z) nounwind { +; CHECK: test1: +; CHECK: sxth + %r = sext i16 %z to i32 + ret i32 %r +} + +define i32 @test2(i8 zeroext %z) nounwind { +; CHECK: test2: +; CHECK: sxtb + %r = sext i8 %z to i32 + ret i32 %r +} + +define i32 @test3(i16 signext %z) nounwind { +; CHECK: test3: +; CHECK: uxth + %r = zext i16 %z to i32 + ret i32 %r +} + +define i32 @test4(i8 signext %z) nounwind { +; CHECK: test4: +; CHECK: uxtb + %r = zext i8 %z to i32 + ret i32 %r +} From resistor at mac.com Mon Aug 8 15:42:17 2011 From: resistor at mac.com (Owen Anderson) Date: Mon, 08 Aug 2011 20:42:17 -0000 Subject: [llvm-commits] [llvm] r137062 - in /llvm/trunk: lib/Target/ARM/ARMCodeEmitter.cpp lib/Target/ARM/ARMInstrThumb.td lib/Target/ARM/ARMInstrThumb2.td lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp utils/TableGen/EDEmitter.cpp Message-ID: <20110808204217.EC3622A6C12C@llvm.org> Author: resistor Date: Mon Aug 8 15:42:17 2011 New Revision: 137062 URL: http://llvm.org/viewvc/llvm-project?rev=137062&view=rev Log: Fix encodings for Thumb ASR and LSR immediate operands. They encode the range 1-32, with 32 encoded as 0. Modified: llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp llvm/trunk/lib/Target/ARM/ARMInstrThumb.td llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp llvm/trunk/utils/TableGen/EDEmitter.cpp Modified: llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp?rev=137062&r1=137061&r2=137062&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMCodeEmitter.cpp Mon Aug 8 15:42:17 2011 @@ -236,6 +236,8 @@ const {return 0; } uint32_t getLdStSORegOpValue(const MachineInstr &MI, unsigned OpIdx) const { return 0; } + unsigned getThumbSRImmOpValue(const MachineInstr &MI, unsigned OpIdx) + const { return 0; } unsigned getAddrModeImm12OpValue(const MachineInstr &MI, unsigned Op) const { Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=137062&r1=137061&r2=137062&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Mon Aug 8 15:42:17 2011 @@ -19,6 +19,13 @@ [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; +def imm_sr : Operand, ImmLeaf 0 && Imm <= 32; +}]> { + let EncoderMethod = "getThumbSRImmOpValue"; + let DecoderMethod = "DecodeThumbSRImm"; +} + def imm_neg_XFORM : SDNodeXFormgetTargetConstant(-(int)N->getZExtValue(), MVT::i32); }]>; @@ -91,6 +98,7 @@ def t_blxtarget : Operand { let EncoderMethod = "getThumbBLXTargetOpValue"; + let DecoderMethod = "DecodeThumbBLXOffset"; } } @@ -876,10 +884,10 @@ // ASR immediate def tASRri : // A8.6.14 - T1sIGenEncodeImm<{0,1,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm5), + T1sIGenEncodeImm<{0,1,0,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5), IIC_iMOVsi, "asr", "\t$Rd, $Rm, $imm5", - [(set tGPR:$Rd, (sra tGPR:$Rm, (i32 imm:$imm5)))]> { + [(set tGPR:$Rd, (sra tGPR:$Rm, (i32 imm_sr:$imm5)))]> { bits<5> imm5; let Inst{10-6} = imm5; } @@ -976,10 +984,10 @@ // LSR immediate def tLSRri : // A8.6.90 - T1sIGenEncodeImm<{0,0,1,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, i32imm:$imm5), + T1sIGenEncodeImm<{0,0,1,?,?}, (outs tGPR:$Rd), (ins tGPR:$Rm, imm_sr:$imm5), IIC_iMOVsi, "lsr", "\t$Rd, $Rm, $imm5", - [(set tGPR:$Rd, (srl tGPR:$Rm, (i32 imm:$imm5)))]> { + [(set tGPR:$Rd, (srl tGPR:$Rm, (i32 imm_sr:$imm5)))]> { bits<5> imm5; let Inst{10-6} = imm5; } Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=137062&r1=137061&r2=137062&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Mon Aug 8 15:42:17 2011 @@ -66,7 +66,7 @@ }], t2_so_imm_neg_XFORM>; /// imm1_31 predicate - True if the 32-bit immediate is in the range [1,31]. -def imm1_31 : ImmLeaf, ImmLeaf= 1 && (int32_t)Imm < 32; }]>; @@ -759,12 +759,12 @@ /// T2I_sh_ir - Defines a set of (op reg, {so_imm|r}) patterns for a shift / // rotate operation that produces a value. -multiclass T2I_sh_ir opcod, string opc, PatFrag opnode> { +multiclass T2I_sh_ir opcod, string opc, Operand ty, PatFrag opnode> { // 5-bit imm def ri : T2sTwoRegShiftImm< - (outs rGPR:$Rd), (ins rGPR:$Rm, i32imm:$imm), IIC_iMOVsi, + (outs rGPR:$Rd), (ins rGPR:$Rm, ty:$imm), IIC_iMOVsi, opc, ".w\t$Rd, $Rm, $imm", - [(set rGPR:$Rd, (opnode rGPR:$Rm, imm1_31:$imm))]> { + [(set rGPR:$Rd, (opnode rGPR:$Rm, ty:$imm))]> { let Inst{31-27} = 0b11101; let Inst{26-21} = 0b010010; let Inst{19-16} = 0b1111; // Rn @@ -1913,10 +1913,10 @@ // Shift and rotate Instructions. // -defm t2LSL : T2I_sh_ir<0b00, "lsl", BinOpFrag<(shl node:$LHS, node:$RHS)>>; -defm t2LSR : T2I_sh_ir<0b01, "lsr", BinOpFrag<(srl node:$LHS, node:$RHS)>>; -defm t2ASR : T2I_sh_ir<0b10, "asr", BinOpFrag<(sra node:$LHS, node:$RHS)>>; -defm t2ROR : T2I_sh_ir<0b11, "ror", BinOpFrag<(rotr node:$LHS, node:$RHS)>>; +defm t2LSL : T2I_sh_ir<0b00, "lsl", imm1_31, BinOpFrag<(shl node:$LHS, node:$RHS)>>; +defm t2LSR : T2I_sh_ir<0b01, "lsr", imm_sr, BinOpFrag<(srl node:$LHS, node:$RHS)>>; +defm t2ASR : T2I_sh_ir<0b10, "asr", imm_sr, BinOpFrag<(sra node:$LHS, node:$RHS)>>; +defm t2ROR : T2I_sh_ir<0b11, "ror", imm1_31, BinOpFrag<(rotr node:$LHS, node:$RHS)>>; // (rotr x, (and y, 0x...1f)) ==> (ROR x, y) def : Pat<(rotr rGPR:$lhs, (and rGPR:$rhs, lo5AllOne)), Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp?rev=137062&r1=137061&r2=137062&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp (original) +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp Mon Aug 8 15:42:17 2011 @@ -294,6 +294,9 @@ unsigned getShiftRight64Imm(const MCInst &MI, unsigned Op, SmallVectorImpl &Fixups) const; + unsigned getThumbSRImmOpValue(const MCInst &MI, unsigned Op, + SmallVectorImpl &Fixups) const; + unsigned NEONThumb2DataIPostEncoder(const MCInst &MI, unsigned EncodedValue) const; unsigned NEONThumb2LoadStorePostEncoder(const MCInst &MI, @@ -440,6 +443,16 @@ return isAdd; } +uint32_t ARMMCCodeEmitter:: +getThumbSRImmOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups) const { + const MCOperand &MO = MI.getOperand(OpIdx); + assert(MO.isImm() && "Expected constant shift!"); + int val = MO.getImm(); + return (val == 32) ? 0 : val; +} + + /// getBranchTargetOpValue - Helper function to get the branch target operand, /// which is either an immediate or requires a fixup. static uint32_t getBranchTargetOpValue(const MCInst &MI, unsigned OpIdx, Modified: llvm/trunk/utils/TableGen/EDEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/EDEmitter.cpp?rev=137062&r1=137061&r2=137062&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/EDEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/EDEmitter.cpp Mon Aug 8 15:42:17 2011 @@ -615,6 +615,8 @@ IMM("t2ldrlabel"); IMM("postidx_imm8"); IMM("postidx_imm8s4"); + IMM("imm_sr"); + IMM("imm1_31"); MISC("brtarget", "kOperandTypeARMBranchTarget"); // ? MISC("uncondbrtarget", "kOperandTypeARMBranchTarget"); // ? From wendling at apple.com Mon Aug 8 15:49:23 2011 From: wendling at apple.com (Bill Wendling) Date: Mon, 08 Aug 2011 13:49:23 -0700 Subject: [llvm-commits] Newest LandingPad Patch In-Reply-To: <4E3FB06D.6080405@free.fr> References: <1D33093C-44C0-43BE-B5CD-9CF8F0907484@apple.com> <4E3FB06D.6080405@free.fr> Message-ID: <9646C440-5F6A-4EB8-A18F-1364B819A83B@apple.com> Hi Duncan, Thanks for the review. The possibility of 'bitcasts' makes this annoying. If I cannot guarantee that they will always be Constant*s or Function*s, I'll just change this to use Value*s instead. -bw On Aug 8, 2011, at 2:46 AM, Duncan Sands wrote: > Hi Bill, > >> + /// getPersonalityFn - Get the personality function associated with this >> + /// landing pad. >> + const Function *getPersonalityFn() const { >> + return cast(getOperand(0)); >> + } > > I think you should change this to > return cast(getOperand(0)->stripPointerCasts()); > > That's because you can't avoid sometimes getting a bitcast here. For example, > suppose you have two modules that both declare __gxx_personality_v0 and use it > in a landingpad instruction, but they use a slightly different prototype for > __gxx_personality_v0. When you link the bitcode from the two modules together, > the prototype difference will be resolved by replacing one __gxx_personality_v0 > with a bitcast of the other. This results in landingpad instructions with a > bitcast of a function for the personality function operand, and then... boom! > > Likewise, you can't assume that typeinfos are global variables, you have to > allow for the possibility that they are bitcasts of global variables. I didn't > notice any place that assumes they are global variables, so hopefully everything > is OK for them. > >> --- lib/VMCore/AsmWriter.cpp (revision 136744) >> +++ lib/VMCore/AsmWriter.cpp (working copy) >> @@ -1735,6 +1735,31 @@ >> writeOperand(I.getOperand(1), true); >> for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i) >> Out << ", " << *i; >> + } else if (const LandingPadInst *LPI = dyn_cast(&I)) { >> + Out << ' '; >> + TypePrinter.print(I.getType(), Out); >> + Out << " personality "; >> + writeOperand(LPI->getPersonalityFn(), true); Out << '\n'; > > If the personality operand was a bitcast then here you would fail to output the > bitcast. You should probably just write out operand 0. > >> @@ -3513,6 +3514,57 @@ >> return AteExtraComma ? InstExtraComma : InstNormal; >> } >> >> +/// ParseLandingPad >> +/// ::= 'landingpad' Type 'personality' TypeAndValue 'cleanup'? Clause+ >> +/// Clause >> +/// ::= 'catch' TypeAndValue >> +/// ::= 'filter' TypeAndValue* >> +bool LLParser::ParseLandingPad(Instruction *&Inst, PerFunctionState &PFS) { >> + Type *Ty = 0; LocTy TyLoc; >> + Value *PersFn; LocTy PersFnLoc; >> + LocTy LPLoc = Lex.getLoc(); >> + >> + if (ParseType(Ty, TyLoc) || >> + ParseToken(lltok::kw_personality, "expected 'personality'") || >> + ParseTypeAndValue(PersFn, PersFnLoc, PFS)) >> + return true; >> + >> + LandingPadInst *LP = LandingPadInst::Create(Ty, cast(PersFn), 0); > > Here you will blow up if the personality function is a bitcast. Also, you > should probably write the parsing in such a way as to output a helpful message > rather than crashing (as cast would) if someone provides invalid > input. > >> + LP->setCleanup(EatIfPresent(lltok::kw_cleanup)); >> + >> + while (Lex.getKind() == lltok::kw_catch || Lex.getKind() == lltok::kw_filter){ >> + if (Lex.getKind() == lltok::kw_catch) { >> + ParseToken(lltok::kw_catch, "expected 'catch'"); >> + >> + Value *V; LocTy VLoc; >> + if (ParseTypeAndValue(V, VLoc, PFS)) { >> + delete LP; >> + return true; >> + } >> + LP->addClause(LandingPadInst::Catch, cast(V)); > > This should probably output an error rather than crashing if V is not a > constant. > >> + } else { >> + ParseToken(lltok::kw_filter, "expected 'filter'"); >> + SmallVector Filters; >> + >> + if (Lex.getKind() == lltok::Type) { >> + do { >> + Value *V; LocTy VLoc; >> + if (ParseTypeAndValue(V, VLoc, PFS)) { >> + delete LP; >> + return true; >> + } >> + Filters.push_back(cast(V)); > > This should probably output an error rather than crashing if V is not a > constant. > >> --- lib/Bitcode/Reader/BitcodeReader.cpp (revision 136744) >> +++ lib/Bitcode/Reader/BitcodeReader.cpp (working copy) >> @@ -2543,6 +2543,45 @@ >> break; >> } >> >> + case bitc::FUNC_CODE_INST_LANDINGPAD: { >> + // LANDINGPAD: [ty, val, val, num, (id0,val0 ...)?] >> + unsigned Idx = 0; >> + if (Record.size() < 4) >> + return Error("Invalid LANDINGPAD record"); >> + Type *Ty = getTypeByID(Record[Idx++]); >> + if (!Ty) return Error("Invalid LANDINGPAD record"); >> + Value *PersFn = 0; >> + if (getValueTypePair(Record, Idx, NextValueNo, PersFn)) >> + return Error("Invalid LANDINGPAD record"); >> + >> + bool IsCleanup = !!Record[Idx++]; >> + unsigned NumClauses = Record[Idx++]; >> + LandingPadInst *LP = LandingPadInst::Create(Ty, cast(PersFn), > > Kaboom if a bitcast of a function rather than a function. Here too you should > probably try to output a message rather than crashing if you get some strange > input. > >> Index: lib/Bitcode/Writer/BitcodeWriter.cpp >> =================================================================== >> --- lib/Bitcode/Writer/BitcodeWriter.cpp (revision 136744) >> +++ lib/Bitcode/Writer/BitcodeWriter.cpp (working copy) >> @@ -1166,6 +1166,26 @@ >> break; >> } >> >> + case Instruction::LandingPad: { >> + const LandingPadInst &LP = cast(I); >> + Code = bitc::FUNC_CODE_INST_LANDINGPAD; >> + Vals.push_back(VE.getTypeID(LP.getType())); >> + PushValueAndType(LP.getPersonalityFn(), InstID, Vals, VE); > > This would drop any bitcast on the personality function. > > Ciao, Duncan. > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From stoklund at 2pi.dk Mon Aug 8 15:53:24 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 08 Aug 2011 20:53:24 -0000 Subject: [llvm-commits] [llvm] r137063 - in /llvm/trunk: include/llvm/Target/TargetInstrInfo.h lib/CodeGen/TargetInstrInfoImpl.cpp lib/Target/X86/X86InstrInfo.cpp lib/Target/X86/X86InstrInfo.h Message-ID: <20110808205324.AA3452A6C12C@llvm.org> Author: stoklund Date: Mon Aug 8 15:53:24 2011 New Revision: 137063 URL: http://llvm.org/viewvc/llvm-project?rev=137063&view=rev Log: Hoist hasLoadFromStackSlot and hasStoreToStackSlot. These the methods are target-independent since they simply scan the memory operands. They can live in TargetInstrInfoImpl. Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp llvm/trunk/lib/Target/X86/X86InstrInfo.cpp llvm/trunk/lib/Target/X86/X86InstrInfo.h Modified: llvm/trunk/include/llvm/Target/TargetInstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetInstrInfo.h?rev=137063&r1=137062&r2=137063&view=diff ============================================================================== --- llvm/trunk/include/llvm/Target/TargetInstrInfo.h (original) +++ llvm/trunk/include/llvm/Target/TargetInstrInfo.h Mon Aug 8 15:53:24 2011 @@ -693,6 +693,12 @@ unsigned &SrcOpIdx2) const; virtual bool canFoldMemoryOperand(const MachineInstr *MI, const SmallVectorImpl &Ops) const; + virtual bool hasLoadFromStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const; + virtual bool hasStoreToStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const; virtual bool PredicateInstruction(MachineInstr *MI, const SmallVectorImpl &Pred) const; virtual void reMaterialize(MachineBasicBlock &MBB, Modified: llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp?rev=137063&r1=137062&r2=137063&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp (original) +++ llvm/trunk/lib/CodeGen/TargetInstrInfoImpl.cpp Mon Aug 8 15:53:24 2011 @@ -160,6 +160,42 @@ return MadeChange; } +bool TargetInstrInfoImpl::hasLoadFromStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const { + for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), + oe = MI->memoperands_end(); + o != oe; + ++o) { + if ((*o)->isLoad() && (*o)->getValue()) + if (const FixedStackPseudoSourceValue *Value = + dyn_cast((*o)->getValue())) { + FrameIndex = Value->getFrameIndex(); + MMO = *o; + return true; + } + } + return false; +} + +bool TargetInstrInfoImpl::hasStoreToStackSlot(const MachineInstr *MI, + const MachineMemOperand *&MMO, + int &FrameIndex) const { + for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), + oe = MI->memoperands_end(); + o != oe; + ++o) { + if ((*o)->isStore() && (*o)->getValue()) + if (const FixedStackPseudoSourceValue *Value = + dyn_cast((*o)->getValue())) { + FrameIndex = Value->getFrameIndex(); + MMO = *o; + return true; + } + } + return false; +} + void TargetInstrInfoImpl::reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=137063&r1=137062&r2=137063&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Mon Aug 8 15:53:24 2011 @@ -856,24 +856,6 @@ return 0; } -bool X86InstrInfo::hasLoadFromStackSlot(const MachineInstr *MI, - const MachineMemOperand *&MMO, - int &FrameIndex) const { - for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), - oe = MI->memoperands_end(); - o != oe; - ++o) { - if ((*o)->isLoad() && (*o)->getValue()) - if (const FixedStackPseudoSourceValue *Value = - dyn_cast((*o)->getValue())) { - FrameIndex = Value->getFrameIndex(); - MMO = *o; - return true; - } - } - return false; -} - unsigned X86InstrInfo::isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const { if (isFrameStoreOpcode(MI->getOpcode())) @@ -896,24 +878,6 @@ return 0; } -bool X86InstrInfo::hasStoreToStackSlot(const MachineInstr *MI, - const MachineMemOperand *&MMO, - int &FrameIndex) const { - for (MachineInstr::mmo_iterator o = MI->memoperands_begin(), - oe = MI->memoperands_end(); - o != oe; - ++o) { - if ((*o)->isStore() && (*o)->getValue()) - if (const FixedStackPseudoSourceValue *Value = - dyn_cast((*o)->getValue())) { - FrameIndex = Value->getFrameIndex(); - MMO = *o; - return true; - } - } - return false; -} - /// regIsPICBase - Return true if register is PIC base (i.e.g defined by /// X86::MOVPC32r. static bool regIsPICBase(unsigned BaseReg, const MachineRegisterInfo &MRI) { Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.h?rev=137063&r1=137062&r2=137063&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrInfo.h (original) +++ llvm/trunk/lib/Target/X86/X86InstrInfo.h Mon Aug 8 15:53:24 2011 @@ -166,17 +166,6 @@ unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, int &FrameIndex) const; - /// hasLoadFromStackSlot - If the specified machine instruction has - /// a load from a stack slot, return true along with the FrameIndex - /// of the loaded stack slot and the machine mem operand containing - /// the reference. If not, return false. Unlike - /// isLoadFromStackSlot, this returns true for any instructions that - /// loads from the stack. This is a hint only and may not catch all - /// cases. - bool hasLoadFromStackSlot(const MachineInstr *MI, - const MachineMemOperand *&MMO, - int &FrameIndex) const; - unsigned isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const; /// isStoreToStackSlotPostFE - Check for post-frame ptr elimination /// stack locations as well. This uses a heuristic so it isn't @@ -184,16 +173,6 @@ unsigned isStoreToStackSlotPostFE(const MachineInstr *MI, int &FrameIndex) const; - /// hasStoreToStackSlot - If the specified machine instruction has a - /// store to a stack slot, return true along with the FrameIndex of - /// the loaded stack slot and the machine mem operand containing the - /// reference. If not, return false. Unlike isStoreToStackSlot, - /// this returns true for any instructions that loads from the - /// stack. This is a hint only and may not catch all cases. - bool hasStoreToStackSlot(const MachineInstr *MI, - const MachineMemOperand *&MMO, - int &FrameIndex) const; - bool isReallyTriviallyReMaterializable(const MachineInstr *MI, AliasAnalysis *AA) const; void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, From grosbach at apple.com Mon Aug 8 15:59:31 2011 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 08 Aug 2011 20:59:31 -0000 Subject: [llvm-commits] [llvm] r137064 - /llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Message-ID: <20110808205931.A743E2A6C12C@llvm.org> Author: grosbach Date: Mon Aug 8 15:59:31 2011 New Revision: 137064 URL: http://llvm.org/viewvc/llvm-project?rev=137064&view=rev Log: ARM load/store label parsing. Allow labels for load/store instructions when parsing. There's encoding issues, still, so this doesn't work all the way through, yet. Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=137064&r1=137063&r2=137064&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original) +++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Mon Aug 8 15:59:31 2011 @@ -566,6 +566,12 @@ return Val > -256 && Val < 256; } bool isMemImm12Offset() const { + // If we have an immediate that's not a constant, treat it as a label + // reference needing a fixup. If it is a constant, it's something else + // and we reject it. + if (Kind == Immediate && !isa(getImm())) + return true; + if (Kind != Memory || Mem.OffsetRegNum != 0) return false; // Immediate offset in range [-4095, 4095]. @@ -830,6 +836,14 @@ void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); + // If this is an immediate, it's a label reference. + if (Kind == Immediate) { + addExpr(Inst, getImm()); + Inst.addOperand(MCOperand::CreateImm(0)); + return; + } + + // Otherwise, it's a normal memory reg+offset. int64_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0; Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); Inst.addOperand(MCOperand::CreateImm(Val)); From gkistanova at gmail.com Mon Aug 8 16:03:11 2011 From: gkistanova at gmail.com (Galina Kistanova) Date: Mon, 08 Aug 2011 21:03:11 -0000 Subject: [llvm-commits] [zorg] r137065 - in /zorg/trunk/buildbot/osuosl/master/config: builders.py slaves.py Message-ID: <20110808210311.7C6572A6C12C@llvm.org> Author: gkistanova Date: Mon Aug 8 16:03:11 2011 New Revision: 137065 URL: http://llvm.org/viewvc/llvm-project?rev=137065&view=rev Log: Add new clang builder. Modified: zorg/trunk/buildbot/osuosl/master/config/builders.py zorg/trunk/buildbot/osuosl/master/config/slaves.py Modified: zorg/trunk/buildbot/osuosl/master/config/builders.py URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/buildbot/osuosl/master/config/builders.py?rev=137065&r1=137064&r2=137065&view=diff ============================================================================== --- zorg/trunk/buildbot/osuosl/master/config/builders.py (original) +++ zorg/trunk/buildbot/osuosl/master/config/builders.py Mon Aug 8 16:03:11 2011 @@ -300,6 +300,15 @@ stage1_config='Release+Asserts', test=True), 'category' : 'clang'}, + + {'name': "clang-native-mingw32-win7", + 'slavenames':["kistanova8"], + 'builddir':"clang-native-mingw32-win7", + 'factory' : ClangBuilder.getClangBuildFactory(triple='i686-pc-mingw32', + useTwoStage=True, + stage1_config='Release+Asserts', + stage2_config='Release+Asserts'), + 'category' : 'clang'}, # Clang cross builders. {'name': "clang-x86_64-darwin10-self-mingw32", Modified: zorg/trunk/buildbot/osuosl/master/config/slaves.py URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/buildbot/osuosl/master/config/slaves.py?rev=137065&r1=137064&r2=137065&view=diff ============================================================================== --- zorg/trunk/buildbot/osuosl/master/config/slaves.py (original) +++ zorg/trunk/buildbot/osuosl/master/config/slaves.py Mon Aug 8 16:03:11 2011 @@ -63,7 +63,7 @@ # FreeBSD 8.2 X86_64 create_slave("kistanova7", properties={'jobs' : 2}, max_builds=1), - # Dummy entries for future use. + # Windows 7 Ultimate create_slave("kistanova8", properties={'jobs' : 1}, max_builds=1), # Quad Core x86_64, Solaris / AurorAUX From wendling at apple.com Mon Aug 8 16:23:27 2011 From: wendling at apple.com (Bill Wendling) Date: Mon, 08 Aug 2011 14:23:27 -0700 Subject: [llvm-commits] [PATCH] Revised LandingPadInst Patch Message-ID: This is the next iteration of the landingpad instruction patch. It incorporates the feedback from Chris and Duncan. Notably, the values that are stored are now "Value*"s instead of "Function*" or "Constant*". Duncan pointed out that bitcasts can get in the way of things. I didn't explain the last patch well. The syntax allows for only one "type" per "catch" clause. However, the "filter" clause needs to allow for zero or more "types". This is because this filter: filter A, B, C is different from this filter: filter A filter B filter C The LandingPadInst has this ugly wart on it, namely the "Index" structure that Chris pointed out. I need a way to indicate the clause type for an object in the OperandList, it's index into that list, and how many "types" are associated with that. This is because of inlining. When we inline things, we are going to append the clauses to this list. And they need to be in the correct order so that the exception tables are generated correctly. Please review and let me know what you think. Thanks! -bw -------------- next part -------------- A non-text attachment was scrubbed... Name: landingpadinst.2.diff Type: application/octet-stream Size: 34897 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110808/1f06ee2c/attachment.obj -------------- next part -------------- From bruno.cardoso at gmail.com Mon Aug 8 16:31:08 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Mon, 08 Aug 2011 21:31:08 -0000 Subject: [llvm-commits] [llvm] r137067 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/avx-shift.ll Message-ID: <20110808213108.A2C652A6C12C@llvm.org> Author: bruno Date: Mon Aug 8 16:31:08 2011 New Revision: 137067 URL: http://llvm.org/viewvc/llvm-project?rev=137067&view=rev Log: Add support for several vector shifts operations while in AVX mode. Fix PR10581 Added: llvm/trunk/test/CodeGen/X86/avx-shift.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137067&r1=137066&r2=137067&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Aug 8 16:31:08 2011 @@ -883,7 +883,7 @@ setOperationAction(ISD::SINT_TO_FP, MVT::v4i32, Legal); } - if (Subtarget->hasSSE41()) { + if (Subtarget->hasSSE41() || Subtarget->hasAVX()) { setOperationAction(ISD::FFLOOR, MVT::f32, Legal); setOperationAction(ISD::FCEIL, MVT::f32, Legal); setOperationAction(ISD::FTRUNC, MVT::f32, Legal); @@ -922,10 +922,11 @@ } } - if (Subtarget->hasSSE2()) { + if (Subtarget->hasSSE2() || Subtarget->hasAVX()) { setOperationAction(ISD::SRL, MVT::v2i64, Custom); setOperationAction(ISD::SRL, MVT::v4i32, Custom); setOperationAction(ISD::SRL, MVT::v16i8, Custom); + setOperationAction(ISD::SRL, MVT::v8i16, Custom); setOperationAction(ISD::SHL, MVT::v2i64, Custom); setOperationAction(ISD::SHL, MVT::v4i32, Custom); @@ -935,7 +936,7 @@ setOperationAction(ISD::SRA, MVT::v8i16, Custom); } - if (Subtarget->hasSSE42()) + if (Subtarget->hasSSE42() || Subtarget->hasAVX()) setOperationAction(ISD::VSETCC, MVT::v2i64, Custom); if (!UseSoftFloat && Subtarget->hasAVX()) { @@ -975,6 +976,19 @@ setOperationAction(ISD::CONCAT_VECTORS, MVT::v32i8, Custom); setOperationAction(ISD::CONCAT_VECTORS, MVT::v16i16, Custom); + setOperationAction(ISD::SRL, MVT::v4i64, Custom); + setOperationAction(ISD::SRL, MVT::v8i32, Custom); + setOperationAction(ISD::SRL, MVT::v16i16, Custom); + setOperationAction(ISD::SRL, MVT::v32i8, Custom); + + setOperationAction(ISD::SHL, MVT::v4i64, Custom); + setOperationAction(ISD::SHL, MVT::v8i32, Custom); + setOperationAction(ISD::SHL, MVT::v16i16, Custom); + setOperationAction(ISD::SHL, MVT::v32i8, Custom); + + setOperationAction(ISD::SRA, MVT::v8i32, Custom); + setOperationAction(ISD::SRA, MVT::v16i16, Custom); + // Custom lower several nodes for 256-bit types. for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) { @@ -9195,11 +9209,42 @@ DebugLoc dl = Op.getDebugLoc(); SDValue R = Op.getOperand(0); SDValue Amt = Op.getOperand(1); - LLVMContext *Context = DAG.getContext(); - // Must have SSE2. - if (!Subtarget->hasSSE2()) return SDValue(); + if (!(Subtarget->hasSSE2() || Subtarget->hasAVX())) + return SDValue(); + + // Decompose 256-bit shifts into smaller 128-bit shifts. + if (VT.getSizeInBits() == 256) { + int NumElems = VT.getVectorNumElements(); + MVT EltVT = VT.getVectorElementType().getSimpleVT(); + EVT NewVT = MVT::getVectorVT(EltVT, NumElems/2); + + // Extract the two vectors + SDValue V1 = Extract128BitVector(R, DAG.getConstant(0, MVT::i32), DAG, dl); + SDValue V2 = Extract128BitVector(R, DAG.getConstant(NumElems/2, MVT::i32), + DAG, dl); + + // Recreate the shift amount vectors + SmallVector Amt1Csts; + SmallVector Amt2Csts; + for (int i = 0; i < NumElems/2; ++i) + Amt1Csts.push_back(Amt->getOperand(i)); + for (int i = NumElems/2; i < NumElems; ++i) + Amt2Csts.push_back(Amt->getOperand(i)); + + SDValue Amt1 = DAG.getNode(ISD::BUILD_VECTOR, dl, NewVT, + &Amt1Csts[0], NumElems/2); + SDValue Amt2 = DAG.getNode(ISD::BUILD_VECTOR, dl, NewVT, + &Amt2Csts[0], NumElems/2); + + // Issue new vector shifts for the smaller types + V1 = DAG.getNode(Op.getOpcode(), dl, NewVT, V1, Amt1); + V2 = DAG.getNode(Op.getOpcode(), dl, NewVT, V2, Amt2); + + // Concatenate the result back + return DAG.getNode(ISD::CONCAT_VECTORS, dl, VT, V1, V2); + } // Optimize shl/srl/sra with constant shift amount. if (isSplatVector(Amt.getNode())) { @@ -9250,9 +9295,6 @@ } // Lower SHL with variable shift amount. - // Cannot lower SHL without SSE2 or later. - if (!Subtarget->hasSSE2()) return SDValue(); - if (VT == MVT::v4i32 && Op->getOpcode() == ISD::SHL) { Op = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, VT, DAG.getConstant(Intrinsic::x86_sse2_pslli_d, MVT::i32), @@ -12099,7 +12141,7 @@ // all elements are shifted by the same amount. We can't do this in legalize // because the a constant vector is typically transformed to a constant pool // so we have no knowledge of the shift amount. - if (!Subtarget->hasSSE2()) + if (!(Subtarget->hasSSE2() || Subtarget->hasAVX())) return SDValue(); if (VT != MVT::v2i64 && VT != MVT::v4i32 && VT != MVT::v8i16) Added: llvm/trunk/test/CodeGen/X86/avx-shift.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-shift.ll?rev=137067&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-shift.ll (added) +++ llvm/trunk/test/CodeGen/X86/avx-shift.ll Mon Aug 8 16:31:08 2011 @@ -0,0 +1,64 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s + +;;; Shift left +; CHECK: vpslld +; CHECK: vpslld +define <8 x i32> @vshift00(<8 x i32> %a) nounwind readnone { + %s = shl <8 x i32> %a, + ret <8 x i32> %s +} + +; CHECK: vpsllw +; CHECK: vpsllw +define <16 x i16> @vshift01(<16 x i16> %a) nounwind readnone { + %s = shl <16 x i16> %a, + ret <16 x i16> %s +} + +; CHECK: vpsllq +; CHECK: vpsllq +define <4 x i64> @vshift02(<4 x i64> %a) nounwind readnone { + %s = shl <4 x i64> %a, + ret <4 x i64> %s +} + +;;; Logical Shift right +; CHECK: vpsrld +; CHECK: vpsrld +define <8 x i32> @vshift03(<8 x i32> %a) nounwind readnone { + %s = lshr <8 x i32> %a, + ret <8 x i32> %s +} + +; CHECK: vpsrlw +; CHECK: vpsrlw +define <16 x i16> @vshift04(<16 x i16> %a) nounwind readnone { + %s = lshr <16 x i16> %a, + ret <16 x i16> %s +} + +; CHECK: vpsrlq +; CHECK: vpsrlq +define <4 x i64> @vshift05(<4 x i64> %a) nounwind readnone { + %s = lshr <4 x i64> %a, + ret <4 x i64> %s +} + +;;; Arithmetic Shift right +; CHECK: vpsrad +; CHECK: vpsrad +define <8 x i32> @vshift06(<8 x i32> %a) nounwind readnone { + %s = ashr <8 x i32> %a, + ret <8 x i32> %s +} + +; CHECK: vpsraw +; CHECK: vpsraw +define <16 x i16> @vshift07(<16 x i16> %a) nounwind readnone { + %s = ashr <16 x i16> %a, + ret <16 x i16> %s +} + From stoklund at 2pi.dk Mon Aug 8 16:45:32 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Mon, 08 Aug 2011 21:45:32 -0000 Subject: [llvm-commits] [llvm] r137069 - in /llvm/trunk/lib/Target/ARM: ARMBaseInstrInfo.cpp ARMBaseInstrInfo.h Message-ID: <20110808214532.65BBC2A6C12C@llvm.org> Author: stoklund Date: Mon Aug 8 16:45:32 2011 New Revision: 137069 URL: http://llvm.org/viewvc/llvm-project?rev=137069&view=rev Log: Implement isLoadFromStackSlotPostFE and isStoreToStackSlotPostFE for ARM. They improve the verbose assembly. 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=137069&r1=137068&r2=137069&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Mon Aug 8 16:45:32 2011 @@ -810,6 +810,12 @@ return 0; } +unsigned ARMBaseInstrInfo::isStoreToStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + const MachineMemOperand *Dummy; + return MI->getDesc().mayStore() && hasStoreToStackSlot(MI, Dummy, FrameIndex); +} + void ARMBaseInstrInfo:: loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, int FI, @@ -945,6 +951,12 @@ return 0; } +unsigned ARMBaseInstrInfo::isLoadFromStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const { + const MachineMemOperand *Dummy; + return MI->getDesc().mayLoad() && hasLoadFromStackSlot(MI, Dummy, FrameIndex); +} + MachineInstr* ARMBaseInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx, uint64_t Offset, Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h?rev=137069&r1=137068&r2=137069&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h (original) +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.h Mon Aug 8 16:45:32 2011 @@ -101,6 +101,10 @@ int &FrameIndex) const; virtual unsigned isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const; + virtual unsigned isLoadFromStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const; + virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI, + int &FrameIndex) const; virtual void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, From wendling at apple.com Mon Aug 8 17:08:48 2011 From: wendling at apple.com (Bill Wendling) Date: Mon, 08 Aug 2011 15:08:48 -0700 Subject: [llvm-commits] [Patch] DwarfEHPrepare for New EH In-Reply-To: <4E3FFD82.8090701@free.fr> References: <4E3FFD82.8090701@free.fr> Message-ID: On Aug 8, 2011, at 8:15 AM, Duncan Sands wrote: > Hi Bill, > >> This patch implements the small amount which needs to be done by the DwarfEHPrepare pass. What it does is takes the 'resume' instruction and converts it into a call to _Unwind_Resume. The SjLj changes will be done in the SjLj lowering pass. > > why do this in DwarfEHPrepare (which should be zapped in the long run I guess)? I did it here because inserting a function call in the back-end is tricky. :) But yes, I'd love to see DwarfEHPrepare (and SjLjEHPrepare) go away. > Shouldn't it be lowered in SelectionDAGBuilder like other instructions are? > Also, it should probably be turned into a RESUME SDag Node, so that different > targets can be different things with it (eg: ARM doesn't want _Unwind_Resume > IIRC). > The ARM stuff uses SjLj exception handling, which is handled by the SjLjEHPrepare pass. The question isn't so much "which back-end needs what function call?", but "what is the family of exception handling we're dealing with, and what does its ABI tell us should be the 'resume' call?". We currently support two types of exception handling, of course: zero-cost and setjmp-longjmp. We are told which one to use via a flag in MCAsmInfo, though it's really personality function specific. I don't know if this will (or should) change in the future. -bw From grosbach at apple.com Mon Aug 8 17:11:33 2011 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 08 Aug 2011 22:11:33 -0000 Subject: [llvm-commits] [llvm] r137070 - /llvm/trunk/test/MC/ARM/arm-memory-instructions.s Message-ID: <20110808221133.8CEC02A6C12C@llvm.org> Author: grosbach Date: Mon Aug 8 17:11:33 2011 New Revision: 137070 URL: http://llvm.org/viewvc/llvm-project?rev=137070&view=rev Log: Add FIXME. Modified: llvm/trunk/test/MC/ARM/arm-memory-instructions.s Modified: llvm/trunk/test/MC/ARM/arm-memory-instructions.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm-memory-instructions.s?rev=137070&r1=137069&r2=137070&view=diff ============================================================================== --- llvm/trunk/test/MC/ARM/arm-memory-instructions.s (original) +++ llvm/trunk/test/MC/ARM/arm-memory-instructions.s Mon Aug 8 17:11:33 2011 @@ -23,6 +23,13 @@ @ CHECK: ldr r1, [r2], #30 @ encoding: [0x1e,0x10,0x92,0xe4] @ CHECK: ldr r3, [r1], #-30 @ encoding: [0x1e,0x30,0x11,0xe4] + at ------------------------------------------------------------------------------ +@ FIXME: LDR (literal) + at ------------------------------------------------------------------------------ +@ label operands currently assert the show-encoding asm comment helper due +@ to the use of non-contiguous bit ranges for fixups in ARM. Once that's +@ cleaned up, we can write useful assembly testcases for these sorts of +@ instructions. @------------------------------------------------------------------------------ @ LDR (register) From grosbach at apple.com Mon Aug 8 17:37:06 2011 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 08 Aug 2011 22:37:06 -0000 Subject: [llvm-commits] [llvm] r137071 - /llvm/trunk/test/MC/ARM/arm-memory-instructions.s Message-ID: <20110808223707.017542A6C12C@llvm.org> Author: grosbach Date: Mon Aug 8 17:37:06 2011 New Revision: 137071 URL: http://llvm.org/viewvc/llvm-project?rev=137071&view=rev Log: ARM parsing and encoding for LDRB instruction. Modified: llvm/trunk/test/MC/ARM/arm-memory-instructions.s Modified: llvm/trunk/test/MC/ARM/arm-memory-instructions.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm-memory-instructions.s?rev=137071&r1=137070&r2=137071&view=diff ============================================================================== --- llvm/trunk/test/MC/ARM/arm-memory-instructions.s (original) +++ llvm/trunk/test/MC/ARM/arm-memory-instructions.s Mon Aug 8 17:37:06 2011 @@ -51,3 +51,41 @@ @ CHECK: ldr r4, [r3], -r6 @ encoding: [0x06,0x40,0x13,0xe6] @ CHECK: ldr r3, [r8, -r2, lsl #15] @ encoding: [0x82,0x37,0x18,0xe7] @ CHECK: ldr r1, [r5], r3, asr #15 @ encoding: [0xc3,0x17,0x95,0xe6] + + + at ------------------------------------------------------------------------------ +@ LDRB (immediate) + at ------------------------------------------------------------------------------ + ldrb r3, [r8] + ldrb r1, [sp, #63] + ldrb r9, [r3, #4095]! + ldrb r8, [r1], #22 + ldrb r2, [r7], #-19 + +@ CHECK: ldrb r3, [r8] @ encoding: [0x00,0x30,0xd8,0xe5] +@ CHECK: ldrb r1, [sp, #63] @ encoding: [0x3f,0x10,0xdd,0xe5] +@ CHECK: ldrb r9, [r3, #4095]! @ encoding: [0xff,0x9f,0xf3,0xe5] +@ CHECK: ldrb r8, [r1], #22 @ encoding: [0x16,0x80,0xd1,0xe4] +@ CHECK: ldrb r2, [r7], #-19 @ encoding: [0x13,0x20,0x57,0xe4] + + + at ------------------------------------------------------------------------------ +@ LDRB (register) + at ------------------------------------------------------------------------------ + ldr r9, [r8, r5] + ldr r1, [r5, -r1] + ldr r3, [r5, r2]! + ldr r6, [r9, -r3]! + ldr r2, [r1], r4 + ldr r8, [r4], -r5 + ldr r7, [r12, -r1, lsl #15] + ldr r5, [r2], r9, asr #15 + +@ CHECK: ldr r9, [r8, r5] @ encoding: [0x05,0x90,0x98,0xe7] +@ CHECK: ldr r1, [r5, -r1] @ encoding: [0x01,0x10,0x15,0xe7] +@ CHECK: ldr r3, [r5, r2]! @ encoding: [0x02,0x30,0xb5,0xe7] +@ CHECK: ldr r6, [r9, -r3]! @ encoding: [0x03,0x60,0x39,0xe7] +@ CHECK: ldr r2, [r1], r4 @ encoding: [0x04,0x20,0x91,0xe6] +@ CHECK: ldr r8, [r4], -r5 @ encoding: [0x05,0x80,0x14,0xe6] +@ CHECK: ldr r7, [r12, -r1, lsl #15] @ encoding: [0x81,0x77,0x1c,0xe7] +@ CHECK: ldr r5, [r2], r9, asr #15 @ encoding: [0xc9,0x57,0x92,0xe6] From echristo at apple.com Mon Aug 8 18:01:28 2011 From: echristo at apple.com (Eric Christopher) Date: Mon, 08 Aug 2011 16:01:28 -0700 Subject: [llvm-commits] [RFC] Adding PassManagerBuilder to the C API In-Reply-To: <4E34BB0D.1050809@gmail.com> References: <4E34BB0D.1050809@gmail.com> Message-ID: <6F803DE5-8DA2-43F5-8442-58CBE280E4A0@apple.com> > > If people agree this is the best way, I will finish up the patch and > send it for review. If you have a better idea, let me know :-) This doesn't appear to be any worse than the current mechanism. :) -eric From isanbard at gmail.com Mon Aug 8 18:01:11 2011 From: isanbard at gmail.com (Bill Wendling) Date: Mon, 08 Aug 2011 23:01:11 -0000 Subject: [llvm-commits] [llvm] r137072 - /llvm/trunk/lib/VMCore/PassManager.cpp Message-ID: <20110808230111.3D8A22A6C12C@llvm.org> Author: void Date: Mon Aug 8 18:01:10 2011 New Revision: 137072 URL: http://llvm.org/viewvc/llvm-project?rev=137072&view=rev Log: Indicate that there are changes if runOfFunction returns saying that there are. Patch by Jingyue! Modified: llvm/trunk/lib/VMCore/PassManager.cpp Modified: llvm/trunk/lib/VMCore/PassManager.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/PassManager.cpp?rev=137072&r1=137071&r2=137072&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/PassManager.cpp (original) +++ llvm/trunk/lib/VMCore/PassManager.cpp Mon Aug 8 18:01:10 2011 @@ -1532,7 +1532,7 @@ bool Changed = doInitialization(M); for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - runOnFunction(*I); + Changed |= runOnFunction(*I); return doFinalization(M) || Changed; } From resistor at mac.com Mon Aug 8 18:25:22 2011 From: resistor at mac.com (Owen Anderson) Date: Mon, 08 Aug 2011 23:25:22 -0000 Subject: [llvm-commits] [llvm] r137073 - /llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Message-ID: <20110808232522.DD4392A6C12C@llvm.org> Author: resistor Date: Mon Aug 8 18:25:22 2011 New Revision: 137073 URL: http://llvm.org/viewvc/llvm-project?rev=137073&view=rev Log: Thumb1 BL instructions encoding 22 bits of displacement, not 21. 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=137073&r1=137072&r2=137073&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Mon Aug 8 18:25:22 2011 @@ -94,6 +94,7 @@ def t_bltarget : Operand { let EncoderMethod = "getThumbBLTargetOpValue"; + let DecoderMethod = "DecodeThumbBLTargetOperand"; } def t_blxtarget : Operand { @@ -168,6 +169,7 @@ def t_addrmode_sp : Operand, ComplexPattern { let EncoderMethod = "getAddrModeThumbSPOpValue"; + let DecoderMethod = "DecodeThumbAddrModeSP"; let PrintMethod = "printThumbAddrModeSPOperand"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } @@ -374,7 +376,8 @@ "bl${p}\t$func", [(ARMtcall tglobaladdr:$func)]>, Requires<[IsThumb, IsNotDarwin]> { - bits<21> func; + bits<22> func; + let Inst{26} = func{21}; let Inst{25-16} = func{20-11}; let Inst{13} = 1; let Inst{11} = 1; From grosbach at apple.com Mon Aug 8 18:28:47 2011 From: grosbach at apple.com (Jim Grosbach) Date: Mon, 08 Aug 2011 23:28:47 -0000 Subject: [llvm-commits] [llvm] r137074 - in /llvm/trunk: lib/Target/ARM/ARMInstrInfo.td test/MC/ARM/arm-memory-instructions.s Message-ID: <20110808232847.4390E2A6C12C@llvm.org> Author: grosbach Date: Mon Aug 8 18:28:47 2011 New Revision: 137074 URL: http://llvm.org/viewvc/llvm-project?rev=137074&view=rev Log: ARM parsing and encoding for LDRBT instruction. Fix the instruction representation to correctly only allow post-indexed form. Add tests. Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td llvm/trunk/test/MC/ARM/arm-memory-instructions.s Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137074&r1=137073&r2=137074&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Mon Aug 8 18:28:47 2011 @@ -2034,20 +2034,37 @@ let Inst{11-0} = addr{11-0}; let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2"; } -def LDRBT : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$base_wb), - (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_bh_ru, - "ldrbt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { - // {17-14} Rn - // {13} 1 == Rm, 0 == imm12 + +def LDRBT_POST_REG : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am2offset_reg:$offset), + IndexModePost, LdFrm, IIC_iLoad_bh_ru, + "ldrbt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { // {12} isAdd // {11-0} imm12/Rm - bits<18> addr; - let Inst{25} = addr{13}; - let Inst{23} = addr{12}; + bits<14> offset; + bits<4> addr; + let Inst{25} = 1; + let Inst{23} = offset{12}; let Inst{21} = 1; // overwrite - let Inst{19-16} = addr{17-14}; - let Inst{11-0} = addr{11-0}; - let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2"; + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; +} + +def LDRBT_POST_IMM : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb), + (ins addr_offset_none:$addr, am2offset_imm:$offset), + IndexModePost, LdFrm, IIC_iLoad_bh_ru, + "ldrbt", "\t$Rt, $addr, $offset", + "$addr.base = $Rn_wb", []> { + // {12} isAdd + // {11-0} imm12/Rm + bits<14> offset; + bits<4> addr; + let Inst{25} = 0; + let Inst{23} = offset{12}; + let Inst{21} = 1; // overwrite + let Inst{19-16} = addr; + let Inst{11-0} = offset{11-0}; } multiclass AI3ldrT op, string opc> { Modified: llvm/trunk/test/MC/ARM/arm-memory-instructions.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm-memory-instructions.s?rev=137074&r1=137073&r2=137074&view=diff ============================================================================== --- llvm/trunk/test/MC/ARM/arm-memory-instructions.s (original) +++ llvm/trunk/test/MC/ARM/arm-memory-instructions.s Mon Aug 8 18:28:47 2011 @@ -89,3 +89,19 @@ @ CHECK: ldr r8, [r4], -r5 @ encoding: [0x05,0x80,0x14,0xe6] @ CHECK: ldr r7, [r12, -r1, lsl #15] @ encoding: [0x81,0x77,0x1c,0xe7] @ CHECK: ldr r5, [r2], r9, asr #15 @ encoding: [0xc9,0x57,0x92,0xe6] + + + at ------------------------------------------------------------------------------ +@ LDRBT + at ------------------------------------------------------------------------------ +@ FIXME: Optional offset operand. + ldrbt r3, [r1], #4 + ldrbt r2, [r8], #-8 + ldrbt r8, [r7], r6 + ldrbt r1, [r2], -r6, lsl #12 + + +@ CHECK: ldrbt r3, [r1], #4 @ encoding: [0x04,0x30,0xf1,0xe4] +@ CHECK: ldrbt r2, [r8], #-8 @ encoding: [0x08,0x20,0x78,0xe4] +@ CHECK: ldrbt r8, [r7], r6 @ encoding: [0x06,0x80,0xf7,0xe6] +@ CHECK: ldrbt r1, [r2], -r6, lsl #12 @ encoding: [0x06,0x16,0x72,0xe6] From aggarwa4 at illinois.edu Mon Aug 8 18:48:15 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Mon, 08 Aug 2011 23:48:15 -0000 Subject: [llvm-commits] [poolalloc] r137076 - /poolalloc/trunk/lib/AssistDS/ArgCast.cpp Message-ID: <20110808234815.6D1192A6C12C@llvm.org> Author: aggarwa4 Date: Mon Aug 8 18:48:15 2011 New Revision: 137076 URL: http://llvm.org/viewvc/llvm-project?rev=137076&view=rev Log: Allow file to compile with mainline. Modified: poolalloc/trunk/lib/AssistDS/ArgCast.cpp Modified: poolalloc/trunk/lib/AssistDS/ArgCast.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/ArgCast.cpp?rev=137076&r1=137075&r2=137076&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/ArgCast.cpp (original) +++ poolalloc/trunk/lib/AssistDS/ArgCast.cpp Mon Aug 8 18:48:15 2011 @@ -58,7 +58,7 @@ // Find all uses of this function for(Value::use_iterator ui = I->use_begin(), ue = I->use_end(); ui != ue; ) { // check if is ever casted to a different function type - ConstantExpr *CE = dyn_cast(ui++); + ConstantExpr *CE = dyn_cast(*ui++); if(!CE) continue; if (CE->getOpcode() != Instruction::BitCast) @@ -82,7 +82,7 @@ uee = CE->use_end(); uii != uee; ++uii) { // Find all uses of the casted value, and check if it is // used in a Call Instruction - if (CallInst* CI = dyn_cast(uii)) { + if (CallInst* CI = dyn_cast(*uii)) { // Check that it is the called value, and not an argument if(CI->getCalledValue() != CE) continue; @@ -113,8 +113,8 @@ SmallVector Args; unsigned i =0; for(i =0; i< FTy->getNumParams(); ++i) { - const Type *ArgType = CI->getOperand(i+1)->getType(); - const Type *FormalType = FTy->getParamType(i); + Type *ArgType = CI->getOperand(i+1)->getType(); + Type *FormalType = FTy->getParamType(i); // If the types for this argument match, just add it to the // parameter list. No cast needs to be inserted. if(ArgType == FormalType) { @@ -171,7 +171,7 @@ } // else replace the call instruction - CallInst *CINew = CallInst::Create(F, Args.begin(), Args.end(), "", CI); + CallInst *CINew = CallInst::Create(F, Args, "", CI); CINew->setCallingConv(CI->getCallingConv()); CINew->setAttributes(CI->getAttributes()); if(!CI->use_empty()) { From aggarwa4 at illinois.edu Mon Aug 8 19:18:22 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Tue, 09 Aug 2011 00:18:22 -0000 Subject: [llvm-commits] [poolalloc] r137079 - in /poolalloc/trunk: include/assistDS/ArgCast.h include/assistDS/Devirt.h include/assistDS/FuncSimplify.h include/assistDS/FuncSpec.h lib/AssistDS/Devirt.cpp lib/AssistDS/DynCount.cpp lib/AssistDS/FuncSpec.cpp Message-ID: <20110809001822.D62302A6C12C@llvm.org> Author: aggarwa4 Date: Mon Aug 8 19:18:22 2011 New Revision: 137079 URL: http://llvm.org/viewvc/llvm-project?rev=137079&view=rev Log: Changes to compile with mainline llvm Modified: poolalloc/trunk/include/assistDS/ArgCast.h poolalloc/trunk/include/assistDS/Devirt.h poolalloc/trunk/include/assistDS/FuncSimplify.h poolalloc/trunk/include/assistDS/FuncSpec.h poolalloc/trunk/lib/AssistDS/Devirt.cpp poolalloc/trunk/lib/AssistDS/DynCount.cpp poolalloc/trunk/lib/AssistDS/FuncSpec.cpp Modified: poolalloc/trunk/include/assistDS/ArgCast.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/ArgCast.h?rev=137079&r1=137078&r2=137079&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/ArgCast.h (original) +++ poolalloc/trunk/include/assistDS/ArgCast.h Mon Aug 8 19:18:22 2011 @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Instructions.h" +#include "llvm/Constants.h" #include "llvm/Module.h" #include "llvm/Pass.h" @@ -27,7 +28,7 @@ class ArgCast : public ModulePass { public: static char ID; - ArgCast() : ModulePass(&ID) {} + ArgCast() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/include/assistDS/Devirt.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/Devirt.h?rev=137079&r1=137078&r2=137079&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/Devirt.h (original) +++ poolalloc/trunk/include/assistDS/Devirt.h Mon Aug 8 19:18:22 2011 @@ -57,7 +57,7 @@ public: static char ID; - Devirtualize() : ModulePass(&ID), CTF(0) {} + Devirtualize() : ModulePass(ID), CTF(0) {} virtual bool runOnModule(Module & M); Modified: poolalloc/trunk/include/assistDS/FuncSimplify.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/FuncSimplify.h?rev=137079&r1=137078&r2=137079&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/FuncSimplify.h (original) +++ poolalloc/trunk/include/assistDS/FuncSimplify.h Mon Aug 8 19:18:22 2011 @@ -23,7 +23,7 @@ class FuncSimplify : public ModulePass { public: static char ID; - FuncSimplify() : ModulePass(&ID) {} + FuncSimplify() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/include/assistDS/FuncSpec.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/FuncSpec.h?rev=137079&r1=137078&r2=137079&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/FuncSpec.h (original) +++ poolalloc/trunk/include/assistDS/FuncSpec.h Mon Aug 8 19:18:22 2011 @@ -28,7 +28,7 @@ class FuncSpec : public ModulePass { public: static char ID; - FuncSpec() : ModulePass(&ID) {} + FuncSpec() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/lib/AssistDS/Devirt.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/Devirt.cpp?rev=137079&r1=137078&r2=137079&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/Devirt.cpp (original) +++ poolalloc/trunk/lib/AssistDS/Devirt.cpp Mon Aug 8 19:18:22 2011 @@ -42,7 +42,7 @@ // static inline PointerType * getVoidPtrType (LLVMContext & C) { - const Type * Int8Type = IntegerType::getInt8Ty(C); + Type * Int8Type = IntegerType::getInt8Ty(C); return PointerType::getUnqual(Int8Type); } @@ -53,7 +53,7 @@ // Given an LLVM value, insert a cast instruction to make it a given type. // static inline Value * -castTo (Value * V, const Type * Ty, std::string Name, Instruction * InsertPt) { +castTo (Value * V, Type * Ty, std::string Name, Instruction * InsertPt) { // // Don't bother creating a cast if it's already the correct type. // @@ -147,7 +147,7 @@ // will be the function to call. // Value* ptr = CS.getCalledValue(); - std::vector TP; + std::vector TP; TP.insert (TP.begin(), ptr->getType()); for (CallSite::arg_iterator i = CS.arg_begin(); i != CS.arg_end(); @@ -155,7 +155,7 @@ TP.push_back ((*i)->getType()); } - const FunctionType* NewTy = FunctionType::get(CS.getType(), TP, false); + FunctionType* NewTy = FunctionType::get(CS.getType(), TP, false); Module * M = CS.getInstruction()->getParent()->getParent()->getParent(); Function* F = Function::Create (NewTy, GlobalValue::InternalLinkage, @@ -193,8 +193,7 @@ targets[FL] = BL; // Create the direct function call Value* directCall = CallInst::Create ((Value *)FL, - fargs.begin(), - fargs.end(), + fargs, "", BL); @@ -224,7 +223,7 @@ // Create basic blocks which will test the value of the incoming function // pointer and branch to the appropriate basic block to call the function. // - const Type * VoidPtrType = getVoidPtrType (M->getContext()); + Type * VoidPtrType = getVoidPtrType (M->getContext()); Value * FArg = castTo (F->arg_begin(), VoidPtrType, "", InsertPt); BasicBlock * tailBB = failBB; for (unsigned index = 0; index < Targets.size(); ++index) { @@ -265,8 +264,9 @@ // // Make the entry basic block branch to the first comparison basic block. // - InsertPt->setUnconditionalDest (tailBB); - + //InsertPt->setUnconditionalDest (tailBB); + InsertPt->setSuccessor(0, tailBB); + InsertPt->setSuccessor(1, tailBB); // // Return the newly created bounce function. // @@ -323,8 +323,7 @@ std::vector Params (CI->op_begin(), CI->op_end()); std::string name = CI->hasName() ? CI->getNameStr() + ".dv" : ""; CallInst* CN = CallInst::Create ((Value *) NF, - Params.begin(), - Params.end(), + Params, name, CI); CI->replaceAllUsesWith(CN); @@ -335,8 +334,7 @@ InvokeInst* CN = InvokeInst::Create((Value *) NF, CI->getNormalDest(), CI->getUnwindDest(), - Params.begin(), - Params.end(), + Params, name, CI); CI->replaceAllUsesWith(CN); Modified: poolalloc/trunk/lib/AssistDS/DynCount.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/DynCount.cpp?rev=137079&r1=137078&r2=137079&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/DynCount.cpp (original) +++ poolalloc/trunk/lib/AssistDS/DynCount.cpp Mon Aug 8 19:18:22 2011 @@ -15,6 +15,7 @@ #include "llvm/Pass.h" #include "llvm/Module.h" #include "llvm/Instructions.h" +#include "llvm/Constants.h" #include "llvm/Target/TargetData.h" #include "dsa/TypeSafety.h" @@ -27,7 +28,7 @@ public: static char ID; - Dyncount () : ModulePass ((intptr_t) &ID) { } + Dyncount () : ModulePass (ID) { } const char *getPassName() const { return "Count safe/unsafe load/store"; } @@ -132,7 +133,7 @@ std::vector args; args.push_back (Total); args.push_back (Safe); - CallInst::Create (Setup, args.begin(), args.end(), "", BB.getFirstNonPHI()); + CallInst::Create (Setup, args, "", BB.getFirstNonPHI()); return true; Modified: poolalloc/trunk/lib/AssistDS/FuncSpec.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/FuncSpec.cpp?rev=137079&r1=137078&r2=137079&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/FuncSpec.cpp (original) +++ poolalloc/trunk/lib/AssistDS/FuncSpec.cpp Mon Aug 8 19:18:22 2011 @@ -71,7 +71,7 @@ // Now find all call sites that it is called from for(Value::use_iterator ui = I->use_begin(), ue = I->use_end(); ui != ue; ++ui) { - if (CallInst* CI = dyn_cast(ui)) { + if (CallInst* CI = dyn_cast(*ui)) { // Check that it is the called value (and not an argument) if(CI->getCalledValue()->stripPointerCasts() == I) { std::vector > Consts; From stoklund at 2pi.dk Mon Aug 8 19:29:53 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 09 Aug 2011 00:29:53 -0000 Subject: [llvm-commits] [llvm] r137082 - in /llvm/trunk: include/llvm/CodeGen/Passes.h lib/CodeGen/RegAllocBasic.cpp lib/CodeGen/RegAllocGreedy.cpp lib/CodeGen/RegAllocLinearScan.cpp lib/CodeGen/RegAllocPBQP.cpp lib/CodeGen/RegisterCoalescer.cpp lib/CodeGen/Splitter.cpp Message-ID: <20110809002953.60B832A6C12C@llvm.org> Author: stoklund Date: Mon Aug 8 19:29:53 2011 New Revision: 137082 URL: http://llvm.org/viewvc/llvm-project?rev=137082&view=rev Log: Refer to the RegisterCoalescer pass by ID. A public interface is no longer needed since RegisterCoalescer is not an analysis any more. Modified: llvm/trunk/include/llvm/CodeGen/Passes.h llvm/trunk/lib/CodeGen/RegAllocBasic.cpp llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp llvm/trunk/lib/CodeGen/Splitter.cpp Modified: llvm/trunk/include/llvm/CodeGen/Passes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=137082&r1=137081&r2=137082&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/Passes.h (original) +++ llvm/trunk/include/llvm/CodeGen/Passes.h Mon Aug 8 19:29:53 2011 @@ -24,7 +24,6 @@ class MachineFunctionPass; class PassInfo; class TargetLowering; - class RegisterCoalescer; class raw_ostream; /// createUnreachableBlockEliminationPass - The LLVM code generator does not @@ -81,6 +80,9 @@ /// register allocators. extern char &TwoAddressInstructionPassID; + /// RegisteCoalescer pass - This pass merges live ranges to eliminate copies. + extern char &RegisterCoalescerPassID; + /// SpillPlacement analysis. Suggest optimal placement of spill code between /// basic blocks. /// @@ -125,11 +127,6 @@ /// FunctionPass *createDefaultPBQPRegisterAllocator(); - /// RegisterCoalescer Pass - Coalesce all copies possible. Can run - /// independently of the register allocator. - /// - RegisterCoalescer *createRegisterCoalescer(); - /// PrologEpilogCodeInserter Pass - This pass inserts prolog and epilog code, /// and eliminates abstract frame references. /// Modified: llvm/trunk/lib/CodeGen/RegAllocBasic.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocBasic.cpp?rev=137082&r1=137081&r2=137082&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocBasic.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocBasic.cpp Mon Aug 8 19:29:53 2011 @@ -20,7 +20,6 @@ #include "RenderMachineFunction.h" #include "Spiller.h" #include "VirtRegMap.h" -#include "RegisterCoalescer.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -160,7 +159,7 @@ AU.addPreserved(); if (StrongPHIElim) AU.addRequiredID(StrongPHIEliminationID); - AU.addRequiredTransitive(); + AU.addRequiredTransitiveID(RegisterCoalescerPassID); AU.addRequired(); AU.addRequired(); AU.addPreserved(); Modified: llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp?rev=137082&r1=137081&r2=137082&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocGreedy.cpp Mon Aug 8 19:29:53 2011 @@ -22,7 +22,6 @@ #include "SpillPlacement.h" #include "SplitKit.h" #include "VirtRegMap.h" -#include "RegisterCoalescer.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Function.h" @@ -324,7 +323,7 @@ AU.addPreserved(); if (StrongPHIElim) AU.addRequiredID(StrongPHIEliminationID); - AU.addRequiredTransitive(); + AU.addRequiredTransitiveID(RegisterCoalescerPassID); AU.addRequired(); AU.addRequired(); AU.addPreserved(); Modified: llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp?rev=137082&r1=137081&r2=137082&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocLinearScan.cpp Mon Aug 8 19:29:53 2011 @@ -18,7 +18,6 @@ #include "VirtRegRewriter.h" #include "RegisterClassInfo.h" #include "Spiller.h" -#include "RegisterCoalescer.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Function.h" #include "llvm/CodeGen/CalcSpillWeights.h" @@ -209,7 +208,7 @@ AU.addRequiredID(StrongPHIEliminationID); // Make sure PassManager knows which analyses to make available // to coalescing and which analyses coalescing invalidates. - AU.addRequiredTransitive(); + AU.addRequiredTransitiveID(RegisterCoalescerPassID); AU.addRequired(); AU.addRequiredID(LiveStacksID); AU.addPreservedID(LiveStacksID); Modified: llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp?rev=137082&r1=137081&r2=137082&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp (original) +++ llvm/trunk/lib/CodeGen/RegAllocPBQP.cpp Mon Aug 8 19:29:53 2011 @@ -450,7 +450,7 @@ au.addPreserved(); au.addRequired(); //au.addRequiredID(SplitCriticalEdgesID); - au.addRequired(); + au.addRequiredID(RegisterCoalescerPassID); if (customPassID) au.addRequiredID(*customPassID); au.addRequired(); Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp?rev=137082&r1=137081&r2=137082&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp (original) +++ llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp Mon Aug 8 19:29:53 2011 @@ -75,6 +75,8 @@ cl::desc("Verify machine instrs before and after register coalescing"), cl::Hidden); +char &llvm::RegisterCoalescerPassID = RegisterCoalescer::ID; + INITIALIZE_PASS_BEGIN(RegisterCoalescer, "simple-register-coalescing", "Simple Register Coalescing", false, false) INITIALIZE_PASS_DEPENDENCY(LiveIntervals) @@ -1841,7 +1843,3 @@ void RegisterCoalescer::print(raw_ostream &O, const Module* m) const { li_->print(O, m); } - -RegisterCoalescer *llvm::createRegisterCoalescer() { - return new RegisterCoalescer(); -} Modified: llvm/trunk/lib/CodeGen/Splitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Splitter.cpp?rev=137082&r1=137081&r2=137082&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/Splitter.cpp (original) +++ llvm/trunk/lib/CodeGen/Splitter.cpp Mon Aug 8 19:29:53 2011 @@ -11,7 +11,6 @@ #include "Splitter.h" -#include "RegisterCoalescer.h" #include "llvm/Module.h" #include "llvm/CodeGen/CalcSpillWeights.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" @@ -20,6 +19,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SlotIndexes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -262,7 +262,7 @@ au.addPreserved(); au.addRequired(); au.addPreserved(); - au.addPreserved(); + au.addPreservedID(RegisterCoalescerPassID); au.addPreserved(); au.addPreserved(); au.addRequired(); From aggarwa4 at illinois.edu Mon Aug 8 19:31:04 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Tue, 09 Aug 2011 00:31:04 -0000 Subject: [llvm-commits] [poolalloc] r137083 - in /poolalloc/trunk: include/assistDS/GEPExprArgs.h lib/AssistDS/GEPExprArgs.cpp Message-ID: <20110809003104.3372C2A6C12C@llvm.org> Author: aggarwa4 Date: Mon Aug 8 19:31:04 2011 New Revision: 137083 URL: http://llvm.org/viewvc/llvm-project?rev=137083&view=rev Log: Port to mainline Modified: poolalloc/trunk/include/assistDS/GEPExprArgs.h poolalloc/trunk/lib/AssistDS/GEPExprArgs.cpp Modified: poolalloc/trunk/include/assistDS/GEPExprArgs.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/GEPExprArgs.h?rev=137083&r1=137082&r2=137083&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/GEPExprArgs.h (original) +++ poolalloc/trunk/include/assistDS/GEPExprArgs.h Mon Aug 8 19:31:04 2011 @@ -1,4 +1,4 @@ -//===-- GEPExprArg.cpp - Promote args if they come from GEPs -------------===// + // // The LLVM Compiler Infrastructure // @@ -27,7 +27,7 @@ class GEPExprArgs : public ModulePass { public: static char ID; - GEPExprArgs() : ModulePass(&ID) {} + GEPExprArgs() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/lib/AssistDS/GEPExprArgs.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/GEPExprArgs.cpp?rev=137083&r1=137082&r2=137083&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/GEPExprArgs.cpp (original) +++ poolalloc/trunk/lib/AssistDS/GEPExprArgs.cpp Mon Aug 8 19:31:04 2011 @@ -14,9 +14,11 @@ #include "assistDS/GEPExprArgs.h" #include "llvm/Constants.h" +#include "llvm/Operator.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/ValueMap.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" #include "llvm/Use.h" @@ -89,14 +91,14 @@ // Construct the new Type // Appends the struct Type at the beginning - std::vectorTP; + std::vectorTP; TP.push_back(GEP->getPointerOperand()->getType()); for(unsigned c = 1; c < CI->getNumOperands();c++) { TP.push_back(CI->getOperand(c)->getType()); } //return type is same as that of original instruction - const FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); + FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); Function *NewF; numSimplified++; if(numSimplified > 800) @@ -111,7 +113,7 @@ NI->setName("GEParg"); ++NI; - DenseMap ValueMap; + ValueToValueMapTy ValueMap; for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++II, ++NI) { ValueMap[II] = NI; @@ -122,7 +124,7 @@ 0, F->getAttributes().getRetAttributes())); // Perform the cloning. SmallVector Returns; - CloneFunctionInto(NewF, F, ValueMap, Returns); + CloneFunctionInto(NewF, F, ValueMap, false, Returns); std::vector fargs; for(Function::arg_iterator ai = NewF->arg_begin(), ae= NewF->arg_end(); ai != ae; ++ai) { @@ -141,8 +143,7 @@ SmallVector Indices; Indices.append(GEP->op_begin()+1, GEP->op_end()); GetElementPtrInst *GEP_new = GetElementPtrInst::Create(cast(NI), - Indices.begin(), - Indices.end(), + Indices, "", InsertPoint); fargs.at(argNum)->replaceAllUsesWith(GEP_new); unsigned j = argNum + 1; @@ -175,7 +176,7 @@ AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); - CallInst *CallI = CallInst::Create(NewF,Args.begin(), Args.end(),"", CI); + CallInst *CallI = CallInst::Create(NewF,Args,"", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); CI->replaceAllUsesWith(CallI); From gohman at apple.com Mon Aug 8 19:33:12 2011 From: gohman at apple.com (Dan Gohman) Date: Tue, 09 Aug 2011 00:33:12 -0000 Subject: [llvm-commits] [llvm] r137085 - /llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll Message-ID: <20110809003312.2C0842A6C12C@llvm.org> Author: djg Date: Mon Aug 8 19:33:11 2011 New Revision: 137085 URL: http://llvm.org/viewvc/llvm-project?rev=137085&view=rev Log: Tidy up these testcases to look more like real code does. Modified: llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll Modified: llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll?rev=137085&r1=137084&r2=137085&view=diff ============================================================================== --- llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll (original) +++ llvm/trunk/test/Transforms/ObjCARC/cfg-hazards.ll Mon Aug 8 19:33:11 2011 @@ -18,18 +18,18 @@ define void @test0(i8* %digits) { entry: %tmp1 = call i8* @objc_retain(i8* %digits) nounwind - call void @use_pointer(i8* %tmp1) + call void @use_pointer(i8* %digits) br label %for.body for.body: ; preds = %for.body, %entry %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] - call void @use_pointer(i8* %tmp1) + call void @use_pointer(i8* %digits) %inc = add i64 %upcDigitIndex.01, 1 %cmp = icmp ult i64 %inc, 12 br i1 %cmp, label %for.body, label %for.end for.end: ; preds = %for.body - call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0 + call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0 ret void } @@ -47,14 +47,14 @@ for.body: ; preds = %for.body, %entry %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] - call void @use_pointer(i8* %tmp1) - call void @use_pointer(i8* %tmp1) + call void @use_pointer(i8* %digits) + call void @use_pointer(i8* %digits) %inc = add i64 %upcDigitIndex.01, 1 %cmp = icmp ult i64 %inc, 12 br i1 %cmp, label %for.body, label %for.end for.end: ; preds = %for.body - call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0 + call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0 ret void } @@ -72,14 +72,14 @@ for.body: ; preds = %for.body, %entry %upcDigitIndex.01 = phi i64 [ 2, %entry ], [ %inc, %for.body ] - call void @use_pointer(i8* %tmp1) + call void @use_pointer(i8* %digits) %inc = add i64 %upcDigitIndex.01, 1 %cmp = icmp ult i64 %inc, 12 br i1 %cmp, label %for.body, label %for.end for.end: ; preds = %for.body - call void @use_pointer(i8* %tmp1) - call void @objc_release(i8* %tmp1) nounwind, !clang.imprecise_release !0 + call void @use_pointer(i8* %digits) + call void @objc_release(i8* %digits) nounwind, !clang.imprecise_release !0 ret void } From aggarwa4 at illinois.edu Mon Aug 8 19:38:50 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Tue, 09 Aug 2011 00:38:50 -0000 Subject: [llvm-commits] [poolalloc] r137087 - in /poolalloc/trunk: include/assistDS/IndCloner.h include/assistDS/Int2PtrCmp.h include/assistDS/LoadArgs.h include/assistDS/MergeGEP.h lib/AssistDS/IndCloner.cpp lib/AssistDS/LoadArgs.cpp lib/AssistDS/MergeGEP.cpp Message-ID: <20110809003850.53C552A6C12C@llvm.org> Author: aggarwa4 Date: Mon Aug 8 19:38:50 2011 New Revision: 137087 URL: http://llvm.org/viewvc/llvm-project?rev=137087&view=rev Log: Changes to compile with mainline Modified: poolalloc/trunk/include/assistDS/IndCloner.h poolalloc/trunk/include/assistDS/Int2PtrCmp.h poolalloc/trunk/include/assistDS/LoadArgs.h poolalloc/trunk/include/assistDS/MergeGEP.h poolalloc/trunk/lib/AssistDS/IndCloner.cpp poolalloc/trunk/lib/AssistDS/LoadArgs.cpp poolalloc/trunk/lib/AssistDS/MergeGEP.cpp Modified: poolalloc/trunk/include/assistDS/IndCloner.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/IndCloner.h?rev=137087&r1=137086&r2=137087&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/IndCloner.h (original) +++ poolalloc/trunk/include/assistDS/IndCloner.h Mon Aug 8 19:38:50 2011 @@ -27,7 +27,7 @@ class IndClone : public ModulePass { public: static char ID; - IndClone() : ModulePass(&ID) {} + IndClone() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/include/assistDS/Int2PtrCmp.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/Int2PtrCmp.h?rev=137087&r1=137086&r2=137087&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/Int2PtrCmp.h (original) +++ poolalloc/trunk/include/assistDS/Int2PtrCmp.h Mon Aug 8 19:38:50 2011 @@ -29,7 +29,7 @@ TargetData * TD; public: static char ID; - Int2PtrCmp() : ModulePass(&ID) {} + Int2PtrCmp() : ModulePass(ID) {} virtual bool runOnModule(Module& M); virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); Modified: poolalloc/trunk/include/assistDS/LoadArgs.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/LoadArgs.h?rev=137087&r1=137086&r2=137087&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/LoadArgs.h (original) +++ poolalloc/trunk/include/assistDS/LoadArgs.h Mon Aug 8 19:38:50 2011 @@ -29,7 +29,7 @@ class LoadArgs : public ModulePass { public: static char ID; - LoadArgs() : ModulePass(&ID) {} + LoadArgs() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/include/assistDS/MergeGEP.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/MergeGEP.h?rev=137087&r1=137086&r2=137087&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/MergeGEP.h (original) +++ poolalloc/trunk/include/assistDS/MergeGEP.h Mon Aug 8 19:38:50 2011 @@ -23,7 +23,7 @@ class MergeArrayGEP : public ModulePass { public: static char ID; - MergeArrayGEP() : ModulePass(&ID) {} + MergeArrayGEP() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/lib/AssistDS/IndCloner.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/IndCloner.cpp?rev=137087&r1=137086&r2=137087&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/IndCloner.cpp (original) +++ poolalloc/trunk/lib/AssistDS/IndCloner.cpp Mon Aug 8 19:38:50 2011 @@ -73,7 +73,7 @@ if (!I->isDeclaration() && !I->mayBeOverridden()) { for (Value::use_iterator ui = I->use_begin(), ue = I->use_end(); ui != ue; ++ui) { - if (!isa(ui) && !isa(ui)) { + if (!isa(*ui) && !isa(*ui)) { if(!ui->use_empty()) // // If this function is used for anything other than a direct function @@ -148,7 +148,7 @@ for (Value::use_iterator ui = Original->use_begin(), ue = Original->use_end(); ui != ue; ) { - CallInst *CI = dyn_cast(ui); + CallInst *CI = dyn_cast(*ui); ui++; if (CI) { if (CI->getOperand(0) == Original) { Modified: poolalloc/trunk/lib/AssistDS/LoadArgs.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/LoadArgs.cpp?rev=137087&r1=137086&r2=137087&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/LoadArgs.cpp (original) +++ poolalloc/trunk/lib/AssistDS/LoadArgs.cpp Mon Aug 8 19:38:50 2011 @@ -19,6 +19,7 @@ #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/ValueMap.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" #include "llvm/Use.h" @@ -118,7 +119,7 @@ // Construct the new Type // Appends the struct Type at the beginning - std::vectorTP; + std::vectorTP; for(unsigned c = 1; c < CI->getNumOperands();c++) { if(c == argNum) TP.push_back(LI->getOperand(0)->getType()); @@ -126,7 +127,7 @@ } //return type is same as that of original instruction - const FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); + FunctionType *NewFTy = FunctionType::get(CI->getType(), TP, false); numSimplified++; //if(numSimplified > 1000) //return true; @@ -145,7 +146,7 @@ fnCache[std::make_pair(F, NewFTy)] = NewF; Function::arg_iterator NI = NewF->arg_begin(); - DenseMap ValueMap; + ValueToValueMapTy ValueMap; unsigned count = 1; for (Function::arg_iterator II = F->arg_begin(); NI != NewF->arg_end(); ++count, ++NI) { @@ -160,7 +161,7 @@ } // Perform the cloning. SmallVector Returns; - CloneFunctionInto(NewF, F, ValueMap, Returns); + CloneFunctionInto(NewF, F, ValueMap, false, Returns); std::vector fargs; for(Function::arg_iterator ai = NewF->arg_begin(), ae= NewF->arg_end(); ai != ae; ++ai) { @@ -202,7 +203,7 @@ AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); - CallInst *CallI = CallInst::Create(NewF,Args.begin(), Args.end(),"", CI); + CallInst *CallI = CallInst::Create(NewF,Args,"", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); CI->replaceAllUsesWith(CallI); Modified: poolalloc/trunk/lib/AssistDS/MergeGEP.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/MergeGEP.cpp?rev=137087&r1=137086&r2=137087&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/MergeGEP.cpp (original) +++ poolalloc/trunk/lib/AssistDS/MergeGEP.cpp Mon Aug 8 19:38:50 2011 @@ -14,6 +14,7 @@ #include "assistDS/MergeGEP.h" #include "llvm/Instructions.h" +#include "llvm/Operator.h" #include "llvm/Module.h" #include "llvm/Pass.h" #include "llvm/Instructions.h" @@ -140,10 +141,10 @@ if (!Indices.empty()){ GetElementPtrInst *GEPNew = (GEP->isInBounds() && Src->isInBounds()) ? - GetElementPtrInst::CreateInBounds(Src->getOperand(0), Indices.begin(), - Indices.end(), GEP->getName(), GEP) : - GetElementPtrInst::Create(Src->getOperand(0), Indices.begin(), - Indices.end(), GEP->getName(), GEP); + GetElementPtrInst::CreateInBounds(Src->getOperand(0), Indices, + GEP->getName(), GEP) : + GetElementPtrInst::Create(Src->getOperand(0), Indices, + GEP->getName(), GEP); numMerged++; GEP->replaceAllUsesWith(GEPNew); GEP->eraseFromParent(); From stoklund at 2pi.dk Mon Aug 8 19:43:37 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 09 Aug 2011 00:43:37 -0000 Subject: [llvm-commits] [llvm] r137088 - in /llvm/trunk/lib/CodeGen: RegisterCoalescer.cpp RegisterCoalescer.h Message-ID: <20110809004337.327382A6C12C@llvm.org> Author: stoklund Date: Mon Aug 8 19:43:37 2011 New Revision: 137088 URL: http://llvm.org/viewvc/llvm-project?rev=137088&view=rev Log: Move the RegisterCoalescer private to its implementation file. RegisterCoalescer.h still has the CoalescerPair class interface. Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp llvm/trunk/lib/CodeGen/RegisterCoalescer.h Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp?rev=137088&r1=137087&r2=137088&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp (original) +++ llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp Mon Aug 8 19:43:37 2011 @@ -15,8 +15,9 @@ #define DEBUG_TYPE "regcoalescing" #include "RegisterCoalescer.h" -#include "VirtRegMap.h" #include "LiveDebugVariables.h" +#include "RegisterClassInfo.h" +#include "VirtRegMap.h" #include "llvm/Pass.h" #include "llvm/Value.h" @@ -75,6 +76,127 @@ cl::desc("Verify machine instrs before and after register coalescing"), cl::Hidden); +namespace { + class RegisterCoalescer : public MachineFunctionPass { + MachineFunction* mf_; + MachineRegisterInfo* mri_; + const TargetMachine* tm_; + const TargetRegisterInfo* tri_; + const TargetInstrInfo* tii_; + LiveIntervals *li_; + LiveDebugVariables *ldv_; + const MachineLoopInfo* loopInfo; + AliasAnalysis *AA; + RegisterClassInfo RegClassInfo; + + /// JoinedCopies - Keep track of copies eliminated due to coalescing. + /// + SmallPtrSet JoinedCopies; + + /// ReMatCopies - Keep track of copies eliminated due to remat. + /// + SmallPtrSet ReMatCopies; + + /// ReMatDefs - Keep track of definition instructions which have + /// been remat'ed. + SmallPtrSet ReMatDefs; + + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting + /// copies that cannot yet be coalesced into the "TryAgain" list. + void CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector &TryAgain); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns + /// true if the copy was successfully coalesced away. If it is not + /// currently possible to coalesce this interval, but it may be possible if + /// other things get coalesced, then it returns true by reference in + /// 'Again'. + bool JoinCopy(MachineInstr *TheCopy, bool &Again); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. The output "SrcInt" will not have been modified, so we + /// can use this information below to update aliases. + bool JoinIntervals(CoalescerPair &CP); + + /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If + /// the source value number is defined by a copy from the destination reg + /// see if we can merge these two destination reg valno# into a single + /// value number, eliminating a copy. + bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); + + /// HasOtherReachingDefs - Return true if there are definitions of IntB + /// other than BValNo val# that can reach uses of AValno val# of IntA. + bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, + VNInfo *AValNo, VNInfo *BValNo); + + /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. + /// If the source value number is defined by a commutable instruction and + /// its other operand is coalesced to the copy dest register, see if we + /// can transform the copy into a noop by commuting the definition. + bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); + + /// ReMaterializeTrivialDef - If the source of a copy is defined by a + /// trivial computation, replace the copy by rematerialize the definition. + /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. + bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, + unsigned DstReg, unsigned DstSubIdx, + MachineInstr *CopyMI); + + /// shouldJoinPhys - Return true if a physreg copy should be joined. + bool shouldJoinPhys(CoalescerPair &CP); + + /// isWinToJoinCrossClass - Return true if it's profitable to coalesce + /// two virtual registers from different register classes. + bool isWinToJoinCrossClass(unsigned SrcReg, + unsigned DstReg, + const TargetRegisterClass *SrcRC, + const TargetRegisterClass *DstRC, + const TargetRegisterClass *NewRC); + + /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and + /// update the subregister number if it is not zero. If DstReg is a + /// physical register and the existing subregister number of the def / use + /// being updated is not zero, make sure to set it to the correct physical + /// subregister. + void UpdateRegDefsUses(const CoalescerPair &CP); + + /// RemoveDeadDef - If a def of a live interval is now determined dead, + /// remove the val# it defines. If the live interval becomes empty, remove + /// it as well. + bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); + + /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the + /// VNInfo copy flag for DstReg and all aliases. + void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); + + /// markAsJoined - Remember that CopyMI has already been joined. + void markAsJoined(MachineInstr *CopyMI); + + /// eliminateUndefCopy - Handle copies of undef values. + bool eliminateUndefCopy(MachineInstr *CopyMI, const CoalescerPair &CP); + + public: + static char ID; // Class identification, replacement for typeinfo + RegisterCoalescer() : MachineFunctionPass(ID) { + initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(raw_ostream &O, const Module* = 0) const; + }; +} /// end anonymous namespace + char &llvm::RegisterCoalescerPassID = RegisterCoalescer::ID; INITIALIZE_PASS_BEGIN(RegisterCoalescer, "simple-register-coalescing", Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.h?rev=137088&r1=137087&r2=137088&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegisterCoalescer.h (original) +++ llvm/trunk/lib/CodeGen/RegisterCoalescer.h Mon Aug 8 19:43:37 2011 @@ -12,156 +12,15 @@ // //===----------------------------------------------------------------------===// -#include "RegisterClassInfo.h" -#include "llvm/Support/IncludeFile.h" -#include "llvm/CodeGen/LiveInterval.h" -#include "llvm/ADT/SmallPtrSet.h" - #ifndef LLVM_CODEGEN_REGISTER_COALESCER_H #define LLVM_CODEGEN_REGISTER_COALESCER_H namespace llvm { - class MachineFunction; - class RegallocQuery; - class AnalysisUsage; class MachineInstr; class TargetRegisterInfo; class TargetRegisterClass; class TargetInstrInfo; - class LiveDebugVariables; - class VirtRegMap; - class MachineLoopInfo; - - class CoalescerPair; - - /// An abstract interface for register coalescers. Coalescers must - /// implement this interface to be part of the coalescer analysis - /// group. - class RegisterCoalescer : public MachineFunctionPass { - MachineFunction* mf_; - MachineRegisterInfo* mri_; - const TargetMachine* tm_; - const TargetRegisterInfo* tri_; - const TargetInstrInfo* tii_; - LiveIntervals *li_; - LiveDebugVariables *ldv_; - const MachineLoopInfo* loopInfo; - AliasAnalysis *AA; - RegisterClassInfo RegClassInfo; - - /// JoinedCopies - Keep track of copies eliminated due to coalescing. - /// - SmallPtrSet JoinedCopies; - - /// ReMatCopies - Keep track of copies eliminated due to remat. - /// - SmallPtrSet ReMatCopies; - - /// ReMatDefs - Keep track of definition instructions which have - /// been remat'ed. - SmallPtrSet ReMatDefs; - - /// joinIntervals - join compatible live intervals - void joinIntervals(); - - /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting - /// copies that cannot yet be coalesced into the "TryAgain" list. - void CopyCoalesceInMBB(MachineBasicBlock *MBB, - std::vector &TryAgain); - - /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, - /// which are the src/dst of the copy instruction CopyMI. This returns true - /// if the copy was successfully coalesced away. If it is not currently - /// possible to coalesce this interval, but it may be possible if other - /// things get coalesced, then it returns true by reference in 'Again'. - bool JoinCopy(MachineInstr *TheCopy, bool &Again); - - /// JoinIntervals - Attempt to join these two intervals. On failure, this - /// returns false. The output "SrcInt" will not have been modified, so we can - /// use this information below to update aliases. - bool JoinIntervals(CoalescerPair &CP); - - /// AdjustCopiesBackFrom - We found a non-trivially-coalescable copy. If - /// the source value number is defined by a copy from the destination reg - /// see if we can merge these two destination reg valno# into a single - /// value number, eliminating a copy. - bool AdjustCopiesBackFrom(const CoalescerPair &CP, MachineInstr *CopyMI); - - /// HasOtherReachingDefs - Return true if there are definitions of IntB - /// other than BValNo val# that can reach uses of AValno val# of IntA. - bool HasOtherReachingDefs(LiveInterval &IntA, LiveInterval &IntB, - VNInfo *AValNo, VNInfo *BValNo); - - /// RemoveCopyByCommutingDef - We found a non-trivially-coalescable copy. - /// If the source value number is defined by a commutable instruction and - /// its other operand is coalesced to the copy dest register, see if we - /// can transform the copy into a noop by commuting the definition. - bool RemoveCopyByCommutingDef(const CoalescerPair &CP,MachineInstr *CopyMI); - - /// ReMaterializeTrivialDef - If the source of a copy is defined by a trivial - /// computation, replace the copy by rematerialize the definition. - /// If PreserveSrcInt is true, make sure SrcInt is valid after the call. - bool ReMaterializeTrivialDef(LiveInterval &SrcInt, bool PreserveSrcInt, - unsigned DstReg, unsigned DstSubIdx, - MachineInstr *CopyMI); - - /// shouldJoinPhys - Return true if a physreg copy should be joined. - bool shouldJoinPhys(CoalescerPair &CP); - - /// isWinToJoinCrossClass - Return true if it's profitable to coalesce - /// two virtual registers from different register classes. - bool isWinToJoinCrossClass(unsigned SrcReg, - unsigned DstReg, - const TargetRegisterClass *SrcRC, - const TargetRegisterClass *DstRC, - const TargetRegisterClass *NewRC); - - /// UpdateRegDefsUses - Replace all defs and uses of SrcReg to DstReg and - /// update the subregister number if it is not zero. If DstReg is a - /// physical register and the existing subregister number of the def / use - /// being updated is not zero, make sure to set it to the correct physical - /// subregister. - void UpdateRegDefsUses(const CoalescerPair &CP); - - /// RemoveDeadDef - If a def of a live interval is now determined dead, - /// remove the val# it defines. If the live interval becomes empty, remove - /// it as well. - bool RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI); - - /// RemoveCopyFlag - If DstReg is no longer defined by CopyMI, clear the - /// VNInfo copy flag for DstReg and all aliases. - void RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI); - - /// markAsJoined - Remember that CopyMI has already been joined. - void markAsJoined(MachineInstr *CopyMI); - - /// eliminateUndefCopy - Handle copies of undef values. - bool eliminateUndefCopy(MachineInstr *CopyMI, const CoalescerPair &CP); - - public: - static char ID; // Class identification, replacement for typeinfo - RegisterCoalescer() : MachineFunctionPass(ID) { - initializeRegisterCoalescerPass(*PassRegistry::getPassRegistry()); - } - - /// Register allocators must call this from their own - /// getAnalysisUsage to cover the case where the coalescer is not - /// a Pass in the proper sense and isn't managed by PassManager. - /// PassManager needs to know which analyses to make available and - /// which to invalidate when running the register allocator or any - /// pass that might call coalescing. The long-term solution is to - /// allow hierarchies of PassManagers. - virtual void getAnalysisUsage(AnalysisUsage &AU) const; - - virtual void releaseMemory(); - - /// runOnMachineFunction - pass entry point - virtual bool runOnMachineFunction(MachineFunction&); - - /// print - Implement the dump method. - virtual void print(raw_ostream &O, const Module* = 0) const; - }; /// CoalescerPair - A helper class for register coalescers. When deciding if /// two registers can be coalesced, CoalescerPair can determine if a copy From aggarwa4 at illinois.edu Mon Aug 8 19:46:44 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Tue, 09 Aug 2011 00:46:44 -0000 Subject: [llvm-commits] [poolalloc] r137089 - in /poolalloc/trunk: include/assistDS/SimplifyExtractValue.h lib/AssistDS/SimplifyExtractValue.cpp Message-ID: <20110809004644.523732A6C12C@llvm.org> Author: aggarwa4 Date: Mon Aug 8 19:46:44 2011 New Revision: 137089 URL: http://llvm.org/viewvc/llvm-project?rev=137089&view=rev Log: Port to mainline Modified: poolalloc/trunk/include/assistDS/SimplifyExtractValue.h poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp Modified: poolalloc/trunk/include/assistDS/SimplifyExtractValue.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/SimplifyExtractValue.h?rev=137089&r1=137088&r2=137089&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/SimplifyExtractValue.h (original) +++ poolalloc/trunk/include/assistDS/SimplifyExtractValue.h Mon Aug 8 19:46:44 2011 @@ -24,7 +24,7 @@ class SimplifyEV : public ModulePass { public: static char ID; - SimplifyEV() : ModulePass(&ID) {} + SimplifyEV() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp?rev=137089&r1=137088&r2=137089&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp (original) +++ poolalloc/trunk/lib/AssistDS/SimplifyExtractValue.cpp Mon Aug 8 19:46:44 2011 @@ -17,6 +17,7 @@ #include "assistDS/SimplifyExtractValue.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" #include "llvm/Support/PatternMatch.h" @@ -98,8 +99,8 @@ // 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->getIndices().slice(1), + "", EV); EV->replaceAllUsesWith(EV_new); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); @@ -126,15 +127,15 @@ // replace the extract value intruction with // a gep and a load. SmallVector Indices; - const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + 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) ; + GetElementPtrInst *GEP = GetElementPtrInst::CreateInBounds(LI->getOperand(0), Indices, + LI->getName(), LI) ; LoadInst *LINew = new LoadInst(GEP, "", LI); EV->replaceAllUsesWith(LINew); EV->eraseFromParent(); @@ -160,7 +161,7 @@ // with // %E = extractvalue { i32, { i32 } } %A, 0 ExtractValueInst *EV_new = ExtractValueInst::Create(IV->getAggregateOperand(), - EV->idx_begin(), EV->idx_end(),"", EV); + EV->getIndices(), "", EV); EV->replaceAllUsesWith(EV_new); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); @@ -198,9 +199,9 @@ // 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); + EV->getIndices(), "", EV); Value *NewIV = InsertValueInst::Create(NewEV, IV->getInsertedValueOperand(), - insi, inse, "", EV); + makeArrayRef(insi, inse), "", EV); EV->replaceAllUsesWith(NewIV); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); @@ -220,7 +221,7 @@ // with // %E extractvalue { i32 } { i32 42 }, 0 ExtractValueInst *EV_new = ExtractValueInst::Create(IV->getInsertedValueOperand(), - exti, exte,"", EV); + makeArrayRef(exti, exte), "", EV); EV->replaceAllUsesWith(EV_new); DEBUG(errs() << "EV:"); DEBUG(errs() << "ERASE:"); From bruno.cardoso at gmail.com Mon Aug 8 19:46:57 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 00:46:57 -0000 Subject: [llvm-commits] [llvm] r137090 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86InstrSSE.td test/CodeGen/X86/avx-256-cmp.ll Message-ID: <20110809004657.844782A6C12C@llvm.org> Author: bruno Date: Mon Aug 8 19:46:57 2011 New Revision: 137090 URL: http://llvm.org/viewvc/llvm-project?rev=137090&view=rev Log: Make LowerVSETCC aware of AVX types and add patterns to match them. Added: llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86InstrSSE.td Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137090&r1=137089&r2=137090&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon Aug 8 19:46:57 2011 @@ -989,6 +989,9 @@ setOperationAction(ISD::SRA, MVT::v8i32, Custom); setOperationAction(ISD::SRA, MVT::v16i16, Custom); + setOperationAction(ISD::VSETCC, MVT::v8i32, Custom); + setOperationAction(ISD::VSETCC, MVT::v4i64, Custom); + // Custom lower several nodes for 256-bit types. for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) { @@ -7912,9 +7915,10 @@ if (isFP) { unsigned SSECC = 8; - EVT VT0 = Op0.getValueType(); - assert(VT0 == MVT::v4f32 || VT0 == MVT::v2f64); - unsigned Opc = VT0 == MVT::v4f32 ? X86ISD::CMPPS : X86ISD::CMPPD; + EVT EltVT = Op0.getValueType().getVectorElementType(); + assert(EltVT == MVT::f32 || EltVT == MVT::f64); + + unsigned Opc = EltVT == MVT::f32 ? X86ISD::CMPPS : X86ISD::CMPPD; bool Swap = false; switch (SetCCOpcode) { @@ -7961,6 +7965,9 @@ return DAG.getNode(Opc, dl, VT, Op0, Op1, DAG.getConstant(SSECC, MVT::i8)); } + if (!isFP && VT.getSizeInBits() == 256) + return SDValue(); + // We are handling one of the integer comparisons here. Since SSE only has // GT and EQ comparisons for integer, swapping operands and multiple // operations may be required for some comparisons. Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=137090&r1=137089&r2=137090&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Mon Aug 8 19:46:57 2011 @@ -1264,14 +1264,39 @@ SSEPackedDouble>, TB, OpSize; } +let Predicates = [HasSSE1] in { def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), VR128:$src2, imm:$cc)), (CMPPSrri (v4f32 VR128:$src1), (v4f32 VR128:$src2), imm:$cc)>; def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), (memop addr:$src2), imm:$cc)), (CMPPSrmi (v4f32 VR128:$src1), addr:$src2, imm:$cc)>; +} + +let Predicates = [HasSSE2] in { def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), VR128:$src2, imm:$cc)), (CMPPDrri VR128:$src1, VR128:$src2, imm:$cc)>; def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), (memop addr:$src2), imm:$cc)), (CMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>; +} + +let Predicates = [HasAVX] in { +def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), VR128:$src2, imm:$cc)), + (VCMPPSrri (v4f32 VR128:$src1), (v4f32 VR128:$src2), imm:$cc)>; +def : Pat<(v4i32 (X86cmpps (v4f32 VR128:$src1), (memop addr:$src2), imm:$cc)), + (VCMPPSrmi (v4f32 VR128:$src1), addr:$src2, imm:$cc)>; +def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), VR128:$src2, imm:$cc)), + (VCMPPDrri VR128:$src1, VR128:$src2, imm:$cc)>; +def : Pat<(v2i64 (X86cmppd (v2f64 VR128:$src1), (memop addr:$src2), imm:$cc)), + (VCMPPDrmi VR128:$src1, addr:$src2, imm:$cc)>; + +def : Pat<(v8i32 (X86cmpps (v8f32 VR256:$src1), VR256:$src2, imm:$cc)), + (VCMPPSYrri (v8f32 VR256:$src1), (v8f32 VR256:$src2), imm:$cc)>; +def : Pat<(v8i32 (X86cmpps (v8f32 VR256:$src1), (memop addr:$src2), imm:$cc)), + (VCMPPSYrmi (v8f32 VR256:$src1), addr:$src2, imm:$cc)>; +def : Pat<(v4i64 (X86cmppd (v4f64 VR256:$src1), VR256:$src2, imm:$cc)), + (VCMPPDYrri VR256:$src1, VR256:$src2, imm:$cc)>; +def : Pat<(v4i64 (X86cmppd (v4f64 VR256:$src1), (memop addr:$src2), imm:$cc)), + (VCMPPDYrmi VR256:$src1, addr:$src2, imm:$cc)>; +} //===----------------------------------------------------------------------===// // SSE 1 & 2 - Shuffle Instructions Added: llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll?rev=137090&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll (added) +++ llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll Mon Aug 8 19:46:57 2011 @@ -0,0 +1,18 @@ +; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s + +; CHECK: vcmpltps %ymm +; CHECK-NOT: vucomiss +define <8 x i32> @cmp00(<8 x float> %a, <8 x float> %b) nounwind readnone { + %bincmp = fcmp olt <8 x float> %a, %b + %s = sext <8 x i1> %bincmp to <8 x i32> + ret <8 x i32> %s +} + +; CHECK: vcmpltpd %ymm +; CHECK-NOT: vucomisd +define <4 x i64> @cmp01(<4 x double> %a, <4 x double> %b) nounwind readnone { + %bincmp = fcmp olt <4 x double> %a, %b + %s = sext <4 x i1> %bincmp to <4 x i64> + ret <4 x i64> %s +} + From isanbard at gmail.com Mon Aug 8 19:47:30 2011 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 09 Aug 2011 00:47:30 -0000 Subject: [llvm-commits] [llvm] r137091 - /llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp Message-ID: <20110809004730.A1A452A6C12C@llvm.org> Author: void Date: Mon Aug 8 19:47:30 2011 New Revision: 137091 URL: http://llvm.org/viewvc/llvm-project?rev=137091&view=rev Log: Add missing attributes to the C++ backend's output. Modified: llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp Modified: llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp?rev=137091&r1=137090&r2=137091&view=diff ============================================================================== --- llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp (original) +++ llvm/trunk/lib/Target/CppBackend/CPPBackend.cpp Mon Aug 8 19:47:30 2011 @@ -470,6 +470,9 @@ HANDLE_ATTR(NoImplicitFloat); HANDLE_ATTR(Naked); HANDLE_ATTR(InlineHint); + HANDLE_ATTR(Hotpatch); + HANDLE_ATTR(UWTable); + HANDLE_ATTR(NonLazyBind); #undef HANDLE_ATTR if (attrs & Attribute::StackAlignment) Out << " | Attribute::constructStackAlignmentFromInt(" From aggarwa4 at illinois.edu Mon Aug 8 19:58:33 2011 From: aggarwa4 at illinois.edu (Arushi Aggarwal) Date: Tue, 09 Aug 2011 00:58:33 -0000 Subject: [llvm-commits] [poolalloc] r137093 - in /poolalloc/trunk: include/assistDS/SimplifyGEP.h include/assistDS/SimplifyInsertValue.h include/assistDS/SimplifyLoad.h include/assistDS/StructReturnToPointer.h lib/AssistDS/SimplifyGEP.cpp lib/AssistDS/SimplifyInsertValue.cpp lib/AssistDS/SimplifyLoad.cpp lib/AssistDS/StructReturnToPointer.cpp Message-ID: <20110809005833.88F012A6C12C@llvm.org> Author: aggarwa4 Date: Mon Aug 8 19:58:33 2011 New Revision: 137093 URL: http://llvm.org/viewvc/llvm-project?rev=137093&view=rev Log: Move to mainline Modified: poolalloc/trunk/include/assistDS/SimplifyGEP.h poolalloc/trunk/include/assistDS/SimplifyInsertValue.h poolalloc/trunk/include/assistDS/SimplifyLoad.h poolalloc/trunk/include/assistDS/StructReturnToPointer.h poolalloc/trunk/lib/AssistDS/SimplifyGEP.cpp poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp poolalloc/trunk/lib/AssistDS/SimplifyLoad.cpp poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp Modified: poolalloc/trunk/include/assistDS/SimplifyGEP.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/SimplifyGEP.h?rev=137093&r1=137092&r2=137093&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/SimplifyGEP.h (original) +++ poolalloc/trunk/include/assistDS/SimplifyGEP.h Mon Aug 8 19:58:33 2011 @@ -25,7 +25,7 @@ TargetData * TD; public: static char ID; - SimplifyGEP() : ModulePass(&ID) {} + SimplifyGEP() : ModulePass(ID) {} virtual bool runOnModule(Module& M); virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); Modified: poolalloc/trunk/include/assistDS/SimplifyInsertValue.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/SimplifyInsertValue.h?rev=137093&r1=137092&r2=137093&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/SimplifyInsertValue.h (original) +++ poolalloc/trunk/include/assistDS/SimplifyInsertValue.h Mon Aug 8 19:58:33 2011 @@ -23,7 +23,7 @@ class SimplifyIV : public ModulePass { public: static char ID; - SimplifyIV() : ModulePass(&ID) {} + SimplifyIV() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/include/assistDS/SimplifyLoad.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/SimplifyLoad.h?rev=137093&r1=137092&r2=137093&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/SimplifyLoad.h (original) +++ poolalloc/trunk/include/assistDS/SimplifyLoad.h Mon Aug 8 19:58:33 2011 @@ -22,7 +22,7 @@ class SimplifyLoad : public ModulePass { public: static char ID; - SimplifyLoad() : ModulePass(&ID) {} + SimplifyLoad() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/include/assistDS/StructReturnToPointer.h URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/assistDS/StructReturnToPointer.h?rev=137093&r1=137092&r2=137093&view=diff ============================================================================== --- poolalloc/trunk/include/assistDS/StructReturnToPointer.h (original) +++ poolalloc/trunk/include/assistDS/StructReturnToPointer.h Mon Aug 8 19:58:33 2011 @@ -23,7 +23,7 @@ class StructRet : public ModulePass { public: static char ID; - StructRet() : ModulePass(&ID) {} + StructRet() : ModulePass(ID) {} virtual bool runOnModule(Module& M); }; } Modified: poolalloc/trunk/lib/AssistDS/SimplifyGEP.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/SimplifyGEP.cpp?rev=137093&r1=137092&r2=137093&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/SimplifyGEP.cpp (original) +++ poolalloc/trunk/lib/AssistDS/SimplifyGEP.cpp Mon Aug 8 19:58:33 2011 @@ -107,8 +107,7 @@ // -> GEP i8* X, ... SmallVector Idx(GEP->idx_begin()+1, GEP->idx_end()); GetElementPtrInst *Res = - GetElementPtrInst::Create(StrippedPtr, Idx.begin(), - Idx.end(), GEP->getName(), GEP); + GetElementPtrInst::Create(StrippedPtr, Idx, GEP->getName(), GEP); Res->setIsInBounds(GEP->isInBounds()); GEP->replaceAllUsesWith(Res); continue; @@ -132,8 +131,8 @@ // Transform things like: // %t = getelementptr i32* bitcast ([2 x i32]* %str to i32*), i32 %V // into: %t1 = getelementptr [2 x i32]* %str, i32 0, i32 %V; bitcast - const Type *SrcElTy = StrippedPtrTy->getElementType(); - const Type *ResElTy=cast(PtrOp->getType())->getElementType(); + Type *SrcElTy = StrippedPtrTy->getElementType(); + Type *ResElTy=cast(PtrOp->getType())->getElementType(); if (TD && SrcElTy->isArrayTy() && TD->getTypeAllocSize(cast(SrcElTy)->getElementType()) == TD->getTypeAllocSize(ResElTy)) { @@ -141,7 +140,7 @@ Idx[0] = Constant::getNullValue(Type::getInt32Ty(GEP->getContext())); Idx[1] = GEP->getOperand(1); Value *NewGEP = GetElementPtrInst::Create(StrippedPtr, Idx, - Idx+2, GEP->getName(), GEP); + GEP->getName(), GEP); // V and GEP are both pointer types --> BitCast GEP->replaceAllUsesWith(new BitCastInst(NewGEP, GEP->getType(), GEP->getName(), GEP)); continue; @@ -200,7 +199,7 @@ Idx[0] = Constant::getNullValue(Type::getInt32Ty(GEP->getContext())); Idx[1] = NewIdx; Value *NewGEP = GetElementPtrInst::Create(StrippedPtr, Idx, - Idx+2, GEP->getName(), GEP); + GEP->getName(), GEP); GEP->replaceAllUsesWith(new BitCastInst(NewGEP, GEP->getType(), GEP->getName(), GEP)); continue; } Modified: poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp?rev=137093&r1=137092&r2=137093&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp (original) +++ poolalloc/trunk/lib/AssistDS/SimplifyInsertValue.cpp Mon Aug 8 19:58:33 2011 @@ -63,7 +63,7 @@ if(IV->getNumUses() != 1) continue; // Check that its only use is a StoreInst - StoreInst *SI = dyn_cast(IV->use_begin()); + StoreInst *SI = dyn_cast(*(IV->use_begin())); if(!SI) continue; // Check that it is the stored value @@ -74,14 +74,14 @@ do { // replace by a series of gep/stores SmallVector Indices; - const Type *Int32Ty = Type::getInt32Ty(M.getContext()); + Type *Int32Ty = Type::getInt32Ty(M.getContext()); Indices.push_back(Constant::getNullValue(Int32Ty)); for (InsertValueInst::idx_iterator I = IV->idx_begin(), E = IV->idx_end(); I != E; ++I) { Indices.push_back(ConstantInt::get(Int32Ty, *I)); } - GetElementPtrInst *GEP = GetElementPtrInst::CreateInBounds(SI->getOperand(1), Indices.begin(), - Indices.end(), SI->getName(), SI) ; + GetElementPtrInst *GEP = GetElementPtrInst::CreateInBounds(SI->getOperand(1), Indices, + SI->getName(), SI) ; new StoreInst(IV->getInsertedValueOperand(), GEP, SI); IV = dyn_cast(IV->getAggregateOperand()); Modified: poolalloc/trunk/lib/AssistDS/SimplifyLoad.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/SimplifyLoad.cpp?rev=137093&r1=137092&r2=137093&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/SimplifyLoad.cpp (original) +++ poolalloc/trunk/lib/AssistDS/SimplifyLoad.cpp Mon Aug 8 19:58:33 2011 @@ -57,7 +57,7 @@ if(!LI) continue; if(LI->getNumUses() == 1) { - if(CastInst *CI = dyn_cast(LI->use_begin())) { + if(CastInst *CI = dyn_cast(*(LI->use_begin()))) { if(LI->getType()->isPointerTy()) { if(ConstantExpr *CE = dyn_cast(LI->getOperand(0))) { if(const PointerType *PTy = dyn_cast(CE->getOperand(0)->getType())) Modified: poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp?rev=137093&r1=137092&r2=137093&view=diff ============================================================================== --- poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp (original) +++ poolalloc/trunk/lib/AssistDS/StructReturnToPointer.cpp Mon Aug 8 19:58:33 2011 @@ -17,6 +17,7 @@ #include "llvm/Attributes.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/ValueMap.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/Debug.h" @@ -60,23 +61,23 @@ while(!worklist.empty()) { Function *F = worklist.back(); worklist.pop_back(); - const Type *NewArgType = F->getReturnType()->getPointerTo(); + Type *NewArgType = F->getReturnType()->getPointerTo(); // Construct the new Type - std::vectorTP; + std::vectorTP; TP.push_back(NewArgType); 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(F->getReturnType(), TP, F->isVarArg()); + FunctionType *NFTy = FunctionType::get(F->getReturnType(), TP, F->isVarArg()); // Create the new function body and insert it into the module. Function *NF = Function::Create(NFTy, GlobalValue::InternalLinkage, F->getName(), &M); - DenseMap ValueMap; + ValueToValueMapTy ValueMap; Function::arg_iterator NI = NF->arg_begin(); NI->setName("ret"); ++NI; @@ -87,7 +88,7 @@ } // Perform the cloning. SmallVector Returns; - CloneFunctionInto(NF, F, ValueMap, Returns); + CloneFunctionInto(NF, F, ValueMap, false, Returns); std::vector fargs; for(Function::arg_iterator ai = NF->arg_begin(), ae= NF->arg_end(); ai != ae; ++ai) { @@ -109,7 +110,7 @@ for(Value::use_iterator ui = F->use_begin(), ue = F->use_end(); ui != ue; ) { - CallInst *CI = dyn_cast(ui++); + CallInst *CI = dyn_cast(*ui++); if(!CI) continue; if(CI->getCalledFunction() != F) @@ -143,7 +144,7 @@ AttrListPtr NewCallPAL = AttrListPtr::get(AttributesVec.begin(), AttributesVec.end()); - CallInst *CallI = CallInst::Create(NF, Args.begin(), Args.end(), "", CI); + CallInst *CallI = CallInst::Create(NF, Args, "", CI); CallI->setCallingConv(CI->getCallingConv()); CallI->setAttributes(NewCallPAL); LoadInst *LI = new LoadInst(AllocaNew, "", CI); From stoklund at 2pi.dk Mon Aug 8 20:01:27 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 09 Aug 2011 01:01:27 -0000 Subject: [llvm-commits] [llvm] r137094 - in /llvm/trunk/lib/CodeGen: RegisterCoalescer.cpp RegisterCoalescer.h Message-ID: <20110809010127.C8DC32A6C12C@llvm.org> Author: stoklund Date: Mon Aug 8 20:01:27 2011 New Revision: 137094 URL: http://llvm.org/viewvc/llvm-project?rev=137094&view=rev Log: Rename member variables to follow coding standards. No functional change. Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp llvm/trunk/lib/CodeGen/RegisterCoalescer.h Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp?rev=137094&r1=137093&r2=137094&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp (original) +++ llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp Mon Aug 8 20:01:27 2011 @@ -78,14 +78,14 @@ namespace { class RegisterCoalescer : public MachineFunctionPass { - MachineFunction* mf_; - MachineRegisterInfo* mri_; - const TargetMachine* tm_; - const TargetRegisterInfo* tri_; - const TargetInstrInfo* tii_; - LiveIntervals *li_; - LiveDebugVariables *ldv_; - const MachineLoopInfo* loopInfo; + MachineFunction* MF; + MachineRegisterInfo* MRI; + const TargetMachine* TM; + const TargetRegisterInfo* TRI; + const TargetInstrInfo* TII; + LiveIntervals *LIS; + LiveDebugVariables *LDV; + const MachineLoopInfo* Loops; AliasAnalysis *AA; RegisterClassInfo RegClassInfo; @@ -240,14 +240,14 @@ } bool CoalescerPair::setRegisters(const MachineInstr *MI) { - srcReg_ = dstReg_ = subIdx_ = 0; - newRC_ = 0; - flipped_ = crossClass_ = false; + SrcReg = DstReg = SubIdx = 0; + NewRC = 0; + Flipped = CrossClass = false; unsigned Src, Dst, SrcSub, DstSub; - if (!isMoveInstr(tri_, MI, Src, Dst, SrcSub, DstSub)) + if (!isMoveInstr(TRI, MI, Src, Dst, SrcSub, DstSub)) return false; - partial_ = SrcSub || DstSub; + Partial = SrcSub || DstSub; // If one register is a physreg, it must be Dst. if (TargetRegisterInfo::isPhysicalRegister(Src)) { @@ -255,7 +255,7 @@ return false; std::swap(Src, Dst); std::swap(SrcSub, DstSub); - flipped_ = true; + Flipped = true; } const MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo(); @@ -263,14 +263,14 @@ if (TargetRegisterInfo::isPhysicalRegister(Dst)) { // Eliminate DstSub on a physreg. if (DstSub) { - Dst = tri_.getSubReg(Dst, DstSub); + Dst = TRI.getSubReg(Dst, DstSub); if (!Dst) return false; DstSub = 0; } // Eliminate SrcSub by picking a corresponding Dst superregister. if (SrcSub) { - Dst = tri_.getMatchingSuperReg(Dst, SrcSub, MRI.getRegClass(Src)); + Dst = TRI.getMatchingSuperReg(Dst, SrcSub, MRI.getRegClass(Src)); if (!Dst) return false; SrcSub = 0; } else if (!MRI.getRegClass(Src)->contains(Dst)) { @@ -298,36 +298,36 @@ std::swap(Src, Dst); DstSub = SrcSub; SrcSub = 0; - assert(!flipped_ && "Unexpected flip"); - flipped_ = true; + assert(!Flipped && "Unexpected flip"); + Flipped = true; } // Find the new register class. const TargetRegisterClass *SrcRC = MRI.getRegClass(Src); const TargetRegisterClass *DstRC = MRI.getRegClass(Dst); if (DstSub) - newRC_ = tri_.getMatchingSuperRegClass(DstRC, SrcRC, DstSub); + NewRC = TRI.getMatchingSuperRegClass(DstRC, SrcRC, DstSub); else - newRC_ = getCommonSubClass(DstRC, SrcRC); - if (!newRC_) + NewRC = getCommonSubClass(DstRC, SrcRC); + if (!NewRC) return false; - crossClass_ = newRC_ != DstRC || newRC_ != SrcRC; + CrossClass = NewRC != DstRC || NewRC != SrcRC; } // Check our invariants assert(TargetRegisterInfo::isVirtualRegister(Src) && "Src must be virtual"); assert(!(TargetRegisterInfo::isPhysicalRegister(Dst) && DstSub) && "Cannot have a physical SubIdx"); - srcReg_ = Src; - dstReg_ = Dst; - subIdx_ = DstSub; + SrcReg = Src; + DstReg = Dst; + SubIdx = DstSub; return true; } bool CoalescerPair::flip() { - if (subIdx_ || TargetRegisterInfo::isPhysicalRegister(dstReg_)) + if (SubIdx || TargetRegisterInfo::isPhysicalRegister(DstReg)) return false; - std::swap(srcReg_, dstReg_); - flipped_ = !flipped_; + std::swap(SrcReg, DstReg); + Flipped = !Flipped; return true; } @@ -335,36 +335,36 @@ if (!MI) return false; unsigned Src, Dst, SrcSub, DstSub; - if (!isMoveInstr(tri_, MI, Src, Dst, SrcSub, DstSub)) + if (!isMoveInstr(TRI, MI, Src, Dst, SrcSub, DstSub)) return false; - // Find the virtual register that is srcReg_. - if (Dst == srcReg_) { + // Find the virtual register that is SrcReg. + if (Dst == SrcReg) { std::swap(Src, Dst); std::swap(SrcSub, DstSub); - } else if (Src != srcReg_) { + } else if (Src != SrcReg) { return false; } - // Now check that Dst matches dstReg_. - if (TargetRegisterInfo::isPhysicalRegister(dstReg_)) { + // Now check that Dst matches DstReg. + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) { if (!TargetRegisterInfo::isPhysicalRegister(Dst)) return false; - assert(!subIdx_ && "Inconsistent CoalescerPair state."); + assert(!SubIdx && "Inconsistent CoalescerPair state."); // DstSub could be set for a physreg from INSERT_SUBREG. if (DstSub) - Dst = tri_.getSubReg(Dst, DstSub); + Dst = TRI.getSubReg(Dst, DstSub); // Full copy of Src. if (!SrcSub) - return dstReg_ == Dst; + return DstReg == Dst; // This is a partial register copy. Check that the parts match. - return tri_.getSubReg(dstReg_, SrcSub) == Dst; + return TRI.getSubReg(DstReg, SrcSub) == Dst; } else { - // dstReg_ is virtual. - if (dstReg_ != Dst) + // DstReg is virtual. + if (DstReg != Dst) return false; // Registers match, do the subregisters line up? - return compose(tri_, subIdx_, SrcSub) == DstSub; + return compose(TRI, SubIdx, SrcSub) == DstSub; } } @@ -416,14 +416,14 @@ MachineInstr *CopyMI) { // Bail if there is no dst interval - can happen when merging physical subreg // operations. - if (!li_->hasInterval(CP.getDstReg())) + if (!LIS->hasInterval(CP.getDstReg())) return false; LiveInterval &IntA = - li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); + LIS->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); LiveInterval &IntB = - li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + LIS->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); + SlotIndex CopyIdx = LIS->getInstructionIndex(CopyMI).getDefIndex(); // BValNo is a value number in B that is defined by a copy from A. 'B3' in // the example above. @@ -479,7 +479,7 @@ // Make sure that the end of the live range is inside the same block as // CopyMI. MachineInstr *ValLREndInst = - li_->getInstructionFromIndex(ValLR->end.getPrevSlot()); + LIS->getInstructionFromIndex(ValLR->end.getPrevSlot()); if (!ValLREndInst || ValLREndInst->getParent() != CopyMI->getParent()) return false; @@ -492,11 +492,11 @@ // 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))) { + for (const unsigned *AS = TRI->getAliasSet(IntB.reg); *AS; ++AS) + if (LIS->hasInterval(*AS) && IntA.overlaps(LIS->getInterval(*AS))) { DEBUG({ dbgs() << "\t\tInterfere with alias "; - li_->getInterval(*AS).print(dbgs(), tri_); + LIS->getInterval(*AS).print(dbgs(), TRI); }); return false; } @@ -504,7 +504,7 @@ DEBUG({ dbgs() << "Extending: "; - IntB.print(dbgs(), tri_); + IntB.print(dbgs(), TRI); }); SlotIndex FillerStart = ValLR->end, FillerEnd = BLR->start; @@ -522,13 +522,13 @@ // If the IntB live range is assigned to a physical register, and if that // physreg has sub-registers, update their live intervals as well. if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) { - for (const unsigned *SR = tri_->getSubRegisters(IntB.reg); *SR; ++SR) { - if (!li_->hasInterval(*SR)) + for (const unsigned *SR = TRI->getSubRegisters(IntB.reg); *SR; ++SR) { + if (!LIS->hasInterval(*SR)) continue; - LiveInterval &SRLI = li_->getInterval(*SR); + LiveInterval &SRLI = LIS->getInterval(*SR); SRLI.addRange(LiveRange(FillerStart, FillerEnd, SRLI.getNextValue(FillerStart, 0, - li_->getVNInfoAllocator()))); + LIS->getVNInfoAllocator()))); } } @@ -543,7 +543,7 @@ } DEBUG({ dbgs() << " result = "; - IntB.print(dbgs(), tri_); + IntB.print(dbgs(), TRI); dbgs() << "\n"; }); @@ -558,7 +558,7 @@ // merge, find the last use and trim the live range. That will also add the // isKill marker. if (ALR->end == CopyIdx) - li_->shrinkToUses(&IntA); + LIS->shrinkToUses(&IntA); ++numExtends; return true; @@ -622,15 +622,15 @@ return false; // Bail if there is no dst interval. - if (!li_->hasInterval(CP.getDstReg())) + if (!LIS->hasInterval(CP.getDstReg())) return false; - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); + SlotIndex CopyIdx = LIS->getInstructionIndex(CopyMI).getDefIndex(); LiveInterval &IntA = - li_->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); + LIS->getInterval(CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg()); LiveInterval &IntB = - li_->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); + LIS->getInterval(CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg()); // BValNo is a value number in B that is defined by a copy from A. 'B3' in // the example above. @@ -648,7 +648,7 @@ // the optimization. if (AValNo->isPHIDef() || AValNo->isUnused() || AValNo->hasPHIKill()) return false; - MachineInstr *DefMI = li_->getInstructionFromIndex(AValNo->def); + MachineInstr *DefMI = LIS->getInstructionFromIndex(AValNo->def); if (!DefMI) return false; const MCInstrDesc &MCID = DefMI->getDesc(); @@ -662,7 +662,7 @@ if (!DefMI->isRegTiedToUseOperand(DefIdx, &UseOpIdx)) return false; unsigned Op1, Op2, NewDstIdx; - if (!tii_->findCommutedOpIndices(DefMI, Op1, Op2)) + if (!TII->findCommutedOpIndices(DefMI, Op1, Op2)) return false; if (Op1 == UseOpIdx) NewDstIdx = Op2; @@ -684,18 +684,18 @@ // Abort if the aliases of IntB.reg have values that are not simply the // clobbers from the superreg. if (TargetRegisterInfo::isPhysicalRegister(IntB.reg)) - for (const unsigned *AS = tri_->getAliasSet(IntB.reg); *AS; ++AS) - if (li_->hasInterval(*AS) && - HasOtherReachingDefs(IntA, li_->getInterval(*AS), AValNo, 0)) + for (const unsigned *AS = TRI->getAliasSet(IntB.reg); *AS; ++AS) + if (LIS->hasInterval(*AS) && + HasOtherReachingDefs(IntA, LIS->getInterval(*AS), AValNo, 0)) return false; // If some of the uses of IntA.reg is already coalesced away, return false. // It's not possible to determine whether it's safe to perform the coalescing. for (MachineRegisterInfo::use_nodbg_iterator UI = - mri_->use_nodbg_begin(IntA.reg), - UE = mri_->use_nodbg_end(); UI != UE; ++UI) { + MRI->use_nodbg_begin(IntA.reg), + UE = MRI->use_nodbg_end(); UI != UE; ++UI) { MachineInstr *UseMI = &*UI; - SlotIndex UseIdx = li_->getInstructionIndex(UseMI); + SlotIndex UseIdx = LIS->getInstructionIndex(UseMI); LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); if (ULR == IntA.end()) continue; @@ -709,15 +709,15 @@ // At this point we have decided that it is legal to do this // transformation. Start by commuting the instruction. MachineBasicBlock *MBB = DefMI->getParent(); - MachineInstr *NewMI = tii_->commuteInstruction(DefMI); + MachineInstr *NewMI = TII->commuteInstruction(DefMI); if (!NewMI) return false; if (TargetRegisterInfo::isVirtualRegister(IntA.reg) && TargetRegisterInfo::isVirtualRegister(IntB.reg) && - !mri_->constrainRegClass(IntB.reg, mri_->getRegClass(IntA.reg))) + !MRI->constrainRegClass(IntB.reg, MRI->getRegClass(IntA.reg))) return false; if (NewMI != DefMI) { - li_->ReplaceMachineInstrInMaps(DefMI, NewMI); + LIS->ReplaceMachineInstrInMaps(DefMI, NewMI); MBB->insert(DefMI, NewMI); MBB->erase(DefMI); } @@ -734,8 +734,8 @@ // = B // Update uses of IntA of the specific Val# with IntB. - for (MachineRegisterInfo::use_iterator UI = mri_->use_begin(IntA.reg), - UE = mri_->use_end(); UI != UE;) { + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(IntA.reg), + UE = MRI->use_end(); UI != UE;) { MachineOperand &UseMO = UI.getOperand(); MachineInstr *UseMI = &*UI; ++UI; @@ -747,12 +747,12 @@ UseMO.setReg(NewReg); continue; } - SlotIndex UseIdx = li_->getInstructionIndex(UseMI).getUseIndex(); + SlotIndex UseIdx = LIS->getInstructionIndex(UseMI).getUseIndex(); LiveInterval::iterator ULR = IntA.FindLiveRangeContaining(UseIdx); if (ULR == IntA.end() || ULR->valno != AValNo) continue; if (TargetRegisterInfo::isPhysicalRegister(NewReg)) - UseMO.substPhysReg(NewReg, *tri_); + UseMO.substPhysReg(NewReg, *TRI); else UseMO.setReg(NewReg); if (UseMI == CopyMI) @@ -800,7 +800,7 @@ unsigned DstReg, unsigned DstSubIdx, MachineInstr *CopyMI) { - SlotIndex CopyIdx = li_->getInstructionIndex(CopyMI).getUseIndex(); + SlotIndex CopyIdx = LIS->getInstructionIndex(CopyMI).getUseIndex(); LiveInterval::iterator SrcLR = SrcInt.FindLiveRangeContaining(CopyIdx); assert(SrcLR != SrcInt.end() && "Live range not found!"); VNInfo *ValNo = SrcLR->valno; @@ -808,17 +808,17 @@ // the optimization. if (ValNo->isPHIDef() || ValNo->isUnused() || ValNo->hasPHIKill()) return false; - MachineInstr *DefMI = li_->getInstructionFromIndex(ValNo->def); + MachineInstr *DefMI = LIS->getInstructionFromIndex(ValNo->def); if (!DefMI) return false; assert(DefMI && "Defining instruction disappeared"); const MCInstrDesc &MCID = DefMI->getDesc(); if (!MCID.isAsCheapAsAMove()) return false; - if (!tii_->isTriviallyReMaterializable(DefMI, AA)) + if (!TII->isTriviallyReMaterializable(DefMI, AA)) return false; bool SawStore = false; - if (!DefMI->isSafeToMove(tii_, AA, SawStore)) + if (!DefMI->isSafeToMove(TII, AA, SawStore)) return false; if (MCID.getNumDefs() != 1) return false; @@ -826,9 +826,9 @@ // Make sure the copy destination register class fits the instruction // definition register class. The mismatch can happen as a result of earlier // extract_subreg, insert_subreg, subreg_to_reg coalescing. - const TargetRegisterClass *RC = tii_->getRegClass(MCID, 0, tri_); + const TargetRegisterClass *RC = TII->getRegClass(MCID, 0, TRI); if (TargetRegisterInfo::isVirtualRegister(DstReg)) { - if (mri_->getRegClass(DstReg) != RC) + if (MRI->getRegClass(DstReg) != RC) return false; } else if (!RC->contains(DstReg)) return false; @@ -840,10 +840,10 @@ const MCInstrDesc &MCID = DefMI->getDesc(); if (MCID.getNumDefs() != 1) return false; - const TargetRegisterClass *DstRC = mri_->getRegClass(DstReg); + const TargetRegisterClass *DstRC = MRI->getRegClass(DstReg); const TargetRegisterClass *DstSubRC = DstRC->getSubRegisterRegClass(DstSubIdx); - const TargetRegisterClass *DefRC = tii_->getRegClass(MCID, 0, tri_); + const TargetRegisterClass *DefRC = TII->getRegClass(MCID, 0, TRI); if (DefRC == DstRC) DstSubIdx = 0; else if (DefRC != DstSubRC) @@ -855,7 +855,7 @@ MachineBasicBlock *MBB = CopyMI->getParent(); MachineBasicBlock::iterator MII = llvm::next(MachineBasicBlock::iterator(CopyMI)); - tii_->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI, *tri_); + TII->reMaterialize(*MBB, MII, DstReg, DstSubIdx, DefMI, *TRI); MachineInstr *NewMI = prior(MII); // CopyMI may have implicit operands, transfer them over to the newly @@ -870,7 +870,7 @@ } NewMI->copyImplicitOps(CopyMI); - li_->ReplaceMachineInstrInMaps(CopyMI, NewMI); + LIS->ReplaceMachineInstrInMaps(CopyMI, NewMI); CopyMI->eraseFromParent(); ReMatCopies.insert(CopyMI); ReMatDefs.insert(DefMI); @@ -879,7 +879,7 @@ // The source interval can become smaller because we removed a use. if (preserveSrcInt) - li_->shrinkToUses(&SrcInt); + LIS->shrinkToUses(&SrcInt); return true; } @@ -893,11 +893,11 @@ /// Any uses of that value number are marked as . bool RegisterCoalescer::eliminateUndefCopy(MachineInstr *CopyMI, const CoalescerPair &CP) { - SlotIndex Idx = li_->getInstructionIndex(CopyMI); - LiveInterval *SrcInt = &li_->getInterval(CP.getSrcReg()); + SlotIndex Idx = LIS->getInstructionIndex(CopyMI); + LiveInterval *SrcInt = &LIS->getInterval(CP.getSrcReg()); if (SrcInt->liveAt(Idx)) return false; - LiveInterval *DstInt = &li_->getInterval(CP.getDstReg()); + LiveInterval *DstInt = &LIS->getInterval(CP.getDstReg()); if (DstInt->liveAt(Idx)) return false; @@ -912,13 +912,13 @@ // Find new undef uses. for (MachineRegisterInfo::reg_nodbg_iterator - I = mri_->reg_nodbg_begin(DstInt->reg), E = mri_->reg_nodbg_end(); + I = MRI->reg_nodbg_begin(DstInt->reg), E = MRI->reg_nodbg_end(); I != E; ++I) { MachineOperand &MO = I.getOperand(); if (MO.isDef() || MO.isUndef()) continue; MachineInstr *MI = MO.getParent(); - SlotIndex Idx = li_->getInstructionIndex(MI); + SlotIndex Idx = LIS->getInstructionIndex(MI); if (DstInt->liveAt(Idx)) continue; MO.setIsUndef(true); @@ -940,9 +940,9 @@ unsigned SubIdx = CP.getSubIdx(); // Update LiveDebugVariables. - ldv_->renameRegister(SrcReg, DstReg, SubIdx); + LDV->renameRegister(SrcReg, DstReg, SubIdx); - for (MachineRegisterInfo::reg_iterator I = mri_->reg_begin(SrcReg); + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(SrcReg); MachineInstr *UseMI = I.skipInstruction();) { // A PhysReg copy that won't be coalesced can perhaps be rematerialized // instead. @@ -954,7 +954,7 @@ UseMI->getOperand(0).getReg() != SrcReg && UseMI->getOperand(0).getReg() != DstReg && !JoinedCopies.count(UseMI) && - ReMaterializeTrivialDef(li_->getInterval(SrcReg), false, + ReMaterializeTrivialDef(LIS->getInterval(SrcReg), false, UseMI->getOperand(0).getReg(), 0, UseMI)) continue; } @@ -971,9 +971,9 @@ Deads |= MO.isDead(); if (DstIsPhys) - MO.substPhysReg(DstReg, *tri_); + MO.substPhysReg(DstReg, *TRI); else - MO.substVirtReg(DstReg, SubIdx, *tri_); + MO.substVirtReg(DstReg, SubIdx, *TRI); } // This instruction is a copy that will be removed. @@ -984,19 +984,19 @@ // If UseMI was a simple SrcReg def, make sure we didn't turn it into a // read-modify-write of DstReg. if (Deads) - UseMI->addRegisterDead(DstReg, tri_); + UseMI->addRegisterDead(DstReg, TRI); else if (!Reads && Writes) - UseMI->addRegisterDefined(DstReg, tri_); + UseMI->addRegisterDefined(DstReg, TRI); // Kill flags apply to the whole physical register. if (DstIsPhys && Kills) - UseMI->addRegisterKilled(DstReg, tri_); + UseMI->addRegisterKilled(DstReg, TRI); } DEBUG({ dbgs() << "\t\tupdated: "; if (!UseMI->isDebugValue()) - dbgs() << li_->getInstructionIndex(UseMI) << "\t"; + dbgs() << LIS->getInstructionIndex(UseMI) << "\t"; dbgs() << *UseMI; }); } @@ -1005,18 +1005,18 @@ /// removeIntervalIfEmpty - Check if the live interval of a physical register /// is empty, if so remove it and also remove the empty intervals of its /// sub-registers. Return true if live interval is removed. -static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *li_, - const TargetRegisterInfo *tri_) { +static bool removeIntervalIfEmpty(LiveInterval &li, LiveIntervals *LIS, + const TargetRegisterInfo *TRI) { if (li.empty()) { if (TargetRegisterInfo::isPhysicalRegister(li.reg)) - for (const unsigned* SR = tri_->getSubRegisters(li.reg); *SR; ++SR) { - if (!li_->hasInterval(*SR)) + for (const unsigned* SR = TRI->getSubRegisters(li.reg); *SR; ++SR) { + if (!LIS->hasInterval(*SR)) continue; - LiveInterval &sli = li_->getInterval(*SR); + LiveInterval &sli = LIS->getInterval(*SR); if (sli.empty()) - li_->removeInterval(*SR); + LIS->removeInterval(*SR); } - li_->removeInterval(li.reg); + LIS->removeInterval(li.reg); return true; } return false; @@ -1026,29 +1026,29 @@ /// the val# it defines. If the live interval becomes empty, remove it as well. bool RegisterCoalescer::RemoveDeadDef(LiveInterval &li, MachineInstr *DefMI) { - SlotIndex DefIdx = li_->getInstructionIndex(DefMI).getDefIndex(); + SlotIndex DefIdx = LIS->getInstructionIndex(DefMI).getDefIndex(); LiveInterval::iterator MLR = li.FindLiveRangeContaining(DefIdx); if (DefIdx != MLR->valno->def) return false; li.removeValNo(MLR->valno); - return removeIntervalIfEmpty(li, li_, tri_); + return removeIntervalIfEmpty(li, LIS, TRI); } void RegisterCoalescer::RemoveCopyFlag(unsigned DstReg, const MachineInstr *CopyMI) { - SlotIndex DefIdx = li_->getInstructionIndex(CopyMI).getDefIndex(); - if (li_->hasInterval(DstReg)) { - LiveInterval &LI = li_->getInterval(DstReg); + SlotIndex DefIdx = LIS->getInstructionIndex(CopyMI).getDefIndex(); + if (LIS->hasInterval(DstReg)) { + LiveInterval &LI = LIS->getInterval(DstReg); if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) if (LR->valno->def == DefIdx) LR->valno->setCopy(0); } if (!TargetRegisterInfo::isPhysicalRegister(DstReg)) return; - for (const unsigned* AS = tri_->getAliasSet(DstReg); *AS; ++AS) { - if (!li_->hasInterval(*AS)) + for (const unsigned* AS = TRI->getAliasSet(DstReg); *AS; ++AS) { + if (!LIS->hasInterval(*AS)) continue; - LiveInterval &LI = li_->getInterval(*AS); + LiveInterval &LI = LIS->getInterval(*AS); if (const LiveRange *LR = LI.getLiveRangeContaining(DefIdx)) if (LR->valno->def == DefIdx) LR->valno->setCopy(0); @@ -1061,8 +1061,8 @@ /// are not spillable! If the destination interval uses are far away, think /// twice about coalescing them! bool RegisterCoalescer::shouldJoinPhys(CoalescerPair &CP) { - bool Allocatable = li_->isAllocatable(CP.getDstReg()); - LiveInterval &JoinVInt = li_->getInterval(CP.getSrcReg()); + bool Allocatable = LIS->isAllocatable(CP.getDstReg()); + LiveInterval &JoinVInt = LIS->getInterval(CP.getSrcReg()); /// Always join simple intervals that are defined by a single copy from a /// reserved register. This doesn't increase register pressure, so it is @@ -1085,8 +1085,8 @@ // Don't join with physregs that have a ridiculous number of live // ranges. The data structure performance is really bad when that // happens. - if (li_->hasInterval(CP.getDstReg()) && - li_->getInterval(CP.getDstReg()).ranges.size() > 1000) { + if (LIS->hasInterval(CP.getDstReg()) && + LIS->getInterval(CP.getDstReg()).ranges.size() > 1000) { ++numAborts; DEBUG(dbgs() << "\tPhysical register live interval too complicated, abort!\n"); @@ -1096,9 +1096,9 @@ // FIXME: Why are we skipping this test for partial copies? // CodeGen/X86/phys_subreg_coalesce-3.ll needs it. if (!CP.isPartial()) { - const TargetRegisterClass *RC = mri_->getRegClass(CP.getSrcReg()); + const TargetRegisterClass *RC = MRI->getRegClass(CP.getSrcReg()); unsigned Threshold = RegClassInfo.getNumAllocatableRegs(RC) * 2; - unsigned Length = li_->getApproximateInstructionCount(JoinVInt); + unsigned Length = LIS->getApproximateInstructionCount(JoinVInt); if (Length > Threshold) { ++numAborts; DEBUG(dbgs() << "\tMay tie down a physical register, abort!\n"); @@ -1124,12 +1124,12 @@ // Early exit if the function is fairly small, coalesce aggressively if // that's the case. For really special register classes with 3 or // fewer registers, be a bit more careful. - (li_->getFuncInstructionCount() / NewRCCount) < 8) + (LIS->getFuncInstructionCount() / NewRCCount) < 8) return true; - LiveInterval &SrcInt = li_->getInterval(SrcReg); - LiveInterval &DstInt = li_->getInterval(DstReg); - unsigned SrcSize = li_->getApproximateInstructionCount(SrcInt); - unsigned DstSize = li_->getApproximateInstructionCount(DstInt); + LiveInterval &SrcInt = LIS->getInterval(SrcReg); + LiveInterval &DstInt = LIS->getInterval(DstReg); + unsigned SrcSize = LIS->getApproximateInstructionCount(SrcInt); + unsigned DstSize = LIS->getApproximateInstructionCount(DstInt); // Coalesce aggressively if the intervals are small compared to the number of // registers in the new class. The number 4 is fairly arbitrary, chosen to be @@ -1139,10 +1139,10 @@ return true; // Estimate *register use density*. If it doubles or more, abort. - unsigned SrcUses = std::distance(mri_->use_nodbg_begin(SrcReg), - mri_->use_nodbg_end()); - unsigned DstUses = std::distance(mri_->use_nodbg_begin(DstReg), - mri_->use_nodbg_end()); + unsigned SrcUses = std::distance(MRI->use_nodbg_begin(SrcReg), + MRI->use_nodbg_end()); + unsigned DstUses = std::distance(MRI->use_nodbg_begin(DstReg), + MRI->use_nodbg_end()); unsigned NewUses = SrcUses + DstUses; unsigned NewSize = SrcSize + DstSize; if (SrcRC != NewRC && SrcSize > ThresSize) { @@ -1170,9 +1170,9 @@ if (JoinedCopies.count(CopyMI) || ReMatCopies.count(CopyMI)) return false; // Already done. - DEBUG(dbgs() << li_->getInstructionIndex(CopyMI) << '\t' << *CopyMI); + DEBUG(dbgs() << LIS->getInstructionIndex(CopyMI) << '\t' << *CopyMI); - CoalescerPair CP(*tii_, *tri_); + CoalescerPair CP(*TII, *TRI); if (!CP.setRegisters(CopyMI)) { DEBUG(dbgs() << "\tNot coalescable.\n"); return false; @@ -1192,8 +1192,8 @@ return false; // Not coalescable. } - DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), tri_) - << " with " << PrintReg(CP.getDstReg(), tri_, CP.getSubIdx()) + DEBUG(dbgs() << "\tConsidering merging " << PrintReg(CP.getSrcReg(), TRI) + << " with " << PrintReg(CP.getDstReg(), TRI, CP.getSubIdx()) << "\n"); // Enforce policies. @@ -1202,7 +1202,7 @@ // Before giving up coalescing, if definition of source is defined by // trivial computation, try rematerializing it. if (!CP.isFlipped() && - ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, + ReMaterializeTrivialDef(LIS->getInterval(CP.getSrcReg()), true, CP.getDstReg(), 0, CopyMI)) return true; return false; @@ -1216,8 +1216,8 @@ return false; } if (!isWinToJoinCrossClass(CP.getSrcReg(), CP.getDstReg(), - mri_->getRegClass(CP.getSrcReg()), - mri_->getRegClass(CP.getDstReg()), + MRI->getRegClass(CP.getSrcReg()), + MRI->getRegClass(CP.getDstReg()), CP.getNewRC())) { DEBUG(dbgs() << "\tAvoid coalescing to constrained register class.\n"); Again = true; // May be possible to coalesce later. @@ -1226,8 +1226,8 @@ } // When possible, let DstReg be the larger interval. - if (!CP.getSubIdx() && li_->getInterval(CP.getSrcReg()).ranges.size() > - li_->getInterval(CP.getDstReg()).ranges.size()) + if (!CP.getSubIdx() && LIS->getInterval(CP.getSrcReg()).ranges.size() > + LIS->getInterval(CP.getDstReg()).ranges.size()) CP.flip(); } @@ -1241,7 +1241,7 @@ // If definition of source is defined by trivial computation, try // rematerializing it. if (!CP.isFlipped() && - ReMaterializeTrivialDef(li_->getInterval(CP.getSrcReg()), true, + ReMaterializeTrivialDef(LIS->getInterval(CP.getSrcReg()), true, CP.getDstReg(), 0, CopyMI)) return true; @@ -1265,7 +1265,7 @@ // other. Make sure the resulting register is set to the right register class. if (CP.isCrossClass()) { ++numCrossRCs; - mri_->setRegClass(CP.getDstReg(), CP.getNewRC()); + MRI->setRegClass(CP.getDstReg(), CP.getNewRC()); } // Remember to delete the copy instruction. @@ -1279,10 +1279,10 @@ SmallVector BlockSeq; // JoinIntervals invalidates the VNInfos in SrcInt, but we only need the // ranges for this, and they are preserved. - LiveInterval &SrcInt = li_->getInterval(CP.getSrcReg()); + LiveInterval &SrcInt = LIS->getInterval(CP.getSrcReg()); for (LiveInterval::const_iterator I = SrcInt.begin(), E = SrcInt.end(); I != E; ++I ) { - li_->findLiveInMBBs(I->start, I->end, BlockSeq); + LIS->findLiveInMBBs(I->start, I->end, BlockSeq); for (unsigned idx = 0, size = BlockSeq.size(); idx != size; ++idx) { MachineBasicBlock &block = *BlockSeq[idx]; if (!block.isLiveIn(CP.getDstReg())) @@ -1294,15 +1294,15 @@ // SrcReg is guarateed to be the register whose live interval that is // being merged. - li_->removeInterval(CP.getSrcReg()); + LIS->removeInterval(CP.getSrcReg()); // Update regalloc hint. - tri_->UpdateRegAllocHint(CP.getSrcReg(), CP.getDstReg(), *mf_); + TRI->UpdateRegAllocHint(CP.getSrcReg(), CP.getDstReg(), *MF); DEBUG({ - LiveInterval &DstInt = li_->getInterval(CP.getDstReg()); + LiveInterval &DstInt = LIS->getInterval(CP.getDstReg()); dbgs() << "\tJoined. Result = "; - DstInt.print(dbgs(), tri_); + DstInt.print(dbgs(), TRI); dbgs() << "\n"; }); @@ -1433,18 +1433,18 @@ /// JoinIntervals - Attempt to join these two intervals. On failure, this /// returns false. bool RegisterCoalescer::JoinIntervals(CoalescerPair &CP) { - LiveInterval &RHS = li_->getInterval(CP.getSrcReg()); - DEBUG({ dbgs() << "\t\tRHS = "; RHS.print(dbgs(), tri_); dbgs() << "\n"; }); + LiveInterval &RHS = LIS->getInterval(CP.getSrcReg()); + DEBUG({ dbgs() << "\t\tRHS = "; RHS.print(dbgs(), TRI); dbgs() << "\n"; }); // If a live interval is a physical register, check for interference with any // aliases. The interference check implemented here is a bit more conservative // than the full interfeence check below. We allow overlapping live ranges // only when one is a copy of the other. if (CP.isPhys()) { - for (const unsigned *AS = tri_->getAliasSet(CP.getDstReg()); *AS; ++AS){ - if (!li_->hasInterval(*AS)) + for (const unsigned *AS = TRI->getAliasSet(CP.getDstReg()); *AS; ++AS){ + if (!LIS->hasInterval(*AS)) continue; - const LiveInterval &LHS = li_->getInterval(*AS); + const LiveInterval &LHS = LIS->getInterval(*AS); LiveInterval::const_iterator LI = LHS.begin(); for (LiveInterval::const_iterator RI = RHS.begin(), RE = RHS.end(); RI != RE; ++RI) { @@ -1452,10 +1452,10 @@ // Does LHS have an overlapping live range starting before RI? if ((LI != LHS.begin() && LI[-1].end > RI->start) && (RI->start != RI->valno->def || - !CP.isCoalescable(li_->getInstructionFromIndex(RI->start)))) { + !CP.isCoalescable(LIS->getInstructionFromIndex(RI->start)))) { DEBUG({ dbgs() << "\t\tInterference from alias: "; - LHS.print(dbgs(), tri_); + LHS.print(dbgs(), TRI); dbgs() << "\n\t\tOverlap at " << RI->start << " and no copy.\n"; }); return false; @@ -1464,10 +1464,10 @@ // Check that LHS ranges beginning in this range are copies. for (; LI != LHS.end() && LI->start < RI->end; ++LI) { if (LI->start != LI->valno->def || - !CP.isCoalescable(li_->getInstructionFromIndex(LI->start))) { + !CP.isCoalescable(LIS->getInstructionFromIndex(LI->start))) { DEBUG({ dbgs() << "\t\tInterference from alias: "; - LHS.print(dbgs(), tri_); + LHS.print(dbgs(), TRI); dbgs() << "\n\t\tDef at " << LI->start << " is not a copy.\n"; }); return false; @@ -1487,8 +1487,8 @@ SmallVector DupCopies; - LiveInterval &LHS = li_->getOrCreateInterval(CP.getDstReg()); - DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), tri_); dbgs() << "\n"; }); + LiveInterval &LHS = LIS->getOrCreateInterval(CP.getDstReg()); + DEBUG({ dbgs() << "\t\tLHS = "; LHS.print(dbgs(), TRI); dbgs() << "\n"; }); // Loop over the value numbers of the LHS, seeing if any are defined from // the RHS. @@ -1511,7 +1511,7 @@ // from the RHS interval, we can use its value #. MachineInstr *MI = VNI->getCopy(); if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*li_, *tri_, CP, VNI, lr, DupCopies)) + !RegistersDefinedFromSameValue(*LIS, *TRI, CP, VNI, lr, DupCopies)) continue; LHSValsDefinedFromRHS[VNI] = lr->valno; @@ -1538,7 +1538,7 @@ // from the LHS interval, we can use its value #. MachineInstr *MI = VNI->getCopy(); if (!CP.isCoalescable(MI) && - !RegistersDefinedFromSameValue(*li_, *tri_, CP, VNI, lr, DupCopies)) + !RegistersDefinedFromSameValue(*LIS, *TRI, CP, VNI, lr, DupCopies)) continue; RHSValsDefinedFromLHS[VNI] = lr->valno; @@ -1660,7 +1660,7 @@ // and mark the X as coalesced to keep the illusion. unsigned Src = MI->getOperand(1).getReg(); SourceRegisters.push_back(Src); - MI->getOperand(0).substVirtReg(Src, 0, *tri_); + MI->getOperand(0).substVirtReg(Src, 0, *TRI); markAsJoined(MI); } @@ -1669,13 +1669,13 @@ // that B = X is gone. for (SmallVector::iterator I = SourceRegisters.begin(), E = SourceRegisters.end(); I != E; ++I) { - li_->shrinkToUses(&li_->getInterval(*I)); + LIS->shrinkToUses(&LIS->getInterval(*I)); } // If we get here, we know that we can coalesce the live ranges. Ask the // intervals to coalesce themselves now. LHS.join(RHS, &LHSValNoAssignments[0], &RHSValNoAssignments[0], NewVNInfo, - mri_); + MRI); return true; } @@ -1726,7 +1726,7 @@ bool SrcIsPhys = TargetRegisterInfo::isPhysicalRegister(SrcReg); bool DstIsPhys = TargetRegisterInfo::isPhysicalRegister(DstReg); - if (li_->hasInterval(SrcReg) && li_->getInterval(SrcReg).empty()) + if (LIS->hasInterval(SrcReg) && LIS->getInterval(SrcReg).empty()) ImpDefCopies.push_back(Inst); else if (SrcIsPhys || DstIsPhys) PhysCopies.push_back(Inst); @@ -1764,9 +1764,9 @@ DEBUG(dbgs() << "********** JOINING INTERVALS ***********\n"); std::vector TryAgainList; - if (loopInfo->empty()) { + if (Loops->empty()) { // If there are no loops in the function, join intervals in function order. - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end(); + for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E; ++I) CopyCoalesceInMBB(I, TryAgainList); } else { @@ -1777,9 +1777,9 @@ // Join intervals in the function prolog first. We want to join physical // registers with virtual registers before the intervals got too long. std::vector > MBBs; - for (MachineFunction::iterator I = mf_->begin(), E = mf_->end();I != E;++I){ + for (MachineFunction::iterator I = MF->begin(), E = MF->end();I != E;++I){ MachineBasicBlock *MBB = I; - MBBs.push_back(std::make_pair(loopInfo->getLoopDepth(MBB), I)); + MBBs.push_back(std::make_pair(Loops->getLoopDepth(MBB), I)); } // Sort by loop depth. @@ -1818,22 +1818,22 @@ } bool RegisterCoalescer::runOnMachineFunction(MachineFunction &fn) { - mf_ = &fn; - mri_ = &fn.getRegInfo(); - tm_ = &fn.getTarget(); - tri_ = tm_->getRegisterInfo(); - tii_ = tm_->getInstrInfo(); - li_ = &getAnalysis(); - ldv_ = &getAnalysis(); + MF = &fn; + MRI = &fn.getRegInfo(); + TM = &fn.getTarget(); + TRI = TM->getRegisterInfo(); + TII = TM->getInstrInfo(); + LIS = &getAnalysis(); + LDV = &getAnalysis(); AA = &getAnalysis(); - loopInfo = &getAnalysis(); + Loops = &getAnalysis(); DEBUG(dbgs() << "********** SIMPLE REGISTER COALESCING **********\n" << "********** Function: " - << ((Value*)mf_->getFunction())->getName() << '\n'); + << ((Value*)MF->getFunction())->getName() << '\n'); if (VerifyCoalescing) - mf_->verify(this, "Before register coalescing"); + MF->verify(this, "Before register coalescing"); RegClassInfo.runOnMachineFunction(fn); @@ -1842,9 +1842,9 @@ joinIntervals(); DEBUG({ dbgs() << "********** INTERVALS POST JOINING **********\n"; - for (LiveIntervals::iterator I = li_->begin(), E = li_->end(); + for (LiveIntervals::iterator I = LIS->begin(), E = LIS->end(); I != E; ++I){ - I->second->print(dbgs(), tri_); + I->second->print(dbgs(), TRI); dbgs() << "\n"; } }); @@ -1853,7 +1853,7 @@ // Perform a final pass over the instructions and compute spill weights // and remove identity moves. SmallVector DeadDefs; - for (MachineFunction::iterator mbbi = mf_->begin(), mbbe = mf_->end(); + for (MachineFunction::iterator mbbi = MF->begin(), mbbe = MF->end(); mbbi != mbbe; ++mbbi) { MachineBasicBlock* mbb = mbbi; for (MachineBasicBlock::iterator mii = mbb->begin(), mie = mbb->end(); @@ -1875,8 +1875,8 @@ if (MI->allDefsAreDead()) { if (TargetRegisterInfo::isVirtualRegister(SrcReg) && - li_->hasInterval(SrcReg)) - li_->shrinkToUses(&li_->getInterval(SrcReg)); + LIS->hasInterval(SrcReg)) + LIS->shrinkToUses(&LIS->getInterval(SrcReg)); DoDelete = true; } if (!DoDelete) { @@ -1885,10 +1885,10 @@ MI->RemoveOperand(3); MI->RemoveOperand(1); } - MI->setDesc(tii_->get(TargetOpcode::KILL)); + MI->setDesc(TII->get(TargetOpcode::KILL)); mii = llvm::next(mii); } else { - li_->RemoveMachineInstrFromMaps(MI); + LIS->RemoveMachineInstrFromMaps(MI); mii = mbbi->erase(mii); ++numPeep; } @@ -1910,7 +1910,7 @@ if (MO.isDead()) continue; if (TargetRegisterInfo::isPhysicalRegister(Reg) || - !mri_->use_nodbg_empty(Reg)) { + !MRI->use_nodbg_empty(Reg)) { isDead = false; break; } @@ -1919,9 +1919,9 @@ while (!DeadDefs.empty()) { unsigned DeadDef = DeadDefs.back(); DeadDefs.pop_back(); - RemoveDeadDef(li_->getInterval(DeadDef), MI); + RemoveDeadDef(LIS->getInterval(DeadDef), MI); } - li_->RemoveMachineInstrFromMaps(mii); + LIS->RemoveMachineInstrFromMaps(mii); mii = mbbi->erase(mii); continue; } else @@ -1931,14 +1931,14 @@ ++mii; // Check for now unnecessary kill flags. - if (li_->isNotInMIMap(MI)) continue; - SlotIndex DefIdx = li_->getInstructionIndex(MI).getDefIndex(); + if (LIS->isNotInMIMap(MI)) continue; + SlotIndex DefIdx = LIS->getInstructionIndex(MI).getDefIndex(); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { MachineOperand &MO = MI->getOperand(i); if (!MO.isReg() || !MO.isKill()) continue; unsigned reg = MO.getReg(); - if (!reg || !li_->hasInterval(reg)) continue; - if (!li_->getInterval(reg).killedAt(DefIdx)) { + if (!reg || !LIS->hasInterval(reg)) continue; + if (!LIS->getInterval(reg).killedAt(DefIdx)) { MO.setIsKill(false); continue; } @@ -1946,22 +1946,22 @@ // remain alive. if (!TargetRegisterInfo::isPhysicalRegister(reg)) continue; - for (const unsigned *SR = tri_->getSubRegisters(reg); + for (const unsigned *SR = TRI->getSubRegisters(reg); unsigned S = *SR; ++SR) - if (li_->hasInterval(S) && li_->getInterval(S).liveAt(DefIdx)) - MI->addRegisterDefined(S, tri_); + if (LIS->hasInterval(S) && LIS->getInterval(S).liveAt(DefIdx)) + MI->addRegisterDefined(S, TRI); } } } DEBUG(dump()); - DEBUG(ldv_->dump()); + DEBUG(LDV->dump()); if (VerifyCoalescing) - mf_->verify(this, "After register coalescing"); + MF->verify(this, "After register coalescing"); return true; } /// print - Implement the dump method. void RegisterCoalescer::print(raw_ostream &O, const Module* m) const { - li_->print(O, m); + LIS->print(O, m); } Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.h?rev=137094&r1=137093&r2=137094&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegisterCoalescer.h (original) +++ llvm/trunk/lib/CodeGen/RegisterCoalescer.h Mon Aug 8 20:01:27 2011 @@ -26,46 +26,46 @@ /// two registers can be coalesced, CoalescerPair can determine if a copy /// instruction would become an identity copy after coalescing. class CoalescerPair { - const TargetInstrInfo &tii_; - const TargetRegisterInfo &tri_; + const TargetInstrInfo &TII; + const TargetRegisterInfo &TRI; - /// dstReg_ - The register that will be left after coalescing. It can be a + /// DstReg - The register that will be left after coalescing. It can be a /// virtual or physical register. - unsigned dstReg_; + unsigned DstReg; - /// srcReg_ - the virtual register that will be coalesced into dstReg. - unsigned srcReg_; + /// SrcReg - the virtual register that will be coalesced into dstReg. + unsigned SrcReg; - /// subReg_ - The subregister index of srcReg in dstReg_. It is possible the - /// coalesce srcReg_ into a subreg of the larger dstReg_ when dstReg_ is a + /// subReg_ - The subregister index of srcReg in DstReg. It is possible the + /// coalesce SrcReg into a subreg of the larger DstReg when DstReg is a /// virtual register. - unsigned subIdx_; + unsigned SubIdx; - /// partial_ - True when the original copy was a partial subregister copy. - bool partial_; + /// Partial - True when the original copy was a partial subregister copy. + bool Partial; - /// crossClass_ - True when both regs are virtual, and newRC is constrained. - bool crossClass_; + /// CrossClass - True when both regs are virtual, and newRC is constrained. + bool CrossClass; - /// flipped_ - True when DstReg and SrcReg are reversed from the oriignal copy - /// instruction. - bool flipped_; + /// Flipped - True when DstReg and SrcReg are reversed from the oriignal + /// copy instruction. + bool Flipped; - /// newRC_ - The register class of the coalesced register, or NULL if dstReg_ + /// NewRC - The register class of the coalesced register, or NULL if DstReg /// is a physreg. - const TargetRegisterClass *newRC_; + const TargetRegisterClass *NewRC; public: CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri) - : tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0), - partial_(false), crossClass_(false), flipped_(false), newRC_(0) {} + : TII(tii), TRI(tri), DstReg(0), SrcReg(0), SubIdx(0), + Partial(false), CrossClass(false), Flipped(false), NewRC(0) {} /// setRegisters - set registers to match the copy instruction MI. Return /// false if MI is not a coalescable copy instruction. bool setRegisters(const MachineInstr*); - /// flip - Swap srcReg_ and dstReg_. Return false if swapping is impossible - /// because dstReg_ is a physical register, or subIdx_ is set. + /// flip - Swap SrcReg and DstReg. Return false if swapping is impossible + /// because DstReg is a physical register, or SubIdx is set. bool flip(); /// isCoalescable - Return true if MI is a copy instruction that will become @@ -73,32 +73,33 @@ bool isCoalescable(const MachineInstr*) const; /// isPhys - Return true if DstReg is a physical register. - bool isPhys() const { return !newRC_; } + bool isPhys() const { return !NewRC; } - /// isPartial - Return true if the original copy instruction did not copy the - /// full register, but was a subreg operation. - bool isPartial() const { return partial_; } - - /// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller register class than DstReg's. - bool isCrossClass() const { return crossClass_; } + /// isPartial - Return true if the original copy instruction did not copy + /// the full register, but was a subreg operation. + bool isPartial() const { return Partial; } + + /// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller + /// register class than DstReg's. + bool isCrossClass() const { return CrossClass; } /// isFlipped - Return true when getSrcReg is the register being defined by /// the original copy instruction. - bool isFlipped() const { return flipped_; } + bool isFlipped() const { return Flipped; } /// getDstReg - Return the register (virtual or physical) that will remain /// after coalescing. - unsigned getDstReg() const { return dstReg_; } + unsigned getDstReg() const { return DstReg; } /// getSrcReg - Return the virtual register that will be coalesced away. - unsigned getSrcReg() const { return srcReg_; } + unsigned getSrcReg() const { return SrcReg; } /// getSubIdx - Return the subregister index in DstReg that SrcReg will be /// coalesced into, or 0. - unsigned getSubIdx() const { return subIdx_; } + unsigned getSubIdx() const { return SubIdx; } /// getNewRC - Return the register class of the coalesced register. - const TargetRegisterClass *getNewRC() const { return newRC_; } + const TargetRegisterClass *getNewRC() const { return NewRC; } }; } // End llvm namespace From dpatel at apple.com Mon Aug 8 20:03:14 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 09 Aug 2011 01:03:14 -0000 Subject: [llvm-commits] [llvm] r137095 - in /llvm/trunk: include/llvm/Analysis/DebugInfo.h lib/Analysis/DebugInfo.cpp Message-ID: <20110809010314.E05552A6C12C@llvm.org> Author: dpatel Date: Mon Aug 8 20:03:14 2011 New Revision: 137095 URL: http://llvm.org/viewvc/llvm-project?rev=137095&view=rev Log: Provide method to print variable's extended name which includes inline location. Modified: llvm/trunk/include/llvm/Analysis/DebugInfo.h llvm/trunk/lib/Analysis/DebugInfo.cpp Modified: llvm/trunk/include/llvm/Analysis/DebugInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/DebugInfo.h?rev=137095&r1=137094&r2=137095&view=diff ============================================================================== --- llvm/trunk/include/llvm/Analysis/DebugInfo.h (original) +++ llvm/trunk/include/llvm/Analysis/DebugInfo.h Mon Aug 8 20:03:14 2011 @@ -615,7 +615,7 @@ } /// getInlinedAt - If this variable is inlined then return inline location. - MDNode *getInlinedAt(); + MDNode *getInlinedAt() const; /// Verify - Verify that a variable descriptor is well formed. bool Verify() const; @@ -648,6 +648,8 @@ /// print - print variable. void print(raw_ostream &OS) const; + void printExtendedName(raw_ostream &OS) const; + /// dump - print variable to dbgs() with a newline. void dump() const; }; Modified: llvm/trunk/lib/Analysis/DebugInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/DebugInfo.cpp?rev=137095&r1=137094&r2=137095&view=diff ============================================================================== --- llvm/trunk/lib/Analysis/DebugInfo.cpp (original) +++ llvm/trunk/lib/Analysis/DebugInfo.cpp Mon Aug 8 20:03:14 2011 @@ -117,7 +117,7 @@ } /// getInlinedAt - If this variable is inlined then return inline location. -MDNode *DIVariable::getInlinedAt() { +MDNode *DIVariable::getInlinedAt() const { if (getVersion() <= llvm::LLVMDebugVersion9) return NULL; return dyn_cast_or_null(DbgNode->getOperand(7)); @@ -674,6 +674,42 @@ OS << "]\n"; } +static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS, + const LLVMContext &Ctx) { + if (!DL.isUnknown()) { // Print source line info. + DIScope Scope(DL.getScope(Ctx)); + // Omit the directory, because it's likely to be long and uninteresting. + if (Scope.Verify()) + CommentOS << Scope.getFilename(); + else + CommentOS << ""; + CommentOS << ':' << DL.getLine(); + if (DL.getCol() != 0) + CommentOS << ':' << DL.getCol(); + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(DL.getInlinedAt(Ctx)); + if (!InlinedAtDL.isUnknown()) { + CommentOS << " @[ "; + printDebugLoc(InlinedAtDL, CommentOS, Ctx); + CommentOS << " ]"; + } + } +} + +void DIVariable::printExtendedName(raw_ostream &OS) const { + const LLVMContext &Ctx = DbgNode->getContext(); + StringRef Res = getName(); + if (!Res.empty()) + OS << Res << "," << getLineNumber(); + if (MDNode *InlinedAt = getInlinedAt()) { + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(InlinedAt); + if (!InlinedAtDL.isUnknown()) { + OS << " @["; + printDebugLoc(InlinedAtDL, OS, Ctx); + OS << "]"; + } + } +} + /// print - Print variable. void DIVariable::print(raw_ostream &OS) const { StringRef Res = getName(); From dpatel at apple.com Mon Aug 8 20:03:35 2011 From: dpatel at apple.com (Devang Patel) Date: Tue, 09 Aug 2011 01:03:35 -0000 Subject: [llvm-commits] [llvm] r137096 - /llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp Message-ID: <20110809010335.8B8F82A6C12C@llvm.org> Author: dpatel Date: Mon Aug 8 20:03:35 2011 New Revision: 137096 URL: http://llvm.org/viewvc/llvm-project?rev=137096&view=rev Log: Print variable's inline location in debug output. Modified: llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp Modified: llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp?rev=137096&r1=137095&r2=137096&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp Mon Aug 8 20:03:35 2011 @@ -25,6 +25,7 @@ #include "llvm/Constants.h" #include "llvm/Metadata.h" #include "llvm/Value.h" +#include "llvm/Analysis/DebugInfo.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" @@ -317,8 +318,10 @@ } // namespace void UserValue::print(raw_ostream &OS, const TargetMachine *TM) { - if (const MDString *MDS = dyn_cast(variable->getOperand(2))) - OS << "!\"" << MDS->getString() << "\"\t"; + DIVariable DV(variable); + OS << "!\""; + DV.printExtendedName(OS); + OS << "\"\t"; if (offset) OS << '+' << offset; for (LocMap::const_iterator I = locInts.begin(); I.valid(); ++I) { From isanbard at gmail.com Mon Aug 8 20:09:22 2011 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 09 Aug 2011 01:09:22 -0000 Subject: [llvm-commits] [llvm] r137098 - /llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp Message-ID: <20110809010922.21DE72A6C12C@llvm.org> Author: void Date: Mon Aug 8 20:09:21 2011 New Revision: 137098 URL: http://llvm.org/viewvc/llvm-project?rev=137098&view=rev Log: Remove an instance where the 'unwind' instruction was created. The 'unwind' instruction was acting essentially as a placeholder, because it would be replaced at the end of this function by a branch to the "unwind handler". The 'unwind' instruction is going away, so use 'unreachable' instead, which serves the same purpose as a placeholder. Modified: llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp Modified: llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp?rev=137098&r1=137097&r2=137098&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp Mon Aug 8 20:09:21 2011 @@ -406,6 +406,7 @@ SmallVector Returns; SmallVector Unwinds; SmallVector Invokes; + SmallVector Unreachables; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { @@ -486,9 +487,10 @@ // Insert a load in the Catch 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). + // for a standard call). We insert an unreachable instruction here and + // modify the block to jump to the correct unwinding pad later. BasicBlock *UnwindBB = BasicBlock::Create(F.getContext(), "unwindbb", &F); - Unwinds.push_back(new UnwindInst(F.getContext(), UnwindBB)); + Unreachables.push_back(new UnreachableInst(F.getContext(), UnwindBB)); Value *CatchLoad = new LoadInst(InvokeNum, "invoke.num", true, CatchBB); SwitchInst *CatchSwitch = @@ -577,6 +579,12 @@ Unwinds[i]->eraseFromParent(); } + // Replace all inserted unreachables with a branch to the unwind handler. + for (unsigned i = 0, e = Unreachables.size(); i != e; ++i) { + BranchInst::Create(UnwindHandler, Unreachables[i]); + Unreachables[i]->eraseFromParent(); + } + // Finally, for any returns from this function, if this function contains an // invoke, restore the old jmpbuf pointer to its input value. if (OldJmpBufPtr) { From isanbard at gmail.com Mon Aug 8 20:17:10 2011 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 09 Aug 2011 01:17:10 -0000 Subject: [llvm-commits] [llvm] r137099 - /llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp Message-ID: <20110809011710.CEB002A6C12C@llvm.org> Author: void Date: Mon Aug 8 20:17:10 2011 New Revision: 137099 URL: http://llvm.org/viewvc/llvm-project?rev=137099&view=rev Log: There is only one instance of this placeholder being created. Just use that instead of a vector. Modified: llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp Modified: llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp?rev=137099&r1=137098&r2=137099&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/LowerInvoke.cpp Mon Aug 8 20:17:10 2011 @@ -406,7 +406,7 @@ SmallVector Returns; SmallVector Unwinds; SmallVector Invokes; - SmallVector Unreachables; + UnreachableInst* UnreachablePlaceholder = 0; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) if (ReturnInst *RI = dyn_cast(BB->getTerminator())) { @@ -490,7 +490,7 @@ // for a standard call). We insert an unreachable instruction here and // modify the block to jump to the correct unwinding pad later. BasicBlock *UnwindBB = BasicBlock::Create(F.getContext(), "unwindbb", &F); - Unreachables.push_back(new UnreachableInst(F.getContext(), UnwindBB)); + UnreachablePlaceholder = new UnreachableInst(F.getContext(), UnwindBB); Value *CatchLoad = new LoadInst(InvokeNum, "invoke.num", true, CatchBB); SwitchInst *CatchSwitch = @@ -579,10 +579,10 @@ Unwinds[i]->eraseFromParent(); } - // Replace all inserted unreachables with a branch to the unwind handler. - for (unsigned i = 0, e = Unreachables.size(); i != e; ++i) { - BranchInst::Create(UnwindHandler, Unreachables[i]); - Unreachables[i]->eraseFromParent(); + // Replace the inserted unreachable with a branch to the unwind handler. + if (UnreachablePlaceholder) { + BranchInst::Create(UnwindHandler, UnreachablePlaceholder); + UnreachablePlaceholder->eraseFromParent(); } // Finally, for any returns from this function, if this function contains an From bruno.cardoso at gmail.com Mon Aug 8 20:43:09 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 01:43:09 -0000 Subject: [llvm-commits] [llvm] r137100 - in /llvm/trunk: lib/Target/X86/X86InstrSSE.td test/CodeGen/X86/avx-load-store.ll Message-ID: <20110809014309.E7DAD2A6C12C@llvm.org> Author: bruno Date: Mon Aug 8 20:43:09 2011 New Revision: 137100 URL: http://llvm.org/viewvc/llvm-project?rev=137100&view=rev Log: Add two patterns to match special vmovss and vmovsd cases. Also fix the patterns already there to be more strict regarding the predicate. This fixes PR10558 Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/test/CodeGen/X86/avx-load-store.ll Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=137100&r1=137099&r2=137100&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Mon Aug 8 20:43:09 2011 @@ -186,26 +186,61 @@ (INSERT_SUBREG (v4f64 (IMPLICIT_DEF)), FR64:$src, sub_sd)>; let AddedComplexity = 20 in { +let Predicates = [HasSSE1] in { + // MOVSSrm zeros the high parts of the register; represent this + // with SUBREG_TO_REG. + def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), + (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>; + def : Pat<(v4f32 (scalar_to_vector (loadf32 addr:$src))), + (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>; + def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), + (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>; +} +let Predicates = [HasSSE2] in { + // MOVSDrm zeros the high parts of the register; represent this + // with SUBREG_TO_REG. + def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + def : Pat<(v2f64 (scalar_to_vector (loadf64 addr:$src))), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + def : Pat<(v2f64 (X86vzload addr:$src)), + (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; +} +} + +let AddedComplexity = 20, Predicates = [HasAVX] in { // MOVSSrm zeros the high parts of the register; represent this -// with SUBREG_TO_REG. +// with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 def : Pat<(v4f32 (X86vzmovl (v4f32 (scalar_to_vector (loadf32 addr:$src))))), - (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>; + (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_ss)>; def : Pat<(v4f32 (scalar_to_vector (loadf32 addr:$src))), - (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>; + (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_ss)>; def : Pat<(v4f32 (X86vzmovl (loadv4f32 addr:$src))), - (SUBREG_TO_REG (i32 0), (MOVSSrm addr:$src), sub_ss)>; + (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_ss)>; // MOVSDrm zeros the high parts of the register; represent this -// with SUBREG_TO_REG. +// with SUBREG_TO_REG. The AVX versions also write: DST[255:128] <- 0 def : Pat<(v2f64 (X86vzmovl (v2f64 (scalar_to_vector (loadf64 addr:$src))))), - (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>; def : Pat<(v2f64 (scalar_to_vector (loadf64 addr:$src))), - (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>; def : Pat<(v2f64 (X86vzmovl (loadv2f64 addr:$src))), - (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>; def : Pat<(v2f64 (X86vzmovl (bc_v2f64 (loadv4f32 addr:$src)))), - (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>; def : Pat<(v2f64 (X86vzload addr:$src)), - (SUBREG_TO_REG (i64 0), (MOVSDrm addr:$src), sub_sd)>; + (SUBREG_TO_REG (i64 0), (VMOVSDrm addr:$src), sub_sd)>; +// Represent the same patterns above but in the form they appear for +// 256-bit types +def : Pat<(v8f32 (X86vzmovl (insert_subvector undef, + (v4f32 (scalar_to_vector (loadf32 addr:$src))), (i32 0)))), + (SUBREG_TO_REG (i32 0), (VMOVSSrm addr:$src), sub_ss)>; +def : Pat<(v4f64 (X86vzmovl (insert_subvector undef, + (v2f64 (scalar_to_vector (loadf64 addr:$src))), (i32 0)))), + (SUBREG_TO_REG (i32 0), (VMOVSDrm addr:$src), sub_sd)>; } // Store scalar value to memory. Modified: llvm/trunk/test/CodeGen/X86/avx-load-store.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-load-store.ll?rev=137100&r1=137099&r2=137100&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-load-store.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-load-store.ll Mon Aug 8 20:43:09 2011 @@ -22,3 +22,21 @@ declare void @dummy(<4 x double>, <8 x float>, <4 x i64>) +;; +;; The two tests below check that we must fold load + scalar_to_vector +;; + ins_subvec+ zext into only a single vmovss or vmovsd + +; CHECK: vmovss (% +define <8 x float> @mov00(<8 x float> %v, float * %ptr) nounwind { + %val = load float* %ptr + %i0 = insertelement <8 x float> zeroinitializer, float %val, i32 0 + ret <8 x float> %i0 +} + +; CHECK: vmovsd (% +define <4 x double> @mov01(<4 x double> %v, double * %ptr) nounwind { + %val = load double* %ptr + %i0 = insertelement <4 x double> zeroinitializer, double %val, i32 0 + ret <4 x double> %i0 +} + From bruno.cardoso at gmail.com Mon Aug 8 22:04:23 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 03:04:23 -0000 Subject: [llvm-commits] [llvm] r137103 - in /llvm/trunk/test/CodeGen/X86: avx-128.ll avx-256-arith.ll avx-256-cmp.ll avx-256-cvt.ll avx-256-logic.ll avx-256-movdup.ll avx-256-splat.ll avx-256-unpack.ll avx-256.ll avx-arith.ll avx-basic.ll avx-cmp-fp.ll avx-cmp.ll avx-cvt.ll avx-logic.ll avx-movdup.ll avx-splat.ll avx-unpack.ll Message-ID: <20110809030423.83C3F2A6C12C@llvm.org> Author: bruno Date: Mon Aug 8 22:04:23 2011 New Revision: 137103 URL: http://llvm.org/viewvc/llvm-project?rev=137103&view=rev Log: Rename and tidy up tests Added: llvm/trunk/test/CodeGen/X86/avx-arith.ll - copied, changed from r137100, llvm/trunk/test/CodeGen/X86/avx-256-arith.ll llvm/trunk/test/CodeGen/X86/avx-basic.ll - copied, changed from r137100, llvm/trunk/test/CodeGen/X86/avx-256.ll llvm/trunk/test/CodeGen/X86/avx-cmp.ll - copied, changed from r137100, llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll llvm/trunk/test/CodeGen/X86/avx-cvt.ll - copied, changed from r137100, llvm/trunk/test/CodeGen/X86/avx-128.ll llvm/trunk/test/CodeGen/X86/avx-logic.ll - copied, changed from r137100, llvm/trunk/test/CodeGen/X86/avx-256-logic.ll llvm/trunk/test/CodeGen/X86/avx-movdup.ll - copied, changed from r137100, llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll llvm/trunk/test/CodeGen/X86/avx-splat.ll - copied, changed from r137100, llvm/trunk/test/CodeGen/X86/avx-256-splat.ll llvm/trunk/test/CodeGen/X86/avx-unpack.ll - copied, changed from r137100, llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll Removed: llvm/trunk/test/CodeGen/X86/avx-128.ll llvm/trunk/test/CodeGen/X86/avx-256-arith.ll llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll llvm/trunk/test/CodeGen/X86/avx-256-cvt.ll llvm/trunk/test/CodeGen/X86/avx-256-logic.ll llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll llvm/trunk/test/CodeGen/X86/avx-256-splat.ll llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll llvm/trunk/test/CodeGen/X86/avx-256.ll llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll Removed: llvm/trunk/test/CodeGen/X86/avx-128.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-128.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-128.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-128.ll (removed) @@ -1,72 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - - at z = common global <4 x float> zeroinitializer, align 16 - -define void @zero() nounwind ssp { -entry: - ; CHECK: vxorps - ; CHECK: vmovaps - store <4 x float> zeroinitializer, <4 x float>* @z, align 16 - ret void -} - -define void @fpext() nounwind uwtable { -entry: - %f = alloca float, align 4 - %d = alloca double, align 8 - %tmp = load float* %f, align 4 - ; CHECK: vcvtss2sd - %conv = fpext float %tmp to double - store double %conv, double* %d, align 8 - ret void -} - -; CHECK: vcvtsi2sdq (% -define double @funcA(i64* nocapture %e) nounwind uwtable readonly ssp { -entry: - %tmp1 = load i64* %e, align 8 - %conv = sitofp i64 %tmp1 to double - ret double %conv -} - -; CHECK: vcvtsi2sd (% -define double @funcB(i32* nocapture %e) nounwind uwtable readonly ssp { -entry: - %tmp1 = load i32* %e, align 4 - %conv = sitofp i32 %tmp1 to double - ret double %conv -} - -; CHECK: vcvtsi2ss (% -define float @funcC(i32* nocapture %e) nounwind uwtable readonly ssp { -entry: - %tmp1 = load i32* %e, align 4 - %conv = sitofp i32 %tmp1 to float - ret float %conv -} - -; CHECK: vcvtsi2ssq (% -define float @funcD(i64* nocapture %e) nounwind uwtable readonly ssp { -entry: - %tmp1 = load i64* %e, align 8 - %conv = sitofp i64 %tmp1 to float - ret float %conv -} - -; CHECK: vsqrtss -define float @sqrtA(float %a) nounwind uwtable readnone ssp { -entry: - %conv1 = tail call float @sqrtf(float %a) nounwind readnone - ret float %conv1 -} - -declare double @sqrt(double) readnone - -; CHECK: vsqrtsd -define double @sqrtB(double %a) nounwind uwtable readnone ssp { -entry: - %call = tail call double @sqrt(double %a) nounwind readnone - ret double %call -} - -declare float @sqrtf(float) readnone Removed: llvm/trunk/test/CodeGen/X86/avx-256-arith.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256-arith.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-arith.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-256-arith.ll (removed) @@ -1,116 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - -; CHECK: vaddpd -define <4 x double> @addpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp { -entry: - %add.i = fadd <4 x double> %x, %y - ret <4 x double> %add.i -} - -; CHECK: vaddpd LCP{{.*}}(%rip) -define <4 x double> @addpd256fold(<4 x double> %y) nounwind uwtable readnone ssp { -entry: - %add.i = fadd <4 x double> %y, - ret <4 x double> %add.i -} - -; CHECK: vaddps -define <8 x float> @addps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp { -entry: - %add.i = fadd <8 x float> %x, %y - ret <8 x float> %add.i -} - -; CHECK: vaddps LCP{{.*}}(%rip) -define <8 x float> @addps256fold(<8 x float> %y) nounwind uwtable readnone ssp { -entry: - %add.i = fadd <8 x float> %y, - ret <8 x float> %add.i -} - -; CHECK: vsubpd -define <4 x double> @subpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp { -entry: - %sub.i = fsub <4 x double> %x, %y - ret <4 x double> %sub.i -} - -; CHECK: vsubpd (% -define <4 x double> @subpd256fold(<4 x double> %y, <4 x double>* nocapture %x) nounwind uwtable readonly ssp { -entry: - %tmp2 = load <4 x double>* %x, align 32 - %sub.i = fsub <4 x double> %y, %tmp2 - ret <4 x double> %sub.i -} - -; CHECK: vsubps -define <8 x float> @subps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp { -entry: - %sub.i = fsub <8 x float> %x, %y - ret <8 x float> %sub.i -} - -; CHECK: vsubps (% -define <8 x float> @subps256fold(<8 x float> %y, <8 x float>* nocapture %x) nounwind uwtable readonly ssp { -entry: - %tmp2 = load <8 x float>* %x, align 32 - %sub.i = fsub <8 x float> %y, %tmp2 - ret <8 x float> %sub.i -} - -; CHECK: vmulpd -define <4 x double> @mulpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp { -entry: - %mul.i = fmul <4 x double> %x, %y - ret <4 x double> %mul.i -} - -; CHECK: vmulpd LCP{{.*}}(%rip) -define <4 x double> @mulpd256fold(<4 x double> %y) nounwind uwtable readnone ssp { -entry: - %mul.i = fmul <4 x double> %y, - ret <4 x double> %mul.i -} - -; CHECK: vmulps -define <8 x float> @mulps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp { -entry: - %mul.i = fmul <8 x float> %x, %y - ret <8 x float> %mul.i -} - -; CHECK: vmulps LCP{{.*}}(%rip) -define <8 x float> @mulps256fold(<8 x float> %y) nounwind uwtable readnone ssp { -entry: - %mul.i = fmul <8 x float> %y, - ret <8 x float> %mul.i -} - -; CHECK: vdivpd -define <4 x double> @divpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp { -entry: - %div.i = fdiv <4 x double> %x, %y - ret <4 x double> %div.i -} - -; CHECK: vdivpd LCP{{.*}}(%rip) -define <4 x double> @divpd256fold(<4 x double> %y) nounwind uwtable readnone ssp { -entry: - %div.i = fdiv <4 x double> %y, - ret <4 x double> %div.i -} - -; CHECK: vdivps -define <8 x float> @divps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp { -entry: - %div.i = fdiv <8 x float> %x, %y - ret <8 x float> %div.i -} - -; CHECK: vdivps LCP{{.*}}(%rip) -define <8 x float> @divps256fold(<8 x float> %y) nounwind uwtable readnone ssp { -entry: - %div.i = fdiv <8 x float> %y, - ret <8 x float> %div.i -} - Removed: llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-256-cmp.ll (removed) @@ -1,18 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - -; CHECK: vcmpltps %ymm -; CHECK-NOT: vucomiss -define <8 x i32> @cmp00(<8 x float> %a, <8 x float> %b) nounwind readnone { - %bincmp = fcmp olt <8 x float> %a, %b - %s = sext <8 x i1> %bincmp to <8 x i32> - ret <8 x i32> %s -} - -; CHECK: vcmpltpd %ymm -; CHECK-NOT: vucomisd -define <4 x i64> @cmp01(<4 x double> %a, <4 x double> %b) nounwind readnone { - %bincmp = fcmp olt <4 x double> %a, %b - %s = sext <4 x i1> %bincmp to <4 x i64> - ret <4 x i64> %s -} - Removed: llvm/trunk/test/CodeGen/X86/avx-256-cvt.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256-cvt.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-cvt.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-256-cvt.ll (removed) @@ -1,21 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - -; CHECK: vcvtdq2ps %ymm -define <8 x float> @funcA(<8 x i32> %a) nounwind { - %b = sitofp <8 x i32> %a to <8 x float> - ret <8 x float> %b -} - -; CHECK: vcvttps2dq %ymm -define <8 x i32> @funcB(<8 x float> %a) nounwind { - %b = fptosi <8 x float> %a to <8 x i32> - ret <8 x i32> %b -} - -; CHECK: vcvtpd2psy %ymm -; CHECK-NEXT: vcvtpd2psy %ymm -; CHECK-NEXT: vinsertf128 $1 -define <8 x float> @funcC(<8 x double> %b) nounwind { - %a = fptrunc <8 x double> %b to <8 x float> - ret <8 x float> %a -} Removed: llvm/trunk/test/CodeGen/X86/avx-256-logic.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256-logic.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-logic.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-256-logic.ll (removed) @@ -1,161 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - -; CHECK: vandpd -define <4 x double> @andpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x double> %x to <4 x i64> - %1 = bitcast <4 x double> %y to <4 x i64> - %and.i = and <4 x i64> %0, %1 - %2 = bitcast <4 x i64> %and.i to <4 x double> - ret <4 x double> %2 -} - -; CHECK: vandpd LCP{{.*}}(%rip) -define <4 x double> @andpd256fold(<4 x double> %y) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x double> %y to <4 x i64> - %and.i = and <4 x i64> %0, - %1 = bitcast <4 x i64> %and.i to <4 x double> - ret <4 x double> %1 -} - -; CHECK: vandps -define <8 x float> @andps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <8 x float> %x to <8 x i32> - %1 = bitcast <8 x float> %y to <8 x i32> - %and.i = and <8 x i32> %0, %1 - %2 = bitcast <8 x i32> %and.i to <8 x float> - ret <8 x float> %2 -} - -; CHECK: vandps LCP{{.*}}(%rip) -define <8 x float> @andps256fold(<8 x float> %y) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <8 x float> %y to <8 x i32> - %and.i = and <8 x i32> %0, - %1 = bitcast <8 x i32> %and.i to <8 x float> - ret <8 x float> %1 -} - -; CHECK: vxorpd -define <4 x double> @xorpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x double> %x to <4 x i64> - %1 = bitcast <4 x double> %y to <4 x i64> - %xor.i = xor <4 x i64> %0, %1 - %2 = bitcast <4 x i64> %xor.i to <4 x double> - ret <4 x double> %2 -} - -; CHECK: vxorpd LCP{{.*}}(%rip) -define <4 x double> @xorpd256fold(<4 x double> %y) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x double> %y to <4 x i64> - %xor.i = xor <4 x i64> %0, - %1 = bitcast <4 x i64> %xor.i to <4 x double> - ret <4 x double> %1 -} - -; CHECK: vxorps -define <8 x float> @xorps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <8 x float> %x to <8 x i32> - %1 = bitcast <8 x float> %y to <8 x i32> - %xor.i = xor <8 x i32> %0, %1 - %2 = bitcast <8 x i32> %xor.i to <8 x float> - ret <8 x float> %2 -} - -; CHECK: vxorps LCP{{.*}}(%rip) -define <8 x float> @xorps256fold(<8 x float> %y) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <8 x float> %y to <8 x i32> - %xor.i = xor <8 x i32> %0, - %1 = bitcast <8 x i32> %xor.i to <8 x float> - ret <8 x float> %1 -} - -; CHECK: vorpd -define <4 x double> @orpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x double> %x to <4 x i64> - %1 = bitcast <4 x double> %y to <4 x i64> - %or.i = or <4 x i64> %0, %1 - %2 = bitcast <4 x i64> %or.i to <4 x double> - ret <4 x double> %2 -} - -; CHECK: vorpd LCP{{.*}}(%rip) -define <4 x double> @orpd256fold(<4 x double> %y) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x double> %y to <4 x i64> - %or.i = or <4 x i64> %0, - %1 = bitcast <4 x i64> %or.i to <4 x double> - ret <4 x double> %1 -} - -; CHECK: vorps -define <8 x float> @orps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <8 x float> %x to <8 x i32> - %1 = bitcast <8 x float> %y to <8 x i32> - %or.i = or <8 x i32> %0, %1 - %2 = bitcast <8 x i32> %or.i to <8 x float> - ret <8 x float> %2 -} - -; CHECK: vorps LCP{{.*}}(%rip) -define <8 x float> @orps256fold(<8 x float> %y) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <8 x float> %y to <8 x i32> - %or.i = or <8 x i32> %0, - %1 = bitcast <8 x i32> %or.i to <8 x float> - ret <8 x float> %1 -} - -; CHECK: vandnpd -define <4 x double> @andnotpd256(<4 x double> %y, <4 x double> %x) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x double> %x to <4 x i64> - %neg.i = xor <4 x i64> %0, - %1 = bitcast <4 x double> %y to <4 x i64> - %and.i = and <4 x i64> %1, %neg.i - %2 = bitcast <4 x i64> %and.i to <4 x double> - ret <4 x double> %2 -} - -; CHECK: vandnpd (% -define <4 x double> @andnotpd256fold(<4 x double> %y, <4 x double>* nocapture %x) nounwind uwtable readonly ssp { -entry: - %tmp2 = load <4 x double>* %x, align 32 - %0 = bitcast <4 x double> %y to <4 x i64> - %neg.i = xor <4 x i64> %0, - %1 = bitcast <4 x double> %tmp2 to <4 x i64> - %and.i = and <4 x i64> %1, %neg.i - %2 = bitcast <4 x i64> %and.i to <4 x double> - ret <4 x double> %2 -} - -; CHECK: vandnps -define <8 x float> @andnotps256(<8 x float> %y, <8 x float> %x) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <8 x float> %x to <8 x i32> - %neg.i = xor <8 x i32> %0, - %1 = bitcast <8 x float> %y to <8 x i32> - %and.i = and <8 x i32> %1, %neg.i - %2 = bitcast <8 x i32> %and.i to <8 x float> - ret <8 x float> %2 -} - -; CHECK: vandnps (% -define <8 x float> @andnotps256fold(<8 x float> %y, <8 x float>* nocapture %x) nounwind uwtable readonly ssp { -entry: - %tmp2 = load <8 x float>* %x, align 32 - %0 = bitcast <8 x float> %y to <8 x i32> - %neg.i = xor <8 x i32> %0, - %1 = bitcast <8 x float> %tmp2 to <8 x i32> - %and.i = and <8 x i32> %1, %neg.i - %2 = bitcast <8 x i32> %and.i to <8 x float> - ret <8 x float> %2 -} Removed: llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll (removed) @@ -1,34 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - -; CHECK: vmovsldup -define <8 x float> @movdupA(<8 x float> %src) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <8 x float> %src, <8 x float> undef, <8 x i32> - ret <8 x float> %shuffle.i -} - -; CHECK: vmovshdup -define <8 x float> @movdupB(<8 x float> %src) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <8 x float> %src, <8 x float> undef, <8 x i32> - ret <8 x float> %shuffle.i -} - -; CHECK: vmovsldup -define <4 x i64> @movdupC(<4 x i64> %src) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x i64> %src to <8 x float> - %shuffle.i = shufflevector <8 x float> %0, <8 x float> undef, <8 x i32> - %1 = bitcast <8 x float> %shuffle.i to <4 x i64> - ret <4 x i64> %1 -} - -; CHECK: vmovshdup -define <4 x i64> @movdupD(<4 x i64> %src) nounwind uwtable readnone ssp { -entry: - %0 = bitcast <4 x i64> %src to <8 x float> - %shuffle.i = shufflevector <8 x float> %0, <8 x float> undef, <8 x i32> - %1 = bitcast <8 x float> %shuffle.i to <4 x i64> - ret <4 x i64> %1 -} - Removed: llvm/trunk/test/CodeGen/X86/avx-256-splat.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256-splat.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-splat.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-256-splat.ll (removed) @@ -1,79 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - -; FIXME: use avx versions for punpcklbw, punpckhbw and punpckhwd - -; CHECK: vextractf128 $0 -; CHECK-NEXT: punpcklbw -; CHECK-NEXT: punpckhbw -; CHECK-NEXT: vinsertf128 $1 -; CHECK-NEXT: vpermilps $85 -define <32 x i8> @funcA(<32 x i8> %a) nounwind uwtable readnone ssp { -entry: - %shuffle = shufflevector <32 x i8> %a, <32 x i8> undef, <32 x i32> - ret <32 x i8> %shuffle -} - -; CHECK: vextractf128 $0 -; CHECK-NEXT: punpckhwd -; CHECK-NEXT: vinsertf128 $1 -; CHECK-NEXT: vpermilps $85 -define <16 x i16> @funcB(<16 x i16> %a) nounwind uwtable readnone ssp { -entry: - %shuffle = shufflevector <16 x i16> %a, <16 x i16> undef, <16 x i32> - ret <16 x i16> %shuffle -} - -; CHECK: vmovd -; CHECK-NEXT: movlhps -; CHECK-NEXT: vinsertf128 $1 -define <4 x i64> @funcC(i64 %q) nounwind uwtable readnone ssp { -entry: - %vecinit.i = insertelement <4 x i64> undef, i64 %q, i32 0 - %vecinit2.i = insertelement <4 x i64> %vecinit.i, i64 %q, i32 1 - %vecinit4.i = insertelement <4 x i64> %vecinit2.i, i64 %q, i32 2 - %vecinit6.i = insertelement <4 x i64> %vecinit4.i, i64 %q, i32 3 - ret <4 x i64> %vecinit6.i -} - -; CHECK: vshufpd -; CHECK-NEXT: vinsertf128 $1 -define <4 x double> @funcD(double %q) nounwind uwtable readnone ssp { -entry: - %vecinit.i = insertelement <4 x double> undef, double %q, i32 0 - %vecinit2.i = insertelement <4 x double> %vecinit.i, double %q, i32 1 - %vecinit4.i = insertelement <4 x double> %vecinit2.i, double %q, i32 2 - %vecinit6.i = insertelement <4 x double> %vecinit4.i, double %q, i32 3 - ret <4 x double> %vecinit6.i -} - -; Test this simple opt: -; shuffle (scalar_to_vector (load (ptr + 4))), undef, <0, 0, 0, 0> -; To: -; shuffle (vload ptr)), undef, <1, 1, 1, 1> -; CHECK: vmovaps -; CHECK-NEXT: vpextrd -define void @funcE() nounwind { -allocas: - %udx495 = alloca [18 x [18 x float]], align 32 - br label %for_test505.preheader - -for_test505.preheader: ; preds = %for_test505.preheader, %allocas - br i1 undef, label %for_exit499, label %for_test505.preheader - -for_exit499: ; preds = %for_test505.preheader - br i1 undef, label %__load_and_broadcast_32.exit1249, label %load.i1247 - -load.i1247: ; preds = %for_exit499 - %ptr1227 = getelementptr [18 x [18 x float]]* %udx495, i64 0, i64 1, i64 1 - %ptr.i1237 = bitcast float* %ptr1227 to i32* - %val.i1238 = load i32* %ptr.i1237, align 4 - %ret6.i1245 = insertelement <8 x i32> undef, i32 %val.i1238, i32 6 - %ret7.i1246 = insertelement <8 x i32> %ret6.i1245, i32 %val.i1238, i32 7 - %phitmp = bitcast <8 x i32> %ret7.i1246 to <8 x float> - br label %__load_and_broadcast_32.exit1249 - -__load_and_broadcast_32.exit1249: ; preds = %load.i1247, %for_exit499 - %load_broadcast12281250 = phi <8 x float> [ %phitmp, %load.i1247 ], [ undef, %for_exit499 ] - ret void -} - Removed: llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll (removed) @@ -1,58 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - -; CHECK: vunpckhps -define <8 x float> @unpackhips(<8 x float> %src1, <8 x float> %src2) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <8 x float> %src1, <8 x float> %src2, <8 x i32> - ret <8 x float> %shuffle.i -} - -; CHECK: vunpckhpd -define <4 x double> @unpackhipd(<4 x double> %src1, <4 x double> %src2) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <4 x double> %src1, <4 x double> %src2, <4 x i32> - ret <4 x double> %shuffle.i -} - -; CHECK: vunpcklps -define <8 x float> @unpacklops(<8 x float> %src1, <8 x float> %src2) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <8 x float> %src1, <8 x float> %src2, <8 x i32> - ret <8 x float> %shuffle.i -} - -; CHECK: vunpcklpd -define <4 x double> @unpacklopd(<4 x double> %src1, <4 x double> %src2) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <4 x double> %src1, <4 x double> %src2, <4 x i32> - ret <4 x double> %shuffle.i -} - -; CHECK-NOT: vunpcklps %ymm -define <8 x float> @unpacklops-not(<8 x float> %src1, <8 x float> %src2) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <8 x float> %src1, <8 x float> %src2, <8 x i32> - ret <8 x float> %shuffle.i -} - -; CHECK-NOT: vunpcklpd %ymm -define <4 x double> @unpacklopd-not(<4 x double> %src1, <4 x double> %src2) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <4 x double> %src1, <4 x double> %src2, <4 x i32> - ret <4 x double> %shuffle.i -} - -; CHECK-NOT: vunpckhps %ymm -define <8 x float> @unpackhips-not(<8 x float> %src1, <8 x float> %src2) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <8 x float> %src1, <8 x float> %src2, <8 x i32> - ret <8 x float> %shuffle.i -} - -; CHECK-NOT: vunpckhpd %ymm -define <4 x double> @unpackhipd-not(<4 x double> %src1, <4 x double> %src2) nounwind uwtable readnone ssp { -entry: - %shuffle.i = shufflevector <4 x double> %src1, <4 x double> %src2, <4 x i32> - ret <4 x double> %shuffle.i -} - Removed: llvm/trunk/test/CodeGen/X86/avx-256.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-256.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-256.ll (removed) @@ -1,35 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - - at x = common global <8 x float> zeroinitializer, align 32 - at y = common global <4 x double> zeroinitializer, align 32 - -define void @zero() nounwind ssp { -entry: - ; CHECK: vxorps - ; CHECK: vmovaps - ; CHECK: vmovaps - store <8 x float> zeroinitializer, <8 x float>* @x, align 32 - store <4 x double> zeroinitializer, <4 x double>* @y, align 32 - ret void -} - -; CHECK: vpcmpeqd -; CHECK: vinsertf128 $1 -define void @ones([0 x float]* nocapture %RET, [0 x float]* nocapture %aFOO) nounwind { -allocas: - %ptr2vec615 = bitcast [0 x float]* %RET to <8 x float>* - store <8 x float> , <8 x -float>* %ptr2vec615, align 32 - ret void -} - -; CHECK: vpcmpeqd -; CHECK: vinsertf128 $1 -define void @ones2([0 x i32]* nocapture %RET, [0 x i32]* nocapture %aFOO) nounwind { -allocas: - %ptr2vec615 = bitcast [0 x i32]* %RET to <8 x i32>* - store <8 x i32> , <8 x i32>* %ptr2vec615, align 32 - ret void -} Copied: llvm/trunk/test/CodeGen/X86/avx-arith.ll (from r137100, llvm/trunk/test/CodeGen/X86/avx-256-arith.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-arith.ll?p2=llvm/trunk/test/CodeGen/X86/avx-arith.ll&p1=llvm/trunk/test/CodeGen/X86/avx-256-arith.ll&r1=137100&r2=137103&rev=137103&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256-arith.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-arith.ll Mon Aug 8 22:04:23 2011 @@ -114,3 +114,20 @@ ret <8 x float> %div.i } +; CHECK: vsqrtss +define float @sqrtA(float %a) nounwind uwtable readnone ssp { +entry: + %conv1 = tail call float @sqrtf(float %a) nounwind readnone + ret float %conv1 +} + +declare double @sqrt(double) readnone + +; CHECK: vsqrtsd +define double @sqrtB(double %a) nounwind uwtable readnone ssp { +entry: + %call = tail call double @sqrt(double %a) nounwind readnone + ret double %call +} + +declare float @sqrtf(float) readnone Copied: llvm/trunk/test/CodeGen/X86/avx-basic.ll (from r137100, llvm/trunk/test/CodeGen/X86/avx-256.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-basic.ll?p2=llvm/trunk/test/CodeGen/X86/avx-basic.ll&p1=llvm/trunk/test/CodeGen/X86/avx-256.ll&r1=137100&r2=137103&rev=137103&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-256.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-basic.ll Mon Aug 8 22:04:23 2011 @@ -2,8 +2,17 @@ @x = common global <8 x float> zeroinitializer, align 32 @y = common global <4 x double> zeroinitializer, align 32 + at z = common global <4 x float> zeroinitializer, align 16 -define void @zero() nounwind ssp { +define void @zero128() nounwind ssp { +entry: + ; CHECK: vxorps + ; CHECK: vmovaps + store <4 x float> zeroinitializer, <4 x float>* @z, align 16 + ret void +} + +define void @zero256() nounwind ssp { entry: ; CHECK: vxorps ; CHECK: vmovaps Removed: llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll?rev=137102&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll (removed) @@ -1,28 +0,0 @@ -; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - -declare void @scale() nounwind uwtable - -; CHECK: vucomisd -define void @render() nounwind uwtable { -entry: - br i1 undef, label %for.cond5, label %for.end52 - -for.cond5: - %or.cond = and i1 undef, false - br i1 %or.cond, label %for.body33, label %for.cond5 - -for.cond30: - br i1 false, label %for.body33, label %for.cond5 - -for.body33: - %tobool = fcmp une double undef, 0.000000e+00 - br i1 %tobool, label %if.then, label %for.cond30 - -if.then: - call void @scale() - br label %for.cond30 - -for.end52: - ret void -} - Copied: llvm/trunk/test/CodeGen/X86/avx-cmp.ll (from r137100, llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-cmp.ll?p2=llvm/trunk/test/CodeGen/X86/avx-cmp.ll&p1=llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll&r1=137100&r2=137103&rev=137103&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-cmp-fp.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-cmp.ll Mon Aug 8 22:04:23 2011 @@ -1,5 +1,21 @@ ; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s +; CHECK: vcmpltps %ymm +; CHECK-NOT: vucomiss +define <8 x i32> @cmp00(<8 x float> %a, <8 x float> %b) nounwind readnone { + %bincmp = fcmp olt <8 x float> %a, %b + %s = sext <8 x i1> %bincmp to <8 x i32> + ret <8 x i32> %s +} + +; CHECK: vcmpltpd %ymm +; CHECK-NOT: vucomisd +define <4 x i64> @cmp01(<4 x double> %a, <4 x double> %b) nounwind readnone { + %bincmp = fcmp olt <4 x double> %a, %b + %s = sext <4 x i1> %bincmp to <4 x i64> + ret <4 x i64> %s +} + declare void @scale() nounwind uwtable ; CHECK: vucomisd Copied: llvm/trunk/test/CodeGen/X86/avx-cvt.ll (from r137100, llvm/trunk/test/CodeGen/X86/avx-128.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-cvt.ll?p2=llvm/trunk/test/CodeGen/X86/avx-cvt.ll&p1=llvm/trunk/test/CodeGen/X86/avx-128.ll&r1=137100&r2=137103&rev=137103&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-128.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-cvt.ll Mon Aug 8 22:04:23 2011 @@ -1,24 +1,23 @@ ; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s - at z = common global <4 x float> zeroinitializer, align 16 - -define void @zero() nounwind ssp { -entry: - ; CHECK: vxorps - ; CHECK: vmovaps - store <4 x float> zeroinitializer, <4 x float>* @z, align 16 - ret void -} - -define void @fpext() nounwind uwtable { -entry: - %f = alloca float, align 4 - %d = alloca double, align 8 - %tmp = load float* %f, align 4 - ; CHECK: vcvtss2sd - %conv = fpext float %tmp to double - store double %conv, double* %d, align 8 - ret void +; CHECK: vcvtdq2ps %ymm +define <8 x float> @sitofp00(<8 x i32> %a) nounwind { + %b = sitofp <8 x i32> %a to <8 x float> + ret <8 x float> %b +} + +; CHECK: vcvttps2dq %ymm +define <8 x i32> @fptosi00(<8 x float> %a) nounwind { + %b = fptosi <8 x float> %a to <8 x i32> + ret <8 x i32> %b +} + +; CHECK: vcvtpd2psy %ymm +; CHECK-NEXT: vcvtpd2psy %ymm +; CHECK-NEXT: vinsertf128 $1 +define <8 x float> @fptrunc00(<8 x double> %b) nounwind { + %a = fptrunc <8 x double> %b to <8 x float> + ret <8 x float> %a } ; CHECK: vcvtsi2sdq (% @@ -53,20 +52,14 @@ ret float %conv } -; CHECK: vsqrtss -define float @sqrtA(float %a) nounwind uwtable readnone ssp { -entry: - %conv1 = tail call float @sqrtf(float %a) nounwind readnone - ret float %conv1 -} - -declare double @sqrt(double) readnone - -; CHECK: vsqrtsd -define double @sqrtB(double %a) nounwind uwtable readnone ssp { +; CHECK: vcvtss2sd +define void @fpext() nounwind uwtable { entry: - %call = tail call double @sqrt(double %a) nounwind readnone - ret double %call + %f = alloca float, align 4 + %d = alloca double, align 8 + %tmp = load float* %f, align 4 + %conv = fpext float %tmp to double + store double %conv, double* %d, align 8 + ret void } -declare float @sqrtf(float) readnone Copied: llvm/trunk/test/CodeGen/X86/avx-logic.ll (from r137100, llvm/trunk/test/CodeGen/X86/avx-256-logic.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-logic.ll?p2=llvm/trunk/test/CodeGen/X86/avx-logic.ll&p1=llvm/trunk/test/CodeGen/X86/avx-256-logic.ll&r1=137100&r2=137103&rev=137103&view=diff ============================================================================== (empty) Copied: llvm/trunk/test/CodeGen/X86/avx-movdup.ll (from r137100, llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-movdup.ll?p2=llvm/trunk/test/CodeGen/X86/avx-movdup.ll&p1=llvm/trunk/test/CodeGen/X86/avx-256-movdup.ll&r1=137100&r2=137103&rev=137103&view=diff ============================================================================== (empty) Copied: llvm/trunk/test/CodeGen/X86/avx-splat.ll (from r137100, llvm/trunk/test/CodeGen/X86/avx-256-splat.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-splat.ll?p2=llvm/trunk/test/CodeGen/X86/avx-splat.ll&p1=llvm/trunk/test/CodeGen/X86/avx-256-splat.ll&r1=137100&r2=137103&rev=137103&view=diff ============================================================================== (empty) Copied: llvm/trunk/test/CodeGen/X86/avx-unpack.ll (from r137100, llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll) URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-unpack.ll?p2=llvm/trunk/test/CodeGen/X86/avx-unpack.ll&p1=llvm/trunk/test/CodeGen/X86/avx-256-unpack.ll&r1=137100&r2=137103&rev=137103&view=diff ============================================================================== (empty) From bruno.cardoso at gmail.com Mon Aug 8 22:04:26 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 03:04:26 -0000 Subject: [llvm-commits] [llvm] r137104 - /llvm/trunk/lib/Target/X86/X86InstrSSE.td Message-ID: <20110809030426.251D62A6C12D@llvm.org> Author: bruno Date: Mon Aug 8 22:04:25 2011 New Revision: 137104 URL: http://llvm.org/viewvc/llvm-project?rev=137104&view=rev Log: Add AVX versions of 128-bit sitofp and fptosi Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=137104&r1=137103&r2=137104&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Mon Aug 8 22:04:25 2011 @@ -935,6 +935,10 @@ def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))), (CVTTPS2DQrr VR128:$src)>, Requires<[HasSSE2]>; +def : Pat<(v4f32 (sint_to_fp (v4i32 VR128:$src))), + (Int_VCVTDQ2PSrr VR128:$src)>, Requires<[HasAVX]>; +def : Pat<(v4i32 (fp_to_sint (v4f32 VR128:$src))), + (VCVTTPS2DQrr VR128:$src)>, Requires<[HasAVX]>; def : Pat<(v8f32 (sint_to_fp (v8i32 VR256:$src))), (VCVTDQ2PSYrr VR256:$src)>, Requires<[HasAVX]>; def : Pat<(v8i32 (fp_to_sint (v8f32 VR256:$src))), From bruno.cardoso at gmail.com Mon Aug 8 22:04:29 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 03:04:29 -0000 Subject: [llvm-commits] [llvm] r137105 - in /llvm/trunk: lib/Target/X86/X86InstrSSE.td test/CodeGen/X86/avx-cvt.ll Message-ID: <20110809030429.4250E2A6C12E@llvm.org> Author: bruno Date: Mon Aug 8 22:04:29 2011 New Revision: 137105 URL: http://llvm.org/viewvc/llvm-project?rev=137105&view=rev Log: Add support for avx vector fextend Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/test/CodeGen/X86/avx-cvt.ll Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=137105&r1=137104&r2=137105&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Mon Aug 8 22:04:29 2011 @@ -1093,12 +1093,17 @@ def : Pat<(int_x86_avx_cvtt_ps2dq_256 (memopv8f32 addr:$src)), (VCVTTPS2DQYrm addr:$src)>; -// Match fround for 128/256-bit conversions +// Match fround and fextend for 128/256-bit conversions def : Pat<(v4f32 (fround (v4f64 VR256:$src))), (VCVTPD2PSYrr VR256:$src)>; def : Pat<(v4f32 (fround (loadv4f64 addr:$src))), (VCVTPD2PSYrm addr:$src)>; +def : Pat<(v4f64 (fextend (v4f32 VR128:$src))), + (VCVTPS2PDYrr VR128:$src)>; +def : Pat<(v4f64 (fextend (loadv4f32 addr:$src))), + (VCVTPS2PDYrm addr:$src)>; + //===----------------------------------------------------------------------===// // SSE 1 & 2 - Compare Instructions //===----------------------------------------------------------------------===// Modified: llvm/trunk/test/CodeGen/X86/avx-cvt.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-cvt.ll?rev=137105&r1=137104&r2=137105&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-cvt.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-cvt.ll Mon Aug 8 22:04:29 2011 @@ -20,6 +20,12 @@ ret <8 x float> %a } +; CHECK: vcvtps2pd %xmm +define <4 x double> @fpext00(<4 x float> %b) nounwind { + %a = fpext <4 x float> %b to <4 x double> + ret <4 x double> %a +} + ; CHECK: vcvtsi2sdq (% define double @funcA(i64* nocapture %e) nounwind uwtable readonly ssp { entry: From atrick at apple.com Mon Aug 8 22:11:30 2011 From: atrick at apple.com (Andrew Trick) Date: Tue, 09 Aug 2011 03:11:30 -0000 Subject: [llvm-commits] [llvm] r137106 - /llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Message-ID: <20110809031130.1F3012A6C12C@llvm.org> Author: atrick Date: Mon Aug 8 22:11:29 2011 New Revision: 137106 URL: http://llvm.org/viewvc/llvm-project?rev=137106&view=rev Log: LoopUnroll looks like it has some stale code. Remove it to prove my sanity and avoid further confusion. Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=137106&r1=137105&r2=137106&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Mon Aug 8 22:11:29 2011 @@ -217,12 +217,7 @@ ValueToValueMapTy LastValueMap; std::vector OrigPHINode; for (BasicBlock::iterator I = Header->begin(); isa(I); ++I) { - PHINode *PN = cast(I); - OrigPHINode.push_back(PN); - if (Instruction *I = - dyn_cast(PN->getIncomingValueForBlock(LatchBlock))) - if (L->contains(I)) - LastValueMap[I] = I; + OrigPHINode.push_back(cast(I)); } std::vector Headers; From jasonwkim at google.com Mon Aug 8 22:28:07 2011 From: jasonwkim at google.com (Jason Kim) Date: Mon, 8 Aug 2011 20:28:07 -0700 Subject: [llvm-commits] [PATCH] ULEB FIXME in ARM back-end In-Reply-To: References: Message-ID: On Mon, Aug 8, 2011 at 2:58 AM, Renato Golin wrote: > Ping? > > Hi Renato Patch looks okay --- Just a couple of nits. Please fix and commit. 1. no need to typedef a anon struct AttributeItem - this is C++ (enter appropriate "300" joke here) 2. Are you sure there is not a better way to null terminate the string then + Streamer.EmitIntValue(0, 1); // '\0' 3. also, in getULEBSize() you are doing a signed right shift. Is that correct? 4. also I like size_t when you have to return size of something - (in case some crazy person wants to emit an attribute more than 2^32 bytes long) It wastes memory, but given that we probably will not see lots (as in millions) of attributes, its probably ok... Thanks > On 1 August 2011 13:20, Renato Golin wrote: > > Hi all, > > > > I've been playing with a FIXME in the ARM back-end (to get more > > acquainted) and one simple FIXME was an ULEB printing in the > > AsmPrinter. > > > > According to the ARM EABI, both build attribute tag and value are > > ULEBs and not chars as they were being emitted. Today, I don't know of > > any attribute that would emit tags or values bigger than 127 but this > > seamed like an easy start. > > > > The patch changes the emission of values to ULEB by storing all tags > > and values in a typed list and emit later the right value, computing > > the size as it goes. I've run all tests (including the build > > attributes ones in ARM be) and it passes everything. > > > > There are three problems I see with this patch, but would like to know > > from you what's the best way to solve them: > > > > 1. It uses a local structure to hold both ULEB and String values in > > order, but other MC structures will also emit ULEB in the near future > > (we should make sure it does, at least), so this structure could > > become a proper small class on a more visible place. > > > > 2. It wastes memory since both number and string values are on every > > item, but it's not possible to put StringRef in an union since > > Stringref has non-trivial constructors. A solution is to use > > polymorphism but that's too big for this tiny case. If we decide to > > expose the class higher up, then it makes sense to do so. > > > > 3. It's calculating the ULEB size in place, where other routines in > > LLVM can do that (but are not accessible from this class). A > > refactoring is in need to expose that routine to the intended > > audience. > > > > If neither of those problems are relevant, or if they're just minor, > > we can put other FIXMEs around. Otherwise, I'm open to suggestions. > > > > best, > > --renato > > > > > > -- > cheers, > --renato > > _______________________________________________ > 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/20110808/2c9c1c87/attachment.html From geek4civic at gmail.com Mon Aug 8 23:05:04 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Tue, 9 Aug 2011 13:05:04 +0900 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: It seems BasicBlock::replaceSuccessorsPhiUsesWith() might not handle incomplete successors properly on msvc. In a case I saw, the successor has no instructions. John, would it be a possible case for CGCleanup to pass incomplete Entry Block to llvm? Jay, would it be assumed? Workaround is as below; --- a/lib/VMCore/BasicBlock.cpp +++ b/lib/VMCore/BasicBlock.cpp @@ -336,7 +336,9 @@ void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *Ne return; for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) { BasicBlock *Succ = TI->getSuccessor(i); - for (iterator II = Succ->begin(); PHINode *PN = dyn_cast(II); + PHINode *PN; + for (iterator II = Succ->begin(), IE = Succ->end(); + II != IE && (PN = dyn_cast(II)) != NULL; ++II) { int i; while ((i = PN->getBasicBlockIndex(this)) >= 0) ...Takumi 2011?7?30?11:03 NAKAMURA Takumi : > I have met infinite loop in clang since yesterday. > (r136404 had triggered the case for me but r136404 must be nothing) > > Now I can reproduce the infinite loop "RelWithDebInfo" on visual studio 10. > (But it happens randomly) > Still I am investigating. > Lemme know whatever I should check up. > > FYI, ...Takumi > > The log is as below. Infinite loop in replaceSuccessorsPhiUsesWith(). > >> clang.exe!llvm::PHINode::getBasicBlockIndex(const llvm::BasicBlock * BB) ? 2000 C++ > clang.exe!llvm::BasicBlock::replaceSuccessorsPhiUsesWith(llvm::BasicBlock > * New) ? 342 + 0x8 ??? C++ > clang.exe!llvm::Value::replaceAllUsesWith(llvm::Value * New) ? 310 > + 0x8 ??? C++ > clang.exe!SimplifyCleanupEntry(clang::CodeGen::CodeGenFunction & > CGF, llvm::BasicBlock * Entry) ? 426 C++ > clang.exe!clang::CodeGen::CodeGenFunction::PopCleanupBlock(bool > FallthroughIsBranchThrough) ? 845 + 0xc ??? C++ > clang.exe!clang::CodeGen::CodeGenFunction::PopCleanupBlocks(clang::CodeGen::EHScopeStack::stable_iterator > Old) ? 372 + 0xb ??? C++ > clang.exe!clang::CodeGen::CodeGenFunction::EmitCompoundStmt(const > clang::CompoundStmt & S, bool GetLast, clang::CodeGen::AggValueSlot > AggSlot) ? 231 + 0x1c ??? C++ > clang.exe!clang::CodeGen::CodeGenFunction::EmitSimpleStmt(const > clang::Stmt * S) ? 183 C++ > clang.exe!clang::CodeGen::CodeGenFunction::EmitStmt(const > clang::Stmt * S) ? 48 + 0xb ??? C++ > clang.exe!clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::CodeGen::FunctionArgList > & Args) ? 353 + 0xf ??? C++ > clang.exe!clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl > GD, llvm::Function * Fn, const clang::CodeGen::CGFunctionInfo & > FnInfo) ? 407 C++ > clang.exe!clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl > GD) ? 1517 + 0x26 ??? C++ > clang.exe!clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl > GD) ? 844 C++ > clang.exe!clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl > GD) ? 803 C++ > clang.exe!clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl > * D) ? 2214 C++ > clang.exe!`anonymous > namespace'::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef > DG) ? 65 + 0xe ??? C++ > clang.exe!clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef > D) ? 92 C++ > clang.exe!clang::ParseAST(clang::Sema & S, bool PrintStats) ? 84 C++ > clang.exe!clang::ASTFrontendAction::ExecuteAction() ? 378 + 0x1a ??? C++ > clang.exe!clang::CodeGenAction::ExecuteAction() ? 348 C++ > clang.exe!clang::FrontendAction::Execute() ? 299 C++ > clang.exe!clang::CompilerInstance::ExecuteAction(clang::FrontendAction > & Act) ? 615 C++ > clang.exe!clang::ExecuteCompilerInvocation(clang::CompilerInstance * > Clang) ? 172 C++ > clang.exe!cc1_main(const char * * ArgBegin, const char * * ArgEnd, > const char * Argv0, void * MainAddr) ? 159 + 0x6 ??? C++ > clang.exe!main(int argc_, const char * * argv_) ? 354 + 0x15 ??? C++ > From bob.wilson at apple.com Tue Aug 9 00:13:36 2011 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 09 Aug 2011 05:13:36 -0000 Subject: [llvm-commits] [llvm] r137111 - /llvm/trunk/lib/Support/Unix/Host.inc Message-ID: <20110809051336.C09ED2A6C12C@llvm.org> Author: bwilson Date: Tue Aug 9 00:13:36 2011 New Revision: 137111 URL: http://llvm.org/viewvc/llvm-project?rev=137111&view=rev Log: Recognize the UNAME_RELEASE environment variable to match Darwin's uname. When this variable is set, "uname -r" will return its value instead of the real OS version. Make this affect LLVM's triple for consistency. Modified: llvm/trunk/lib/Support/Unix/Host.inc Modified: llvm/trunk/lib/Support/Unix/Host.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Host.inc?rev=137111&r1=137110&r2=137111&view=diff ============================================================================== --- llvm/trunk/lib/Support/Unix/Host.inc (original) +++ llvm/trunk/lib/Support/Unix/Host.inc Tue Aug 9 00:13:36 2011 @@ -22,12 +22,18 @@ #include #include #include +#include // ::getenv using namespace llvm; static std::string getOSVersion() { struct utsname info; + // Recognize UNAME_RELEASE environment variable to match Darwin uname. + const char *UnameOverride = ::getenv("UNAME_RELEASE"); + if (UnameOverride && UnameOverride[0] != '\0') + return UnameOverride; + if (uname(&info)) return ""; From bruno.cardoso at gmail.com Tue Aug 9 00:48:01 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 05:48:01 -0000 Subject: [llvm-commits] [llvm] r137114 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/avx-cvt.ll Message-ID: <20110809054801.6A5EB2A6C12C@llvm.org> Author: bruno Date: Tue Aug 9 00:48:01 2011 New Revision: 137114 URL: http://llvm.org/viewvc/llvm-project?rev=137114&view=rev Log: Handle sitofp between v4f64 <- v4i32. Fix PR10559 Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/test/CodeGen/X86/avx-cvt.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137114&r1=137113&r2=137114&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Aug 9 00:48:01 2011 @@ -969,6 +969,9 @@ setOperationAction(ISD::SINT_TO_FP, MVT::v8i32, Legal); setOperationAction(ISD::FP_ROUND, MVT::v4f32, Legal); + // sint_to_fp between different vector types needs custom handling + setOperationAction(ISD::SINT_TO_FP, MVT::v4i32, Custom); + setOperationAction(ISD::CONCAT_VECTORS, MVT::v4f64, Custom); setOperationAction(ISD::CONCAT_VECTORS, MVT::v4i64, Custom); setOperationAction(ISD::CONCAT_VECTORS, MVT::v8f32, Custom); @@ -7078,6 +7081,24 @@ SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const { EVT SrcVT = Op.getOperand(0).getValueType(); + EVT DstVT = Op.getValueType(); + DebugLoc dl = Op.getDebugLoc(); + + if (SrcVT.isVector() && DstVT.isVector()) { + unsigned SrcVTSize = SrcVT.getSizeInBits(); + unsigned DstVTSize = DstVT.getSizeInBits(); + + // Support directly by the target + if (SrcVTSize == DstVTSize) + return Op; + + // Handle v4f64 = sitofp v4i32 + if (DstVT != MVT::v4f64 && SrcVT != MVT::v4i32) + return SDValue(); + + SDValue V = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, Op.getOperand(0)); + return DAG.getNode(ISD::FP_EXTEND, dl, DstVT, V); + } if (SrcVT.isVector()) return SDValue(); @@ -7094,7 +7115,6 @@ return Op; } - DebugLoc dl = Op.getDebugLoc(); unsigned Size = SrcVT.getSizeInBits()/8; MachineFunction &MF = DAG.getMachineFunction(); int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size, false); Modified: llvm/trunk/test/CodeGen/X86/avx-cvt.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-cvt.ll?rev=137114&r1=137113&r2=137114&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-cvt.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-cvt.ll Tue Aug 9 00:48:01 2011 @@ -6,6 +6,13 @@ ret <8 x float> %b } +; CHECK: vcvtdq2ps +; CHECK-NEXT: vcvtps2pd +define <4 x double> @sitofp01(<4 x i32> %a) { + %b = sitofp <4 x i32> %a to <4 x double> + ret <4 x double> %b +} + ; CHECK: vcvttps2dq %ymm define <8 x i32> @fptosi00(<8 x float> %a) nounwind { %b = fptosi <8 x float> %a to <8 x i32> From eli.friedman at gmail.com Tue Aug 9 00:55:26 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Mon, 8 Aug 2011 22:55:26 -0700 Subject: [llvm-commits] [llvm] r137114 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/avx-cvt.ll In-Reply-To: <20110809054801.6A5EB2A6C12C@llvm.org> References: <20110809054801.6A5EB2A6C12C@llvm.org> Message-ID: On Mon, Aug 8, 2011 at 10:48 PM, Bruno Cardoso Lopes wrote: > Author: bruno > Date: Tue Aug ?9 00:48:01 2011 > New Revision: 137114 > > URL: http://llvm.org/viewvc/llvm-project?rev=137114&view=rev > Log: > Handle sitofp between v4f64 <- v4i32. Fix PR10559 > > Modified: > ? ?llvm/trunk/lib/Target/X86/X86ISelLowering.cpp > ? ?llvm/trunk/test/CodeGen/X86/avx-cvt.ll > > Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137114&r1=137113&r2=137114&view=diff > ============================================================================== > --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) > +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Aug ?9 00:48:01 2011 > @@ -969,6 +969,9 @@ > ? ? setOperationAction(ISD::SINT_TO_FP, ? ? ? ? MVT::v8i32, Legal); > ? ? setOperationAction(ISD::FP_ROUND, ? ? ? ? ? MVT::v4f32, Legal); > > + ? ?// sint_to_fp between different vector types needs custom handling > + ? ?setOperationAction(ISD::SINT_TO_FP, ? ? ? ? MVT::v4i32, Custom); > + > ? ? setOperationAction(ISD::CONCAT_VECTORS, ? ? MVT::v4f64, ?Custom); > ? ? setOperationAction(ISD::CONCAT_VECTORS, ? ? MVT::v4i64, ?Custom); > ? ? setOperationAction(ISD::CONCAT_VECTORS, ? ? MVT::v8f32, ?Custom); > @@ -7078,6 +7081,24 @@ > ?SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SelectionDAG &DAG) const { > ? EVT SrcVT = Op.getOperand(0).getValueType(); > + ?EVT DstVT = Op.getValueType(); > + ?DebugLoc dl = Op.getDebugLoc(); > + > + ?if (SrcVT.isVector() && DstVT.isVector()) { > + ? ?unsigned SrcVTSize = SrcVT.getSizeInBits(); > + ? ?unsigned DstVTSize = DstVT.getSizeInBits(); > + > + ? ?// Support directly by the target > + ? ?if (SrcVTSize == DstVTSize) > + ? ? ?return Op; > + > + ? ?// Handle v4f64 = sitofp v4i32 > + ? ?if (DstVT != MVT::v4f64 && SrcVT != MVT::v4i32) > + ? ? ?return SDValue(); > + > + ? ?SDValue V = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, Op.getOperand(0)); > + ? ?return DAG.getNode(ISD::FP_EXTEND, dl, DstVT, V); > + ?} Aren't there accuracy issues with this approach? A float can't precisely represent every possible i32. -Eli From rjmccall at apple.com Tue Aug 9 00:58:32 2011 From: rjmccall at apple.com (John McCall) Date: Mon, 08 Aug 2011 22:58:32 -0700 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: On Aug 8, 2011, at 9:05 PM, NAKAMURA Takumi wrote: > It seems BasicBlock::replaceSuccessorsPhiUsesWith() might not handle > incomplete successors properly on msvc. > > In a case I saw, the successor has no instructions. > > John, would it be a possible case for CGCleanup to pass incomplete > Entry Block to llvm? Well, the block being replaced shouldn't be empty, and the block it's being replaced with shouldn't be empty, but it is possible for there to be empty blocks in the CFG somewhere. I think your patch to LLVM is a good idea; replaceAllUsesWith should not be assuming a fully-formed AST. As a slight optimization, I would suggest doing this instead: if (Succ->empty()) continue; Jay, does that seem reasonable? That aside, I'll go ahead and patch clang; SimplifyCleanupEntry is really just a case of me being too clever by half. John. From rjmccall at apple.com Tue Aug 9 01:02:06 2011 From: rjmccall at apple.com (John McCall) Date: Mon, 08 Aug 2011 23:02:06 -0700 Subject: [llvm-commits] [cfe-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: <73EC9F6A-45F0-4053-97EB-1CD059E6E2B7@apple.com> On Aug 8, 2011, at 10:58 PM, John McCall wrote: > That aside, I'll go ahead and patch clang; SimplifyCleanupEntry is > really just a case of me being too clever by half. Er, actually, llvm::MergeBlockIntoPredecessor has the same fault, so I think you just need the LLVM patch. John. From zwarich at apple.com Tue Aug 9 01:03:48 2011 From: zwarich at apple.com (Cameron Zwarich) Date: Mon, 08 Aug 2011 23:03:48 -0700 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: <09C95A35-FA79-4241-A4FE-FD123CD8E109@apple.com> Do you know why this only happens with MSVC++? We have had cases of infinite loops in the past caused by MSVC++ miscomputing code. Cameron On Aug 8, 2011, at 9:05 PM, NAKAMURA Takumi wrote: > It seems BasicBlock::replaceSuccessorsPhiUsesWith() might not handle > incomplete successors properly on msvc. > > In a case I saw, the successor has no instructions. > > John, would it be a possible case for CGCleanup to pass incomplete > Entry Block to llvm? > > Jay, would it be assumed? > > Workaround is as below; > > --- a/lib/VMCore/BasicBlock.cpp > +++ b/lib/VMCore/BasicBlock.cpp > @@ -336,7 +336,9 @@ void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *Ne > return; > for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) { > BasicBlock *Succ = TI->getSuccessor(i); > - for (iterator II = Succ->begin(); PHINode *PN = dyn_cast(II); > + PHINode *PN; > + for (iterator II = Succ->begin(), IE = Succ->end(); > + II != IE && (PN = dyn_cast(II)) != NULL; > ++II) { > int i; > while ((i = PN->getBasicBlockIndex(this)) >= 0) > > > ...Takumi > > > 2011?7?30?11:03 NAKAMURA Takumi : >> I have met infinite loop in clang since yesterday. >> (r136404 had triggered the case for me but r136404 must be nothing) >> >> Now I can reproduce the infinite loop "RelWithDebInfo" on visual studio 10. >> (But it happens randomly) >> Still I am investigating. >> Lemme know whatever I should check up. >> >> FYI, ...Takumi >> >> The log is as below. Infinite loop in replaceSuccessorsPhiUsesWith(). >> >>> clang.exe!llvm::PHINode::getBasicBlockIndex(const llvm::BasicBlock * BB) ? 2000 C++ >> clang.exe!llvm::BasicBlock::replaceSuccessorsPhiUsesWith(llvm::BasicBlock >> * New) ? 342 + 0x8 ??? C++ >> clang.exe!llvm::Value::replaceAllUsesWith(llvm::Value * New) ? 310 >> + 0x8 ??? C++ >> clang.exe!SimplifyCleanupEntry(clang::CodeGen::CodeGenFunction & >> CGF, llvm::BasicBlock * Entry) ? 426 C++ >> clang.exe!clang::CodeGen::CodeGenFunction::PopCleanupBlock(bool >> FallthroughIsBranchThrough) ? 845 + 0xc ??? C++ >> clang.exe!clang::CodeGen::CodeGenFunction::PopCleanupBlocks(clang::CodeGen::EHScopeStack::stable_iterator >> Old) ? 372 + 0xb ??? C++ >> clang.exe!clang::CodeGen::CodeGenFunction::EmitCompoundStmt(const >> clang::CompoundStmt & S, bool GetLast, clang::CodeGen::AggValueSlot >> AggSlot) ? 231 + 0x1c ??? C++ >> clang.exe!clang::CodeGen::CodeGenFunction::EmitSimpleStmt(const >> clang::Stmt * S) ? 183 C++ >> clang.exe!clang::CodeGen::CodeGenFunction::EmitStmt(const >> clang::Stmt * S) ? 48 + 0xb ??? C++ >> clang.exe!clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::CodeGen::FunctionArgList >> & Args) ? 353 + 0xf ??? C++ >> clang.exe!clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl >> GD, llvm::Function * Fn, const clang::CodeGen::CGFunctionInfo & >> FnInfo) ? 407 C++ >> clang.exe!clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl >> GD) ? 1517 + 0x26 ??? C++ >> clang.exe!clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl >> GD) ? 844 C++ >> clang.exe!clang::CodeGen::CodeGenModule::EmitGlobal(clang::GlobalDecl >> GD) ? 803 C++ >> clang.exe!clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl >> * D) ? 2214 C++ >> clang.exe!`anonymous >> namespace'::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef >> DG) ? 65 + 0xe ??? C++ >> clang.exe!clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef >> D) ? 92 C++ >> clang.exe!clang::ParseAST(clang::Sema & S, bool PrintStats) ? 84 C++ >> clang.exe!clang::ASTFrontendAction::ExecuteAction() ? 378 + 0x1a ??? C++ >> clang.exe!clang::CodeGenAction::ExecuteAction() ? 348 C++ >> clang.exe!clang::FrontendAction::Execute() ? 299 C++ >> clang.exe!clang::CompilerInstance::ExecuteAction(clang::FrontendAction >> & Act) ? 615 C++ >> clang.exe!clang::ExecuteCompilerInvocation(clang::CompilerInstance * >> Clang) ? 172 C++ >> clang.exe!cc1_main(const char * * ArgBegin, const char * * ArgEnd, >> const char * Argv0, void * MainAddr) ? 159 + 0x6 ??? C++ >> clang.exe!main(int argc_, const char * * argv_) ? 354 + 0x15 ??? C++ >> > _______________________________________________ > 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 Aug 9 01:04:10 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 09 Aug 2011 08:04:10 +0200 Subject: [llvm-commits] Newest LandingPad Patch In-Reply-To: <9646C440-5F6A-4EB8-A18F-1364B819A83B@apple.com> References: <1D33093C-44C0-43BE-B5CD-9CF8F0907484@apple.com> <4E3FB06D.6080405@free.fr> <9646C440-5F6A-4EB8-A18F-1364B819A83B@apple.com> Message-ID: <4E40CDDA.4070201@free.fr> Hi Bill, > Thanks for the review. The possibility of 'bitcasts' makes this annoying. If I cannot guarantee that they will always be Constant*s or Function*s, I'll just change this to use Value*s instead. Constant* should be OK. Ciao, Duncan. From rjmccall at apple.com Tue Aug 9 01:50:24 2011 From: rjmccall at apple.com (John McCall) Date: Mon, 08 Aug 2011 23:50:24 -0700 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: <09C95A35-FA79-4241-A4FE-FD123CD8E109@apple.com> References: <09C95A35-FA79-4241-A4FE-FD123CD8E109@apple.com> Message-ID: On Aug 8, 2011, at 11:03 PM, Cameron Zwarich wrote: > Do you know why this only happens with MSVC++? We have had cases of infinite loops in the past caused by MSVC++ miscomputing code. It looks completely bogus that this works under either Clang or GCC. replaceSuccessorsPhiUsesWith is doing a dyn_cast on the end() of a BasicBlock. Due to craziness in ilist_traits, this is loading from the memory immediately before ilist_traits::Sentinel, i.e. from random global memory. Since loads from global memory are likely to succeed, and even more likely to not randomly return Instruction::PHI, I can easily imagine this being a latent bug. There's no way that MSVC++ could be figuring that this is happening and aggressively optimizing, but I guess it could somehow be locating something that looks like a PHINode there (Instruction::PHI == 48 == '0'), or it could be screwing up the template metaprograms somehow. Anyway, the fix is to either (1) put an empty() check in replaceSuccessorsPhiUsesWith or (2) say that you can never do replaceAllUsesWith on partially-formed IR. (2) would be pretty cruel to front-ends. John. From baldrick at free.fr Tue Aug 9 02:27:42 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 09 Aug 2011 09:27:42 +0200 Subject: [llvm-commits] [PATCH] Revised LandingPadInst Patch In-Reply-To: References: Message-ID: <4E40E16E.6090908@free.fr> Hi Bill, > This is the next iteration of the landingpad instruction patch. It incorporates the feedback from Chris and Duncan. Notably, the values that are stored are now "Value*"s instead of "Function*" or "Constant*". Duncan pointed out that bitcasts can get in the way of things. they are constant bitcasts (ConstExpr), so Constant* is fine. I think Constant* is better than Value*. > The LandingPadInst has this ugly wart on it, namely the "Index" structure that Chris pointed out. I need a way to indicate the clause type for an object in the OperandList, it's index into that list, and how many "types" are associated with that. This is because of inlining. When we inline things, we are going to append the clauses to this list. And they need to be in the correct order so that the exception tables are generated correctly. If you only had (say) filters and no catches, then you could use a null operand to indicate the end of a sequence of filters, so you would have operands like this: not-null ... not-null null not-null ... not-null null \___ filter1 ___/ \___ filter2 ___/ But you have both catches and filters, so need something more clever... I didn't come up with anything yet :) Ciao, Duncan. From wendling at apple.com Tue Aug 9 03:52:00 2011 From: wendling at apple.com (Bill Wendling) Date: Tue, 09 Aug 2011 01:52:00 -0700 Subject: [llvm-commits] [PATCH] Revised LandingPadInst Patch In-Reply-To: <4E40E16E.6090908@free.fr> References: <4E40E16E.6090908@free.fr> Message-ID: <52C08EA4-D7BB-4B65-8850-582C6078F246@apple.com> On Aug 9, 2011, at 12:27 AM, Duncan Sands wrote: > Hi Bill, > >> This is the next iteration of the landingpad instruction patch. It incorporates the feedback from Chris and Duncan. Notably, the values that are stored are now "Value*"s instead of "Function*" or "Constant*". Duncan pointed out that bitcasts can get in the way of things. > > they are constant bitcasts (ConstExpr), so Constant* is fine. I think Constant* > is better than Value*. > Okay. I'll make that change before committing it. :) >> The LandingPadInst has this ugly wart on it, namely the "Index" structure that Chris pointed out. I need a way to indicate the clause type for an object in the OperandList, it's index into that list, and how many "types" are associated with that. This is because of inlining. When we inline things, we are going to append the clauses to this list. And they need to be in the correct order so that the exception tables are generated correctly. > > If you only had (say) filters and no catches, then you could use a null operand > to indicate the end of a sequence of filters, so you would have operands like > this: > not-null ... not-null null not-null ... not-null null > \___ filter1 ___/ \___ filter2 ___/ > But you have both catches and filters, so need something more clever... I > didn't come up with anything yet :) > Also, I don't want to specify a type that may be used as a real value in the list. (i8* null is of course the "catchall" indicator for C++.) Maybe I could encode the clause type, the number of elements, and the elements like this: OperandList: OperandList[1] = ConstantInt::get(LandingPadInst::Catch) OperandList[2] = OperandList[3] = ConstantInt::get(LandingPadInst::Filter) OperandList[4] = ConstantInt::get() OperandList[5] = ? OperandList[5+n] = Etc? That way there's no need for the "Index" structure. The only problem is that random access of variables no longer has O(1) complexity. That may not be a factor, depending on how often one needs to access the clauses in a random fashion... -bw From baldrick at free.fr Tue Aug 9 03:59:29 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 09 Aug 2011 10:59:29 +0200 Subject: [llvm-commits] [PATCH] Revised LandingPadInst Patch In-Reply-To: <52C08EA4-D7BB-4B65-8850-582C6078F246@apple.com> References: <4E40E16E.6090908@free.fr> <52C08EA4-D7BB-4B65-8850-582C6078F246@apple.com> Message-ID: <4E40F6F1.1030507@free.fr> Hi Bill, >>> The LandingPadInst has this ugly wart on it, namely the "Index" structure that Chris pointed out. I need a way to indicate the clause type for an object in the OperandList, it's index into that list, and how many "types" are associated with that. This is because of inlining. When we inline things, we are going to append the clauses to this list. And they need to be in the correct order so that the exception tables are generated correctly. >> >> If you only had (say) filters and no catches, then you could use a null operand >> to indicate the end of a sequence of filters, so you would have operands like >> this: >> not-null ... not-null null not-null ... not-null null >> \___ filter1 ___/ \___ filter2 ___/ >> But you have both catches and filters, so need something more clever... I >> didn't come up with anything yet :) >> > > Also, I don't want to specify a type that may be used as a real value in the list. (i8* null is of course the "catchall" indicator for C++.) I meant the operand really being a null pointer, not a constant of type i8* with a value of null (the C++ catch-all). Maybe I could encode the clause type, the number of elements, and the elements like this: > > OperandList: > > OperandList[1] = ConstantInt::get(LandingPadInst::Catch) > OperandList[2] = > OperandList[3] = ConstantInt::get(LandingPadInst::Filter) > OperandList[4] = ConstantInt::get() > OperandList[5] = > ? > OperandList[5+n] = > > Etc? That way there's no need for the "Index" structure. The only problem is that random access of variables no longer has O(1) complexity. That may not be a factor, depending on how often one needs to access the clauses in a random fashion... That's pretty similar to how the eh.selector intrinsic did it, see http://llvm.org/docs/ExceptionHandling.html#llvm_eh_selector I don't think there was any random access of the eh.selector operands. For codegen you traverse them. For inlining you will just traverse them too right? An alternative is to have: for a catch, an operand which is a (bitcast) global or null*; for a filter, an operand which is a constant array, each element of which is a (bitcast) global or null*. Thus each clause would only take up one operand. Ciao, Duncan. From wendling at apple.com Tue Aug 9 04:26:45 2011 From: wendling at apple.com (Bill Wendling) Date: Tue, 09 Aug 2011 02:26:45 -0700 Subject: [llvm-commits] [PATCH] Revised LandingPadInst Patch In-Reply-To: <4E40F6F1.1030507@free.fr> References: <4E40E16E.6090908@free.fr> <52C08EA4-D7BB-4B65-8850-582C6078F246@apple.com> <4E40F6F1.1030507@free.fr> Message-ID: On Aug 9, 2011, at 1:59 AM, Duncan Sands wrote: >> OperandList: >> >> OperandList[1] = ConstantInt::get(LandingPadInst::Catch) >> OperandList[2] = >> OperandList[3] = ConstantInt::get(LandingPadInst::Filter) >> OperandList[4] = ConstantInt::get() >> OperandList[5] = >> ? >> OperandList[5+n] = >> >> Etc? That way there's no need for the "Index" structure. The only problem is that random access of variables no longer has O(1) complexity. That may not be a factor, depending on how often one needs to access the clauses in a random fashion... > > That's pretty similar to how the eh.selector intrinsic did it, see > http://llvm.org/docs/ExceptionHandling.html#llvm_eh_selector > Similar, but not the same. :-) It's more explicit (at least to me) where one clause leaves off and the others take over. > I don't think there was any random access of the eh.selector operands. For > codegen you traverse them. For inlining you will just traverse them too right? > Yeah. I don't think it would be a huge problem, to be honest. Just something for me to worry about is all. :-) > An alternative is to have: for a catch, an operand which is a (bitcast) global > or null*; for a filter, an operand which is a constant array, each element of > which is a (bitcast) global or null*. Thus each clause would only take up one > operand. The "OperandList" setup for the Instructions is rather complex as it is. Having two or more OperandLists (one list for each 'filter' array) gets very complex very quickly. And we want an OperandList-like data structure so that it can track uses of the LLVM IR objects. -bw From baldrick at free.fr Tue Aug 9 04:32:59 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 09 Aug 2011 11:32:59 +0200 Subject: [llvm-commits] [PATCH] Revised LandingPadInst Patch In-Reply-To: References: <4E40E16E.6090908@free.fr> <52C08EA4-D7BB-4B65-8850-582C6078F246@apple.com> <4E40F6F1.1030507@free.fr> Message-ID: <4E40FECB.5090901@free.fr> Hi Bill, >> An alternative is to have: for a catch, an operand which is a (bitcast) global >> or null*; for a filter, an operand which is a constant array, each element of >> which is a (bitcast) global or null*. Thus each clause would only take up one >> operand. > > > The "OperandList" setup for the Instructions is rather complex as it is. Having two or more OperandLists (one list for each 'filter' array) gets very complex very quickly. And we want an OperandList-like data structure so that it can track uses of the LLVM IR objects. I think you misunderstood. I meant something like this: @_ZTIc = external constant i8* @_ZTId = external constant i8* @_ZTIPKc = external constant i8* %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 cleanup i8** @_ZTIc ; catch because global variable [0 x i8**] [] ; (empty) filter because constant array i8** @_ZTIc ; catch because global variable [0 x i8**] [] ; (empty) filter because constant array i8** @_ZTId ; catch because global variable [2 x i8**] [ i8** @_ZTIPKc, i8** @_ZTId ] ; filter because constant array Ciao, Duncan. From renato.golin at arm.com Tue Aug 9 04:50:10 2011 From: renato.golin at arm.com (Renato Golin) Date: Tue, 09 Aug 2011 09:50:10 -0000 Subject: [llvm-commits] [llvm] r137115 - /llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Message-ID: <20110809095010.9DF2F2A6C12C@llvm.org> Author: rengolin Date: Tue Aug 9 04:50:10 2011 New Revision: 137115 URL: http://llvm.org/viewvc/llvm-project?rev=137115&view=rev Log: Emitting ARM build attributes and values as ULEB, rather than char. Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp?rev=137115&r1=137114&r2=137115&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Tue Aug 9 04:50:10 2011 @@ -100,13 +100,41 @@ }; class ObjectAttributeEmitter : public AttributeEmitter { + // This structure holds all attributes, accounting for + // their string/numeric value, so we can later emmit them + // in declaration order, keeping all in the same vector + struct AttributeItemType { + enum { + HiddenAttribute = 0, + NumericAttribute, + TextAttribute + } Type; + unsigned Tag; + unsigned IntValue; + StringRef StringValue; + } AttributeItem; + MCObjectStreamer &Streamer; StringRef CurrentVendor; - SmallString<64> Contents; + SmallVector Contents; + + // Account for the ULEB/String size of each item, + // not just the number of items + size_t ContentsSize; + // FIXME: this should be in a more generic place, but + // getULEBSize() is in MCAsmInfo and will be moved to MCDwarf + size_t getULEBSize(int Value) { + size_t Size = 0; + do { + Value >>= 7; + Size += sizeof(int8_t); // Is this really necessary? + } while (Value); + return Size; + } public: ObjectAttributeEmitter(MCObjectStreamer &Streamer_) : - Streamer(Streamer_), CurrentVendor("") { } + Streamer(Streamer_), CurrentVendor(""), ContentsSize(0) { } void MaybeSwitchVendor(StringRef Vendor) { assert(!Vendor.empty() && "Vendor cannot be empty."); @@ -124,20 +152,32 @@ } void EmitAttribute(unsigned Attribute, unsigned Value) { - // FIXME: should be ULEB - Contents += Attribute; - Contents += Value; + AttributeItemType attr = { + AttributeItemType::NumericAttribute, + Attribute, + Value, + StringRef("") + }; + ContentsSize += getULEBSize(Attribute); + ContentsSize += getULEBSize(Value); + Contents.push_back(attr); } void EmitTextAttribute(unsigned Attribute, StringRef String) { - Contents += Attribute; - Contents += UppercaseString(String); - Contents += 0; + AttributeItemType attr = { + AttributeItemType::TextAttribute, + Attribute, + 0, + String + }; + ContentsSize += getULEBSize(Attribute); + // String + \0 + ContentsSize += String.size()+1; + + Contents.push_back(attr); } void Finish() { - const size_t ContentsSize = Contents.size(); - // Vendor size + Vendor name + '\0' const size_t VendorHeaderSize = 4 + CurrentVendor.size() + 1; @@ -151,7 +191,23 @@ Streamer.EmitIntValue(ARMBuildAttrs::File, 1); Streamer.EmitIntValue(TagHeaderSize + ContentsSize, 4); - Streamer.EmitBytes(Contents, 0); + // Size should have been accounted for already, now + // emit each field as its type (ULEB or String) + for (unsigned int i=0; i References: Message-ID: On 9 August 2011 04:28, Jason Kim wrote: > Patch looks okay --- Hi Jason, Thanks for reviewing the patch. I'm assuming there is no immediate problem in duplicating the getULEBSize() here and that the AttributeItem structure is fine where it is. > Just a couple of nits. Please fix and commit. > 1. no need to typedef a anon struct?AttributeItem - this is C++ (enter > appropriate "300" joke here) Working with a mix of C and C++ has its tolls... ;) I've declared the structure as AttributeItemType rather than leaving it unnamed. I need this to use it in smallVector template argument. > 2. Are you sure there is not a better way to null terminate the string > then?+ ? ? ? ? ?Streamer.EmitIntValue(0, 1); // '\0' It's used all over the AsmPrinter to print null-terminated strings (see Finish()). Besides, MCStreamer doesn't have an EmitNullString() or equivalent from StringRef. > 3. also, in getULEBSize() you are doing a signed right shift. Is that > correct? This is copy&paste from LLVM's Dwarf code. ULEB cannot have the high bit set, so the right shift will never pad with ones. (Dwarf 3.0, ch7.6) > 4. also I like size_t when you have to return size of something - (in case > some crazy person wants to emit an attribute more than 2^32 bytes long) > It wastes memory, but given that we probably will not see lots (as in > millions) of attributes, its probably ok... Ok. Done. Committed in 137115. cheers, --renato From jay.foad at gmail.com Tue Aug 9 05:40:06 2011 From: jay.foad at gmail.com (Jay Foad) Date: Tue, 9 Aug 2011 11:40:06 +0100 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: On 9 August 2011 06:58, John McCall wrote: > I think your patch to LLVM is a good idea; ?replaceAllUsesWith should > not be assuming a fully-formed AST. ?As a slight optimization, I would > suggest doing this instead: > ?if (Succ->empty()) continue; > Jay, does that seem reasonable? Sure, I'm fine with either your or Takumi's fix. Thanks for taking the time to investigate. Jay. From jay.foad at gmail.com Tue Aug 9 05:44:23 2011 From: jay.foad at gmail.com (Jay Foad) Date: Tue, 9 Aug 2011 11:44:23 +0100 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: On 9 August 2011 11:40, Jay Foad wrote: > On 9 August 2011 06:58, John McCall wrote: >> I think your patch to LLVM is a good idea; ?replaceAllUsesWith should >> not be assuming a fully-formed AST. ?As a slight optimization, I would >> suggest doing this instead: >> ?if (Succ->empty()) continue; >> Jay, does that seem reasonable? > > Sure, I'm fine with either your or Takumi's fix. Thanks for taking the > time to investigate. Hang on... if we need to cope with half-baked IR, won't your fix still fall over on a BB that contains some phi nodes but nothing else? Jay. From geek4civic at gmail.com Tue Aug 9 06:12:39 2011 From: geek4civic at gmail.com (NAKAMURA Takumi) Date: Tue, 9 Aug 2011 20:12:39 +0900 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: 2011/8/9 Jay Foad : > On 9 August 2011 11:40, Jay Foad wrote: >> On 9 August 2011 06:58, John McCall wrote: >>> I think your patch to LLVM is a good idea; ?replaceAllUsesWith should >>> not be assuming a fully-formed AST. ?As a slight optimization, I would >>> suggest doing this instead: >>> ?if (Succ->empty()) continue; >>> Jay, does that seem reasonable? >> >> Sure, I'm fine with either your or Takumi's fix. Thanks for taking the >> time to investigate. > > Hang on... if we need to cope with half-baked IR, won't your fix still > fall over on a BB that contains some phi nodes but nothing else? Jay, yeah, I was afraid that case. (it was the reason I proposed checking iterator end) Or, shall we let the sentinel to have a naive (incompatible to PHInode) llvm::Instruction? I don't have any concrete fixes but kludge workarounds. I hope anyone would lead me the right solution. Please! ...Takumi From jay.foad at gmail.com Tue Aug 9 06:21:24 2011 From: jay.foad at gmail.com (Jay Foad) Date: Tue, 9 Aug 2011 12:21:24 +0100 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: On 9 August 2011 12:12, NAKAMURA Takumi wrote: > 2011/8/9 Jay Foad : >> On 9 August 2011 11:40, Jay Foad wrote: >>> On 9 August 2011 06:58, John McCall wrote: >>>> I think your patch to LLVM is a good idea; ?replaceAllUsesWith should >>>> not be assuming a fully-formed AST. ?As a slight optimization, I would >>>> suggest doing this instead: >>>> ?if (Succ->empty()) continue; >>>> Jay, does that seem reasonable? >>> >>> Sure, I'm fine with either your or Takumi's fix. Thanks for taking the >>> time to investigate. >> >> Hang on... if we need to cope with half-baked IR, won't your fix still >> fall over on a BB that contains some phi nodes but nothing else? > > Jay, yeah, I was afraid that case. (it was the reason I proposed > checking iterator end) I like your fix, Takumi. Personally I would write it like this: // N.B. Succ might not be a complete BasicBlock, so don't assume that it ends with a non-phi instruction. for (iterator II = Succ->begin(), IE = Succ->end(); II != IE; ++II) { PHINode *PN = dyn_cast(II); if (!PN) break; ... } but that's just bike-shedding. Jay. From baldrick at free.fr Tue Aug 9 10:11:51 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 09 Aug 2011 15:11:51 -0000 Subject: [llvm-commits] [dragonegg] r137119 - in /dragonegg/trunk: Makefile include/dragonegg/Cache.h include/dragonegg/cache.h include/dragonegg/gt-cache-4.5.h include/dragonegg/gt-cache-4.6.h src/Backend.cpp src/Cache.cpp src/Constants.cpp src/Types.cpp src/cache.c Message-ID: <20110809151151.918E02A6C12E@llvm.org> Author: baldrick Date: Tue Aug 9 10:11:51 2011 New Revision: 137119 URL: http://llvm.org/viewvc/llvm-project?rev=137119&view=rev Log: Fix an obscure use-after-free coming from the tree to constant map: if a constant used a global variable, and the global variable was replaced with another because the initializer changed, then the constant is freed if it is the last user of the initializer. The map was updated for the global variable change, but wasn't expecting the knock-on effect on constant users of the global. Solve by having a tree to weak value handle map instead. Since the map also has to be GCC garbage collector aware, some hoops need to be jumped through to ensure that weakvh destructors are run when map entries are garbage collected and so on. Added: dragonegg/trunk/include/dragonegg/Cache.h - copied, changed from r137045, dragonegg/trunk/include/dragonegg/cache.h dragonegg/trunk/src/Cache.cpp - copied, changed from r137045, dragonegg/trunk/src/cache.c Removed: dragonegg/trunk/include/dragonegg/cache.h dragonegg/trunk/src/cache.c Modified: dragonegg/trunk/Makefile dragonegg/trunk/include/dragonegg/gt-cache-4.5.h dragonegg/trunk/include/dragonegg/gt-cache-4.6.h dragonegg/trunk/src/Backend.cpp dragonegg/trunk/src/Constants.cpp dragonegg/trunk/src/Types.cpp Modified: dragonegg/trunk/Makefile URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Makefile?rev=137119&r1=137118&r2=137119&view=diff ============================================================================== --- dragonegg/trunk/Makefile (original) +++ dragonegg/trunk/Makefile Tue Aug 9 10:11:51 2011 @@ -40,7 +40,7 @@ REVISION:=$(shell svnversion -n $(TOP_DIR)) PLUGIN=dragonegg.so -PLUGIN_OBJECTS=cache.o Backend.o Constants.o Convert.o Debug.o DefaultABI.o \ +PLUGIN_OBJECTS=Backend.o Cache.o Constants.o Convert.o Debug.o DefaultABI.o \ Trees.o Types.o bits_and_bobs.o TARGET_OBJECT=Target.o @@ -77,10 +77,6 @@ $(QUIET)$(CXX) -o $@ $^ $(shell $(LLVM_CONFIG) --libs support) \ $(LD_OPTIONS) -%.o : $(SRC_DIR)/%.c $(TARGET_UTIL) - @echo Compiling $*.c - $(QUIET)$(CC) -c $(TARGET_HEADERS) $(CPP_OPTIONS) $(CFLAGS) $< - %.o : $(SRC_DIR)/%.cpp $(TARGET_UTIL) @echo Compiling $*.cpp $(QUIET)$(CXX) -c $(TARGET_HEADERS) $(CPP_OPTIONS) $(CXXFLAGS) $< @@ -106,7 +102,7 @@ # The following target exists for the benefit of the dragonegg maintainers, and # is not used in a normal build. You need to specify the path to the GCC build # directory in GCC_BUILD_DIR. -GENGTYPE_INPUT=$(SRC_DIR)/cache.c +GENGTYPE_INPUT=$(SRC_DIR)/Cache.cpp GENGTYPE_OUTPUT=$(INCLUDE_DIR)/dragonegg/gt-cache-$(GCC_MAJOR).$(GCC_MINOR).h gt-cache.h:: $(QUIET)$(GCC_BUILD_DIR)/gcc/build/gengtype \ Copied: dragonegg/trunk/include/dragonegg/Cache.h (from r137045, dragonegg/trunk/include/dragonegg/cache.h) URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Cache.h?p2=dragonegg/trunk/include/dragonegg/Cache.h&p1=dragonegg/trunk/include/dragonegg/cache.h&r1=137045&r2=137119&rev=137119&view=diff ============================================================================== --- dragonegg/trunk/include/dragonegg/cache.h (original) +++ dragonegg/trunk/include/dragonegg/Cache.h Tue Aug 9 10:11:51 2011 @@ -1,41 +1,61 @@ -/*===----------- cache.h - Caching values "in" GCC trees ----------*- C -*-===*\ -|* *| -|* Copyright (C) 2009, 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 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. *| -\*===----------------------------------------------------------------------===*/ +//==----------- Cache.h - Caching values "in" GCC trees ----------*- C++ -*-==// +// +// Copyright (C) 2009, 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 code lets you associate a value 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. +//===----------------------------------------------------------------------===// #ifndef DRAGONEGG_CACHE_H #define DRAGONEGG_CACHE_H +// Forward declarations. +namespace llvm { + class Type; + class Value; +} union tree_node; -/* llvm_get_cached - Returns the value associated with the tree, or NULL. */ -extern const void *llvm_get_cached(union tree_node *tree); - -/* llvm_set_cached - Associates the given value with the tree (and returns it). - To delete an association, pass NULL for the value. */ -extern const void *llvm_set_cached(union tree_node *tree, const void *val); - -/* llvm_replace_cached - Replaces all occurrences of old_val with new_val. */ -extern void llvm_replace_cached(const void *old_val, const void *new_val); +/// getCachedInteger - Returns true if there is an integer associated with the +/// given GCC tree and puts the integer in 'val'. Otherwise returns false. +extern bool getCachedInteger(union tree_node *t, int &Val); + +/// setCachedInteger - Associates the given integer with the given GCC tree, and +/// returns the integer. +extern void setCachedInteger(union tree_node *t, int Val); + +/// getCachedType - Returns the type associated with the given GCC tree, or null +/// if none. +extern llvm::Type *getCachedType(union tree_node *t); + +/// setCachedType - Associates the given type (which may be null) with the given +/// GCC tree, and returns the type. +extern void setCachedType(union tree_node *t, llvm::Type *Ty); + +/// getCachedValue - Returns the value associated with the given GCC tree, or +/// null if none. +extern llvm::Value *getCachedValue(union tree_node *t); + +/// setCachedValue - Associates the given value (which may be null) with the +/// given GCC tree. The association is removed if tree is garbage collected +/// or the value deleted. +extern void setCachedValue(union tree_node *t, llvm::Value *V); #endif /* DRAGONEGG_CACHE_H */ Removed: dragonegg/trunk/include/dragonegg/cache.h URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/cache.h?rev=137118&view=auto ============================================================================== --- dragonegg/trunk/include/dragonegg/cache.h (original) +++ dragonegg/trunk/include/dragonegg/cache.h (removed) @@ -1,41 +0,0 @@ -/*===----------- cache.h - Caching values "in" GCC trees ----------*- C -*-===*\ -|* *| -|* Copyright (C) 2009, 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 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. *| -\*===----------------------------------------------------------------------===*/ - -#ifndef DRAGONEGG_CACHE_H -#define DRAGONEGG_CACHE_H - -union tree_node; - -/* llvm_get_cached - Returns the value associated with the tree, or NULL. */ -extern const void *llvm_get_cached(union tree_node *tree); - -/* llvm_set_cached - Associates the given value with the tree (and returns it). - To delete an association, pass NULL for the value. */ -extern const void *llvm_set_cached(union tree_node *tree, const void *val); - -/* llvm_replace_cached - Replaces all occurrences of old_val with new_val. */ -extern void llvm_replace_cached(const void *old_val, const void *new_val); - -#endif /* DRAGONEGG_CACHE_H */ Modified: dragonegg/trunk/include/dragonegg/gt-cache-4.5.h URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/gt-cache-4.5.h?rev=137119&r1=137118&r2=137119&view=diff ============================================================================== --- dragonegg/trunk/include/dragonegg/gt-cache-4.5.h (original) +++ dragonegg/trunk/include/dragonegg/gt-cache-4.5.h Tue Aug 9 10:11:51 2011 @@ -21,10 +21,18 @@ /* GC marker procedures. */ /* macros and declarations */ -#define gt_ggc_m_13tree_llvm_map(X) do { \ - if (X != NULL) gt_ggc_mx_tree_llvm_map (X);\ +#define gt_ggc_m_11tree2WeakVH(X) do { \ + if (X != NULL) gt_ggc_mx_tree2WeakVH (X);\ } while (0) -extern void gt_ggc_mx_tree_llvm_map (void *); +extern void gt_ggc_mx_tree2WeakVH (void *); +#define gt_ggc_m_9tree2Type(X) do { \ + if (X != NULL) gt_ggc_mx_tree2Type (X);\ + } while (0) +extern void gt_ggc_mx_tree2Type (void *); +#define gt_ggc_m_8tree2int(X) do { \ + if (X != NULL) gt_ggc_mx_tree2int (X);\ + } while (0) +extern void gt_ggc_mx_tree2int (void *); #define gt_ggc_m_15interface_tuple(X) do { \ if (X != NULL) gt_ggc_mx_interface_tuple (X);\ } while (0) @@ -105,14 +113,6 @@ if (X != NULL) gt_ggc_mx_opt_stack (X);\ } while (0) extern void gt_ggc_mx_opt_stack (void *); -#define gt_ggc_m_16def_pragma_macro(X) do { \ - if (X != NULL) gt_ggc_mx_def_pragma_macro (X);\ - } while (0) -extern void gt_ggc_mx_def_pragma_macro (void *); -#define gt_ggc_m_22def_pragma_macro_value(X) do { \ - if (X != NULL) gt_ggc_mx_def_pragma_macro_value (X);\ - } while (0) -extern void gt_ggc_mx_def_pragma_macro_value (void *); #define gt_ggc_m_11align_stack(X) do { \ if (X != NULL) gt_ggc_mx_align_stack (X);\ } while (0) @@ -169,10 +169,6 @@ if (X != NULL) gt_ggc_mx_VEC_deferred_access_check_gc (X);\ } while (0) extern void gt_ggc_mx_VEC_deferred_access_check_gc (void *); -#define gt_ggc_m_11tinst_level(X) do { \ - if (X != NULL) gt_ggc_mx_tinst_level (X);\ - } while (0) -extern void gt_ggc_mx_tinst_level (void *); #define gt_ggc_m_18sorted_fields_type(X) do { \ if (X != NULL) gt_ggc_mx_sorted_fields_type (X);\ } while (0) @@ -185,6 +181,10 @@ if (X != NULL) gt_ggc_mx_named_label_entry (X);\ } while (0) extern void gt_ggc_mx_named_label_entry (void *); +#define gt_ggc_m_32VEC_qualified_typedef_usage_t_gc(X) do { \ + if (X != NULL) gt_ggc_mx_VEC_qualified_typedef_usage_t_gc (X);\ + } while (0) +extern void gt_ggc_mx_VEC_qualified_typedef_usage_t_gc (void *); #define gt_ggc_m_14cp_token_cache(X) do { \ if (X != NULL) gt_ggc_mx_cp_token_cache (X);\ } while (0) @@ -221,6 +221,10 @@ if (X != NULL) gt_ggc_mx_binding_table_s (X);\ } while (0) extern void gt_ggc_mx_binding_table_s (void *); +#define gt_ggc_m_11tinst_level(X) do { \ + if (X != NULL) gt_ggc_mx_tinst_level (X);\ + } while (0) +extern void gt_ggc_mx_tinst_level (void *); #define gt_ggc_m_14VEC_tinfo_s_gc(X) do { \ if (X != NULL) gt_ggc_mx_VEC_tinfo_s_gc (X);\ } while (0) @@ -261,6 +265,10 @@ if (X != NULL) gt_ggc_mx_scev_info_str (X);\ } while (0) extern void gt_ggc_mx_scev_info_str (void *); +#define gt_ggc_m_24VEC_mem_addr_template_gc(X) do { \ + if (X != NULL) gt_ggc_mx_VEC_mem_addr_template_gc (X);\ + } while (0) +extern void gt_ggc_mx_VEC_mem_addr_template_gc (void *); #define gt_ggc_m_13VEC_gimple_gc(X) do { \ if (X != NULL) gt_ggc_mx_VEC_gimple_gc (X);\ } while (0) @@ -565,6 +573,10 @@ if (X != NULL) gt_ggc_mx_tree_statement_list_node (X);\ } while (0) extern void gt_ggc_mx_tree_statement_list_node (void *); +#define gt_ggc_m_9var_ann_d(X) do { \ + if (X != NULL) gt_ggc_mx_var_ann_d (X);\ + } while (0) +extern void gt_ggc_mx_var_ann_d (void *); #define gt_ggc_m_9lang_decl(X) do { \ if (X != NULL) gt_ggc_mx_lang_decl (X);\ } while (0) @@ -589,10 +601,6 @@ if (X != NULL) gt_ggc_mx_VEC_constructor_elt_gc (X);\ } while (0) extern void gt_ggc_mx_VEC_constructor_elt_gc (void *); -#define gt_ggc_m_10tree_ann_d(X) do { \ - if (X != NULL) gt_ggc_mx_tree_ann_d (X);\ - } while (0) -extern void gt_ggc_mx_tree_ann_d (void *); #define gt_ggc_m_17VEC_alias_pair_gc(X) do { \ if (X != NULL) gt_ggc_mx_VEC_alias_pair_gc (X);\ } while (0) @@ -713,14 +721,15 @@ extern void gt_ggc_m_SP9tree_node17splay_tree_node_s (void *); extern void gt_ggc_m_P9tree_nodeP9tree_node17splay_tree_node_s (void *); extern void gt_ggc_m_IP9tree_node17splay_tree_node_s (void *); -extern void gt_ggc_m_P13tree_llvm_map4htab (void *); +extern void gt_ggc_m_P11tree2WeakVH4htab (void *); +extern void gt_ggc_m_P9tree2Type4htab (void *); +extern void gt_ggc_m_P8tree2int4htab (void *); extern void gt_ggc_m_P15interface_tuple4htab (void *); extern void gt_ggc_m_P16volatilized_type4htab (void *); extern void gt_ggc_m_P17string_descriptor4htab (void *); extern void gt_ggc_m_P14type_assertion4htab (void *); extern void gt_ggc_m_P18treetreehash_entry4htab (void *); extern void gt_ggc_m_P17module_htab_entry4htab (void *); -extern void gt_ggc_m_P16def_pragma_macro4htab (void *); extern void gt_ggc_m_P21pending_abstract_type4htab (void *); extern void gt_ggc_m_P10spec_entry4htab (void *); extern void gt_ggc_m_P16cxx_int_tree_map4htab (void *); @@ -761,9 +770,19 @@ /* functions code */ void -gt_ggc_mx_tree_llvm_map (void *x_p) +gt_ggc_mx_tree2WeakVH (void *x_p) +{ + struct tree2WeakVH * const x = (struct tree2WeakVH *)x_p; + if (ggc_test_and_set_mark (x)) + { + gt_ggc_m_9tree_node ((*x).base.from); + } +} + +void +gt_ggc_mx_tree2Type (void *x_p) { - struct tree_llvm_map * const x = (struct tree_llvm_map *)x_p; + struct tree2Type * const x = (struct tree2Type *)x_p; if (ggc_test_and_set_mark (x)) { gt_ggc_m_9tree_node ((*x).base.from); @@ -771,7 +790,17 @@ } void -gt_ggc_m_P13tree_llvm_map4htab (void *x_p) +gt_ggc_mx_tree2int (void *x_p) +{ + struct tree2int * const x = (struct tree2int *)x_p; + if (ggc_test_and_set_mark (x)) + { + gt_ggc_m_9tree_node ((*x).base.from); + } +} + +void +gt_ggc_m_P11tree2WeakVH4htab (void *x_p) { struct htab * const x = (struct htab *)x_p; if (ggc_test_and_set_mark (x)) @@ -779,7 +808,39 @@ if ((*x).entries != NULL) { size_t i0; for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) { - gt_ggc_m_13tree_llvm_map ((*x).entries[i0]); + gt_ggc_m_11tree2WeakVH ((*x).entries[i0]); + } + ggc_mark ((*x).entries); + } + } +} + +void +gt_ggc_m_P9tree2Type4htab (void *x_p) +{ + struct htab * const x = (struct htab *)x_p; + if (ggc_test_and_set_mark (x)) + { + if ((*x).entries != NULL) { + size_t i0; + for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) { + gt_ggc_m_9tree2Type ((*x).entries[i0]); + } + ggc_mark ((*x).entries); + } + } +} + +void +gt_ggc_m_P8tree2int4htab (void *x_p) +{ + struct htab * const x = (struct htab *)x_p; + if (ggc_test_and_set_mark (x)) + { + if ((*x).entries != NULL) { + size_t i0; + for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) { + gt_ggc_m_8tree2int ((*x).entries[i0]); } ggc_mark ((*x).entries); } @@ -790,12 +851,28 @@ EXPORTED_CONST struct ggc_cache_tab gt_ggc_rc__gt_cache_h[] = { { - &llvm_cache, + &WeakVHCache, + 1, + sizeof (WeakVHCache), + >_ggc_mx_tree2WeakVH, + NULL, + &tree2WeakVH_marked_p + }, + { + &TypeCache, + 1, + sizeof (TypeCache), + >_ggc_mx_tree2Type, + NULL, + &tree2Type_marked_p + }, + { + &intCache, 1, - sizeof (llvm_cache), - >_ggc_mx_tree_llvm_map, + sizeof (intCache), + >_ggc_mx_tree2int, NULL, - &tree_llvm_map_marked_p + &tree2int_marked_p }, LAST_GGC_CACHE_TAB }; Modified: dragonegg/trunk/include/dragonegg/gt-cache-4.6.h URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/gt-cache-4.6.h?rev=137119&r1=137118&r2=137119&view=diff ============================================================================== --- dragonegg/trunk/include/dragonegg/gt-cache-4.6.h (original) +++ dragonegg/trunk/include/dragonegg/gt-cache-4.6.h Tue Aug 9 10:11:51 2011 @@ -21,23 +21,47 @@ /* Allocators for known structs and unions. */ -#define ggc_alloc_tree_llvm_map() ((struct tree_llvm_map *)(ggc_internal_alloc_stat (sizeof (struct tree_llvm_map) MEM_STAT_INFO))) -#define ggc_alloc_cleared_tree_llvm_map() ((struct tree_llvm_map *)(ggc_internal_cleared_alloc_stat (sizeof (struct tree_llvm_map) MEM_STAT_INFO))) -#define ggc_alloc_vec_tree_llvm_map(n) ((struct tree_llvm_map *)(ggc_internal_vec_alloc_stat (sizeof (struct tree_llvm_map), n MEM_STAT_INFO))) -#define ggc_alloc_cleared_vec_tree_llvm_map(n) ((struct tree_llvm_map *)(ggc_internal_cleared_vec_alloc_stat (sizeof (struct tree_llvm_map), n MEM_STAT_INFO))) -#define ggc_alloc_zone_tree_llvm_map(z) ((struct tree_llvm_map *)(ggc_internal_zone_alloc_stat (z, sizeof (struct tree_llvm_map) MEM_STAT_INFO))) -#define ggc_alloc_zone_cleared_tree_llvm_map(z) ((struct tree_llvm_map *)(ggc_internal_zone_cleared_alloc_stat (z, sizeof (struct tree_llvm_map) MEM_STAT_INFO))) -#define ggc_alloc_zone_vec_tree_llvm_map(n, z) ((struct tree_llvm_map *)(ggc_internal_zone_vec_alloc_stat (z, sizeof (struct tree_llvm_map), n MEM_STAT_INFO))) -#define ggc_alloc_zone_cleared_vec_tree_llvm_map(n, z) ((struct tree_llvm_map *)(ggc_internal_zone_cleared_vec_alloc_stat (z, sizeof (struct tree_llvm_map), n MEM_STAT_INFO))) +#define ggc_alloc_tree2WeakVH() ((struct tree2WeakVH *)(ggc_internal_alloc_stat (sizeof (struct tree2WeakVH) MEM_STAT_INFO))) +#define ggc_alloc_cleared_tree2WeakVH() ((struct tree2WeakVH *)(ggc_internal_cleared_alloc_stat (sizeof (struct tree2WeakVH) MEM_STAT_INFO))) +#define ggc_alloc_vec_tree2WeakVH(n) ((struct tree2WeakVH *)(ggc_internal_vec_alloc_stat (sizeof (struct tree2WeakVH), n MEM_STAT_INFO))) +#define ggc_alloc_cleared_vec_tree2WeakVH(n) ((struct tree2WeakVH *)(ggc_internal_cleared_vec_alloc_stat (sizeof (struct tree2WeakVH), n MEM_STAT_INFO))) +#define ggc_alloc_zone_tree2WeakVH(z) ((struct tree2WeakVH *)(ggc_internal_zone_alloc_stat (z, sizeof (struct tree2WeakVH) MEM_STAT_INFO))) +#define ggc_alloc_zone_cleared_tree2WeakVH(z) ((struct tree2WeakVH *)(ggc_internal_zone_cleared_alloc_stat (z, sizeof (struct tree2WeakVH) MEM_STAT_INFO))) +#define ggc_alloc_zone_vec_tree2WeakVH(n, z) ((struct tree2WeakVH *)(ggc_internal_zone_vec_alloc_stat (z, sizeof (struct tree2WeakVH), n MEM_STAT_INFO))) +#define ggc_alloc_zone_cleared_vec_tree2WeakVH(n, z) ((struct tree2WeakVH *)(ggc_internal_zone_cleared_vec_alloc_stat (z, sizeof (struct tree2WeakVH), n MEM_STAT_INFO))) +#define ggc_alloc_tree2Type() ((struct tree2Type *)(ggc_internal_alloc_stat (sizeof (struct tree2Type) MEM_STAT_INFO))) +#define ggc_alloc_cleared_tree2Type() ((struct tree2Type *)(ggc_internal_cleared_alloc_stat (sizeof (struct tree2Type) MEM_STAT_INFO))) +#define ggc_alloc_vec_tree2Type(n) ((struct tree2Type *)(ggc_internal_vec_alloc_stat (sizeof (struct tree2Type), n MEM_STAT_INFO))) +#define ggc_alloc_cleared_vec_tree2Type(n) ((struct tree2Type *)(ggc_internal_cleared_vec_alloc_stat (sizeof (struct tree2Type), n MEM_STAT_INFO))) +#define ggc_alloc_zone_tree2Type(z) ((struct tree2Type *)(ggc_internal_zone_alloc_stat (z, sizeof (struct tree2Type) MEM_STAT_INFO))) +#define ggc_alloc_zone_cleared_tree2Type(z) ((struct tree2Type *)(ggc_internal_zone_cleared_alloc_stat (z, sizeof (struct tree2Type) MEM_STAT_INFO))) +#define ggc_alloc_zone_vec_tree2Type(n, z) ((struct tree2Type *)(ggc_internal_zone_vec_alloc_stat (z, sizeof (struct tree2Type), n MEM_STAT_INFO))) +#define ggc_alloc_zone_cleared_vec_tree2Type(n, z) ((struct tree2Type *)(ggc_internal_zone_cleared_vec_alloc_stat (z, sizeof (struct tree2Type), n MEM_STAT_INFO))) +#define ggc_alloc_tree2int() ((struct tree2int *)(ggc_internal_alloc_stat (sizeof (struct tree2int) MEM_STAT_INFO))) +#define ggc_alloc_cleared_tree2int() ((struct tree2int *)(ggc_internal_cleared_alloc_stat (sizeof (struct tree2int) MEM_STAT_INFO))) +#define ggc_alloc_vec_tree2int(n) ((struct tree2int *)(ggc_internal_vec_alloc_stat (sizeof (struct tree2int), n MEM_STAT_INFO))) +#define ggc_alloc_cleared_vec_tree2int(n) ((struct tree2int *)(ggc_internal_cleared_vec_alloc_stat (sizeof (struct tree2int), n MEM_STAT_INFO))) +#define ggc_alloc_zone_tree2int(z) ((struct tree2int *)(ggc_internal_zone_alloc_stat (z, sizeof (struct tree2int) MEM_STAT_INFO))) +#define ggc_alloc_zone_cleared_tree2int(z) ((struct tree2int *)(ggc_internal_zone_cleared_alloc_stat (z, sizeof (struct tree2int) MEM_STAT_INFO))) +#define ggc_alloc_zone_vec_tree2int(n, z) ((struct tree2int *)(ggc_internal_zone_vec_alloc_stat (z, sizeof (struct tree2int), n MEM_STAT_INFO))) +#define ggc_alloc_zone_cleared_vec_tree2int(n, z) ((struct tree2int *)(ggc_internal_zone_cleared_vec_alloc_stat (z, sizeof (struct tree2int), n MEM_STAT_INFO))) /* Allocators for known typedefs. */ /* GC marker procedures. */ /* macros and declarations */ -#define gt_ggc_m_13tree_llvm_map(X) do { \ - if (X != NULL) gt_ggc_mx_tree_llvm_map (X);\ +#define gt_ggc_m_11tree2WeakVH(X) do { \ + if (X != NULL) gt_ggc_mx_tree2WeakVH (X);\ } while (0) -extern void gt_ggc_mx_tree_llvm_map (void *); +extern void gt_ggc_mx_tree2WeakVH (void *); +#define gt_ggc_m_9tree2Type(X) do { \ + if (X != NULL) gt_ggc_mx_tree2Type (X);\ + } while (0) +extern void gt_ggc_mx_tree2Type (void *); +#define gt_ggc_m_8tree2int(X) do { \ + if (X != NULL) gt_ggc_mx_tree2int (X);\ + } while (0) +extern void gt_ggc_mx_tree2int (void *); #define gt_ggc_m_15c_inline_static(X) do { \ if (X != NULL) gt_ggc_mx_c_inline_static (X);\ } while (0) @@ -130,6 +154,10 @@ if (X != NULL) gt_ggc_mx_binding_level (X);\ } while (0) extern void gt_ggc_mx_binding_level (void *); +#define gt_ggc_m_23VEC_pending_noexcept_gc(X) do { \ + if (X != NULL) gt_ggc_mx_VEC_pending_noexcept_gc (X);\ + } while (0) +extern void gt_ggc_mx_VEC_pending_noexcept_gc (void *); #define gt_ggc_m_9opt_stack(X) do { \ if (X != NULL) gt_ggc_mx_opt_stack (X);\ } while (0) @@ -202,10 +230,6 @@ if (X != NULL) gt_ggc_mx_VEC_deferred_access_gc (X);\ } while (0) extern void gt_ggc_mx_VEC_deferred_access_gc (void *); -#define gt_ggc_m_17VEC_spec_entry_gc(X) do { \ - if (X != NULL) gt_ggc_mx_VEC_spec_entry_gc (X);\ - } while (0) -extern void gt_ggc_mx_VEC_spec_entry_gc (void *); #define gt_ggc_m_10spec_entry(X) do { \ if (X != NULL) gt_ggc_mx_spec_entry (X);\ } while (0) @@ -454,18 +478,22 @@ if (X != NULL) gt_ggc_mx_VEC_deferred_locations_gc (X);\ } while (0) extern void gt_ggc_mx_VEC_deferred_locations_gc (void *); -#define gt_ggc_m_18dw_loc_list_struct(X) do { \ - if (X != NULL) gt_ggc_mx_dw_loc_list_struct (X);\ +#define gt_ggc_m_17VEC_dw_fde_ref_gc(X) do { \ + if (X != NULL) gt_ggc_mx_VEC_dw_fde_ref_gc (X);\ } while (0) -extern void gt_ggc_mx_dw_loc_list_struct (void *); +extern void gt_ggc_mx_VEC_dw_fde_ref_gc (void *); +#define gt_ggc_m_24reg_saved_in_data_struct(X) do { \ + if (X != NULL) gt_ggc_mx_reg_saved_in_data_struct (X);\ + } while (0) +extern void gt_ggc_mx_reg_saved_in_data_struct (void *); +#define gt_ggc_m_17dw_cfi_row_struct(X) do { \ + if (X != NULL) gt_ggc_mx_dw_cfi_row_struct (X);\ + } while (0) +extern void gt_ggc_mx_dw_cfi_row_struct (void *); #define gt_ggc_m_15dwarf_file_data(X) do { \ if (X != NULL) gt_ggc_mx_dwarf_file_data (X);\ } while (0) extern void gt_ggc_mx_dwarf_file_data (void *); -#define gt_ggc_m_15queued_reg_save(X) do { \ - if (X != NULL) gt_ggc_mx_queued_reg_save (X);\ - } while (0) -extern void gt_ggc_mx_queued_reg_save (void *); #define gt_ggc_m_20indirect_string_node(X) do { \ if (X != NULL) gt_ggc_mx_indirect_string_node (X);\ } while (0) @@ -474,14 +502,14 @@ if (X != NULL) gt_ggc_mx_VEC_dw_cfi_ref_gc (X);\ } while (0) extern void gt_ggc_mx_VEC_dw_cfi_ref_gc (void *); +#define gt_ggc_m_18dw_loc_list_struct(X) do { \ + if (X != NULL) gt_ggc_mx_dw_loc_list_struct (X);\ + } while (0) +extern void gt_ggc_mx_dw_loc_list_struct (void *); #define gt_ggc_m_19dw_loc_descr_struct(X) do { \ if (X != NULL) gt_ggc_mx_dw_loc_descr_struct (X);\ } while (0) extern void gt_ggc_mx_dw_loc_descr_struct (void *); -#define gt_ggc_m_13dw_fde_struct(X) do { \ - if (X != NULL) gt_ggc_mx_dw_fde_struct (X);\ - } while (0) -extern void gt_ggc_mx_dw_fde_struct (void *); #define gt_ggc_m_13dw_cfi_struct(X) do { \ if (X != NULL) gt_ggc_mx_dw_cfi_struct (X);\ } while (0) @@ -610,6 +638,10 @@ if (X != NULL) gt_ggc_mx_VEC_temp_slot_p_gc (X);\ } while (0) extern void gt_ggc_mx_VEC_temp_slot_p_gc (void *); +#define gt_ggc_m_13dw_fde_struct(X) do { \ + if (X != NULL) gt_ggc_mx_dw_fde_struct (X);\ + } while (0) +extern void gt_ggc_mx_dw_fde_struct (void *); #define gt_ggc_m_9temp_slot(X) do { \ if (X != NULL) gt_ggc_mx_temp_slot (X);\ } while (0) @@ -634,6 +666,10 @@ if (X != NULL) gt_ggc_mx_libfunc_entry (X);\ } while (0) extern void gt_ggc_mx_libfunc_entry (void *); +#define gt_ggc_m_12tree_vec_map(X) do { \ + if (X != NULL) gt_ggc_mx_tree_vec_map (X);\ + } while (0) +extern void gt_ggc_mx_tree_vec_map (void *); #define gt_ggc_m_17tree_priority_map(X) do { \ if (X != NULL) gt_ggc_mx_tree_priority_map (X);\ } while (0) @@ -798,7 +834,9 @@ if (X != NULL) gt_ggc_mx_line_maps (X);\ } while (0) extern void gt_ggc_mx_line_maps (void *); -extern void gt_ggc_m_P13tree_llvm_map4htab (void *); +extern void gt_ggc_m_P11tree2WeakVH4htab (void *); +extern void gt_ggc_m_P9tree2Type4htab (void *); +extern void gt_ggc_m_P8tree2int4htab (void *); extern void gt_ggc_m_II17splay_tree_node_s (void *); extern void gt_ggc_m_SP9tree_node17splay_tree_node_s (void *); extern void gt_ggc_m_P9tree_nodeP9tree_node17splay_tree_node_s (void *); @@ -825,6 +863,7 @@ extern void gt_ggc_m_P12object_block4htab (void *); extern void gt_ggc_m_P7section4htab (void *); extern void gt_ggc_m_P17tree_priority_map4htab (void *); +extern void gt_ggc_m_P12tree_vec_map4htab (void *); extern void gt_ggc_m_P13tree_decl_map4htab (void *); extern void gt_ggc_m_P9type_hash4htab (void *); extern void gt_ggc_m_P23temp_slot_address_entry4htab (void *); @@ -832,12 +871,12 @@ extern void gt_ggc_m_P9reg_attrs4htab (void *); extern void gt_ggc_m_P9mem_attrs4htab (void *); extern void gt_ggc_m_P7rtx_def4htab (void *); -extern void gt_ggc_m_SP9tree_node12splay_tree_s (void *); extern void gt_ggc_m_P22cached_dw_loc_list_def4htab (void *); extern void gt_ggc_m_P16var_loc_list_def4htab (void *); extern void gt_ggc_m_P10die_struct4htab (void *); extern void gt_ggc_m_P15dwarf_file_data4htab (void *); extern void gt_ggc_m_P20indirect_string_node4htab (void *); +extern void gt_ggc_m_SP9tree_node12splay_tree_s (void *); extern void gt_ggc_m_P11cgraph_node4htab (void *); extern void gt_ggc_m_II12splay_tree_s (void *); extern void gt_ggc_m_P11cgraph_edge4htab (void *); @@ -849,9 +888,9 @@ /* functions code */ void -gt_ggc_mx_tree_llvm_map (void *x_p) +gt_ggc_mx_tree2WeakVH (void *x_p) { - struct tree_llvm_map * const x = (struct tree_llvm_map *)x_p; + struct tree2WeakVH * const x = (struct tree2WeakVH *)x_p; if (ggc_test_and_set_mark (x)) { gt_ggc_m_9tree_node ((*x).base.from); @@ -859,7 +898,27 @@ } void -gt_ggc_m_P13tree_llvm_map4htab (void *x_p) +gt_ggc_mx_tree2Type (void *x_p) +{ + struct tree2Type * const x = (struct tree2Type *)x_p; + if (ggc_test_and_set_mark (x)) + { + gt_ggc_m_9tree_node ((*x).base.from); + } +} + +void +gt_ggc_mx_tree2int (void *x_p) +{ + struct tree2int * const x = (struct tree2int *)x_p; + if (ggc_test_and_set_mark (x)) + { + gt_ggc_m_9tree_node ((*x).base.from); + } +} + +void +gt_ggc_m_P11tree2WeakVH4htab (void *x_p) { struct htab * const x = (struct htab *)x_p; if (ggc_test_and_set_mark (x)) @@ -867,7 +926,39 @@ if ((*x).entries != NULL) { size_t i0; for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) { - gt_ggc_m_13tree_llvm_map ((*x).entries[i0]); + gt_ggc_m_11tree2WeakVH ((*x).entries[i0]); + } + ggc_mark ((*x).entries); + } + } +} + +void +gt_ggc_m_P9tree2Type4htab (void *x_p) +{ + struct htab * const x = (struct htab *)x_p; + if (ggc_test_and_set_mark (x)) + { + if ((*x).entries != NULL) { + size_t i0; + for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) { + gt_ggc_m_9tree2Type ((*x).entries[i0]); + } + ggc_mark ((*x).entries); + } + } +} + +void +gt_ggc_m_P8tree2int4htab (void *x_p) +{ + struct htab * const x = (struct htab *)x_p; + if (ggc_test_and_set_mark (x)) + { + if ((*x).entries != NULL) { + size_t i0; + for (i0 = 0; i0 != (size_t)(((*x)).size); i0++) { + gt_ggc_m_8tree2int ((*x).entries[i0]); } ggc_mark ((*x).entries); } @@ -878,12 +969,28 @@ EXPORTED_CONST struct ggc_cache_tab gt_ggc_rc__gt_cache_h[] = { { - &llvm_cache, + &WeakVHCache, + 1, + sizeof (WeakVHCache), + >_ggc_mx_tree2WeakVH, + NULL, + &tree2WeakVH_marked_p + }, + { + &TypeCache, + 1, + sizeof (TypeCache), + >_ggc_mx_tree2Type, + NULL, + &tree2Type_marked_p + }, + { + &intCache, 1, - sizeof (llvm_cache), - >_ggc_mx_tree_llvm_map, + sizeof (intCache), + >_ggc_mx_tree2int, NULL, - &tree_llvm_map_marked_p + &tree2int_marked_p }, LAST_GGC_CACHE_TAB }; Modified: dragonegg/trunk/src/Backend.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Backend.cpp?rev=137119&r1=137118&r2=137119&view=diff ============================================================================== --- dragonegg/trunk/src/Backend.cpp (original) +++ dragonegg/trunk/src/Backend.cpp Tue Aug 9 10:11:51 2011 @@ -22,9 +22,7 @@ //===----------------------------------------------------------------------===// // Plugin headers -extern "C" { -#include "dragonegg/cache.h" -} +#include "dragonegg/Cache.h" #include "dragonegg/Constants.h" #include "dragonegg/Debug.h" #include "dragonegg/OS.h" @@ -134,13 +132,14 @@ /// 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); + setCachedValue(t, V); + return 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); + return getCachedValue(t); } /// set_decl_index - Associate a non-negative number with the given GCC @@ -148,9 +147,7 @@ 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)); + setCachedInteger(t, i); return i; } @@ -158,9 +155,10 @@ /// 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)); + int Idx; + if (getCachedInteger(t, Idx)) + return Idx; + return -1; } /// changeLLVMConstant - Replace Old with New everywhere, updating all maps @@ -189,7 +187,7 @@ StaticDtors[i].first = New; } - llvm_replace_cached(Old, New); + // No need to update the value cache - it autoupdates on RAUW. } /// handleVisibility - Forward decl visibility style to global. Copied: dragonegg/trunk/src/Cache.cpp (from r137045, dragonegg/trunk/src/cache.c) URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Cache.cpp?p2=dragonegg/trunk/src/Cache.cpp&p1=dragonegg/trunk/src/cache.c&r1=137045&r2=137119&rev=137119&view=diff ============================================================================== --- dragonegg/trunk/src/cache.c (original) +++ dragonegg/trunk/src/Cache.cpp Tue Aug 9 10:11:51 2011 @@ -1,139 +1,239 @@ -/* Caching values "in" trees -Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. +//==----------- Cache.h - Caching values "in" GCC trees ----------*- C++ -*-==// +// +// Copyright (C) 2009, 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 code lets you associate values 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" + +// LLVM headers +#include "llvm/Support/ValueHandle.h" + +// System headers +#include +#include -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. */ +// 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 "ggc.h" +} + +using namespace llvm; + +// Hash table mapping trees to integers. -struct GTY(()) tree_llvm_map { +struct GTY(()) tree2int { struct tree_map_base base; - const void * GTY((skip)) val; + int 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; +#define tree2int_eq tree_map_base_eq +#define tree2int_hash tree_map_base_hash +#define tree2int_marked_p tree_map_base_marked_p + +static GTY((if_marked("tree2int_marked_p"), + param_is(struct tree2int))) + htab_t intCache; + + +// Hash table mapping trees to Type*. + +// Forward declare Type for the benefit of gengtype. +#ifndef IN_GCC +struct Type; +#endif +struct GTY(()) tree2Type { + struct tree_map_base base; +#ifndef IN_GCC + struct +#endif + Type *GTY((skip)) Ty; +}; + +#define tree2Type_eq tree_map_base_eq +#define tree2Type_hash tree_map_base_hash +#define tree2Type_marked_p tree_map_base_marked_p + +static GTY((if_marked("tree2Type_marked_p"), + param_is(struct tree2Type))) + htab_t TypeCache; + + +// Hash table mapping trees to WeakVH. + +// Forward declare WeakVH for the benefit of gengtype. +#ifndef IN_GCC +struct WeakVH; +#endif +struct GTY(()) tree2WeakVH { + struct tree_map_base base; +#ifndef IN_GCC + struct +#endif + WeakVH GTY((skip)) V; +}; + +#define tree2WeakVH_eq tree_map_base_eq +#define tree2WeakVH_hash tree_map_base_hash +#define tree2WeakVH_marked_p tree_map_base_marked_p + +static GTY((if_marked("tree2WeakVH_marked_p"), + param_is(struct tree2WeakVH))) + htab_t WeakVHCache; + -/* Garbage collector header. */ +// Include the garbage collector header. +extern "C" { #if (GCC_MINOR > 5) #include "dragonegg/gt-cache-4.6.h" #else #include "dragonegg/gt-cache-4.5.h" #endif +} + +bool getCachedInteger(tree t, int &Val) { + if (!intCache) + return false; + tree_map_base in = { t }; + tree2int *h = (tree2int *)htab_find(intCache, &in); + if (!h) + return false; + Val = h->val; + return true; +} + +void setCachedInteger(tree t, int Val) { + if (!intCache) + intCache = htab_create_ggc(1024, tree2int_hash, tree2int_eq, 0); + + tree_map_base in = { t }; + tree2int **slot = (tree2int **)htab_find_slot(intCache, &in, INSERT); + assert(slot && "Failed to create hash table slot!"); + + if (!*slot) { + *slot = +#if (GCC_MINOR > 5) + ggc_alloc_tree2int(); +#else + GGC_NEW(struct tree2int); +#endif + (*slot)->base.from = t; + } + + (*slot)->val = Val; +} -/* 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; +Type *getCachedType(tree t) { + if (!TypeCache) + return 0; + tree_map_base in = { t }; + tree2Type *h = (tree2Type *)htab_find(TypeCache, &in); + return h ? h->Ty : 0; +} - in.from = tree; +void setCachedType(tree t, Type *Ty) { + tree_map_base in = { t }; /* If deleting, remove the slot. */ - if (val == NULL) { - if (llvm_cache) - htab_remove_elt(llvm_cache, &in); - return NULL; + if (!Ty) { + if (TypeCache) + htab_remove_elt(TypeCache, &in); + return; } - if (!llvm_cache) - llvm_cache = htab_create_ggc(1024, tree_llvm_map_hash, tree_llvm_map_eq, NULL); + if (!TypeCache) + TypeCache = htab_create_ggc(1024, tree2Type_hash, tree2Type_eq, 0); - slot = (struct tree_llvm_map **) htab_find_slot(llvm_cache, &in, INSERT); - gcc_assert(slot); + tree2Type **slot = (tree2Type **)htab_find_slot(TypeCache, &in, INSERT); + assert(slot && "Failed to create hash table slot!"); if (!*slot) { *slot = #if (GCC_MINOR > 5) - ggc_alloc_tree_llvm_map(); + ggc_alloc_tree2Type(); #else - GGC_NEW(struct tree_llvm_map); + GGC_NEW(struct tree2Type); #endif - (*slot)->base.from = tree; + (*slot)->base.from = t; } - (*slot)->val = val; + (*slot)->Ty = Ty; +} - return val; +/// getCachedValue - Returns the value associated with the given GCC tree, or +/// null if none. +Value *getCachedValue(tree t) { + if (!WeakVHCache) + return 0; + tree_map_base in = { t }; + tree2WeakVH *h = (tree2WeakVH *)htab_find(WeakVHCache, &in); + return h ? h->V : 0; } -struct update { - const void *old_val; - const void *new_val; -}; +static void DestructWeakVH(void *p) { + ((WeakVH*)&((tree2WeakVH*)p)->V)->~WeakVH(); +} -/* 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; +/// setCachedValue - Associates the given value (which may be null) with the +/// given GCC tree. The association is removed if tree is garbage collected +/// or the value deleted. +void setCachedValue(tree t, Value *V) { + tree_map_base in = { t }; + + // If deleting, remove the slot. + if (!V) { + if (WeakVHCache) + htab_remove_elt(WeakVHCache, &in); + return; + } - if (!llvm_cache || old_val == NULL) + if (!WeakVHCache) + WeakVHCache = htab_create_ggc(1024, tree2WeakVH_hash, tree2WeakVH_eq, + DestructWeakVH); + + tree2WeakVH **slot = (tree2WeakVH **)htab_find_slot(WeakVHCache, &in, INSERT); + assert(slot && "Failed to create hash table slot!"); + + if (*slot) { + (*slot)->V = V; return; + } - htab_traverse(llvm_cache, replace, &u); + *slot = +#if (GCC_MINOR > 5) + ggc_alloc_tree2WeakVH(); +#else + GGC_NEW(struct tree2WeakVH); +#endif + (*slot)->base.from = t; + WeakVH *W = new(&(*slot)->V) WeakVH(V); + assert(W == &(*slot)->V && "Pointer was displaced!"); } Modified: dragonegg/trunk/src/Constants.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Constants.cpp?rev=137119&r1=137118&r2=137119&view=diff ============================================================================== --- dragonegg/trunk/src/Constants.cpp (original) +++ dragonegg/trunk/src/Constants.cpp Tue Aug 9 10:11:51 2011 @@ -21,15 +21,13 @@ //===----------------------------------------------------------------------===// // Plugin headers +#include "dragonegg/Cache.h" #include "dragonegg/Constants.h" #include "dragonegg/Internals.h" #include "dragonegg/Trees.h" #include "dragonegg/Types.h" #include "dragonegg/ADT/IntervalList.h" #include "dragonegg/ADT/Range.h" -extern "C" { -#include "dragonegg/cache.h" -} // LLVM headers #include "llvm/GlobalVariable.h" @@ -1277,7 +1275,7 @@ /// ConvertInitializerImpl - Implementation of ConvertInitializer. static Constant *ConvertInitializerImpl(tree exp, TargetFolder &Folder) { // If we already converted the initializer then return the cached copy. - if (Constant *C = (Constant *)llvm_get_cached(exp)) + if (Constant *C = cast_or_null(getCachedValue(exp))) return C; Constant *Init; @@ -1344,7 +1342,7 @@ // Cache the result of converting the initializer since the same tree is often // converted multiple times. - llvm_set_cached(exp, Init); + setCachedValue(exp, Init); return Init; } Modified: dragonegg/trunk/src/Types.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Types.cpp?rev=137119&r1=137118&r2=137119&view=diff ============================================================================== --- dragonegg/trunk/src/Types.cpp (original) +++ dragonegg/trunk/src/Types.cpp Tue Aug 9 10:11:51 2011 @@ -23,11 +23,9 @@ // Plugin headers #include "dragonegg/ABI.h" +#include "dragonegg/Cache.h" #include "dragonegg/Trees.h" #include "dragonegg/Types.h" -extern "C" { -#include "dragonegg/cache.h" -} // LLVM headers #include "llvm/Module.h" @@ -306,7 +304,7 @@ // Matching LLVM types with GCC trees //===----------------------------------------------------------------------===// -// llvm_get_type/llvm_set_type - Associate an LLVM type with each TREE type. +// llvm_set_type - Associate an LLVM type with each TREE type. // These are lazily computed by ConvertType. static Type *llvm_set_type(tree Tr, Type *Ty) { @@ -329,16 +327,8 @@ } #endif - return (Type *)llvm_set_cached(Tr, Ty); -} - -static Type *llvm_get_type(tree Tr) { - assert(TYPE_P(Tr) && "Expected a gcc type!"); - return (Type *)llvm_get_cached(Tr); -} - -static bool llvm_has_type(tree Tr) { - return llvm_get_type(Tr) != 0; + setCachedType(Tr, Ty); + return Ty; } @@ -1460,8 +1450,8 @@ static Type *ConvertRECORD(tree type) { assert(TYPE_SIZE(type) && "Incomplete types should be handled elsewhere!"); - assert(llvm_get_type(type) && isa(llvm_get_type(type)) && - cast(llvm_get_type(type))->isOpaque() && + assert(getCachedType(type) && isa(getCachedType(type)) && + cast(getCachedType(type))->isOpaque() && "Incorrect placeholder for struct type!"); // Record those fields which will be converted to LLVM fields. @@ -1552,7 +1542,7 @@ } else Info->RemoveExtraBytes(); - StructType *ResultTy = cast(llvm_get_type(type)); + StructType *ResultTy = cast(getCachedType(type)); Info->fillInLLVMType(ResultTy); return ResultTy; @@ -1605,7 +1595,7 @@ case POINTER_TYPE: case REFERENCE_TYPE: // Converting these types may recurse unless the type was already converted. - return !llvm_has_type(type); + return getCachedType(type) == 0; case QUAL_UNION_TYPE: case RECORD_TYPE: @@ -1620,7 +1610,7 @@ return false; // If the type was not previously converted then converting it may recurse. - Type *Ty = llvm_get_type(type); + Type *Ty = getCachedType(type); if (!Ty) return true; @@ -1740,7 +1730,7 @@ case REFERENCE_TYPE: { // If these types are not recursive it can only be because they were already // converted and we can safely return the result of the previous conversion. - Type *Ty = llvm_get_type(type); + Type *Ty = getCachedType(type); assert(Ty && "Type not already converted!"); return Ty; } @@ -1757,7 +1747,7 @@ } case COMPLEX_TYPE: { - if (Type *Ty = llvm_get_type(type)) return Ty; + if (Type *Ty = getCachedType(type)) return Ty; Type *Ty = ConvertNonRecursiveType(TYPE_MAIN_VARIANT(TREE_TYPE(type))); Ty = StructType::get(Ty, Ty, NULL); return llvm_set_type(type, Ty); @@ -1790,7 +1780,7 @@ case QUAL_UNION_TYPE: case UNION_TYPE: // If the type was already converted then return the already computed type. - if (Type *Ty = llvm_get_type(type)) return Ty; + if (Type *Ty = getCachedType(type)) return Ty; // Otherwise this must be an incomplete type - return an opaque struct. assert(!TYPE_SIZE(type) && "Expected an incomplete type!"); @@ -1798,7 +1788,7 @@ getDescriptiveName(type))); case VECTOR_TYPE: { - if (Type *Ty = llvm_get_type(type)) return Ty; + if (Type *Ty = getCachedType(type)) return Ty; Type *Ty; // LLVM does not support vectors of pointers, so turn any pointers into // integers. @@ -1894,7 +1884,7 @@ if (TREE_CODE(pointee) == QUAL_UNION_TYPE || TREE_CODE(pointee) == RECORD_TYPE || TREE_CODE(pointee) == UNION_TYPE) - PointeeTy = llvm_get_type(pointee); + PointeeTy = getCachedType(pointee); else PointeeTy = StructType::get(Context); } @@ -1979,12 +1969,12 @@ if (TREE_CODE(some_type) != QUAL_UNION_TYPE && TREE_CODE(some_type) != RECORD_TYPE && TREE_CODE(some_type) != UNION_TYPE) { - assert(!llvm_has_type(some_type) && "Type already converted!"); + assert(!getCachedType(some_type) && "Type already converted!"); continue; } // If the type used to be incomplete then a opaque struct placeholder may // have been created for it already. - Type *Ty = llvm_get_type(some_type); + Type *Ty = getCachedType(some_type); if (Ty) { assert(isa(Ty) && cast(Ty)->isOpaque() && "Recursive struct already fully converted!"); @@ -2012,7 +2002,7 @@ // At this point every type reachable from this one has been converted, and // the conversion results cached. Return the value computed for the type. - Type *Ty = llvm_get_type(type); + Type *Ty = getCachedType(type); assert(Ty && "Type not converted!"); return Ty; } Removed: dragonegg/trunk/src/cache.c URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/cache.c?rev=137118&view=auto ============================================================================== --- dragonegg/trunk/src/cache.c (original) +++ dragonegg/trunk/src/cache.c (removed) @@ -1,139 +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. */ -#if (GCC_MINOR > 5) -#include "dragonegg/gt-cache-4.6.h" -#else -#include "dragonegg/gt-cache-4.5.h" -#endif - -/* 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 = -#if (GCC_MINOR > 5) - ggc_alloc_tree_llvm_map(); -#else - GGC_NEW(struct tree_llvm_map); -#endif - (*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); -} From stoklund at 2pi.dk Tue Aug 9 11:46:27 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 09 Aug 2011 16:46:27 -0000 Subject: [llvm-commits] [llvm] r137123 - in /llvm/trunk: include/llvm/CodeGen/CalcSpillWeights.h include/llvm/CodeGen/MachineRegisterInfo.h lib/CodeGen/CalcSpillWeights.cpp lib/CodeGen/LiveRangeEdit.cpp lib/CodeGen/MachineRegisterInfo.cpp Message-ID: <20110809164627.B67922A6C12E@llvm.org> Author: stoklund Date: Tue Aug 9 11:46:27 2011 New Revision: 137123 URL: http://llvm.org/viewvc/llvm-project?rev=137123&view=rev Log: Move CalculateRegClass to MRI::recomputeRegClass. This function doesn't have anything to do with spill weights, and MRI already has functions for manipulating the register class of a virtual register. Modified: llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp Modified: llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h?rev=137123&r1=137122&r2=137123&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h (original) +++ llvm/trunk/include/llvm/CodeGen/CalcSpillWeights.h Tue Aug 9 11:46:27 2011 @@ -49,11 +49,6 @@ const MachineLoopInfo &loops) : MF(mf), LIS(lis), Loops(loops) {} - /// CalculateRegClass - recompute the register class for reg from its uses. - /// Since the register class can affect the allocation hint, this function - /// should be called before CalculateWeightAndHint if both are called. - void CalculateRegClass(unsigned reg); - /// CalculateWeightAndHint - (re)compute li's spill weight and allocation /// hint. void CalculateWeightAndHint(LiveInterval &li); Modified: llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h?rev=137123&r1=137122&r2=137123&view=diff ============================================================================== --- llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h (original) +++ llvm/trunk/include/llvm/CodeGen/MachineRegisterInfo.h Tue Aug 9 11:46:27 2011 @@ -219,9 +219,20 @@ /// Return the new register class, or NULL if no such class exists. /// This should only be used when the constraint is known to be trivial, like /// GR32 -> GR32_NOSP. Beware of increasing register pressure. + /// const TargetRegisterClass *constrainRegClass(unsigned Reg, const TargetRegisterClass *RC); + /// recomputeRegClass - Try to find a legal super-class of Reg's register + /// class that still satisfies the constraints from the instructions using + /// Reg. Returns true if Reg was upgraded. + /// + /// This method can be used after constraints have been removed from a + /// virtual register, for example after removing instructions or splitting + /// the live range. + /// + bool recomputeRegClass(unsigned Reg, const TargetMachine&); + /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. /// Modified: llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp?rev=137123&r1=137122&r2=137123&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp (original) +++ llvm/trunk/lib/CodeGen/CalcSpillWeights.cpp Tue Aug 9 11:46:27 2011 @@ -185,35 +185,3 @@ li.weight = normalizeSpillWeight(totalWeight, li.getSize()); } - -void VirtRegAuxInfo::CalculateRegClass(unsigned reg) { - MachineRegisterInfo &MRI = MF.getRegInfo(); - const TargetInstrInfo *TII = MF.getTarget().getInstrInfo(); - const TargetRegisterInfo *TRI = MF.getTarget().getRegisterInfo(); - const TargetRegisterClass *OldRC = MRI.getRegClass(reg); - const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC); - - // Stop early if there is no room to grow. - if (NewRC == OldRC) - return; - - // Accumulate constraints from all uses. - for (MachineRegisterInfo::reg_nodbg_iterator I = MRI.reg_nodbg_begin(reg), - E = MRI.reg_nodbg_end(); I != E; ++I) { - // TRI doesn't have accurate enough information to model this yet. - if (I.getOperand().getSubReg()) - return; - // Inline asm instuctions don't remember their constraints. - if (I->isInlineAsm()) - return; - const TargetRegisterClass *OpRC = - TII->getRegClass(I->getDesc(), I.getOperandNo(), TRI); - if (OpRC) - NewRC = getCommonSubClass(NewRC, OpRC); - if (!NewRC || NewRC == OldRC) - return; - } - DEBUG(dbgs() << "Inflating " << OldRC->getName() << ':' << PrintReg(reg) - << " to " << NewRC->getName() <<".\n"); - MRI.setRegClass(reg, NewRC); -} Modified: llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp?rev=137123&r1=137122&r2=137123&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp (original) +++ llvm/trunk/lib/CodeGen/LiveRangeEdit.cpp Tue Aug 9 11:46:27 2011 @@ -319,9 +319,12 @@ LiveIntervals &LIS, const MachineLoopInfo &Loops) { VirtRegAuxInfo VRAI(MF, LIS, Loops); + MachineRegisterInfo &MRI = MF.getRegInfo(); for (iterator I = begin(), E = end(); I != E; ++I) { LiveInterval &LI = **I; - VRAI.CalculateRegClass(LI.reg); + if (MRI.recomputeRegClass(LI.reg, MF.getTarget())) + DEBUG(dbgs() << "Inflated " << PrintReg(LI.reg) << " to " + << MRI.getRegClass(LI.reg)->getName() << '\n'); VRAI.CalculateWeightAndHint(LI); } } Modified: llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp?rev=137123&r1=137122&r2=137123&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp (original) +++ llvm/trunk/lib/CodeGen/MachineRegisterInfo.cpp Tue Aug 9 11:46:27 2011 @@ -14,7 +14,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Support/CommandLine.h" +#include "llvm/Target/TargetMachine.h" using namespace llvm; MachineRegisterInfo::MachineRegisterInfo(const TargetRegisterInfo &TRI) @@ -61,6 +61,37 @@ return NewRC; } +bool +MachineRegisterInfo::recomputeRegClass(unsigned Reg, const TargetMachine &TM) { + const TargetInstrInfo *TII = TM.getInstrInfo(); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + const TargetRegisterClass *OldRC = getRegClass(Reg); + const TargetRegisterClass *NewRC = TRI->getLargestLegalSuperClass(OldRC); + + // Stop early if there is no room to grow. + if (NewRC == OldRC) + return false; + + // Accumulate constraints from all uses. + for (reg_nodbg_iterator I = reg_nodbg_begin(Reg), E = reg_nodbg_end(); I != E; + ++I) { + // TRI doesn't have accurate enough information to model this yet. + if (I.getOperand().getSubReg()) + return false; + // Inline asm instuctions don't remember their constraints. + if (I->isInlineAsm()) + return false; + const TargetRegisterClass *OpRC = + TII->getRegClass(I->getDesc(), I.getOperandNo(), TRI); + if (OpRC) + NewRC = getCommonSubClass(NewRC, OpRC); + if (!NewRC || NewRC == OldRC) + return false; + } + setRegClass(Reg, NewRC); + return true; +} + /// createVirtualRegister - Create and return a new virtual register in the /// function with the specified register class. /// From bruno.cardoso at gmail.com Tue Aug 9 11:56:05 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 9 Aug 2011 09:56:05 -0700 Subject: [llvm-commits] [llvm] r137114 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/avx-cvt.ll In-Reply-To: References: <20110809054801.6A5EB2A6C12C@llvm.org> Message-ID: I was thinking about that too. Just found a much better solution! Thanks Eli! On Mon, Aug 8, 2011 at 10:55 PM, Eli Friedman wrote: > On Mon, Aug 8, 2011 at 10:48 PM, Bruno Cardoso Lopes > wrote: >> Author: bruno >> Date: Tue Aug ?9 00:48:01 2011 >> New Revision: 137114 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=137114&view=rev >> Log: >> Handle sitofp between v4f64 <- v4i32. Fix PR10559 >> >> Modified: >> ? ?llvm/trunk/lib/Target/X86/X86ISelLowering.cpp >> ? ?llvm/trunk/test/CodeGen/X86/avx-cvt.ll >> >> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137114&r1=137113&r2=137114&view=diff >> ============================================================================== >> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) >> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Aug ?9 00:48:01 2011 >> @@ -969,6 +969,9 @@ >> ? ? setOperationAction(ISD::SINT_TO_FP, ? ? ? ? MVT::v8i32, Legal); >> ? ? setOperationAction(ISD::FP_ROUND, ? ? ? ? ? MVT::v4f32, Legal); >> >> + ? ?// sint_to_fp between different vector types needs custom handling >> + ? ?setOperationAction(ISD::SINT_TO_FP, ? ? ? ? MVT::v4i32, Custom); >> + >> ? ? setOperationAction(ISD::CONCAT_VECTORS, ? ? MVT::v4f64, ?Custom); >> ? ? setOperationAction(ISD::CONCAT_VECTORS, ? ? MVT::v4i64, ?Custom); >> ? ? setOperationAction(ISD::CONCAT_VECTORS, ? ? MVT::v8f32, ?Custom); >> @@ -7078,6 +7081,24 @@ >> ?SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op, >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SelectionDAG &DAG) const { >> ? EVT SrcVT = Op.getOperand(0).getValueType(); >> + ?EVT DstVT = Op.getValueType(); >> + ?DebugLoc dl = Op.getDebugLoc(); >> + >> + ?if (SrcVT.isVector() && DstVT.isVector()) { >> + ? ?unsigned SrcVTSize = SrcVT.getSizeInBits(); >> + ? ?unsigned DstVTSize = DstVT.getSizeInBits(); >> + >> + ? ?// Support directly by the target >> + ? ?if (SrcVTSize == DstVTSize) >> + ? ? ?return Op; >> + >> + ? ?// Handle v4f64 = sitofp v4i32 >> + ? ?if (DstVT != MVT::v4f64 && SrcVT != MVT::v4i32) >> + ? ? ?return SDValue(); >> + >> + ? ?SDValue V = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, Op.getOperand(0)); >> + ? ?return DAG.getNode(ISD::FP_EXTEND, dl, DstVT, V); >> + ?} > > Aren't there accuracy issues with this approach? ?A float can't > precisely represent every possible i32. > > -Eli > -- Bruno Cardoso Lopes http://www.brunocardoso.cc From rjmccall at apple.com Tue Aug 9 12:14:44 2011 From: rjmccall at apple.com (John McCall) Date: Tue, 09 Aug 2011 10:14:44 -0700 Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls In-Reply-To: References: Message-ID: <2B900B62-E852-4E5A-89C1-E5F0DBB44EA6@apple.com> On Aug 9, 2011, at 3:44 AM, Jay Foad wrote: > On 9 August 2011 11:40, Jay Foad wrote: >> On 9 August 2011 06:58, John McCall wrote: >>> I think your patch to LLVM is a good idea; replaceAllUsesWith should >>> not be assuming a fully-formed AST. As a slight optimization, I would >>> suggest doing this instead: >>> if (Succ->empty()) continue; >>> Jay, does that seem reasonable? >> >> Sure, I'm fine with either your or Takumi's fix. Thanks for taking the >> time to investigate. > > Hang on... if we need to cope with half-baked IR, won't your fix still > fall over on a BB that contains some phi nodes but nothing else? Ah, yes, that's true; good catch. Clang (and frontends in general) are much less likely to generate such code, but that's not a good reason for replaceAllUsesWith to fall over. John. From justin.holewinski at gmail.com Tue Aug 9 12:36:31 2011 From: justin.holewinski at gmail.com (Justin Holewinski) Date: Tue, 09 Aug 2011 17:36:31 -0000 Subject: [llvm-commits] [llvm] r137125 - in /llvm/trunk: lib/Target/PTX/PTXAsmPrinter.cpp lib/Target/PTX/PTXISelLowering.cpp lib/Target/PTX/PTXISelLowering.h lib/Target/PTX/PTXInstrInfo.td lib/Target/PTX/PTXMachineFunctionInfo.h lib/Target/PTX/PTXSubtarget.h test/CodeGen/PTX/simple-call.ll Message-ID: <20110809173631.A9ECC2A6C12E@llvm.org> Author: jholewinski Date: Tue Aug 9 12:36:31 2011 New Revision: 137125 URL: http://llvm.org/viewvc/llvm-project?rev=137125&view=rev Log: PTX: Add initial support for device function calls - Calls are supported on SM 2.0+ for function with no return values Added: llvm/trunk/test/CodeGen/PTX/simple-call.ll Modified: llvm/trunk/lib/Target/PTX/PTXAsmPrinter.cpp llvm/trunk/lib/Target/PTX/PTXISelLowering.cpp llvm/trunk/lib/Target/PTX/PTXISelLowering.h llvm/trunk/lib/Target/PTX/PTXInstrInfo.td llvm/trunk/lib/Target/PTX/PTXMachineFunctionInfo.h llvm/trunk/lib/Target/PTX/PTXSubtarget.h Modified: llvm/trunk/lib/Target/PTX/PTXAsmPrinter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PTX/PTXAsmPrinter.cpp?rev=137125&r1=137124&r2=137125&view=diff ============================================================================== --- llvm/trunk/lib/Target/PTX/PTXAsmPrinter.cpp (original) +++ llvm/trunk/lib/Target/PTX/PTXAsmPrinter.cpp Tue Aug 9 12:36:31 2011 @@ -70,6 +70,8 @@ const char *Modifier = 0); void printPredicateOperand(const MachineInstr *MI, raw_ostream &O); + void printCall(const MachineInstr *MI, raw_ostream &O); + unsigned GetOrCreateSourceID(StringRef FileName, StringRef DirName); @@ -242,6 +244,19 @@ OutStreamer.EmitRawText(Twine(def)); } } + + unsigned Index = 1; + // Print parameter passing params + for (PTXMachineFunctionInfo::param_iterator + i = MFI->paramBegin(), e = MFI->paramEnd(); i != e; ++i) { + std::string def = "\t.param .b"; + def += utostr(*i); + def += " __ret_"; + def += utostr(Index); + Index++; + def += ";"; + OutStreamer.EmitRawText(Twine(def)); + } } void PTXAsmPrinter::EmitInstruction(const MachineInstr *MI) { @@ -302,7 +317,11 @@ printPredicateOperand(MI, OS); // Write instruction to str - printInstruction(MI, OS); + if (MI->getOpcode() == PTX::CALL) { + printCall(MI, OS); + } else { + printInstruction(MI, OS); + } OS << ';'; OS.flush(); @@ -569,6 +588,28 @@ } } +void PTXAsmPrinter:: +printCall(const MachineInstr *MI, raw_ostream &O) { + + O << "\tcall.uni\t"; + + const GlobalValue *Address = MI->getOperand(2).getGlobal(); + O << Address->getName() << ", ("; + + // (0,1) : predicate register/flag + // (2) : callee + for (unsigned i = 3; i < MI->getNumOperands(); ++i) { + //const MachineOperand& MO = MI->getOperand(i); + + printReturnOperand(MI, i, O); + if (i < MI->getNumOperands()-1) { + O << ", "; + } + } + + O << ")"; +} + unsigned PTXAsmPrinter::GetOrCreateSourceID(StringRef FileName, StringRef DirName) { // If FE did not provide a file name, then assume stdin. Modified: llvm/trunk/lib/Target/PTX/PTXISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PTX/PTXISelLowering.cpp?rev=137125&r1=137124&r2=137125&view=diff ============================================================================== --- llvm/trunk/lib/Target/PTX/PTXISelLowering.cpp (original) +++ llvm/trunk/lib/Target/PTX/PTXISelLowering.cpp Tue Aug 9 12:36:31 2011 @@ -22,6 +22,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -134,6 +135,8 @@ return "PTXISD::EXIT"; case PTXISD::RET: return "PTXISD::RET"; + case PTXISD::CALL: + return "PTXISD::CALL"; } } @@ -345,3 +348,49 @@ return DAG.getNode(PTXISD::RET, dl, MVT::Other, Chain, Flag); } } + +SDValue +PTXTargetLowering::LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const { + + MachineFunction& MF = DAG.getMachineFunction(); + PTXMachineFunctionInfo *MFI = MF.getInfo(); + const PTXSubtarget& ST = getTargetMachine().getSubtarget(); + + assert(ST.callsAreHandled() && "Calls are not handled for the target device"); + + // Is there a more "LLVM"-way to create a variable-length array of values? + SDValue* ops = new SDValue[OutVals.size() + 2]; + + ops[0] = Chain; + + if (GlobalAddressSDNode *G = dyn_cast(Callee)) { + const GlobalValue *GV = G->getGlobal(); + Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy()); + ops[1] = Callee; + } else { + assert(false && "Function must be a GlobalAddressSDNode"); + } + + for (unsigned i = 0; i != OutVals.size(); ++i) { + unsigned Size = OutVals[i].getValueType().getSizeInBits(); + SDValue Index = DAG.getTargetConstant(MFI->getNextParam(Size), MVT::i32); + Chain = DAG.getNode(PTXISD::STORE_PARAM, dl, MVT::Other, Chain, + Index, OutVals[i]); + ops[i+2] = Index; + } + + ops[0] = Chain; + + Chain = DAG.getNode(PTXISD::CALL, dl, MVT::Other, ops, OutVals.size()+2); + + delete [] ops; + + return Chain; +} Modified: llvm/trunk/lib/Target/PTX/PTXISelLowering.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PTX/PTXISelLowering.h?rev=137125&r1=137124&r2=137125&view=diff ============================================================================== --- llvm/trunk/lib/Target/PTX/PTXISelLowering.h (original) +++ llvm/trunk/lib/Target/PTX/PTXISelLowering.h Tue Aug 9 12:36:31 2011 @@ -28,7 +28,8 @@ STORE_PARAM, EXIT, RET, - COPY_ADDRESS + COPY_ADDRESS, + CALL }; } // namespace PTXISD @@ -60,6 +61,16 @@ DebugLoc dl, SelectionDAG &DAG) const; + virtual SDValue + LowerCall(SDValue Chain, SDValue Callee, + CallingConv::ID CallConv, bool isVarArg, + bool &isTailCall, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SmallVectorImpl &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl &InVals) const; + virtual MVT::SimpleValueType getSetCCResultType(EVT VT) const; private: Modified: llvm/trunk/lib/Target/PTX/PTXInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PTX/PTXInstrInfo.td?rev=137125&r1=137124&r2=137125&view=diff ============================================================================== --- llvm/trunk/lib/Target/PTX/PTXInstrInfo.td (original) +++ llvm/trunk/lib/Target/PTX/PTXInstrInfo.td Tue Aug 9 12:36:31 2011 @@ -168,6 +168,18 @@ let MIOperandInfo = (ops i32imm); } +// def SDT_PTXCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>; +// def SDT_PTXCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>; + +// def PTXcallseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PTXCallSeqStart, +// [SDNPHasChain, SDNPOutGlue]>; +// def PTXcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PTXCallSeqEnd, +// [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; + +def PTXcall : SDNode<"PTXISD::CALL", SDTNone, + [SDNPHasChain, SDNPVariadic, SDNPOptInGlue, SDNPOutGlue]>; + + // Branch & call targets have OtherVT type. def brtarget : Operand; def calltarget : Operand; @@ -1073,6 +1085,11 @@ def RET : InstPTX<(outs), (ins), "ret", [(PTXret)]>; } +let hasSideEffects = 1 in { + def CALL : InstPTX<(outs), (ins), "call", [(PTXcall)]>; +} + + ///===- Spill Instructions ------------------------------------------------===// // Special instructions used for stack spilling def STACKSTOREI16 : InstPTX<(outs), (ins i32imm:$d, RegI16:$a), @@ -1097,6 +1114,15 @@ def STACKLOADF64 : InstPTX<(outs), (ins RegF64:$d, i32imm:$a), "mov.f64\t$d, s$a", []>; + +// Call handling +// def ADJCALLSTACKUP : +// InstPTX<(outs), (ins i32imm:$amt1, i32imm:$amt2), "", +// [(PTXcallseq_end timm:$amt1, timm:$amt2)]>; +// def ADJCALLSTACKDOWN : +// InstPTX<(outs), (ins i32imm:$amt), "", +// [(PTXcallseq_start timm:$amt)]>; + ///===- Intrinsic Instructions --------------------------------------------===// include "PTXIntrinsicInstrInfo.td" Modified: llvm/trunk/lib/Target/PTX/PTXMachineFunctionInfo.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PTX/PTXMachineFunctionInfo.h?rev=137125&r1=137124&r2=137125&view=diff ============================================================================== --- llvm/trunk/lib/Target/PTX/PTXMachineFunctionInfo.h (original) +++ llvm/trunk/lib/Target/PTX/PTXMachineFunctionInfo.h Tue Aug 9 12:36:31 2011 @@ -27,6 +27,7 @@ bool is_kernel; std::vector reg_arg, reg_local_var; std::vector reg_ret; + std::vector call_params; bool _isDoneAddArg; public: @@ -56,6 +57,7 @@ typedef std::vector::const_iterator reg_iterator; typedef std::vector::const_reverse_iterator reg_reverse_iterator; typedef std::vector::const_iterator ret_iterator; + typedef std::vector::const_iterator param_iterator; bool argRegEmpty() const { return reg_arg.empty(); } int getNumArg() const { return reg_arg.size(); } @@ -73,6 +75,13 @@ ret_iterator retRegBegin() const { return reg_ret.begin(); } ret_iterator retRegEnd() const { return reg_ret.end(); } + param_iterator paramBegin() const { return call_params.begin(); } + param_iterator paramEnd() const { return call_params.end(); } + unsigned getNextParam(unsigned size) { + call_params.push_back(size); + return call_params.size()-1; + } + bool isArgReg(unsigned reg) const { return std::find(reg_arg.begin(), reg_arg.end(), reg) != reg_arg.end(); } Modified: llvm/trunk/lib/Target/PTX/PTXSubtarget.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PTX/PTXSubtarget.h?rev=137125&r1=137124&r2=137125&view=diff ============================================================================== --- llvm/trunk/lib/Target/PTX/PTXSubtarget.h (original) +++ llvm/trunk/lib/Target/PTX/PTXSubtarget.h Tue Aug 9 12:36:31 2011 @@ -114,7 +114,12 @@ (PTXTarget >= PTX_COMPUTE_2_0 && PTXTarget < PTX_LAST_COMPUTE); } - void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + bool callsAreHandled() const { + return (PTXTarget >= PTX_SM_2_0 && PTXTarget < PTX_LAST_SM) || + (PTXTarget >= PTX_COMPUTE_2_0 && PTXTarget < PTX_LAST_COMPUTE); + } + + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); }; // class PTXSubtarget } // namespace llvm Added: llvm/trunk/test/CodeGen/PTX/simple-call.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PTX/simple-call.ll?rev=137125&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/PTX/simple-call.ll (added) +++ llvm/trunk/test/CodeGen/PTX/simple-call.ll Tue Aug 9 12:36:31 2011 @@ -0,0 +1,14 @@ +; RUN: llc < %s -march=ptx32 -mattr=sm20 | FileCheck %s + +define ptx_device void @test_add(float %x, float %y) { +; CHECK: ret; + %z = fadd float %x, %y + ret void +} + +define ptx_device float @test_call(float %x, float %y) { + %a = fadd float %x, %y +; CHECK: call.uni test_add, (__ret_{{[0-9]+}}, __ret_{{[0-9]+}}); + call void @test_add(float %a, float %y) + ret float %a +} From bruno.cardoso at gmail.com Tue Aug 9 12:39:01 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 17:39:01 -0000 Subject: [llvm-commits] [llvm] r137127 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/avx-cvt.ll Message-ID: <20110809173901.D4CD62A6C12E@llvm.org> Author: bruno Date: Tue Aug 9 12:39:01 2011 New Revision: 137127 URL: http://llvm.org/viewvc/llvm-project?rev=137127&view=rev Log: Revert r137114 Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/test/CodeGen/X86/avx-cvt.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137127&r1=137126&r2=137127&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Aug 9 12:39:01 2011 @@ -969,9 +969,6 @@ setOperationAction(ISD::SINT_TO_FP, MVT::v8i32, Legal); setOperationAction(ISD::FP_ROUND, MVT::v4f32, Legal); - // sint_to_fp between different vector types needs custom handling - setOperationAction(ISD::SINT_TO_FP, MVT::v4i32, Custom); - setOperationAction(ISD::CONCAT_VECTORS, MVT::v4f64, Custom); setOperationAction(ISD::CONCAT_VECTORS, MVT::v4i64, Custom); setOperationAction(ISD::CONCAT_VECTORS, MVT::v8f32, Custom); @@ -7081,24 +7078,6 @@ SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) const { EVT SrcVT = Op.getOperand(0).getValueType(); - EVT DstVT = Op.getValueType(); - DebugLoc dl = Op.getDebugLoc(); - - if (SrcVT.isVector() && DstVT.isVector()) { - unsigned SrcVTSize = SrcVT.getSizeInBits(); - unsigned DstVTSize = DstVT.getSizeInBits(); - - // Support directly by the target - if (SrcVTSize == DstVTSize) - return Op; - - // Handle v4f64 = sitofp v4i32 - if (DstVT != MVT::v4f64 && SrcVT != MVT::v4i32) - return SDValue(); - - SDValue V = DAG.getNode(ISD::SINT_TO_FP, dl, MVT::v4f32, Op.getOperand(0)); - return DAG.getNode(ISD::FP_EXTEND, dl, DstVT, V); - } if (SrcVT.isVector()) return SDValue(); @@ -7115,6 +7094,7 @@ return Op; } + DebugLoc dl = Op.getDebugLoc(); unsigned Size = SrcVT.getSizeInBits()/8; MachineFunction &MF = DAG.getMachineFunction(); int SSFI = MF.getFrameInfo()->CreateStackObject(Size, Size, false); Modified: llvm/trunk/test/CodeGen/X86/avx-cvt.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-cvt.ll?rev=137127&r1=137126&r2=137127&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-cvt.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-cvt.ll Tue Aug 9 12:39:01 2011 @@ -6,13 +6,6 @@ ret <8 x float> %b } -; CHECK: vcvtdq2ps -; CHECK-NEXT: vcvtps2pd -define <4 x double> @sitofp01(<4 x i32> %a) { - %b = sitofp <4 x i32> %a to <4 x double> - ret <4 x double> %b -} - ; CHECK: vcvttps2dq %ymm define <8 x i32> @fptosi00(<8 x float> %a) nounwind { %b = fptosi <8 x float> %a to <8 x i32> From bruno.cardoso at gmail.com Tue Aug 9 12:39:13 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 17:39:13 -0000 Subject: [llvm-commits] [llvm] r137128 - in /llvm/trunk: lib/Target/X86/X86InstrSSE.td test/CodeGen/X86/avx-cvt.ll Message-ID: <20110809173914.196C32A6C12E@llvm.org> Author: bruno Date: Tue Aug 9 12:39:13 2011 New Revision: 137128 URL: http://llvm.org/viewvc/llvm-project?rev=137128&view=rev Log: Reapply a more appropriate solution than in r137114. AVX supports v4f64 = sitofp v4i32. This fix PR10559. Also add support for v4i32 = fptosi v4f64. Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/test/CodeGen/X86/avx-cvt.ll Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=137128&r1=137127&r2=137128&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Tue Aug 9 12:39:13 2011 @@ -3305,6 +3305,11 @@ def CVTPD2DQrr : S3DI<0xE6, MRMSrcReg, (outs VR128:$dst), (ins VR128:$src), "cvtpd2dq\t{$src, $dst|$dst, $src}", []>; +def : Pat<(v4i32 (fp_to_sint (v4f64 VR256:$src))), + (VCVTPD2DQYrr VR256:$src)>; +def : Pat<(v4i32 (fp_to_sint (memopv4f64 addr:$src))), + (VCVTPD2DQYrm addr:$src)>; + // Convert Packed DW Integers to Packed Double FP let Predicates = [HasAVX] in { def VCVTDQ2PDrm : S3SI<0xE6, MRMSrcMem, (outs VR128:$dst), (ins f128mem:$src), @@ -3333,6 +3338,11 @@ def : Pat<(int_x86_avx_cvt_pd2dq_256 (memopv4f64 addr:$src)), (VCVTPD2DQYrm addr:$src)>; +def : Pat<(v4f64 (sint_to_fp (v4i32 VR128:$src))), + (VCVTDQ2PDYrr VR128:$src)>; +def : Pat<(v4f64 (sint_to_fp (memopv4i32 addr:$src))), + (VCVTDQ2PDYrm addr:$src)>; + //===---------------------------------------------------------------------===// // SSE3 - Move Instructions //===---------------------------------------------------------------------===// Modified: llvm/trunk/test/CodeGen/X86/avx-cvt.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-cvt.ll?rev=137128&r1=137127&r2=137128&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-cvt.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-cvt.ll Tue Aug 9 12:39:13 2011 @@ -12,6 +12,18 @@ ret <8 x i32> %b } +; CHECK: vcvtdq2pd %xmm +define <4 x double> @sitofp01(<4 x i32> %a) { + %b = sitofp <4 x i32> %a to <4 x double> + ret <4 x double> %b +} + +; CHECK: vcvtpd2dqy %ymm +define <4 x i32> @fptosi01(<4 x double> %a) { + %b = fptosi <4 x double> %a to <4 x i32> + ret <4 x i32> %b +} + ; CHECK: vcvtpd2psy %ymm ; CHECK-NEXT: vcvtpd2psy %ymm ; CHECK-NEXT: vinsertf128 $1 From bob.wilson at apple.com Tue Aug 9 12:47:41 2011 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 09 Aug 2011 10:47:41 -0700 Subject: [llvm-commits] [llvm-gcc-4.2] r136345 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp In-Reply-To: <4E36E21A.2050103@free.fr> References: <20110728091343.E09F02A6C12C@llvm.org> <515E325F-1081-4CB8-8296-C8D1F5F06E8C@apple.com> <4E35A51A.6050009@free.fr> <4E36E21A.2050103@free.fr> Message-ID: On Aug 1, 2011, at 10:27 AM, Duncan Sands wrote: > Hi Bob, > >>> commit 136600 hopefully fixed these failures. >> >> I haven't confirmed yet whether it fixed the ARM problems (due to other issues), >> but it seems to be causing massive failures on i386: >> >> http://llvm.org/perf/db_default/simple/nts/263/ >> >> I can reproduce some of those failures with -O0 and we're not seeing any issues >> with clang, so I think it's due to your change. I'm going to revert it for now >> and re-run the tests to confirm that. > > OK, sorry for the breakage. I only tested on x86-64, I will take a look at > i386. Duncan, are you still planning to get to this? Those ObjC unit tests are still failing. From stoklund at 2pi.dk Tue Aug 9 13:19:41 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 09 Aug 2011 18:19:41 -0000 Subject: [llvm-commits] [llvm] r137133 - in /llvm/trunk: lib/CodeGen/RegisterCoalescer.cpp test/CodeGen/ARM/fabss.ll test/CodeGen/ARM/fp_convert.ll Message-ID: <20110809181941.F08772A6C12E@llvm.org> Author: stoklund Date: Tue Aug 9 13:19:41 2011 New Revision: 137133 URL: http://llvm.org/viewvc/llvm-project?rev=137133&view=rev Log: Inflate register classes after coalescing. Coalescing can remove copy-like instructions with sub-register operands that constrained the register class. Examples are: x86: GR32_ABCD:sub_8bit_hi -> GR32 arm: DPR_VFP2:ssub0 -> DPR Recompute the register class of any virtual registers that are used by less instructions after coalescing. This affects code generation for the Cortex-A8 where we use NEON instructions for f32 operations, c.f. fp_convert.ll: vadd.f32 d16, d1, d0 vcvt.s32.f32 d0, d16 The register allocator is now free to use d16 for the temporary, and that comes first in the allocation order because it doesn't interfere with any s-registers. Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp llvm/trunk/test/CodeGen/ARM/fabss.ll llvm/trunk/test/CodeGen/ARM/fp_convert.ll Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp?rev=137133&r1=137132&r2=137133&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp (original) +++ llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp Tue Aug 9 13:19:41 2011 @@ -55,6 +55,7 @@ STATISTIC(NumReMats , "Number of instructions re-materialized"); STATISTIC(numPeep , "Number of identity moves eliminated after coalescing"); STATISTIC(numAborts , "Number of times interval joining aborted"); +STATISTIC(NumInflated , "Number of register classes inflated"); static cl::opt EnableJoining("join-liveintervals", @@ -1852,7 +1853,7 @@ // Perform a final pass over the instructions and compute spill weights // and remove identity moves. - SmallVector DeadDefs; + SmallVector DeadDefs, InflateRegs; for (MachineFunction::iterator mbbi = MF->begin(), mbbe = MF->end(); mbbi != mbbe; ++mbbi) { MachineBasicBlock* mbb = mbbi; @@ -1864,6 +1865,16 @@ bool DoDelete = true; assert(MI->isCopyLike() && "Unrecognized copy instruction"); unsigned SrcReg = MI->getOperand(MI->isSubregToReg() ? 2 : 1).getReg(); + unsigned DstReg = MI->getOperand(0).getReg(); + + // Collect candidates for register class inflation. + if (TargetRegisterInfo::isVirtualRegister(SrcReg) && + RegClassInfo.isProperSubClass(MRI->getRegClass(SrcReg))) + InflateRegs.push_back(SrcReg); + if (TargetRegisterInfo::isVirtualRegister(DstReg) && + RegClassInfo.isProperSubClass(MRI->getRegClass(DstReg))) + InflateRegs.push_back(DstReg); + if (TargetRegisterInfo::isPhysicalRegister(SrcReg) && MI->getNumOperands() > 2) // Do not delete extract_subreg, insert_subreg of physical @@ -1905,8 +1916,12 @@ unsigned Reg = MO.getReg(); if (!Reg) continue; - if (TargetRegisterInfo::isVirtualRegister(Reg)) + if (TargetRegisterInfo::isVirtualRegister(Reg)) { DeadDefs.push_back(Reg); + // Remat may also enable register class inflation. + if (RegClassInfo.isProperSubClass(MRI->getRegClass(Reg))) + InflateRegs.push_back(Reg); + } if (MO.isDead()) continue; if (TargetRegisterInfo::isPhysicalRegister(Reg) || @@ -1954,6 +1969,24 @@ } } + // After deleting a lot of copies, register classes may be less constrained. + // Removing sub-register opreands may alow GR32_ABCD -> GR32 and DPR_VFP2 -> + // DPR inflation. + array_pod_sort(InflateRegs.begin(), InflateRegs.end()); + InflateRegs.erase(std::unique(InflateRegs.begin(), InflateRegs.end()), + InflateRegs.end()); + DEBUG(dbgs() << "Trying to inflate " << InflateRegs.size() << " regs.\n"); + for (unsigned i = 0, e = InflateRegs.size(); i != e; ++i) { + unsigned Reg = InflateRegs[i]; + if (MRI->reg_nodbg_empty(Reg)) + continue; + if (MRI->recomputeRegClass(Reg, *TM)) { + DEBUG(dbgs() << PrintReg(Reg) << " inflated to " + << MRI->getRegClass(Reg)->getName() << '\n'); + ++NumInflated; + } + } + DEBUG(dump()); DEBUG(LDV->dump()); if (VerifyCoalescing) Modified: llvm/trunk/test/CodeGen/ARM/fabss.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/fabss.ll?rev=137133&r1=137132&r2=137133&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/fabss.ll (original) +++ llvm/trunk/test/CodeGen/ARM/fabss.ll Tue Aug 9 13:19:41 2011 @@ -22,6 +22,8 @@ ; NFP0: vabs.f32 s1, s1 ; CORTEXA8: test: -; CORTEXA8: vabs.f32 d1, d1 +; CORTEXA8: vadd.f32 [[D1:d[0-9]+]] +; CORTEXA8: vabs.f32 {{d[0-9]+}}, [[D1]] + ; CORTEXA9: test: ; CORTEXA9: vabs.f32 s{{.}}, s{{.}} Modified: llvm/trunk/test/CodeGen/ARM/fp_convert.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/fp_convert.ll?rev=137133&r1=137132&r2=137133&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/ARM/fp_convert.ll (original) +++ llvm/trunk/test/CodeGen/ARM/fp_convert.ll Tue Aug 9 13:19:41 2011 @@ -7,7 +7,8 @@ ; VFP2: test1: ; VFP2: vcvt.s32.f32 s{{.}}, s{{.}} ; NEON: test1: -; NEON: vcvt.s32.f32 d0, d0 +; NEON: vadd.f32 [[D0:d[0-9]+]] +; NEON: vcvt.s32.f32 d0, [[D0]] entry: %0 = fadd float %a, %b %1 = fptosi float %0 to i32 @@ -18,7 +19,8 @@ ; VFP2: test2: ; VFP2: vcvt.u32.f32 s{{.}}, s{{.}} ; NEON: test2: -; NEON: vcvt.u32.f32 d0, d0 +; NEON: vadd.f32 [[D0:d[0-9]+]] +; NEON: vcvt.u32.f32 d0, [[D0]] entry: %0 = fadd float %a, %b %1 = fptoui float %0 to i32 From wendling at apple.com Tue Aug 9 13:25:53 2011 From: wendling at apple.com (Bill Wendling) Date: Tue, 09 Aug 2011 11:25:53 -0700 Subject: [llvm-commits] [PATCH] Revised LandingPadInst Patch In-Reply-To: <4E40FECB.5090901@free.fr> References: <4E40E16E.6090908@free.fr> <52C08EA4-D7BB-4B65-8850-582C6078F246@apple.com> <4E40F6F1.1030507@free.fr> <4E40FECB.5090901@free.fr> Message-ID: <4978D8A1-9343-4521-844D-81D0B62E4FE9@apple.com> On Aug 9, 2011, at 2:32 AM, Duncan Sands wrote: > Hi Bill, > >>> An alternative is to have: for a catch, an operand which is a (bitcast) global >>> or null*; for a filter, an operand which is a constant array, each element of >>> which is a (bitcast) global or null*. Thus each clause would only take up one >>> operand. >> >> >> The "OperandList" setup for the Instructions is rather complex as it is. Having two or more OperandLists (one list for each 'filter' array) gets very complex very quickly. And we want an OperandList-like data structure so that it can track uses of the LLVM IR objects. > > I think you misunderstood. I meant something like this: > > @_ZTIc = external constant i8* > @_ZTId = external constant i8* > @_ZTIPKc = external constant i8* > > %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 > cleanup > i8** @_ZTIc ; catch because global variable > [0 x i8**] [] ; (empty) filter because constant array > i8** @_ZTIc ; catch because global variable > [0 x i8**] [] ; (empty) filter because constant array > i8** @_ZTId ; catch because global variable > [2 x i8**] [ i8** @_ZTIPKc, i8** @_ZTId ] ; filter because constant array > > Ciao, Duncan. Ah! I think I understand. So it's not so much that the arrays would be splatted out into the OperandList, but that they would be referenced from there (or something). BTW, care must be taken. An empty filter has a specific meaning in this scheme: it's equivalent to a "throw()" in C++. -bw From isanbard at gmail.com Tue Aug 9 13:31:50 2011 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 09 Aug 2011 18:31:50 -0000 Subject: [llvm-commits] [llvm] r137134 - in /llvm/trunk: lib/Target/CBackend/CBackend.cpp test/CodeGen/CBackend/pr10081.ll Message-ID: <20110809183150.AC89D2A6C12E@llvm.org> Author: void Date: Tue Aug 9 13:31:50 2011 New Revision: 137134 URL: http://llvm.org/viewvc/llvm-project?rev=137134&view=rev Log: Print out the variable declaration only if it is a declaration. Otherwise, a 'static' variable will be emitted twice. PR10081 Added: llvm/trunk/test/CodeGen/CBackend/pr10081.ll Modified: llvm/trunk/lib/Target/CBackend/CBackend.cpp Modified: llvm/trunk/lib/Target/CBackend/CBackend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CBackend/CBackend.cpp?rev=137134&r1=137133&r2=137134&view=diff ============================================================================== --- llvm/trunk/lib/Target/CBackend/CBackend.cpp (original) +++ llvm/trunk/lib/Target/CBackend/CBackend.cpp Tue Aug 9 13:31:50 2011 @@ -1817,7 +1817,7 @@ Out << "\n\n/* Global Variable Declarations */\n"; for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (!I->isDeclaration()) { + if (I->isDeclaration()) { // Ignore special globals, such as debug info. if (getGlobalVariableClass(I)) continue; Added: llvm/trunk/test/CodeGen/CBackend/pr10081.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CBackend/pr10081.ll?rev=137134&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/CBackend/pr10081.ll (added) +++ llvm/trunk/test/CodeGen/CBackend/pr10081.ll Tue Aug 9 13:31:50 2011 @@ -0,0 +1,11 @@ +; RUN: llc < %s -march=c | grep {static float _ZL3foo} | count 1 +; PR10081 + + at _ZL3foo = internal global float 0.000000e+00, align 4 + +define float @_Z3barv() nounwind ssp { + %1 = load float* @_ZL3foo, align 4 + %2 = fadd float %1, 1.000000e+00 + store float %2, float* @_ZL3foo, align 4 + ret float %1 +} From baldrick at free.fr Tue Aug 9 13:32:37 2011 From: baldrick at free.fr (Duncan Sands) Date: Tue, 09 Aug 2011 20:32:37 +0200 Subject: [llvm-commits] [llvm-gcc-4.2] r136345 - /llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp In-Reply-To: References: <20110728091343.E09F02A6C12C@llvm.org> <515E325F-1081-4CB8-8296-C8D1F5F06E8C@apple.com> <4E35A51A.6050009@free.fr> <4E36E21A.2050103@free.fr> Message-ID: <4E417D45.2090905@free.fr> Hi Bob, >>>> commit 136600 hopefully fixed these failures. >>> >>> I haven't confirmed yet whether it fixed the ARM problems (due to other issues), >>> but it seems to be causing massive failures on i386: >>> >>> http://llvm.org/perf/db_default/simple/nts/263/ >>> >>> I can reproduce some of those failures with -O0 and we're not seeing any issues >>> with clang, so I think it's due to your change. I'm going to revert it for now >>> and re-run the tests to confirm that. >> >> OK, sorry for the breakage. I only tested on x86-64, I will take a look at >> i386. > > Duncan, are you still planning to get to this? Those ObjC unit tests are still failing. not really. The basic problem is that the same GCC pointer type is converted into more than one LLVM type, depending on whether it is converted as part of converting an enclosing struct or not. In the ObjC testcases this results in an apparent change in the initializer: the initializer is basically unchanged, only the type of some pointers changed. This can be fixed by caching the result of the pointer conversion the first time it happens, and then using that everywhere. This resulted in miscompiles on x86 (and presumably elsewhere, only less spectacular), because code in various parts of llvm-gcc assumes that if you convert a T*, then you get a pointer to convert(T). For example, to evaluate p + n where p is a T*, it (IIRC) just does a "GEP p, n". But if sometimes T* is converted to i8*, then "GEP p, n" advances by n bytes rather than by n * sizeof(T) bytes. In fact, if you think about it, if ever convert(T*) != convert(T)*, then there is a chance of things going wrong. Unfortunately the new type system requires that occasionally T* not be converted to convert(T)*. The right thing to do is to audit all of the llvm-gcc code for places where it makes assumptions about how T* is converted, and fix them all. I actually did this in dragonegg some time ago, which is why it doesn't suffer like llvm-gcc does from the new type system. The quick and nasty thing to do is to paper over problems until you don't notice problems any more. For example, fix the objc testcases by handling the case where the new initializer doesn't have the same type as the old one. I'm not interested in auditing llvm-gcc's code (though probably there wouldn't be too much to check). I'm also not interested in hacking in a nasty "fix". Thus I'm not planning to do anything about this. Ciao, Duncan. PS: You could revert the change that fixed the Fortran builders, and stop those builders from building Fortran. That would also just be papering over the underlying problem, but maybe is acceptable. From eli.friedman at gmail.com Tue Aug 9 13:44:15 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 9 Aug 2011 11:44:15 -0700 Subject: [llvm-commits] [llvm] r137134 - in /llvm/trunk: lib/Target/CBackend/CBackend.cpp test/CodeGen/CBackend/pr10081.ll In-Reply-To: <20110809183150.AC89D2A6C12E@llvm.org> References: <20110809183150.AC89D2A6C12E@llvm.org> Message-ID: On Tue, Aug 9, 2011 at 11:31 AM, Bill Wendling wrote: > Author: void > Date: Tue Aug ?9 13:31:50 2011 > New Revision: 137134 > > URL: http://llvm.org/viewvc/llvm-project?rev=137134&view=rev > Log: > Print out the variable declaration only if it is a declaration. Otherwise, a > 'static' variable will be emitted twice. > PR10081 > > Added: > ? ?llvm/trunk/test/CodeGen/CBackend/pr10081.ll > Modified: > ? ?llvm/trunk/lib/Target/CBackend/CBackend.cpp > > Modified: llvm/trunk/lib/Target/CBackend/CBackend.cpp > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CBackend/CBackend.cpp?rev=137134&r1=137133&r2=137134&view=diff > ============================================================================== > --- llvm/trunk/lib/Target/CBackend/CBackend.cpp (original) > +++ llvm/trunk/lib/Target/CBackend/CBackend.cpp Tue Aug ?9 13:31:50 2011 > @@ -1817,7 +1817,7 @@ > ? ? Out << "\n\n/* Global Variable Declarations */\n"; > ? ? for (Module::global_iterator I = M.global_begin(), E = M.global_end(); > ? ? ? ? ?I != E; ++I) > - ? ? ?if (!I->isDeclaration()) { > + ? ? ?if (I->isDeclaration()) { > ? ? ? ? // Ignore special globals, such as debug info. > ? ? ? ? if (getGlobalVariableClass(I)) > ? ? ? ? ? continue; I'm pretty sure the original code was correct... and works as long as you don't try to compile the output of the C backend as C++. Consider something like the following C code: static void* x; static void* y = &x; static void* x = &y; void* z = &y; -Eli From isanbard at gmail.com Tue Aug 9 13:56:35 2011 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 09 Aug 2011 18:56:35 -0000 Subject: [llvm-commits] [llvm] r137135 - in /llvm/trunk: lib/Target/CBackend/CBackend.cpp test/CodeGen/CBackend/pr10081.ll Message-ID: <20110809185635.3C4BD2A6C12E@llvm.org> Author: void Date: Tue Aug 9 13:56:35 2011 New Revision: 137135 URL: http://llvm.org/viewvc/llvm-project?rev=137135&view=rev Log: Revert r137134. It breaks some code as Eli pointed out. Removed: llvm/trunk/test/CodeGen/CBackend/pr10081.ll Modified: llvm/trunk/lib/Target/CBackend/CBackend.cpp Modified: llvm/trunk/lib/Target/CBackend/CBackend.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CBackend/CBackend.cpp?rev=137135&r1=137134&r2=137135&view=diff ============================================================================== --- llvm/trunk/lib/Target/CBackend/CBackend.cpp (original) +++ llvm/trunk/lib/Target/CBackend/CBackend.cpp Tue Aug 9 13:56:35 2011 @@ -1817,7 +1817,7 @@ Out << "\n\n/* Global Variable Declarations */\n"; for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) - if (I->isDeclaration()) { + if (!I->isDeclaration()) { // Ignore special globals, such as debug info. if (getGlobalVariableClass(I)) continue; Removed: llvm/trunk/test/CodeGen/CBackend/pr10081.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/CBackend/pr10081.ll?rev=137134&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/CBackend/pr10081.ll (original) +++ llvm/trunk/test/CodeGen/CBackend/pr10081.ll (removed) @@ -1,11 +0,0 @@ -; RUN: llc < %s -march=c | grep {static float _ZL3foo} | count 1 -; PR10081 - - at _ZL3foo = internal global float 0.000000e+00, align 4 - -define float @_Z3barv() nounwind ssp { - %1 = load float* @_ZL3foo, align 4 - %2 = fadd float %1, 1.000000e+00 - store float %2, float* @_ZL3foo, align 4 - ret float %1 -} From isanbard at gmail.com Tue Aug 9 13:57:40 2011 From: isanbard at gmail.com (Bill Wendling) Date: Tue, 9 Aug 2011 11:57:40 -0700 Subject: [llvm-commits] [llvm] r137134 - in /llvm/trunk: lib/Target/CBackend/CBackend.cpp test/CodeGen/CBackend/pr10081.ll In-Reply-To: References: <20110809183150.AC89D2A6C12E@llvm.org> Message-ID: <6D8345E2-9609-4191-AC32-56CCEB82EC36@gmail.com> On Aug 9, 2011, at 11:44 AM, Eli Friedman wrote: > On Tue, Aug 9, 2011 at 11:31 AM, Bill Wendling wrote: >> Author: void >> Date: Tue Aug 9 13:31:50 2011 >> New Revision: 137134 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=137134&view=rev >> Log: >> Print out the variable declaration only if it is a declaration. Otherwise, a >> 'static' variable will be emitted twice. >> PR10081 >> >> Added: >> llvm/trunk/test/CodeGen/CBackend/pr10081.ll >> Modified: >> llvm/trunk/lib/Target/CBackend/CBackend.cpp >> >> Modified: llvm/trunk/lib/Target/CBackend/CBackend.cpp >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CBackend/CBackend.cpp?rev=137134&r1=137133&r2=137134&view=diff >> ============================================================================== >> --- llvm/trunk/lib/Target/CBackend/CBackend.cpp (original) >> +++ llvm/trunk/lib/Target/CBackend/CBackend.cpp Tue Aug 9 13:31:50 2011 >> @@ -1817,7 +1817,7 @@ >> Out << "\n\n/* Global Variable Declarations */\n"; >> for (Module::global_iterator I = M.global_begin(), E = M.global_end(); >> I != E; ++I) >> - if (!I->isDeclaration()) { >> + if (I->isDeclaration()) { >> // Ignore special globals, such as debug info. >> if (getGlobalVariableClass(I)) >> continue; > > I'm pretty sure the original code was correct... and works as long as > you don't try to compile the output of the C backend as C++. Consider > something like the following C code: > static void* x; > static void* y = &x; > static void* x = &y; > void* z = &y; > Doh!! You're right? -bw From clattner at apple.com Tue Aug 9 14:02:33 2011 From: clattner at apple.com (Chris Lattner) Date: Tue, 09 Aug 2011 12:02:33 -0700 Subject: [llvm-commits] [llvm] r137111 - /llvm/trunk/lib/Support/Unix/Host.inc In-Reply-To: <20110809051336.C09ED2A6C12C@llvm.org> References: <20110809051336.C09ED2A6C12C@llvm.org> Message-ID: <0624A676-9485-4208-8EAC-F836B4795A39@apple.com> On Aug 8, 2011, at 10:13 PM, Bob Wilson wrote: > Author: bwilson > Date: Tue Aug 9 00:13:36 2011 > New Revision: 137111 > > URL: http://llvm.org/viewvc/llvm-project?rev=137111&view=rev > Log: > Recognize the UNAME_RELEASE environment variable to match Darwin's uname. > When this variable is set, "uname -r" will return its value instead of the > real OS version. Make this affect LLVM's triple for consistency. > Hi Bob, Should this be #ifdef __APPLE__ or something? -Chris > > Modified: > llvm/trunk/lib/Support/Unix/Host.inc > > Modified: llvm/trunk/lib/Support/Unix/Host.inc > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Host.inc?rev=137111&r1=137110&r2=137111&view=diff > ============================================================================== > --- llvm/trunk/lib/Support/Unix/Host.inc (original) > +++ llvm/trunk/lib/Support/Unix/Host.inc Tue Aug 9 00:13:36 2011 > @@ -22,12 +22,18 @@ > #include > #include > #include > +#include // ::getenv > > using namespace llvm; > > static std::string getOSVersion() { > struct utsname info; > > + // Recognize UNAME_RELEASE environment variable to match Darwin uname. > + const char *UnameOverride = ::getenv("UNAME_RELEASE"); > + if (UnameOverride && UnameOverride[0] != '\0') > + return UnameOverride; > + > if (uname(&info)) > return ""; > > > > _______________________________________________ > llvm-commits mailing list > llvm-commits at cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits From bob.wilson at apple.com Tue Aug 9 14:35:29 2011 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 09 Aug 2011 12:35:29 -0700 Subject: [llvm-commits] [llvm] r137111 - /llvm/trunk/lib/Support/Unix/Host.inc In-Reply-To: <0624A676-9485-4208-8EAC-F836B4795A39@apple.com> References: <20110809051336.C09ED2A6C12C@llvm.org> <0624A676-9485-4208-8EAC-F836B4795A39@apple.com> Message-ID: <6FB8361D-F840-41E4-A578-73319167473A@apple.com> On Aug 9, 2011, at 12:02 PM, Chris Lattner wrote: > > On Aug 8, 2011, at 10:13 PM, Bob Wilson wrote: > >> Author: bwilson >> Date: Tue Aug 9 00:13:36 2011 >> New Revision: 137111 >> >> URL: http://llvm.org/viewvc/llvm-project?rev=137111&view=rev >> Log: >> Recognize the UNAME_RELEASE environment variable to match Darwin's uname. >> When this variable is set, "uname -r" will return its value instead of the >> real OS version. Make this affect LLVM's triple for consistency. >> > > Hi Bob, > > Should this be #ifdef __APPLE__ or something? > > -Chris I thought about that but decided that since no one else is likely to set UNAME_RELEASE that it wasn't necessary. I'll take your question as a hint that you would prefer it with the #ifdef. > >> >> Modified: >> llvm/trunk/lib/Support/Unix/Host.inc >> >> Modified: llvm/trunk/lib/Support/Unix/Host.inc >> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Host.inc?rev=137111&r1=137110&r2=137111&view=diff >> ============================================================================== >> --- llvm/trunk/lib/Support/Unix/Host.inc (original) >> +++ llvm/trunk/lib/Support/Unix/Host.inc Tue Aug 9 00:13:36 2011 >> @@ -22,12 +22,18 @@ >> #include >> #include >> #include >> +#include // ::getenv >> >> using namespace llvm; >> >> static std::string getOSVersion() { >> struct utsname info; >> >> + // Recognize UNAME_RELEASE environment variable to match Darwin uname. >> + const char *UnameOverride = ::getenv("UNAME_RELEASE"); >> + if (UnameOverride && UnameOverride[0] != '\0') >> + return UnameOverride; >> + >> if (uname(&info)) >> return ""; >> >> >> >> _______________________________________________ >> llvm-commits mailing list >> llvm-commits at cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits > From echristo at apple.com Tue Aug 9 14:52:43 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 09 Aug 2011 12:52:43 -0700 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: <4E4032A3.4050608@gmail.com> References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> <4E4000A6.1070908@gmail.com> <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> <4E401109.1050203@gmail.com> <4E401D24.4060605@gmail.com> <4E4032A3.4050608@gmail.com> Message-ID: On Aug 8, 2011, at 12:01 PM, Rafael ?vila de Esp?ndola wrote: >> Sorry about the delay in responding, I've just returned from >> vacation. > > np and welcome back! > >> I have some concerns about this patch as is - basically I'm worried >> about subtle miscompiles based on how gcc does register allocation >> for multiple reg wide values versus how llvm does it. In the gcc case >> it will (as far as I know) assign consecutive registers for these >> sorts of values, but there's no guarantee that llvm will do this. > > I think that is correct. When printing 'H' for example, gcc uses "REGNO (x) + 1". I could not find any other reference to those constraints, so it looks like gcc uses sequential registers unconditionally. > Yep. >> This means that in the case of stm/ldm instructions with the 'Q' and >> 'R' modifiers that we'd get registers that weren't meant, leading to >> subtle problems that users would need to debug. When we get support >> for assigning values into consecutive registers this won't be a >> problem. >> >> What are your thoughts? > > This is the first time I have seen these constraints, so I don't know how common they are and of those uses which ones assume sequential registers. > Btw, these are modifiers not constraints just to be careful about it. > I have attached the testcase where we have found this problem. In this particular case, we don't depend on the registers being sequential (but llvm does it anyway because it is an argument). > I see that. This is a good example of how you're supposed to be doing this. > How hard would it be to add the constraint that the registers have to be sequential? If doing it I would probably try it by creating a new pseudo reg class that alias the regular R registers and use those as operands to the inline asm. Is that what you had in mind? > Pretty much exactly. > So, I guess this is a judgment call. The current patch allows us to handle some inline asm but causes us to miscompile others that we currently reject. I'm going to say we should add them for now. People that are using it incorrectly may get a hard to debug problem, but the use case you guys have totally makes sense and isn't necessarily easy to rewrite to make more sense. Though, seriously, what's wrong with a .s file for that function? -eric From bob.wilson at apple.com Tue Aug 9 14:54:33 2011 From: bob.wilson at apple.com (Bob Wilson) Date: Tue, 09 Aug 2011 19:54:33 -0000 Subject: [llvm-commits] [llvm] r137137 - /llvm/trunk/lib/Support/Unix/Host.inc Message-ID: <20110809195433.22E0C2A6C12E@llvm.org> Author: bwilson Date: Tue Aug 9 14:54:32 2011 New Revision: 137137 URL: http://llvm.org/viewvc/llvm-project?rev=137137&view=rev Log: Put Darwin-specific code inside an __APPLE__ ifdef. Modified: llvm/trunk/lib/Support/Unix/Host.inc Modified: llvm/trunk/lib/Support/Unix/Host.inc URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Host.inc?rev=137137&r1=137136&r2=137137&view=diff ============================================================================== --- llvm/trunk/lib/Support/Unix/Host.inc (original) +++ llvm/trunk/lib/Support/Unix/Host.inc Tue Aug 9 14:54:32 2011 @@ -29,10 +29,12 @@ static std::string getOSVersion() { struct utsname info; +#ifdef __APPLE__ // Recognize UNAME_RELEASE environment variable to match Darwin uname. const char *UnameOverride = ::getenv("UNAME_RELEASE"); if (UnameOverride && UnameOverride[0] != '\0') return UnameOverride; +#endif // __APPLE__ if (uname(&info)) return ""; From stoklund at 2pi.dk Tue Aug 9 15:19:53 2011 From: stoklund at 2pi.dk (Jakob Stoklund Olesen) Date: Tue, 09 Aug 2011 13:19:53 -0700 Subject: [llvm-commits] [patch][arm] Implement support for the Q, R and H modifiers In-Reply-To: References: <4E3AFA25.6040300@gmail.com> <27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com> <1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk> <4E4000A6.1070908@gmail.com> <23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk> <4E401109.1050203@gmail.com> <4E401D24.4060605@gmail.com> <4E4032A3.4050608@gmail.com> Message-ID: <4461C812-305F-4631-AE78-10FFE4B0868B@2pi.dk> On Aug 9, 2011, at 12:52 PM, Eric Christopher wrote: >> How hard would it be to add the constraint that the registers have to be sequential? If doing it I would probably try it by creating a new pseudo reg class that alias the regular R registers and use those as operands to the inline asm. Is that what you had in mind? >> > > Pretty much exactly. The hard part is convincing isel to do this since i64 is not a legal type. You can play tricks with a REG_SEQUENCE node feeding an MVT::untyped edge to the INLINEASM. >> So, I guess this is a judgment call. The current patch allows us to handle some inline asm but causes us to miscompile others that we currently reject. > > I'm going to say we should add them for now. People that are using it incorrectly may get a hard to debug problem, but the use case you guys have totally makes sense and isn't necessarily easy to rewrite to make more sense. Agreed. Actually, there is a good chance they will get assembler errors instead of miscompiles. /jakob From echristo at apple.com Tue Aug 9 15:45:48 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 09 Aug 2011 13:45:48 -0700 Subject: [llvm-commits] [patch] Add a C interface to PassManagerBuilder In-Reply-To: <4E39975B.8080103@gmail.com> References: <4E39975B.8080103@gmail.com> Message-ID: On Aug 3, 2011, at 11:45 AM, Rafael ?vila de Esp?ndola wrote: > The attached patch adds a C interface to PassManagerBuilder. It is missing the addExtension functionality since in the C api > a pass is created and added to a pass manager in a single call. > > Is it OK? Cool with me. -eric From resistor at mac.com Tue Aug 9 15:55:18 2011 From: resistor at mac.com (Owen Anderson) Date: Tue, 09 Aug 2011 20:55:18 -0000 Subject: [llvm-commits] [llvm] r137144 - in /llvm/trunk: lib/Target/ARM/ lib/Target/ARM/Disassembler/ test/MC/Disassembler/ARM/ utils/TableGen/ Message-ID: <20110809205519.AA7252A6C12E@llvm.org> Author: resistor Date: Tue Aug 9 15:55:18 2011 New Revision: 137144 URL: http://llvm.org/viewvc/llvm-project?rev=137144&view=rev Log: Replace the existing ARM disassembler with a new one based on the FixedLenDecoderEmitter. This new disassembler can correctly decode all the testcases that the old one did, though some "expected failure" testcases are XFAIL'd for now because it is not (yet) as strict in operand checking as the old one was. Removed: 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/lib/Target/ARM/ARMInstrFormats.td llvm/trunk/lib/Target/ARM/ARMInstrInfo.td llvm/trunk/lib/Target/ARM/ARMInstrNEON.td llvm/trunk/lib/Target/ARM/ARMInstrThumb.td llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt llvm/trunk/lib/Target/ARM/Makefile llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-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-LSL-regform.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Tue Aug 9 15:55:18 2011 @@ -152,6 +152,7 @@ (ops (i32 14), (i32 zero_reg))> { let PrintMethod = "printPredicateOperand"; let ParserMatchClass = CondCodeOperand; + let DecoderMethod = "DecodePredicateOperand"; } // Conditional code result for instructions whose 's' bit is set, e.g. subs. @@ -160,6 +161,7 @@ let EncoderMethod = "getCCOutOpValue"; let PrintMethod = "printSBitModifierOperand"; let ParserMatchClass = CCOutOperand; + let DecoderMethod = "DecodeCCOutOperand"; } // Same as cc_out except it defaults to setting CPSR. @@ -167,6 +169,7 @@ let EncoderMethod = "getCCOutOpValue"; let PrintMethod = "printSBitModifierOperand"; let ParserMatchClass = CCOutOperand; + let DecoderMethod = "DecodeCCOutOperand"; } // ARM special operands for disassembly only. @@ -199,15 +202,19 @@ // 64 64 - is encoded in imm6<5:0> def shr_imm8 : Operand { let EncoderMethod = "getShiftRight8Imm"; + let DecoderMethod = "DecodeShiftRight8Imm"; } def shr_imm16 : Operand { let EncoderMethod = "getShiftRight16Imm"; + let DecoderMethod = "DecodeShiftRight16Imm"; } def shr_imm32 : Operand { let EncoderMethod = "getShiftRight32Imm"; + let DecoderMethod = "DecodeShiftRight32Imm"; } def shr_imm64 : Operand { let EncoderMethod = "getShiftRight64Imm"; + let DecoderMethod = "DecodeShiftRight64Imm"; } //===----------------------------------------------------------------------===// @@ -579,6 +586,8 @@ let Inst{11-8} = addr{7-4}; // imm7_4/zero let Inst{7-4} = op; let Inst{3-0} = addr{3-0}; // imm3_0/Rm + + let DecoderMethod = "DecodeAddrMode3Instruction"; } class AI3ldstidx op, bit op20, bit isLd, bit isPre, dag oops, dag iops, @@ -1265,6 +1274,7 @@ let AsmString = !strconcat(opc, "${p}", asm); let Pattern = pattern; let PostEncoderMethod = "VFPThumb2PostEncoder"; + let DecoderNamespace = "VFP"; list Predicates = [HasVFP2]; } @@ -1280,6 +1290,7 @@ let AsmString = asm; let Pattern = pattern; let PostEncoderMethod = "VFPThumb2PostEncoder"; + let DecoderNamespace = "VFP"; list Predicates = [HasVFP2]; } @@ -1597,6 +1608,7 @@ let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm); let Pattern = pattern; list Predicates = [HasNEON]; + let DecoderNamespace = "NEON"; } // Same as NeonI except it does not have a "data type" specifier. @@ -1609,6 +1621,7 @@ let AsmString = !strconcat(opc, "${p}", "\t", asm); let Pattern = pattern; list Predicates = [HasNEON]; + let DecoderNamespace = "NEON"; } class NLdSt op21_20, bits<4> op11_8, bits<4> op7_4, @@ -1700,6 +1713,7 @@ let Inst{24} = SIMM{7}; let Inst{18-16} = SIMM{6-4}; let Inst{3-0} = SIMM{3-0}; + let DecoderMethod = "DecodeNEONModImmInstruction"; } // NEON 2 vector register format. Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug 9 15:55:18 2011 @@ -315,6 +315,7 @@ def brtarget : Operand { let EncoderMethod = "getBranchTargetOpValue"; let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeT2BROperand"; } // FIXME: get rid of this one? @@ -343,6 +344,7 @@ // Encoded the same as branch targets. let EncoderMethod = "getARMBranchTargetOpValue"; let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBLTargetOperand"; } @@ -352,6 +354,7 @@ let EncoderMethod = "getRegisterListOpValue"; let ParserMatchClass = RegListAsmOperand; let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeRegListOperand"; } def DPRRegListAsmOperand : AsmOperandClass { let Name = "DPRRegList"; } @@ -359,6 +362,7 @@ let EncoderMethod = "getRegisterListOpValue"; let ParserMatchClass = DPRRegListAsmOperand; let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeDPRRegListOperand"; } def SPRRegListAsmOperand : AsmOperandClass { let Name = "SPRRegList"; } @@ -366,6 +370,7 @@ let EncoderMethod = "getRegisterListOpValue"; let ParserMatchClass = SPRRegListAsmOperand; let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeSPRRegListOperand"; } // An operand for the CONSTPOOL_ENTRY pseudo-instruction. @@ -385,6 +390,7 @@ def neon_vcvt_imm32 : Operand { let EncoderMethod = "getNEONVcvtImm32OpValue"; + let DecoderMethod = "DecodeVCVTImmOperand"; } // rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24. @@ -431,6 +437,7 @@ [shl, srl, sra, rotr]> { let EncoderMethod = "getSORegRegOpValue"; let PrintMethod = "printSORegRegOperand"; + let DecoderMethod = "DecodeSORegRegOperand"; let ParserMatchClass = ShiftedRegAsmOperand; let MIOperandInfo = (ops GPR, GPR, i32imm); } @@ -441,6 +448,7 @@ [shl, srl, sra, rotr]> { let EncoderMethod = "getSORegImmOpValue"; let PrintMethod = "printSORegImmOperand"; + let DecoderMethod = "DecodeSORegImmOperand"; let ParserMatchClass = ShiftedImmAsmOperand; let MIOperandInfo = (ops GPR, i32imm); } @@ -451,6 +459,7 @@ [shl,srl,sra,rotr]> { let EncoderMethod = "getSORegRegOpValue"; let PrintMethod = "printSORegRegOperand"; + let DecoderMethod = "DecodeSORegRegOperand"; let MIOperandInfo = (ops GPR, GPR, i32imm); } @@ -460,6 +469,7 @@ [shl,srl,sra,rotr]> { let EncoderMethod = "getSORegImmOpValue"; let PrintMethod = "printSORegImmOperand"; + let DecoderMethod = "DecodeSORegImmOperand"; let MIOperandInfo = (ops GPR, i32imm); } @@ -472,6 +482,7 @@ }]> { let EncoderMethod = "getSOImmOpValue"; let ParserMatchClass = SOImmAsmOperand; + let DecoderMethod = "DecodeSOImmOperand"; } // Break so_imm's up into two pieces. This handles immediates with up to 16 @@ -552,6 +563,7 @@ }] > { let EncoderMethod = "getBitfieldInvertedMaskOpValue"; let PrintMethod = "printBitfieldInvMaskImmOperand"; + let DecoderMethod = "DecodeBitfieldMaskOperand"; let ParserMatchClass = BitfieldAsmOperand; } @@ -599,6 +611,7 @@ let EncoderMethod = "getAddrModeImm12OpValue"; let PrintMethod = "printAddrModeImm12Operand"; + let DecoderMethod = "DecodeAddrModeImm12Operand"; let ParserMatchClass = MemImm12OffsetAsmOperand; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } @@ -610,6 +623,7 @@ let EncoderMethod = "getLdStSORegOpValue"; // FIXME: Simplify the printer let PrintMethod = "printAddrMode2Operand"; + let DecoderMethod = "DecodeSORegMemOperand"; let ParserMatchClass = MemRegOffsetAsmOperand; let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$shift); } @@ -645,6 +659,7 @@ } def postidx_reg : Operand { let EncoderMethod = "getPostIdxRegOpValue"; + let DecoderMethod = "DecodePostIdxReg"; let PrintMethod = "printPostIdxRegOperand"; let ParserMatchClass = PostIdxRegAsmOperand; let MIOperandInfo = (ops GPR, i32imm); @@ -707,6 +722,7 @@ ComplexPattern { let EncoderMethod = "getAddrMode3OffsetOpValue"; + let DecoderMethod = "DecodeAddrMode3Offset"; let PrintMethod = "printAddrMode3OffsetOperand"; let MIOperandInfo = (ops GPR, i32imm); } @@ -725,6 +741,7 @@ ComplexPattern { let PrintMethod = "printAddrMode5Operand"; let EncoderMethod = "getAddrMode5OpValue"; + let DecoderMethod = "DecodeAddrMode5Operand"; let ParserMatchClass = AddrMode5AsmOperand; let MIOperandInfo = (ops GPR:$base, i32imm); } @@ -736,6 +753,7 @@ let PrintMethod = "printAddrMode6Operand"; let MIOperandInfo = (ops GPR:$addr, i32imm); let EncoderMethod = "getAddrMode6AddressOpValue"; + let DecoderMethod = "DecodeAddrMode6Operand"; } def am6offset : Operand, @@ -744,6 +762,7 @@ let PrintMethod = "printAddrMode6OffsetOperand"; let MIOperandInfo = (ops GPR); let EncoderMethod = "getAddrMode6OffsetOpValue"; + let DecoderMethod = "DecodeGPRRegisterClass"; } // Special version of addrmode6 to handle alignment encoding for VST1/VLD1 @@ -778,6 +797,7 @@ def addr_offset_none : Operand, ComplexPattern { let PrintMethod = "printAddrMode7Operand"; + let DecoderMethod = "DecodeAddrMode7Operand"; let ParserMatchClass = MemNoOffsetAsmOperand; let MIOperandInfo = (ops GPR:$base); } @@ -793,6 +813,7 @@ def p_imm : Operand { let PrintMethod = "printPImmediate"; let ParserMatchClass = CoprocNumAsmOperand; + let DecoderMethod = "DecodeCoprocessor"; } def CoprocRegAsmOperand : AsmOperandClass { @@ -1654,6 +1675,7 @@ [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> { bits<24> target; let Inst{23-0} = target; + let DecoderMethod = "DecodeBranchImmInstruction"; } let isBarrier = 1 in { @@ -1917,6 +1939,7 @@ let Inst{23} = addr{12}; let Inst{19-16} = addr{17-14}; let Inst{11-0} = addr{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2"; } @@ -1933,6 +1956,8 @@ let Inst{23} = offset{12}; let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; + + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb), @@ -1948,7 +1973,10 @@ let Inst{23} = offset{12}; let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; + + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } + } let mayLoad = 1, neverHasSideEffects = 1 in { @@ -2019,20 +2047,39 @@ // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only. let mayLoad = 1, neverHasSideEffects = 1 in { -def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb), - (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru, +def LDRTr : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb), + (ins ldst_so_reg:$addr), IndexModePost, LdFrm, IIC_iLoad_ru, + "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { + // {17-14} Rn + // {13} 1 == Rm, 0 == imm12 + // {12} isAdd + // {11-0} imm12/Rm + bits<18> addr; + let Inst{25} = 1; + let Inst{23} = addr{12}; + let Inst{21} = 1; // overwrite + let Inst{19-16} = addr{17-14}; + let Inst{11-5} = addr{11-5}; + let Inst{4} = 0; + let Inst{3-0} = addr{3-0}; + let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2"; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; +} +def LDRTi : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb), + (ins addrmode_imm12:$addr), IndexModePost, LdFrm, IIC_iLoad_ru, "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> { // {17-14} Rn // {13} 1 == Rm, 0 == imm12 // {12} isAdd // {11-0} imm12/Rm bits<18> addr; - let Inst{25} = addr{13}; + let Inst{25} = 0; let Inst{23} = addr{12}; let Inst{21} = 1; // overwrite let Inst{19-16} = addr{17-14}; let Inst{11-0} = addr{11-0}; let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2"; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } def LDRBT_POST_REG : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb), @@ -2049,6 +2096,7 @@ let Inst{21} = 1; // overwrite let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } def LDRBT_POST_IMM : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb), @@ -2065,6 +2113,7 @@ let Inst{21} = 1; // overwrite let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } multiclass AI3ldrT op, string opc> { @@ -2151,6 +2200,8 @@ let Inst{23} = offset{12}; let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; + + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } def _POST_IMM : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb), @@ -2166,6 +2217,8 @@ let Inst{23} = offset{12}; let Inst{19-16} = addr; let Inst{11-0} = offset{11-0}; + + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } } @@ -2287,6 +2340,7 @@ let Inst{21} = 1; // overwrite let Inst{4} = 0; let AsmMatchConverter = "cvtStWriteBackRegAddrMode2"; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } def STRTi : AI2stridxT<0, 0, (outs GPR:$Rn_wb), @@ -2297,6 +2351,7 @@ let Inst{25} = 0; let Inst{21} = 1; // overwrite let AsmMatchConverter = "cvtStWriteBackRegAddrMode2"; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } @@ -2309,6 +2364,7 @@ let Inst{21} = 1; // overwrite let Inst{4} = 0; let AsmMatchConverter = "cvtStWriteBackRegAddrMode2"; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } def STRBTi : AI2stridxT<1, 0, (outs GPR:$Rn_wb), @@ -2319,6 +2375,7 @@ let Inst{25} = 0; let Inst{21} = 1; // overwrite let AsmMatchConverter = "cvtStWriteBackRegAddrMode2"; + let DecoderMethod = "DecodeAddrMode2IdxInstruction"; } multiclass AI3strT op, string opc> { @@ -2373,6 +2430,8 @@ let Inst{24-23} = 0b01; // Increment After let Inst{21} = 1; // Writeback let Inst{20} = L_bit; + + let DecoderMethod = "DecodeMemMultipleWritebackInstruction"; } def DA : AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), @@ -2389,6 +2448,8 @@ let Inst{24-23} = 0b00; // Decrement After let Inst{21} = 1; // Writeback let Inst{20} = L_bit; + + let DecoderMethod = "DecodeMemMultipleWritebackInstruction"; } def DB : AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), @@ -2405,6 +2466,8 @@ let Inst{24-23} = 0b10; // Decrement Before let Inst{21} = 1; // Writeback let Inst{20} = L_bit; + + let DecoderMethod = "DecodeMemMultipleWritebackInstruction"; } def IB : AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), @@ -2421,6 +2484,8 @@ let Inst{24-23} = 0b11; // Increment Before let Inst{21} = 1; // Writeback let Inst{20} = L_bit; + + let DecoderMethod = "DecodeMemMultipleWritebackInstruction"; } } @@ -2504,8 +2569,6 @@ let Inst{25} = 0; } - - let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi, "mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP { @@ -3383,6 +3446,7 @@ multiclass AI_smla { + let DecoderMethod = "DecodeSMLAInstruction" in { def BB : AMulxyIa<0b0001000, 0b00, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra", @@ -3425,6 +3489,7 @@ [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn, (sra GPR:$Rm, (i32 16))), (i32 16))))]>, Requires<[IsARM, HasV5TE]>; + } } defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>; @@ -3989,7 +4054,7 @@ } multiclass LdStCop op31_28, bit load, dag ops, string opc, string cond>{ - + let DecoderNamespace = "Common" in { def _OFFSET : ACI<(outs), !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops), !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr"> { @@ -3998,6 +4063,7 @@ let Inst{21} = 0; // W = 0 let Inst{22} = 0; // D = 0 let Inst{20} = load; + let DecoderMethod = "DecodeCopMemInstruction"; } def _PRE : ACI<(outs), @@ -4008,6 +4074,7 @@ let Inst{21} = 1; // W = 1 let Inst{22} = 0; // D = 0 let Inst{20} = load; + let DecoderMethod = "DecodeCopMemInstruction"; } def _POST : ACI<(outs), @@ -4018,6 +4085,7 @@ let Inst{21} = 1; // W = 1 let Inst{22} = 0; // D = 0 let Inst{20} = load; + let DecoderMethod = "DecodeCopMemInstruction"; } def _OPTION : ACI<(outs), @@ -4030,6 +4098,7 @@ let Inst{21} = 0; // W = 0 let Inst{22} = 0; // D = 0 let Inst{20} = load; + let DecoderMethod = "DecodeCopMemInstruction"; } def L_OFFSET : ACI<(outs), @@ -4040,6 +4109,7 @@ let Inst{21} = 0; // W = 0 let Inst{22} = 1; // D = 1 let Inst{20} = load; + let DecoderMethod = "DecodeCopMemInstruction"; } def L_PRE : ACI<(outs), @@ -4051,6 +4121,7 @@ let Inst{21} = 1; // W = 1 let Inst{22} = 1; // D = 1 let Inst{20} = load; + let DecoderMethod = "DecodeCopMemInstruction"; } def L_POST : ACI<(outs), @@ -4063,6 +4134,7 @@ let Inst{21} = 1; // W = 1 let Inst{22} = 1; // D = 1 let Inst{20} = load; + let DecoderMethod = "DecodeCopMemInstruction"; } def L_OPTION : ACI<(outs), @@ -4076,6 +4148,8 @@ let Inst{21} = 0; // W = 0 let Inst{22} = 1; // D = 1 let Inst{20} = load; + let DecoderMethod = "DecodeCopMemInstruction"; + } } } Modified: llvm/trunk/lib/Target/ARM/ARMInstrNEON.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrNEON.td?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrNEON.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrNEON.td Tue Aug 9 15:55:18 2011 @@ -191,6 +191,7 @@ "vld1", Dt, "\\{$Vd\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD1Q op7_4, string Dt> : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2), @@ -198,6 +199,7 @@ "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD1d8 : VLD1D<{0,0,0,?}, "8">; @@ -222,6 +224,7 @@ "vld1", Dt, "\\{$Vd\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD1QWB op7_4, string Dt> : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), @@ -229,6 +232,7 @@ "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD1d8_UPD : VLD1DWB<{0,0,0,?}, "8">; @@ -253,12 +257,14 @@ "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD1D3WB op7_4, string Dt> : NLdSt<0,0b10,0b0110,op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb), (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x3u, "vld1", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD1d8T : VLD1D3<{0,0,0,?}, "8">; @@ -281,6 +287,7 @@ "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD1D4WB op7_4, string Dt> : NLdSt<0,0b10,0b0010,op7_4, @@ -289,6 +296,7 @@ "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD1d8Q : VLD1D4<{0,0,?,?}, "8">; @@ -311,6 +319,7 @@ "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD2Q op7_4, string Dt> : NLdSt<0, 0b10, 0b0011, op7_4, @@ -319,6 +328,7 @@ "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD2d8 : VLD2D<0b1000, {0,0,?,?}, "8">; @@ -344,6 +354,7 @@ "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } class VLD2QWB op7_4, string Dt> : NLdSt<0, 0b10, 0b0011, op7_4, @@ -352,6 +363,7 @@ "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD2d8_UPD : VLD2DWB<0b1000, {0,0,?,?}, "8">; @@ -385,6 +397,7 @@ "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD3d8 : VLD3D<0b0100, {0,0,0,?}, "8">; @@ -403,6 +416,7 @@ "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD3d8_UPD : VLD3DWB<0b0100, {0,0,0,?}, "8">; @@ -442,6 +456,7 @@ "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD4d8 : VLD4D<0b0000, {0,0,?,?}, "8">; @@ -460,6 +475,7 @@ "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; } def VLD4d8_UPD : VLD4DWB<0b0000, {0,0,?,?}, "8">; @@ -826,6 +842,7 @@ [(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD1DupInstruction"; } class VLD1QDUPPseudo : VLDQPseudo { let Pattern = [(set QPR:$dst, @@ -853,6 +870,7 @@ "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD1DupInstruction"; } def VLD1DUPq8 : VLD1QDUP<{0,0,1,0}, "8">; @@ -865,12 +883,14 @@ (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu, "vld1", Dt, "\\{$Vd[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD1DupInstruction"; } class VLD1QDUPWB op7_4, string Dt> : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb), (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu, "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD1DupInstruction"; } def VLD1DUPd8_UPD : VLD1DUPWB<{0,0,0,0}, "8">; @@ -892,6 +912,7 @@ "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD2DupInstruction"; } def VLD2DUPd8 : VLD2DUP<{0,0,0,?}, "8">; @@ -913,6 +934,7 @@ (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD2dupu, "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD2DupInstruction"; } def VLD2DUPd8_UPD : VLD2DUPWB<{0,0,0,0}, "8">; @@ -934,6 +956,7 @@ "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD3DupInstruction"; } def VLD3DUPd8 : VLD3DUP<{0,0,0,?}, "8">; @@ -956,6 +979,7 @@ "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD3DupInstruction"; } def VLD3DUPd8_UPD : VLD3DUPWB<{0,0,0,0}, "8">; @@ -978,6 +1002,7 @@ "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD4DupInstruction"; } def VLD4DUPd8 : VLD4DUP<{0,0,0,?}, "8">; @@ -1001,6 +1026,7 @@ "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLD4DupInstruction"; } def VLD4DUPd8_UPD : VLD4DUPWB<{0,0,0,0}, "8">; @@ -1046,6 +1072,7 @@ IIC_VST1, "vst1", Dt, "\\{$Vd\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST1Q op7_4, string Dt> : NLdSt<0,0b00,0b1010,op7_4, (outs), @@ -1053,6 +1080,7 @@ "vst1", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST1d8 : VST1D<{0,0,0,?}, "8">; @@ -1076,6 +1104,7 @@ (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd), IIC_VST1u, "vst1", Dt, "\\{$Vd\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST1QWB op7_4, string Dt> : NLdSt<0, 0b00, 0b1010, op7_4, (outs GPR:$wb), @@ -1083,6 +1112,7 @@ IIC_VST1x2u, "vst1", Dt, "\\{$Vd, $src2\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST1d8_UPD : VST1DWB<{0,0,0,?}, "8">; @@ -1107,6 +1137,7 @@ IIC_VST1x3, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST1D3WB op7_4, string Dt> : NLdSt<0, 0b00, 0b0110, op7_4, (outs GPR:$wb), @@ -1115,6 +1146,7 @@ IIC_VST1x3u, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST1d8T : VST1D3<{0,0,0,?}, "8">; @@ -1138,6 +1170,7 @@ []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST1D4WB op7_4, string Dt> : NLdSt<0, 0b00, 0b0010, op7_4, (outs GPR:$wb), @@ -1146,6 +1179,7 @@ "vst1", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST1d8Q : VST1D4<{0,0,?,?}, "8">; @@ -1168,6 +1202,7 @@ IIC_VST2, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST2Q op7_4, string Dt> : NLdSt<0, 0b00, 0b0011, op7_4, (outs), @@ -1176,6 +1211,7 @@ "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST2d8 : VST2D<0b1000, {0,0,?,?}, "8">; @@ -1201,6 +1237,7 @@ IIC_VST2u, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } class VST2QWB op7_4, string Dt> : NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb), @@ -1209,6 +1246,7 @@ "vst2", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST2d8_UPD : VST2DWB<0b1000, {0,0,?,?}, "8">; @@ -1242,6 +1280,7 @@ "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> { let Rm = 0b1111; let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST3d8 : VST3D<0b0100, {0,0,0,?}, "8">; @@ -1260,6 +1299,7 @@ "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST3d8_UPD : VST3DWB<0b0100, {0,0,0,?}, "8">; @@ -1299,6 +1339,7 @@ "", []> { let Rm = 0b1111; let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST4d8 : VST4D<0b0000, {0,0,?,?}, "8">; @@ -1317,6 +1358,7 @@ "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm", "$Rn.addr = $wb", []> { let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVSTInstruction"; } def VST4d8_UPD : VST4DWB<0b0000, {0,0,?,?}, "8">; @@ -4040,6 +4082,7 @@ : N2VLSh { let Inst{21-16} = op21_16; + let DecoderMethod = "DecodeVSHLMaxInstruction"; } def VSHLLi8 : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8", v8i16, v8i8, NEONvshlli>; @@ -4754,6 +4797,7 @@ // Vector Table Lookup and Table Extension. // VTBL : Vector Table Lookup +let DecoderMethod = "DecodeTBLInstruction" in { def VTBL1 : N3V<1,1,0b11,0b1000,0,0, (outs DPR:$Vd), (ins DPR:$Vn, DPR:$Vm), NVTBLFrm, IIC_VTB1, @@ -4816,6 +4860,7 @@ def VTBX4Pseudo : PseudoNeonI<(outs DPR:$dst), (ins DPR:$orig, QQPR:$tbl, DPR:$src), IIC_VTBX4, "$orig = $dst", []>; +} // DecoderMethod = "DecodeTBLInstruction" //===----------------------------------------------------------------------===// // NEON instructions for single-precision FP math Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Tue Aug 9 15:55:18 2011 @@ -82,14 +82,17 @@ let OperandType = "OPERAND_PCREL" in { def t_brtarget : Operand { let EncoderMethod = "getThumbBRTargetOpValue"; + let DecoderMethod = "DecodeThumbBROperand"; } def t_bcctarget : Operand { let EncoderMethod = "getThumbBCCTargetOpValue"; + let DecoderMethod = "DecodeThumbBCCTargetOperand"; } def t_cbtarget : Operand { let EncoderMethod = "getThumbCBTargetOpValue"; + let DecoderMethod = "DecodeThumbCmpBROperand"; } def t_bltarget : Operand { @@ -119,12 +122,14 @@ ComplexPattern { let EncoderMethod = "getThumbAddrModeRegRegOpValue"; let PrintMethod = "printThumbAddrModeRROperand"; + let DecoderMethod = "DecodeThumbAddrModeRR"; let ParserMatchClass = t_addrmode_rr_asm_operand; let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); } def t_addrmode_rrs2 : Operand, ComplexPattern { let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let DecoderMethod = "DecodeThumbAddrModeRR"; let PrintMethod = "printThumbAddrModeRROperand"; let ParserMatchClass = t_addrmode_rr_asm_operand; let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); @@ -132,6 +137,7 @@ def t_addrmode_rrs4 : Operand, ComplexPattern { let EncoderMethod = "getThumbAddrModeRegRegOpValue"; + let DecoderMethod = "DecodeThumbAddrModeRR"; let PrintMethod = "printThumbAddrModeRROperand"; let ParserMatchClass = t_addrmode_rr_asm_operand; let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg); @@ -142,6 +148,7 @@ def t_addrmode_is4 : Operand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; + let DecoderMethod = "DecodeThumbAddrModeIS"; let PrintMethod = "printThumbAddrModeImm5S4Operand"; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); } @@ -151,6 +158,7 @@ def t_addrmode_is2 : Operand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; + let DecoderMethod = "DecodeThumbAddrModeIS"; let PrintMethod = "printThumbAddrModeImm5S2Operand"; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); } @@ -160,6 +168,7 @@ def t_addrmode_is1 : Operand, ComplexPattern { let EncoderMethod = "getAddrModeISOpValue"; + let DecoderMethod = "DecodeThumbAddrModeIS"; let PrintMethod = "printThumbAddrModeImm5S1Operand"; let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm); } @@ -178,6 +187,7 @@ // def t_addrmode_pc : Operand { let EncoderMethod = "getAddrModePCOpValue"; + let DecoderMethod = "DecodeThumbAddrModePC"; } //===----------------------------------------------------------------------===// @@ -259,6 +269,7 @@ let Inst{4} = imod; let Inst{3} = 0; let Inst{2-0} = iflags; + let DecoderMethod = "DecodeThumbCPS"; } // For both thumb1 and thumb2. @@ -272,17 +283,6 @@ let Inst{2-0} = dst; } -// PC relative add (ADR). -def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, - "add\t$dst, pc, $rhs", []>, - T1Encoding<{1,0,1,0,0,?}> { - // A6.2 & A8.6.10 - bits<3> dst; - bits<8> rhs; - let Inst{10-8} = dst; - let Inst{7-0} = rhs; -} - // ADD , sp, # // This is rematerializable, which is particularly useful for taking the // address of locals. @@ -295,6 +295,7 @@ bits<8> rhs; let Inst{10-8} = dst; let Inst{7-0} = rhs; + let DecoderMethod = "DecodeThumbAddSpecialReg"; } // ADD sp, sp, # @@ -304,6 +305,7 @@ // A6.2.5 & A8.6.8 bits<7> rhs; let Inst{6-0} = rhs; + let DecoderMethod = "DecodeThumbAddSPImm"; } // SUB sp, sp, # @@ -314,6 +316,7 @@ // A6.2.5 & A8.6.214 bits<7> rhs; let Inst{6-0} = rhs; + let DecoderMethod = "DecodeThumbAddSPImm"; } // ADD , sp @@ -325,6 +328,7 @@ let Inst{7} = dst{3}; let Inst{6-3} = 0b1101; let Inst{2-0} = dst{2-0}; + let DecoderMethod = "DecodeThumbAddSPReg"; } // ADD sp, @@ -336,6 +340,7 @@ let Inst{7} = 1; let Inst{6-3} = dst; let Inst{2-0} = 0b101; + let DecoderMethod = "DecodeThumbAddSPReg"; } //===----------------------------------------------------------------------===// @@ -1189,6 +1194,7 @@ bits<8> addr; let Inst{10-8} = Rd; let Inst{7-0} = addr; + let DecoderMethod = "DecodeThumbAddSpecialReg"; } let neverHasSideEffects = 1, isReMaterializable = 1 in Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Aug 9 15:55:18 2011 @@ -50,6 +50,7 @@ }]> { let ParserMatchClass = t2_so_imm_asmoperand; let EncoderMethod = "getT2SOImmOpValue"; + let DecoderMethod = "DecodeT2SOImm"; } // t2_so_imm_not - Match an immediate that is a complement @@ -100,6 +101,7 @@ ComplexPattern { let PrintMethod = "printAddrModeImm12Operand"; let EncoderMethod = "getAddrModeImm12OpValue"; + let DecoderMethod = "DecodeT2AddrModeImm12"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } @@ -121,6 +123,7 @@ ComplexPattern { let PrintMethod = "printT2AddrModeImm8Operand"; let EncoderMethod = "getT2AddrModeImm8OpValue"; + let DecoderMethod = "DecodeT2AddrModeImm8"; let ParserMatchClass = MemImm8OffsetAsmOperand; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } @@ -130,12 +133,14 @@ [], [SDNPWantRoot]> { let PrintMethod = "printT2AddrModeImm8OffsetOperand"; let EncoderMethod = "getT2AddrModeImm8OffsetOpValue"; + let DecoderMethod = "DecodeT2Imm8"; } // t2addrmode_imm8s4 := reg +/- (imm8 << 2) def t2addrmode_imm8s4 : Operand { let PrintMethod = "printT2AddrModeImm8s4Operand"; let EncoderMethod = "getT2AddrModeImm8s4OpValue"; + let DecoderMethod = "DecodeT2AddrModeImm8s4"; let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm); } @@ -149,6 +154,7 @@ ComplexPattern { let PrintMethod = "printT2AddrModeSoRegOperand"; let EncoderMethod = "getT2AddrModeSORegOpValue"; + let DecoderMethod = "DecodeT2AddrModeSOReg"; let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm); } @@ -158,6 +164,7 @@ // def t2addrmode_reg : Operand { let PrintMethod = "printAddrMode7Operand"; + let DecoderMethod = "DecodeGPRRegisterClass"; let MIOperandInfo = (ops GPR); } @@ -892,6 +899,8 @@ let Inst{19-16} = addr{9-6}; // Rn let Inst{3-0} = addr{5-2}; // Rm let Inst{5-4} = addr{1-0}; // imm + + let DecoderMethod = "DecodeT2LoadShift"; } // FIXME: Is the pci variant actually needed? @@ -1430,6 +1439,8 @@ let Inst{19-16} = addr{9-6}; // Rn let Inst{3-0} = addr{5-2}; // Rm let Inst{5-4} = addr{1-0}; // imm2 + + let DecoderMethod = "DecodeT2LoadShift"; } } @@ -2994,6 +3005,8 @@ let Inst{13} = target{18}; let Inst{21-16} = target{17-12}; let Inst{10-0} = target{11-1}; + + let DecoderMethod = "DecodeThumb2BCCInstruction"; } // Tail calls. The Darwin version of thumb tail calls uses a t2 branch, so 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug 9 15:55:18 2011 @@ -6,584 +6,2328 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file is part of the ARM Disassembler. -// It contains code to implement the public interfaces of ARMDisassembler and -// ThumbDisassembler, both of which are instances of MCDisassembler. -// -//===----------------------------------------------------------------------===// #define DEBUG_TYPE "arm-disassembler" #include "ARMDisassembler.h" -#include "ARMDisassemblerCore.h" - -#include "llvm/ADT/OwningPtr.h" +#include "ARM.h" +#include "ARMRegisterInfo.h" +#include "MCTargetDesc/ARMAddressingModes.h" +#include "MCTargetDesc/ARMBaseInfo.h" #include "llvm/MC/EDInstInfo.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCContext.h" #include "llvm/Target/TargetRegistry.h" #include "llvm/Support/Debug.h" #include "llvm/Support/MemoryObject.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" -//#define DEBUG(X) do { X; } while (0) - -/// ARMGenDecoderTables.inc - ARMDecoderTables.inc is tblgen'ed from -/// ARMDecoderEmitter.cpp TableGen backend. It contains: -/// -/// o Mappings from opcode to ARM/Thumb instruction format -/// -/// o static uint16_t decodeInstruction(uint32_t insn) - the decoding function -/// for an ARM instruction. -/// -/// o static uint16_t decodeThumbInstruction(field_t insn) - the decoding -/// function for a Thumb instruction. -/// -#include "ARMGenDecoderTables.inc" +// Forward declare these because the autogenerated code will reference them. +// Definitions are further down. +static bool DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static bool DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static bool DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static bool DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static bool DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static bool DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static bool DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static bool DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); +static bool DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); + +static bool DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeBLTargetOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); + +static bool DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + +static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst & Inst, + unsigned Insn, + uint64_t Adddress, + const void *Decoder); +static bool DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeBranchImmInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeCoprocessor(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + + +static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn, + uint64_t Address, const void *Decoder); +static bool DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn, + uint64_t Address, const void *Decoder); +static bool DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn, + uint64_t Address, const void *Decoder); +static bool DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); +static bool DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbSRImm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbBCCTargetOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +static bool DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder); +#include "ARMGenDisassemblerTables.inc" +#include "ARMGenInstrInfo.inc" #include "ARMGenEDInfo.inc" using namespace llvm; -/// showBitVector - Use the raw_ostream to log a diagnostic message describing -/// the inidividual bits of the instruction. -/// -static inline void showBitVector(raw_ostream &os, const uint32_t &insn) { - // Split the bit position markers into more than one lines to fit 80 columns. - os << " 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 \n"; - os << "---------------------------------------------------------------" - << "----------------------------------\n"; - os << '|'; - for (unsigned i = 32; i != 0; --i) { - if (insn >> (i - 1) & 0x01) - os << " 1"; - else - os << " 0"; - os << (i%4 == 1 ? '|' : ':'); +static MCDisassembler *createARMDisassembler(const Target &T) { + return new ARMDisassembler; +} + +static MCDisassembler *createThumbDisassembler(const Target &T) { + return new ThumbDisassembler; +} + +EDInstInfo *ARMDisassembler::getEDInfo() const { + return instInfoARM; +} + +EDInstInfo *ThumbDisassembler::getEDInfo() const { + return instInfoARM; +} + + +bool ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size, + const MemoryObject &Region, + uint64_t Address,raw_ostream &os) const { + uint8_t bytes[4]; + + // We want to read exactly 4 bytes of data. + if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1) + return false; + + // Encoded as a small-endian 32-bit word in the stream. + uint32_t insn = (bytes[3] << 24) | + (bytes[2] << 16) | + (bytes[1] << 8) | + (bytes[0] << 0); + + // Calling the auto-generated decoder function. + bool result = decodeARMInstruction32(MI, insn, Address, this); + if (result) { + Size = 4; + return true; } - os << '\n'; - // Split the bit position markers into more than one lines to fit 80 columns. - os << "---------------------------------------------------------------" - << "----------------------------------\n"; - os << '\n'; -} - -/// decodeARMInstruction is a decorator function which tries special cases of -/// instruction matching before calling the auto-generated decoder function. -static unsigned decodeARMInstruction(uint32_t &insn) { - if (slice(insn, 31, 28) == 15) - goto AutoGenedDecoder; - - // Special case processing, if any, goes here.... - - // LLVM combines the offset mode of A8.6.197 & A8.6.198 into STRB. - // The insufficient encoding information of the combined instruction confuses - // the decoder wrt BFC/BFI. Therefore, we try to recover here. - // For BFC, Inst{27-21} = 0b0111110 & Inst{6-0} = 0b0011111. - // For BFI, Inst{27-21} = 0b0111110 & Inst{6-4} = 0b001 & Inst{3-0} =! 0b1111. - if (slice(insn, 27, 21) == 0x3e && slice(insn, 6, 4) == 1) { - if (slice(insn, 3, 0) == 15) - return ARM::BFC; - else - return ARM::BFI; + + // Instructions that are shared between ARM and Thumb modes. + // FIXME: This shouldn't really exist. It's an artifact of the + // fact that we fail to encode a few instructions properly for Thumb. + MI.clear(); + result = decodeCommonInstruction32(MI, insn, Address, this); + if (result) { + Size = 4; + return true; } - // Ditto for STRBT, which is a super-instruction for A8.6.199 Encodings - // A1 & A2. - // As a result, the decoder fails to deocode USAT properly. - if (slice(insn, 27, 21) == 0x37 && slice(insn, 5, 4) == 1) - return ARM::USAT; - // As a result, the decoder fails to deocode UQADD16 properly. - if (slice(insn, 27, 20) == 0x66 && slice(insn, 7, 4) == 1) - return ARM::UQADD16; - - // Ditto for ADDSrs, which is a super-instruction for A8.6.7 & A8.6.8. - // As a result, the decoder fails to decode UMULL properly. - if (slice(insn, 27, 21) == 0x04 && slice(insn, 7, 4) == 9) { - return ARM::UMULL; - } - - // Ditto for STR_PRE, which is a super-instruction for A8.6.194 & A8.6.195. - // As a result, the decoder fails to decode SBFX properly. - if (slice(insn, 27, 21) == 0x3d && slice(insn, 6, 4) == 5) - return ARM::SBFX; - - // And STRB_PRE, which is a super-instruction for A8.6.197 & A8.6.198. - // As a result, the decoder fails to decode UBFX properly. - if (slice(insn, 27, 21) == 0x3f && slice(insn, 6, 4) == 5) - return ARM::UBFX; - - // Ditto for STRT, which is a super-instruction for A8.6.210 Encoding A1 & A2. - // As a result, the decoder fails to deocode SSAT properly. - if (slice(insn, 27, 21) == 0x35 && slice(insn, 5, 4) == 1) - return ARM::SSAT; - - // Ditto for RSCrs, which is a super-instruction for A8.6.146 & A8.6.147. - // As a result, the decoder fails to decode STRHT/LDRHT/LDRSHT/LDRSBT. - if (slice(insn, 27, 24) == 0) { - switch (slice(insn, 21, 20)) { - case 2: - switch (slice(insn, 7, 4)) { - case 11: - return slice(insn, 22, 22) ? ARM::STRHTi : ARM::STRHTr; - default: - break; // fallthrough - } - break; - case 3: - switch (slice(insn, 7, 4)) { - case 11: - return slice(insn, 22, 22) ? ARM::LDRHTi : ARM::LDRHTr; - case 13: - return slice(insn, 22, 22) ? ARM::LDRSBTi : ARM::LDRSBTr; - case 15: - return slice(insn, 22, 22) ? ARM::LDRSHTi : ARM::LDRSHTr; - default: - break; // fallthrough - } - break; - default: - break; // fallthrough - } + // VFP and NEON instructions, similarly, are shared between ARM + // and Thumb modes. + MI.clear(); + result = decodeVFPInstruction32(MI, insn, Address, this); + if (result) { + Size = 4; + return true; } - // Ditto for SBCrs, which is a super-instruction for A8.6.152 & A8.6.153. - // As a result, the decoder fails to decode STRH_Post/LDRD_POST/STRD_POST - // properly. - if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 0) { - unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21); - switch (slice(insn, 7, 4)) { - case 11: - switch (PW) { - case 2: // Offset - return ARM::STRH; - case 3: // Pre-indexed - return ARM::STRH_PRE; - case 0: // Post-indexed - return ARM::STRH_POST; - default: - break; // fallthrough - } - break; - case 13: - switch (PW) { - case 2: // Offset - return ARM::LDRD; - case 3: // Pre-indexed - return ARM::LDRD_PRE; - case 0: // Post-indexed - return ARM::LDRD_POST; - default: - break; // fallthrough - } - break; - case 15: - switch (PW) { - case 2: // Offset - return ARM::STRD; - case 3: // Pre-indexed - return ARM::STRD_PRE; - case 0: // Post-indexed - return ARM::STRD_POST; - default: - break; // fallthrough - } - break; - default: - break; // fallthrough - } + MI.clear(); + result = decodeNEONInstruction32(MI, insn, Address, this); + if (result) { + // Add a fake predicate operand, because we share these instruction + // definitions with Thumb2 where these instructions are predicable. + if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false; + Size = 4; + return true; } - // Ditto for SBCSSrs, which is a super-instruction for A8.6.152 & A8.6.153. - // As a result, the decoder fails to decode LDRH_POST/LDRSB_POST/LDRSH_POST - // properly. - if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 1) { - unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21); - switch (slice(insn, 7, 4)) { - case 11: - switch (PW) { - case 2: // Offset - return ARM::LDRH; - case 3: // Pre-indexed - return ARM::LDRH_PRE; - case 0: // Post-indexed - return ARM::LDRH_POST; - default: - break; // fallthrough - } - break; - case 13: - switch (PW) { - case 2: // Offset - return ARM::LDRSB; - case 3: // Pre-indexed - return ARM::LDRSB_PRE; - case 0: // Post-indexed - return ARM::LDRSB_POST; - default: - break; // fallthrough - } - break; - case 15: - switch (PW) { - case 2: // Offset - return ARM::LDRSH; - case 3: // Pre-indexed - return ARM::LDRSH_PRE; - case 0: // Post-indexed - return ARM::LDRSH_POST; - default: - break; // fallthrough - } - break; - default: - break; // fallthrough + MI.clear(); + + return false; +} + +namespace llvm { +extern MCInstrDesc ARMInsts[]; +} + +// Thumb1 instructions don't have explicit S bits. Rather, they +// implicitly set CPSR. Since it's not represented in the encoding, the +// auto-generated decoder won't inject the CPSR operand. We need to fix +// that as a post-pass. +static void AddThumb1SBit(MCInst &MI, bool InITBlock) { + const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo; + MCInst::iterator I = MI.begin(); + for (unsigned i = 0; i < MI.size(); ++i, ++I) { + if (OpInfo[i].isOptionalDef() && OpInfo[i].RegClass == ARM::CCRRegClassID) { + MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR)); + return; } } -AutoGenedDecoder: - // Calling the auto-generated decoder function. - return decodeInstruction(insn); + if (OpInfo[MI.size()].isOptionalDef() && + OpInfo[MI.size()].RegClass == ARM::CCRRegClassID) + MI.insert(MI.end(), MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR)); } -// Helper function for special case handling of LDR (literal) and friends. -// See, for example, A6.3.7 Load word: Table A6-18 Load word. -// See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode -// before returning it. -static unsigned T2Morph2LoadLiteral(unsigned Opcode) { - switch (Opcode) { - default: - return Opcode; // Return unmorphed opcode. - - case ARM::t2LDR_POST: case ARM::t2LDR_PRE: - case ARM::t2LDRi12: case ARM::t2LDRi8: - case ARM::t2LDRs: case ARM::t2LDRT: - return ARM::t2LDRpci; - - case ARM::t2LDRB_POST: case ARM::t2LDRB_PRE: - case ARM::t2LDRBi12: case ARM::t2LDRBi8: - case ARM::t2LDRBs: case ARM::t2LDRBT: - return ARM::t2LDRBpci; - - case ARM::t2LDRH_POST: case ARM::t2LDRH_PRE: - case ARM::t2LDRHi12: case ARM::t2LDRHi8: - case ARM::t2LDRHs: case ARM::t2LDRHT: - return ARM::t2LDRHpci; - - case ARM::t2LDRSB_POST: case ARM::t2LDRSB_PRE: - case ARM::t2LDRSBi12: case ARM::t2LDRSBi8: - case ARM::t2LDRSBs: case ARM::t2LDRSBT: - return ARM::t2LDRSBpci; - - case ARM::t2LDRSH_POST: case ARM::t2LDRSH_PRE: - case ARM::t2LDRSHi12: case ARM::t2LDRSHi8: - case ARM::t2LDRSHs: case ARM::t2LDRSHT: - return ARM::t2LDRSHpci; - } -} - -// Helper function for special case handling of PLD (literal) and friends. -// See A8.6.117 T1 & T2 and friends for why we morphed the opcode -// before returning it. -static unsigned T2Morph2PLDLiteral(unsigned Opcode) { - switch (Opcode) { - default: - return Opcode; // Return unmorphed opcode. - - case ARM::t2PLDi8: case ARM::t2PLDs: - case ARM::t2PLDWi12: case ARM::t2PLDWi8: - case ARM::t2PLDWs: - return ARM::t2PLDi12; - - case ARM::t2PLIi8: case ARM::t2PLIs: - return ARM::t2PLIi12; - } -} - -/// decodeThumbSideEffect is a decorator function which can potentially twiddle -/// the instruction or morph the returned opcode under Thumb2. -/// -/// First it checks whether the insn is a NEON or VFP instr; if true, bit -/// twiddling could be performed on insn to turn it into an ARM NEON/VFP -/// equivalent instruction and decodeInstruction is called with the transformed -/// insn. -/// -/// Next, there is special handling for Load byte/halfword/word instruction by -/// checking whether Rn=0b1111 and call T2Morph2LoadLiteral() on the decoded -/// Thumb2 instruction. See comments below for further details. -/// -/// Finally, one last check is made to see whether the insn is a NEON/VFP and -/// decodeInstruction(insn) is invoked on the original insn. -/// -/// Otherwise, decodeThumbInstruction is called with the original insn. -static unsigned decodeThumbSideEffect(bool IsThumb2, unsigned &insn) { - if (IsThumb2) { - uint16_t op1 = slice(insn, 28, 27); - uint16_t op2 = slice(insn, 26, 20); - - // A6.3 32-bit Thumb instruction encoding - // Table A6-9 32-bit Thumb instruction encoding - - // The coprocessor instructions of interest are transformed to their ARM - // equivalents. - - // --------- Transform Begin Marker --------- - if ((op1 == 1 || op1 == 3) && slice(op2, 6, 4) == 7) { - // A7.4 Advanced SIMD data-processing instructions - // U bit of Thumb corresponds to Inst{24} of ARM. - uint16_t U = slice(op1, 1, 1); - - // Inst{28-24} of ARM = {1,0,0,1,U}; - uint16_t bits28_24 = 9 << 1 | U; - DEBUG(showBitVector(errs(), insn)); - setSlice(insn, 28, 24, bits28_24); - return decodeInstruction(insn); - } - - if (op1 == 3 && slice(op2, 6, 4) == 1 && slice(op2, 0, 0) == 0) { - // A7.7 Advanced SIMD element or structure load/store instructions - // Inst{27-24} of Thumb = 0b1001 - // Inst{27-24} of ARM = 0b0100 - DEBUG(showBitVector(errs(), insn)); - setSlice(insn, 27, 24, 4); - return decodeInstruction(insn); - } - // --------- Transform End Marker --------- - - unsigned unmorphed = decodeThumbInstruction(insn); - - // See, for example, A6.3.7 Load word: Table A6-18 Load word. - // See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode - // before returning it to our caller. - if (op1 == 3 && slice(op2, 6, 5) == 0 && slice(op2, 0, 0) == 1 - && slice(insn, 19, 16) == 15) { - unsigned morphed = T2Morph2LoadLiteral(unmorphed); - if (morphed != unmorphed) - return morphed; - } - - // See, for example, A8.6.117 PLD,PLDW (immediate) T1 & T2, and friends for - // why we morphed the opcode before returning it to our caller. - if (slice(insn, 31, 25) == 0x7C && slice(insn, 15, 12) == 0xF - && slice(insn, 22, 22) == 0 && slice(insn, 20, 20) == 1 - && slice(insn, 19, 16) == 15) { - unsigned morphed = T2Morph2PLDLiteral(unmorphed); - if (morphed != unmorphed) - return morphed; - } - - // One last check for NEON/VFP instructions. - if ((op1 == 1 || op1 == 3) && slice(op2, 6, 6) == 1) - return decodeInstruction(insn); +// Most Thumb instructions don't have explicit predicates in the +// encoding, but rather get their predicates from IT context. We need +// to fix up the predicate operands using this context information as a +// post-pass. +void ThumbDisassembler::AddThumbPredicate(MCInst &MI) const { + // A few instructions actually have predicates encoded in them. Don't + // try to overwrite it if we're seeing one of those. + switch (MI.getOpcode()) { + case ARM::tBcc: + case ARM::t2Bcc: + return; + default: + break; + } - // Fall through. + // If we're in an IT block, base the predicate on that. Otherwise, + // assume a predicate of AL. + unsigned CC; + if (ITBlock.size()) { + CC = ITBlock.back(); + ITBlock.pop_back(); + } else + CC = ARMCC::AL; + + const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo; + MCInst::iterator I = MI.begin(); + for (unsigned i = 0; i < MI.size(); ++i, ++I) { + if (OpInfo[i].isPredicate()) { + I = MI.insert(I, MCOperand::CreateImm(CC)); + ++I; + if (CC == ARMCC::AL) + MI.insert(I, MCOperand::CreateReg(0)); + else + MI.insert(I, MCOperand::CreateReg(ARM::CPSR)); + return; + } } - return decodeThumbInstruction(insn); + MI.insert(MI.end(), MCOperand::CreateImm(CC)); + if (CC == ARMCC::AL) + MI.insert(MI.end(), MCOperand::CreateReg(0)); + else + MI.insert(MI.end(), MCOperand::CreateReg(ARM::CPSR)); } -// -// Public interface for the disassembler -// +// Thumb VFP instructions are a special case. Because we share their +// encodings between ARM and Thumb modes, and they are predicable in ARM +// mode, the auto-generated decoder will give them an (incorrect) +// predicate operand. We need to rewrite these operands based on the IT +// context as a post-pass. +void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const { + unsigned CC; + if (ITBlock.size()) { + CC = ITBlock.back(); + ITBlock.pop_back(); + } else + CC = ARMCC::AL; + + const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo; + MCInst::iterator I = MI.begin(); + for (unsigned i = 0; i < MI.size(); ++i, ++I) { + if (OpInfo[i].isPredicate() ) { + I->setImm(CC); + ++I; + if (CC == ARMCC::AL) + I->setReg(0); + else + I->setReg(ARM::CPSR); + return; + } + } +} -bool ARMDisassembler::getInstruction(MCInst &MI, - uint64_t &Size, - const MemoryObject &Region, - uint64_t Address, - raw_ostream &os) const { - // The machine instruction. - uint32_t insn; + +bool ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, + const MemoryObject &Region, + uint64_t Address,raw_ostream &os) const { uint8_t bytes[4]; + // We want to read exactly 2 bytes of data. + if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1) + return false; + + uint16_t insn16 = (bytes[1] << 8) | bytes[0]; + bool result = decodeThumbInstruction16(MI, insn16, Address, this); + if (result) { + Size = 2; + bool InITBlock = ITBlock.size(); + AddThumbPredicate(MI); + AddThumb1SBit(MI, InITBlock); + return true; + } + + MI.clear(); + result = decodeThumb2Instruction16(MI, insn16, Address, this); + if (result) { + Size = 2; + AddThumbPredicate(MI); + + // If we find an IT instruction, we need to parse its condition + // code and mask operands so that we can apply them correctly + // to the subsequent instructions. + if (MI.getOpcode() == ARM::t2IT) { + unsigned firstcond = MI.getOperand(0).getImm(); + uint32_t mask = MI.getOperand(1).getImm(); + unsigned zeros = CountTrailingZeros_32(mask); + mask >>= zeros+1; + + for (unsigned i = 0; i < 4 - (zeros+1); ++i) { + if (firstcond ^ (mask & 1)) + ITBlock.push_back(firstcond ^ 1); + else + ITBlock.push_back(firstcond); + mask >>= 1; + } + ITBlock.push_back(firstcond); + } + + return true; + } + // We want to read exactly 4 bytes of data. if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1) return false; - // Encoded as a small-endian 32-bit word in the stream. - insn = (bytes[3] << 24) | - (bytes[2] << 16) | - (bytes[1] << 8) | - (bytes[0] << 0); + uint32_t insn32 = (bytes[3] << 8) | + (bytes[2] << 0) | + (bytes[1] << 24) | + (bytes[0] << 16); + MI.clear(); + result = decodeThumbInstruction32(MI, insn32, Address, this); + if (result) { + Size = 4; + bool InITBlock = ITBlock.size(); + AddThumbPredicate(MI); + AddThumb1SBit(MI, InITBlock); + return true; + } + + MI.clear(); + result = decodeThumb2Instruction32(MI, insn32, Address, this); + if (result) { + Size = 4; + AddThumbPredicate(MI); + return true; + } + + MI.clear(); + result = decodeVFPInstruction32(MI, insn32, Address, this); + if (result) { + Size = 4; + UpdateThumbVFPPredicate(MI); + return true; + } + + MI.clear(); + result = decodeCommonInstruction32(MI, insn32, Address, this); + if (result) { + Size = 4; + AddThumbPredicate(MI); + return true; + } + + return false; +} - unsigned Opcode = decodeARMInstruction(insn); - ARMFormat Format = ARMFormats[Opcode]; - Size = 4; - DEBUG({ - errs() << "\nOpcode=" << Opcode << " Name=" < Builder(CreateMCBuilder(Opcode, Format)); - if (!Builder) +static const unsigned GPRDecoderTable[] = { + ARM::R0, ARM::R1, ARM::R2, ARM::R3, + ARM::R4, ARM::R5, ARM::R6, ARM::R7, + ARM::R8, ARM::R9, ARM::R10, ARM::R11, + ARM::R12, ARM::SP, ARM::LR, ARM::PC +}; + +static bool DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo > 15) return false; - Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(), - getDisInfoBlock(), getMCContext(), - Address); + unsigned Register = GPRDecoderTable[RegNo]; + Inst.addOperand(MCOperand::CreateReg(Register)); + return true; +} - if (!Builder->Build(MI, insn)) +static bool DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo > 7) return false; + return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder); +} + +static bool DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + unsigned Register = 0; + switch (RegNo) { + case 0: + Register = ARM::R0; + break; + case 1: + Register = ARM::R1; + break; + case 2: + Register = ARM::R2; + break; + case 3: + Register = ARM::R3; + break; + case 9: + Register = ARM::R9; + break; + case 12: + Register = ARM::R12; + break; + default: + return false; + } + Inst.addOperand(MCOperand::CreateReg(Register)); return true; } -bool ThumbDisassembler::getInstruction(MCInst &MI, - uint64_t &Size, - const MemoryObject &Region, - uint64_t Address, - raw_ostream &os) const { - // The Thumb instruction stream is a sequence of halfwords. - - // This represents the first halfword as well as the machine instruction - // passed to decodeThumbInstruction(). For 16-bit Thumb instruction, the top - // halfword of insn is 0x00 0x00; otherwise, the first halfword is moved to - // the top half followed by the second halfword. - unsigned insn = 0; - // Possible second halfword. - uint16_t insn1 = 0; - - // A6.1 Thumb instruction set encoding - // - // If bits [15:11] of the halfword being decoded take any of the following - // values, the halfword is the first halfword of a 32-bit instruction: - // o 0b11101 - // o 0b11110 - // o 0b11111. - // - // Otherwise, the halfword is a 16-bit instruction. +static bool DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo == 13 || RegNo == 15) return false; + return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder); +} - // Read 2 bytes of data first. - uint8_t bytes[2]; - if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1) +static const unsigned SPRDecoderTable[] = { + ARM::S0, ARM::S1, ARM::S2, ARM::S3, + ARM::S4, ARM::S5, ARM::S6, ARM::S7, + ARM::S8, ARM::S9, ARM::S10, ARM::S11, + ARM::S12, ARM::S13, ARM::S14, ARM::S15, + ARM::S16, ARM::S17, ARM::S18, ARM::S19, + ARM::S20, ARM::S21, ARM::S22, ARM::S23, + ARM::S24, ARM::S25, ARM::S26, ARM::S27, + ARM::S28, ARM::S29, ARM::S30, ARM::S31 +}; + +static bool DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo > 31) return false; - // Encoded as a small-endian 16-bit halfword in the stream. - insn = (bytes[1] << 8) | bytes[0]; - unsigned bits15_11 = slice(insn, 15, 11); - bool IsThumb2 = false; - - // 32-bit instructions if the bits [15:11] of the halfword matches - // { 0b11101 /* 0x1D */, 0b11110 /* 0x1E */, ob11111 /* 0x1F */ }. - if (bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F) { - IsThumb2 = true; - if (Region.readBytes(Address + 2, 2, (uint8_t*)bytes, NULL) == -1) - return false; - // Encoded as a small-endian 16-bit halfword in the stream. - insn1 = (bytes[1] << 8) | bytes[0]; - insn = (insn << 16 | insn1); - } + unsigned Register = SPRDecoderTable[RegNo]; + Inst.addOperand(MCOperand::CreateReg(Register)); + return true; +} - // The insn could potentially be bit-twiddled in order to be decoded as an ARM - // NEON/VFP opcode. In such case, the modified insn is later disassembled as - // an ARM NEON/VFP instruction. - // - // This is a short term solution for lack of encoding bits specified for the - // Thumb2 NEON/VFP instructions. The long term solution could be adding some - // infrastructure to have each instruction support more than one encodings. - // Which encoding is used would be based on which subtarget the compiler/ - // disassembler is working with at the time. This would allow the sharing of - // the NEON patterns between ARM and Thumb2, as well as potential greater - // sharing between the regular ARM instructions and the 32-bit wide Thumb2 - // instructions as well. - unsigned Opcode = decodeThumbSideEffect(IsThumb2, insn); +static const unsigned DPRDecoderTable[] = { + ARM::D0, ARM::D1, ARM::D2, ARM::D3, + ARM::D4, ARM::D5, ARM::D6, ARM::D7, + ARM::D8, ARM::D9, ARM::D10, ARM::D11, + ARM::D12, ARM::D13, ARM::D14, ARM::D15, + ARM::D16, ARM::D17, ARM::D18, ARM::D19, + ARM::D20, ARM::D21, ARM::D22, ARM::D23, + ARM::D24, ARM::D25, ARM::D26, ARM::D27, + ARM::D28, ARM::D29, ARM::D30, ARM::D31 +}; + +static bool DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo > 31) + return false; - ARMFormat Format = ARMFormats[Opcode]; - Size = IsThumb2 ? 4 : 2; + unsigned Register = DPRDecoderTable[RegNo]; + Inst.addOperand(MCOperand::CreateReg(Register)); + return true; +} - DEBUG({ - errs() << "Opcode=" << Opcode << " Name=" << ARMUtils::OpcodeName(Opcode) - << " Format=" << stringForARMFormat(Format) << '(' << (int)Format - << ")\n"; - showBitVector(errs(), insn); - }); +static bool DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo > 7) + return false; + return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder); +} - OwningPtr Builder(CreateMCBuilder(Opcode, Format)); - if (!Builder) +static bool DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo > 15) return false; + return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder); +} - Builder->SetSession(const_cast(&SO)); +static const unsigned QPRDecoderTable[] = { + ARM::Q0, ARM::Q1, ARM::Q2, ARM::Q3, + ARM::Q4, ARM::Q5, ARM::Q6, ARM::Q7, + ARM::Q8, ARM::Q9, ARM::Q10, ARM::Q11, + ARM::Q12, ARM::Q13, ARM::Q14, ARM::Q15 +}; - Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(), - getDisInfoBlock(), getMCContext(), - Address); - if (!Builder->Build(MI, insn)) +static bool DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo > 31) return false; + RegNo >>= 1; + unsigned Register = QPRDecoderTable[RegNo]; + Inst.addOperand(MCOperand::CreateReg(Register)); return true; } -// A8.6.50 -// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition. -static unsigned short CountITSize(unsigned ITMask) { - // First count the trailing zeros of the IT mask. - unsigned TZ = CountTrailingZeros_32(ITMask); - if (TZ > 3) { - DEBUG(errs() << "Encoding error: IT Mask '0000'"); - return 0; - } - return (4 - TZ); +static bool DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + if (Val == 0xF) return false; + Inst.addOperand(MCOperand::CreateImm(Val)); + if (Val == ARMCC::AL) { + Inst.addOperand(MCOperand::CreateReg(0)); + } else + Inst.addOperand(MCOperand::CreateReg(ARM::CPSR)); + return true; } -/// Init ITState. Note that at least one bit is always 1 in mask. -bool Session::InitIT(unsigned short bits7_0) { - ITCounter = CountITSize(slice(bits7_0, 3, 0)); - if (ITCounter == 0) - return false; +static bool DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + if (Val) + Inst.addOperand(MCOperand::CreateReg(ARM::CPSR)); + else + Inst.addOperand(MCOperand::CreateReg(0)); + return true; +} - // A8.6.50 IT - unsigned short FirstCond = slice(bits7_0, 7, 4); - if (FirstCond == 0xF) { - DEBUG(errs() << "Encoding error: IT FirstCond '1111'"); - return false; +static bool DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + uint32_t imm = Val & 0xFF; + uint32_t rot = (Val & 0xF00) >> 7; + uint32_t rot_imm = (imm >> rot) | (imm << (32-rot)); + Inst.addOperand(MCOperand::CreateImm(rot_imm)); + return true; +} + +static bool DecodeBLTargetOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Val <<= 2; + Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(Val))); + return true; +} + +static bool DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + + unsigned Rm = fieldFromInstruction32(Val, 0, 4); + unsigned type = fieldFromInstruction32(Val, 5, 2); + unsigned imm = fieldFromInstruction32(Val, 7, 5); + + // Register-immediate + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + + ARM_AM::ShiftOpc Shift = ARM_AM::lsl; + switch (type) { + case 0: + Shift = ARM_AM::lsl; + break; + case 1: + Shift = ARM_AM::lsr; + break; + case 2: + Shift = ARM_AM::asr; + break; + case 3: + Shift = ARM_AM::ror; + break; } - if (FirstCond == 0xE && ITCounter != 1) { - DEBUG(errs() << "Encoding error: IT FirstCond '1110' && Mask != '1000'"); - return false; + + if (Shift == ARM_AM::ror && imm == 0) + Shift = ARM_AM::rrx; + + unsigned Op = Shift | (imm << 3); + Inst.addOperand(MCOperand::CreateImm(Op)); + + return true; +} + +static bool DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + + unsigned Rm = fieldFromInstruction32(Val, 0, 4); + unsigned type = fieldFromInstruction32(Val, 5, 2); + unsigned Rs = fieldFromInstruction32(Val, 8, 4); + + // Register-register + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + DecodeGPRRegisterClass(Inst, Rs, Address, Decoder); + + ARM_AM::ShiftOpc Shift = ARM_AM::lsl; + switch (type) { + case 0: + Shift = ARM_AM::lsl; + break; + case 1: + Shift = ARM_AM::lsr; + break; + case 2: + Shift = ARM_AM::asr; + break; + case 3: + Shift = ARM_AM::ror; + break; } - ITState = bits7_0; + Inst.addOperand(MCOperand::CreateImm(Shift)); return true; } -/// Update ITState if necessary. -void Session::UpdateIT() { - assert(ITCounter); - --ITCounter; - if (ITCounter == 0) - ITState = 0; - else { - unsigned short NewITState4_0 = slice(ITState, 4, 0) << 1; - setSlice(ITState, 4, 0, NewITState4_0); +static bool DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + for (unsigned i = 0; i < 16; ++i) { + if (Val & (1 << i)) + DecodeGPRRegisterClass(Inst, i, Address, Decoder); } + + return true; } -static MCDisassembler *createARMDisassembler(const Target &T) { - return new ARMDisassembler; +static bool DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Vd = fieldFromInstruction32(Val, 8, 4); + unsigned regs = Val & 0xFF; + + DecodeSPRRegisterClass(Inst, Vd, Address, Decoder); + for (unsigned i = 0; i < (regs - 1); ++i) + DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder); + + return true; } -static MCDisassembler *createThumbDisassembler(const Target &T) { - return new ThumbDisassembler; +static bool DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Vd = fieldFromInstruction32(Val, 8, 4); + unsigned regs = (Val & 0xFF) / 2; + + DecodeDPRRegisterClass(Inst, Vd, Address, Decoder); + for (unsigned i = 0; i < (regs - 1); ++i) + DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder); + + return true; } -extern "C" void LLVMInitializeARMDisassembler() { - // Register the disassembler. - TargetRegistry::RegisterMCDisassembler(TheARMTarget, - createARMDisassembler); - TargetRegistry::RegisterMCDisassembler(TheThumbTarget, - createThumbDisassembler); +static bool DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned msb = fieldFromInstruction32(Val, 5, 5); + unsigned lsb = fieldFromInstruction32(Val, 0, 5); + uint32_t msb_mask = (1 << (msb+1)) - 1; + uint32_t lsb_mask = (1 << lsb) - 1; + Inst.addOperand(MCOperand::CreateImm(~(msb_mask ^ lsb_mask))); + return true; } -EDInstInfo *ARMDisassembler::getEDInfo() const { - return instInfoARM; +static bool DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned CRd = fieldFromInstruction32(Insn, 12, 4); + unsigned coproc = fieldFromInstruction32(Insn, 8, 4); + unsigned imm = fieldFromInstruction32(Insn, 0, 8); + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned U = fieldFromInstruction32(Insn, 23, 1); + + switch (Inst.getOpcode()) { + case ARM::LDC_OFFSET: + case ARM::LDC_PRE: + case ARM::LDC_POST: + case ARM::LDC_OPTION: + case ARM::LDCL_OFFSET: + case ARM::LDCL_PRE: + case ARM::LDCL_POST: + case ARM::LDCL_OPTION: + case ARM::STC_OFFSET: + case ARM::STC_PRE: + case ARM::STC_POST: + case ARM::STC_OPTION: + case ARM::STCL_OFFSET: + case ARM::STCL_PRE: + case ARM::STCL_POST: + case ARM::STCL_OPTION: + if (coproc == 0xA || coproc == 0xB) + return false; + break; + default: + break; + } + + Inst.addOperand(MCOperand::CreateImm(coproc)); + Inst.addOperand(MCOperand::CreateImm(CRd)); + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + switch (Inst.getOpcode()) { + case ARM::LDC_OPTION: + case ARM::LDCL_OPTION: + case ARM::LDC2_OPTION: + case ARM::LDC2L_OPTION: + case ARM::STC_OPTION: + case ARM::STCL_OPTION: + case ARM::STC2_OPTION: + case ARM::STC2L_OPTION: + case ARM::LDCL_POST: + case ARM::STCL_POST: + break; + default: + Inst.addOperand(MCOperand::CreateReg(0)); + break; + } + + unsigned P = fieldFromInstruction32(Insn, 24, 1); + unsigned W = fieldFromInstruction32(Insn, 21, 1); + + bool writeback = (P == 0) || (W == 1); + unsigned idx_mode = 0; + if (P && writeback) + idx_mode = ARMII::IndexModePre; + else if (!P && writeback) + idx_mode = ARMII::IndexModePost; + + switch (Inst.getOpcode()) { + case ARM::LDCL_POST: + case ARM::STCL_POST: + imm |= U << 8; + case ARM::LDC_OPTION: + case ARM::LDCL_OPTION: + case ARM::LDC2_OPTION: + case ARM::LDC2L_OPTION: + case ARM::STC_OPTION: + case ARM::STCL_OPTION: + case ARM::STC2_OPTION: + case ARM::STC2L_OPTION: + Inst.addOperand(MCOperand::CreateImm(imm)); + break; + default: + if (U) + Inst.addOperand(MCOperand::CreateImm( + ARM_AM::getAM2Opc(ARM_AM::add, imm, ARM_AM::lsl, idx_mode))); + else + Inst.addOperand(MCOperand::CreateImm( + ARM_AM::getAM2Opc(ARM_AM::sub, imm, ARM_AM::lsl, idx_mode))); + break; + } + + switch (Inst.getOpcode()) { + case ARM::LDC_OFFSET: + case ARM::LDC_PRE: + case ARM::LDC_POST: + case ARM::LDC_OPTION: + case ARM::LDCL_OFFSET: + case ARM::LDCL_PRE: + case ARM::LDCL_POST: + case ARM::LDCL_OPTION: + case ARM::STC_OFFSET: + case ARM::STC_PRE: + case ARM::STC_POST: + case ARM::STC_OPTION: + case ARM::STCL_OFFSET: + case ARM::STCL_PRE: + case ARM::STCL_POST: + case ARM::STCL_OPTION: + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false; + break; + default: + break; + } + + return true; } -EDInstInfo *ThumbDisassembler::getEDInfo() const { - return instInfoARM; +static bool DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned Rt = fieldFromInstruction32(Insn, 12, 4); + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned imm = fieldFromInstruction32(Insn, 0, 12); + unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned reg = fieldFromInstruction32(Insn, 25, 1); + unsigned P = fieldFromInstruction32(Insn, 24, 1); + unsigned W = fieldFromInstruction32(Insn, 21, 1); + + // On stores, the writeback operand precedes Rt. + switch (Inst.getOpcode()) { + case ARM::STR_POST_IMM: + case ARM::STR_POST_REG: + case ARM::STRTr: + case ARM::STRTi: + case ARM::STRBTr: + case ARM::STRBTi: + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + break; + default: + break; + } + + DecodeGPRRegisterClass(Inst, Rt, Address, Decoder); + + // On loads, the writeback operand comes after Rt. + switch (Inst.getOpcode()) { + case ARM::LDR_POST_IMM: + case ARM::LDR_POST_REG: + case ARM::LDR_PRE: + case ARM::LDRBT_POST_REG: + case ARM::LDRBT_POST_IMM: + case ARM::LDRTr: + case ARM::LDRTi: + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + break; + default: + break; + } + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + ARM_AM::AddrOpc Op = ARM_AM::add; + if (!fieldFromInstruction32(Insn, 23, 1)) + Op = ARM_AM::sub; + + bool writeback = (P == 0) || (W == 1); + unsigned idx_mode = 0; + if (P && writeback) + idx_mode = ARMII::IndexModePre; + else if (!P && writeback) + idx_mode = ARMII::IndexModePost; + + if (reg) { + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + ARM_AM::ShiftOpc Opc = ARM_AM::lsl; + switch( fieldFromInstruction32(Insn, 5, 2)) { + case 0: + Opc = ARM_AM::lsl; + break; + case 1: + Opc = ARM_AM::lsr; + break; + case 2: + Opc = ARM_AM::asr; + break; + case 3: + Opc = ARM_AM::ror; + break; + default: + return false; + } + unsigned amt = fieldFromInstruction32(Insn, 7, 5); + unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode); + + Inst.addOperand(MCOperand::CreateImm(imm)); + } else { + Inst.addOperand(MCOperand::CreateReg(0)); + unsigned tmp = ARM_AM::getAM2Opc(Op, imm, ARM_AM::lsl, idx_mode); + Inst.addOperand(MCOperand::CreateImm(tmp)); + } + + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false; + + return true; +} + +static bool DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Val, 13, 4); + unsigned Rm = fieldFromInstruction32(Val, 0, 4); + unsigned type = fieldFromInstruction32(Val, 5, 2); + unsigned imm = fieldFromInstruction32(Val, 7, 5); + unsigned U = fieldFromInstruction32(Val, 12, 1); + + ARM_AM::ShiftOpc ShOp; + switch (type) { + case 0: + ShOp = ARM_AM::lsl; + break; + case 1: + ShOp = ARM_AM::lsr; + break; + case 2: + ShOp = ARM_AM::asr; + break; + case 3: + ShOp = ARM_AM::ror; + break; + } + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + unsigned shift; + if (U) + shift = ARM_AM::getAM2Opc(ARM_AM::add, imm, ShOp); + else + shift = ARM_AM::getAM2Opc(ARM_AM::sub, imm, ShOp); + Inst.addOperand(MCOperand::CreateImm(shift)); + + return true; +} + +static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rt = fieldFromInstruction32(Insn, 12, 4); + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned type = fieldFromInstruction32(Insn, 22, 1); + unsigned imm = fieldFromInstruction32(Insn, 8, 4); + unsigned U = ((~fieldFromInstruction32(Insn, 23, 1)) & 1) << 8; + unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned W = fieldFromInstruction32(Insn, 21, 1); + unsigned P = fieldFromInstruction32(Insn, 24, 1); + + bool writeback = (W == 1) | (P == 0); + if (writeback) { // Writeback + if (P) + U |= ARMII::IndexModePre << 9; + else + U |= ARMII::IndexModePost << 9; + + // On stores, the writeback operand precedes Rt. + switch (Inst.getOpcode()) { + case ARM::STRD: + case ARM::STRD_PRE: + case ARM::STRD_POST: + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + break; + default: + break; + } + } + + DecodeGPRRegisterClass(Inst, Rt, Address, Decoder); + switch (Inst.getOpcode()) { + case ARM::STRD: + case ARM::STRD_PRE: + case ARM::STRD_POST: + case ARM::LDRD: + case ARM::LDRD_PRE: + case ARM::LDRD_POST: + DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder); + break; + default: + break; + } + + if (writeback) { + // On loads, the writeback operand comes after Rt. + switch (Inst.getOpcode()) { + case ARM::LDRD: + case ARM::LDRD_PRE: + case ARM::LDRD_POST: + case ARM::LDRHTr: + case ARM::LDRSBTr: + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + break; + default: + break; + } + } + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + if (type) { + Inst.addOperand(MCOperand::CreateReg(0)); + Inst.addOperand(MCOperand::CreateImm(U | (imm << 4) | Rm)); + } else { + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(U)); + } + + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false; + + return true; +} + +static bool DecodeRFEInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned mode = fieldFromInstruction32(Insn, 23, 2); + + switch (mode) { + case 0: + mode = ARM_AM::da; + break; + case 1: + mode = ARM_AM::ia; + break; + case 2: + mode = ARM_AM::db; + break; + case 3: + mode = ARM_AM::ib; + break; + } + + Inst.addOperand(MCOperand::CreateImm(mode)); + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + return true; +} + +static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst &Inst, + unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned reglist = fieldFromInstruction32(Insn, 0, 16); + + if (pred == 0xF) { + switch (Inst.getOpcode()) { + case ARM::STMDA: + Inst.setOpcode(ARM::RFEDA); + break; + case ARM::STMDA_UPD: + Inst.setOpcode(ARM::RFEDA_UPD); + break; + case ARM::STMDB: + Inst.setOpcode(ARM::RFEDB); + break; + case ARM::STMDB_UPD: + Inst.setOpcode(ARM::RFEDB_UPD); + break; + case ARM::STMIA: + Inst.setOpcode(ARM::RFEIA); + break; + case ARM::STMIA_UPD: + Inst.setOpcode(ARM::RFEIA_UPD); + break; + case ARM::STMIB: + Inst.setOpcode(ARM::RFEIB); + break; + case ARM::STMIB_UPD: + Inst.setOpcode(ARM::RFEIB_UPD); + break; + + } + return DecodeRFEInstruction(Inst, Insn, Address, Decoder); + } + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); // Tied + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false; + DecodeRegListOperand(Inst, reglist, Address, Decoder); + + return true; +} + +static bool DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned imod = fieldFromInstruction32(Insn, 18, 2); + unsigned M = fieldFromInstruction32(Insn, 17, 1); + unsigned iflags = fieldFromInstruction32(Insn, 6, 3); + unsigned mode = fieldFromInstruction32(Insn, 0, 5); + + if (M && mode && imod && iflags) { + Inst.setOpcode(ARM::CPS3p); + Inst.addOperand(MCOperand::CreateImm(imod)); + Inst.addOperand(MCOperand::CreateImm(iflags)); + Inst.addOperand(MCOperand::CreateImm(mode)); + return true; + } else if (!mode && !M) { + Inst.setOpcode(ARM::CPS2p); + Inst.addOperand(MCOperand::CreateImm(imod)); + Inst.addOperand(MCOperand::CreateImm(iflags)); + return true; + } else if (!imod && !iflags && M) { + Inst.setOpcode(ARM::CPS1p); + Inst.addOperand(MCOperand::CreateImm(mode)); + return true; + } + + return false; +} + +static bool DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 16, 4); + unsigned Rn = fieldFromInstruction32(Insn, 0, 4); + unsigned Rm = fieldFromInstruction32(Insn, 8, 4); + unsigned Ra = fieldFromInstruction32(Insn, 12, 4); + unsigned pred = fieldFromInstruction32(Insn, 28, 4); + + if (pred == 0xF) + return DecodeCPSInstruction(Inst, Insn, Address, Decoder); + + DecodeGPRRegisterClass(Inst, Rd, Address, Decoder); + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + DecodeGPRRegisterClass(Inst, Ra, Address, Decoder); + + return true; +} + +static bool DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned add = fieldFromInstruction32(Val, 12, 1); + unsigned imm = fieldFromInstruction32(Val, 0, 12); + unsigned Rn = fieldFromInstruction32(Val, 13, 4); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + if (!add) imm *= -1; + if (imm == 0 && !add) imm = INT32_MIN; + Inst.addOperand(MCOperand::CreateImm(imm)); + + return true; +} + +static bool DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Val, 9, 4); + unsigned U = fieldFromInstruction32(Val, 8, 1); + unsigned imm = fieldFromInstruction32(Val, 0, 8); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + if (U) + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, imm))); + else + Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub, imm))); + + return true; +} + +static bool DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + return DecodeGPRRegisterClass(Inst, Val, Address, Decoder); +} + +static bool DecodeBranchImmInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned pred = fieldFromInstruction32(Insn, 28, 4); + unsigned imm = fieldFromInstruction32(Insn, 0, 24) << 2; + + if (pred == 0xF) { + Inst.setOpcode(ARM::BLXi); + imm |= fieldFromInstruction32(Insn, 24, 1) << 1; + Inst.addOperand(MCOperand::CreateImm(imm)); + return true; + } + + Inst.addOperand(MCOperand::CreateImm(imm)); + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false; + + return true; +} + + +static bool DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(64 - Val)); + return true; +} + +static bool DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rm = fieldFromInstruction32(Val, 0, 4); + unsigned align = fieldFromInstruction32(Val, 4, 2); + + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + if (!align) + Inst.addOperand(MCOperand::CreateImm(0)); + else + Inst.addOperand(MCOperand::CreateImm(4 << align)); + + return true; +} + +static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned wb = fieldFromInstruction32(Insn, 16, 4); + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + Rn |= fieldFromInstruction32(Insn, 4, 2) << 4; + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + + // First output register + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + + // Second output register + switch (Inst.getOpcode()) { + case ARM::VLD1q8: + case ARM::VLD1q16: + case ARM::VLD1q32: + case ARM::VLD1q64: + case ARM::VLD1q8_UPD: + case ARM::VLD1q16_UPD: + case ARM::VLD1q32_UPD: + case ARM::VLD1q64_UPD: + case ARM::VLD1d8T: + case ARM::VLD1d16T: + case ARM::VLD1d32T: + case ARM::VLD1d64T: + case ARM::VLD1d8T_UPD: + case ARM::VLD1d16T_UPD: + case ARM::VLD1d32T_UPD: + case ARM::VLD1d64T_UPD: + case ARM::VLD1d8Q: + case ARM::VLD1d16Q: + case ARM::VLD1d32Q: + case ARM::VLD1d64Q: + case ARM::VLD1d8Q_UPD: + case ARM::VLD1d16Q_UPD: + case ARM::VLD1d32Q_UPD: + case ARM::VLD1d64Q_UPD: + case ARM::VLD2d8: + case ARM::VLD2d16: + case ARM::VLD2d32: + case ARM::VLD2d8_UPD: + case ARM::VLD2d16_UPD: + case ARM::VLD2d32_UPD: + case ARM::VLD2q8: + case ARM::VLD2q16: + case ARM::VLD2q32: + case ARM::VLD2q8_UPD: + case ARM::VLD2q16_UPD: + case ARM::VLD2q32_UPD: + case ARM::VLD3d8: + case ARM::VLD3d16: + case ARM::VLD3d32: + case ARM::VLD3d8_UPD: + case ARM::VLD3d16_UPD: + case ARM::VLD3d32_UPD: + case ARM::VLD4d8: + case ARM::VLD4d16: + case ARM::VLD4d32: + case ARM::VLD4d8_UPD: + case ARM::VLD4d16_UPD: + case ARM::VLD4d32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder); + break; + case ARM::VLD2b8: + case ARM::VLD2b16: + case ARM::VLD2b32: + case ARM::VLD2b8_UPD: + case ARM::VLD2b16_UPD: + case ARM::VLD2b32_UPD: + case ARM::VLD3q8: + case ARM::VLD3q16: + case ARM::VLD3q32: + case ARM::VLD3q8_UPD: + case ARM::VLD3q16_UPD: + case ARM::VLD3q32_UPD: + case ARM::VLD4q8: + case ARM::VLD4q16: + case ARM::VLD4q32: + case ARM::VLD4q8_UPD: + case ARM::VLD4q16_UPD: + case ARM::VLD4q32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder); + default: + break; + } + + // Third output register + switch(Inst.getOpcode()) { + case ARM::VLD1d8T: + case ARM::VLD1d16T: + case ARM::VLD1d32T: + case ARM::VLD1d64T: + case ARM::VLD1d8T_UPD: + case ARM::VLD1d16T_UPD: + case ARM::VLD1d32T_UPD: + case ARM::VLD1d64T_UPD: + case ARM::VLD1d8Q: + case ARM::VLD1d16Q: + case ARM::VLD1d32Q: + case ARM::VLD1d64Q: + case ARM::VLD1d8Q_UPD: + case ARM::VLD1d16Q_UPD: + case ARM::VLD1d32Q_UPD: + case ARM::VLD1d64Q_UPD: + case ARM::VLD2q8: + case ARM::VLD2q16: + case ARM::VLD2q32: + case ARM::VLD2q8_UPD: + case ARM::VLD2q16_UPD: + case ARM::VLD2q32_UPD: + case ARM::VLD3d8: + case ARM::VLD3d16: + case ARM::VLD3d32: + case ARM::VLD3d8_UPD: + case ARM::VLD3d16_UPD: + case ARM::VLD3d32_UPD: + case ARM::VLD4d8: + case ARM::VLD4d16: + case ARM::VLD4d32: + case ARM::VLD4d8_UPD: + case ARM::VLD4d16_UPD: + case ARM::VLD4d32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder); + break; + case ARM::VLD3q8: + case ARM::VLD3q16: + case ARM::VLD3q32: + case ARM::VLD3q8_UPD: + case ARM::VLD3q16_UPD: + case ARM::VLD3q32_UPD: + case ARM::VLD4q8: + case ARM::VLD4q16: + case ARM::VLD4q32: + case ARM::VLD4q8_UPD: + case ARM::VLD4q16_UPD: + case ARM::VLD4q32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder); + break; + default: + break; + } + + // Fourth output register + switch (Inst.getOpcode()) { + case ARM::VLD1d8Q: + case ARM::VLD1d16Q: + case ARM::VLD1d32Q: + case ARM::VLD1d64Q: + case ARM::VLD1d8Q_UPD: + case ARM::VLD1d16Q_UPD: + case ARM::VLD1d32Q_UPD: + case ARM::VLD1d64Q_UPD: + case ARM::VLD2q8: + case ARM::VLD2q16: + case ARM::VLD2q32: + case ARM::VLD2q8_UPD: + case ARM::VLD2q16_UPD: + case ARM::VLD2q32_UPD: + case ARM::VLD4d8: + case ARM::VLD4d16: + case ARM::VLD4d32: + case ARM::VLD4d8_UPD: + case ARM::VLD4d16_UPD: + case ARM::VLD4d32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder); + break; + case ARM::VLD4q8: + case ARM::VLD4q16: + case ARM::VLD4q32: + case ARM::VLD4q8_UPD: + case ARM::VLD4q16_UPD: + case ARM::VLD4q32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder); + break; + default: + break; + } + + // Writeback operand + switch (Inst.getOpcode()) { + case ARM::VLD1d8_UPD: + case ARM::VLD1d16_UPD: + case ARM::VLD1d32_UPD: + case ARM::VLD1d64_UPD: + case ARM::VLD1q8_UPD: + case ARM::VLD1q16_UPD: + case ARM::VLD1q32_UPD: + case ARM::VLD1q64_UPD: + case ARM::VLD1d8T_UPD: + case ARM::VLD1d16T_UPD: + case ARM::VLD1d32T_UPD: + case ARM::VLD1d64T_UPD: + case ARM::VLD1d8Q_UPD: + case ARM::VLD1d16Q_UPD: + case ARM::VLD1d32Q_UPD: + case ARM::VLD1d64Q_UPD: + case ARM::VLD2d8_UPD: + case ARM::VLD2d16_UPD: + case ARM::VLD2d32_UPD: + case ARM::VLD2q8_UPD: + case ARM::VLD2q16_UPD: + case ARM::VLD2q32_UPD: + case ARM::VLD2b8_UPD: + case ARM::VLD2b16_UPD: + case ARM::VLD2b32_UPD: + case ARM::VLD3d8_UPD: + case ARM::VLD3d16_UPD: + case ARM::VLD3d32_UPD: + case ARM::VLD3q8_UPD: + case ARM::VLD3q16_UPD: + case ARM::VLD3q32_UPD: + case ARM::VLD4d8_UPD: + case ARM::VLD4d16_UPD: + case ARM::VLD4d32_UPD: + case ARM::VLD4q8_UPD: + case ARM::VLD4q16_UPD: + case ARM::VLD4q32_UPD: + DecodeGPRRegisterClass(Inst, wb, Address, Decoder); + break; + default: + break; + } + + // AddrMode6 Base (register+alignment) + DecodeAddrMode6Operand(Inst, Rn, Address, Decoder); + + // AddrMode6 Offset (register) + if (Rm == 0xD) + Inst.addOperand(MCOperand::CreateReg(0)); + else if (Rm != 0xF) + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + + return true; +} + +static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned wb = fieldFromInstruction32(Insn, 16, 4); + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + Rn |= fieldFromInstruction32(Insn, 4, 2) << 4; + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + + // Writeback Operand + switch (Inst.getOpcode()) { + case ARM::VST1d8_UPD: + case ARM::VST1d16_UPD: + case ARM::VST1d32_UPD: + case ARM::VST1d64_UPD: + case ARM::VST1q8_UPD: + case ARM::VST1q16_UPD: + case ARM::VST1q32_UPD: + case ARM::VST1q64_UPD: + case ARM::VST1d8T_UPD: + case ARM::VST1d16T_UPD: + case ARM::VST1d32T_UPD: + case ARM::VST1d64T_UPD: + case ARM::VST1d8Q_UPD: + case ARM::VST1d16Q_UPD: + case ARM::VST1d32Q_UPD: + case ARM::VST1d64Q_UPD: + case ARM::VST2d8_UPD: + case ARM::VST2d16_UPD: + case ARM::VST2d32_UPD: + case ARM::VST2q8_UPD: + case ARM::VST2q16_UPD: + case ARM::VST2q32_UPD: + case ARM::VST2b8_UPD: + case ARM::VST2b16_UPD: + case ARM::VST2b32_UPD: + case ARM::VST3d8_UPD: + case ARM::VST3d16_UPD: + case ARM::VST3d32_UPD: + case ARM::VST3q8_UPD: + case ARM::VST3q16_UPD: + case ARM::VST3q32_UPD: + case ARM::VST4d8_UPD: + case ARM::VST4d16_UPD: + case ARM::VST4d32_UPD: + case ARM::VST4q8_UPD: + case ARM::VST4q16_UPD: + case ARM::VST4q32_UPD: + DecodeGPRRegisterClass(Inst, wb, Address, Decoder); + break; + default: + break; + } + + // AddrMode6 Base (register+alignment) + DecodeAddrMode6Operand(Inst, Rn, Address, Decoder); + + // AddrMode6 Offset (register) + if (Rm == 0xD) + Inst.addOperand(MCOperand::CreateReg(0)); + else if (Rm != 0xF) + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + + // First input register + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + + // Second input register + switch (Inst.getOpcode()) { + case ARM::VST1q8: + case ARM::VST1q16: + case ARM::VST1q32: + case ARM::VST1q64: + case ARM::VST1q8_UPD: + case ARM::VST1q16_UPD: + case ARM::VST1q32_UPD: + case ARM::VST1q64_UPD: + case ARM::VST1d8T: + case ARM::VST1d16T: + case ARM::VST1d32T: + case ARM::VST1d64T: + case ARM::VST1d8T_UPD: + case ARM::VST1d16T_UPD: + case ARM::VST1d32T_UPD: + case ARM::VST1d64T_UPD: + case ARM::VST1d8Q: + case ARM::VST1d16Q: + case ARM::VST1d32Q: + case ARM::VST1d64Q: + case ARM::VST1d8Q_UPD: + case ARM::VST1d16Q_UPD: + case ARM::VST1d32Q_UPD: + case ARM::VST1d64Q_UPD: + case ARM::VST2d8: + case ARM::VST2d16: + case ARM::VST2d32: + case ARM::VST2d8_UPD: + case ARM::VST2d16_UPD: + case ARM::VST2d32_UPD: + case ARM::VST2q8: + case ARM::VST2q16: + case ARM::VST2q32: + case ARM::VST2q8_UPD: + case ARM::VST2q16_UPD: + case ARM::VST2q32_UPD: + case ARM::VST3d8: + case ARM::VST3d16: + case ARM::VST3d32: + case ARM::VST3d8_UPD: + case ARM::VST3d16_UPD: + case ARM::VST3d32_UPD: + case ARM::VST4d8: + case ARM::VST4d16: + case ARM::VST4d32: + case ARM::VST4d8_UPD: + case ARM::VST4d16_UPD: + case ARM::VST4d32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder); + break; + case ARM::VST2b8: + case ARM::VST2b16: + case ARM::VST2b32: + case ARM::VST2b8_UPD: + case ARM::VST2b16_UPD: + case ARM::VST2b32_UPD: + case ARM::VST3q8: + case ARM::VST3q16: + case ARM::VST3q32: + case ARM::VST3q8_UPD: + case ARM::VST3q16_UPD: + case ARM::VST3q32_UPD: + case ARM::VST4q8: + case ARM::VST4q16: + case ARM::VST4q32: + case ARM::VST4q8_UPD: + case ARM::VST4q16_UPD: + case ARM::VST4q32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder); + break; + default: + break; + } + + // Third input register + switch (Inst.getOpcode()) { + case ARM::VST1d8T: + case ARM::VST1d16T: + case ARM::VST1d32T: + case ARM::VST1d64T: + case ARM::VST1d8T_UPD: + case ARM::VST1d16T_UPD: + case ARM::VST1d32T_UPD: + case ARM::VST1d64T_UPD: + case ARM::VST1d8Q: + case ARM::VST1d16Q: + case ARM::VST1d32Q: + case ARM::VST1d64Q: + case ARM::VST1d8Q_UPD: + case ARM::VST1d16Q_UPD: + case ARM::VST1d32Q_UPD: + case ARM::VST1d64Q_UPD: + case ARM::VST2q8: + case ARM::VST2q16: + case ARM::VST2q32: + case ARM::VST2q8_UPD: + case ARM::VST2q16_UPD: + case ARM::VST2q32_UPD: + case ARM::VST3d8: + case ARM::VST3d16: + case ARM::VST3d32: + case ARM::VST3d8_UPD: + case ARM::VST3d16_UPD: + case ARM::VST3d32_UPD: + case ARM::VST4d8: + case ARM::VST4d16: + case ARM::VST4d32: + case ARM::VST4d8_UPD: + case ARM::VST4d16_UPD: + case ARM::VST4d32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder); + break; + case ARM::VST3q8: + case ARM::VST3q16: + case ARM::VST3q32: + case ARM::VST3q8_UPD: + case ARM::VST3q16_UPD: + case ARM::VST3q32_UPD: + case ARM::VST4q8: + case ARM::VST4q16: + case ARM::VST4q32: + case ARM::VST4q8_UPD: + case ARM::VST4q16_UPD: + case ARM::VST4q32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder); + break; + default: + break; + } + + // Fourth input register + switch (Inst.getOpcode()) { + case ARM::VST1d8Q: + case ARM::VST1d16Q: + case ARM::VST1d32Q: + case ARM::VST1d64Q: + case ARM::VST1d8Q_UPD: + case ARM::VST1d16Q_UPD: + case ARM::VST1d32Q_UPD: + case ARM::VST1d64Q_UPD: + case ARM::VST2q8: + case ARM::VST2q16: + case ARM::VST2q32: + case ARM::VST2q8_UPD: + case ARM::VST2q16_UPD: + case ARM::VST2q32_UPD: + case ARM::VST4d8: + case ARM::VST4d16: + case ARM::VST4d32: + case ARM::VST4d8_UPD: + case ARM::VST4d16_UPD: + case ARM::VST4d32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder); + break; + case ARM::VST4q8: + case ARM::VST4q16: + case ARM::VST4q32: + case ARM::VST4q8_UPD: + case ARM::VST4q16_UPD: + case ARM::VST4q32_UPD: + DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder); + break; + default: + break; + } + + return true; +} + +static bool DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned align = fieldFromInstruction32(Insn, 4, 1); + unsigned size = fieldFromInstruction32(Insn, 6, 2); + unsigned regs = fieldFromInstruction32(Insn, 5, 1) + 1; + + align *= (1 << size); + + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + if (regs == 2) DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder); + if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(align)); + + if (Rm == 0xD) + Inst.addOperand(MCOperand::CreateReg(0)); + else if (Rm != 0xF) + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + + return true; +} + +static bool DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned align = fieldFromInstruction32(Insn, 4, 1); + unsigned size = 1 << fieldFromInstruction32(Insn, 6, 2); + unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1; + align *= 2*size; + + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder); + if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(align)); + + if (Rm == 0xD) + Inst.addOperand(MCOperand::CreateReg(0)); + else if (Rm != 0xF) + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + + return true; +} + +static bool DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1; + + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder); + DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder); + if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(0)); + + if (Rm == 0xD) + Inst.addOperand(MCOperand::CreateReg(0)); + else if (Rm != 0xF) + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + + return true; +} + +static bool DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned size = fieldFromInstruction32(Insn, 6, 2); + unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1; + unsigned align = fieldFromInstruction32(Insn, 4, 1); + + if (size == 0x3) { + size = 4; + align = 16; + } else { + if (size == 2) { + size = 1 << size; + align *= 8; + } else { + size = 1 << size; + align *= 4*size; + } + } + + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder); + DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder); + DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder); + if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(align)); + + if (Rm == 0xD) + Inst.addOperand(MCOperand::CreateReg(0)); + else if (Rm != 0xF) + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + + return true; +} + +static bool DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned imm = fieldFromInstruction32(Insn, 0, 4); + imm |= fieldFromInstruction32(Insn, 16, 3) << 4; + imm |= fieldFromInstruction32(Insn, 24, 1) << 7; + imm |= fieldFromInstruction32(Insn, 8, 4) << 8; + imm |= fieldFromInstruction32(Insn, 5, 1) << 12; + unsigned Q = fieldFromInstruction32(Insn, 6, 1); + + if (Q) + DecodeQPRRegisterClass(Inst, Rd, Address, Decoder); + else + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + + Inst.addOperand(MCOperand::CreateImm(imm)); + + switch (Inst.getOpcode()) { + case ARM::VORRiv4i16: + case ARM::VORRiv2i32: + case ARM::VBICiv4i16: + case ARM::VBICiv2i32: + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + break; + case ARM::VORRiv8i16: + case ARM::VORRiv4i32: + case ARM::VBICiv8i16: + case ARM::VBICiv4i32: + DecodeQPRRegisterClass(Inst, Rd, Address, Decoder); + break; + default: + break; + } + + + return true; +} + +static bool DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + Rm |= fieldFromInstruction32(Insn, 5, 1) << 4; + unsigned size = fieldFromInstruction32(Insn, 18, 2); + + DecodeQPRRegisterClass(Inst, Rd, Address, Decoder); + DecodeDPRRegisterClass(Inst, Rm, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(8 << size)); + + return true; +} + +static bool DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(8 - Val)); + return true; +} + +static bool DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(16 - Val)); + return true; +} + +static bool DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(32 - Val)); + return true; +} + +static bool DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(64 - Val)); + return true; +} + +static bool DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rd = fieldFromInstruction32(Insn, 12, 4); + Rd |= fieldFromInstruction32(Insn, 22, 1) << 4; + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + Rn |= fieldFromInstruction32(Insn, 7, 1) << 4; + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + Rm |= fieldFromInstruction32(Insn, 5, 1) << 4; + unsigned op = fieldFromInstruction32(Insn, 6, 1); + unsigned length = fieldFromInstruction32(Insn, 8, 2) + 1; + + DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); + if (op) DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); // Writeback + + for (unsigned i = 0; i < length; ++i) + DecodeDPRRegisterClass(Inst, (Rn+i)%32, Address, Decoder); + + DecodeDPRRegisterClass(Inst, Rm, Address, Decoder); + + return true; +} + +static bool DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + // The immediate needs to be a fully instantiated float. However, the + // auto-generated decoder is only able to fill in some of the bits + // necessary. For instance, the 'b' bit is replicated multiple times, + // and is even present in inverted form in one bit. We do a little + // binary parsing here to fill in those missing bits, and then + // reinterpret it all as a float. + union { + uint32_t integer; + float fp; + } fp_conv; + + fp_conv.integer = Val; + uint32_t b = fieldFromInstruction32(Val, 25, 1); + fp_conv.integer |= b << 26; + fp_conv.integer |= b << 27; + fp_conv.integer |= b << 28; + fp_conv.integer |= b << 29; + fp_conv.integer |= (~b & 0x1) << 30; + + Inst.addOperand(MCOperand::CreateFPImm(fp_conv.fp)); + return true; +} + +static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn, + uint64_t Address, const void *Decoder) { + unsigned dst = fieldFromInstruction16(Insn, 8, 3); + unsigned imm = fieldFromInstruction16(Insn, 0, 8); + + DecodetGPRRegisterClass(Inst, dst, Address, Decoder); + + if (Inst.getOpcode() == ARM::tADR) + Inst.addOperand(MCOperand::CreateReg(ARM::PC)); + else if (Inst.getOpcode() == ARM::tADDrSPi) + Inst.addOperand(MCOperand::CreateReg(ARM::SP)); + else + return false; + + Inst.addOperand(MCOperand::CreateImm(imm)); + return true; +} + +static bool DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(SignExtend32<12>(Val << 1))); + return true; +} + +static bool DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(SignExtend32<21>(Val))); + return true; +} + +static bool DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(SignExtend32<7>(Val << 1))); + return true; +} + +static bool DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Val, 0, 3); + unsigned Rm = fieldFromInstruction32(Val, 3, 3); + + DecodetGPRRegisterClass(Inst, Rn, Address, Decoder); + DecodetGPRRegisterClass(Inst, Rm, Address, Decoder); + + return true; +} + +static bool DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Val, 0, 3); + unsigned imm = fieldFromInstruction32(Val, 3, 5); + + DecodetGPRRegisterClass(Inst, Rn, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(imm)); + + return true; +} + +static bool DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(Val << 2)); + + return true; +} + +static bool DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateReg(ARM::SP)); + Inst.addOperand(MCOperand::CreateImm(Val << 2)); + + return true; +} + +static bool DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Val, 6, 4); + unsigned Rm = fieldFromInstruction32(Val, 2, 4); + unsigned imm = fieldFromInstruction32(Val, 0, 2); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + DecoderGPRRegisterClass(Inst, Rm, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(imm)); + + return true; +} + +static bool DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + if (Inst.getOpcode() != ARM::t2PLDs) { + unsigned Rt = fieldFromInstruction32(Insn, 12, 4); + DecodeGPRRegisterClass(Inst, Rt, Address, Decoder); + } + + unsigned Rn = fieldFromInstruction32(Insn, 16, 4); + if (Rn == 0xF) { + switch (Inst.getOpcode()) { + case ARM::t2LDRBs: + Inst.setOpcode(ARM::t2LDRBpci); + break; + case ARM::t2LDRHs: + Inst.setOpcode(ARM::t2LDRHpci); + break; + case ARM::t2LDRSHs: + Inst.setOpcode(ARM::t2LDRSHpci); + break; + case ARM::t2LDRSBs: + Inst.setOpcode(ARM::t2LDRSBpci); + break; + case ARM::t2PLDs: + Inst.setOpcode(ARM::t2PLDi12); + Inst.addOperand(MCOperand::CreateReg(ARM::PC)); + break; + default: + return false; + } + + int imm = fieldFromInstruction32(Insn, 0, 12); + if (!fieldFromInstruction32(Insn, 23, 1)) imm *= -1; + Inst.addOperand(MCOperand::CreateImm(imm)); + + return true; + } + + unsigned addrmode = fieldFromInstruction32(Insn, 4, 2); + addrmode |= fieldFromInstruction32(Insn, 0, 4) << 2; + addrmode |= fieldFromInstruction32(Insn, 16, 4) << 6; + DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder); + + return true; +} + +static bool DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + int imm = Val & 0xFF; + if (!(Val & 0x100)) imm *= -1; + Inst.addOperand(MCOperand::CreateImm(imm << 2)); + + return true; +} + +static bool DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Val, 9, 4); + unsigned imm = fieldFromInstruction32(Val, 0, 9); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + DecodeT2Imm8S4(Inst, imm, Address, Decoder); + + return true; +} + +static bool DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + int imm = Val & 0xFF; + if (!(Val & 0x100)) imm *= -1; + Inst.addOperand(MCOperand::CreateImm(imm)); + + return true; +} + + +static bool DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Val, 9, 4); + unsigned imm = fieldFromInstruction32(Val, 0, 9); + + // Some instructions always use an additive offset. + switch (Inst.getOpcode()) { + case ARM::t2LDRT: + case ARM::t2LDRBT: + case ARM::t2LDRHT: + case ARM::t2LDRSBT: + case ARM::t2LDRSHT: + imm |= 0x100; + break; + default: + break; + } + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + DecodeT2Imm8(Inst, imm, Address, Decoder); + + return true; +} + + +static bool DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned Rn = fieldFromInstruction32(Val, 13, 4); + unsigned imm = fieldFromInstruction32(Val, 0, 12); + + DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(imm)); + + return true; +} + + +static bool DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Insn, + uint64_t Address, const void *Decoder) { + unsigned imm = fieldFromInstruction16(Insn, 0, 7); + + Inst.addOperand(MCOperand::CreateReg(ARM::SP)); + Inst.addOperand(MCOperand::CreateReg(ARM::SP)); + Inst.addOperand(MCOperand::CreateImm(imm)); + + return true; +} + +static bool DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn, + uint64_t Address, const void *Decoder) { + if (Inst.getOpcode() == ARM::tADDrSP) { + unsigned Rdm = fieldFromInstruction16(Insn, 0, 3); + Rdm |= fieldFromInstruction16(Insn, 7, 1) << 3; + + DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder); + Inst.addOperand(MCOperand::CreateReg(ARM::SP)); + DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder); + } else if (Inst.getOpcode() == ARM::tADDspr) { + unsigned Rm = fieldFromInstruction16(Insn, 3, 4); + + Inst.addOperand(MCOperand::CreateReg(ARM::SP)); + Inst.addOperand(MCOperand::CreateReg(ARM::SP)); + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + } + + return true; +} + +static bool DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn, + uint64_t Address, const void *Decoder) { + unsigned imod = fieldFromInstruction16(Insn, 4, 1) | 0x2; + unsigned flags = fieldFromInstruction16(Insn, 0, 3); + + Inst.addOperand(MCOperand::CreateImm(imod)); + Inst.addOperand(MCOperand::CreateImm(flags)); + + return true; +} + +static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned Rm = fieldFromInstruction32(Insn, 0, 4); + unsigned add = fieldFromInstruction32(Insn, 4, 1); + + DecodeGPRRegisterClass(Inst, Rm, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(add)); + + return true; +} + +static bool DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1))); + return true; +} + +static bool DecodeCoprocessor(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + if (Val == 0xA || Val == 0xB) + return false; + + Inst.addOperand(MCOperand::CreateImm(Val)); + return true; +} + +static bool DecodeThumbSRImm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + if (Val == 0) + Inst.addOperand(MCOperand::CreateImm(32)); + else + Inst.addOperand(MCOperand::CreateImm(Val)); + return true; +} + +static bool DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned pred = fieldFromInstruction32(Insn, 22, 4); + if (pred == 0xE || pred == 0xF) { + unsigned opc = fieldFromInstruction32(Insn, 4, 2); + switch (opc) { + default: + return false; + case 0: + Inst.setOpcode(ARM::t2DSB); + break; + case 1: + Inst.setOpcode(ARM::t2DMB); + break; + case 2: + Inst.setOpcode(ARM::t2ISB); + return true; + } + + unsigned imm = fieldFromInstruction32(Insn, 0, 4); + Inst.addOperand(MCOperand::CreateImm(imm)); + return true; + } + + unsigned brtarget = fieldFromInstruction32(Insn, 0, 11) << 1; + brtarget |= fieldFromInstruction32(Insn, 11, 1) << 19; + brtarget |= fieldFromInstruction32(Insn, 13, 1) << 18; + brtarget |= fieldFromInstruction32(Insn, 16, 6) << 12; + brtarget |= fieldFromInstruction32(Insn, 26, 1) << 20; + + DecodeT2BROperand(Inst, brtarget, Address, Decoder); + if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) + return false; + + return true; +} + +// Decode a shifted immediate operand. These basically consist +// of an 8-bit value, and a 4-bit directive that specifies either +// a splat operation or a rotation. +static bool DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + unsigned ctrl = fieldFromInstruction32(Val, 10, 2); + if (ctrl == 0) { + unsigned byte = fieldFromInstruction32(Val, 8, 2); + unsigned imm = fieldFromInstruction32(Val, 0, 8); + switch (byte) { + case 0: + Inst.addOperand(MCOperand::CreateImm(imm)); + break; + case 1: + Inst.addOperand(MCOperand::CreateImm((imm << 16) | imm)); + break; + case 2: + Inst.addOperand(MCOperand::CreateImm((imm << 24) | (imm << 8))); + break; + case 3: + Inst.addOperand(MCOperand::CreateImm((imm << 24) | (imm << 16) | + (imm << 8) | imm)); + break; + } + } else { + unsigned unrot = fieldFromInstruction32(Val, 0, 7) | 0x80; + unsigned rot = fieldFromInstruction32(Val, 7, 5); + unsigned imm = (unrot >> rot) | (unrot << ((32-rot)&31)); + Inst.addOperand(MCOperand::CreateImm(imm)); + } + + return true; +} + +static bool DecodeThumbBCCTargetOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder){ + Inst.addOperand(MCOperand::CreateImm(Val << 1)); + return true; +} + +static bool DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder){ + Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1))); + return true; +} + +static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Val, + uint64_t Address, const void *Decoder) { + bool isImm = fieldFromInstruction32(Val, 9, 1); + bool isAdd = fieldFromInstruction32(Val, 8, 1); + unsigned imm = fieldFromInstruction32(Val, 0, 8); + + if (!isImm) { + DecodeGPRRegisterClass(Inst, imm, Address, Decoder); + Inst.addOperand(MCOperand::CreateImm(!isAdd << 8)); + } else { + Inst.addOperand(MCOperand::CreateReg(0)); + Inst.addOperand(MCOperand::CreateImm(imm | (!isAdd << 8))); + } + + return true; } Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h Tue Aug 9 15:55:18 2011 @@ -17,15 +17,16 @@ #define ARMDISASSEMBLER_H #include "llvm/MC/MCDisassembler.h" +#include namespace llvm { class MCInst; class MemoryObject; class raw_ostream; - + struct EDInstInfo; - + /// ARMDisassembler - ARM disassembler for all ARM platforms. class ARMDisassembler : public MCDisassembler { public: @@ -44,38 +45,19 @@ const MemoryObject ®ion, uint64_t address, raw_ostream &vStream) const; - + /// getEDInfo - See MCDisassembler. EDInstInfo *getEDInfo() const; private: }; -// Forward declaration. -class ARMBasicMCBuilder; - -/// Session - Keep track of the IT Block progression. -class Session { - friend class ARMBasicMCBuilder; -public: - Session() : ITCounter(0), ITState(0) {} - ~Session() {} - /// InitIT - Initializes ITCounter/ITState. - bool InitIT(unsigned short bits7_0); - /// UpdateIT - Updates ITCounter/ITState as IT Block progresses. - void UpdateIT(); - -private: - unsigned ITCounter; // Possible values: 0, 1, 2, 3, 4. - unsigned ITState; // A2.5.2 Consists of IT[7:5] and IT[4:0] initially. -}; - -/// ThumbDisassembler - Thumb disassembler for all ARM platforms. +/// ARMDisassembler - ARM disassembler for all ARM platforms. class ThumbDisassembler : public MCDisassembler { public: /// Constructor - Initializes the disassembler. /// ThumbDisassembler() : - MCDisassembler(), SO() { + MCDisassembler() { } ~ThumbDisassembler() { @@ -87,13 +69,16 @@ const MemoryObject ®ion, uint64_t address, raw_ostream &vStream) const; - + /// getEDInfo - See MCDisassembler. EDInstInfo *getEDInfo() const; private: - Session SO; + mutable std::vector ITBlock; + void AddThumbPredicate(MCInst&) const; + void UpdateThumbVFPPredicate(MCInst&) const; }; + } // namespace llvm - + #endif Removed: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=137143&view=auto ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (removed) @@ -1,3894 +0,0 @@ -//===- ARMDisassemblerCore.cpp - ARM disassembler helpers -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is part of the ARM Disassembler. -// It contains code to represent the core concepts of Builder and DisassembleFP -// to solve the problem of disassembling an ARM instr. -// -//===----------------------------------------------------------------------===// - -#define DEBUG_TYPE "arm-disassembler" - -#include "ARMDisassemblerCore.h" -#include "MCTargetDesc/ARMAddressingModes.h" -#include "MCTargetDesc/ARMMCExpr.h" -#include "llvm/ADT/APInt.h" -#include "llvm/ADT/APFloat.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -//#define DEBUG(X) do { X; } while (0) - -/// ARMGenInstrInfo.inc - ARMGenInstrInfo.inc contains the static const -/// MCInstrDesc ARMInsts[] definition and the MCOperandInfo[]'s describing the -/// operand info for each ARMInsts[i]. -/// -/// Together with an instruction's encoding format, we can take advantage of the -/// NumOperands and the OpInfo fields of the target instruction description in -/// the quest to build out the MCOperand list for an MCInst. -/// -/// The general guideline is that with a known format, the number of dst and src -/// operands are well-known. The dst is built first, followed by the src -/// operand(s). The operands not yet used at this point are for the Implicit -/// Uses and Defs by this instr. For the Uses part, the pred:$p operand is -/// defined with two components: -/// -/// def pred { // Operand PredicateOperand -/// ValueType Type = OtherVT; -/// string PrintMethod = "printPredicateOperand"; -/// string AsmOperandLowerMethod = ?; -/// dag MIOperandInfo = (ops i32imm, CCR); -/// AsmOperandClass ParserMatchClass = ImmAsmOperand; -/// dag DefaultOps = (ops (i32 14), (i32 zero_reg)); -/// } -/// -/// which is manifested by the MCOperandInfo[] of: -/// -/// { 0, 0|(1<SetErr(-1); - return 0; - } - // For this purpose, we can treat rGPR as if it were GPR. - RegClassID = ARM::GPRRegClassID; - } - - // See also decodeNEONRd(), decodeNEONRn(), decodeNEONRm(). - // A7.3 register encoding - // Qd -> bit[12] == 0 - // Qn -> bit[16] == 0 - // Qm -> bit[0] == 0 - // - // If one of these bits is 1, the instruction is UNDEFINED. - if (RegClassID == ARM::QPRRegClassID && slice(RawRegister, 0, 0) == 1) { - B->SetErr(-1); - return 0; - } - unsigned RegNum = - RegClassID == ARM::QPRRegClassID ? RawRegister >> 1 : RawRegister; - - switch (RegNum) { - default: - break; - case 0: - switch (RegClassID) { - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R0; - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID: - case ARM::DPR_VFP2RegClassID: - return ARM::D0; - case ARM::QPRRegClassID: case ARM::QPR_8RegClassID: - case ARM::QPR_VFP2RegClassID: - return ARM::Q0; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S0; - } - break; - case 1: - switch (RegClassID) { - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R1; - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID: - case ARM::DPR_VFP2RegClassID: - return ARM::D1; - case ARM::QPRRegClassID: case ARM::QPR_8RegClassID: - case ARM::QPR_VFP2RegClassID: - return ARM::Q1; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S1; - } - break; - case 2: - switch (RegClassID) { - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R2; - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID: - case ARM::DPR_VFP2RegClassID: - return ARM::D2; - case ARM::QPRRegClassID: case ARM::QPR_8RegClassID: - case ARM::QPR_VFP2RegClassID: - return ARM::Q2; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S2; - } - break; - case 3: - switch (RegClassID) { - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R3; - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID: - case ARM::DPR_VFP2RegClassID: - return ARM::D3; - case ARM::QPRRegClassID: case ARM::QPR_8RegClassID: - case ARM::QPR_VFP2RegClassID: - return ARM::Q3; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S3; - } - break; - case 4: - switch (RegClassID) { - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R4; - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID: - case ARM::DPR_VFP2RegClassID: - return ARM::D4; - case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q4; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S4; - } - break; - case 5: - switch (RegClassID) { - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R5; - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID: - case ARM::DPR_VFP2RegClassID: - return ARM::D5; - case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q5; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S5; - } - break; - case 6: - switch (RegClassID) { - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R6; - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID: - case ARM::DPR_VFP2RegClassID: - return ARM::D6; - case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q6; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S6; - } - break; - case 7: - switch (RegClassID) { - case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R7; - case ARM::DPRRegClassID: case ARM::DPR_8RegClassID: - case ARM::DPR_VFP2RegClassID: - return ARM::D7; - case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q7; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S7; - } - break; - case 8: - switch (RegClassID) { - case ARM::GPRRegClassID: return ARM::R8; - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D8; - case ARM::QPRRegClassID: return ARM::Q8; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S8; - } - break; - case 9: - switch (RegClassID) { - case ARM::GPRRegClassID: return ARM::R9; - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D9; - case ARM::QPRRegClassID: return ARM::Q9; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S9; - } - break; - case 10: - switch (RegClassID) { - case ARM::GPRRegClassID: return ARM::R10; - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D10; - case ARM::QPRRegClassID: return ARM::Q10; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S10; - } - break; - case 11: - switch (RegClassID) { - case ARM::GPRRegClassID: return ARM::R11; - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D11; - case ARM::QPRRegClassID: return ARM::Q11; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S11; - } - break; - case 12: - switch (RegClassID) { - case ARM::GPRRegClassID: return ARM::R12; - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D12; - case ARM::QPRRegClassID: return ARM::Q12; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S12; - } - break; - case 13: - switch (RegClassID) { - case ARM::GPRRegClassID: return ARM::SP; - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D13; - case ARM::QPRRegClassID: return ARM::Q13; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S13; - } - break; - case 14: - switch (RegClassID) { - case ARM::GPRRegClassID: return ARM::LR; - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D14; - case ARM::QPRRegClassID: return ARM::Q14; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S14; - } - break; - case 15: - switch (RegClassID) { - case ARM::GPRRegClassID: return ARM::PC; - case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D15; - case ARM::QPRRegClassID: return ARM::Q15; - case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S15; - } - break; - case 16: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D16; - case ARM::SPRRegClassID: return ARM::S16; - } - break; - case 17: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D17; - case ARM::SPRRegClassID: return ARM::S17; - } - break; - case 18: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D18; - case ARM::SPRRegClassID: return ARM::S18; - } - break; - case 19: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D19; - case ARM::SPRRegClassID: return ARM::S19; - } - break; - case 20: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D20; - case ARM::SPRRegClassID: return ARM::S20; - } - break; - case 21: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D21; - case ARM::SPRRegClassID: return ARM::S21; - } - break; - case 22: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D22; - case ARM::SPRRegClassID: return ARM::S22; - } - break; - case 23: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D23; - case ARM::SPRRegClassID: return ARM::S23; - } - break; - case 24: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D24; - case ARM::SPRRegClassID: return ARM::S24; - } - break; - case 25: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D25; - case ARM::SPRRegClassID: return ARM::S25; - } - break; - case 26: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D26; - case ARM::SPRRegClassID: return ARM::S26; - } - break; - case 27: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D27; - case ARM::SPRRegClassID: return ARM::S27; - } - break; - case 28: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D28; - case ARM::SPRRegClassID: return ARM::S28; - } - break; - case 29: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D29; - case ARM::SPRRegClassID: return ARM::S29; - } - break; - case 30: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D30; - case ARM::SPRRegClassID: return ARM::S30; - } - break; - case 31: - switch (RegClassID) { - case ARM::DPRRegClassID: return ARM::D31; - case ARM::SPRRegClassID: return ARM::S31; - } - break; - } - DEBUG(errs() << "Invalid (RegClassID, RawRegister) combination\n"); - // Encoding error. Mark the builder with error code != 0. - B->SetErr(-1); - return 0; -} - -/////////////////////////////// -// // -// Utility Functions // -// // -/////////////////////////////// - -// Extract/Decode Rd: Inst{15-12}. -static inline unsigned decodeRd(uint32_t insn) { - return (insn >> ARMII::RegRdShift) & ARMII::GPRRegMask; -} - -// Extract/Decode Rn: Inst{19-16}. -static inline unsigned decodeRn(uint32_t insn) { - return (insn >> ARMII::RegRnShift) & ARMII::GPRRegMask; -} - -// Extract/Decode Rm: Inst{3-0}. -static inline unsigned decodeRm(uint32_t insn) { - return (insn & ARMII::GPRRegMask); -} - -// Extract/Decode Rs: Inst{11-8}. -static inline unsigned decodeRs(uint32_t insn) { - return (insn >> ARMII::RegRsShift) & ARMII::GPRRegMask; -} - -static inline unsigned getCondField(uint32_t insn) { - return (insn >> ARMII::CondShift); -} - -static inline unsigned getIBit(uint32_t insn) { - return (insn >> ARMII::I_BitShift) & 1; -} - -static inline unsigned getAM3IBit(uint32_t insn) { - return (insn >> ARMII::AM3_I_BitShift) & 1; -} - -static inline unsigned getPBit(uint32_t insn) { - return (insn >> ARMII::P_BitShift) & 1; -} - -static inline unsigned getUBit(uint32_t insn) { - return (insn >> ARMII::U_BitShift) & 1; -} - -static inline unsigned getPUBits(uint32_t insn) { - return (insn >> ARMII::U_BitShift) & 3; -} - -static inline unsigned getSBit(uint32_t insn) { - return (insn >> ARMII::S_BitShift) & 1; -} - -static inline unsigned getWBit(uint32_t insn) { - return (insn >> ARMII::W_BitShift) & 1; -} - -static inline unsigned getDBit(uint32_t insn) { - return (insn >> ARMII::D_BitShift) & 1; -} - -static inline unsigned getNBit(uint32_t insn) { - return (insn >> ARMII::N_BitShift) & 1; -} - -static inline unsigned getMBit(uint32_t insn) { - return (insn >> ARMII::M_BitShift) & 1; -} - -// See A8.4 Shifts applied to a register. -// A8.4.2 Register controlled shifts. -// -// getShiftOpcForBits - getShiftOpcForBits translates from the ARM encoding bits -// into llvm enums for shift opcode. The API clients should pass in the value -// encoded with two bits, so the assert stays to signal a wrong API usage. -// -// A8-12: DecodeRegShift() -static inline ARM_AM::ShiftOpc getShiftOpcForBits(unsigned bits) { - switch (bits) { - default: assert(0 && "No such value"); return ARM_AM::no_shift; - case 0: return ARM_AM::lsl; - case 1: return ARM_AM::lsr; - case 2: return ARM_AM::asr; - case 3: return ARM_AM::ror; - } -} - -// See A8.4 Shifts applied to a register. -// A8.4.1 Constant shifts. -// -// getImmShiftSE - getImmShiftSE translates from the raw ShiftOpc and raw Imm5 -// encodings into the intended ShiftOpc and shift amount. -// -// A8-11: DecodeImmShift() -static inline void getImmShiftSE(ARM_AM::ShiftOpc &ShOp, unsigned &ShImm) { - if (ShImm != 0) - return; - switch (ShOp) { - case ARM_AM::no_shift: - case ARM_AM::rrx: - break; - case ARM_AM::lsl: - ShOp = ARM_AM::no_shift; - break; - case ARM_AM::lsr: - case ARM_AM::asr: - ShImm = 32; - break; - case ARM_AM::ror: - ShOp = ARM_AM::rrx; - break; - } -} - -// getAMSubModeForBits - getAMSubModeForBits translates from the ARM encoding -// bits Inst{24-23} (P(24) and U(23)) into llvm enums for AMSubMode. The API -// clients should pass in the value encoded with two bits, so the assert stays -// to signal a wrong API usage. -static inline ARM_AM::AMSubMode getAMSubModeForBits(unsigned bits) { - switch (bits) { - default: assert(0 && "No such value"); return ARM_AM::bad_am_submode; - case 1: return ARM_AM::ia; // P=0 U=1 - case 3: return ARM_AM::ib; // P=1 U=1 - case 0: return ARM_AM::da; // P=0 U=0 - case 2: return ARM_AM::db; // P=1 U=0 - } -} - -//////////////////////////////////////////// -// // -// Disassemble function definitions // -// // -//////////////////////////////////////////// - -/// There is a separate Disassemble*Frm function entry for disassembly of an ARM -/// instr into a list of MCOperands in the appropriate order, with possible dst, -/// followed by possible src(s). -/// -/// The processing of the predicate, and the 'S' modifier bit, if MI modifies -/// the CPSR, is factored into ARMBasicMCBuilder's method named -/// TryPredicateAndSBitModifier. - -static bool DisassemblePseudo(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO) { - - assert(0 && "Unexpected pseudo instruction!"); - return false; -} - -// A8.6.94 MLA -// if d == 15 || n == 15 || m == 15 || a == 15 then UNPREDICTABLE; -// -// A8.6.105 MUL -// if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; -// -// A8.6.246 UMULL -// if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE; -// if dHi == dLo then UNPREDICTABLE; -static bool BadRegsMulFrm(unsigned Opcode, uint32_t insn) { - unsigned R19_16 = slice(insn, 19, 16); - unsigned R15_12 = slice(insn, 15, 12); - unsigned R11_8 = slice(insn, 11, 8); - unsigned R3_0 = slice(insn, 3, 0); - switch (Opcode) { - default: - // Did we miss an opcode? - DEBUG(errs() << "BadRegsMulFrm: unexpected opcode!"); - return false; - case ARM::MLA: case ARM::MLS: case ARM::SMLABB: case ARM::SMLABT: - case ARM::SMLATB: case ARM::SMLATT: case ARM::SMLAWB: case ARM::SMLAWT: - case ARM::SMMLA: case ARM::SMMLAR: case ARM::SMMLS: case ARM::SMMLSR: - case ARM::USADA8: - if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15) - return true; - return false; - case ARM::MUL: case ARM::SMMUL: case ARM::SMMULR: - case ARM::SMULBB: case ARM::SMULBT: case ARM::SMULTB: case ARM::SMULTT: - case ARM::SMULWB: case ARM::SMULWT: case ARM::SMUAD: case ARM::SMUADX: - // A8.6.167 SMLAD & A8.6.172 SMLSD - case ARM::SMLAD: case ARM::SMLADX: case ARM::SMLSD: case ARM::SMLSDX: - case ARM::USAD8: - if (R19_16 == 15 || R11_8 == 15 || R3_0 == 15) - return true; - return false; - case ARM::SMLAL: case ARM::SMULL: case ARM::UMAAL: case ARM::UMLAL: - case ARM::UMULL: - case ARM::SMLALBB: case ARM::SMLALBT: case ARM::SMLALTB: case ARM::SMLALTT: - case ARM::SMLALD: case ARM::SMLALDX: case ARM::SMLSLD: case ARM::SMLSLDX: - if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15) - return true; - if (R19_16 == R15_12) - return true; - return false;; - } -} - -// Multiply Instructions. -// MLA, MLS, SMLABB, SMLABT, SMLATB, SMLATT, SMLAWB, SMLAWT, SMMLA, SMMLAR, -// SMMLS, SMMLAR, SMLAD, SMLADX, SMLSD, SMLSDX, and USADA8 (for convenience): -// Rd{19-16} Rn{3-0} Rm{11-8} Ra{15-12} -// But note that register checking for {SMLAD, SMLADX, SMLSD, SMLSDX} is -// only for {d, n, m}. -// -// MUL, SMMUL, SMMULR, SMULBB, SMULBT, SMULTB, SMULTT, SMULWB, SMULWT, SMUAD, -// SMUADX, and USAD8 (for convenience): -// Rd{19-16} Rn{3-0} Rm{11-8} -// -// SMLAL, SMULL, UMAAL, UMLAL, UMULL, SMLALBB, SMLALBT, SMLALTB, SMLALTT, -// SMLALD, SMLADLX, SMLSLD, SMLSLDX: -// RdLo{15-12} RdHi{19-16} Rn{3-0} Rm{11-8} -// -// The mapping of the multiply registers to the "regular" ARM registers, where -// there are convenience decoder functions, is: -// -// Inst{15-12} => Rd -// Inst{19-16} => Rn -// Inst{3-0} => Rm -// Inst{11-8} => Rs -static bool DisassembleMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - unsigned short NumDefs = MCID.getNumDefs(); - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumDefs > 0 && "NumDefs should be greater than 0 for MulFrm"); - assert(NumOps >= 3 - && OpInfo[0].RegClass == ARM::GPRRegClassID - && OpInfo[1].RegClass == ARM::GPRRegClassID - && OpInfo[2].RegClass == ARM::GPRRegClassID - && "Expect three register operands"); - - // Sanity check for the register encodings. - if (BadRegsMulFrm(Opcode, insn)) - return false; - - // Instructions with two destination registers have RdLo{15-12} first. - if (NumDefs == 2) { - assert(NumOps >= 4 && OpInfo[3].RegClass == ARM::GPRRegClassID && - "Expect 4th register operand"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - } - - // The destination register: RdHi{19-16} or Rd{19-16}. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - - // The two src regsiters: Rn{3-0}, then Rm{11-8}. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRs(insn)))); - OpIdx += 3; - - // Many multiply instructions (e.g., MLA) have three src registers. - // The third register operand is Ra{15-12}. - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - } - - return true; -} - -// Helper routines for disassembly of coprocessor instructions. - -static bool LdStCopOpcode(unsigned Opcode) { - if ((Opcode >= ARM::LDC2L_OFFSET && Opcode <= ARM::LDC_PRE) || - (Opcode >= ARM::STC2L_OFFSET && Opcode <= ARM::STC_PRE)) - return true; - return false; -} -static bool CoprocessorOpcode(unsigned Opcode) { - if (LdStCopOpcode(Opcode)) - return true; - - switch (Opcode) { - default: - return false; - case ARM::CDP: case ARM::CDP2: - case ARM::MCR: case ARM::MCR2: case ARM::MRC: case ARM::MRC2: - case ARM::MCRR: case ARM::MCRR2: case ARM::MRRC: case ARM::MRRC2: - return true; - } -} -static inline unsigned GetCoprocessor(uint32_t insn) { - return slice(insn, 11, 8); -} -static inline unsigned GetCopOpc1(uint32_t insn, bool CDP) { - return CDP ? slice(insn, 23, 20) : slice(insn, 23, 21); -} -static inline unsigned GetCopOpc2(uint32_t insn) { - return slice(insn, 7, 5); -} -static inline unsigned GetCopOpc(uint32_t insn) { - return slice(insn, 7, 4); -} -// Most of the operands are in immediate forms, except Rd and Rn, which are ARM -// core registers. -// -// CDP, CDP2: cop opc1 CRd CRn CRm opc2 -// -// MCR, MCR2, MRC, MRC2: cop opc1 Rd CRn CRm opc2 -// -// MCRR, MCRR2, MRRC, MRRc2: cop opc Rd Rn CRm -// -// LDC_OFFSET, LDC_PRE, LDC_POST: cop CRd Rn R0 [+/-]imm8:00 -// and friends -// STC_OFFSET, STC_PRE, STC_POST: cop CRd Rn R0 [+/-]imm8:00 -// and friends -// <-- addrmode2 --> -// -// LDC_OPTION: cop CRd Rn imm8 -// and friends -// STC_OPTION: cop CRd Rn imm8 -// and friends -// -static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 4 && "Num of operands >= 4 for coprocessor instr"); - - unsigned &OpIdx = NumOpsAdded; - // A8.6.92 - // if coproc == '101x' then SEE "Advanced SIMD and VFP" - // But since the special instructions have more explicit encoding bits - // specified, if coproc == 10 or 11, we should reject it as invalid. - unsigned coproc = GetCoprocessor(insn); - if ((Opcode == ARM::MCR || Opcode == ARM::MCRR || - Opcode == ARM::MRC || Opcode == ARM::MRRC) && - (coproc == 10 || coproc == 11)) { - DEBUG(errs() << "Encoding error: coproc == 10 or 11 for MCR[R]/MR[R]C\n"); - return false; - } - - bool OneCopOpc = (Opcode == ARM::MCRR || Opcode == ARM::MCRR2 || - Opcode == ARM::MRRC || Opcode == ARM::MRRC2); - - // CDP/CDP2 has no GPR operand; the opc1 operand is also wider (Inst{23-20}). - bool NoGPR = (Opcode == ARM::CDP || Opcode == ARM::CDP2); - bool LdStCop = LdStCopOpcode(Opcode); - bool RtOut = (Opcode == ARM::MRC || Opcode == ARM::MRC2); - - OpIdx = 0; - - if (RtOut) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - } - MI.addOperand(MCOperand::CreateImm(coproc)); - ++OpIdx; - - if (LdStCop) { - // Unindex if P:W = 0b00 --> _OPTION variant - unsigned PW = getPBit(insn) << 1 | getWBit(insn); - - MI.addOperand(MCOperand::CreateImm(decodeRd(insn))); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - OpIdx += 2; - - if (PW) { - MI.addOperand(MCOperand::CreateReg(0)); - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; - const MCInstrDesc &MCID = ARMInsts[Opcode]; - unsigned IndexMode = - (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; - unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2, - ARM_AM::no_shift, IndexMode); - MI.addOperand(MCOperand::CreateImm(Offset)); - OpIdx += 2; - } else { - MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 0))); - ++OpIdx; - } - } else { - MI.addOperand(MCOperand::CreateImm(OneCopOpc ? GetCopOpc(insn) - : GetCopOpc1(insn, NoGPR))); - ++OpIdx; - - if (!RtOut) { - MI.addOperand(NoGPR ? MCOperand::CreateImm(decodeRd(insn)) - : MCOperand::CreateReg( - getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - } - - MI.addOperand(OneCopOpc ? MCOperand::CreateReg( - getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn))) - : MCOperand::CreateImm(decodeRn(insn))); - - MI.addOperand(MCOperand::CreateImm(decodeRm(insn))); - - OpIdx += 2; - - if (!OneCopOpc) { - MI.addOperand(MCOperand::CreateImm(GetCopOpc2(insn))); - ++OpIdx; - } - } - - return true; -} - -// Branch Instructions. -// BL: SignExtend(Imm24:'00', 32) -// Bcc, BL_pred: SignExtend(Imm24:'00', 32) Pred0 Pred1 -// SMC: ZeroExtend(imm4, 32) -// SVC: ZeroExtend(Imm24, 32) -// -// Various coprocessor instructions are assigned BrFrm arbitrarily. -// Delegates to DisassembleCoprocessor() helper function. -// -// MRS/MRSsys: Rd -// MSR/MSRsys: Rm mask=Inst{19-16} -// BXJ: Rm -// MSRi/MSRsysi: so_imm -// SRS: mode_imm -// RFE: Rn -static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - if (CoprocessorOpcode(Opcode)) - return DisassembleCoprocessor(MI, Opcode, insn, NumOps, NumOpsAdded, B); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - // MRS and MRSsys take one GPR reg Rd. - if (Opcode == ARM::MRS || Opcode == ARM::MRSsys) { - assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - NumOpsAdded = 1; - return true; - } - // BXJ takes one GPR reg Rm. - if (Opcode == ARM::BXJ) { - assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - NumOpsAdded = 1; - return true; - } - // MSR take a mask, followed by one GPR reg Rm. The mask contains the R Bit in - // bit 4, and the special register fields in bits 3-0. - if (Opcode == ARM::MSR) { - assert(NumOps >= 1 && OpInfo[1].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ | - slice(insn, 19, 16) /* Special Reg */ )); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - NumOpsAdded = 2; - return true; - } - // MSRi take a mask, followed by one so_imm operand. The mask contains the - // R Bit in bit 4, and the special register fields in bits 3-0. - if (Opcode == ARM::MSRi) { - // A5.2.11 MSR (immediate), and hints & B6.1.6 MSR (immediate) - // The hints instructions have more specific encodings, so if mask == 0, - // we should reject this as an invalid instruction. - if (slice(insn, 19, 16) == 0) - return false; - MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ | - slice(insn, 19, 16) /* Special Reg */ )); - // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0. - // A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}. - // See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot(). - unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF; - unsigned Imm = insn & 0xFF; - MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot))); - NumOpsAdded = 2; - return true; - } - if (Opcode == ARM::SRSDA || Opcode == ARM::SRSDB || - Opcode == ARM::SRSIA || Opcode == ARM::SRSIB || - Opcode == ARM::SRSDA_UPD || Opcode == ARM::SRSDB_UPD || - Opcode == ARM::SRSIA_UPD || Opcode == ARM::SRSIB_UPD) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); - NumOpsAdded = 1; - return true; - } - if (Opcode == ARM::RFEDA || Opcode == ARM::RFEDB || - Opcode == ARM::RFEIA || Opcode == ARM::RFEIB || - Opcode == ARM::RFEDA_UPD || Opcode == ARM::RFEDB_UPD || - Opcode == ARM::RFEIA_UPD || Opcode == ARM::RFEIB_UPD) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - NumOpsAdded = 1; - return true; - } - - assert((Opcode == ARM::Bcc || Opcode == ARM::BL || Opcode == ARM::BL_pred - || Opcode == ARM::SMC || Opcode == ARM::SVC) && - "Unexpected Opcode"); - - assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected"); - - int Imm32 = 0; - if (Opcode == ARM::SMC) { - // ZeroExtend(imm4, 32) where imm24 = Inst{3-0}. - Imm32 = slice(insn, 3, 0); - } else if (Opcode == ARM::SVC) { - // ZeroExtend(imm24, 32) where imm24 = Inst{23-0}. - Imm32 = slice(insn, 23, 0); - } else { - // SignExtend(imm24:'00', 32) where imm24 = Inst{23-0}. - unsigned Imm26 = slice(insn, 23, 0) << 2; - //Imm32 = signextend(Imm26); - Imm32 = SignExtend32<26>(Imm26); - } - - MI.addOperand(MCOperand::CreateImm(Imm32)); - NumOpsAdded = 1; - - return true; -} - -// Misc. Branch Instructions. -// BX_RET, MOVPCLR -// BLX, BLX_pred, BX, BX_pred -// BLXi -static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - // BX_RET and MOVPCLR have only two predicate operands; do an early return. - if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR) - return true; - - // BLX and BX take one GPR reg. - if (Opcode == ARM::BLX || Opcode == ARM::BLX_pred || - Opcode == ARM::BX || Opcode == ARM::BX_pred) { - assert(NumOps >= 1 && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - OpIdx = 1; - return true; - } - - // BLXi takes imm32 (the PC offset). - if (Opcode == ARM::BLXi) { - assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected"); - // SignExtend(imm24:H:'0', 32) where imm24 = Inst{23-0} and H = Inst{24}. - unsigned Imm26 = slice(insn, 23, 0) << 2 | slice(insn, 24, 24) << 1; - int Imm32 = SignExtend32<26>(Imm26); - MI.addOperand(MCOperand::CreateImm(Imm32)); - OpIdx = 1; - return true; - } - - return false; -} - -static inline bool getBFCInvMask(uint32_t insn, uint32_t &mask) { - uint32_t lsb = slice(insn, 11, 7); - uint32_t msb = slice(insn, 20, 16); - uint32_t Val = 0; - if (msb < lsb) { - DEBUG(errs() << "Encoding error: msb < lsb\n"); - return false; - } - - for (uint32_t i = lsb; i <= msb; ++i) - Val |= (1 << i); - mask = ~Val; - return true; -} - -// Standard data-processing instructions allow PC as a register specifier, -// but we should reject other DPFrm instructions with PC as registers. -static bool BadRegsDPFrm(unsigned Opcode, uint32_t insn) { - switch (Opcode) { - default: - // Did we miss an opcode? - if (decodeRd(insn) == 15 || decodeRn(insn) == 15 || decodeRm(insn) == 15) { - DEBUG(errs() << "DPFrm with bad reg specifier(s)\n"); - return true; - } - case ARM::ADCrr: case ARM::ADDSrr: case ARM::ADDrr: case ARM::ANDrr: - case ARM::BICrr: case ARM::CMNzrr: case ARM::CMPrr: case ARM::EORrr: - case ARM::ORRrr: case ARM::RSBrr: case ARM::RSCrr: case ARM::SBCrr: - case ARM::SUBSrr: case ARM::SUBrr: case ARM::TEQrr: case ARM::TSTrr: - return false; - } -} - -// A major complication is the fact that some of the saturating add/subtract -// operations have Rd Rm Rn, instead of the "normal" Rd Rn Rm. -// They are QADD, QDADD, QDSUB, and QSUB. -static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - unsigned short NumDefs = MCID.getNumDefs(); - bool isUnary = isUnaryDP(MCID.TSFlags); - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - // Disassemble register def if there is one. - if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - } - - // Now disassemble the src operands. - if (OpIdx >= NumOps) - return false; - - // Special-case handling of BFC/BFI/SBFX/UBFX. - if (Opcode == ARM::BFC || Opcode == ARM::BFI) { - // A8.6.17 BFC & A8.6.18 BFI - // Sanity check Rd. - if (decodeRd(insn) == 15) - return false; - MI.addOperand(MCOperand::CreateReg(0)); - if (Opcode == ARM::BFI) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - ++OpIdx; - } - uint32_t mask = 0; - if (!getBFCInvMask(insn, mask)) - return false; - - MI.addOperand(MCOperand::CreateImm(mask)); - OpIdx += 2; - return true; - } - if (Opcode == ARM::SBFX || Opcode == ARM::UBFX) { - // Sanity check Rd and Rm. - if (decodeRd(insn) == 15 || decodeRm(insn) == 15) - return false; - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 7))); - MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 16))); - OpIdx += 3; - return true; - } - - bool RmRn = (Opcode == ARM::QADD || Opcode == ARM::QDADD || - Opcode == ARM::QDSUB || Opcode == ARM::QSUB); - - // BinaryDP has an Rn operand. - if (!isUnary) { - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::GPRRegClassID, - RmRn ? decodeRm(insn) : decodeRn(insn)))); - ++OpIdx; - } - - // If this is a two-address operand, skip it, e.g., MOVCCr operand 1. - if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) { - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - // Now disassemble operand 2. - if (OpIdx >= NumOps) - return false; - - if (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) { - // We have a reg/reg form. - // Assert disabled because saturating operations, e.g., A8.6.127 QASX, are - // routed here as well. - // assert(getIBit(insn) == 0 && "I_Bit != '0' reg/reg form"); - if (BadRegsDPFrm(Opcode, insn)) - return false; - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::GPRRegClassID, - RmRn? decodeRn(insn) : decodeRm(insn)))); - ++OpIdx; - } else if (Opcode == ARM::MOVi16 || Opcode == ARM::MOVTi16) { - // These two instructions don't allow d as 15. - if (decodeRd(insn) == 15) - return false; - // 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); - if (!B->tryAddingSymbolicOperand(Imm16, 4, MI)) - MI.addOperand(MCOperand::CreateImm(Imm16)); - ++OpIdx; - } else { - // We have a reg/imm form. - // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0. - // A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}. - // See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot(). - assert(getIBit(insn) == 1 && "I_Bit != '1' reg/imm form"); - unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF; - unsigned Imm = insn & 0xFF; - MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot))); - ++OpIdx; - } - - return true; -} - -static bool DisassembleDPSoRegRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - unsigned short NumDefs = MCID.getNumDefs(); - bool isUnary = isUnaryDP(MCID.TSFlags); - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - // Disassemble register def if there is one. - if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - } - - // Disassemble the src operands. - if (OpIdx >= NumOps) - return false; - - // BinaryDP has an Rn operand. - if (!isUnary) { - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - // If this is a two-address operand, skip it, e.g., MOVCCs operand 1. - if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) { - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - // Disassemble operand 2, which consists of three components. - if (OpIdx + 2 >= NumOps) - return false; - - assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) && - (OpInfo[OpIdx+1].RegClass == ARM::GPRRegClassID) && - (OpInfo[OpIdx+2].RegClass < 0) && - "Expect 3 reg operands"); - - // Register-controlled shifts have Inst{7} = 0 and Inst{4} = 1. - unsigned Rs = slice(insn, 4, 4); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - if (Rs) { - // If Inst{7} != 0, we should reject this insn as an invalid encoding. - if (slice(insn, 7, 7)) - return false; - - // A8.6.3 ADC (register-shifted register) - // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE; - // - // This also accounts for shift instructions (register) where, fortunately, - // Inst{19-16} = 0b0000. - // A8.6.89 LSL (register) - // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE; - if (decodeRd(insn) == 15 || decodeRn(insn) == 15 || - decodeRm(insn) == 15 || decodeRs(insn) == 15) - return false; - - // Register-controlled shifts: [Rm, Rs, shift]. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRs(insn)))); - // Inst{6-5} encodes the shift opcode. - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5)); - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, 0))); - } else { - // Constant shifts: [Rm, reg0, shift_imm]. - MI.addOperand(MCOperand::CreateReg(0)); // NoRegister - // Inst{6-5} encodes the shift opcode. - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5)); - // Inst{11-7} encodes the imm5 shift amount. - unsigned ShImm = slice(insn, 11, 7); - - // A8.4.1. Possible rrx or shift amount of 32... - getImmShiftSE(ShOp, ShImm); - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShImm))); - } - OpIdx += 3; - - return true; -} - -static bool DisassembleDPSoRegImmFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - unsigned short NumDefs = MCID.getNumDefs(); - bool isUnary = isUnaryDP(MCID.TSFlags); - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - // Disassemble register def if there is one. - if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - } - - // Disassemble the src operands. - if (OpIdx >= NumOps) - return false; - - // BinaryDP has an Rn operand. - if (!isUnary) { - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - // If this is a two-address operand, skip it, e.g., MOVCCs operand 1. - if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) { - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - // Disassemble operand 2, which consists of two components. - if (OpIdx + 1 >= NumOps) - return false; - - assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) && - (OpInfo[OpIdx+1].RegClass < 0) && - "Expect 2 reg operands"); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - - // Inst{6-5} encodes the shift opcode. - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5)); - // Inst{11-7} encodes the imm5 shift amount. - unsigned ShImm = slice(insn, 11, 7); - - // A8.4.1. Possible rrx or shift amount of 32... - getImmShiftSE(ShOp, ShImm); - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShImm))); - - OpIdx += 2; - - 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) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - bool isPrePost = isPrePostLdSt(MCID.TSFlags); - const MCOperandInfo *OpInfo = MCID.OpInfo; - if (!OpInfo) return false; - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(((!isStore && MCID.getNumDefs() > 0) || - (isStore && (MCID.getNumDefs() == 0 || isPrePost))) - && "Invalid arguments"); - - // Operand 0 of a pre- and post-indexed store is the address base writeback. - if (isPrePost && isStore) { - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - // Disassemble the dst/src operand. - if (OpIdx >= NumOps) - return false; - - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - - // After dst of a pre- and post-indexed load is the address base writeback. - if (isPrePost && !isStore) { - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - // Disassemble the base operand. - if (OpIdx >= NumOps) - return false; - - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) - && "Index mode or tied_to operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - - // For reg/reg form, base reg is followed by +/- reg shop imm. - // For immediate form, it is followed by +/- imm12. - // See also ARMAddressingModes.h (Addressing Mode #2). - 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 = - (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; - if (getIBit(insn) == 0) { - // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2). - // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already - // been populated. - if (isPrePost) { - MI.addOperand(MCOperand::CreateReg(0)); - OpIdx += 1; - } - - unsigned Imm12 = slice(insn, 11, 0); - if (Opcode == ARM::LDRBi12 || Opcode == ARM::LDRi12 || - Opcode == ARM::STRBi12 || Opcode == ARM::STRi12) { - // Disassemble the 12-bit immediate offset, which is the second operand in - // $addrmode_imm12 => (ops GPR:$base, i32imm:$offsimm). - int Offset = AddrOpcode == ARM_AM::add ? 1 * Imm12 : -1 * Imm12; - MI.addOperand(MCOperand::CreateImm(Offset)); - } else { - // Disassemble the 12-bit immediate offset, which is the second operand in - // $am2offset => (ops GPR, i32imm). - unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift, - IndexMode); - MI.addOperand(MCOperand::CreateImm(Offset)); - } - OpIdx += 1; - } else { - // If Inst{25} = 1 and Inst{4} != 0, we should reject this as invalid. - if (slice(insn,4,4) == 1) - return false; - - // Disassemble the offset reg (Rm), shift type, and immediate shift length. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - // Inst{6-5} encodes the shift opcode. - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5)); - // Inst{11-7} encodes the imm5 shift amount. - unsigned ShImm = slice(insn, 11, 7); - - // A8.4.1. Possible rrx or shift amount of 32... - getImmShiftSE(ShOp, ShImm); - MI.addOperand(MCOperand::CreateImm( - ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp, IndexMode))); - OpIdx += 2; - } - - return true; -} - -static bool DisassembleLdFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false, B); -} - -static bool DisassembleStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B); -} - -static bool HasDualReg(unsigned Opcode) { - switch (Opcode) { - default: - return false; - case ARM::LDRD: case ARM::LDRD_PRE: case ARM::LDRD_POST: - case ARM::STRD: case ARM::STRD_PRE: case ARM::STRD_POST: - return true; - } -} - -static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - bool isPrePost = isPrePostLdSt(MCID.TSFlags); - const MCOperandInfo *OpInfo = MCID.OpInfo; - if (!OpInfo) return false; - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(((!isStore && MCID.getNumDefs() > 0) || - (isStore && (MCID.getNumDefs() == 0 || isPrePost))) - && "Invalid arguments"); - - // Operand 0 of a pre- and post-indexed store is the address base writeback. - if (isPrePost && isStore) { - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - // Disassemble the dst/src operand. - if (OpIdx >= NumOps) - return false; - - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - - // Fill in LDRD and STRD's second operand Rt operand. - if (HasDualReg(Opcode)) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn) + 1))); - ++OpIdx; - } - - // After dst of a pre- and post-indexed load is the address base writeback. - if (isPrePost && !isStore) { - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - // Disassemble the base operand. - if (OpIdx >= NumOps) - return false; - - assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) - && "Offset mode or tied_to operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - - // For reg/reg form, base reg is followed by +/- reg. - // For immediate form, it is followed by +/- imm8. - if (OpIdx + 1 >= NumOps) - return false; - - unsigned IndexMode = - (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; - if (getAM3IBit(insn) == 1) { - // FIXME: Conditional while in the midst of refactoring addrmode3. Will - // go away entirely when the rest are converted. - if (Opcode != ARM::STRHTi && Opcode != ARM::LDRSBTi && - Opcode != ARM::LDRHTi && Opcode != ARM::LDRSHTi) { - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - // Disassemble the 8-bit immediate offset (postidx_imm8). - unsigned Imm4H = (insn >> ARMII::ImmHiShift) & 0xF; - unsigned Imm4L = insn & 0xF; - unsigned Offset; - // FIXME: Remove the 'else' once done w/ addrmode3 refactor. - if (Opcode == ARM::STRHTi || Opcode == ARM::LDRSBTi || - Opcode == ARM::LDRHTi || Opcode == ARM::LDRSHTi) - Offset = (Imm4H << 4) | Imm4L | (getUBit(insn) << 8); - else - Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L, - IndexMode); - - MI.addOperand(MCOperand::CreateImm(Offset)); - ++OpIdx; - } else { - // Disassemble the offset reg (Rm). - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - // FIXME: Remove the 'else' once done w/ addrmode3 refactor. - if (Opcode == ARM::STRHTr || Opcode == ARM::LDRSBTr || - Opcode == ARM::LDRHTr || Opcode == ARM::LDRSHTr) - MI.addOperand(MCOperand::CreateImm(getUBit(insn))); - else { - unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0); - MI.addOperand(MCOperand::CreateImm(Offset)); - } - OpIdx += 2; - } - - return true; -} - -static bool DisassembleLdMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false, - B); -} - -static bool DisassembleStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B); -} - -// The algorithm for disassembly of LdStMulFrm is different from others because -// it explicitly populates the two predicate operands after the base register. -// After that, we need to populate the reglist with each affected register -// encoded as an MCOperand. -static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 4 && "LdStMulFrm expects NumOps >= 4"); - NumOpsAdded = 0; - - unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)); - - // Writeback to base, if necessary. - if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::STMIA_UPD || - Opcode == ARM::LDMDA_UPD || Opcode == ARM::STMDA_UPD || - Opcode == ARM::LDMDB_UPD || Opcode == ARM::STMDB_UPD || - Opcode == ARM::LDMIB_UPD || Opcode == ARM::STMIB_UPD) { - MI.addOperand(MCOperand::CreateReg(Base)); - ++NumOpsAdded; - } - - // Add the base register operand. - MI.addOperand(MCOperand::CreateReg(Base)); - - // Handling the two predicate operands before the reglist. - int64_t CondVal = getCondField(insn); - if (CondVal == 0xF) - return false; - MI.addOperand(MCOperand::CreateImm(CondVal)); - MI.addOperand(MCOperand::CreateReg(ARM::CPSR)); - - NumOpsAdded += 3; - - // Fill the variadic part of reglist. - unsigned RegListBits = insn & ((1 << 16) - 1); - for (unsigned i = 0; i < 16; ++i) { - if ((RegListBits >> i) & 1) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - i))); - ++NumOpsAdded; - } - } - - return true; -} - -// LDREX, LDREXB, LDREXH: Rd Rn -// LDREXD: Rd Rd+1 Rn -// STREX, STREXB, STREXH: Rd Rm Rn -// STREXD: Rd Rm Rm+1 Rn -// -// SWP, SWPB: Rd Rm Rn -static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 2 - && OpInfo[0].RegClass == ARM::GPRRegClassID - && OpInfo[1].RegClass == ARM::GPRRegClassID - && "Expect 2 reg operands"); - - bool isStore = slice(insn, 20, 20) == 0; - bool isDW = (Opcode == ARM::LDREXD || Opcode == ARM::STREXD); - - // Add the destination operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - - // Store register Exclusive needs a source operand. - if (isStore) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - ++OpIdx; - - if (isDW) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)+1))); - ++OpIdx; - } - } else if (isDW) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)+1))); - ++OpIdx; - } - - // Finally add the pointer operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - - return true; -} - -// Misc. Arithmetic Instructions. -// CLZ: Rd Rm -// PKHBT, PKHTB: Rd Rn Rm , LSL/ASR #imm5 -// RBIT, REV, REV16, REVSH: Rd Rm -static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 2 - && OpInfo[0].RegClass == ARM::GPRRegClassID - && OpInfo[1].RegClass == ARM::GPRRegClassID - && "Expect 2 reg operands"); - - bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID; - - // Sanity check the registers, which should not be 15. - if (decodeRd(insn) == 15 || decodeRm(insn) == 15) - return false; - if (ThreeReg && decodeRn(insn) == 15) - return false; - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - - if (ThreeReg) { - assert(NumOps >= 4 && "Expect >= 4 operands"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - ++OpIdx; - - // If there is still an operand info left which is an immediate operand, add - // an additional imm5 LSL/ASR operand. - if (ThreeReg && OpInfo[OpIdx].RegClass < 0 - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - // Extract the 5-bit immediate field Inst{11-7}. - unsigned ShiftAmt = (insn >> ARMII::ShiftShift) & 0x1F; - if (Opcode == ARM::PKHBT || Opcode == ARM::PKHTB) - MI.addOperand(MCOperand::CreateImm(ShiftAmt)); - else - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ARM_AM::no_shift, - ShiftAmt))); - ++OpIdx; - } - - return true; -} - -/// DisassembleSatFrm - Disassemble saturate instructions: -/// SSAT, SSAT16, USAT, and USAT16. -static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - // A8.6.183 SSAT - // if d == 15 || n == 15 then UNPREDICTABLE; - if (decodeRd(insn) == 15 || decodeRm(insn) == 15) - return false; - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands - - // Disassemble register def. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - - unsigned Pos = slice(insn, 20, 16); - MI.addOperand(MCOperand::CreateImm(Pos)); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - - if (NumOpsAdded == 4) { - // Inst{6} encodes the shift type. - bool isASR = slice(insn, 6, 6); - // Inst{11-7} encodes the imm5 shift amount. - unsigned ShAmt = slice(insn, 11, 7); - MI.addOperand(MCOperand::CreateImm(isASR << 5 | ShAmt)); - } - return true; -} - -// Extend instructions. -// SXT* and UXT*: Rd [Rn] Rm [rot_imm]. -// The 2nd operand register is Rn and the 3rd operand regsiter is Rm for the -// three register operand form. Otherwise, Rn=0b1111 and only Rm is used. -static bool DisassembleExtFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - // A8.6.220 SXTAB - // if d == 15 || m == 15 then UNPREDICTABLE; - if (decodeRd(insn) == 15 || decodeRm(insn) == 15) - return false; - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 2 - && OpInfo[0].RegClass == ARM::GPRRegClassID - && OpInfo[1].RegClass == ARM::GPRRegClassID - && "Expect 2 reg operands"); - - bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID; - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - ++OpIdx; - - if (ThreeReg) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - ++OpIdx; - - // If there is still an operand info left which is an immediate operand, add - // an additional rotate immediate operand. - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - // Extract the 2-bit rotate field Inst{11-10}. - unsigned rot = (insn >> ARMII::ExtRotImmShift) & 3; - MI.addOperand(MCOperand::CreateImm(rot)); - ++OpIdx; - } - - return true; -} - -///////////////////////////////////// -// // -// Utility Functions For VFP // -// // -///////////////////////////////////// - -// Extract/Decode Dd/Sd: -// -// SP => d = UInt(Vd:D) -// DP => d = UInt(D:Vd) -static unsigned decodeVFPRd(uint32_t insn, bool isSPVFP) { - return isSPVFP ? (decodeRd(insn) << 1 | getDBit(insn)) - : (decodeRd(insn) | getDBit(insn) << 4); -} - -// Extract/Decode Dn/Sn: -// -// SP => n = UInt(Vn:N) -// DP => n = UInt(N:Vn) -static unsigned decodeVFPRn(uint32_t insn, bool isSPVFP) { - return isSPVFP ? (decodeRn(insn) << 1 | getNBit(insn)) - : (decodeRn(insn) | getNBit(insn) << 4); -} - -// Extract/Decode Dm/Sm: -// -// SP => m = UInt(Vm:M) -// DP => m = UInt(M:Vm) -static unsigned decodeVFPRm(uint32_t insn, bool isSPVFP) { - return isSPVFP ? (decodeRm(insn) << 1 | getMBit(insn)) - : (decodeRm(insn) | getMBit(insn) << 4); -} - -// A7.5.1 -static APInt VFPExpandImm(unsigned char byte, unsigned N) { - assert(N == 32 || N == 64); - - uint64_t Result; - unsigned bit6 = slice(byte, 6, 6); - if (N == 32) { - Result = slice(byte, 7, 7) << 31 | slice(byte, 5, 0) << 19; - if (bit6) - Result |= 0x1f << 25; - else - Result |= 0x1 << 30; - } else { - Result = (uint64_t)slice(byte, 7, 7) << 63 | - (uint64_t)slice(byte, 5, 0) << 48; - if (bit6) - Result |= 0xffULL << 54; - else - Result |= 0x1ULL << 62; - } - return APInt(N, Result); -} - -// VFP Unary Format Instructions: -// -// VCMP[E]ZD, VCMP[E]ZS: compares one floating-point register with zero -// VCVTDS, VCVTSD: converts between double-precision and single-precision -// The rest of the instructions have homogeneous [VFP]Rd and [VFP]Rm registers. -static bool DisassembleVFPUnaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 1 && "VFPUnaryFrm expects NumOps >= 1"); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - unsigned RegClass = OpInfo[OpIdx].RegClass; - assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) && - "Reg operand expected"); - bool isSP = (RegClass == ARM::SPRRegClassID); - - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP)))); - ++OpIdx; - - // Early return for compare with zero instructions. - if (Opcode == ARM::VCMPEZD || Opcode == ARM::VCMPEZS - || Opcode == ARM::VCMPZD || Opcode == ARM::VCMPZS) - return true; - - RegClass = OpInfo[OpIdx].RegClass; - assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) && - "Reg operand expected"); - isSP = (RegClass == ARM::SPRRegClassID); - - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP)))); - ++OpIdx; - - return true; -} - -// All the instructions have homogeneous [VFP]Rd, [VFP]Rn, and [VFP]Rm regs. -// Some of them have operand constraints which tie the first operand in the -// InOperandList to that of the dst. As far as asm printing is concerned, this -// tied_to operand is simply skipped. -static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 3 && "VFPBinaryFrm expects NumOps >= 3"); - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - unsigned RegClass = OpInfo[OpIdx].RegClass; - assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) && - "Reg operand expected"); - bool isSP = (RegClass == ARM::SPRRegClassID); - - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP)))); - ++OpIdx; - - // Skip tied_to operand constraint. - if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { - assert(NumOps >= 4 && "Expect >=4 operands"); - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, decodeVFPRn(insn, isSP)))); - ++OpIdx; - - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP)))); - ++OpIdx; - - return true; -} - -// A8.6.295 vcvt (floating-point <-> integer) -// Int to FP: VSITOD, VSITOS, VUITOD, VUITOS -// FP to Int: VTOSI[Z|R]D, VTOSI[Z|R]S, VTOUI[Z|R]D, VTOUI[Z|R]S -// -// A8.6.297 vcvt (floating-point and fixed-point) -// Dd|Sd Dd|Sd(TIED_TO) #fbits(= 16|32 - UInt(imm4:i)) -static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 2 && "VFPConv1Frm expects NumOps >= 2"); - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - if (!OpInfo) return false; - - bool SP = slice(insn, 8, 8) == 0; // A8.6.295 & A8.6.297 - bool fixed_point = slice(insn, 17, 17) == 1; // A8.6.297 - unsigned RegClassID = SP ? ARM::SPRRegClassID : ARM::DPRRegClassID; - - if (fixed_point) { - // A8.6.297 - assert(NumOps >= 3 && "Expect >= 3 operands"); - int size = slice(insn, 7, 7) == 0 ? 16 : 32; - int fbits = size - (slice(insn,3,0) << 1 | slice(insn,5,5)); - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClassID, - decodeVFPRd(insn, SP)))); - - assert(MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 && - "Tied to operand expected"); - MI.addOperand(MI.getOperand(0)); - - assert(OpInfo[2].RegClass < 0 && !OpInfo[2].isPredicate() && - !OpInfo[2].isOptionalDef() && "Imm operand expected"); - MI.addOperand(MCOperand::CreateImm(fbits)); - - NumOpsAdded = 3; - } else { - // A8.6.295 - // The Rd (destination) and Rm (source) bits have different interpretations - // depending on their single-precisonness. - unsigned d, m; - if (slice(insn, 18, 18) == 1) { // to_integer operation - d = decodeVFPRd(insn, true /* Is Single Precision */); - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::SPRRegClassID, d))); - m = decodeVFPRm(insn, SP); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, m))); - } else { - d = decodeVFPRd(insn, SP); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, d))); - m = decodeVFPRm(insn, true /* Is Single Precision */); - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::SPRRegClassID, m))); - } - NumOpsAdded = 2; - } - - return true; -} - -// VMOVRS - A8.6.330 -// Rt => Rd; Sn => UInt(Vn:N) -static bool DisassembleVFPConv2Frm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 2 && "VFPConv2Frm expects NumOps >= 2"); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID, - decodeVFPRn(insn, true)))); - NumOpsAdded = 2; - return true; -} - -// VMOVRRD - A8.6.332 -// Rt => Rd; Rt2 => Rn; Dm => UInt(M:Vm) -// -// VMOVRRS - A8.6.331 -// Rt => Rd; Rt2 => Rn; Sm => UInt(Vm:M); Sm1 = Sm+1 -static bool DisassembleVFPConv3Frm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 3 && "VFPConv3Frm expects NumOps >= 3"); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - unsigned &OpIdx = NumOpsAdded; - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - OpIdx = 2; - - if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) { - unsigned Sm = decodeVFPRm(insn, true); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID, - Sm))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID, - Sm+1))); - OpIdx += 2; - } else { - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::DPRRegClassID, - decodeVFPRm(insn, false)))); - ++OpIdx; - } - return true; -} - -// VMOVSR - A8.6.330 -// Rt => Rd; Sn => UInt(Vn:N) -static bool DisassembleVFPConv4Frm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 2 && "VFPConv4Frm expects NumOps >= 2"); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID, - decodeVFPRn(insn, true)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - NumOpsAdded = 2; - return true; -} - -// VMOVDRR - A8.6.332 -// Rt => Rd; Rt2 => Rn; Dm => UInt(M:Vm) -// -// VMOVRRS - A8.6.331 -// Rt => Rd; Rt2 => Rn; Sm => UInt(Vm:M); Sm1 = Sm+1 -static bool DisassembleVFPConv5Frm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 3 && "VFPConv5Frm expects NumOps >= 3"); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) { - unsigned Sm = decodeVFPRm(insn, true); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID, - Sm))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID, - Sm+1))); - OpIdx += 2; - } else { - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::DPRRegClassID, - decodeVFPRm(insn, false)))); - ++OpIdx; - } - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - OpIdx += 2; - return true; -} - -// VFP Load/Store Instructions. -// VLDRD, VLDRS, VSTRD, VSTRS -static bool DisassembleVFPLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 3 && "VFPLdStFrm expects NumOps >= 3"); - - bool isSPVFP = (Opcode == ARM::VLDRS || Opcode == ARM::VSTRS); - unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID; - - // Extract Dd/Sd for operand 0. - unsigned RegD = decodeVFPRd(insn, isSPVFP); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, RegD))); - - unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)); - MI.addOperand(MCOperand::CreateReg(Base)); - - // Next comes the AM5 Opcode. - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; - unsigned char Imm8 = insn & 0xFF; - MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(AddrOpcode, Imm8))); - - NumOpsAdded = 3; - - return true; -} - -// VFP Load/Store Multiple Instructions. -// We have an optional write back reg, the base, and two predicate operands. -// It is then followed by a reglist of either DPR(s) or SPR(s). -// -// VLDMD[_UPD], VLDMS[_UPD], VSTMD[_UPD], VSTMS[_UPD] -static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 4 && "VFPLdStMulFrm expects NumOps >= 4"); - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)); - - // Writeback to base, if necessary. - if (Opcode == ARM::VLDMDIA_UPD || Opcode == ARM::VLDMSIA_UPD || - Opcode == ARM::VLDMDDB_UPD || Opcode == ARM::VLDMSDB_UPD || - Opcode == ARM::VSTMDIA_UPD || Opcode == ARM::VSTMSIA_UPD || - Opcode == ARM::VSTMDDB_UPD || Opcode == ARM::VSTMSDB_UPD) { - MI.addOperand(MCOperand::CreateReg(Base)); - ++OpIdx; - } - - MI.addOperand(MCOperand::CreateReg(Base)); - - // Handling the two predicate operands before the reglist. - int64_t CondVal = getCondField(insn); - if (CondVal == 0xF) - return false; - MI.addOperand(MCOperand::CreateImm(CondVal)); - MI.addOperand(MCOperand::CreateReg(ARM::CPSR)); - - OpIdx += 3; - - bool isSPVFP = (Opcode == ARM::VLDMSIA || - Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMSDB_UPD || - Opcode == ARM::VSTMSIA || - Opcode == ARM::VSTMSIA_UPD || Opcode == ARM::VSTMSDB_UPD); - unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID; - - // Extract Dd/Sd. - unsigned RegD = decodeVFPRd(insn, isSPVFP); - - // Fill the variadic part of reglist. - unsigned char Imm8 = insn & 0xFF; - unsigned Regs = isSPVFP ? Imm8 : Imm8/2; - - // Apply some sanity checks before proceeding. - if (Regs == 0 || (RegD + Regs) > 32 || (!isSPVFP && Regs > 16)) - return false; - - for (unsigned i = 0; i < Regs; ++i) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, - RegD + i))); - ++OpIdx; - } - - return true; -} - -// Misc. VFP Instructions. -// FMSTAT (vmrs with Rt=0b1111, i.e., to apsr_nzcv and no register operand) -// FCONSTD (DPR and a VFPf64Imm operand) -// FCONSTS (SPR and a VFPf32Imm operand) -// VMRS/VMSR (GPR operand) -static bool DisassembleVFPMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - if (Opcode == ARM::FMSTAT) - return true; - - assert(NumOps >= 2 && "VFPMiscFrm expects >=2 operands"); - - unsigned RegEnum = 0; - switch (OpInfo[0].RegClass) { - case ARM::DPRRegClassID: - RegEnum = getRegisterEnum(B, ARM::DPRRegClassID, decodeVFPRd(insn, false)); - break; - case ARM::SPRRegClassID: - RegEnum = getRegisterEnum(B, ARM::SPRRegClassID, decodeVFPRd(insn, true)); - break; - case ARM::GPRRegClassID: - RegEnum = getRegisterEnum(B, ARM::GPRRegClassID, decodeRd(insn)); - break; - default: - assert(0 && "Invalid reg class id"); - return false; - } - - MI.addOperand(MCOperand::CreateReg(RegEnum)); - ++OpIdx; - - // Extract/decode the f64/f32 immediate. - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - // The asm syntax specifies the floating point value, not the 8-bit literal. - APInt immRaw = VFPExpandImm(slice(insn,19,16) << 4 | slice(insn, 3, 0), - Opcode == ARM::FCONSTD ? 64 : 32); - APFloat immFP = APFloat(immRaw, true); - double imm = Opcode == ARM::FCONSTD ? immFP.convertToDouble() : - immFP.convertToFloat(); - MI.addOperand(MCOperand::CreateFPImm(imm)); - - ++OpIdx; - } - - return true; -} - -// DisassembleThumbFrm() is defined in ThumbDisassemblerCore.h file. -#include "ThumbDisassemblerCore.h" - -///////////////////////////////////////////////////// -// // -// Utility Functions For ARM Advanced SIMD // -// // -///////////////////////////////////////////////////// - -// The following NEON namings are based on A8.6.266 VABA, VABAL. Notice that -// A8.6.303 VDUP (ARM core register)'s D/Vd pair is the N/Vn pair of VABA/VABAL. - -// A7.3 Register encoding - -// Extract/Decode NEON D/Vd: -// -// Note that for quadword, Qd = UInt(D:Vd<3:1>) = Inst{22:15-13}, whereas for -// doubleword, Dd = UInt(D:Vd). We compensate for this difference by -// handling it in the getRegisterEnum() utility function. -// D = Inst{22}, Vd = Inst{15-12} -static unsigned decodeNEONRd(uint32_t insn) { - return ((insn >> ARMII::NEON_D_BitShift) & 1) << 4 - | ((insn >> ARMII::NEON_RegRdShift) & ARMII::NEONRegMask); -} - -// Extract/Decode NEON N/Vn: -// -// Note that for quadword, Qn = UInt(N:Vn<3:1>) = Inst{7:19-17}, whereas for -// doubleword, Dn = UInt(N:Vn). We compensate for this difference by -// handling it in the getRegisterEnum() utility function. -// N = Inst{7}, Vn = Inst{19-16} -static unsigned decodeNEONRn(uint32_t insn) { - return ((insn >> ARMII::NEON_N_BitShift) & 1) << 4 - | ((insn >> ARMII::NEON_RegRnShift) & ARMII::NEONRegMask); -} - -// Extract/Decode NEON M/Vm: -// -// Note that for quadword, Qm = UInt(M:Vm<3:1>) = Inst{5:3-1}, whereas for -// doubleword, Dm = UInt(M:Vm). We compensate for this difference by -// handling it in the getRegisterEnum() utility function. -// M = Inst{5}, Vm = Inst{3-0} -static unsigned decodeNEONRm(uint32_t insn) { - return ((insn >> ARMII::NEON_M_BitShift) & 1) << 4 - | ((insn >> ARMII::NEON_RegRmShift) & ARMII::NEONRegMask); -} - -namespace { -enum ElemSize { - ESizeNA = 0, - ESize8 = 8, - ESize16 = 16, - ESize32 = 32, - ESize64 = 64 -}; -} // End of unnamed namespace - -// size field -> Inst{11-10} -// index_align field -> Inst{7-4} -// -// The Lane Index interpretation depends on the Data Size: -// 8 (encoded as size = 0b00) -> Index = index_align[3:1] -// 16 (encoded as size = 0b01) -> Index = index_align[3:2] -// 32 (encoded as size = 0b10) -> Index = index_align[3] -// -// Ref: A8.6.317 VLD4 (single 4-element structure to one lane). -static unsigned decodeLaneIndex(uint32_t insn) { - unsigned size = insn >> 10 & 3; - assert((size == 0 || size == 1 || size == 2) && - "Encoding error: size should be either 0, 1, or 2"); - - unsigned index_align = insn >> 4 & 0xF; - return (index_align >> 1) >> size; -} - -// imm64 = AdvSIMDExpandImm(op, cmode, i:imm3:imm4) -// op = Inst{5}, cmode = Inst{11-8} -// i = Inst{24} (ARM architecture) -// imm3 = Inst{18-16}, imm4 = Inst{3-0} -// Ref: Table A7-15 Modified immediate values for Advanced SIMD instructions. -static uint64_t decodeN1VImm(uint32_t insn, ElemSize esize) { - unsigned char op = (insn >> 5) & 1; - unsigned char cmode = (insn >> 8) & 0xF; - unsigned char Imm8 = ((insn >> 24) & 1) << 7 | - ((insn >> 16) & 7) << 4 | - (insn & 0xF); - return (op << 12) | (cmode << 8) | Imm8; -} - -// A8.6.339 VMUL, VMULL (by scalar) -// ESize16 => m = Inst{2-0} (Vm<2:0>) D0-D7 -// ESize32 => m = Inst{3-0} (Vm<3:0>) D0-D15 -static unsigned decodeRestrictedDm(uint32_t insn, ElemSize esize) { - switch (esize) { - case ESize16: - return insn & 7; - case ESize32: - return insn & 0xF; - default: - assert(0 && "Unreachable code!"); - return 0; - } -} - -// A8.6.339 VMUL, VMULL (by scalar) -// ESize16 => index = Inst{5:3} (M:Vm<3>) D0-D7 -// ESize32 => index = Inst{5} (M) D0-D15 -static unsigned decodeRestrictedDmIndex(uint32_t insn, ElemSize esize) { - switch (esize) { - case ESize16: - return (((insn >> 5) & 1) << 1) | ((insn >> 3) & 1); - case ESize32: - return (insn >> 5) & 1; - default: - assert(0 && "Unreachable code!"); - return 0; - } -} - -// A8.6.296 VCVT (between floating-point and fixed-point, Advanced SIMD) -// (64 - ) is encoded as imm6, i.e., Inst{21-16}. -static unsigned decodeVCVTFractionBits(uint32_t insn) { - return 64 - ((insn >> 16) & 0x3F); -} - -// A8.6.302 VDUP (scalar) -// ESize8 => index = Inst{19-17} -// ESize16 => index = Inst{19-18} -// ESize32 => index = Inst{19} -static unsigned decodeNVLaneDupIndex(uint32_t insn, ElemSize esize) { - switch (esize) { - case ESize8: - return (insn >> 17) & 7; - case ESize16: - return (insn >> 18) & 3; - case ESize32: - return (insn >> 19) & 1; - default: - assert(0 && "Unspecified element size!"); - return 0; - } -} - -// A8.6.328 VMOV (ARM core register to scalar) -// A8.6.329 VMOV (scalar to ARM core register) -// ESize8 => index = Inst{21:6-5} -// ESize16 => index = Inst{21:6} -// ESize32 => index = Inst{21} -static unsigned decodeNVLaneOpIndex(uint32_t insn, ElemSize esize) { - switch (esize) { - case ESize8: - return ((insn >> 21) & 1) << 2 | ((insn >> 5) & 3); - case ESize16: - return ((insn >> 21) & 1) << 1 | ((insn >> 6) & 1); - case ESize32: - return ((insn >> 21) & 1); - default: - assert(0 && "Unspecified element size!"); - return 0; - } -} - -// Imm6 = Inst{21-16}, L = Inst{7} -// -// LeftShift == true (A8.6.367 VQSHL, A8.6.387 VSLI): -// case L:imm6 of -// '0001xxx' => esize = 8; shift_amount = imm6 - 8 -// '001xxxx' => esize = 16; shift_amount = imm6 - 16 -// '01xxxxx' => esize = 32; shift_amount = imm6 - 32 -// '1xxxxxx' => esize = 64; shift_amount = imm6 -// -// LeftShift == false (A8.6.376 VRSHR, A8.6.368 VQSHRN): -// case L:imm6 of -// '0001xxx' => esize = 8; shift_amount = 16 - imm6 -// '001xxxx' => esize = 16; shift_amount = 32 - imm6 -// '01xxxxx' => esize = 32; shift_amount = 64 - imm6 -// '1xxxxxx' => esize = 64; shift_amount = 64 - imm6 -// -static unsigned decodeNVSAmt(uint32_t insn, bool LeftShift) { - ElemSize esize = ESizeNA; - unsigned L = (insn >> 7) & 1; - unsigned imm6 = (insn >> 16) & 0x3F; - if (L == 0) { - if (imm6 >> 3 == 1) - esize = ESize8; - else if (imm6 >> 4 == 1) - esize = ESize16; - else if (imm6 >> 5 == 1) - esize = ESize32; - else - assert(0 && "Wrong encoding of Inst{7:21-16}!"); - } else - esize = ESize64; - - if (LeftShift) - return esize == ESize64 ? imm6 : (imm6 - esize); - else - return esize == ESize64 ? (esize - imm6) : (2*esize - imm6); -} - -// A8.6.305 VEXT -// Imm4 = Inst{11-8} -static unsigned decodeN3VImm(uint32_t insn) { - return (insn >> 8) & 0xF; -} - -// VLD* -// D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm] -// VLD*LN* -// D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm] TIED_TO ... imm(idx) -// VST* -// Rn [TIED_TO Rn] align [Rm] D[d] D[d2] ... -// VST*LN* -// Rn [TIED_TO Rn] align [Rm] D[d] D[d2] ... [imm(idx)] -// -// Correctly set VLD*/VST*'s TIED_TO GPR, as the asm printer needs it. -static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, bool Store, bool DblSpaced, - unsigned alignment, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - - // At least one DPR register plus addressing mode #6. - assert(NumOps >= 3 && "Expect >= 3 operands"); - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - // We have homogeneous NEON registers for Load/Store. - unsigned RegClass = 0; - - // Double-spaced registers have increments of 2. - unsigned Inc = DblSpaced ? 2 : 1; - - unsigned Rn = decodeRn(insn); - unsigned Rm = decodeRm(insn); - unsigned Rd = decodeNEONRd(insn); - - // A7.7.1 Advanced SIMD addressing mode. - bool WB = Rm != 15; - - // LLVM Addressing Mode #6. - unsigned RmEnum = 0; - if (WB && Rm != 13) - RmEnum = getRegisterEnum(B, ARM::GPRRegClassID, Rm); - - if (Store) { - // Consume possible WB, AddrMode6, possible increment reg, the DPR/QPR's, - // then possible lane index. - assert(OpIdx < NumOps && OpInfo[0].RegClass == ARM::GPRRegClassID && - "Reg operand expected"); - - if (WB) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - Rn))); - ++OpIdx; - } - - assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected"); - // addrmode6 := (ops GPR:$addr, i32imm) - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - Rn))); - MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment - OpIdx += 2; - - if (WB) { - MI.addOperand(MCOperand::CreateReg(RmEnum)); - ++OpIdx; - } - - assert(OpIdx < NumOps && - (OpInfo[OpIdx].RegClass == ARM::DPRRegClassID || - OpInfo[OpIdx].RegClass == ARM::QPRRegClassID) && - "Reg operand expected"); - - RegClass = OpInfo[OpIdx].RegClass; - while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) { - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, Rd))); - Rd += Inc; - ++OpIdx; - } - - // Handle possible lane index. - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - MI.addOperand(MCOperand::CreateImm(decodeLaneIndex(insn))); - ++OpIdx; - } - - } else { - // Consume the DPR/QPR's, possible WB, AddrMode6, possible incrment reg, - // possible TIED_TO DPR/QPR's (ignored), then possible lane index. - RegClass = OpInfo[0].RegClass; - - while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) { - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, Rd))); - Rd += Inc; - ++OpIdx; - } - - if (WB) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - Rn))); - ++OpIdx; - } - - assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID && - OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected"); - // addrmode6 := (ops GPR:$addr, i32imm) - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - Rn))); - MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment - OpIdx += 2; - - if (WB) { - MI.addOperand(MCOperand::CreateReg(RmEnum)); - ++OpIdx; - } - - while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) { - assert(MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1 && - "Tied to operand expected"); - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - // Handle possible lane index. - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - MI.addOperand(MCOperand::CreateImm(decodeLaneIndex(insn))); - ++OpIdx; - } - } - - // Accessing registers past the end of the NEON register file is not - // defined. - if (Rd > 32) - return false; - - return true; -} - -// A8.6.308, A8.6.311, A8.6.314, A8.6.317. -static bool Align4OneLaneInst(unsigned elem, unsigned size, - unsigned index_align, unsigned & alignment) { - unsigned bits = 0; - switch (elem) { - default: - return false; - case 1: - // A8.6.308 - if (size == 0) - return slice(index_align, 0, 0) == 0; - else if (size == 1) { - bits = slice(index_align, 1, 0); - if (bits != 0 && bits != 1) - return false; - if (bits == 1) - alignment = 16; - return true; - } else if (size == 2) { - bits = slice(index_align, 2, 0); - if (bits != 0 && bits != 3) - return false; - if (bits == 3) - alignment = 32; - return true;; - } - return true; - case 2: - // A8.6.311 - if (size == 0) { - if (slice(index_align, 0, 0) == 1) - alignment = 16; - return true; - } if (size == 1) { - if (slice(index_align, 0, 0) == 1) - alignment = 32; - return true; - } else if (size == 2) { - if (slice(index_align, 1, 1) != 0) - return false; - if (slice(index_align, 0, 0) == 1) - alignment = 64; - return true;; - } - return true; - case 3: - // A8.6.314 - if (size == 0) { - if (slice(index_align, 0, 0) != 0) - return false; - return true; - } if (size == 1) { - if (slice(index_align, 0, 0) != 0) - return false; - return true; - return true; - } else if (size == 2) { - if (slice(index_align, 1, 0) != 0) - return false; - return true;; - } - return true; - case 4: - // A8.6.317 - if (size == 0) { - if (slice(index_align, 0, 0) == 1) - alignment = 32; - return true; - } if (size == 1) { - if (slice(index_align, 0, 0) == 1) - alignment = 64; - return true; - } else if (size == 2) { - bits = slice(index_align, 1, 0); - if (bits == 3) - return false; - if (bits == 1) - alignment = 64; - else if (bits == 2) - alignment = 128; - return true;; - } - return true; - } -} - -// A7.7 -// If L (Inst{21}) == 0, store instructions. -// Find out about double-spaced-ness of the Opcode and pass it on to -// DisassembleNLdSt0(). -static bool DisassembleNLdSt(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const StringRef Name = ARMInsts[Opcode].Name; - bool DblSpaced = false; - // 0 represents standard alignment, i.e., unaligned data access. - unsigned alignment = 0; - - unsigned elem = 0; // legal values: {1, 2, 3, 4} - if (Name.startswith("VST1") || Name.startswith("VLD1")) - elem = 1; - - if (Name.startswith("VST2") || Name.startswith("VLD2")) - elem = 2; - - if (Name.startswith("VST3") || Name.startswith("VLD3")) - elem = 3; - - if (Name.startswith("VST4") || Name.startswith("VLD4")) - elem = 4; - - if (Name.find("LN") != std::string::npos) { - // To one lane instructions. - // See, for example, 8.6.317 VLD4 (single 4-element structure to one lane). - - // Utility function takes number of elements, size, and index_align. - if (!Align4OneLaneInst(elem, - slice(insn, 11, 10), - slice(insn, 7, 4), - alignment)) - return false; - - // == 16 && Inst{5} == 1 --> DblSpaced = true - if (Name.endswith("16") || Name.endswith("16_UPD")) - DblSpaced = slice(insn, 5, 5) == 1; - - // == 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 { - if (a) { - // A8.6.315 VLD3 (single 3-element structure to all lanes) - // The a bit must be encoded as 0. - return false; - } - } - } else { - // Multiple n-element structures with type encoded as Inst{11-8}. - // See, for example, A8.6.316 VLD4 (multiple 4-element structures). - - // Inst{5-4} encodes alignment. - unsigned align = slice(insn, 5, 4); - switch (align) { - default: - break; - case 1: - alignment = 64; break; - case 2: - alignment = 128; break; - case 3: - alignment = 256; break; - } - - unsigned type = slice(insn, 11, 8); - // Reject UNDEFINED instructions based on type and align. - // Plus set DblSpaced flag where appropriate. - switch (elem) { - default: - break; - case 1: - // n == 1 - // A8.6.307 & A8.6.391 - if ((type == 7 && slice(align, 1, 1) == 1) || - (type == 10 && align == 3) || - (type == 6 && slice(align, 1, 1) == 1)) - return false; - break; - case 2: - // n == 2 && type == 0b1001 -> DblSpaced = true - // A8.6.310 & A8.6.393 - if ((type == 8 || type == 9) && align == 3) - return false; - DblSpaced = (type == 9); - break; - case 3: - // n == 3 && type == 0b0101 -> DblSpaced = true - // A8.6.313 & A8.6.395 - if (slice(insn, 7, 6) == 3 || slice(align, 1, 1) == 1) - return false; - DblSpaced = (type == 5); - break; - case 4: - // n == 4 && type == 0b0001 -> DblSpaced = true - // A8.6.316 & A8.6.397 - if (slice(insn, 7, 6) == 3) - return false; - DblSpaced = (type == 1); - break; - } - } - return DisassembleNLdSt0(MI, Opcode, insn, NumOps, NumOpsAdded, - slice(insn, 21, 21) == 0, DblSpaced, alignment/8, B); -} - -// VMOV (immediate) -// Qd/Dd imm -// VBIC (immediate) -// VORR (immediate) -// Qd/Dd imm src(=Qd/Dd) -static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - - assert(NumOps >= 2 && - (OpInfo[0].RegClass == ARM::DPRRegClassID || - OpInfo[0].RegClass == ARM::QPRRegClassID) && - (OpInfo[1].RegClass < 0) && - "Expect 1 reg operand followed by 1 imm operand"); - - // Qd/Dd = Inst{22:15-12} => NEON Rd - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass, - decodeNEONRd(insn)))); - - ElemSize esize = ESizeNA; - switch (Opcode) { - case ARM::VMOVv8i8: - case ARM::VMOVv16i8: - esize = ESize8; - break; - case ARM::VMOVv4i16: - case ARM::VMOVv8i16: - case ARM::VMVNv4i16: - case ARM::VMVNv8i16: - case ARM::VBICiv4i16: - case ARM::VBICiv8i16: - case ARM::VORRiv4i16: - case ARM::VORRiv8i16: - esize = ESize16; - break; - case ARM::VMOVv2i32: - case ARM::VMOVv4i32: - case ARM::VMVNv2i32: - case ARM::VMVNv4i32: - case ARM::VBICiv2i32: - case ARM::VBICiv4i32: - case ARM::VORRiv2i32: - case ARM::VORRiv4i32: - esize = ESize32; - break; - case ARM::VMOVv1i64: - case ARM::VMOVv2i64: - esize = ESize64; - break; - default: - assert(0 && "Unexpected opcode!"); - return false; - } - - // One register and a modified immediate value. - // Add the imm operand. - MI.addOperand(MCOperand::CreateImm(decodeN1VImm(insn, esize))); - - NumOpsAdded = 2; - - // VBIC/VORRiv*i* variants have an extra $src = $Vd to be filled in. - if (NumOps >= 3 && - (OpInfo[2].RegClass == ARM::DPRRegClassID || - OpInfo[2].RegClass == ARM::QPRRegClassID)) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass, - decodeNEONRd(insn)))); - NumOpsAdded += 1; - } - - return true; -} - -namespace { -enum N2VFlag { - N2V_None, - N2V_VectorDupLane, - N2V_VectorConvert_Between_Float_Fixed -}; -} // End of unnamed namespace - -// Vector Convert [between floating-point and fixed-point] -// Qd/Dd Qm/Dm [fbits] -// -// Vector Duplicate Lane (from scalar to all elements) Instructions. -// VDUPLN16d, VDUPLN16q, VDUPLN32d, VDUPLN32q, VDUPLN8d, VDUPLN8q: -// Qd/Dd Dm index -// -// Vector Move Long: -// Qd Dm -// -// Vector Move Narrow: -// Dd Qm -// -// Others -static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, N2VFlag Flag, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opc]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - - assert(NumOps >= 2 && - (OpInfo[0].RegClass == ARM::DPRRegClassID || - OpInfo[0].RegClass == ARM::QPRRegClassID) && - (OpInfo[1].RegClass == ARM::DPRRegClassID || - OpInfo[1].RegClass == ARM::QPRRegClassID) && - "Expect >= 2 operands and first 2 as reg operands"); - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - ElemSize esize = ESizeNA; - if (Flag == N2V_VectorDupLane) { - // VDUPLN has its index embedded. Its size can be inferred from the Opcode. - assert(Opc >= ARM::VDUPLN16d && Opc <= ARM::VDUPLN8q && - "Unexpected Opcode"); - esize = (Opc == ARM::VDUPLN8d || Opc == ARM::VDUPLN8q) ? ESize8 - : ((Opc == ARM::VDUPLN16d || Opc == ARM::VDUPLN16q) ? ESize16 - : ESize32); - } - - // Qd/Dd = Inst{22:15-12} => NEON Rd - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeNEONRd(insn)))); - ++OpIdx; - - // VPADAL... - if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { - // TIED_TO operand. - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - // Dm = Inst{5:3-0} => NEON Rm - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeNEONRm(insn)))); - ++OpIdx; - - // VZIP and others have two TIED_TO reg operands. - int Idx; - while (OpIdx < NumOps && - (Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { - // Add TIED_TO operand. - MI.addOperand(MI.getOperand(Idx)); - ++OpIdx; - } - - // Add the imm operand, if required. - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - - unsigned imm = 0xFFFFFFFF; - - if (Flag == N2V_VectorDupLane) - imm = decodeNVLaneDupIndex(insn, esize); - if (Flag == N2V_VectorConvert_Between_Float_Fixed) - imm = decodeVCVTFractionBits(insn); - - assert(imm != 0xFFFFFFFF && "Internal error"); - MI.addOperand(MCOperand::CreateImm(imm)); - ++OpIdx; - } - - return true; -} - -static bool DisassembleN2RegFrm(MCInst &MI, unsigned Opc, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded, - N2V_None, B); -} -static bool DisassembleNVCVTFrm(MCInst &MI, unsigned Opc, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded, - N2V_VectorConvert_Between_Float_Fixed, B); -} -static bool DisassembleNVecDupLnFrm(MCInst &MI, unsigned Opc, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded, - N2V_VectorDupLane, B); -} - -// Vector Shift [Accumulate] Instructions. -// Qd/Dd [Qd/Dd (TIED_TO)] Qm/Dm ShiftAmt -// -// Vector Shift Left Long (with maximum shift count) Instructions. -// VSHLLi16, VSHLLi32, VSHLLi8: Qd Dm imm (== size) -// -static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, bool LeftShift, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - - assert(NumOps >= 3 && - (OpInfo[0].RegClass == ARM::DPRRegClassID || - OpInfo[0].RegClass == ARM::QPRRegClassID) && - (OpInfo[1].RegClass == ARM::DPRRegClassID || - OpInfo[1].RegClass == ARM::QPRRegClassID) && - "Expect >= 3 operands and first 2 as reg operands"); - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - // Qd/Dd = Inst{22:15-12} => NEON Rd - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeNEONRd(insn)))); - ++OpIdx; - - if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { - // TIED_TO operand. - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - assert((OpInfo[OpIdx].RegClass == ARM::DPRRegClassID || - OpInfo[OpIdx].RegClass == ARM::QPRRegClassID) && - "Reg operand expected"); - - // Qm/Dm = Inst{5:3-0} => NEON Rm - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeNEONRm(insn)))); - ++OpIdx; - - assert(OpInfo[OpIdx].RegClass < 0 && "Imm operand expected"); - - // Add the imm operand. - - // VSHLL has maximum shift count as the imm, inferred from its size. - unsigned Imm; - switch (Opcode) { - default: - Imm = decodeNVSAmt(insn, LeftShift); - break; - case ARM::VSHLLi8: - Imm = 8; - break; - case ARM::VSHLLi16: - Imm = 16; - break; - case ARM::VSHLLi32: - Imm = 32; - break; - } - MI.addOperand(MCOperand::CreateImm(Imm)); - ++OpIdx; - - return true; -} - -// Left shift instructions. -static bool DisassembleN2RegVecShLFrm(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, true, - B); -} -// Right shift instructions have different shift amount interpretation. -static bool DisassembleN2RegVecShRFrm(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, false, - B); -} - -namespace { -enum N3VFlag { - N3V_None, - N3V_VectorExtract, - N3V_VectorShift, - N3V_Multiply_By_Scalar -}; -} // End of unnamed namespace - -// NEON Three Register Instructions with Optional Immediate Operand -// -// Vector Extract Instructions. -// Qd/Dd Qn/Dn Qm/Dm imm4 -// -// Vector Shift (Register) Instructions. -// Qd/Dd Qm/Dm Qn/Dn (notice the order of m, n) -// -// Vector Multiply [Accumulate/Subtract] [Long] By Scalar Instructions. -// Qd/Dd Qn/Dn RestrictedDm index -// -// Others -static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, N3VFlag Flag, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - - // No checking for OpInfo[2] because of MOVDneon/MOVQ with only two regs. - assert(NumOps >= 3 && - (OpInfo[0].RegClass == ARM::DPRRegClassID || - OpInfo[0].RegClass == ARM::QPRRegClassID) && - (OpInfo[1].RegClass == ARM::DPRRegClassID || - OpInfo[1].RegClass == ARM::QPRRegClassID) && - "Expect >= 3 operands and first 2 as reg operands"); - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - bool VdVnVm = Flag == N3V_VectorShift ? false : true; - bool IsImm4 = Flag == N3V_VectorExtract ? true : false; - bool IsDmRestricted = Flag == N3V_Multiply_By_Scalar ? true : false; - ElemSize esize = ESizeNA; - if (Flag == N3V_Multiply_By_Scalar) { - unsigned size = (insn >> 20) & 3; - if (size == 1) esize = ESize16; - if (size == 2) esize = ESize32; - assert (esize == ESize16 || esize == ESize32); - } - - // Qd/Dd = Inst{22:15-12} => NEON Rd - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeNEONRd(insn)))); - ++OpIdx; - - // VABA, VABAL, VBSLd, VBSLq, ... - if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) { - // TIED_TO operand. - MI.addOperand(MCOperand::CreateReg(0)); - ++OpIdx; - } - - // Dn = Inst{7:19-16} => NEON Rn - // or - // Dm = Inst{5:3-0} => NEON Rm - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, OpInfo[OpIdx].RegClass, - VdVnVm ? decodeNEONRn(insn) - : decodeNEONRm(insn)))); - ++OpIdx; - - // Dm = Inst{5:3-0} => NEON Rm - // or - // Dm is restricted to D0-D7 if size is 16, D0-D15 otherwise - // or - // Dn = Inst{7:19-16} => NEON Rn - unsigned m = VdVnVm ? (IsDmRestricted ? decodeRestrictedDm(insn, esize) - : decodeNEONRm(insn)) - : decodeNEONRn(insn); - - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, OpInfo[OpIdx].RegClass, m))); - ++OpIdx; - - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - // Add the imm operand. - unsigned Imm = 0; - if (IsImm4) - Imm = decodeN3VImm(insn); - else if (IsDmRestricted) - Imm = decodeRestrictedDmIndex(insn, esize); - else { - assert(0 && "Internal error: unreachable code!"); - return false; - } - - MI.addOperand(MCOperand::CreateImm(Imm)); - ++OpIdx; - } - - return true; -} - -static bool DisassembleN3RegFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded, - N3V_None, B); -} -static bool DisassembleN3RegVecShFrm(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded, - N3V_VectorShift, B); -} -static bool DisassembleNVecExtractFrm(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded, - N3V_VectorExtract, B); -} -static bool DisassembleNVecMulScalarFrm(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded, - N3V_Multiply_By_Scalar, B); -} - -// Vector Table Lookup -// -// VTBL1, VTBX1: Dd [Dd(TIED_TO)] Dn Dm -// VTBL2, VTBX2: Dd [Dd(TIED_TO)] Dn Dn+1 Dm -// VTBL3, VTBX3: Dd [Dd(TIED_TO)] Dn Dn+1 Dn+2 Dm -// VTBL4, VTBX4: Dd [Dd(TIED_TO)] Dn Dn+1 Dn+2 Dn+3 Dm -static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - if (!OpInfo) return false; - - assert(NumOps >= 3 && - OpInfo[0].RegClass == ARM::DPRRegClassID && - OpInfo[1].RegClass == ARM::DPRRegClassID && - OpInfo[2].RegClass == ARM::DPRRegClassID && - "Expect >= 3 operands and first 3 as reg operands"); - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - unsigned Rn = decodeNEONRn(insn); - - // {Dn} encoded as len = 0b00 - // {Dn Dn+1} encoded as len = 0b01 - // {Dn Dn+1 Dn+2 } encoded as len = 0b10 - // {Dn Dn+1 Dn+2 Dn+3} encoded as len = 0b11 - unsigned Len = slice(insn, 9, 8) + 1; - - // Dd (the destination vector) - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID, - decodeNEONRd(insn)))); - ++OpIdx; - - // Process tied_to operand constraint. - int Idx; - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { - MI.addOperand(MI.getOperand(Idx)); - ++OpIdx; - } - - // Do the now. - for (unsigned i = 0; i < Len; ++i) { - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID && - "Reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID, - Rn + i))); - ++OpIdx; - } - - // Dm (the index vector) - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID && - "Reg operand (index vector) expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID, - decodeNEONRm(insn)))); - ++OpIdx; - - return true; -} - -// Vector Get Lane (move scalar to ARM core register) Instructions. -// VGETLNi32, VGETLNs16, VGETLNs8, VGETLNu16, VGETLNu8: Rt Dn index -static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - if (!OpInfo) return false; - - assert(MCID.getNumDefs() == 1 && NumOps >= 3 && - OpInfo[0].RegClass == ARM::GPRRegClassID && - OpInfo[1].RegClass == ARM::DPRRegClassID && - OpInfo[2].RegClass < 0 && - "Expect >= 3 operands with one dst operand"); - - ElemSize esize = - Opcode == ARM::VGETLNi32 ? ESize32 - : ((Opcode == ARM::VGETLNs16 || Opcode == ARM::VGETLNu16) ? ESize16 - : ESize8); - - // Rt = Inst{15-12} => ARM Rd - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - - // Dn = Inst{7:19-16} => NEON Rn - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID, - decodeNEONRn(insn)))); - - MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize))); - - NumOpsAdded = 3; - return true; -} - -// Vector Set Lane (move ARM core register to scalar) Instructions. -// VSETLNi16, VSETLNi32, VSETLNi8: Dd Dd (TIED_TO) Rt index -static bool DisassembleNSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - if (!OpInfo) return false; - - assert(MCID.getNumDefs() == 1 && NumOps >= 3 && - OpInfo[0].RegClass == ARM::DPRRegClassID && - OpInfo[1].RegClass == ARM::DPRRegClassID && - MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 && - OpInfo[2].RegClass == ARM::GPRRegClassID && - OpInfo[3].RegClass < 0 && - "Expect >= 3 operands with one dst operand"); - - ElemSize esize = - Opcode == ARM::VSETLNi8 ? ESize8 - : (Opcode == ARM::VSETLNi16 ? ESize16 - : ESize32); - - // Dd = Inst{7:19-16} => NEON Rn - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID, - decodeNEONRn(insn)))); - - // TIED_TO operand. - MI.addOperand(MCOperand::CreateReg(0)); - - // Rt = Inst{15-12} => ARM Rd - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - - MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize))); - - NumOpsAdded = 4; - return true; -} - -// Vector Duplicate Instructions (from ARM core register to all elements). -// VDUP8d, VDUP16d, VDUP32d, VDUP8q, VDUP16q, VDUP32q: Qd/Dd Rt -static bool DisassembleNDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - - assert(NumOps >= 2 && - (OpInfo[0].RegClass == ARM::DPRRegClassID || - OpInfo[0].RegClass == ARM::QPRRegClassID) && - OpInfo[1].RegClass == ARM::GPRRegClassID && - "Expect >= 2 operands and first 2 as reg operand"); - - unsigned RegClass = OpInfo[0].RegClass; - - // Qd/Dd = Inst{7:19-16} => NEON Rn - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClass, - decodeNEONRn(insn)))); - - // Rt = Inst{15-12} => ARM Rd - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - - NumOpsAdded = 2; - return true; -} - -static inline bool PreLoadOpcode(unsigned Opcode) { - switch(Opcode) { - case ARM::PLDi12: case ARM::PLDrs: - case ARM::PLDWi12: case ARM::PLDWrs: - case ARM::PLIi12: case ARM::PLIrs: - return true; - default: - return false; - } -} - -static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - // Preload Data/Instruction requires either 2 or 3 operands. - // PLDi12, PLDWi12, PLIi12: addrmode_imm12 - // PLDrs, PLDWrs, PLIrs: ldst_so_reg - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - - if (Opcode == ARM::PLDi12 || Opcode == ARM::PLDWi12 - || Opcode == ARM::PLIi12) { - unsigned Imm12 = slice(insn, 11, 0); - bool Negative = getUBit(insn) == 0; - - // A8.6.118 PLD (literal) PLDWi12 with Rn=PC is transformed to PLDi12. - if (Opcode == ARM::PLDWi12 && slice(insn, 19, 16) == 0xF) { - DEBUG(errs() << "Rn == '1111': PLDWi12 morphed to PLDi12\n"); - MI.setOpcode(ARM::PLDi12); - } - - // -0 is represented specially. All other values are as normal. - int Offset = Negative ? -1 * Imm12 : Imm12; - if (Imm12 == 0 && Negative) - Offset = INT32_MIN; - - MI.addOperand(MCOperand::CreateImm(Offset)); - NumOpsAdded = 2; - } else { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - - ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub; - - // Inst{6-5} encodes the shift opcode. - ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5)); - // Inst{11-7} encodes the imm5 shift amount. - unsigned ShImm = slice(insn, 11, 7); - - // A8.4.1. Possible rrx or shift amount of 32... - getImmShiftSE(ShOp, ShImm); - MI.addOperand(MCOperand::CreateImm( - ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp))); - NumOpsAdded = 3; - } - - return true; -} - -static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - if (Opcode == ARM::DMB || Opcode == ARM::DSB || Opcode == ARM::ISB) { - // Inst{3-0} encodes the memory barrier option for the variants. - unsigned opt = slice(insn, 3, 0); - switch (opt) { - case ARM_MB::SY: case ARM_MB::ST: - case ARM_MB::ISH: case ARM_MB::ISHST: - case ARM_MB::NSH: case ARM_MB::NSHST: - case ARM_MB::OSH: case ARM_MB::OSHST: - MI.addOperand(MCOperand::CreateImm(opt)); - NumOpsAdded = 1; - return true; - default: - return false; - } - } - - switch (Opcode) { - case ARM::CLREX: - case ARM::NOP: - case ARM::TRAP: - case ARM::YIELD: - case ARM::WFE: - case ARM::WFI: - case ARM::SEV: - return true; - case ARM::SWP: - case ARM::SWPB: - // SWP, SWPB: Rd Rm Rn - // Delegate to DisassembleLdStExFrm().... - return DisassembleLdStExFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B); - default: - break; - } - - if (Opcode == ARM::SETEND) { - NumOpsAdded = 1; - MI.addOperand(MCOperand::CreateImm(slice(insn, 9, 9))); - return true; - } - - // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different - // opcodes which match the same real instruction. This is needed since there's - // no current handling of optional arguments. Fix here when a better handling - // of optional arguments is implemented. - if (Opcode == ARM::CPS3p) { // M = 1 - // Let's reject these impossible imod values by returning false: - // 1. (imod=0b01) - // - // AsmPrinter cannot handle imod=0b00, plus (imod=0b00,M=1,iflags!=0) is an - // invalid combination, so we just check for imod=0b00 here. - if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1) - return false; - MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod - MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode - NumOpsAdded = 3; - return true; - } - if (Opcode == ARM::CPS2p) { // mode = 0, M = 0 - // Let's reject these impossible imod values by returning false: - // 1. (imod=0b00,M=0) - // 2. (imod=0b01) - if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1) - return false; - MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod - MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6))); // iflags - NumOpsAdded = 2; - return true; - } - if (Opcode == ARM::CPS1p) { // imod = 0, iflags = 0, M = 1 - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode - NumOpsAdded = 1; - return true; - } - - // DBG has its option specified in Inst{3-0}. - if (Opcode == ARM::DBG) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0))); - NumOpsAdded = 1; - return true; - } - - // BKPT takes an imm32 val equal to ZeroExtend(Inst{19-8:3-0}). - if (Opcode == ARM::BKPT) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 8) << 4 | - slice(insn, 3, 0))); - NumOpsAdded = 1; - return true; - } - - if (PreLoadOpcode(Opcode)) - return DisassemblePreLoadFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B); - - assert(0 && "Unexpected misc instruction!"); - return false; -} - -/// FuncPtrs - FuncPtrs maps ARMFormat to its corresponding DisassembleFP. -/// We divide the disassembly task into different categories, with each one -/// corresponding to a specific instruction encoding format. There could be -/// exceptions when handling a specific format, and that is why the Opcode is -/// also present in the function prototype. -static const DisassembleFP FuncPtrs[] = { - &DisassemblePseudo, - &DisassembleMulFrm, - &DisassembleBrFrm, - &DisassembleBrMiscFrm, - &DisassembleDPFrm, - &DisassembleDPSoRegRegFrm, - &DisassembleLdFrm, - &DisassembleStFrm, - &DisassembleLdMiscFrm, - &DisassembleStMiscFrm, - &DisassembleLdStMulFrm, - &DisassembleLdStExFrm, - &DisassembleArithMiscFrm, - &DisassembleSatFrm, - &DisassembleExtFrm, - &DisassembleVFPUnaryFrm, - &DisassembleVFPBinaryFrm, - &DisassembleVFPConv1Frm, - &DisassembleVFPConv2Frm, - &DisassembleVFPConv3Frm, - &DisassembleVFPConv4Frm, - &DisassembleVFPConv5Frm, - &DisassembleVFPLdStFrm, - &DisassembleVFPLdStMulFrm, - &DisassembleVFPMiscFrm, - &DisassembleThumbFrm, - &DisassembleMiscFrm, - &DisassembleNGetLnFrm, - &DisassembleNSetLnFrm, - &DisassembleNDupFrm, - - // VLD and VST (including one lane) Instructions. - &DisassembleNLdSt, - - // A7.4.6 One register and a modified immediate value - // 1-Register Instructions with imm. - // LLVM only defines VMOVv instructions. - &DisassembleN1RegModImmFrm, - - // 2-Register Instructions with no imm. - &DisassembleN2RegFrm, - - // 2-Register Instructions with imm (vector convert float/fixed point). - &DisassembleNVCVTFrm, - - // 2-Register Instructions with imm (vector dup lane). - &DisassembleNVecDupLnFrm, - - // Vector Shift Left Instructions. - &DisassembleN2RegVecShLFrm, - - // Vector Shift Righ Instructions, which has different interpretation of the - // shift amount from the imm6 field. - &DisassembleN2RegVecShRFrm, - - // 3-Register Data-Processing Instructions. - &DisassembleN3RegFrm, - - // Vector Shift (Register) Instructions. - // D:Vd M:Vm N:Vn (notice that M:Vm is the first operand) - &DisassembleN3RegVecShFrm, - - // Vector Extract Instructions. - &DisassembleNVecExtractFrm, - - // Vector [Saturating Rounding Doubling] Multiply [Accumulate/Subtract] [Long] - // By Scalar Instructions. - &DisassembleNVecMulScalarFrm, - - // Vector Table Lookup uses byte indexes in a control vector to look up byte - // values in a table and generate a new vector. - &DisassembleNVTBLFrm, - - &DisassembleDPSoRegImmFrm, - - - NULL -}; - -/// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder. -/// The general idea is to set the Opcode for the MCInst, followed by adding -/// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates -/// to the Format-specific disassemble function for disassembly, followed by -/// TryPredicateAndSBitModifier() to do PredicateOperand and OptionalDefOperand -/// which follow the Dst/Src Operands. -bool ARMBasicMCBuilder::BuildIt(MCInst &MI, uint32_t insn) { - // Stage 1 sets the Opcode. - MI.setOpcode(Opcode); - // If the number of operands is zero, we're done! - if (NumOps == 0) - return true; - - // Stage 2 calls the format-specific disassemble function to build the operand - // list. - if (Disasm == NULL) - return false; - unsigned NumOpsAdded = 0; - bool OK = (*Disasm)(MI, Opcode, insn, NumOps, NumOpsAdded, this); - - if (!OK || this->Err != 0) return false; - if (NumOpsAdded >= NumOps) - return true; - - // Stage 3 deals with operands unaccounted for after stage 2 is finished. - // FIXME: Should this be done selectively? - return TryPredicateAndSBitModifier(MI, Opcode, insn, NumOps - NumOpsAdded); -} - -// A8.3 Conditional execution -// A8.3.1 Pseudocode details of conditional execution -// Condition bits '111x' indicate the instruction is always executed. -static uint32_t CondCode(uint32_t CondField) { - if (CondField == 0xF) - return ARMCC::AL; - return CondField; -} - -/// DoPredicateOperands - DoPredicateOperands process the predicate operands -/// of some Thumb instructions which come before the reglist operands. It -/// returns true if the two predicate operands have been processed. -bool ARMBasicMCBuilder::DoPredicateOperands(MCInst& MI, unsigned Opcode, - uint32_t /* insn */, unsigned short NumOpsRemaining) { - - assert(NumOpsRemaining > 0 && "Invalid argument"); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - unsigned Idx = MI.getNumOperands(); - - // First, we check whether this instr specifies the PredicateOperand through - // a pair of MCOperandInfos with isPredicate() property. - if (NumOpsRemaining >= 2 && - OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() && - OpInfo[Idx].RegClass < 0 && - OpInfo[Idx+1].RegClass == ARM::CCRRegClassID) - { - // If we are inside an IT block, get the IT condition bits maintained via - // ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond(). - // See also A2.5.2. - if (InITBlock()) - MI.addOperand(MCOperand::CreateImm(GetITCond())); - else - MI.addOperand(MCOperand::CreateImm(ARMCC::AL)); - MI.addOperand(MCOperand::CreateReg(ARM::CPSR)); - return true; - } - - return false; -} - -/// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process -/// the possible Predicate and SBitModifier, to build the remaining MCOperand -/// constituents. -bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode, - uint32_t insn, unsigned short NumOpsRemaining) { - - assert(NumOpsRemaining > 0 && "Invalid argument"); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - const std::string &Name = ARMInsts[Opcode].Name; - unsigned Idx = MI.getNumOperands(); - uint64_t TSFlags = ARMInsts[Opcode].TSFlags; - - // First, we check whether this instr specifies the PredicateOperand through - // a pair of MCOperandInfos with isPredicate() property. - if (NumOpsRemaining >= 2 && - OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() && - OpInfo[Idx].RegClass < 0 && - OpInfo[Idx+1].RegClass == ARM::CCRRegClassID) - { - // If we are inside an IT block, get the IT condition bits maintained via - // ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond(). - // See also A2.5.2. - if (InITBlock()) - MI.addOperand(MCOperand::CreateImm(GetITCond())); - else { - if (Name.length() > 1 && Name[0] == 't') { - // Thumb conditional branch instructions have their cond field embedded, - // like ARM. - // - // A8.6.16 B - // 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}. - // We should reject Inst{31-28} = 0b1111 as invalid encoding. - if (!isNEONDomain(TSFlags) && getCondField(insn) == 0xF) - return false; - MI.addOperand(MCOperand::CreateImm(CondCode(getCondField(insn)))); - } - } - MI.addOperand(MCOperand::CreateReg(ARM::CPSR)); - Idx += 2; - NumOpsRemaining -= 2; - } - - if (NumOpsRemaining == 0) - return true; - - // Next, if OptionalDefOperand exists, we check whether the 'S' bit is set. - if (OpInfo[Idx].isOptionalDef() && OpInfo[Idx].RegClass==ARM::CCRRegClassID) { - MI.addOperand(MCOperand::CreateReg(getSBit(insn) == 1 ? ARM::CPSR : 0)); - --NumOpsRemaining; - } - - if (NumOpsRemaining == 0) - return true; - else - return false; -} - -/// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary -/// after BuildIt is finished. -bool ARMBasicMCBuilder::RunBuildAfterHook(bool Status, MCInst &MI, - uint32_t insn) { - - if (!SP) return Status; - - if (Opcode == ARM::t2IT) - Status = SP->InitIT(slice(insn, 7, 0)) ? Status : false; - else if (InITBlock()) - SP->UpdateIT(); - - return Status; -} - -/// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder. -ARMBasicMCBuilder::ARMBasicMCBuilder(unsigned opc, ARMFormat format, - unsigned short num) - : Opcode(opc), Format(format), NumOps(num), SP(0), Err(0) { - unsigned Idx = (unsigned)format; - assert(Idx < (array_lengthof(FuncPtrs) - 1) && "Unknown format"); - Disasm = FuncPtrs[Idx]; -} - -/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC -/// infrastructure of an MCInst given the Opcode and Format of the instr. -/// Return NULL if it fails to create/return a proper builder. API clients -/// are responsible for freeing up of the allocated memory. Cacheing can be -/// performed by the API clients to improve performance. -ARMBasicMCBuilder *llvm::CreateMCBuilder(unsigned Opcode, ARMFormat Format) { - // For "Unknown format", fail by returning a NULL pointer. - if ((unsigned)Format >= (array_lengthof(FuncPtrs) - 1)) { - DEBUG(errs() << "Unknown format\n"); - return 0; - } - - 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 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, - 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 { - if (Off != 0) - Expr = Off; - else - Expr = MCConstantExpr::Create(0, *Ctx); - } - - 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; -} Removed: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h?rev=137143&view=auto ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (removed) @@ -1,337 +0,0 @@ -//===- ARMDisassemblerCore.h - ARM disassembler helpers ---------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is part of the ARM Disassembler. -// -// The first part defines the enumeration type of ARM instruction format, which -// specifies the encoding used by the instruction, as well as a helper function -// to convert the enums to printable char strings. -// -// It also contains code to represent the concepts of Builder and DisassembleFP -// to solve the problem of disassembling an ARM instr. -// -//===----------------------------------------------------------------------===// - -#ifndef ARMDISASSEMBLERCORE_H -#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: - static const char *OpcodeName(unsigned Opcode); -}; - -///////////////////////////////////////////////////// -// // -// Enums and Utilities for ARM Instruction Format // -// // -///////////////////////////////////////////////////// - -#define ARM_FORMATS \ - ENTRY(ARM_FORMAT_PSEUDO, 0) \ - ENTRY(ARM_FORMAT_MULFRM, 1) \ - ENTRY(ARM_FORMAT_BRFRM, 2) \ - ENTRY(ARM_FORMAT_BRMISCFRM, 3) \ - ENTRY(ARM_FORMAT_DPFRM, 4) \ - ENTRY(ARM_FORMAT_DPSOREGREGFRM, 5) \ - ENTRY(ARM_FORMAT_LDFRM, 6) \ - ENTRY(ARM_FORMAT_STFRM, 7) \ - ENTRY(ARM_FORMAT_LDMISCFRM, 8) \ - ENTRY(ARM_FORMAT_STMISCFRM, 9) \ - ENTRY(ARM_FORMAT_LDSTMULFRM, 10) \ - ENTRY(ARM_FORMAT_LDSTEXFRM, 11) \ - ENTRY(ARM_FORMAT_ARITHMISCFRM, 12) \ - ENTRY(ARM_FORMAT_SATFRM, 13) \ - ENTRY(ARM_FORMAT_EXTFRM, 14) \ - ENTRY(ARM_FORMAT_VFPUNARYFRM, 15) \ - ENTRY(ARM_FORMAT_VFPBINARYFRM, 16) \ - ENTRY(ARM_FORMAT_VFPCONV1FRM, 17) \ - ENTRY(ARM_FORMAT_VFPCONV2FRM, 18) \ - ENTRY(ARM_FORMAT_VFPCONV3FRM, 19) \ - ENTRY(ARM_FORMAT_VFPCONV4FRM, 20) \ - ENTRY(ARM_FORMAT_VFPCONV5FRM, 21) \ - ENTRY(ARM_FORMAT_VFPLDSTFRM, 22) \ - ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \ - ENTRY(ARM_FORMAT_VFPMISCFRM, 24) \ - ENTRY(ARM_FORMAT_THUMBFRM, 25) \ - ENTRY(ARM_FORMAT_MISCFRM, 26) \ - ENTRY(ARM_FORMAT_NEONGETLNFRM, 27) \ - ENTRY(ARM_FORMAT_NEONSETLNFRM, 28) \ - ENTRY(ARM_FORMAT_NEONDUPFRM, 29) \ - ENTRY(ARM_FORMAT_NLdSt, 30) \ - ENTRY(ARM_FORMAT_N1RegModImm, 31) \ - ENTRY(ARM_FORMAT_N2Reg, 32) \ - ENTRY(ARM_FORMAT_NVCVT, 33) \ - ENTRY(ARM_FORMAT_NVecDupLn, 34) \ - ENTRY(ARM_FORMAT_N2RegVecShL, 35) \ - ENTRY(ARM_FORMAT_N2RegVecShR, 36) \ - ENTRY(ARM_FORMAT_N3Reg, 37) \ - ENTRY(ARM_FORMAT_N3RegVecSh, 38) \ - ENTRY(ARM_FORMAT_NVecExtract, 39) \ - ENTRY(ARM_FORMAT_NVecMulScalar, 40) \ - ENTRY(ARM_FORMAT_NVTBL, 41) \ - ENTRY(ARM_FORMAT_DPSOREGIMMFRM, 42) - -// ARM instruction format specifies the encoding used by the instruction. -#define ENTRY(n, v) n = v, -typedef enum { - ARM_FORMATS - ARM_FORMAT_NA -} ARMFormat; -#undef ENTRY - -// Converts enum to const char*. -static const inline char *stringForARMFormat(ARMFormat form) { -#define ENTRY(n, v) case n: return #n; - switch(form) { - ARM_FORMATS - case ARM_FORMAT_NA: - default: - return ""; - } -#undef ENTRY -} - -/// Expands on the enum definitions from ARMBaseInstrInfo.h. -/// They are being used by the disassembler implementation. -namespace ARMII { - enum { - NEONRegMask = 15, - GPRRegMask = 15, - NEON_RegRdShift = 12, - NEON_D_BitShift = 22, - NEON_RegRnShift = 16, - NEON_N_BitShift = 7, - NEON_RegRmShift = 0, - NEON_M_BitShift = 5 - }; -} - -/// Utility function for extracting [From, To] bits from a uint32_t. -static inline unsigned slice(uint32_t Bits, unsigned From, unsigned To) { - assert(From < 32 && To < 32 && From >= To); - return (Bits >> To) & ((1 << (From - To + 1)) - 1); -} - -/// Utility function for setting [From, To] bits to Val for a uint32_t. -static inline void setSlice(unsigned &Bits, unsigned From, unsigned To, - unsigned Val) { - assert(From < 32 && To < 32 && From >= To); - uint32_t Mask = ((1 << (From - To + 1)) - 1); - Bits &= ~(Mask << To); - 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. -static inline bool isUnaryDP(uint64_t TSFlags) { - return (TSFlags & ARMII::UnaryDP); -} - -/// A NEON Domain instruction has cond field (Inst{31-28}) as 0b1111. -static inline bool isNEONDomain(uint64_t TSFlags) { - return (TSFlags & ARMII::DomainNEON) || - (TSFlags & ARMII::DomainNEONA8); -} - -/// This four-bit field describes the addressing mode used. -/// See also ARMBaseInstrInfo.h. -static inline unsigned getAddrMode(uint64_t TSFlags) { - return (TSFlags & ARMII::AddrModeMask); -} - -/// {IndexModePre, IndexModePost} -/// Only valid for load and store ops. -/// See also ARMBaseInstrInfo.h. -static inline unsigned getIndexMode(uint64_t TSFlags) { - return (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift; -} - -/// Pre-/post-indexed operations define an extra $base_wb in the OutOperandList. -static inline bool isPrePostLdSt(uint64_t TSFlags) { - return (TSFlags & ARMII::IndexModeMask) != 0; -} - -// Forward declaration. -class ARMBasicMCBuilder; - -// Builder Object is mostly ignored except in some Thumb disassemble functions. -typedef ARMBasicMCBuilder *BO; - -/// DisassembleFP - DisassembleFP points to a function that disassembles an insn -/// and builds the MCOperand list upon disassembly. It returns false on failure -/// or true on success. The number of operands added is updated upon success. -typedef bool (*DisassembleFP)(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO Builder); - -/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC -/// infrastructure of an MCInst given the Opcode and Format of the instr. -/// Return NULL if it fails to create/return a proper builder. API clients -/// are responsible for freeing up of the allocated memory. Cacheing can be -/// performed by the API clients to improve performance. -extern ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format); - -/// ARMBasicMCBuilder - ARMBasicMCBuilder represents an ARM MCInst builder that -/// knows how to build up the MCOperand list. -class ARMBasicMCBuilder { - friend ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format); - unsigned Opcode; - ARMFormat Format; - unsigned short NumOps; - DisassembleFP Disasm; - Session *SP; - int Err; // !=0 if the builder encounters some error condition during build. - -private: - /// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder. - ARMBasicMCBuilder(unsigned opc, ARMFormat format, unsigned short num); - -public: - ARMBasicMCBuilder(ARMBasicMCBuilder &B) - : Opcode(B.Opcode), Format(B.Format), NumOps(B.NumOps), Disasm(B.Disasm), - SP(B.SP), GetOpInfo(0), DisInfo(0), Ctx(0) { - Err = 0; - } - - virtual ~ARMBasicMCBuilder() {} - - void SetSession(Session *sp) { - SP = sp; - } - - void SetErr(int ErrCode) { - Err = ErrCode; - } - - /// DoPredicateOperands - DoPredicateOperands process the predicate operands - /// of some Thumb instructions which come before the reglist operands. It - /// returns true if the two predicate operands have been processed. - bool DoPredicateOperands(MCInst& MI, unsigned Opcode, - uint32_t insn, unsigned short NumOpsRemaning); - - /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process - /// the possible Predicate and SBitModifier, to build the remaining MCOperand - /// constituents. - bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode, - uint32_t insn, unsigned short NumOpsRemaning); - - /// InITBlock - InITBlock returns true if we are inside an IT block. - bool InITBlock() { - if (SP) - return SP->ITCounter > 0; - - return false; - } - - /// Build - Build delegates to BuildIt to perform the heavy liftling. After - /// that, it invokes RunBuildAfterHook where some housekeepings can be done. - virtual bool Build(MCInst &MI, uint32_t insn) { - bool Status = BuildIt(MI, insn); - return RunBuildAfterHook(Status, MI, insn); - } - - /// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder. - /// The general idea is to set the Opcode for the MCInst, followed by adding - /// the appropriate MCOperands to the MCInst. ARM Basic MC Builder delegates - /// to the Format-specific disassemble function for disassembly, followed by - /// TryPredicateAndSBitModifier() for PredicateOperand and OptionalDefOperand - /// which follow the Dst/Src Operands. - virtual bool BuildIt(MCInst &MI, uint32_t insn); - - /// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary - /// after BuildIt is finished. - virtual bool RunBuildAfterHook(bool Status, MCInst &MI, uint32_t insn); - -private: - /// Get condition of the current IT instruction. - unsigned GetITCond() { - 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 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); - -}; - -} // namespace llvm - -#endif Modified: llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt Tue Aug 9 15:55:18 2011 @@ -2,7 +2,6 @@ add_llvm_library(LLVMARMDisassembler ARMDisassembler.cpp - ARMDisassemblerCore.cpp ) # workaround for hanging compilation on MSVC8, 9 and 10 if( MSVC_VERSION EQUAL 1400 OR MSVC_VERSION EQUAL 1500 OR MSVC_VERSION EQUAL 1600 ) Removed: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=137143&view=auto ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (removed) @@ -1,2461 +0,0 @@ -//===- ThumbDisassemblerCore.h - Thumb disassembler helpers -----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file is part of the ARM Disassembler. -// It contains code for disassembling a Thumb instr. It is to be included by -// ARMDisassemblerCore.cpp because it contains the static DisassembleThumbFrm() -// function which acts as the dispatcher to disassemble a Thumb instruction. -// -//===----------------------------------------------------------------------===// - -/////////////////////////////// -// // -// Utility Functions // -// // -/////////////////////////////// - -// Utilities for 16-bit Thumb instructions. -/* -15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - [ tRt ] - [ tRm ] [ tRn ] [ tRd ] - D [ Rm ] [ Rd ] - - [ imm3] - [ imm5 ] - i [ imm5 ] - [ imm7 ] - [ imm8 ] - [ imm11 ] - - [ cond ] -*/ - -// Extract tRt: Inst{10-8}. -static inline unsigned getT1tRt(uint32_t insn) { - return slice(insn, 10, 8); -} - -// Extract tRm: Inst{8-6}. -static inline unsigned getT1tRm(uint32_t insn) { - return slice(insn, 8, 6); -} - -// Extract tRn: Inst{5-3}. -static inline unsigned getT1tRn(uint32_t insn) { - return slice(insn, 5, 3); -} - -// Extract tRd: Inst{2-0}. -static inline unsigned getT1tRd(uint32_t insn) { - return slice(insn, 2, 0); -} - -// Extract [D:Rd]: Inst{7:2-0}. -static inline unsigned getT1Rd(uint32_t insn) { - return slice(insn, 7, 7) << 3 | slice(insn, 2, 0); -} - -// Extract Rm: Inst{6-3}. -static inline unsigned getT1Rm(uint32_t insn) { - return slice(insn, 6, 3); -} - -// Extract imm3: Inst{8-6}. -static inline unsigned getT1Imm3(uint32_t insn) { - return slice(insn, 8, 6); -} - -// Extract imm5: Inst{10-6}. -static inline unsigned getT1Imm5(uint32_t insn) { - return slice(insn, 10, 6); -} - -// Extract i:imm5: Inst{9:7-3}. -static inline unsigned getT1Imm6(uint32_t insn) { - return slice(insn, 9, 9) << 5 | slice(insn, 7, 3); -} - -// Extract imm7: Inst{6-0}. -static inline unsigned getT1Imm7(uint32_t insn) { - return slice(insn, 6, 0); -} - -// Extract imm8: Inst{7-0}. -static inline unsigned getT1Imm8(uint32_t insn) { - return slice(insn, 7, 0); -} - -// Extract imm11: Inst{10-0}. -static inline unsigned getT1Imm11(uint32_t insn) { - return slice(insn, 10, 0); -} - -// Extract cond: Inst{11-8}. -static inline unsigned getT1Cond(uint32_t insn) { - return slice(insn, 11, 8); -} - -static inline bool IsGPR(unsigned RegClass) { - return RegClass == ARM::GPRRegClassID || RegClass == ARM::rGPRRegClassID; -} - -// 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); -} - -// Extract imm3: Inst{14-12}. -static inline unsigned getImm3(uint32_t insn) { - return slice(insn, 14, 12); -} - -// Extract imm8: Inst{7-0}. -static inline unsigned getImm8(uint32_t insn) { - return slice(insn, 7, 0); -} - -// A8.6.61 LDRB (immediate, Thumb) and friends -// +/-: Inst{9} -// imm8: Inst{7-0} -static inline int decodeImm8(uint32_t insn) { - int Offset = getImm8(insn); - return slice(insn, 9, 9) ? Offset : -Offset; -} - -// Extract imm12: Inst{11-0}. -static inline unsigned getImm12(uint32_t insn) { - return slice(insn, 11, 0); -} - -// A8.6.63 LDRB (literal) and friends -// +/-: Inst{23} -// imm12: Inst{11-0} -static inline int decodeImm12(uint32_t insn) { - int Offset = getImm12(insn); - return slice(insn, 23, 23) ? Offset : -Offset; -} - -// Extract imm2: Inst{7-6}. -static inline unsigned getImm2(uint32_t insn) { - return slice(insn, 7, 6); -} - -// For BFI, BFC, t2SBFX, and t2UBFX. -// Extract lsb: Inst{14-12:7-6}. -static inline unsigned getLsb(uint32_t insn) { - return getImm3(insn) << 2 | getImm2(insn); -} - -// For BFI and BFC. -// Extract msb: Inst{4-0}. -static inline unsigned getMsb(uint32_t insn) { - return slice(insn, 4, 0); -} - -// For t2SBFX and t2UBFX. -// Extract widthminus1: Inst{4-0}. -static inline unsigned getWidthMinus1(uint32_t insn) { - return slice(insn, 4, 0); -} - -// For t2ADDri12 and t2SUBri12. -// imm12 = i:imm3:imm8; -static inline unsigned getIImm3Imm8(uint32_t insn) { - return slice(insn, 26, 26) << 11 | getImm3(insn) << 8 | getImm8(insn); -} - -// For t2MOVi16 and t2MOVTi16. -// imm16 = imm4:i:imm3:imm8; -static inline unsigned getImm16(uint32_t insn) { - return getImm4(insn) << 12 | slice(insn, 26, 26) << 11 | - getImm3(insn) << 8 | getImm8(insn); -} - -// Inst{5-4} encodes the shift type. -static inline unsigned getShiftTypeBits(uint32_t insn) { - return slice(insn, 5, 4); -} - -// Inst{14-12}:Inst{7-6} encodes the imm5 shift amount. -static inline unsigned getShiftAmtBits(uint32_t insn) { - return getImm3(insn) << 2 | getImm2(insn); -} - -// A8.6.17 BFC -// Encoding T1 ARMv6T2, ARMv7 -// LLVM-specific encoding for # and # -static inline bool getBitfieldInvMask(uint32_t insn, uint32_t &mask) { - uint32_t lsb = getImm3(insn) << 2 | getImm2(insn); - uint32_t msb = getMsb(insn); - uint32_t Val = 0; - if (msb < lsb) { - DEBUG(errs() << "Encoding error: msb < lsb\n"); - return false; - } - for (uint32_t i = lsb; i <= msb; ++i) - Val |= (1 << i); - mask = ~Val; - return true; -} - -// A8.4 Shifts applied to a register -// A8.4.1 Constant shifts -// A8.4.3 Pseudocode details of instruction-specified shifts and rotates -// -// decodeImmShift() returns the shift amount and the the shift opcode. -// Note that, as of Jan-06-2010, LLVM does not support rrx shifted operands yet. -static inline unsigned decodeImmShift(unsigned bits2, unsigned imm5, - ARM_AM::ShiftOpc &ShOp) { - - assert(imm5 < 32 && "Invalid imm5 argument"); - switch (bits2) { - default: assert(0 && "No such value"); - case 0: - ShOp = (imm5 == 0 ? ARM_AM::no_shift : ARM_AM::lsl); - return imm5; - case 1: - ShOp = ARM_AM::lsr; - return (imm5 == 0 ? 32 : imm5); - case 2: - ShOp = ARM_AM::asr; - return (imm5 == 0 ? 32 : imm5); - case 3: - ShOp = (imm5 == 0 ? ARM_AM::rrx : ARM_AM::ror); - return (imm5 == 0 ? 1 : imm5); - } -} - -// A6.3.2 Modified immediate constants in Thumb instructions -// -// ThumbExpandImm() returns the modified immediate constant given an imm12 for -// Thumb data-processing instructions with modified immediate. -// See also A6.3.1 Data-processing (modified immediate). -static inline unsigned ThumbExpandImm(unsigned imm12) { - assert(imm12 <= 0xFFF && "Invalid imm12 argument"); - - // If the leading two bits is 0b00, the modified immediate constant is - // obtained by splatting the low 8 bits into the first byte, every other byte, - // or every byte of a 32-bit value. - // - // Otherwise, a rotate right of '1':imm12<6:0> by the amount imm12<11:7> is - // performed. - - if (slice(imm12, 11, 10) == 0) { - unsigned short control = slice(imm12, 9, 8); - unsigned imm8 = slice(imm12, 7, 0); - switch (control) { - default: - assert(0 && "No such value"); - return 0; - case 0: - return imm8; - case 1: - return imm8 << 16 | imm8; - case 2: - return imm8 << 24 | imm8 << 8; - case 3: - return imm8 << 24 | imm8 << 16 | imm8 << 8 | imm8; - } - } else { - // A rotate is required. - unsigned Val = 1 << 7 | slice(imm12, 6, 0); - unsigned Amt = slice(imm12, 11, 7); - return ARM_AM::rotr32(Val, Amt); - } -} - -static inline int decodeImm32_B_EncodingT3(uint32_t insn) { - bool S = slice(insn, 26, 26); - bool J1 = slice(insn, 13, 13); - bool J2 = slice(insn, 11, 11); - unsigned Imm21 = slice(insn, 21, 16) << 12 | slice(insn, 10, 0) << 1; - if (S) Imm21 |= 1 << 20; - if (J2) Imm21 |= 1 << 19; - if (J1) Imm21 |= 1 << 18; - - return SignExtend32<21>(Imm21); -} - -static inline int decodeImm32_B_EncodingT4(uint32_t insn) { - unsigned S = slice(insn, 26, 26); - bool I1 = slice(insn, 13, 13) == S; - bool I2 = slice(insn, 11, 11) == S; - unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 0) << 1; - if (S) Imm25 |= 1 << 24; - if (I1) Imm25 |= 1 << 23; - if (I2) Imm25 |= 1 << 22; - - return SignExtend32<25>(Imm25); -} - -static inline int decodeImm32_BL(uint32_t insn) { - unsigned S = slice(insn, 26, 26); - bool I1 = slice(insn, 13, 13) == S; - bool I2 = slice(insn, 11, 11) == S; - unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 0) << 1; - if (S) Imm25 |= 1 << 24; - if (I1) Imm25 |= 1 << 23; - if (I2) Imm25 |= 1 << 22; - - return SignExtend32<25>(Imm25); -} - -static inline int decodeImm32_BLX(uint32_t insn) { - unsigned S = slice(insn, 26, 26); - bool I1 = slice(insn, 13, 13) == S; - bool I2 = slice(insn, 11, 11) == S; - unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 1) << 2; - if (S) Imm25 |= 1 << 24; - if (I1) Imm25 |= 1 << 23; - if (I2) Imm25 |= 1 << 22; - - return SignExtend32<25>(Imm25); -} - -/////////////////////////////////////////////// -// // -// Thumb1 instruction disassembly functions. // -// // -/////////////////////////////////////////////// - -// See "Utilities for 16-bit Thumb instructions" for register naming convention. - -// A6.2.1 Shift (immediate), add, subtract, move, and compare -// -// shift immediate: tRd CPSR tRn imm5 -// add/sub register: tRd CPSR tRn tRm -// add/sub 3-bit immediate: tRd CPSR tRn imm3 -// add/sub 8-bit immediate: tRt CPSR tRt(TIED_TO) imm8 -// mov/cmp immediate: tRt [CPSR] imm8 (CPSR present for mov) -// -// Special case: -// tMOVSr: tRd tRn -static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID - && "Invalid arguments"); - - bool Imm3 = (Opcode == ARM::tADDi3 || Opcode == ARM::tSUBi3); - - // Use Rt implies use imm8. - bool UseRt = (Opcode == ARM::tADDi8 || Opcode == ARM::tSUBi8 || - Opcode == ARM::tMOVi8 || Opcode == ARM::tCMPi8); - - // Add the destination operand. - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::tGPRRegClassID, - UseRt ? getT1tRt(insn) : getT1tRd(insn)))); - ++OpIdx; - - // Check whether the next operand to be added is a CCR Register. - if (OpInfo[OpIdx].RegClass == ARM::CCRRegClassID) { - assert(OpInfo[OpIdx].isOptionalDef() && "Optional def operand expected"); - MI.addOperand(MCOperand::CreateReg(B->InITBlock() ? 0 : ARM::CPSR)); - ++OpIdx; - } - - // Check whether the next operand to be added is a Thumb1 Register. - assert(OpIdx < NumOps && "More operands expected"); - if (OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) { - // For UseRt, the reg operand is tied to the first reg operand. - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, ARM::tGPRRegClassID, - UseRt ? getT1tRt(insn) : getT1tRn(insn)))); - ++OpIdx; - } - - // Special case for tMOVSr. - if (OpIdx == NumOps) - return true; - - // The next available operand is either a reg operand or an imm operand. - if (OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) { - // Three register operand instructions. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRm(insn)))); - } else { - assert(OpInfo[OpIdx].RegClass < 0 && - !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef() - && "Pure imm operand expected"); - 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; - - return true; -} - -// A6.2.2 Data-processing -// -// tCMPr, tTST, tCMN: tRd tRn -// tMVN, tRSB: tRd CPSR tRn -// Others: tRd CPSR tRd(TIED_TO) tRn -static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && - (OpInfo[1].RegClass == ARM::CCRRegClassID - || OpInfo[1].RegClass == ARM::tGPRRegClassID) - && "Invalid arguments"); - - // Add the destination operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRd(insn)))); - ++OpIdx; - - // Check whether the next operand to be added is a CCR Register. - if (OpInfo[OpIdx].RegClass == ARM::CCRRegClassID) { - assert(OpInfo[OpIdx].isOptionalDef() && "Optional def operand expected"); - MI.addOperand(MCOperand::CreateReg(B->InITBlock() ? 0 : ARM::CPSR)); - ++OpIdx; - } - - // We have either { tRd(TIED_TO), tRn } or { tRn } remaining. - // Process the TIED_TO operand first. - - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID - && "Thumb reg operand expected"); - int Idx; - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { - // The reg operand is tied to the first reg operand. - MI.addOperand(MI.getOperand(Idx)); - ++OpIdx; - } - - // Process possible next reg operand. - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) { - // Add tRn operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRn(insn)))); - ++OpIdx; - } - - return true; -} - -// A6.2.3 Special data instructions and branch and exchange -// -// tADDhirr: Rd Rd(TIED_TO) Rm -// tCMPhir: Rd Rm -// tMOVr, tMOVgpr2gpr, tMOVgpr2tgpr, tMOVtgpr2gpr: Rd|tRd Rm|tRn -// tBX: Rm -// tBX_RET: 0 operand -// tBX_RET_vararg: Rm -// tBLXr: Rm -// tBRIND: Rm -static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - // tBX_RET has 0 operand. - if (NumOps == 0) - return true; - - // BX/BLX/tBRIND (indirect branch, i.e, mov pc, Rm) has 1 reg operand: Rm. - if (Opcode==ARM::tBLXr || Opcode==ARM::tBX || Opcode==ARM::tBRIND) { - if (Opcode == ARM::tBLXr) { - // 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 += 1; - - if (Opcode == ARM::tBX) { - // Handling the two predicate operands after the reg operand. - if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps)) - return false; - NumOpsAdded += 2; - } - - return true; - } - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - // Add the destination operand. - unsigned RegClass = OpInfo[OpIdx].RegClass; - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, - IsGPR(RegClass) ? getT1Rd(insn) - : getT1tRd(insn)))); - ++OpIdx; - - // We have either { Rd(TIED_TO), Rm } or { Rm|tRn } remaining. - // Process the TIED_TO operand first. - - assert(OpIdx < NumOps && "More operands expected"); - int Idx; - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { - // The reg operand is tied to the first reg operand. - MI.addOperand(MI.getOperand(Idx)); - ++OpIdx; - } - - // The next reg operand is either Rm or tRn. - assert(OpIdx < NumOps && "More operands expected"); - RegClass = OpInfo[OpIdx].RegClass; - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, - IsGPR(RegClass) ? getT1Rm(insn) - : getT1tRn(insn)))); - ++OpIdx; - - return true; -} - -// A8.6.59 LDR (literal) -// -// tLDRpci: tRt imm8*4 -static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && - (OpInfo[1].RegClass < 0 && - !OpInfo[1].isPredicate() && - !OpInfo[1].isOptionalDef()) - && "Invalid arguments"); - - // Add the destination operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRt(insn)))); - - // And the (imm8 << 2) operand. - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn) << 2)); - - NumOpsAdded = 2; - - return true; -} - -// Thumb specific addressing modes (see ARMInstrThumb.td): -// -// t_addrmode_rr := reg + reg -// -// t_addrmode_s4 := reg + reg -// reg + imm5 * 4 -// -// t_addrmode_s2 := reg + reg -// reg + imm5 * 2 -// -// t_addrmode_s1 := reg + reg -// reg + imm5 -// -// t_addrmode_sp := sp + imm8 * 4 -// - -// A8.6.63 LDRB (literal) -// A8.6.79 LDRSB (literal) -// A8.6.75 LDRH (literal) -// A8.6.83 LDRSH (literal) -// A8.6.59 LDR (literal) -// -// These instrs calculate an address from the PC value and an immediate offset. -// Rd Rn=PC (+/-)imm12 (+ if Inst{23} == 0b1) -static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - assert(NumOps >= 2 && - OpInfo[0].RegClass == ARM::GPRRegClassID && - OpInfo[1].RegClass < 0 && - "Expect >= 2 operands, first as reg, and second as imm operand"); - - // Build the register operand, followed by the (+/-)imm12 immediate. - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRd(insn)))); - - MI.addOperand(MCOperand::CreateImm(decodeImm12(insn))); - - NumOpsAdded = 2; - - return true; -} - - -// A6.2.4 Load/store single data item -// -// Load/Store Register (reg|imm): tRd tRn imm5|tRm -// Load Register Signed Byte|Halfword: tRd tRn tRm -static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - assert(NumOps >= 2 - && OpInfo[0].RegClass == ARM::tGPRRegClassID - && OpInfo[1].RegClass == ARM::tGPRRegClassID - && "Expect >= 2 operands and first two as thumb reg operands"); - - // Add the destination reg and the base reg. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRd(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRn(insn)))); - OpIdx = 2; - - // We have either { imm5 } or { tRm } remaining. - // Note that STR/LDR (register) should skip the imm5 offset operand for - // t_addrmode_s[1|2|4]. - - assert(OpIdx < NumOps && "More operands expected"); - - if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() && - !OpInfo[OpIdx].isOptionalDef()) { - // Table A6-5 16-bit Thumb Load/store instructions - // opA = 0b0101 for STR/LDR (register) and friends. - // Otherwise, we have STR/LDR (immediate) and friends. - assert(opA != 5 && "Immediate operand expected for this opcode"); - MI.addOperand(MCOperand::CreateImm(getT1Imm5(insn))); - ++OpIdx; - } else { - // The next reg operand is tRm, the offset. - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID - && "Thumb reg operand expected"); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRm(insn)))); - ++OpIdx; - } - return true; -} - -// A6.2.4 Load/store single data item -// -// Load/Store Register SP relative: tRt ARM::SP imm8 -static bool DisassembleThumb1LdStSP(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert((Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) - && "Unexpected opcode"); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - assert(NumOps >= 3 && - OpInfo[0].RegClass == ARM::tGPRRegClassID && - OpInfo[1].RegClass == ARM::GPRRegClassID && - (OpInfo[2].RegClass < 0 && - !OpInfo[2].isPredicate() && - !OpInfo[2].isOptionalDef()) - && "Invalid arguments"); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRt(insn)))); - MI.addOperand(MCOperand::CreateReg(ARM::SP)); - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn))); - NumOpsAdded = 3; - return true; -} - -// Table A6-1 16-bit Thumb instruction encoding -// A8.6.10 ADR -// -// tADDrPCi: tRt imm8 -static bool DisassembleThumb1AddPCi(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(Opcode == ARM::tADDrPCi && "Unexpected opcode"); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && - (OpInfo[1].RegClass < 0 && - !OpInfo[1].isPredicate() && - !OpInfo[1].isOptionalDef()) - && "Invalid arguments"); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRt(insn)))); - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn))); - NumOpsAdded = 2; - return true; -} - -// Table A6-1 16-bit Thumb instruction encoding -// A8.6.8 ADD (SP plus immediate) -// -// tADDrSPi: tRt ARM::SP imm8 -static bool DisassembleThumb1AddSPi(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(Opcode == ARM::tADDrSPi && "Unexpected opcode"); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - assert(NumOps >= 3 && - OpInfo[0].RegClass == ARM::tGPRRegClassID && - OpInfo[1].RegClass == ARM::GPRRegClassID && - (OpInfo[2].RegClass < 0 && - !OpInfo[2].isPredicate() && - !OpInfo[2].isOptionalDef()) - && "Invalid arguments"); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRt(insn)))); - MI.addOperand(MCOperand::CreateReg(ARM::SP)); - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn))); - NumOpsAdded = 3; - return true; -} - -// tPUSH, tPOP: Pred-Imm Pred-CCR register_list -// -// where register_list = low registers + [lr] for PUSH or -// low registers + [pc] for POP -// -// "low registers" is specified by Inst{7-0} -// lr|pc is specified by Inst{8} -static bool DisassembleThumb1PushPop(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert((Opcode == ARM::tPUSH || Opcode == ARM::tPOP) && "Unexpected opcode"); - - unsigned &OpIdx = NumOpsAdded; - - // Handling the two predicate operands before the reglist. - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) - OpIdx += 2; - else { - DEBUG(errs() << "Expected predicate operands not found.\n"); - return false; - } - - unsigned RegListBits = slice(insn, 8, 8) << (Opcode == ARM::tPUSH ? 14 : 15) - | slice(insn, 7, 0); - - // Fill the variadic part of reglist. - for (unsigned i = 0; i < 16; ++i) { - if ((RegListBits >> i) & 1) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - i))); - ++OpIdx; - } - } - - return true; -} - -// A6.2.5 Miscellaneous 16-bit instructions -// Delegate to DisassembleThumb1PushPop() for tPUSH & tPOP. -// -// tADDspi, tSUBspi: ARM::SP ARM::SP(TIED_TO) imm7 -// t2IT: firstcond=Inst{7-4} mask=Inst{3-0} -// tCBNZ, tCBZ: tRd imm6*2 -// tBKPT: imm8 -// tNOP, tSEV, tYIELD, tWFE, tWFI: -// no operand (except predicate pair) -// tSETEND: i1 -// Others: tRd tRn -static bool DisassembleThumb1Misc(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - if (NumOps == 0) - return true; - - if (Opcode == ARM::tPUSH || Opcode == ARM::tPOP) - return DisassembleThumb1PushPop(MI, Opcode, insn, NumOps, NumOpsAdded, B); - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - - // Predicate operands are handled elsewhere. - if (NumOps == 2 && - OpInfo[0].isPredicate() && OpInfo[1].isPredicate() && - OpInfo[0].RegClass < 0 && OpInfo[1].RegClass == ARM::CCRRegClassID) { - return true; - } - - if (Opcode == ARM::tADDspi || Opcode == ARM::tSUBspi) { - // Special case handling for tADDspi and tSUBspi. - // A8.6.8 ADD (SP plus immediate) & A8.6.215 SUB (SP minus immediate) - MI.addOperand(MCOperand::CreateReg(ARM::SP)); - MI.addOperand(MCOperand::CreateReg(ARM::SP)); - MI.addOperand(MCOperand::CreateImm(getT1Imm7(insn))); - NumOpsAdded = 3; - return true; - } - - if (Opcode == ARM::t2IT) { - // Special case handling for If-Then. - // A8.6.50 IT - // Tag the (firstcond[0] bit << 4) along with mask. - - // firstcond - MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 4))); - - // firstcond[0] and mask - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); - NumOpsAdded = 2; - return true; - } - - if (Opcode == ARM::tBKPT) { - MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn))); // breakpoint value - NumOpsAdded = 1; - return true; - } - - // CPS has a singleton $opt operand that contains the following information: - // The first op would be 0b10 as enable and 0b11 as disable in regular ARM, - // but in Thumb it's is 0 as enable and 1 as disable. So map it to ARM's - // default one. The second get the AIF flags from Inst{2-0}. - if (Opcode == ARM::tCPS) { - MI.addOperand(MCOperand::CreateImm(2 + slice(insn, 4, 4))); - MI.addOperand(MCOperand::CreateImm(slice(insn, 2, 0))); - NumOpsAdded = 2; - return true; - } - - if (Opcode == ARM::tSETEND) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 1))); - NumOpsAdded = 1; - return true; - } - - assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID && - (OpInfo[1].RegClass < 0 || OpInfo[1].RegClass==ARM::tGPRRegClassID) - && "Expect >=2 operands"); - - // Add the destination operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRd(insn)))); - - if (OpInfo[1].RegClass == ARM::tGPRRegClassID) { - // Two register instructions. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - getT1tRn(insn)))); - } else { - // CBNZ, CBZ - assert((Opcode == ARM::tCBNZ || Opcode == ARM::tCBZ) &&"Unexpected opcode"); - MI.addOperand(MCOperand::CreateImm(getT1Imm6(insn) * 2)); - } - - NumOpsAdded = 2; - - return true; -} - -// A8.6.53 LDM / LDMIA -// A8.6.189 STM / STMIA -// -// tLDMIA_UPD/tSTMIA_UPD: tRt tRt AM4ModeImm Pred-Imm Pred-CCR register_list -// tLDMIA: tRt AM4ModeImm Pred-Imm Pred-CCR register_list -static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, - unsigned &NumOpsAdded, BO B) { - assert((Opcode == ARM::tLDMIA || Opcode == ARM::tSTMIA) && - "Unexpected opcode"); - - unsigned tRt = getT1tRt(insn); - NumOpsAdded = 0; - - // WB register, if necessary. - if (Opcode == ARM::tLDMIA_UPD || Opcode == ARM::tSTMIA_UPD) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - tRt))); - ++NumOpsAdded; - } - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - tRt))); - ++NumOpsAdded; - - // Handling the two predicate operands before the reglist. - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) { - NumOpsAdded += 2; - } else { - DEBUG(errs() << "Expected predicate operands not found.\n"); - return false; - } - - 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) - if ((RegListBits >> i) & 1) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, - i))); - ++NumOpsAdded; - } - - return true; -} - -static bool DisassembleThumb1LdMul(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - return DisassembleThumb1LdStMul(true, MI, Opcode, insn, NumOps, NumOpsAdded, - B); -} - -static bool DisassembleThumb1StMul(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - return DisassembleThumb1LdStMul(false, MI, Opcode, insn, NumOps, NumOpsAdded, - B); -} - -// A8.6.16 B Encoding T1 -// cond = Inst{11-8} & imm8 = Inst{7-0} -// imm32 = SignExtend(imm8:'0', 32) -// -// tBcc: offset Pred-Imm Pred-CCR -// tSVC: imm8 Pred-Imm Pred-CCR -// tTRAP: 0 operand (early return) -static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO) { - - if (Opcode == ARM::tTRAP) - return true; - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - assert(NumOps == 3 && OpInfo[0].RegClass < 0 && - OpInfo[1].isPredicate() && OpInfo[2].RegClass == ARM::CCRRegClassID - && "Exactly 3 operands expected"); - - unsigned Imm8 = getT1Imm8(insn); - MI.addOperand(MCOperand::CreateImm( - Opcode == ARM::tBcc ? SignExtend32<9>(Imm8 << 1) - : (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; -} - -// A8.6.16 B Encoding T2 -// imm11 = Inst{10-0} -// imm32 = SignExtend(imm11:'0', 32) -// -// tB: offset -static bool DisassembleThumb1Br(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - assert(NumOps == 1 && OpInfo[0].RegClass < 0 && "1 imm operand expected"); - - unsigned Imm11 = getT1Imm11(insn); - - MI.addOperand(MCOperand::CreateImm(SignExtend32<12>(Imm11 << 1))); - - NumOpsAdded = 1; - - return true; - -} - -// See A6.2 16-bit Thumb instruction encoding for instruction classes -// corresponding to op. -// -// Table A6-1 16-bit Thumb instruction encoding (abridged) -// op Instruction or instruction class -// ------ -------------------------------------------------------------------- -// 00xxxx Shift (immediate), add, subtract, move, and compare on page A6-7 -// 010000 Data-processing on page A6-8 -// 010001 Special data instructions and branch and exchange on page A6-9 -// 01001x Load from Literal Pool, see LDR (literal) on page A8-122 -// 0101xx Load/store single data item on page A6-10 -// 011xxx -// 100xxx -// 10100x Generate PC-relative address, see ADR on page A8-32 -// 10101x Generate SP-relative address, see ADD (SP plus immediate) on -// page A8-28 -// 1011xx Miscellaneous 16-bit instructions on page A6-11 -// 11000x Store multiple registers, see STM / STMIA / STMEA on page A8-374 -// 11001x Load multiple registers, see LDM / LDMIA / LDMFD on page A8-110 a -// 1101xx Conditional branch, and Supervisor Call on page A6-13 -// 11100x Unconditional Branch, see B on page A8-44 -// -static bool DisassembleThumb1(uint16_t op, MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - unsigned op1 = slice(op, 5, 4); - unsigned op2 = slice(op, 3, 2); - unsigned op3 = slice(op, 1, 0); - unsigned opA = slice(op, 5, 2); - switch (op1) { - case 0: - // A6.2.1 Shift (immediate), add, subtract, move, and compare - return DisassembleThumb1General(MI, Opcode, insn, NumOps, NumOpsAdded, B); - case 1: - switch (op2) { - case 0: - switch (op3) { - case 0: - // A6.2.2 Data-processing - return DisassembleThumb1DP(MI, Opcode, insn, NumOps, NumOpsAdded, B); - case 1: - // A6.2.3 Special data instructions and branch and exchange - return DisassembleThumb1Special(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - default: - // A8.6.59 LDR (literal) - return DisassembleThumb1LdPC(MI, Opcode, insn, NumOps, NumOpsAdded, B); - } - break; - default: - // A6.2.4 Load/store single data item - return DisassembleThumb1LdSt(opA, MI, Opcode, insn, NumOps, NumOpsAdded, - B); - break; - } - break; - case 2: - switch (op2) { - case 0: - // A6.2.4 Load/store single data item - return DisassembleThumb1LdSt(opA, MI, Opcode, insn, NumOps, NumOpsAdded, - B); - case 1: - // A6.2.4 Load/store single data item - return DisassembleThumb1LdStSP(MI, Opcode, insn, NumOps, NumOpsAdded, B); - case 2: - if (op3 <= 1) { - // A8.6.10 ADR - return DisassembleThumb1AddPCi(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - } else { - // A8.6.8 ADD (SP plus immediate) - return DisassembleThumb1AddSPi(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - } - default: - // A6.2.5 Miscellaneous 16-bit instructions - return DisassembleThumb1Misc(MI, Opcode, insn, NumOps, NumOpsAdded, B); - } - break; - case 3: - switch (op2) { - case 0: - if (op3 <= 1) { - // A8.6.189 STM / STMIA / STMEA - return DisassembleThumb1StMul(MI, Opcode, insn, NumOps, NumOpsAdded, B); - } else { - // A8.6.53 LDM / LDMIA / LDMFD - return DisassembleThumb1LdMul(MI, Opcode, insn, NumOps, NumOpsAdded, B); - } - case 1: - // A6.2.6 Conditional branch, and Supervisor Call - return DisassembleThumb1CondBr(MI, Opcode, insn, NumOps, NumOpsAdded, B); - case 2: - // Unconditional Branch, see B on page A8-44 - return DisassembleThumb1Br(MI, Opcode, insn, NumOps, NumOpsAdded, B); - default: - assert(0 && "Unreachable code"); - break; - } - break; - default: - assert(0 && "Unreachable code"); - break; - } - - return false; -} - -/////////////////////////////////////////////// -// // -// Thumb2 instruction disassembly functions. // -// // -/////////////////////////////////////////////// - -/////////////////////////////////////////////////////////// -// // -// Note: the register naming follows the ARM convention! // -// // -/////////////////////////////////////////////////////////// - -static inline bool Thumb2SRSOpcode(unsigned Opcode) { - switch (Opcode) { - default: - return false; - case ARM::t2SRSDBW: case ARM::t2SRSDB: - case ARM::t2SRSIAW: case ARM::t2SRSIA: - return true; - } -} - -static inline bool Thumb2RFEOpcode(unsigned Opcode) { - switch (Opcode) { - default: - return false; - case ARM::t2RFEDBW: case ARM::t2RFEDB: - case ARM::t2RFEIAW: case ARM::t2RFEIA: - return true; - } -} - -// t2SRS[IA|DB]W/t2SRS[IA|DB]: mode_imm = Inst{4-0} -static bool DisassembleThumb2SRS(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); - NumOpsAdded = 1; - return true; -} - -// 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) { - 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; -} - -static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - if (Thumb2SRSOpcode(Opcode)) - return DisassembleThumb2SRS(MI, Opcode, insn, NumOps, NumOpsAdded); - - if (Thumb2RFEOpcode(Opcode)) - return DisassembleThumb2RFE(MI, Opcode, insn, NumOps, NumOpsAdded, B); - - assert((Opcode == ARM::t2LDMIA || Opcode == ARM::t2LDMIA_UPD || - Opcode == ARM::t2LDMDB || Opcode == ARM::t2LDMDB_UPD || - Opcode == ARM::t2STMIA || Opcode == ARM::t2STMIA_UPD || - Opcode == ARM::t2STMDB || Opcode == ARM::t2STMDB_UPD) - && "Unexpected opcode"); - assert(NumOps >= 4 && "Thumb2 LdStMul expects NumOps >= 4"); - - NumOpsAdded = 0; - - unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)); - - // Writeback to base. - if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD || - Opcode == ARM::t2STMIA_UPD || Opcode == ARM::t2STMDB_UPD) { - MI.addOperand(MCOperand::CreateReg(Base)); - ++NumOpsAdded; - } - - MI.addOperand(MCOperand::CreateReg(Base)); - ++NumOpsAdded; - - // Handling the two predicate operands before the reglist. - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) { - NumOpsAdded += 2; - } else { - DEBUG(errs() << "Expected predicate operands not found.\n"); - return false; - } - - unsigned RegListBits = insn & ((1 << 16) - 1); - - // Fill the variadic part of reglist. - for (unsigned i = 0; i < 16; ++i) - if ((RegListBits >> i) & 1) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - i))); - ++NumOpsAdded; - } - - return true; -} - -// t2LDREX: Rd Rn -// t2LDREXD: Rd Rs Rn -// t2LDREXB, t2LDREXH: Rd Rn -// t2STREX: Rs Rd Rn -// t2STREXD: Rm Rd Rs Rn -// t2STREXB, t2STREXH: Rm Rd Rn -static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 2 - && OpInfo[0].RegClass > 0 - && OpInfo[1].RegClass > 0 - && "Expect >=2 operands and first two as reg operands"); - - bool isStore = (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH); - 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 ? Rt2 : Rd))); - ++OpIdx; - } - - // Source operand for store and destination operand for load. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - Rt))); - ++OpIdx; - - // Thumb2 doubleword complication: with an extra source/destination operand. - if (isDW) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass, - Rt2))); - ++OpIdx; - } - - // Finally add the pointer operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - Rn))); - ++OpIdx; - - return true; -} - -// t2LDRDi8: Rd Rs Rn imm8s4 (offset mode) -// t2LDRDpci: Rd Rs imm8s4 (Not decoded, prefer the generic t2LDRDi8 version) -// t2STRDi8: Rd Rs Rn imm8s4 (offset mode) -// -// Ditto for t2LDRD_PRE, t2LDRD_POST, t2STRD_PRE, t2STRD_POST, which are for -// disassembly only and do not have a tied_to writeback base register operand. -static bool DisassembleThumb2LdStDual(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - if (!OpInfo) return false; - - // 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; - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair, - decodeRd(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair, - decodeRs(insn)))); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassBase, - decodeRn(insn)))); - unsigned Added = 4; - switch (MI.getOpcode()) { - case ARM::t2LDRD_PRE: - case ARM::t2LDRD_POST: - case ARM::t2STRD_PRE: - case ARM::t2STRD_POST: - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassBase, - decodeRn(insn)))); - Added = 5; - default: - break; - } - - // Finally add (+/-)imm8*4, depending on the U bit. - int Offset = getImm8(insn) * 4; - if (getUBit(insn) == 0) - Offset = -Offset; - MI.addOperand(MCOperand::CreateImm(Offset)); - NumOpsAdded = Added; - - return true; -} - -// t2TBB, t2TBH: Rn Rm Pred-Imm Pred-CCR -static bool DisassembleThumb2TB(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert(NumOps >= 2 && "Expect >= 2 operands"); - - // The generic version of TBB/TBH needs a base register. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - // Add the index register. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - NumOpsAdded = 2; - - return true; -} - -static inline bool Thumb2ShiftOpcode(unsigned Opcode) { - switch (Opcode) { - default: - return false; - case ARM::t2MOVCClsl: case ARM::t2MOVCClsr: - case ARM::t2MOVCCasr: case ARM::t2MOVCCror: - case ARM::t2LSLri: case ARM::t2LSRri: - case ARM::t2ASRri: case ARM::t2RORri: - return true; - } -} - -// A6.3.11 Data-processing (shifted register) -// -// Two register operands (Rn=0b1111 no 1st operand reg): Rs Rm -// Two register operands (Rs=0b1111 no dst operand reg): Rn Rm -// Three register operands: Rs Rn Rm -// Three register operands: (Rn=0b1111 Conditional Move) Rs Ro(TIED_TO) Rm -// -// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2 -// register with shift forms: (Rm, ConstantShiftSpecifier). -// Constant shift specifier: Imm = (ShOp | ShAmt<<3). -// -// There are special instructions, like t2MOVsra_flag and t2MOVsrl_flag, which -// only require two register operands: Rd, Rm in ARM Reference Manual terms, and -// nothing else, because the shift amount is already specified. -// Similar case holds for t2MOVrx, t2ADDrr, ..., etc. -static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - // Special case handling. - if (Opcode == ARM::t2BR_JT) { - assert(NumOps == 4 - && OpInfo[0].RegClass == ARM::GPRRegClassID - && OpInfo[1].RegClass == ARM::GPRRegClassID - && OpInfo[2].RegClass < 0 - && OpInfo[3].RegClass < 0 - && "Exactly 4 operands expect and first two as reg operands"); - // Only need to populate the src reg operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - MI.addOperand(MCOperand::CreateReg(0)); - MI.addOperand(MCOperand::CreateImm(0)); - MI.addOperand(MCOperand::CreateImm(0)); - NumOpsAdded = 4; - return true; - } - - OpIdx = 0; - - assert(NumOps >= 2 - && (OpInfo[0].RegClass == ARM::GPRRegClassID || - OpInfo[0].RegClass == ARM::rGPRRegClassID) - && (OpInfo[1].RegClass == ARM::GPRRegClassID || - OpInfo[1].RegClass == ARM::rGPRRegClassID) - && "Expect >= 2 operands and first two as reg operands"); - - bool ThreeReg = (NumOps > 2 && (OpInfo[2].RegClass == ARM::GPRRegClassID || - OpInfo[2].RegClass == ARM::rGPRRegClassID)); - bool NoDstReg = (decodeRs(insn) == 0xF); - - // Build the register operands, followed by the constant shift specifier. - - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, OpInfo[0].RegClass, - NoDstReg ? decodeRn(insn) : decodeRs(insn)))); - ++OpIdx; - - if (ThreeReg) { - int Idx; - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { - // Process tied_to operand constraint. - MI.addOperand(MI.getOperand(Idx)); - ++OpIdx; - } else if (!NoDstReg) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[1].RegClass, - decodeRn(insn)))); - ++OpIdx; - } else { - DEBUG(errs() << "Thumb2 encoding error: d==15 for three-reg operands.\n"); - return false; - } - } - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeRm(insn)))); - ++OpIdx; - - if (NumOps == OpIdx) - return true; - - if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() - && !OpInfo[OpIdx].isOptionalDef()) { - - 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 imm5 = getShiftAmtBits(insn); - // The PKHBT/PKHTB instructions have an implied shift type and so just - // use a plain immediate for the amount. - if (Opcode == ARM::t2PKHBT || Opcode == ARM::t2PKHTB) - MI.addOperand(MCOperand::CreateImm(imm5)); - else { - ARM_AM::ShiftOpc ShOp = ARM_AM::no_shift; - unsigned bits2 = getShiftTypeBits(insn); - unsigned ShAmt = decodeImmShift(bits2, imm5, ShOp); - MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShAmt))); - } - } - ++OpIdx; - } - - return true; -} - -// A6.3.1 Data-processing (modified immediate) -// -// Two register operands: Rs Rn ModImm -// One register operands (Rs=0b1111 no explicit dest reg): Rn ModImm -// One register operands (Rn=0b1111 no explicit src reg): Rs ModImm - -// {t2MOVi, t2MVNi} -// -// ModImm = ThumbExpandImm(i:imm3:imm8) -static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - unsigned RdRegClassID = OpInfo[0].RegClass; - assert(NumOps >= 2 && (RdRegClassID == ARM::GPRRegClassID || - RdRegClassID == ARM::rGPRRegClassID) - && "Expect >= 2 operands and first one as reg operand"); - - unsigned RnRegClassID = OpInfo[1].RegClass; - bool TwoReg = (RnRegClassID == ARM::GPRRegClassID - || RnRegClassID == ARM::rGPRRegClassID); - bool NoDstReg = (decodeRs(insn) == 0xF); - - // Build the register operands, followed by the modified immediate. - - MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RdRegClassID, - NoDstReg ? decodeRn(insn) : decodeRs(insn)))); - ++OpIdx; - - if (TwoReg) { - if (NoDstReg) { - DEBUG(errs()<<"Thumb2 encoding error: d==15 for DPModImm 2-reg instr.\n"); - return false; - } - int Idx; - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::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; - } - - // The modified immediate operand should come next. - assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 && - !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef() - && "Pure imm operand expected"); - - // i:imm3:imm8 - // A6.3.2 Modified immediate constants in Thumb instructions - unsigned imm12 = getIImm3Imm8(insn); - MI.addOperand(MCOperand::CreateImm(ThumbExpandImm(imm12))); - ++OpIdx; - - return true; -} - -static inline bool Thumb2SaturateOpcode(unsigned Opcode) { - switch (Opcode) { - case ARM::t2SSAT: case ARM::t2SSAT16: - case ARM::t2USAT: case ARM::t2USAT16: - return true; - default: - return false; - } -} - -/// DisassembleThumb2Sat - Disassemble Thumb2 saturate instructions: -/// o t2SSAT, t2USAT: Rs sat_pos Rn shamt -/// o t2SSAT16, t2USAT16: Rs sat_pos Rn -static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned &NumOpsAdded, BO B) { - const MCInstrDesc &MCID = ARMInsts[Opcode]; - NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands - - // Disassemble the register def. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRs(insn)))); - - unsigned Pos = slice(insn, 4, 0); - MI.addOperand(MCOperand::CreateImm(Pos)); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRn(insn)))); - - if (NumOpsAdded == 4) { - // Inst{6} encodes the shift type. - bool isASR = slice(insn, 6, 6); - // Inst{11-7} encodes the imm5 shift amount. - unsigned ShAmt = slice(insn, 11, 7); - MI.addOperand(MCOperand::CreateImm(isASR << 5 | ShAmt)); - } - return true; -} - -// A6.3.3 Data-processing (plain binary immediate) -// -// o t2ADDri12, t2SUBri12: Rs Rn imm12 -// o t2LEApcrel (ADR): Rs imm12 -// o t2BFC (BFC): Rs Ro(TIED_TO) bf_inv_mask_imm -// o t2BFI (BFI): Rs Ro(TIED_TO) Rn bf_inv_mask_imm -// o t2MOVi16: Rs imm16 -// o t2MOVTi16: Rs imm16 -// o t2SBFX (SBFX): Rs Rn lsb width -// o t2UBFX (UBFX): Rs Rn lsb width -// o t2BFI (BFI): Rs Rn lsb width -static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - unsigned RdRegClassID = OpInfo[0].RegClass; - assert(NumOps >= 2 && (RdRegClassID == ARM::GPRRegClassID || - RdRegClassID == ARM::rGPRRegClassID) - && "Expect >= 2 operands and first one as reg operand"); - - unsigned RnRegClassID = OpInfo[1].RegClass; - bool TwoReg = (RnRegClassID == ARM::GPRRegClassID - || RnRegClassID == ARM::rGPRRegClassID); - - // Build the register operand(s), followed by the immediate(s). - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RdRegClassID, - decodeRs(insn)))); - ++OpIdx; - - if (TwoReg) { - assert(NumOps >= 3 && "Expect >= 3 operands"); - int Idx; - if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) { - // Process tied_to operand constraint. - MI.addOperand(MI.getOperand(Idx)); - } else { - // Add src reg operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID, - decodeRn(insn)))); - } - ++OpIdx; - } - - if (Opcode == ARM::t2BFI) { - // Add val reg operand. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID, - decodeRn(insn)))); - ++OpIdx; - } - - assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() - && !OpInfo[OpIdx].isOptionalDef() - && "Pure imm operand expected"); - - // Pre-increment OpIdx. - ++OpIdx; - - if (Opcode == ARM::t2ADDri12 || Opcode == ARM::t2SUBri12 - || Opcode == ARM::t2LEApcrel) - MI.addOperand(MCOperand::CreateImm(getIImm3Imm8(insn))); - 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)); - else - return false; - } else { - // Handle the case of: lsb width - assert((Opcode == ARM::t2SBFX || Opcode == ARM::t2UBFX) - && "Unexpected opcode"); - MI.addOperand(MCOperand::CreateImm(getLsb(insn))); - MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn))); - - ++OpIdx; - } - - return true; -} - -// A6.3.4 Table A6-15 Miscellaneous control instructions -// A8.6.41 DMB -// A8.6.42 DSB -// A8.6.49 ISB -static inline bool t2MiscCtrlInstr(uint32_t insn) { - if (slice(insn, 31, 20) == 0xf3b && slice(insn, 15, 14) == 2 && - slice(insn, 12, 12) == 0) - return true; - - return false; -} - -// A6.3.4 Branches and miscellaneous control -// -// A8.6.16 B -// Branches: t2B, t2Bcc -> imm operand -// -// Branches: t2TPsoft -> no operand -// -// A8.6.23 BL, BLX (immediate) -// Branches (defined in ARMInstrThumb.td): tBL, tBLXi -> imm operand -// -// A8.6.26 -// t2BXJ -> Rn -// -// Miscellaneous control: -// -> no operand (except pred-imm pred-ccr for CLREX, memory barrier variants) -// -// Hint: t2NOP, t2YIELD, t2WFE, t2WFI, t2SEV -// -> no operand (except pred-imm pred-ccr) -// -// t2DBG -> imm4 = Inst{3-0} -// -// t2MRS/t2MRSsys -> Rs -// t2MSR/t2MSRsys -> Rn mask=Inst{11-8} -// t2SMC -> imm4 = Inst{19-16} -static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - if (NumOps == 0) - return true; - - if (Opcode == ARM::t2DMB || Opcode == ARM::t2DSB) { - // Inst{3-0} encodes the memory barrier option for the variants. - unsigned opt = slice(insn, 3, 0); - switch (opt) { - case ARM_MB::SY: case ARM_MB::ST: - case ARM_MB::ISH: case ARM_MB::ISHST: - case ARM_MB::NSH: case ARM_MB::NSHST: - case ARM_MB::OSH: case ARM_MB::OSHST: - MI.addOperand(MCOperand::CreateImm(opt)); - NumOpsAdded = 1; - return true; - default: - return false; - } - } - - if (t2MiscCtrlInstr(insn)) - return true; - - switch (Opcode) { - case ARM::t2CLREX: - case ARM::t2NOP: - case ARM::t2YIELD: - case ARM::t2WFE: - case ARM::t2WFI: - case ARM::t2SEV: - return true; - default: - break; - } - - // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different - // opcodes which match the same real instruction. This is needed since there's - // no current handling of optional arguments. Fix here when a better handling - // of optional arguments is implemented. - if (Opcode == ARM::t2CPS3p) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod - MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5))); // iflags - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode - NumOpsAdded = 3; - return true; - } - if (Opcode == ARM::t2CPS2p) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod - MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5))); // iflags - NumOpsAdded = 2; - return true; - } - if (Opcode == ARM::t2CPS1p) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode - NumOpsAdded = 1; - return true; - } - - // DBG has its option specified in Inst{3-0}. - if (Opcode == ARM::t2DBG) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0))); - NumOpsAdded = 1; - return true; - } - - // MRS and MRSsys take one GPR reg Rs. - if (Opcode == ARM::t2MRS || Opcode == ARM::t2MRSsys) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRs(insn)))); - NumOpsAdded = 1; - return true; - } - // BXJ takes one GPR reg Rn. - if (Opcode == ARM::t2BXJ) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - NumOpsAdded = 1; - return true; - } - // MSR take a mask, followed by one GPR reg Rn. The mask contains the R Bit in - // bit 4, and the special register fields in bits 3-0. - if (Opcode == ARM::t2MSR) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 20) << 4 /* R Bit */ | - slice(insn, 11, 8) /* Special Reg */)); - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - NumOpsAdded = 2; - return true; - } - // SMC take imm4. - if (Opcode == ARM::t2SMC) { - MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 16))); - NumOpsAdded = 1; - return true; - } - - // Some instructions have predicate operands first before the immediate. - if (Opcode == ARM::tBLXi || Opcode == ARM::tBL) { - // Handling the two predicate operands before the imm operand. - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) - NumOpsAdded += 2; - else { - DEBUG(errs() << "Expected predicate operands not found.\n"); - return false; - } - } - - // Add the imm operand. - int Offset = 0; - - switch (Opcode) { - default: - assert(0 && "Unexpected opcode"); - return false; - case ARM::t2B: - Offset = decodeImm32_B_EncodingT4(insn); - break; - case ARM::t2Bcc: - Offset = decodeImm32_B_EncodingT3(insn); - break; - case ARM::tBL: - Offset = decodeImm32_BL(insn); - break; - case ARM::tBLXi: - Offset = decodeImm32_BLX(insn); - break; - } - - 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; - - return true; -} - -static inline bool Thumb2PreloadOpcode(unsigned Opcode) { - switch (Opcode) { - default: - return false; - case ARM::t2PLDi12: case ARM::t2PLDi8: - case ARM::t2PLDs: - case ARM::t2PLDWi12: case ARM::t2PLDWi8: - case ARM::t2PLDWs: - case ARM::t2PLIi12: case ARM::t2PLIi8: - case ARM::t2PLIs: - return true; - } -} - -static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - // Preload Data/Instruction requires either 2 or 3 operands. - // t2PLDi12, t2PLDi8, t2PLDpci: Rn [+/-]imm12/imm8 - // t2PLDr: Rn Rm - // t2PLDs: Rn Rm imm2=Inst{5-4} - // Same pattern applies for t2PLDW* and t2PLI*. - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 2 && - OpInfo[0].RegClass == ARM::GPRRegClassID && - "Expect >= 2 operands and first one as reg operand"); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRn(insn)))); - ++OpIdx; - - if (OpInfo[OpIdx].RegClass == ARM::rGPRRegClassID) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, - decodeRm(insn)))); - } else { - assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() - && !OpInfo[OpIdx].isOptionalDef() - && "Pure imm operand expected"); - int Offset = 0; - if (Opcode == ARM::t2PLDi8 || Opcode == ARM::t2PLDWi8 || - Opcode == ARM::t2PLIi8) { - // A8.6.117 Encoding T2: add = FALSE - unsigned Imm8 = getImm8(insn); - Offset = -1 * Imm8; - } else { - // The i12 forms. See, for example, A8.6.117 Encoding T1. - // Note that currently t2PLDi12 also handles the previously named t2PLDpci - // opcode, that's why we use decodeImm12(insn) which returns +/- imm12. - Offset = decodeImm12(insn); - } - MI.addOperand(MCOperand::CreateImm(Offset)); - } - ++OpIdx; - - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 && - !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - // Fills in the shift amount for t2PLDs, t2PLDWs, t2PLIs. - MI.addOperand(MCOperand::CreateImm(slice(insn, 5, 4))); - ++OpIdx; - } - - 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); - 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"); - return true; - } - - if (Load) { - if (!Word && R0 == 13) { - 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 - if (Half) { - 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"); - 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 -// A6.3.7 Load word -// -// For example, -// -// t2LDRi12: Rd Rn (+)imm12 -// t2LDRi8: Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1) -// t2LDRs: Rd Rn Rm ConstantShiftSpecifier (see also -// DisassembleThumb2DPSoReg) -// t2LDR_POST: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1) -// t2LDR_PRE: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1) -// -// t2STRi12: Rd Rn (+)imm12 -// t2STRi8: Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1) -// t2STRs: Rd Rn Rm ConstantShiftSpecifier (see also -// DisassembleThumb2DPSoReg) -// t2STR_POST: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1) -// t2STR_PRE: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1) -// -// Note that for indexed modes, the Rn(TIED_TO) operand needs to be populated -// correctly, as LLVM AsmPrinter depends on it. For indexed stores, the first -// operand is Rn; for all the other instructions, Rd is the first operand. -// -// Delegates to DisassembleThumb2PreLoad() for preload data/instruction. -// Delegates to DisassembleThumb2Ldpci() for load * literal operations. -static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - unsigned Rn = decodeRn(insn); - - if (Thumb2PreloadOpcode(Opcode)) - return DisassembleThumb2PreLoad(MI, Opcode, insn, NumOps, NumOpsAdded, B); - - // See, for example, A6.3.7 Load word: Table A6-18 Load word. - if (Load && Rn == 15) - return DisassembleThumb2Ldpci(MI, Opcode, insn, NumOps, NumOpsAdded, B); - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 3 && - OpInfo[0].RegClass > 0 && - OpInfo[1].RegClass > 0 && - "Expect >= 3 operands and first two as reg operands"); - - bool ThreeReg = (OpInfo[2].RegClass > 0); - bool TIED_TO = ThreeReg && MCID.getOperandConstraint(2, MCOI::TIED_TO) != -1; - bool Imm12 = !ThreeReg && slice(insn, 23, 23) == 1; // ARMInstrThumb2.td - - // Build the register operands, followed by the immediate. - unsigned R0 = 0, R1 = 0, R2 = 0; - unsigned Rd = decodeRd(insn); - int Imm = 0; - - if (!Load && TIED_TO) { - R0 = Rn; - R1 = Rd; - } else { - R0 = Rd; - R1 = Rn; - } - if (ThreeReg) { - if (TIED_TO) { - R2 = Rn; - Imm = decodeImm8(insn); - } else { - R2 = decodeRm(insn); - // See, for example, A8.6.64 LDRB (register). - // And ARMAsmPrinter::printT2AddrModeSoRegOperand(). - // LSL is the default shift opc, and LLVM does not expect it to be encoded - // as part of the immediate operand. - // Imm = ARM_AM::getSORegOpc(ARM_AM::lsl, slice(insn, 5, 4)); - Imm = slice(insn, 5, 4); - } - } else { - if (Imm12) - Imm = getImm12(insn); - else - Imm = decodeImm8(insn); - } - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - R0))); - ++OpIdx; - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - R1))); - ++OpIdx; - - if (ThreeReg) { - // This could be an offset register or a TIED_TO register. - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass, - R2))); - ++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"); - - MI.addOperand(MCOperand::CreateImm(Imm)); - ++OpIdx; - - return true; -} - -// A6.3.12 Data-processing (register) -// -// Two register operands [rotate]: Rs Rm [rotation(= (rotate:'000'))] -// Three register operands only: Rs Rn Rm -// Three register operands [rotate]: Rs Rn Rm [rotation(= (rotate:'000'))] -// -// Parallel addition and subtraction 32-bit Thumb instructions: Rs Rn Rm -// -// Miscellaneous operations: Rs [Rn] Rm -static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCInstrDesc &MCID = ARMInsts[Opcode]; - const MCOperandInfo *OpInfo = MCID.OpInfo; - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; - - assert(NumOps >= 2 && - OpInfo[0].RegClass > 0 && - OpInfo[1].RegClass > 0 && - "Expect >= 2 operands and first two as reg operands"); - - // Build the register operands, followed by the optional rotation amount. - - bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass > 0; - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeRs(insn)))); - ++OpIdx; - - if (ThreeReg) { - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass, - decodeRn(insn)))); - ++OpIdx; - } - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass, - decodeRm(insn)))); - ++OpIdx; - - if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 - && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) { - // Add the rotation amount immediate. - MI.addOperand(MCOperand::CreateImm(slice(insn, 5, 4))); - ++OpIdx; - } - - return true; -} - -// A6.3.16 Multiply, multiply accumulate, and absolute difference -// -// t2MLA, t2MLS, t2SMMLA, t2SMMLS: Rs Rn Rm Ra=Inst{15-12} -// t2MUL, t2SMMUL: Rs Rn Rm -// t2SMLA[BB|BT|TB|TT|WB|WT]: Rs Rn Rm Ra=Inst{15-12} -// t2SMUL[BB|BT|TB|TT|WB|WT]: Rs Rn Rm -// -// Dual halfword multiply: t2SMUAD[X], t2SMUSD[X], t2SMLAD[X], t2SMLSD[X]: -// Rs Rn Rm Ra=Inst{15-12} -// -// Unsigned Sum of Absolute Differences [and Accumulate] -// Rs Rn Rm [Ra=Inst{15-12}] -static bool DisassembleThumb2Mul(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - - assert(NumOps >= 3 && - OpInfo[0].RegClass == ARM::rGPRRegClassID && - OpInfo[1].RegClass == ARM::rGPRRegClassID && - OpInfo[2].RegClass == ARM::rGPRRegClassID && - "Expect >= 3 operands and first three as reg operands"); - - // Build the register operands. - - bool FourReg = NumOps > 3 && OpInfo[3].RegClass == ARM::rGPRRegClassID; - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRs(insn)))); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRn(insn)))); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRm(insn)))); - - if (FourReg) - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRd(insn)))); - - NumOpsAdded = FourReg ? 4 : 3; - - return true; -} - -// A6.3.17 Long multiply, long multiply accumulate, and divide -// -// t2SMULL, t2UMULL, t2SMLAL, t2UMLAL, t2UMAAL: RdLo RdHi Rn Rm -// where RdLo = Inst{15-12} and RdHi = Inst{11-8} -// -// Halfword multiple accumulate long: t2SMLAL: RdLo RdHi Rn Rm -// where RdLo = Inst{15-12} and RdHi = Inst{11-8} -// -// Dual halfword multiple: t2SMLALD[X], t2SMLSLD[X]: RdLo RdHi Rn Rm -// where RdLo = Inst{15-12} and RdHi = Inst{11-8} -// -// Signed/Unsigned divide: t2SDIV, t2UDIV: Rs Rn Rm -static bool DisassembleThumb2LongMul(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo; - - assert(NumOps >= 3 && - OpInfo[0].RegClass == ARM::rGPRRegClassID && - OpInfo[1].RegClass == ARM::rGPRRegClassID && - OpInfo[2].RegClass == ARM::rGPRRegClassID && - "Expect >= 3 operands and first three as reg operands"); - - bool FourReg = NumOps > 3 && OpInfo[3].RegClass == ARM::rGPRRegClassID; - - // Build the register operands. - - if (FourReg) - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRd(insn)))); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRs(insn)))); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRn(insn)))); - - MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID, - decodeRm(insn)))); - - if (FourReg) - NumOpsAdded = 4; - else - NumOpsAdded = 3; - - return true; -} - -// See A6.3 32-bit Thumb instruction encoding for instruction classes -// corresponding to (op1, op2, op). -// -// Table A6-9 32-bit Thumb instruction encoding -// op1 op2 op Instruction class, see -// --- ------- -- ----------------------------------------------------------- -// 01 00xx0xx - Load/store multiple on page A6-23 -// 00xx1xx - Load/store dual, load/store exclusive, table branch on -// page A6-24 -// 01xxxxx - Data-processing (shifted register) on page A6-31 -// 1xxxxxx - Coprocessor instructions on page A6-40 -// 10 x0xxxxx 0 Data-processing (modified immediate) on page A6-15 -// x1xxxxx 0 Data-processing (plain binary immediate) on page A6-19 -// - 1 Branches and miscellaneous control on page A6-20 -// 11 000xxx0 - Store single data item on page A6-30 -// 001xxx0 - Advanced SIMD element or structure load/store instructions -// on page A7-27 -// 00xx001 - Load byte, memory hints on page A6-28 -// 00xx011 - Load halfword, memory hints on page A6-26 -// 00xx101 - Load word on page A6-25 -// 00xx111 - UNDEFINED -// 010xxxx - Data-processing (register) on page A6-33 -// 0110xxx - Multiply, multiply accumulate, and absolute difference on -// page A6-38 -// 0111xxx - Long multiply, long multiply accumulate, and divide on -// page A6-39 -// 1xxxxxx - Coprocessor instructions on page A6-40 -// -static bool DisassembleThumb2(uint16_t op1, uint16_t op2, uint16_t op, - MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, - unsigned &NumOpsAdded, BO B) { - - switch (op1) { - case 1: - if (slice(op2, 6, 5) == 0) { - if (slice(op2, 2, 2) == 0) { - // Load/store multiple. - return DisassembleThumb2LdStMul(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - } - - // Load/store dual, load/store exclusive, table branch, otherwise. - assert(slice(op2, 2, 2) == 1 && "Thumb2 encoding error!"); - if ((ARM::t2LDREX <= Opcode && Opcode <= ARM::t2LDREXH) || - (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH)) { - // Load/store exclusive. - return DisassembleThumb2LdStEx(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - } - if (Opcode == ARM::t2LDRDi8 || - Opcode == ARM::t2LDRD_PRE || Opcode == ARM::t2LDRD_POST || - Opcode == ARM::t2STRDi8 || - Opcode == ARM::t2STRD_PRE || Opcode == ARM::t2STRD_POST) { - // Load/store dual. - return DisassembleThumb2LdStDual(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - } - if (Opcode == ARM::t2TBB || Opcode == ARM::t2TBH) { - // Table branch. - return DisassembleThumb2TB(MI, Opcode, insn, NumOps, NumOpsAdded, B); - } - } else if (slice(op2, 6, 5) == 1) { - // Data-processing (shifted register). - return DisassembleThumb2DPSoReg(MI, Opcode, insn, NumOps, NumOpsAdded, B); - } - - // FIXME: A6.3.18 Coprocessor instructions - // But see ThumbDisassembler::getInstruction(). - - break; - case 2: - if (op == 0) { - if (slice(op2, 5, 5) == 0) - // Data-processing (modified immediate) - return DisassembleThumb2DPModImm(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - if (Thumb2SaturateOpcode(Opcode)) - return DisassembleThumb2Sat(MI, Opcode, insn, NumOpsAdded, B); - - // Data-processing (plain binary immediate) - return DisassembleThumb2DPBinImm(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - } - // Branches and miscellaneous control on page A6-20. - return DisassembleThumb2BrMiscCtrl(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - case 3: - switch (slice(op2, 6, 5)) { - case 0: - // Load/store instructions... - if (slice(op2, 0, 0) == 0) { - if (slice(op2, 4, 4) == 0) { - // Store single data item on page A6-30 - return DisassembleThumb2LdSt(false, MI,Opcode,insn,NumOps,NumOpsAdded, - B); - } else { - // FIXME: Advanced SIMD element or structure load/store instructions. - // But see ThumbDisassembler::getInstruction(). - ; - } - } else { - // Table A6-9 32-bit Thumb instruction encoding: Load byte|halfword|word - return DisassembleThumb2LdSt(true, MI, Opcode, insn, NumOps, - NumOpsAdded, B); - } - break; - case 1: - if (slice(op2, 4, 4) == 0) { - // A6.3.12 Data-processing (register) - return DisassembleThumb2DPReg(MI, Opcode, insn, NumOps, NumOpsAdded, B); - } else if (slice(op2, 3, 3) == 0) { - // A6.3.16 Multiply, multiply accumulate, and absolute difference - return DisassembleThumb2Mul(MI, Opcode, insn, NumOps, NumOpsAdded, B); - } else { - // A6.3.17 Long multiply, long multiply accumulate, and divide - return DisassembleThumb2LongMul(MI, Opcode, insn, NumOps, NumOpsAdded, - B); - } - break; - default: - // FIXME: A6.3.18 Coprocessor instructions - // But see ThumbDisassembler::getInstruction(). - ; - break; - } - - break; - default: - assert(0 && "Thumb2 encoding error!"); - break; - } - - return false; -} - -static bool DisassembleThumbFrm(MCInst &MI, unsigned Opcode, uint32_t insn, - unsigned short NumOps, unsigned &NumOpsAdded, BO Builder) { - - uint16_t HalfWord = slice(insn, 31, 16); - - if (HalfWord == 0) { - // A6.2 16-bit Thumb instruction encoding - // op = bits[15:10] - uint16_t op = slice(insn, 15, 10); - return DisassembleThumb1(op, MI, Opcode, insn, NumOps, NumOpsAdded, - Builder); - } - - unsigned bits15_11 = slice(HalfWord, 15, 11); - - // A6.1 Thumb instruction set encoding - if (!(bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F)) { - assert("Bits[15:11] first halfword of Thumb2 instruction is out of range"); - return false; - } - - // A6.3 32-bit Thumb instruction encoding - - uint16_t op1 = slice(HalfWord, 12, 11); - uint16_t op2 = slice(HalfWord, 10, 4); - uint16_t op = slice(insn, 15, 15); - - return DisassembleThumb2(op1, op2, op, MI, Opcode, insn, NumOps, NumOpsAdded, - Builder); -} Modified: llvm/trunk/lib/Target/ARM/Makefile URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Makefile?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Makefile (original) +++ llvm/trunk/lib/Target/ARM/Makefile Tue Aug 9 15:55:18 2011 @@ -18,7 +18,7 @@ ARMGenCodeEmitter.inc ARMGenCallingConv.inc \ ARMGenDecoderTables.inc ARMGenEDInfo.inc \ ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \ - ARMGenMCPseudoLowering.inc + ARMGenMCPseudoLowering.inc ARMGenDisassemblerTables.inc DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc Modified: llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt Tue Aug 9 15:55:18 2011 @@ -60,11 +60,14 @@ # CHECK: ldrh r0, [r2], #0 0xb0 0x00 0xd2 0xe0 +# CHECK: ldrh r0, [r2] +0xb0 0x00 0xd2 0xe1 + # CHECK: ldrht r0, [r2], #15 0xbf 0x00 0xf2 0xe0 # CHECK: ldrsbtvs lr, [r2], -r9 -0xd9 0xe9 0x32 0x60 +0xd9 0xe0 0x32 0x60 # CHECK: lsls r0, r2, #31 0x82 0x0f 0xb0 0xe1 @@ -177,7 +180,7 @@ 0x15 0xff 0x2f 0x01 # CHECK: uqadd16mi r6, r11, r8 -0x18 0x60 0x6b 0x46 +0x18 0x6F 0x6b 0x46 # CHECK: str r0, [sp, #4] 0x04 0x00 0x8d 0xe5 @@ -230,7 +233,7 @@ # CHECK: umull r1, r2, r3, r4 0x93 0x14 0x82 0xe0 -# CHECK: pld [pc, #-0] +# CHECK: pldw [pc, #-0] 0x00 0xf0 0x1f 0xf5 # CHECK: pli [pc, #-0] Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,8 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=60 Name=BFI Format=ARM_FORMAT_DPFRM(4) -# 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 +# 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: 1| 0: 1: 1: 0| # ------------------------------------------------------------------------------------------------- Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,10 +1,11 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 +# 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # invalid imod value (0b01) 0xc0 0x67 0x4 0xf1 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # invalid (imod, M, iflags) combination 0x93 0x1c 0x02 0xf1 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=1908 Name=t2DMB 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=102 Name=DSB Format=ARM_FORMAT_MISCFRM(26) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,7 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=0 Name=PHI Format=(42) -# 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 +# 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: 0: 1| 1: 1: 0: 0| 0: 0: 0: 1| 1: 1: 1: 1| 1: 0: 1: 1| 0: 1: 0: 0| 1: 0: 0: 1| 0: 0: 1: 0| # ------------------------------------------------------------------------------------------------- Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,7 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=0 Name=PHI Format=(42) -# 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 +# 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| 0: 0: 1: 1| 0: 1: 1: 1| 0: 1: 0: 1| 0: 0: 0: 1| 0: 0: 0: 1| 0: 0: 0: 0| # ------------------------------------------------------------------------------------------------- Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # LDR_PRE/POST has encoding Inst{4} = 0. 0xde 0x69 0x18 0x46 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,7 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=171 Name=MCR Format=ARM_FORMAT_BRFRM(2) -# 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 +# 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: 1: 0| 1: 1: 1: 0| 1: 0: 1: 0| 0: 0: 0: 0| 0: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 1| 1: 0: 1: 1| # ------------------------------------------------------------------------------------------------- Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=185 Name=MOVTi16 Format=ARM_FORMAT_DPFRM(4) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,7 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=0 Name=PHI Format=(42) -# 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 +# 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: 0: 0: 1| 1: 0: 1: 1| 1: 1: 0: 0| 1: 1: 0: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 1: 0| # ------------------------------------------------------------------------------------------------- Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,7 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5) -# 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 +# 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: 0: 1| 0: 0: 0: 1| 1: 0: 1: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 0: 1: 0| 1: 0: 0: 1| 0: 0: 1: 1| # ------------------------------------------------------------------------------------------------- Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,7 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=0 Name=PHI Format=(42) -# 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 +# 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: 0: 0: 1| 1: 0: 1: 1| 1: 1: 0: 0| 1: 1: 0: 1| 0: 0: 0: 1| 0: 0: 0: 0| 0: 0: 1: 0| # ------------------------------------------------------------------------------------------------- Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=206 Name=MSRi Format=ARM_FORMAT_BRFRM(2) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,7 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=134 Name=LDMIA Format=ARM_FORMAT_LDSTMULFRM(10) -# 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 +# 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| 1: 0: 0: 1| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 1| 0: 0: 1: 1| 0: 0: 1: 0| # ------------------------------------------------------------------------------------------------- Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=261 Name=RSCrs Format=ARM_FORMAT_DPSOREGFRM(5) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=271 Name=SBFX Format=ARM_FORMAT_DPFRM(4) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=284 Name=SMLAD Format=ARM_FORMAT_MULFRM(1) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,7 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=0 Name=PHI Format=(42) -# 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 +# 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| 1: 1: 0: 0| 0: 1: 0: 1| 0: 0: 0: 1| 1: 1: 0: 0| 1: 0: 0: 0| 0: 0: 1: 1| # ------------------------------------------------------------------------------------------------- Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=322 Name=SSAT Format=ARM_FORMAT_SATFRM(13) # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=390 Name=SXTBr_rot Format=ARM_FORMAT_EXTFRM(14) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,11 +1,11 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=419 Name=UMAAL Format=ARM_FORMAT_MULFRM(1) -# 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 +# 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: 0: 0: 0| 0: 1: 0: 0| 1: 1: 1: 1| 1: 0: 1: 1| 1: 1: 1: 1| 1: 0: 0: 1| 1: 0: 0: 0| # ------------------------------------------------------------------------------------------------- # # A8.6.244 UMAAL # if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE; -0x98 0xbf 0x4f 0xf0 +0x98 0xbf 0x4f 0xf0 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=426 Name=UQADD8 Format=ARM_FORMAT_DPFRM(4) # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,11 +1,11 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} # Opcode=871 Name=VLD3DUPd32_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 +# 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: 1: 0| 0: 0: 1: 0| 1: 1: 1: 0| 1: 0: 0: 1| 0: 0: 1: 0| # ------------------------------------------------------------------------------------------------- -# +# # A8.6.315 VLD3 (single 3-element structure to all lanes) # The a bit must be encoded as 0. 0xa2 0xf9 0x92 0x2e Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # core registers out of range 0xa5 0xba 0x72 0xed Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=1225 Name=VQADDsv16i8 Format=ARM_FORMAT_N3Reg(37) # 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 Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt Tue Aug 9 15:55:18 2011 @@ -1,7 +1,8 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # Opcode=1641 Name=VST2b32_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 +# 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| 0: 0: 0: 0| 0: 0: 1: 1| 0: 0: 0: 0| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 1: 1| # ------------------------------------------------------------------------------------------------- Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,10 +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 +# 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 Modified: 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,10 +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 +# 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/invalid-t2STR_POST-thumb.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt Tue Aug 9 15:55:18 2011 @@ -1,4 +1,5 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} +# XFAIL: * # 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 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=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt Tue Aug 9 15:55:18 2011 @@ -24,7 +24,7 @@ # CHECK: vld1.32 {d3[], d4[]}, [r0, :32]! 0xbd 0x3c 0xa0 0xf4 -# CHECK: vld4.16 {d3[], d4[], d5[], d6[]}, [r0, :64]! +# CHECK: vld4.16 {d3[], d5[], d7[], d9[]}, [r0, :64]! 0x7d 0x3f 0xa0 0xf4 # CHECK: vorr d0, d15, d15 @@ -87,5 +87,5 @@ # CHECK: usada8mi r8, r9, r5, r9 0x19 0x95 0x88 0x47 -# CHECK: vext.8 q4, q2, q1, #4 +# CHECK: vext.32 q4, q2, q1, #1 0x42 0x84 0xb4 0xf2 Modified: llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp?rev=137144&r1=137143&r2=137144&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp Tue Aug 9 15:55:18 2011 @@ -128,12 +128,5 @@ return; } - // Fixed-instruction-length targets use a common disassembler. - // ARM use its own implementation for now. - if (Target.getName() == "ARM") { - ARMDecoderEmitter(Records).run(OS); - return; - } - FixedLenDecoderEmitter(Records).run(OS); } From wendling at apple.com Tue Aug 9 15:57:53 2011 From: wendling at apple.com (Bill Wendling) Date: Tue, 09 Aug 2011 13:57:53 -0700 Subject: [llvm-commits] [PATCH] Revised LandingPadInst Patch In-Reply-To: <4978D8A1-9343-4521-844D-81D0B62E4FE9@apple.com> References: <4E40E16E.6090908@free.fr> <52C08EA4-D7BB-4B65-8850-582C6078F246@apple.com> <4E40F6F1.1030507@free.fr> <4E40FECB.5090901@free.fr> <4978D8A1-9343-4521-844D-81D0B62E4FE9@apple.com> Message-ID: <1D151E9C-4518-4B61-996E-A1985E4F1867@apple.com> On Aug 9, 2011, at 11:25 AM, Bill Wendling wrote: > On Aug 9, 2011, at 2:32 AM, Duncan Sands wrote: > >> Hi Bill, >> >>>> An alternative is to have: for a catch, an operand which is a (bitcast) global >>>> or null*; for a filter, an operand which is a constant array, each element of >>>> which is a (bitcast) global or null*. Thus each clause would only take up one >>>> operand. >>> >>> >>> The "OperandList" setup for the Instructions is rather complex as it is. Having two or more OperandLists (one list for each 'filter' array) gets very complex very quickly. And we want an OperandList-like data structure so that it can track uses of the LLVM IR objects. >> >> I think you misunderstood. I meant something like this: >> >> @_ZTIc = external constant i8* >> @_ZTId = external constant i8* >> @_ZTIPKc = external constant i8* >> >> %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 >> cleanup >> i8** @_ZTIc ; catch because global variable >> [0 x i8**] [] ; (empty) filter because constant array >> i8** @_ZTIc ; catch because global variable >> [0 x i8**] [] ; (empty) filter because constant array >> i8** @_ZTId ; catch because global variable >> [2 x i8**] [ i8** @_ZTIPKc, i8** @_ZTId ] ; filter because constant array >> >> Ciao, Duncan. > > Ah! I think I understand. So it's not so much that the arrays would be splatted out into the OperandList, but that they would be referenced from there (or something). > > BTW, care must be taken. An empty filter has a specific meaning in this scheme: it's equivalent to a "throw()" in C++. > That worked! Here's the revised patch. It now has no more (obvious) grossness in the LandingPadInst instruction. I modified the LangRef.html doc to show this change. My only concern with going this route is that we no longer have a way to add additional clauses to the instruction. I could modify the patch slightly to add the clause type to the OperandList. So something like this: OperandList[1] = ConstantInt::get(LandingPadInst::Catch) OperandList[2] = i8** @_ZTIc OperandList[3] = ConstantInst::get(LandingPadInst::Filter) OperandList[4] = [2 x i8**] [ i8** @_ZTIPKc, i8** @_ZTId ] etc. Please review this and let me know if there are any further issues. :-) -bw -------------- next part -------------- A non-text attachment was scrubbed... Name: landingpadinst.3.diff Type: application/octet-stream Size: 34960 bytes Desc: not available Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110809/d244538d/attachment.obj -------------- next part -------------- From eli.friedman at gmail.com Tue Aug 9 16:07:11 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 09 Aug 2011 21:07:11 -0000 Subject: [llvm-commits] [llvm] r137145 - /llvm/trunk/docs/Atomics.html Message-ID: <20110809210711.371622A6C12E@llvm.org> Author: efriedma Date: Tue Aug 9 16:07:10 2011 New Revision: 137145 URL: http://llvm.org/viewvc/llvm-project?rev=137145&view=rev Log: First draft of the practical guide to atomics. This is mostly descriptive of the intended state once atomic load and store have landed. Added: llvm/trunk/docs/Atomics.html Added: llvm/trunk/docs/Atomics.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/Atomics.html?rev=137145&view=auto ============================================================================== --- llvm/trunk/docs/Atomics.html (added) +++ llvm/trunk/docs/Atomics.html Tue Aug 9 16:07:10 2011 @@ -0,0 +1,295 @@ + + + + LLVM Atomic Instructions and Concurrency Guide + + + + +

    + LLVM Atomic Instructions and Concurrency Guide +

    + +
      +
    1. Introduction
    2. +
    3. Load and store
    4. +
    5. Atomic orderings
    6. +
    7. Other atomic instructions
    8. +
    9. Atomics and IR optimization
    10. +
    11. Atomics and Codegen
    12. +
    + +
    +

    Written by Eli Friedman

    +
    + + +

    + Introduction +

    + + +
    + +

    Historically, LLVM has not had very strong support for concurrency; some +minimal intrinsics were provided, and volatile was used in some +cases to achieve rough semantics in the presence of concurrency. However, this +is changing; there are now new instructions which are well-defined in the +presence of threads and asynchronous signals, and the model for existing +instructions has been clarified in the IR.

    + +

    The atomic instructions are designed specifically to provide readable IR and + optimized code generation for the following:

    +
      +
    • The new C++0x <atomic> header.
    • +
    • Proper semantics for Java-style memory, for both volatile and + regular shared variables.
    • +
    • gcc-compatible __sync_* builtins.
    • +
    • Other scenarios with atomic semantics, including static + variables with non-trivial constructors in C++.
    • +
    + +

    This document is intended to provide a guide to anyone either writing a + frontend for LLVM or working on optimization passes for LLVM with a guide + for how to deal with instructions with special semantics in the presence of + concurrency. This is not intended to be a precise guide to the semantics; + the details can get extremely complicated and unreadable, and are not + usually necessary.

    + +
    + + +

    + Load and store +

    + + +
    + +

    The basic 'load' and 'store' allow a variety of + optimizations, but can have unintuitive results in a concurrent environment. + For a frontend writer, the rule is essentially that all memory accessed + with basic loads and stores by multiple threads should be protected by a + lock or other synchronization; otherwise, you are likely to run into + undefined behavior. (Do not use volatile as a substitute for atomics; it + might work on some platforms, but does not provide the necessary guarantees + in general.)

    + +

    From the optimizer's point of view, the rule is that if there + are not any instructions with atomic ordering involved, concurrency does not + matter, with one exception: if a variable might be visible to another + thread or signal handler, a store cannot be inserted along a path where it + might not execute otherwise. Note that speculative loads are allowed; + a load which is part of a race returns undef, but is not + undefined behavior.

    + +

    For cases where simple loads and stores are not sufficient, LLVM provides + atomic loads and stores with varying levels of guarantees.

    + +
    + + +

    + Atomic orderings +

    + + +
    + +

    In order to achieve a balance between performance and necessary guarantees, + there are six levels of atomicity. They are listed in order of strength; + each level includes all the guarantees of the previous level except for + Acquire/Release.

    + +

    Unordered is the lowest level of atomicity. It essentially guarantees that + races produce somewhat sane results instead of having undefined behavior. + This is intended to match the Java memory model for shared variables. It + cannot be used for synchronization, but is useful for Java and other + "safe" languages which need to guarantee that the generated code never + exhibits undefined behavior. Note that this guarantee is cheap on common + platforms for loads of a native width, but can be expensive or unavailable + for wider loads, like a 64-bit load on ARM. (A frontend for a "safe" + language would normally split a 64-bit load on ARM into two 32-bit + unordered loads.) In terms of the optimizer, this prohibits any + transformation that transforms a single load into multiple loads, + transforms a store into multiple stores, narrows a store, or stores a + value which would not be stored otherwise. Some examples of unsafe + optimizations are narrowing an assignment into a bitfield, rematerializing + a load, and turning loads and stores into a memcpy call. Reordering + unordered operations is safe, though, and optimizers should take + advantage of that because unordered operations are common in + languages that need them.

    + +

    Monotonic is the weakest level of atomicity that can be used in + synchronization primitives, although it does not provide any general + synchronization. It essentially guarantees that if you take all the + operations affecting a specific address, a consistent ordering exists. + This corresponds to the C++0x/C1x memory_order_relaxed; see + those standards for the exact definition. If you are writing a frontend, do + not use the low-level synchronization primitives unless you are compiling + a language which requires it or are sure a given pattern is correct. In + terms of the optimizer, this can be treated as a read+write on the relevant + memory location (and alias analysis will take advantage of that). In + addition, it is legal to reorder non-atomic and Unordered loads around + Monotonic loads. CSE/DSE and a few other optimizations are allowed, but + Monotonic operations are unlikely to be used in ways which would make + those optimizations useful.

    + +

    Acquire provides a barrier of the sort necessary to acquire a lock to access + other memory with normal loads and stores. This corresponds to the + C++0x/C1x memory_order_acquire. This is a low-level + synchronization primitive. In general, optimizers should treat this like + a nothrow call.

    + +

    Release is similar to Acquire, but with a barrier of the sort necessary to + release a lock.This corresponds to the C++0x/C1x + memory_order_release.

    + +

    AcquireRelease (acq_rel in IR) provides both an Acquire and a Release barrier. + This corresponds to the C++0x/C1x memory_order_acq_rel. In general, + optimizers should treat this like a nothrow call.

    + +

    SequentiallyConsistent (seq_cst in IR) provides Acquire and/or + Release semantics, and in addition guarantees a total ordering exists with + all other SequentiallyConsistent operations. This corresponds to the + C++0x/C1x memory_order_seq_cst, and Java volatile. The intent + of this ordering level is to provide a programming model which is relatively + easy to understand. In general, optimizers should treat this like a + nothrow call.

    + +
    + + +

    + Other atomic instructions +

    + + +
    + +

    cmpxchg and atomicrmw are essentially like an + atomic load followed by an atomic store (where the store is conditional for + cmpxchg), but no other memory operation operation can happen + between the load and store.

    + +

    A fence provides Acquire and/or Release ordering which is not + part of another operation; it is normally used along with Monotonic memory + operations. A Monotonic load followed by an Acquire fence is roughly + equivalent to an Acquire load.

    + +

    Frontends generating atomic instructions generally need to be aware of the + target to some degree; atomic instructions are guaranteed to be lock-free, + and therefore an instruction which is wider than the target natively supports + can be impossible to generate.

    + +
    + + +

    + Atomics and IR optimization +

    + + +
    + +

    Predicates for optimizer writers to query: +

      +
    • isSimple(): A load or store which is not volatile or atomic. This is + what, for example, memcpyopt would check for operations it might + transform. +
    • isUnordered(): A load or store which is not volatile and at most + Unordered. This would be checked, for example, by LICM before hoisting + an operation. +
    • mayReadFromMemory()/mayWriteToMemory(): Existing predicate, but note + that they returns true for any operation which is volatile or at least + Monotonic. +
    • Alias analysis: Note that AA will return ModRef for anything Acquire or + Release, and for the address accessed by any Monotonic operation. +
    + +

    There are essentially two components to supporting atomic operations. The + first is making sure to query isSimple() or isUnordered() instead + of isVolatile() before transforming an operation. The other piece is + making sure that a transform does not end up replacing, for example, an + Unordered operation with a non-atomic operation. Most of the other + necessary checks automatically fall out from existing predicates and + alias analysis queries.

    + +

    Some examples of how optimizations interact with various kinds of atomic + operations: +

      +
    • memcpyopt: An atomic operation cannot be optimized into part of a + memcpy/memset, including unordered loads/stores. It can pull operations + across some atomic operations. +
    • LICM: Unordered loads/stores can be moved out of a loop. It just treats + monotonic operations like a read+write to a memory location, and anything + stricter than that like a nothrow call. +
    • DSE: Unordered stores can be DSE'ed like normal stores. Monotonic stores + can be DSE'ed in some cases, but it's tricky to reason about, and not + especially important. +
    • Folding a load: Any atomic load from a constant global can be + constant-folded, because it cannot be observed. Similar reasoning allows + scalarrepl with atomic loads and stores. +
    + +
    + + +

    + Atomics and Codegen +

    + + +
    + +

    Atomic operations are represented in the SelectionDAG with + ATOMIC_* opcodes. On architectures which use barrier + instructions for all atomic ordering (like ARM), appropriate fences are + split out as the DAG is built.

    + +

    The MachineMemOperand for all atomic operations is currently marked as + volatile; this is not correct in the IR sense of volatile, but CodeGen + handles anything marked volatile very conservatively. This should get + fixed at some point.

    + +

    The implementation of atomics on LL/SC architectures (like ARM) is currently + a bit of a mess; there is a lot of copy-pasted code across targets, and + the representation is relatively unsuited to optimization (it would be nice + to be able to optimize loops involving cmpxchg etc.).

    + +

    On x86, all atomic loads generate a MOV. + SequentiallyConsistent stores generate an XCHG, other stores + generate a MOV. SequentiallyConsistent fences generate an + MFENCE, other fences do not cause any code to be generated. + cmpxchg uses the LOCK CMPXCHG instruction. + atomicrmw xchg uses XCHG, + atomicrmw add and atomicrmw sub use + XADD, and all other atomicrmw operations generate + a loop with LOCK CMPXCHG. Depending on the users of the + result, some atomicrmw operations can be translated into + operations like LOCK AND, but that does not work in + general.

    + +

    On ARM, MIPS, and many other RISC architectures, Acquire, Release, and + SequentiallyConsistent semantics require barrier instructions + for every such operation. Loads and stores generate normal instructions. + atomicrmw and cmpxchg generate LL/SC loops.

    + +
    + + + +
    +
    + Valid CSS + Valid HTML 4.01 + + LLVM Compiler Infrastructure
    + Last modified: $Date: 2011-08-09 02:07:00 -0700 (Tue, 09 Aug 2011) $ +
    + + + From resistor at mac.com Tue Aug 9 16:07:46 2011 From: resistor at mac.com (Owen Anderson) Date: Tue, 09 Aug 2011 21:07:46 -0000 Subject: [llvm-commits] [llvm] r137146 - in /llvm/trunk: lib/Target/ARM/Disassembler/ARMDisassembler.cpp test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt Message-ID: <20110809210746.13C552A6C12E@llvm.org> Author: resistor Date: Tue Aug 9 16:07:45 2011 New Revision: 137146 URL: http://llvm.org/viewvc/llvm-project?rev=137146&view=rev Log: Tighten Thumb1 branch predicate decoding. Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt 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=137146&r1=137145&r2=137146&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug 9 16:07:45 2011 @@ -592,6 +592,9 @@ static bool DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { if (Val == 0xF) return false; + // AL predicate is not allowed on Thumb1 branches. + if (Inst.getOpcode() == ARM::tBcc && Val == 0xE) + return false; Inst.addOperand(MCOperand::CreateImm(Val)); if (Val == ARMCC::AL) { Inst.addOperand(MCOperand::CreateReg(0)); Modified: 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=137146&r1=137145&r2=137146&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt Tue Aug 9 16:07:45 2011 @@ -1,5 +1,4 @@ # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding} -# XFAIL: * # 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 From resistor at mac.com Tue Aug 9 16:09:59 2011 From: resistor at mac.com (Owen Anderson) Date: Tue, 09 Aug 2011 21:09:59 -0000 Subject: [llvm-commits] [llvm] r137147 - /llvm/trunk/lib/Target/ARM/CMakeLists.txt Message-ID: <20110809210959.CB2B82A6C12E@llvm.org> Author: resistor Date: Tue Aug 9 16:09:59 2011 New Revision: 137147 URL: http://llvm.org/viewvc/llvm-project?rev=137147&view=rev Log: Attempt to fix CMake build. Modified: llvm/trunk/lib/Target/ARM/CMakeLists.txt Modified: llvm/trunk/lib/Target/ARM/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/CMakeLists.txt?rev=137147&r1=137146&r2=137147&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/CMakeLists.txt (original) +++ llvm/trunk/lib/Target/ARM/CMakeLists.txt Tue Aug 9 16:09:59 2011 @@ -13,6 +13,7 @@ tablegen(ARMGenSubtargetInfo.inc -gen-subtarget) tablegen(ARMGenEDInfo.inc -gen-enhanced-disassembly-info) tablegen(ARMGenDecoderTables.inc -gen-arm-decoder) +tablegen(ARMGenDisassemblerTables.inc -gen-disassembler) add_public_tablegen_target(ARMCommonTableGen) add_llvm_target(ARMCodeGen From eli.friedman at gmail.com Tue Aug 9 16:15:39 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 9 Aug 2011 14:15:39 -0700 Subject: [llvm-commits] [llvm] r137144 - in /llvm/trunk: lib/Target/ARM/ lib/Target/ARM/Disassembler/ test/MC/Disassembler/ARM/ utils/TableGen/ In-Reply-To: <20110809205519.AA7252A6C12E@llvm.org> References: <20110809205519.AA7252A6C12E@llvm.org> Message-ID: On Tue, Aug 9, 2011 at 1:55 PM, Owen Anderson wrote: > Author: resistor > Date: Tue Aug ?9 15:55:18 2011 > New Revision: 137144 > > URL: http://llvm.org/viewvc/llvm-project?rev=137144&view=rev > Log: > Replace the existing ARM disassembler with a new one based on the FixedLenDecoderEmitter. > This new disassembler can correctly decode all the testcases that the old one did, though > some "expected failure" testcases are XFAIL'd for now because it is not (yet) as strict in > operand checking as the old one was. > > Removed: > ? ?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/lib/Target/ARM/ARMInstrFormats.td > ? ?llvm/trunk/lib/Target/ARM/ARMInstrInfo.td > ? ?llvm/trunk/lib/Target/ARM/ARMInstrNEON.td > ? ?llvm/trunk/lib/Target/ARM/ARMInstrThumb.td > ? ?llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td > ? ?llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp > ? ?llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h > ? ?llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt > ? ?llvm/trunk/lib/Target/ARM/Makefile > ? ?llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-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-LSL-regform.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt > ? ?llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt > ? ?llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp 59 files changed, 2431 insertions(+), 7215 deletions(-) Nice. :) -Eli From grosbach at apple.com Tue Aug 9 16:22:41 2011 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 09 Aug 2011 21:22:41 -0000 Subject: [llvm-commits] [llvm] r137148 - /llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Message-ID: <20110809212241.E28D52A6C12E@llvm.org> Author: grosbach Date: Tue Aug 9 16:22:41 2011 New Revision: 137148 URL: http://llvm.org/viewvc/llvm-project?rev=137148&view=rev Log: ARM fix typo in pre-indexed store lowering. rdar://9915869 Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=137148&r1=137147&r2=137148&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Tue Aug 9 16:22:41 2011 @@ -5291,7 +5291,7 @@ } case ARM::STRi_preidx: case ARM::STRBi_preidx: { - unsigned NewOpc = MI->getOpcode() == ARM::STRr_preidx ? + unsigned NewOpc = MI->getOpcode() == ARM::STRi_preidx ? ARM::STR_PRE_IMM : ARM::STRB_PRE_IMM; // Decode the offset. unsigned Offset = MI->getOperand(4).getImm(); From resistor at mac.com Tue Aug 9 16:30:29 2011 From: resistor at mac.com (Owen Anderson) Date: Tue, 09 Aug 2011 21:30:29 -0000 Subject: [llvm-commits] [llvm] r137150 - /llvm/trunk/lib/Target/ARM/Makefile Message-ID: <20110809213029.B5CCD2A6C12E@llvm.org> Author: resistor Date: Tue Aug 9 16:30:29 2011 New Revision: 137150 URL: http://llvm.org/viewvc/llvm-project?rev=137150&view=rev Log: Don't continue generating the old-style decoder file. Modified: llvm/trunk/lib/Target/ARM/Makefile Modified: llvm/trunk/lib/Target/ARM/Makefile URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Makefile?rev=137150&r1=137149&r2=137150&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Makefile (original) +++ llvm/trunk/lib/Target/ARM/Makefile Tue Aug 9 16:30:29 2011 @@ -16,9 +16,8 @@ ARMGenAsmWriter.inc ARMGenAsmMatcher.inc \ ARMGenDAGISel.inc ARMGenSubtargetInfo.inc \ ARMGenCodeEmitter.inc ARMGenCallingConv.inc \ - ARMGenDecoderTables.inc ARMGenEDInfo.inc \ - ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \ - ARMGenMCPseudoLowering.inc ARMGenDisassemblerTables.inc + ARMGenEDInfo.inc ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \ + ARMGenMCPseudoLowering.inc ARMGenDisassemblerTables.inc DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc From benny.kra at googlemail.com Tue Aug 9 16:34:19 2011 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Tue, 09 Aug 2011 21:34:19 -0000 Subject: [llvm-commits] [llvm] r137151 - /llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp Message-ID: <20110809213420.0659D2A6C12E@llvm.org> Author: d0k Date: Tue Aug 9 16:34:19 2011 New Revision: 137151 URL: http://llvm.org/viewvc/llvm-project?rev=137151&view=rev Log: The new ARM disassembler disassembles "bx lr" as a special BX_ret instruction so target specific analysis isn't needed anymore. Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp Modified: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp?rev=137151&r1=137150&r2=137151&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp (original) +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp Tue Aug 9 16:34:19 2011 @@ -165,11 +165,6 @@ class ARMMCInstrAnalysis : public MCInstrAnalysis { public: ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} - virtual bool isBranch(const MCInst &Inst) const { - // Don't flag "bx lr" as a branch. - return MCInstrAnalysis::isBranch(Inst) && (Inst.getOpcode() != ARM::BX || - Inst.getOperand(0).getReg() != ARM::LR); - } virtual bool isUnconditionalBranch(const MCInst &Inst) const { // BCCs with the "always" predicate are unconditional branches. @@ -185,11 +180,6 @@ return MCInstrAnalysis::isConditionalBranch(Inst); } - virtual bool isReturn(const MCInst &Inst) const { - // Recognize "bx lr" as return. - return Inst.getOpcode() == ARM::BX && Inst.getOperand(0).getReg()==ARM::LR; - } - uint64_t evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size) const { // We only handle PCRel branches for now. From resistor at mac.com Tue Aug 9 16:36:11 2011 From: resistor at mac.com (Owen Anderson) Date: Tue, 09 Aug 2011 21:36:11 -0000 Subject: [llvm-commits] [llvm] r137153 - /llvm/trunk/lib/Target/ARM/CMakeLists.txt Message-ID: <20110809213611.3B20B2A6C12E@llvm.org> Author: resistor Date: Tue Aug 9 16:36:11 2011 New Revision: 137153 URL: http://llvm.org/viewvc/llvm-project?rev=137153&view=rev Log: Don't generate the old-style disassembler in CMake builds either. Modified: llvm/trunk/lib/Target/ARM/CMakeLists.txt Modified: llvm/trunk/lib/Target/ARM/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/CMakeLists.txt?rev=137153&r1=137152&r2=137153&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/CMakeLists.txt (original) +++ llvm/trunk/lib/Target/ARM/CMakeLists.txt Tue Aug 9 16:36:11 2011 @@ -12,7 +12,6 @@ tablegen(ARMGenCallingConv.inc -gen-callingconv) tablegen(ARMGenSubtargetInfo.inc -gen-subtarget) tablegen(ARMGenEDInfo.inc -gen-enhanced-disassembly-info) -tablegen(ARMGenDecoderTables.inc -gen-arm-decoder) tablegen(ARMGenDisassemblerTables.inc -gen-disassembler) add_public_tablegen_target(ARMCommonTableGen) From resistor at mac.com Tue Aug 9 16:38:14 2011 From: resistor at mac.com (Owen Anderson) Date: Tue, 09 Aug 2011 21:38:14 -0000 Subject: [llvm-commits] [llvm] r137154 - /llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Message-ID: <20110809213814.DFAC02A6C12E@llvm.org> Author: resistor Date: Tue Aug 9 16:38:14 2011 New Revision: 137154 URL: http://llvm.org/viewvc/llvm-project?rev=137154&view=rev Log: Silence an false-positive warning. Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp 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=137154&r1=137153&r2=137154&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug 9 16:38:14 2011 @@ -949,7 +949,7 @@ unsigned imm = fieldFromInstruction32(Val, 7, 5); unsigned U = fieldFromInstruction32(Val, 12, 1); - ARM_AM::ShiftOpc ShOp; + ARM_AM::ShiftOpc ShOp = ARM_AM::lsl; switch (type) { case 0: ShOp = ARM_AM::lsl; From benny.kra at googlemail.com Tue Aug 9 17:02:50 2011 From: benny.kra at googlemail.com (Benjamin Kramer) Date: Tue, 09 Aug 2011 22:02:50 -0000 Subject: [llvm-commits] [llvm] r137156 - in /llvm/trunk: lib/Target/ARM/Disassembler/ARMDisassembler.cpp test/MC/Disassembler/ARM/arm-tests.txt Message-ID: <20110809220250.6D1AD2A6C12C@llvm.org> Author: d0k Date: Tue Aug 9 17:02:50 2011 New Revision: 137156 URL: http://llvm.org/viewvc/llvm-project?rev=137156&view=rev Log: ARM Disassembler: sign extend branch immediates. Not sure about BLXi, but this is what the old disassembler did. Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt 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=137156&r1=137155&r2=137156&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug 9 17:02:50 2011 @@ -1214,11 +1214,11 @@ if (pred == 0xF) { Inst.setOpcode(ARM::BLXi); imm |= fieldFromInstruction32(Insn, 24, 1) << 1; - Inst.addOperand(MCOperand::CreateImm(imm)); + Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(imm))); return true; } - Inst.addOperand(MCOperand::CreateImm(imm)); + Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(imm))); if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false; return true; Modified: llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt?rev=137156&r1=137155&r2=137156&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt Tue Aug 9 17:02:50 2011 @@ -248,6 +248,9 @@ # CHECK: stc2 p2, cr4, [r9], {157} 0x9d 0x42 0x89 0xfc +# CHECK: bne #-24 +0xfa 0xff 0xff 0x1a + # CHECK: blx #60 0x0f 0x00 0x00 0xfa From grosbach at apple.com Tue Aug 9 17:12:37 2011 From: grosbach at apple.com (Jim Grosbach) Date: Tue, 09 Aug 2011 22:12:37 -0000 Subject: [llvm-commits] [llvm] r137158 - /llvm/trunk/lib/MC/MachObjectWriter.cpp Message-ID: <20110809221237.2CAD32A6C12C@llvm.org> Author: grosbach Date: Tue Aug 9 17:12:37 2011 New Revision: 137158 URL: http://llvm.org/viewvc/llvm-project?rev=137158&view=rev Log: Don't truncate MachO addresses. Assigned symbol addresses get truncated to 32-bits, even on 64-bit platforms. That's obviously bogus. For example, .globl _foo .equ _foo, 0x987654321ULL rdar://9922863 Modified: llvm/trunk/lib/MC/MachObjectWriter.cpp Modified: llvm/trunk/lib/MC/MachObjectWriter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MachObjectWriter.cpp?rev=137158&r1=137157&r2=137158&view=diff ============================================================================== --- llvm/trunk/lib/MC/MachObjectWriter.cpp (original) +++ llvm/trunk/lib/MC/MachObjectWriter.cpp Tue Aug 9 17:12:37 2011 @@ -291,7 +291,7 @@ const MCSymbol &Symbol = Data.getSymbol(); uint8_t Type = 0; uint16_t Flags = Data.getFlags(); - uint32_t Address = 0; + uint64_t Address = 0; // Set the N_TYPE bits. See . // From rafael.espindola at gmail.com Tue Aug 9 17:17:34 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Tue, 09 Aug 2011 22:17:34 -0000 Subject: [llvm-commits] [llvm] r137159 - /llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Message-ID: <20110809221734.5E0032A6C12C@llvm.org> Author: rafael Date: Tue Aug 9 17:17:34 2011 New Revision: 137159 URL: http://llvm.org/viewvc/llvm-project?rev=137159&view=rev Log: Add a C interface to PassManagerBuilder. It is missing the addExtension functionality since in the C api a pass is created and added to a pass manager in a single call. Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Modified: llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp?rev=137159&r1=137158&r2=137159&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp (original) +++ llvm/trunk/lib/Transforms/IPO/PassManagerBuilder.cpp Tue Aug 9 17:17:34 2011 @@ -15,6 +15,8 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" + #include "llvm/PassManager.h" #include "llvm/DefaultPasses.h" #include "llvm/PassManager.h" @@ -246,3 +248,81 @@ // Now that we have optimized the program, discard unreachable functions. PM.add(createGlobalDCEPass()); } + +LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate(void) { + PassManagerBuilder *PMB = new PassManagerBuilder(); + return wrap(PMB); +} + +void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) { + PassManagerBuilder *Builder = unwrap(PMB); + delete Builder; +} + +void +LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, + unsigned OptLevel) { + PassManagerBuilder *Builder = unwrap(PMB); + Builder->OptLevel = OptLevel; +} + +void +LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, + unsigned SizeLevel) { + PassManagerBuilder *Builder = unwrap(PMB); + Builder->SizeLevel = SizeLevel; +} + +void +LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB, + LLVMBool Value) { + PassManagerBuilder *Builder = unwrap(PMB); + Builder->DisableUnitAtATime = Value; +} + +void +LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, + LLVMBool Value) { + PassManagerBuilder *Builder = unwrap(PMB); + Builder->DisableUnrollLoops = Value; +} + +void +LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB, + LLVMBool Value) { + PassManagerBuilder *Builder = unwrap(PMB); + Builder->DisableSimplifyLibCalls = Value; +} + +void +LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, + unsigned Threshold) { + PassManagerBuilder *Builder = unwrap(PMB); + Builder->Inliner = createFunctionInliningPass(Threshold); +} + +void +LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM) { + PassManagerBuilder *Builder = unwrap(PMB); + FunctionPassManager *FPM = unwrap(PM); + Builder->populateFunctionPassManager(*FPM); +} + +void +LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM) { + PassManagerBuilder *Builder = unwrap(PMB); + PassManagerBase *MPM = unwrap(PM); + Builder->populateModulePassManager(*MPM); +} + +void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM, + bool Internalize, + bool RunInliner) { + PassManagerBuilder *Builder = unwrap(PMB); + PassManagerBase *LPM = unwrap(PM); + Builder->populateLTOPassManager(*LPM, Internalize, RunInliner); +} + From eli.friedman at gmail.com Tue Aug 9 17:17:39 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 09 Aug 2011 22:17:39 -0000 Subject: [llvm-commits] [llvm] r137160 - in /llvm/trunk: lib/Target/X86/X86InstrCompiler.td test/CodeGen/X86/lock-inst-encoding.ll Message-ID: <20110809221739.679C62A6C12D@llvm.org> Author: efriedma Date: Tue Aug 9 17:17:39 2011 New Revision: 137160 URL: http://llvm.org/viewvc/llvm-project?rev=137160&view=rev Log: Fix a couple ridiculous copy-paste errors. rdar://9914773 . Modified: llvm/trunk/lib/Target/X86/X86InstrCompiler.td llvm/trunk/test/CodeGen/X86/lock-inst-encoding.ll Modified: llvm/trunk/lib/Target/X86/X86InstrCompiler.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrCompiler.td?rev=137160&r1=137159&r2=137160&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrCompiler.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrCompiler.td Tue Aug 9 17:17:39 2011 @@ -630,8 +630,8 @@ defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, "add">; defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, "sub">; defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, "or">; -defm LOCK_AND : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM4m, "and">; -defm LOCK_XOR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM6m, "xor">; +defm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, "and">; +defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, "xor">; // Optimized codegen when the non-memory output is not used. let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1 in { Modified: llvm/trunk/test/CodeGen/X86/lock-inst-encoding.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/lock-inst-encoding.ll?rev=137160&r1=137159&r2=137160&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/lock-inst-encoding.ll (original) +++ llvm/trunk/test/CodeGen/X86/lock-inst-encoding.ll Tue Aug 9 17:17:39 2011 @@ -3,19 +3,52 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" target triple = "x86_64-apple-darwin10.0.0" -; CHECK: f0: -; CHECK: addq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0, +; CHECK: f1: +; CHECK: addq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x01,0x37] ; CHECK: ret -define void @f0(i64* %a0) nounwind { - %t0 = and i64 1, 1 - call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) nounwind - %1 = call i64 @llvm.atomic.load.add.i64.p0i64(i64* %a0, i64 %t0) nounwind - call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true) nounwind +define void @f1(i64* %a, i64 %b) nounwind { + call i64 @llvm.atomic.load.add.i64.p0i64(i64* %a, i64 %b) nounwind ret void } -declare void @llvm.memory.barrier(i1, i1, i1, i1, i1) nounwind +declare i64 @llvm.atomic.load.add.i64.p0i64(i64* nocapture, i64) nounwind -declare i32 @llvm.atomic.load.and.i32.p0i32(i32* nocapture, i32) nounwind +; CHECK: f2: +; CHECK: subq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x29,0x37] +; CHECK: ret +define void @f2(i64* %a, i64 %b) nounwind { + call i64 @llvm.atomic.load.sub.i64.p0i64(i64* %a, i64 %b) nounwind + ret void +} -declare i64 @llvm.atomic.load.add.i64.p0i64(i64* nocapture, i64) nounwind +declare i64 @llvm.atomic.load.sub.i64.p0i64(i64* nocapture, i64) nounwind + +; CHECK: f3: +; CHECK: andq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x21,0x37] +; CHECK: ret +define void @f3(i64* %a, i64 %b) nounwind { + call i64 @llvm.atomic.load.and.i64.p0i64(i64* %a, i64 %b) nounwind + ret void +} + +declare i64 @llvm.atomic.load.and.i64.p0i64(i64* nocapture, i64) nounwind + +; CHECK: f4: +; CHECK: orq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x09,0x37] +; CHECK: ret +define void @f4(i64* %a, i64 %b) nounwind { + call i64 @llvm.atomic.load.or.i64.p0i64(i64* %a, i64 %b) nounwind + ret void +} + +declare i64 @llvm.atomic.load.or.i64.p0i64(i64* nocapture, i64) nounwind + +; CHECK: f5: +; CHECK: xorq %{{.*}}, ({{.*}}){{.*}}encoding: [0xf0,0x48,0x31,0x37] +; CHECK: ret +define void @f5(i64* %a, i64 %b) nounwind { + call i64 @llvm.atomic.load.xor.i64.p0i64(i64* %a, i64 %b) nounwind + ret void +} + +declare i64 @llvm.atomic.load.xor.i64.p0i64(i64* nocapture, i64) nounwind From bruno.cardoso at gmail.com Tue Aug 9 17:18:37 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 22:18:37 -0000 Subject: [llvm-commits] [llvm] r137161 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86InstrSSE.td test/CodeGen/X86/avx-unpack.ll Message-ID: <20110809221837.E38FA2A6C12C@llvm.org> Author: bruno Date: Tue Aug 9 17:18:37 2011 New Revision: 137161 URL: http://llvm.org/viewvc/llvm-project?rev=137161&view=rev Log: Use fp unpack instructions to unpack int types. Until we have AVX2, this is the best we can do for these patterns. This fix PR10554. Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/test/CodeGen/X86/avx-unpack.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137161&r1=137160&r2=137161&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Aug 9 17:18:37 2011 @@ -5940,7 +5940,9 @@ case MVT::v2i64: return X86ISD::PUNPCKLQDQ; case MVT::v4f32: return X86ISD::UNPCKLPS; case MVT::v2f64: return X86ISD::UNPCKLPD; + case MVT::v8i32: // Use fp unit for int unpack. case MVT::v8f32: return X86ISD::VUNPCKLPSY; + case MVT::v4i64: // Use fp unit for int unpack. case MVT::v4f64: return X86ISD::VUNPCKLPDY; case MVT::v16i8: return X86ISD::PUNPCKLBW; case MVT::v8i16: return X86ISD::PUNPCKLWD; @@ -5956,7 +5958,9 @@ case MVT::v2i64: return X86ISD::PUNPCKHQDQ; case MVT::v4f32: return X86ISD::UNPCKHPS; case MVT::v2f64: return X86ISD::UNPCKHPD; + case MVT::v8i32: // Use fp unit for int unpack. case MVT::v8f32: return X86ISD::VUNPCKHPSY; + case MVT::v4i64: // Use fp unit for int unpack. case MVT::v4f64: return X86ISD::VUNPCKHPDY; case MVT::v16i8: return X86ISD::PUNPCKHBW; case MVT::v8i16: return X86ISD::PUNPCKHWD; Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=137161&r1=137160&r2=137161&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Tue Aug 9 17:18:37 2011 @@ -5799,18 +5799,24 @@ // Shuffle with UNPCKLPS def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))), (VUNPCKLPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>; -def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, (memopv8f32 addr:$src2))), - (VUNPCKLPSYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; def : Pat<(v4f32 (X86Unpcklps VR128:$src1, (memopv4f32 addr:$src2))), (UNPCKLPSrm VR128:$src1, addr:$src2)>; def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)), (VUNPCKLPSrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>; -def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, VR256:$src2)), - (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; def : Pat<(v4f32 (X86Unpcklps VR128:$src1, VR128:$src2)), (UNPCKLPSrr VR128:$src1, VR128:$src2)>; +// Shuffle with VUNPCKHPSY +def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, (memopv8f32 addr:$src2))), + (VUNPCKLPSYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; +def : Pat<(v8f32 (X86Unpcklpsy VR256:$src1, VR256:$src2)), + (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; +def : Pat<(v8i32 (X86Unpcklpsy VR256:$src1, VR256:$src2)), + (VUNPCKLPSYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; +def : Pat<(v8i32 (X86Unpcklpsy VR256:$src1, (memopv8i32 addr:$src2))), + (VUNPCKLPSYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; + // Shuffle with UNPCKHPS def : Pat<(v4f32 (X86Unpckhps VR128:$src1, (memopv4f32 addr:$src2))), (VUNPCKHPSrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>; @@ -5828,21 +5834,33 @@ def : Pat<(v8f32 (X86Unpckhpsy VR256:$src1, VR256:$src2)), (VUNPCKHPSYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; +def : Pat<(v8i32 (X86Unpckhpsy VR256:$src1, (memopv8i32 addr:$src2))), + (VUNPCKHPSYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; +def : Pat<(v8i32 (X86Unpckhpsy VR256:$src1, VR256:$src2)), + (VUNPCKHPSYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; + // Shuffle with UNPCKLPD def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))), (VUNPCKLPDrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>; -def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, (memopv4f64 addr:$src2))), - (VUNPCKLPDYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, (memopv2f64 addr:$src2))), (UNPCKLPDrm VR128:$src1, addr:$src2)>; def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)), (VUNPCKLPDrr VR128:$src1, VR128:$src2)>, Requires<[HasAVX]>; -def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, VR256:$src2)), - (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; def : Pat<(v2f64 (X86Unpcklpd VR128:$src1, VR128:$src2)), (UNPCKLPDrr VR128:$src1, VR128:$src2)>; +// Shuffle with VUNPCKLPDY +def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, (memopv4f64 addr:$src2))), + (VUNPCKLPDYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; +def : Pat<(v4f64 (X86Unpcklpdy VR256:$src1, VR256:$src2)), + (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; + +def : Pat<(v4i64 (X86Unpcklpdy VR256:$src1, (memopv4i64 addr:$src2))), + (VUNPCKLPDYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; +def : Pat<(v4i64 (X86Unpcklpdy VR256:$src1, VR256:$src2)), + (VUNPCKLPDYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; + // Shuffle with UNPCKHPD def : Pat<(v2f64 (X86Unpckhpd VR128:$src1, (memopv2f64 addr:$src2))), (VUNPCKHPDrm VR128:$src1, addr:$src2)>, Requires<[HasAVX]>; @@ -5859,6 +5877,10 @@ (VUNPCKHPDYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; def : Pat<(v4f64 (X86Unpckhpdy VR256:$src1, VR256:$src2)), (VUNPCKHPDYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; +def : Pat<(v4i64 (X86Unpckhpdy VR256:$src1, (memopv4i64 addr:$src2))), + (VUNPCKHPDYrm VR256:$src1, addr:$src2)>, Requires<[HasAVX]>; +def : Pat<(v4i64 (X86Unpckhpdy VR256:$src1, VR256:$src2)), + (VUNPCKHPDYrr VR256:$src1, VR256:$src2)>, Requires<[HasAVX]>; // Shuffle with MOVLHPS def : Pat<(X86Movlhps VR128:$src1, Modified: llvm/trunk/test/CodeGen/X86/avx-unpack.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-unpack.ll?rev=137161&r1=137160&r2=137161&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-unpack.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-unpack.ll Tue Aug 9 17:18:37 2011 @@ -56,3 +56,34 @@ ret <4 x double> %shuffle.i } +;;;; +;;;; Unpack versions using the fp unit for int unpacking +;;;; + +; CHECK: vunpckhps +define <8 x i32> @unpackhips1(<8 x i32> %src1, <8 x i32> %src2) nounwind uwtable readnone ssp { +entry: + %shuffle.i = shufflevector <8 x i32> %src1, <8 x i32> %src2, <8 x i32> + ret <8 x i32> %shuffle.i +} + +; CHECK: vunpckhpd +define <4 x i64> @unpackhipd1(<4 x i64> %src1, <4 x i64> %src2) nounwind uwtable readnone ssp { +entry: + %shuffle.i = shufflevector <4 x i64> %src1, <4 x i64> %src2, <4 x i32> + ret <4 x i64> %shuffle.i +} + +; CHECK: vunpcklps +define <8 x i32> @unpacklops1(<8 x i32> %src1, <8 x i32> %src2) nounwind uwtable readnone ssp { +entry: + %shuffle.i = shufflevector <8 x i32> %src1, <8 x i32> %src2, <8 x i32> + ret <8 x i32> %shuffle.i +} + +; CHECK: vunpcklpd +define <4 x i64> @unpacklopd1(<4 x i64> %src1, <4 x i64> %src2) nounwind uwtable readnone ssp { +entry: + %shuffle.i = shufflevector <4 x i64> %src1, <4 x i64> %src2, <4 x i32> + ret <4 x i64> %shuffle.i +} From rafael.espindola at gmail.com Tue Aug 9 17:19:53 2011 From: rafael.espindola at gmail.com (Rafael Espindola) Date: Tue, 09 Aug 2011 22:19:53 -0000 Subject: [llvm-commits] [llvm] r137162 - /llvm/trunk/include/llvm-c/Transforms/PassManagerBuilder.h Message-ID: <20110809221953.1B4392A6C12C@llvm.org> Author: rafael Date: Tue Aug 9 17:19:52 2011 New Revision: 137162 URL: http://llvm.org/viewvc/llvm-project?rev=137162&view=rev Log: Add missing file. Added: llvm/trunk/include/llvm-c/Transforms/PassManagerBuilder.h Added: llvm/trunk/include/llvm-c/Transforms/PassManagerBuilder.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm-c/Transforms/PassManagerBuilder.h?rev=137162&view=auto ============================================================================== --- llvm/trunk/include/llvm-c/Transforms/PassManagerBuilder.h (added) +++ llvm/trunk/include/llvm-c/Transforms/PassManagerBuilder.h Tue Aug 9 17:19:52 2011 @@ -0,0 +1,90 @@ +/*===-- llvm-c/Transform/PassManagerBuilder.h - PMB C Interface ---*- C -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This header declares the C interface to the PassManagerBuilder class. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_C_PASSMANAGERBUILDER +#define LLVM_C_PASSMANAGERBUILDER + +#include "llvm-c/Core.h" + +typedef struct LLVMOpaquePassManagerBuilder *LLVMPassManagerBuilderRef; + +#ifdef __cplusplus +#include "llvm/Transforms/IPO/PassManagerBuilder.h" +extern "C" { +#endif + +/** See llvm::PassManagerBuilder. */ +LLVMPassManagerBuilderRef LLVMPassManagerBuilderCreate(void); +void LLVMPassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB); + +/** See llvm::PassManagerBuilder::OptLevel. */ +void +LLVMPassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, + unsigned OptLevel); + +/** See llvm::PassManagerBuilder::SizeLevel. */ +void +LLVMPassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, + unsigned SizeLevel); + +/** See llvm::PassManagerBuilder::DisableUnitAtATime. */ +void +LLVMPassManagerBuilderSetDisableUnitAtATime(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::DisableUnrollLoops. */ +void +LLVMPassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::DisableSimplifyLibCalls */ +void +LLVMPassManagerBuilderSetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef PMB, + LLVMBool Value); + +/** See llvm::PassManagerBuilder::Inliner. */ +void +LLVMPassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, + unsigned Threshold); + +/** See llvm::PassManagerBuilder::populateFunctionPassManager. */ +void +LLVMPassManagerBuilderPopulateFunctionPassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM); + +/** See llvm::PassManagerBuilder::populateModulePassManager. */ +void +LLVMPassManagerBuilderPopulateModulePassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM); + +/** See llvm::PassManagerBuilder::populateLTOPassManager. */ +void LLVMPassManagerBuilderPopulateLTOPassManager(LLVMPassManagerBuilderRef PMB, + LLVMPassManagerRef PM, + bool Internalize, + bool RunInliner); + +#ifdef __cplusplus +} + +namespace llvm { + inline PassManagerBuilder *unwrap(LLVMPassManagerBuilderRef P) { + return reinterpret_cast(P); + } + + inline LLVMPassManagerBuilderRef wrap(PassManagerBuilder *P) { + return reinterpret_cast(P); + } +} +#endif + +#endif From echristo at apple.com Tue Aug 9 17:21:26 2011 From: echristo at apple.com (Eric Christopher) Date: Tue, 09 Aug 2011 15:21:26 -0700 Subject: [llvm-commits] [llvm] r137160 - in /llvm/trunk: lib/Target/X86/X86InstrCompiler.td test/CodeGen/X86/lock-inst-encoding.ll In-Reply-To: <20110809221739.679C62A6C12D@llvm.org> References: <20110809221739.679C62A6C12D@llvm.org> Message-ID: <6906417C-5B5E-46CD-AECA-93CC42F730C1@apple.com> On Aug 9, 2011, at 3:17 PM, Eli Friedman wrote: > URL: http://llvm.org/viewvc/llvm-project?rev=137160&view=rev > Log: > Fix a couple ridiculous copy-paste errors. rdar://9914773 . Thanks! -eric -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110809/4e39745c/attachment.html From mcrosier at apple.com Tue Aug 9 17:23:40 2011 From: mcrosier at apple.com (Chad Rosier) Date: Tue, 09 Aug 2011 22:23:40 -0000 Subject: [llvm-commits] [llvm] r137163 - /llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Message-ID: <20110809222340.A0A652A6C12C@llvm.org> Author: mcrosier Date: Tue Aug 9 17:23:40 2011 New Revision: 137163 URL: http://llvm.org/viewvc/llvm-project?rev=137163&view=rev Log: Fix 80-column violations. Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=137163&r1=137162&r2=137163&view=diff ============================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original) +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Tue Aug 9 17:23:40 2011 @@ -1859,9 +1859,9 @@ if (Code != bitc::ENTER_SUBBLOCK) { - // The ranlib in xcode 4 will align archive members by appending newlines to the - // end of them. If this file size is a multiple of 4 but not 8, we have to read and - // ignore these final 4 bytes :-( + // The ranlib in xcode 4 will align archive members by appending newlines + // to the end of them. If this file size is a multiple of 4 but not 8, we + // have to read and ignore these final 4 bytes :-( if (Stream.GetAbbrevIDWidth() == 2 && Code == 2 && Stream.Read(6) == 2 && Stream.Read(24) == 0xa0a0a && Stream.AtEndOfStream()) From bruno.cardoso at gmail.com Tue Aug 9 17:39:53 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Tue, 09 Aug 2011 22:39:53 -0000 Subject: [llvm-commits] [llvm] r137166 - in /llvm/trunk: lib/Target/X86/X86InstrSSE.td test/CodeGen/X86/avx-load-store.ll Message-ID: <20110809223954.088962A6C12C@llvm.org> Author: bruno Date: Tue Aug 9 17:39:53 2011 New Revision: 137166 URL: http://llvm.org/viewvc/llvm-project?rev=137166&view=rev Log: Add v16i16 and v32i8 store patterns Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/test/CodeGen/X86/avx-load-store.ll Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=137166&r1=137165&r2=137166&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Tue Aug 9 17:39:53 2011 @@ -4063,10 +4063,18 @@ (VMOVAPSYmr addr:$dst, VR256:$src)>; def : Pat<(alignedstore (v8i32 VR256:$src), addr:$dst), (VMOVAPSYmr addr:$dst, VR256:$src)>; + def : Pat<(alignedstore (v16i16 VR256:$src), addr:$dst), + (VMOVAPSYmr addr:$dst, VR256:$src)>; + def : Pat<(alignedstore (v32i8 VR256:$src), addr:$dst), + (VMOVAPSYmr addr:$dst, VR256:$src)>; def : Pat<(store (v4i64 VR256:$src), addr:$dst), (VMOVUPSYmr addr:$dst, VR256:$src)>; def : Pat<(store (v8i32 VR256:$src), addr:$dst), (VMOVUPSYmr addr:$dst, VR256:$src)>; + def : Pat<(store (v16i16 VR256:$src), addr:$dst), + (VMOVUPSYmr addr:$dst, VR256:$src)>; + def : Pat<(store (v32i8 VR256:$src), addr:$dst), + (VMOVUPSYmr addr:$dst, VR256:$src)>; } //===----------------------------------------------------------------------===// Modified: llvm/trunk/test/CodeGen/X86/avx-load-store.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-load-store.ll?rev=137166&r1=137165&r2=137166&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/avx-load-store.ll (original) +++ llvm/trunk/test/CodeGen/X86/avx-load-store.ll Tue Aug 9 17:39:53 2011 @@ -40,3 +40,27 @@ ret <4 x double> %i0 } +; CHECK: vmovaps %ymm +define void @storev16i16(<16 x i16> %a) nounwind { + store <16 x i16> %a, <16 x i16>* undef, align 32 + unreachable +} + +; CHECK: vmovups %ymm +define void @storev16i16_01(<16 x i16> %a) nounwind { + store <16 x i16> %a, <16 x i16>* undef, align 4 + unreachable +} + +; CHECK: vmovaps %ymm +define void @storev32i8(<32 x i8> %a) nounwind { + store <32 x i8> %a, <32 x i8>* undef, align 32 + unreachable +} + +; CHECK: vmovups %ymm +define void @storev32i8_01(<32 x i8> %a) nounwind { + store <32 x i8> %a, <32 x i8>* undef, align 4 + unreachable +} + From resistor at mac.com Tue Aug 9 17:48:45 2011 From: resistor at mac.com (Owen Anderson) Date: Tue, 09 Aug 2011 22:48:45 -0000 Subject: [llvm-commits] [llvm] r137168 - in /llvm/trunk: lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/ARMRegisterInfo.td lib/Target/ARM/Disassembler/ARMDisassembler.cpp test/MC/Disassembler/ARM/invalid-BFI-arm.txt utils/TableGen/EDEmitter.cpp Message-ID: <20110809224846.058242A6C12C@llvm.org> Author: resistor Date: Tue Aug 9 17:48:45 2011 New Revision: 137168 URL: http://llvm.org/viewvc/llvm-project?rev=137168&view=rev Log: Create a new register class for the set of all GPRs except the PC. Use it to tighten our decoding of BFI. Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt llvm/trunk/utils/TableGen/EDEmitter.cpp Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137168&r1=137167&r2=137168&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug 9 17:48:45 2011 @@ -3131,10 +3131,10 @@ } // A8.6.18 BFI - Bitfield insert (Encoding A1) -def BFI : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, bf_inv_mask_imm:$imm), +def BFI : I<(outs GPRnopc:$Rd), (ins GPRnopc:$src, GPR:$Rn, bf_inv_mask_imm:$imm), AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "bfi", "\t$Rd, $Rn, $imm", "$src = $Rd", - [(set GPR:$Rd, (ARMbfi GPR:$src, GPR:$Rn, + [(set GPRnopc:$Rd, (ARMbfi GPRnopc:$src, GPR:$Rn, bf_inv_mask_imm:$imm))]>, Requires<[IsARM, HasV6T2]> { bits<4> Rd; @@ -3150,7 +3150,7 @@ // GNU as only supports this form of bfi (w/ 4 arguments) let isAsmParserOnly = 1 in -def BFI4p : I<(outs GPR:$Rd), (ins GPR:$src, GPR:$Rn, +def BFI4p : I<(outs GPRnopc:$Rd), (ins GPRnopc:$src, GPR:$Rn, lsb_pos_imm:$lsb, width_imm:$width), AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi, "bfi", "\t$Rd, $Rn, $lsb, $width", "$src = $Rd", Modified: llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td?rev=137168&r1=137167&r2=137168&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMRegisterInfo.td Tue Aug 9 17:48:45 2011 @@ -215,6 +215,16 @@ }]; } +// GPRs without the PC. Some ARM instructions do not allow the PC in +// certain operand slots, particularly as the destination. Primarily +// useful for disassembly. +def GPRnopc : RegisterClass<"ARM", [i32], 32, (sub GPR, PC)> { + let AltOrders = [(add LR, GPRnopc), (trunc GPRnopc, 8)]; + let AltOrderSelect = [{ + return 1 + MF.getTarget().getSubtarget().isThumb1Only(); + }]; +} + // restricted GPR register class. Many Thumb2 instructions allow the full // register range for operands, but have undefined behaviours when PC // or SP (R13 or R15) are used. The ARM ISA refers to these operands 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=137168&r1=137167&r2=137168&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug 9 17:48:45 2011 @@ -28,6 +28,8 @@ // Definitions are further down. static bool DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); +static bool DecodeGPRnopcRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder); static bool DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder); static bool DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, @@ -471,6 +473,12 @@ return true; } +static bool DecodeGPRnopcRegisterClass(llvm::MCInst &Inst, unsigned RegNo, + uint64_t Address, const void *Decoder) { + if (RegNo == 15) return false; + return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder); +} + static bool DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { if (RegNo > 7) Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt?rev=137168&r1=137167&r2=137168&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt Tue Aug 9 17:48:45 2011 @@ -1,5 +1,4 @@ # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding} -# XFAIL: * # Opcode=60 Name=BFI Format=ARM_FORMAT_DPFRM(4) # 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 Modified: llvm/trunk/utils/TableGen/EDEmitter.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/EDEmitter.cpp?rev=137168&r1=137167&r2=137168&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/EDEmitter.cpp (original) +++ llvm/trunk/utils/TableGen/EDEmitter.cpp Tue Aug 9 17:48:45 2011 @@ -555,6 +555,7 @@ const std::string &name) { REG("GPR"); REG("rGPR"); + REG("GPRnopc"); REG("tcGPR"); REG("cc_out"); REG("s_cc_out"); From eli.friedman at gmail.com Tue Aug 9 18:02:54 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Tue, 09 Aug 2011 23:02:54 -0000 Subject: [llvm-commits] [llvm] r137170 - in /llvm/trunk: docs/Atomics.html docs/LangRef.html include/llvm/Bitcode/LLVMBitCodes.h include/llvm/Instructions.h lib/AsmParser/LLParser.cpp lib/AsmParser/LLParser.h lib/Bitcode/Reader/BitcodeReader.cpp lib/Bitcode/Writer/BitcodeWriter.cpp lib/Transforms/Scalar/LowerAtomic.cpp lib/VMCore/AsmWriter.cpp lib/VMCore/Instructions.cpp lib/VMCore/Verifier.cpp Message-ID: <20110809230254.7D1AD2A6C12C@llvm.org> Author: efriedma Date: Tue Aug 9 18:02:53 2011 New Revision: 137170 URL: http://llvm.org/viewvc/llvm-project?rev=137170&view=rev Log: Representation of 'atomic load' and 'atomic store' in IR. Modified: llvm/trunk/docs/Atomics.html llvm/trunk/docs/LangRef.html llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h llvm/trunk/include/llvm/Instructions.h llvm/trunk/lib/AsmParser/LLParser.cpp llvm/trunk/lib/AsmParser/LLParser.h llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp llvm/trunk/lib/VMCore/AsmWriter.cpp llvm/trunk/lib/VMCore/Instructions.cpp llvm/trunk/lib/VMCore/Verifier.cpp Modified: llvm/trunk/docs/Atomics.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/Atomics.html?rev=137170&r1=137169&r2=137170&view=diff ============================================================================== --- llvm/trunk/docs/Atomics.html (original) +++ llvm/trunk/docs/Atomics.html Tue Aug 9 18:02:53 2011 @@ -3,6 +3,7 @@ LLVM Atomic Instructions and Concurrency Guide + Modified: llvm/trunk/docs/LangRef.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=137170&r1=137169&r2=137170&view=diff ============================================================================== --- llvm/trunk/docs/LangRef.html (original) +++ llvm/trunk/docs/LangRef.html Tue Aug 9 18:02:53 2011 @@ -1583,8 +1583,10 @@

    Atomic instructions (cmpxchg, -atomicrmw, and -fence) take an ordering parameter +atomicrmw, +fence, +atomic load, and +atomic store) take an ordering parameter that determines which other atomic instructions on the same address they synchronize with. These semantics are borrowed from Java and C++0x, but are somewhat more colloquial. If these descriptions aren't precise enough, @@ -1592,11 +1594,7 @@ treat these orderings somewhat differently since they don't take an address. See that instruction's documentation for details.

    - -
    -
    unordered
    The set of values that can be read is governed by the happens-before partial order. A value cannot be read unless some operation wrote it. @@ -4572,8 +4570,8 @@
    Syntax:
    -  <result> = load <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
    -  <result> = volatile load <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
    +  <result> = [volatile] load <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]
    +  <result> = atomic [volatile] load <ty>* <pointer> [singlethread] <ordering>, align <alignment>
       !<index> = !{ i32 1 }
     
    @@ -4588,6 +4586,19 @@ number or order of execution of this load with other volatile operations.

    +

    If the load is marked as atomic, it takes an extra + ordering and optional singlethread + argument. The release and acq_rel orderings are + not valid on load instructions. Atomic loads produce defined results when they may see multiple atomic + stores. The type of the pointee must be an integer type whose bit width + is a power of two greater than or equal to eight and less than or equal + to a target-specific size limit. align must be explicitly + specified on atomic loads, and the load has undefined behavior if the + alignment is not set to a value which is at least the size in bytes of + the pointee. !nontemporal does not have any defined semantics + for atomic loads.

    +

    The optional constant align argument specifies the alignment of the operation (that is, the alignment of the memory address). A value of 0 or an omitted align argument means that the operation has the preferential @@ -4631,8 +4642,8 @@

    Syntax:
    -  store <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]                   ; yields {void}
    -  volatile store <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]          ; yields {void}
    +  [volatile] store <ty> <value>, <ty>* <pointer>[, align <alignment>][, !nontemporal !<index>]                   ; yields {void}
    +  atomic [volatile] store <ty> <value>, <ty>* <pointer> [singlethread] <ordering>, align <alignment>             ; yields {void}
     
    Overview:
    @@ -4648,6 +4659,19 @@ order of execution of this store with other volatile operations.

    +

    If the store is marked as atomic, it takes an extra + ordering and optional singlethread + argument. The acquire and acq_rel orderings aren't + valid on store instructions. Atomic loads produce defined results when they may see multiple atomic + stores. The type of the pointee must be an integer type whose bit width + is a power of two greater than or equal to eight and less than or equal + to a target-specific size limit. align must be explicitly + specified on atomic stores, and the store has undefined behavior if the + alignment is not set to a value which is at least the size in bytes of + the pointee. !nontemporal does not have any defined semantics + for atomic stores.

    +

    The optional constant "align" argument specifies the alignment of the operation (that is, the alignment of the memory address). A value of 0 or an omitted "align" argument means that the operation has the preferential @@ -4730,9 +4754,6 @@ specifies that the fence only synchronizes with other fences in the same thread. (This is useful for interacting with signal handlers.)

    -

    FIXME: This instruction is a work in progress; until it is finished, use - llvm.memory.barrier. -

    Example:
       fence acquire                          ; yields {void}
    
    Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
    +++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Tue Aug  9 18:02:53 2011
    @@ -307,7 +307,11 @@
         FUNC_CODE_INST_ATOMICRMW   = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
                                          //             align, vol,
                                          //             ordering, synchscope]
    -    FUNC_CODE_INST_RESUME      = 39  // RESUME:     [opval]
    +    FUNC_CODE_INST_RESUME      = 39, // RESUME:     [opval]
    +    FUNC_CODE_INST_LOADATOMIC  = 40, // LOAD: [opty, op, align, vol,
    +                                     //        ordering, synchscope]
    +    FUNC_CODE_INST_STOREATOMIC = 41  // STORE: [ptrty,ptr,val, align, vol
    +                                     //         ordering, synchscope]
       };
     } // End bitc namespace
     } // End llvm namespace
    
    Modified: llvm/trunk/include/llvm/Instructions.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instructions.h?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Instructions.h (original)
    +++ llvm/trunk/include/llvm/Instructions.h Tue Aug  9 18:02:53 2011
    @@ -143,11 +143,19 @@
       LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile = false,
                Instruction *InsertBefore = 0);
       LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
    -           unsigned Align, Instruction *InsertBefore = 0);
    -  LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
                BasicBlock *InsertAtEnd);
       LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
    +           unsigned Align, Instruction *InsertBefore = 0);
    +  LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
                unsigned Align, BasicBlock *InsertAtEnd);
    +  LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
    +           unsigned Align, AtomicOrdering Order,
    +           SynchronizationScope SynchScope = CrossThread,
    +           Instruction *InsertBefore = 0);
    +  LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile,
    +           unsigned Align, AtomicOrdering Order,
    +           SynchronizationScope SynchScope,
    +           BasicBlock *InsertAtEnd);
     
       LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore);
       LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd);
    @@ -171,11 +179,47 @@
       /// getAlignment - Return the alignment of the access that is being performed
       ///
       unsigned getAlignment() const {
    -    return (1 << (getSubclassDataFromInstruction() >> 1)) >> 1;
    +    return (1 << ((getSubclassDataFromInstruction() >> 1) & 31)) >> 1;
       }
     
       void setAlignment(unsigned Align);
     
    +  /// Returns the ordering effect of this fence.
    +  AtomicOrdering getOrdering() const {
    +    return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7);
    +  }
    +
    +  /// Set the ordering constraint on this load. May not be Release or
    +  /// AcquireRelease.
    +  void setOrdering(AtomicOrdering Ordering) {
    +    setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) |
    +                               (Ordering << 7));
    +  }
    +
    +  SynchronizationScope getSynchScope() const {
    +    return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1);
    +  }
    +
    +  /// Specify whether this load is ordered with respect to all
    +  /// concurrently executing threads, or only with respect to signal handlers
    +  /// executing in the same thread.
    +  void setSynchScope(SynchronizationScope xthread) {
    +    setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) |
    +                               (xthread << 6));
    +  }
    +
    +  bool isAtomic() const { return getOrdering() != NotAtomic; }
    +  void setAtomic(AtomicOrdering Ordering,
    +                 SynchronizationScope SynchScope = CrossThread) {
    +    setOrdering(Ordering);
    +    setSynchScope(SynchScope);
    +  }
    +
    +  bool isSimple() const { return !isAtomic() && !isVolatile(); }
    +  bool isUnordered() const {
    +    return getOrdering() <= Unordered && !isVolatile();
    +  }
    +
       Value *getPointerOperand() { return getOperand(0); }
       const Value *getPointerOperand() const { return getOperand(0); }
       static unsigned getPointerOperandIndex() { return 0U; }
    @@ -222,19 +266,27 @@
       StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd);
       StoreInst(Value *Val, Value *Ptr, bool isVolatile = false,
                 Instruction *InsertBefore = 0);
    +  StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd);
       StoreInst(Value *Val, Value *Ptr, bool isVolatile,
                 unsigned Align, Instruction *InsertBefore = 0);
    -  StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd);
       StoreInst(Value *Val, Value *Ptr, bool isVolatile,
                 unsigned Align, BasicBlock *InsertAtEnd);
    +  StoreInst(Value *Val, Value *Ptr, bool isVolatile,
    +            unsigned Align, AtomicOrdering Order,
    +            SynchronizationScope SynchScope = CrossThread,
    +            Instruction *InsertBefore = 0);
    +  StoreInst(Value *Val, Value *Ptr, bool isVolatile,
    +            unsigned Align, AtomicOrdering Order,
    +            SynchronizationScope SynchScope,
    +            BasicBlock *InsertAtEnd);
    +          
     
    -
    -  /// isVolatile - Return true if this is a load from a volatile memory
    +  /// isVolatile - Return true if this is a store to a volatile memory
       /// location.
       ///
       bool isVolatile() const { return getSubclassDataFromInstruction() & 1; }
     
    -  /// setVolatile - Specify whether this is a volatile load or not.
    +  /// setVolatile - Specify whether this is a volatile store or not.
       ///
       void setVolatile(bool V) {
         setInstructionSubclassData((getSubclassDataFromInstruction() & ~1) |
    @@ -247,11 +299,47 @@
       /// getAlignment - Return the alignment of the access that is being performed
       ///
       unsigned getAlignment() const {
    -    return (1 << (getSubclassDataFromInstruction() >> 1)) >> 1;
    +    return (1 << ((getSubclassDataFromInstruction() >> 1) & 31)) >> 1;
       }
     
       void setAlignment(unsigned Align);
     
    +  /// Returns the ordering effect of this store.
    +  AtomicOrdering getOrdering() const {
    +    return AtomicOrdering((getSubclassDataFromInstruction() >> 7) & 7);
    +  }
    +
    +  /// Set the ordering constraint on this store.  May not be Acquire or
    +  /// AcquireRelease.
    +  void setOrdering(AtomicOrdering Ordering) {
    +    setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 7)) |
    +                               (Ordering << 7));
    +  }
    +
    +  SynchronizationScope getSynchScope() const {
    +    return SynchronizationScope((getSubclassDataFromInstruction() >> 6) & 1);
    +  }
    +
    +  /// Specify whether this store instruction is ordered with respect to all
    +  /// concurrently executing threads, or only with respect to signal handlers
    +  /// executing in the same thread.
    +  void setSynchScope(SynchronizationScope xthread) {
    +    setInstructionSubclassData((getSubclassDataFromInstruction() & ~(1 << 6)) |
    +                               (xthread << 6));
    +  }
    +
    +  bool isAtomic() const { return getOrdering() != NotAtomic; }
    +  void setAtomic(AtomicOrdering Ordering,
    +                 SynchronizationScope SynchScope = CrossThread) {
    +    setOrdering(Ordering);
    +    setSynchScope(SynchScope);
    +  }
    +
    +  bool isSimple() const { return !isAtomic() && !isVolatile(); }
    +  bool isUnordered() const {
    +    return getOrdering() <= Unordered && !isVolatile();
    +  }
    +
       Value *getValueOperand() { return getOperand(0); }
       const Value *getValueOperand() const { return getOperand(0); }
     
    @@ -319,18 +407,8 @@
       /// Set the ordering constraint on this fence.  May only be Acquire, Release,
       /// AcquireRelease, or SequentiallyConsistent.
       void setOrdering(AtomicOrdering Ordering) {
    -    switch (Ordering) {
    -    case Acquire:
    -    case Release:
    -    case AcquireRelease:
    -    case SequentiallyConsistent:
    -      setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
    -                                 (Ordering << 1));
    -      return;
    -    default:
    -      llvm_unreachable("FenceInst ordering must be Acquire, Release,"
    -                       " AcquireRelease, or SequentiallyConsistent");
    -    }
    +    setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
    +                               (Ordering << 1));
       }
     
       SynchronizationScope getSynchScope() const {
    @@ -555,7 +633,7 @@
       void setOrdering(AtomicOrdering Ordering) {
         assert(Ordering != NotAtomic &&
                "atomicrmw instructions can only be atomic.");
    -    setInstructionSubclassData((getSubclassDataFromInstruction() & ~28) |
    +    setInstructionSubclassData((getSubclassDataFromInstruction() & ~(7 << 2)) |
                                    (Ordering << 2));
       }
     
    @@ -569,7 +647,7 @@
     
       /// Returns the ordering constraint on this RMW.
       AtomicOrdering getOrdering() const {
    -    return AtomicOrdering((getSubclassDataFromInstruction() & 28) >> 2);
    +    return AtomicOrdering((getSubclassDataFromInstruction() >> 2) & 7);
       }
     
       /// Returns whether this RMW is atomic between threads or only within a
    
    Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
    +++ llvm/trunk/lib/AsmParser/LLParser.cpp Tue Aug  9 18:02:53 2011
    @@ -2949,16 +2949,23 @@
       case lltok::kw_tail:           return ParseCall(Inst, PFS, true);
       // Memory.
       case lltok::kw_alloca:         return ParseAlloc(Inst, PFS);
    -  case lltok::kw_load:           return ParseLoad(Inst, PFS, false);
    -  case lltok::kw_store:          return ParseStore(Inst, PFS, false);
    +  case lltok::kw_load:           return ParseLoad(Inst, PFS, false, false);
    +  case lltok::kw_store:          return ParseStore(Inst, PFS, false, false);
       case lltok::kw_cmpxchg:        return ParseCmpXchg(Inst, PFS, false);
       case lltok::kw_atomicrmw:      return ParseAtomicRMW(Inst, PFS, false);
       case lltok::kw_fence:          return ParseFence(Inst, PFS);
    +  case lltok::kw_atomic: {
    +    bool isVolatile = EatIfPresent(lltok::kw_volatile);
    +    if (EatIfPresent(lltok::kw_load))
    +      return ParseLoad(Inst, PFS, true, isVolatile);
    +    else if (EatIfPresent(lltok::kw_store))
    +      return ParseStore(Inst, PFS, true, isVolatile);
    +  }
       case lltok::kw_volatile:
         if (EatIfPresent(lltok::kw_load))
    -      return ParseLoad(Inst, PFS, true);
    +      return ParseLoad(Inst, PFS, false, true);
         else if (EatIfPresent(lltok::kw_store))
    -      return ParseStore(Inst, PFS, true);
    +      return ParseStore(Inst, PFS, false, true);
         else if (EatIfPresent(lltok::kw_cmpxchg))
           return ParseCmpXchg(Inst, PFS, true);
         else if (EatIfPresent(lltok::kw_atomicrmw))
    @@ -3635,34 +3642,48 @@
     }
     
     /// ParseLoad
    -///   ::= 'volatile'? 'load' TypeAndValue (',' OptionalInfo)?
    +///   ::= 'volatile'? 'load' TypeAndValue (',' 'align' i32)?
    +//    ::= 'atomic' 'volatile'? 'load' TypeAndValue 
    +//        'singlethread'? AtomicOrdering (',' 'align' i32)?
     int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState &PFS,
    -                        bool isVolatile) {
    +                        bool isAtomic, bool isVolatile) {
       Value *Val; LocTy Loc;
       unsigned Alignment = 0;
       bool AteExtraComma = false;
    +  AtomicOrdering Ordering = NotAtomic;
    +  SynchronizationScope Scope = CrossThread;
       if (ParseTypeAndValue(Val, Loc, PFS) ||
    +      ParseScopeAndOrdering(isAtomic, Scope, Ordering) ||
           ParseOptionalCommaAlign(Alignment, AteExtraComma))
         return true;
     
       if (!Val->getType()->isPointerTy() ||
           !cast(Val->getType())->getElementType()->isFirstClassType())
         return Error(Loc, "load operand must be a pointer to a first class type");
    +  if (isAtomic && !Alignment)
    +    return Error(Loc, "atomic load must have explicit non-zero alignment");
    +  if (Ordering == Release || Ordering == AcquireRelease)
    +    return Error(Loc, "atomic load cannot use Release ordering");
     
    -  Inst = new LoadInst(Val, "", isVolatile, Alignment);
    +  Inst = new LoadInst(Val, "", isVolatile, Alignment, Ordering, Scope);
       return AteExtraComma ? InstExtraComma : InstNormal;
     }
     
     /// ParseStore
     ///   ::= 'volatile'? 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)?
    +///   ::= 'atomic' 'volatile'? 'store' TypeAndValue ',' TypeAndValue
    +///       'singlethread'? AtomicOrdering (',' 'align' i32)?
     int LLParser::ParseStore(Instruction *&Inst, PerFunctionState &PFS,
    -                         bool isVolatile) {
    +                         bool isAtomic, bool isVolatile) {
       Value *Val, *Ptr; LocTy Loc, PtrLoc;
       unsigned Alignment = 0;
       bool AteExtraComma = false;
    +  AtomicOrdering Ordering = NotAtomic;
    +  SynchronizationScope Scope = CrossThread;
       if (ParseTypeAndValue(Val, Loc, PFS) ||
           ParseToken(lltok::comma, "expected ',' after store operand") ||
           ParseTypeAndValue(Ptr, PtrLoc, PFS) ||
    +      ParseScopeAndOrdering(isAtomic, Scope, Ordering) ||
           ParseOptionalCommaAlign(Alignment, AteExtraComma))
         return true;
     
    @@ -3672,8 +3693,12 @@
         return Error(Loc, "store operand must be a first class value");
       if (cast(Ptr->getType())->getElementType() != Val->getType())
         return Error(Loc, "stored value and pointer type do not match");
    +  if (isAtomic && !Alignment)
    +    return Error(Loc, "atomic store must have explicit non-zero alignment");
    +  if (Ordering == Acquire || Ordering == AcquireRelease)
    +    return Error(Loc, "atomic store cannot use Acquire ordering");
     
    -  Inst = new StoreInst(Val, Ptr, isVolatile, Alignment);
    +  Inst = new StoreInst(Val, Ptr, isVolatile, Alignment, Ordering, Scope);
       return AteExtraComma ? InstExtraComma : InstNormal;
     }
     
    
    Modified: llvm/trunk/lib/AsmParser/LLParser.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/lib/AsmParser/LLParser.h (original)
    +++ llvm/trunk/lib/AsmParser/LLParser.h Tue Aug  9 18:02:53 2011
    @@ -362,8 +362,10 @@
         int ParsePHI(Instruction *&I, PerFunctionState &PFS);
         bool ParseCall(Instruction *&I, PerFunctionState &PFS, bool isTail);
         int ParseAlloc(Instruction *&I, PerFunctionState &PFS);
    -    int ParseLoad(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
    -    int ParseStore(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
    +    int ParseLoad(Instruction *&I, PerFunctionState &PFS,
    +                  bool isAtomic, bool isVolatile);
    +    int ParseStore(Instruction *&I, PerFunctionState &PFS,
    +                   bool isAtomic, bool isVolatile);
         int ParseCmpXchg(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
         int ParseAtomicRMW(Instruction *&I, PerFunctionState &PFS, bool isVolatile);
         int ParseFence(Instruction *&I, PerFunctionState &PFS);
    
    Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
    +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Tue Aug  9 18:02:53 2011
    @@ -2567,6 +2567,28 @@
           InstructionList.push_back(I);
           break;
         }
    +    case bitc::FUNC_CODE_INST_LOADATOMIC: {
    +       // LOADATOMIC: [opty, op, align, vol, ordering, synchscope]
    +      unsigned OpNum = 0;
    +      Value *Op;
    +      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
    +          OpNum+4 != Record.size())
    +        return Error("Invalid LOADATOMIC record");
    +        
    +
    +      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
    +      if (Ordering == NotAtomic || Ordering == Release ||
    +          Ordering == AcquireRelease)
    +        return Error("Invalid LOADATOMIC record");
    +      if (Ordering != NotAtomic && Record[OpNum] == 0)
    +        return Error("Invalid LOADATOMIC record");
    +      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
    +
    +      I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1,
    +                       Ordering, SynchScope);
    +      InstructionList.push_back(I);
    +      break;
    +    }
         case bitc::FUNC_CODE_INST_STORE: { // STORE2:[ptrty, ptr, val, align, vol]
           unsigned OpNum = 0;
           Value *Val, *Ptr;
    @@ -2580,6 +2602,29 @@
           InstructionList.push_back(I);
           break;
         }
    +    case bitc::FUNC_CODE_INST_STOREATOMIC: {
    +      // STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, synchscope]
    +      unsigned OpNum = 0;
    +      Value *Val, *Ptr;
    +      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
    +          getValue(Record, OpNum,
    +                    cast(Ptr->getType())->getElementType(), Val) ||
    +          OpNum+4 != Record.size())
    +        return Error("Invalid STOREATOMIC record");
    +
    +      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
    +      if (Ordering == NotAtomic || Ordering == Release ||
    +          Ordering == AcquireRelease)
    +        return Error("Invalid STOREATOMIC record");
    +      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
    +      if (Ordering != NotAtomic && Record[OpNum] == 0)
    +        return Error("Invalid STOREATOMIC record");
    +
    +      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1,
    +                        Ordering, SynchScope);
    +      InstructionList.push_back(I);
    +      break;
    +    }
         case bitc::FUNC_CODE_INST_CMPXCHG: {
           // CMPXCHG:[ptrty, ptr, cmp, new, vol, ordering, synchscope]
           unsigned OpNum = 0;
    @@ -2592,7 +2637,7 @@
               OpNum+3 != Record.size())
             return Error("Invalid CMPXCHG record");
           AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+1]);
    -      if (Ordering == NotAtomic)
    +      if (Ordering == NotAtomic || Ordering == Unordered)
             return Error("Invalid CMPXCHG record");
           SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+2]);
           I = new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope);
    @@ -2614,7 +2659,7 @@
               Operation > AtomicRMWInst::LAST_BINOP)
             return Error("Invalid ATOMICRMW record");
           AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
    -      if (Ordering == NotAtomic)
    +      if (Ordering == NotAtomic || Ordering == Unordered)
             return Error("Invalid ATOMICRMW record");
           SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
           I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SynchScope);
    
    Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
    +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Tue Aug  9 18:02:53 2011
    @@ -1175,19 +1175,34 @@
         break;
     
       case Instruction::Load:
    -    Code = bitc::FUNC_CODE_INST_LOAD;
    -    if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))  // ptr
    -      AbbrevToUse = FUNCTION_INST_LOAD_ABBREV;
    -
    +    if (cast(I).isAtomic()) {
    +      Code = bitc::FUNC_CODE_INST_LOADATOMIC;
    +      PushValueAndType(I.getOperand(0), InstID, Vals, VE);
    +    } else {
    +      Code = bitc::FUNC_CODE_INST_LOAD;
    +      if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))  // ptr
    +        AbbrevToUse = FUNCTION_INST_LOAD_ABBREV;
    +    }
         Vals.push_back(Log2_32(cast(I).getAlignment())+1);
         Vals.push_back(cast(I).isVolatile());
    +    if (cast(I).isAtomic()) {
    +      Vals.push_back(GetEncodedOrdering(cast(I).getOrdering()));
    +      Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope()));
    +    }
         break;
       case Instruction::Store:
    -    Code = bitc::FUNC_CODE_INST_STORE;
    +    if (cast(I).isAtomic())
    +      Code = bitc::FUNC_CODE_INST_STOREATOMIC;
    +    else
    +      Code = bitc::FUNC_CODE_INST_STORE;
         PushValueAndType(I.getOperand(1), InstID, Vals, VE);  // ptrty + ptr
         Vals.push_back(VE.getValueID(I.getOperand(0)));       // val.
         Vals.push_back(Log2_32(cast(I).getAlignment())+1);
         Vals.push_back(cast(I).isVolatile());
    +    if (cast(I).isAtomic()) {
    +      Vals.push_back(GetEncodedOrdering(cast(I).getOrdering()));
    +      Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope()));
    +    }
         break;
       case Instruction::AtomicCmpXchg:
         Code = bitc::FUNC_CODE_INST_CMPXCHG;
    
    Modified: llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp (original)
    +++ llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp Tue Aug  9 18:02:53 2011
    @@ -190,6 +190,16 @@
       return true;
     }
     
    +static bool LowerLoadInst(LoadInst *LI) {
    +  LI->setAtomic(NotAtomic);
    +  return true;
    +}
    +
    +static bool LowerStoreInst(StoreInst *SI) {
    +  SI->setAtomic(NotAtomic);
    +  return true;
    +}
    +
     namespace {
       struct LowerAtomic : public BasicBlockPass {
         static char ID;
    @@ -208,6 +218,13 @@
               Changed |= LowerAtomicCmpXchgInst(CXI);
             else if (AtomicRMWInst *RMWI = dyn_cast(Inst))
               Changed |= LowerAtomicRMWInst(RMWI);
    +        else if (LoadInst *LI = dyn_cast(Inst)) {
    +          if (LI->isAtomic())
    +            LowerLoadInst(LI);
    +        } else if (StoreInst *SI = dyn_cast(Inst)) {
    +          if (SI->isAtomic())
    +            LowerStoreInst(SI);
    +        }
           }
           return Changed;
         }
    
    Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AsmWriter.cpp?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/lib/VMCore/AsmWriter.cpp (original)
    +++ llvm/trunk/lib/VMCore/AsmWriter.cpp Tue Aug  9 18:02:53 2011
    @@ -1659,14 +1659,18 @@
           Out << '%' << SlotNum << " = ";
       }
     
    +  // If this is an atomic load or store, print out the atomic marker.
    +  if ((isa(I)  && cast(I).isAtomic()) ||
    +      (isa(I) && cast(I).isAtomic()))
    +    Out << "atomic ";
    +
       // If this is a volatile load or store, print out the volatile marker.
       if ((isa(I)  && cast(I).isVolatile()) ||
    -      (isa(I) && cast(I).isVolatile())) {
    -      Out << "volatile ";
    -  } else if (isa(I) && cast(I).isTailCall()) {
    -    // If this is a call, check if it's a tail call.
    +      (isa(I) && cast(I).isVolatile()))
    +    Out << "volatile ";
    +  
    +  if (isa(I) && cast(I).isTailCall())
         Out << "tail ";
    -  }
     
       // Print out the opcode...
       Out << I.getOpcodeName();
    @@ -1913,11 +1917,17 @@
         }
       }
     
    -  // Print post operand alignment for load/store.
    -  if (isa(I) && cast(I).getAlignment()) {
    -    Out << ", align " << cast(I).getAlignment();
    -  } else if (isa(I) && cast(I).getAlignment()) {
    -    Out << ", align " << cast(I).getAlignment();
    +  // Print atomic ordering/alignment for memory operations
    +  if (const LoadInst *LI = dyn_cast(&I)) {
    +    if (LI->isAtomic())
    +      writeAtomic(LI->getOrdering(), LI->getSynchScope());
    +    if (LI->getAlignment())
    +      Out << ", align " << LI->getAlignment();
    +  } else if (const StoreInst *SI = dyn_cast(&I)) {
    +    if (SI->isAtomic())
    +      writeAtomic(SI->getOrdering(), SI->getSynchScope());
    +    if (SI->getAlignment())
    +      Out << ", align " << SI->getAlignment();
       } else if (const AtomicCmpXchgInst *CXI = dyn_cast(&I)) {
         writeAtomic(CXI->getOrdering(), CXI->getSynchScope());
       } else if (const AtomicRMWInst *RMWI = dyn_cast(&I)) {
    
    Modified: llvm/trunk/lib/VMCore/Instructions.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/lib/VMCore/Instructions.cpp (original)
    +++ llvm/trunk/lib/VMCore/Instructions.cpp Tue Aug  9 18:02:53 2011
    @@ -822,6 +822,8 @@
     void LoadInst::AssertOK() {
       assert(getOperand(0)->getType()->isPointerTy() &&
              "Ptr must have pointer type.");
    +  assert(!(isAtomic() && getAlignment() == 0) &&
    +         "Alignment required for atomic load");
     }
     
     LoadInst::LoadInst(Value *Ptr, const Twine &Name, Instruction *InsertBef)
    @@ -829,6 +831,7 @@
                          Load, Ptr, InsertBef) {
       setVolatile(false);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
       setName(Name);
     }
    @@ -838,6 +841,7 @@
                          Load, Ptr, InsertAE) {
       setVolatile(false);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
       setName(Name);
     }
    @@ -848,6 +852,18 @@
                          Load, Ptr, InsertBef) {
       setVolatile(isVolatile);
       setAlignment(0);
    +  setAtomic(NotAtomic);
    +  AssertOK();
    +  setName(Name);
    +}
    +
    +LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
    +                   BasicBlock *InsertAE)
    +  : UnaryInstruction(cast(Ptr->getType())->getElementType(),
    +                     Load, Ptr, InsertAE) {
    +  setVolatile(isVolatile);
    +  setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
       setName(Name);
     }
    @@ -858,6 +874,7 @@
                          Load, Ptr, InsertBef) {
       setVolatile(isVolatile);
       setAlignment(Align);
    +  setAtomic(NotAtomic);
       AssertOK();
       setName(Name);
     }
    @@ -868,27 +885,43 @@
                          Load, Ptr, InsertAE) {
       setVolatile(isVolatile);
       setAlignment(Align);
    +  setAtomic(NotAtomic);
       AssertOK();
       setName(Name);
     }
     
    -LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile,
    +LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, 
    +                   unsigned Align, AtomicOrdering Order,
    +                   SynchronizationScope SynchScope,
    +                   Instruction *InsertBef)
    +  : UnaryInstruction(cast(Ptr->getType())->getElementType(),
    +                     Load, Ptr, InsertBef) {
    +  setVolatile(isVolatile);
    +  setAlignment(Align);
    +  setAtomic(Order, SynchScope);
    +  AssertOK();
    +  setName(Name);
    +}
    +
    +LoadInst::LoadInst(Value *Ptr, const Twine &Name, bool isVolatile, 
    +                   unsigned Align, AtomicOrdering Order,
    +                   SynchronizationScope SynchScope,
                        BasicBlock *InsertAE)
       : UnaryInstruction(cast(Ptr->getType())->getElementType(),
                          Load, Ptr, InsertAE) {
       setVolatile(isVolatile);
    -  setAlignment(0);
    +  setAlignment(Align);
    +  setAtomic(Order, SynchScope);
       AssertOK();
       setName(Name);
     }
     
    -
    -
     LoadInst::LoadInst(Value *Ptr, const char *Name, Instruction *InsertBef)
       : UnaryInstruction(cast(Ptr->getType())->getElementType(),
                          Load, Ptr, InsertBef) {
       setVolatile(false);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
       if (Name && Name[0]) setName(Name);
     }
    @@ -898,6 +931,7 @@
                          Load, Ptr, InsertAE) {
       setVolatile(false);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
       if (Name && Name[0]) setName(Name);
     }
    @@ -908,6 +942,7 @@
                        Load, Ptr, InsertBef) {
       setVolatile(isVolatile);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
       if (Name && Name[0]) setName(Name);
     }
    @@ -918,6 +953,7 @@
                          Load, Ptr, InsertAE) {
       setVolatile(isVolatile);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
       if (Name && Name[0]) setName(Name);
     }
    @@ -926,7 +962,7 @@
       assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
       assert(Align <= MaximumAlignment &&
              "Alignment is greater than MaximumAlignment!");
    -  setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
    +  setInstructionSubclassData((getSubclassDataFromInstruction() & ~(31 << 1)) |
                                  ((Log2_32(Align)+1)<<1));
       assert(getAlignment() == Align && "Alignment representation error!");
     }
    @@ -942,6 +978,8 @@
       assert(getOperand(0)->getType() ==
                      cast(getOperand(1)->getType())->getElementType()
              && "Ptr must be a pointer to Val type!");
    +  assert(!(isAtomic() && getAlignment() == 0) &&
    +         "Alignment required for atomic load");
     }
     
     
    @@ -954,6 +992,7 @@
       Op<1>() = addr;
       setVolatile(false);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
     }
     
    @@ -966,6 +1005,7 @@
       Op<1>() = addr;
       setVolatile(false);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
     }
     
    @@ -979,6 +1019,7 @@
       Op<1>() = addr;
       setVolatile(isVolatile);
       setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
     }
     
    @@ -992,6 +1033,37 @@
       Op<1>() = addr;
       setVolatile(isVolatile);
       setAlignment(Align);
    +  setAtomic(NotAtomic);
    +  AssertOK();
    +}
    +
    +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
    +                     unsigned Align, AtomicOrdering Order,
    +                     SynchronizationScope SynchScope,
    +                     Instruction *InsertBefore)
    +  : Instruction(Type::getVoidTy(val->getContext()), Store,
    +                OperandTraits::op_begin(this),
    +                OperandTraits::operands(this),
    +                InsertBefore) {
    +  Op<0>() = val;
    +  Op<1>() = addr;
    +  setVolatile(isVolatile);
    +  setAlignment(Align);
    +  setAtomic(Order, SynchScope);
    +  AssertOK();
    +}
    +
    +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
    +                     BasicBlock *InsertAtEnd)
    +  : Instruction(Type::getVoidTy(val->getContext()), Store,
    +                OperandTraits::op_begin(this),
    +                OperandTraits::operands(this),
    +                InsertAtEnd) {
    +  Op<0>() = val;
    +  Op<1>() = addr;
    +  setVolatile(isVolatile);
    +  setAlignment(0);
    +  setAtomic(NotAtomic);
       AssertOK();
     }
     
    @@ -1005,10 +1077,13 @@
       Op<1>() = addr;
       setVolatile(isVolatile);
       setAlignment(Align);
    +  setAtomic(NotAtomic);
       AssertOK();
     }
     
     StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
    +                     unsigned Align, AtomicOrdering Order,
    +                     SynchronizationScope SynchScope,
                          BasicBlock *InsertAtEnd)
       : Instruction(Type::getVoidTy(val->getContext()), Store,
                     OperandTraits::op_begin(this),
    @@ -1017,7 +1092,8 @@
       Op<0>() = val;
       Op<1>() = addr;
       setVolatile(isVolatile);
    -  setAlignment(0);
    +  setAlignment(Align);
    +  setAtomic(Order, SynchScope);
       AssertOK();
     }
     
    @@ -1025,7 +1101,7 @@
       assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
       assert(Align <= MaximumAlignment &&
              "Alignment is greater than MaximumAlignment!");
    -  setInstructionSubclassData((getSubclassDataFromInstruction() & 1) |
    +  setInstructionSubclassData((getSubclassDataFromInstruction() & ~(31 << 1)) |
                                  ((Log2_32(Align)+1) << 1));
       assert(getAlignment() == Align && "Alignment representation error!");
     }
    @@ -3158,14 +3234,14 @@
     }
     
     LoadInst *LoadInst::clone_impl() const {
    -  return new LoadInst(getOperand(0),
    -                      Twine(), isVolatile(),
    -                      getAlignment());
    +  return new LoadInst(getOperand(0), Twine(), isVolatile(),
    +                      getAlignment(), getOrdering(), getSynchScope());
     }
     
     StoreInst *StoreInst::clone_impl() const {
    -  return new StoreInst(getOperand(0), getOperand(1),
    -                       isVolatile(), getAlignment());
    +  return new StoreInst(getOperand(0), getOperand(1),isVolatile(),
    +                       getAlignment(), getOrdering(), getSynchScope());
    +  
     }
     
     AtomicCmpXchgInst *AtomicCmpXchgInst::clone_impl() const {
    
    Modified: llvm/trunk/lib/VMCore/Verifier.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=137170&r1=137169&r2=137170&view=diff
    ==============================================================================
    --- llvm/trunk/lib/VMCore/Verifier.cpp (original)
    +++ llvm/trunk/lib/VMCore/Verifier.cpp Tue Aug  9 18:02:53 2011
    @@ -1297,6 +1297,15 @@
       Type *ElTy = PTy->getElementType();
       Assert2(ElTy == LI.getType(),
               "Load result type does not match pointer operand type!", &LI, ElTy);
    +  if (LI.isAtomic()) {
    +    Assert1(LI.getOrdering() != Release && LI.getOrdering() != AcquireRelease,
    +            "Load cannot have Release ordering", &LI);
    +    Assert1(LI.getAlignment() != 0,
    +            "Atomic load must specify explicit alignment", &LI);
    +  } else {
    +    Assert1(LI.getSynchScope() == CrossThread,
    +            "Non-atomic load cannot have SynchronizationScope specified", &LI);
    +  }
       visitInstruction(LI);
     }
     
    @@ -1307,6 +1316,15 @@
       Assert2(ElTy == SI.getOperand(0)->getType(),
               "Stored value type does not match pointer operand type!",
               &SI, ElTy);
    +  if (SI.isAtomic()) {
    +    Assert1(SI.getOrdering() != Acquire && SI.getOrdering() != AcquireRelease,
    +            "Store cannot have Acquire ordering", &SI);
    +    Assert1(SI.getAlignment() != 0,
    +            "Atomic store must specify explicit alignment", &SI);
    +  } else {
    +    Assert1(SI.getSynchScope() == CrossThread,
    +            "Non-atomic store cannot have SynchronizationScope specified", &SI);
    +  }
       visitInstruction(SI);
     }
     
    
    
    
    From resistor at mac.com  Tue Aug  9 18:05:24 2011
    From: resistor at mac.com (Owen Anderson)
    Date: Tue, 09 Aug 2011 23:05:24 -0000
    Subject: [llvm-commits] [llvm] r137171 -
    	/llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp
    Message-ID: <20110809230524.235F32A6C12C@llvm.org>
    
    Author: resistor
    Date: Tue Aug  9 18:05:23 2011
    New Revision: 137171
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137171&view=rev
    Log:
    Fix an oversight in the FixedLenDecoderEmitter where we weren't correctly checking the success result of custom decoder hooks on singleton decodings.
    
    Modified:
        llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp
    
    Modified: llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp?rev=137171&r1=137170&r2=137171&view=diff
    ==============================================================================
    --- llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp (original)
    +++ llvm/trunk/utils/TableGen/FixedLenDecoderEmitter.cpp Tue Aug  9 18:05:23 2011
    @@ -821,8 +821,8 @@
            I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) {
         // If a custom instruction decoder was specified, use that.
         if (I->numFields() == 0 && I->Decoder.size()) {
    -      o.indent(Indentation) << "  " << I->Decoder
    -                            << "(MI, insn, Address, Decoder);\n";
    +      o.indent(Indentation) << "  if (!" << I->Decoder
    +                            << "(MI, insn, Address, Decoder)) return false;\n";
           break;
         }
     
    
    
    
    From resistor at mac.com  Tue Aug  9 18:05:39 2011
    From: resistor at mac.com (Owen Anderson)
    Date: Tue, 09 Aug 2011 23:05:39 -0000
    Subject: [llvm-commits] [llvm] r137172 - in /llvm/trunk:
     lib/Target/ARM/ARMInstrInfo.td
     lib/Target/ARM/Disassembler/ARMDisassembler.cpp
     test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt
     test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
    Message-ID: <20110809230539.5FC982A6C12C@llvm.org>
    
    Author: resistor
    Date: Tue Aug  9 18:05:39 2011
    New Revision: 137172
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137172&view=rev
    Log:
    Tighten operand checking on CPS instructions.
    
    Modified:
        llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
        llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
        llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
    
    Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137172&r1=137171&r2=137172&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
    +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug  9 18:05:39 2011
    @@ -1390,6 +1390,7 @@
       let Inst{4-0}   = mode;
     }
     
    +let DecoderMethod = "DecodeCPSInstruction" in {
     let M = 1 in
       def CPS3p : CPS<(ins imod_op:$imod, iflags_op:$iflags, imm0_31:$mode),
                       "$imod\t$iflags, $mode">;
    @@ -1398,6 +1399,7 @@
     
     let imod = 0, iflags = 0, M = 1 in
       def CPS1p : CPS<(ins imm0_31:$mode), "\t$mode">;
    +}
     
     // Preload signals the memory system of possible future data/instruction access.
     // These are for disassembly only.
    
    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=137172&r1=137171&r2=137172&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
    +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug  9 18:05:39 2011
    @@ -83,6 +83,8 @@
                                                       const void *Decoder);
     static bool DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
                                    uint64_t Address, const void *Decoder);
    +static bool DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn,
    +                               uint64_t Address, const void *Decoder);
     static bool DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
                                    uint64_t Address, const void *Decoder);
     static bool DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
    @@ -1139,6 +1141,9 @@
       unsigned iflags = fieldFromInstruction32(Insn, 6, 3);
       unsigned mode = fieldFromInstruction32(Insn, 0, 5);
     
    +  // imod == '01' --> UNPREDICTABLE
    +  if (imod == 1) return false;
    +
       if (M && mode && imod && iflags) {
         Inst.setOpcode(ARM::CPS3p);
         Inst.addOperand(MCOperand::CreateImm(imod));
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt?rev=137172&r1=137171&r2=137172&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt Tue Aug  9 18:05:39 2011
    @@ -1,5 +1,4 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # invalid imod value (0b01)
     0xc0 0x67 0x4 0xf1
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt?rev=137172&r1=137171&r2=137172&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt Tue Aug  9 18:05:39 2011
    @@ -1,5 +1,4 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # invalid (imod, M, iflags) combination
     0x93 0x1c 0x02 0xf1
    
    
    
    From grosbach at apple.com  Tue Aug  9 18:07:33 2011
    From: grosbach at apple.com (Jim Grosbach)
    Date: Tue, 09 Aug 2011 16:07:33 -0700
    Subject: [llvm-commits] [PATCH] Fix NOP encodings in ARM backend.
    In-Reply-To: <001001cc55d2$c1c4e020$454ea060$%beyls@arm.com>
    References: <001001cc55d2$c1c4e020$454ea060$%beyls@arm.com>
    Message-ID: 
    
    Hi Kristof,
    
    Thanks for looking at this.
    
    1. You should be able to derive the needed information from the Triple, which is already passed in. There's already some code there that does something similar to set the CPU Subtype correctly for Darwin MachO files. See the factory method createARMAsmBackend() for details. There shouldn't be any need to change the top level constructors or the target-independent bits.
    
    2. That sounds like a nasty bug. A bugzilla with a test case would be great.
    
    -Jim
    
    On Aug 8, 2011, at 6:54 AM, Kristof Beyls wrote:
    
    > Hi,
    > 
    > With the attached patch, I'm trying to fix a FIXME in the ARM backend.  This
    > patch fixes ARMAsmBackend::WriteNopData, so that it takes into account the
    > version of the ARM architecture that is being targeted. For versions before
    > ARMv6T2, there is no NOP instruction, and NOPs are encoded as MOV r0,r0 (in
    > ARM
    > mode) or MOV r8,r8 (in Thumb mode). For targets later than ARMv6T2, the
    > encoding for the NOP instruction is created.
    > 
    > I have a few questions about this patch:
    > 
    > 1. To make sure that ARMAsmBackend::WriteNopData can figure out which ARM
    >   sub-target it compiles for, I had to adapt the Target::MCAsmBackendCtorTy
    > to
    >   also pass on an MCSubtargetInfo argument. Is this the best way to get
    >   sub-target information to the ARMAsmBackend object?
    >   (this change results in a few function signature changes in the
    >    ARM, PowerPC, X86 and MBlaze backends).
    > 
    > 2. It's hard to create test cases to test this properly, since I think
    >   that there is another bug in lib/MC/MCAssembler.cpp, where processing 
    >   an alignment fragment results in calling ARMAsmBackend::WriteNopData, but
    >   without putting the ARMAsmBackend in the right ARM or Thumb state.
    >   Therefore, e.g. when processing an assembler file with .align directives
    >   in the middle of a Thumb code section, still ARM NOP encodings are 
    >   generated instead of Thumb NOP encodings.
    >   Question 2a: Is it OK to write a FIXME to indicate this brokenness?
    > Should
    >   I also file a bugzilla issue?
    >   Question 2b: Is it OK to leave that fix for a later, separate, patch? For
    >   that fix, it will be easier to create good test cases that will also test
    >   this patch.
    > 
    > Thanks,
    > 
    > Kristof
    > 
    > PS. I'm cc-ing to the cfe-commits list because the change in
    > Target::MCAsmBackendCtorTy requires 2 lines to change in Clang too, see
    > attached file clang_arm_nop_encoding.patch._______________________________________________
    > llvm-commits mailing list
    > llvm-commits at cs.uiuc.edu
    > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
    
    
    From geek4civic at gmail.com  Tue Aug  9 18:12:56 2011
    From: geek4civic at gmail.com (NAKAMURA Takumi)
    Date: Tue, 09 Aug 2011 23:12:56 -0000
    Subject: [llvm-commits] [llvm] r137174 -
    	/llvm/trunk/lib/VMCore/BasicBlock.cpp
    Message-ID: <20110809231256.D4C4F2A6C12C@llvm.org>
    
    Author: chapuni
    Date: Tue Aug  9 18:12:56 2011
    New Revision: 137174
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137174&view=rev
    Log:
    Fix whitespace.
    
    Modified:
        llvm/trunk/lib/VMCore/BasicBlock.cpp
    
    Modified: llvm/trunk/lib/VMCore/BasicBlock.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/BasicBlock.cpp?rev=137174&r1=137173&r2=137174&view=diff
    ==============================================================================
    --- llvm/trunk/lib/VMCore/BasicBlock.cpp (original)
    +++ llvm/trunk/lib/VMCore/BasicBlock.cpp Tue Aug  9 18:12:56 2011
    @@ -53,7 +53,7 @@
       } else if (NewParent) {
         NewParent->getBasicBlockList().push_back(this);
       }
    -  
    +
       setName(Name);
     }
     
    @@ -76,7 +76,7 @@
           BA->destroyConstant();
         }
       }
    -  
    +
       assert(getParent() == 0 && "BasicBlock still linked into the program!");
       dropAllReferences();
       InstList.clear();
    @@ -184,8 +184,8 @@
     
     /// getUniquePredecessor - If this basic block has a unique predecessor block,
     /// return the block, otherwise return a null pointer.
    -/// Note that unique predecessor doesn't mean single edge, there can be 
    -/// multiple edges from the unique predecessor to this block (for example 
    +/// Note that unique predecessor doesn't mean single edge, there can be
    +/// multiple edges from the unique predecessor to this block (for example
     /// a switch statement with multiple cases having the same destination).
     BasicBlock *BasicBlock::getUniquePredecessor() {
       pred_iterator PI = pred_begin(this), E = pred_end(this);
    
    
    
    From geek4civic at gmail.com  Tue Aug  9 18:13:05 2011
    From: geek4civic at gmail.com (NAKAMURA Takumi)
    Date: Tue, 09 Aug 2011 23:13:05 -0000
    Subject: [llvm-commits] [llvm] r137175 -
    	/llvm/trunk/lib/VMCore/BasicBlock.cpp
    Message-ID: <20110809231305.C63F42A6C12C@llvm.org>
    
    Author: chapuni
    Date: Tue Aug  9 18:13:05 2011
    New Revision: 137175
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137175&view=rev
    Log:
    VMCore/BasicBlock.cpp: Don't assume BasicBlock::iterator might end with a non-PHInode Instruction in successors.
    
    Frontends(eg. clang) might pass incomplete form of IR, to step off the way beyond iterator end. In the case I had met, it took infinite loop due to meeting bogus PHInode.
    
    Thanks to Jay Foad and John McCall.
    
    Modified:
        llvm/trunk/lib/VMCore/BasicBlock.cpp
    
    Modified: llvm/trunk/lib/VMCore/BasicBlock.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/BasicBlock.cpp?rev=137175&r1=137174&r2=137175&view=diff
    ==============================================================================
    --- llvm/trunk/lib/VMCore/BasicBlock.cpp (original)
    +++ llvm/trunk/lib/VMCore/BasicBlock.cpp Tue Aug  9 18:13:05 2011
    @@ -336,8 +336,12 @@
         return;
       for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) {
         BasicBlock *Succ = TI->getSuccessor(i);
    -    for (iterator II = Succ->begin(); PHINode *PN = dyn_cast(II);
    -         ++II) {
    +    // N.B. Succ might not be a complete BasicBlock, so don't assume
    +    // that it ends with a non-phi instruction.
    +    for (iterator II = Succ->begin(), IE = Succ->end(); II != IE; ++II) {
    +      PHINode *PN = dyn_cast(II);
    +      if (!PN)
    +        break;
           int i;
           while ((i = PN->getBasicBlockIndex(this)) >= 0)
             PN->setIncomingBlock(i, New);
    
    
    
    From resistor at mac.com  Tue Aug  9 18:25:42 2011
    From: resistor at mac.com (Owen Anderson)
    Date: Tue, 09 Aug 2011 23:25:42 -0000
    Subject: [llvm-commits] [llvm] r137176 - in /llvm/trunk:
     lib/Target/ARM/ARMInstrInfo.td
     lib/Target/ARM/Disassembler/ARMDisassembler.cpp
     test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
     test/MC/Disassembler/ARM/invalid-DSB-arm.txt
     test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
    Message-ID: <20110809232542.E4E262A6C12C@llvm.org>
    
    Author: resistor
    Date: Tue Aug  9 18:25:42 2011
    New Revision: 137176
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137176&view=rev
    Log:
    Tighten operand checking on memory barrier instructions.
    
    Modified:
        llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
        llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
        llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
    
    Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137176&r1=137175&r2=137176&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
    +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug  9 18:25:42 2011
    @@ -3814,6 +3814,7 @@
     def memb_opt : Operand {
       let PrintMethod = "printMemBOption";
       let ParserMatchClass = MemBarrierOptOperand;
    +  let DecoderMethod = "DecodeMemBarrierOption";
     }
     
     // memory barriers protect the atomic sequences
    
    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=137176&r1=137175&r2=137176&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
    +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug  9 18:25:42 2011
    @@ -131,6 +131,8 @@
                                    uint64_t Address, const void *Decoder);
     static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Insn,
                                    uint64_t Address, const void *Decoder);
    +static bool DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Insn,
    +                               uint64_t Address, const void *Decoder);
     
     
     static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
    @@ -2268,8 +2270,7 @@
         }
     
         unsigned imm = fieldFromInstruction32(Insn, 0, 4);
    -    Inst.addOperand(MCOperand::CreateImm(imm));
    -    return true;
    +    return DecodeMemBarrierOption(Inst, imm, Address, Decoder);
       }
     
       unsigned brtarget = fieldFromInstruction32(Insn, 0, 11) << 1;
    @@ -2347,3 +2348,24 @@
     
       return true;
     }
    +
    +static bool DecodeMemBarrierOption(llvm::MCInst &Inst, unsigned Val,
    +                                   uint64_t Address, const void *Decoder) {
    +  switch (Val) {
    +  default:
    +    return false;
    +  case 0xF: // SY
    +  case 0xE: // ST
    +  case 0xB: // ISH
    +  case 0xA: // ISHST
    +  case 0x7: // NSH
    +  case 0x6: // NSHST
    +  case 0x3: // OSH
    +  case 0x2: // OSHST
    +    break;
    +  }
    +
    +  Inst.addOperand(MCOperand::CreateImm(Val));
    +  return true;
    +}
    +
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt?rev=137176&r1=137175&r2=137176&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt Tue Aug  9 18:25:42 2011
    @@ -1,12 +1,11 @@
     # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=1908 Name=t2DMB 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 
    +#  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: 0: 1: 1| 1: 0: 1: 1| 1: 1: 1: 1| 1: 0: 0: 0| 1: 1: 1: 1| 0: 1: 0: 1| 0: 0: 0: 1|
     # -------------------------------------------------------------------------------------------------
    -# 
    +#
     # Inst{3-0} encodes the option: SY, ST, ISH, ISHST, NSH, NSHST, OSH, OSHST.
     # Reject invalid encodings.
     #
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt?rev=137176&r1=137175&r2=137176&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt Tue Aug  9 18:25:42 2011
    @@ -1,12 +1,11 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=102 Name=DSB Format=ARM_FORMAT_MISCFRM(26)
    -#  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 
    +#  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: 1| 0: 1: 1: 1| 1: 1: 1: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 1: 0: 0| 0: 0: 0: 0|
     # -------------------------------------------------------------------------------------------------
    -# 
    +#
     # Inst{3-0} encodes the option: SY, ST, ISH, ISHST, NSH, NSHST, OSH, OSHST.
     # Reject invalid encodings.
     #
    
    Modified: 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=137176&r1=137175&r2=137176&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt Tue Aug  9 18:25:42 2011
    @@ -1,12 +1,11 @@
     # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # 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 
    +#  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
    
    
    
    From eli.friedman at gmail.com  Tue Aug  9 18:26:13 2011
    From: eli.friedman at gmail.com (Eli Friedman)
    Date: Tue, 09 Aug 2011 23:26:13 -0000
    Subject: [llvm-commits] [llvm] r137177 - /llvm/trunk/docs/LangRef.html
    Message-ID: <20110809232613.4FE1F2A6C12C@llvm.org>
    
    Author: efriedma
    Date: Tue Aug  9 18:26:12 2011
    New Revision: 137177
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137177&view=rev
    Log:
    Fix minor typo.
    
    
    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=137177&r1=137176&r2=137177&view=diff
    ==============================================================================
    --- llvm/trunk/docs/LangRef.html (original)
    +++ llvm/trunk/docs/LangRef.html Tue Aug  9 18:26:12 2011
    @@ -1586,7 +1586,7 @@
     atomicrmw,
     fence,
     atomic load, and
    -atomic store) take an ordering parameter
    +atomic store) take an ordering parameter
     that determines which other atomic instructions on the same address they
     synchronize with.  These semantics are borrowed from Java and C++0x,
     but are somewhat more colloquial. If these descriptions aren't precise enough,
    
    
    
    From bruno.cardoso at gmail.com  Tue Aug  9 18:27:13 2011
    From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes)
    Date: Tue, 09 Aug 2011 23:27:13 -0000
    Subject: [llvm-commits] [llvm] r137179 - in /llvm/trunk:
     lib/Target/X86/X86ISelLowering.cpp lib/Target/X86/X86InstrCompiler.td
     test/CodeGen/X86/avx-select.ll
    Message-ID: <20110809232713.55FF22A6C12C@llvm.org>
    
    Author: bruno
    Date: Tue Aug  9 18:27:13 2011
    New Revision: 137179
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137179&view=rev
    Log:
    Add 256-bit support for v8i32, v4i64 and v4f64 ISD::SELECT. Fix PR10556
    
    Added:
        llvm/trunk/test/CodeGen/X86/avx-select.ll
    Modified:
        llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
        llvm/trunk/lib/Target/X86/X86InstrCompiler.td
    
    Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137179&r1=137178&r2=137179&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
    +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Aug  9 18:27:13 2011
    @@ -992,6 +992,10 @@
         setOperationAction(ISD::VSETCC,            MVT::v8i32, Custom);
         setOperationAction(ISD::VSETCC,            MVT::v4i64, Custom);
     
    +    setOperationAction(ISD::SELECT,            MVT::v4f64, Custom);
    +    setOperationAction(ISD::SELECT,            MVT::v4i64, Custom);
    +    setOperationAction(ISD::SELECT,            MVT::v8f32, Custom);
    +
         // Custom lower several nodes for 256-bit types.
         for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE;
                       i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) {
    @@ -11172,6 +11176,9 @@
       case X86::CMOV_V4F32:
       case X86::CMOV_V2F64:
       case X86::CMOV_V2I64:
    +  case X86::CMOV_V8F32:
    +  case X86::CMOV_V4F64:
    +  case X86::CMOV_V4I64:
       case X86::CMOV_GR16:
       case X86::CMOV_GR32:
       case X86::CMOV_RFP32:
    
    Modified: llvm/trunk/lib/Target/X86/X86InstrCompiler.td
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrCompiler.td?rev=137179&r1=137178&r2=137179&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/X86/X86InstrCompiler.td (original)
    +++ llvm/trunk/lib/Target/X86/X86InstrCompiler.td Tue Aug  9 18:27:13 2011
    @@ -759,6 +759,24 @@
                         [(set VR128:$dst,
                           (v2i64 (X86cmov VR128:$t, VR128:$f, imm:$cond,
                                               EFLAGS)))]>;
    +  def CMOV_V8F32 : I<0, Pseudo,
    +                    (outs VR256:$dst), (ins VR256:$t, VR256:$f, i8imm:$cond),
    +                    "#CMOV_V8F32 PSEUDO!",
    +                    [(set VR256:$dst,
    +                      (v8f32 (X86cmov VR256:$t, VR256:$f, imm:$cond,
    +                                          EFLAGS)))]>;
    +  def CMOV_V4F64 : I<0, Pseudo,
    +                    (outs VR256:$dst), (ins VR256:$t, VR256:$f, i8imm:$cond),
    +                    "#CMOV_V4F64 PSEUDO!",
    +                    [(set VR256:$dst,
    +                      (v4f64 (X86cmov VR256:$t, VR256:$f, imm:$cond,
    +                                          EFLAGS)))]>;
    +  def CMOV_V4I64 : I<0, Pseudo,
    +                    (outs VR256:$dst), (ins VR256:$t, VR256:$f, i8imm:$cond),
    +                    "#CMOV_V4I64 PSEUDO!",
    +                    [(set VR256:$dst,
    +                      (v4i64 (X86cmov VR256:$t, VR256:$f, imm:$cond,
    +                                          EFLAGS)))]>;
     }
     
     
    
    Added: llvm/trunk/test/CodeGen/X86/avx-select.ll
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-select.ll?rev=137179&view=auto
    ==============================================================================
    --- llvm/trunk/test/CodeGen/X86/avx-select.ll (added)
    +++ llvm/trunk/test/CodeGen/X86/avx-select.ll Tue Aug  9 18:27:13 2011
    @@ -0,0 +1,22 @@
    +; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7-avx -mattr=+avx | FileCheck %s
    +
    +; CHECK: _select00
    +; CHECK: vmovaps
    +; CHECK-NEXT: LBB
    +define <8 x i32> @select00(i32 %a, <8 x i32> %b) nounwind {
    +  %cmpres = icmp eq i32 %a, 255
    +  %selres = select i1 %cmpres, <8 x i32> zeroinitializer, <8 x i32> %b
    +  %res = xor <8 x i32> %b, %selres
    +  ret <8 x i32> %res
    +}
    +
    +; CHECK: _select01
    +; CHECK: vmovaps
    +; CHECK-NEXT: LBB
    +define <4 x i64> @select01(i32 %a, <4 x i64> %b) nounwind {
    +  %cmpres = icmp eq i32 %a, 255
    +  %selres = select i1 %cmpres, <4 x i64> zeroinitializer, <4 x i64> %b
    +  %res = xor <4 x i64> %b, %selres
    +  ret <4 x i64> %res
    +}
    +
    
    
    
    From resistor at mac.com  Tue Aug  9 18:33:27 2011
    From: resistor at mac.com (Owen Anderson)
    Date: Tue, 09 Aug 2011 23:33:27 -0000
    Subject: [llvm-commits] [llvm] r137180 - in /llvm/trunk:
     lib/Target/ARM/ARMInstrInfo.td
     lib/Target/ARM/Disassembler/ARMDisassembler.cpp
     test/MC/Disassembler/ARM/invalid-LSL-regform.txt
     test/MC/Disassembler/ARM/invalid-RSC-arm.txt
    Message-ID: <20110809233327.AB7912A6C12C@llvm.org>
    
    Author: resistor
    Date: Tue Aug  9 18:33:27 2011
    New Revision: 137180
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137180&view=rev
    Log:
    Tighten operand checking of register-shifted-register operands.
    
    Modified:
        llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
        llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
        llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
    
    Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137180&r1=137179&r2=137180&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
    +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug  9 18:33:27 2011
    @@ -439,7 +439,7 @@
       let PrintMethod = "printSORegRegOperand";
       let DecoderMethod = "DecodeSORegRegOperand";
       let ParserMatchClass = ShiftedRegAsmOperand;
    -  let MIOperandInfo = (ops GPR, GPR, i32imm);
    +  let MIOperandInfo = (ops GPRnopc, GPRnopc, i32imm);
     }
     
     def ShiftedImmAsmOperand : AsmOperandClass { let Name = "RegShiftedImm"; }
    @@ -2541,9 +2541,9 @@
       let Inst{15-12} = Rd;
     }
     
    -def MOVsr : AsI1<0b1101, (outs GPR:$Rd), (ins shift_so_reg_reg:$src),
    +def MOVsr : AsI1<0b1101, (outs GPRnopc:$Rd), (ins shift_so_reg_reg:$src),
                     DPSoRegRegFrm, IIC_iMOVsr,
    -                "mov", "\t$Rd, $src", [(set GPR:$Rd, shift_so_reg_reg:$src)]>,
    +                "mov", "\t$Rd, $src", [(set GPRnopc:$Rd, shift_so_reg_reg:$src)]>,
                     UnaryDP {
       bits<4> Rd;
       bits<12> src;
    
    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=137180&r1=137179&r2=137180&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
    +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug  9 18:33:27 2011
    @@ -683,8 +683,8 @@
       unsigned Rs = fieldFromInstruction32(Val, 8, 4);
     
       // Register-register
    -  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    -  DecodeGPRRegisterClass(Inst, Rs, Address, Decoder);
    +  if (!DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder)) return false;
    +  if (!DecodeGPRnopcRegisterClass(Inst, Rs, Address, Decoder)) return false;
     
       ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
       switch (type) {
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt?rev=137180&r1=137179&r2=137180&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt Tue Aug  9 18:33:27 2011
    @@ -1,8 +1,7 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5)
    -#  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 
    +#  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: 0: 0: 1| 1: 0: 1: 0| 0: 0: 0: 0| 1: 1: 1: 1| 0: 0: 0: 1| 0: 0: 0: 1| 0: 0: 1: 0|
     # -------------------------------------------------------------------------------------------------
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt?rev=137180&r1=137179&r2=137180&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt Tue Aug  9 18:33:27 2011
    @@ -1,8 +1,7 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=261 Name=RSCrs Format=ARM_FORMAT_DPSOREGFRM(5)
    -#  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 
    +#  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: 1: 1| 0: 0: 0: 0| 1: 1: 1: 0| 0: 1: 0: 0| 1: 1: 1: 1| 1: 0: 0: 0| 0: 1: 0: 1| 1: 1: 1: 1|
     # -------------------------------------------------------------------------------------------------
    
    
    
    From geek4civic at gmail.com  Tue Aug  9 18:42:37 2011
    From: geek4civic at gmail.com (NAKAMURA Takumi)
    Date: Wed, 10 Aug 2011 08:42:37 +0900
    Subject: [llvm-commits] r133708 strikes me again? - the case clang stalls
    In-Reply-To: <2B900B62-E852-4E5A-89C1-E5F0DBB44EA6@apple.com>
    References: 
    	
    	
    	
    	
    	<2B900B62-E852-4E5A-89C1-E5F0DBB44EA6@apple.com>
    Message-ID: 
    
    Jay and John, I have committed Jay's in r137175, thank you!
    
    ...Takumi
    
    From stoklund at 2pi.dk  Tue Aug  9 18:41:44 2011
    From: stoklund at 2pi.dk (Jakob Stoklund Olesen)
    Date: Tue, 09 Aug 2011 23:41:44 -0000
    Subject: [llvm-commits] [llvm] r137182 -
    	/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
    Message-ID: <20110809234144.BBC572A6C12C@llvm.org>
    
    Author: stoklund
    Date: Tue Aug  9 18:41:44 2011
    New Revision: 137182
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137182&view=rev
    Log:
    Promote VMOVS to VMOVD when possible.
    
    On Cortex-A8, we use the NEON v2f32 instructions for f32 arithmetic. For
    better latency, we also send D-register copies down the NEON pipeline by
    translating them to vorr instructions.
    
    This patch promotes even S-register copies to D-register copies when
    possible so they can also go down the NEON pipeline.  Example:
    
            vldr.32 s0, LCPI0_0
        loop:
            vorr    d1, d0, d0
        loop2:
            ...
            vadd.f32        d1, d1, d16
    
    The vorr instruction looked like this after regalloc:
    
        %S2 = COPY %S0, %D1
    
    Copies involving odd S-registers, and copies that don't define the full
    D-register are left alone.
    
    Modified:
        llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
    
    Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=137182&r1=137181&r2=137182&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)
    +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Tue Aug  9 18:41:44 2011
    @@ -629,9 +629,36 @@
       bool SPRSrc  = ARM::SPRRegClass.contains(SrcReg);
     
       unsigned Opc;
    -  if (SPRDest && SPRSrc)
    +  if (SPRDest && SPRSrc) {
         Opc = ARM::VMOVS;
    -  else if (GPRDest && SPRSrc)
    +
    +    // An even S-S copy may be feeding a NEON v2f32 instruction being used for
    +    // f32 operations.  In that case, it is better to copy the full D-regs with
    +    // a VMOVD since that can be converted to a NEON-domain move by
    +    // NEONMoveFix.cpp.  Check that MI is the original COPY instruction, and
    +    // that it really defines the whole D-register.
    +    if ((DestReg - ARM::S0) % 2 == 0 && (SrcReg - ARM::S0) % 2 == 0 &&
    +        I != MBB.end() && I->isCopy() &&
    +        I->getOperand(0).getReg() == DestReg &&
    +        I->getOperand(1).getReg() == SrcReg) {
    +      // I is pointing to the ortiginal COPY instruction.
    +      // Find the parent D-registers.
    +      const TargetRegisterInfo *TRI = &getRegisterInfo();
    +      unsigned SrcD = TRI->getMatchingSuperReg(SrcReg, ARM::ssub_0,
    +                                               &ARM::DPRRegClass);
    +      unsigned DestD = TRI->getMatchingSuperReg(DestReg, ARM::ssub_0,
    +                                                &ARM::DPRRegClass);
    +      // Be careful to not clobber an INSERT_SUBREG that reads and redefines a
    +      // D-register.  There must be an  of destD, and no .
    +      if (I->definesRegister(DestD, TRI) && !I->readsRegister(DestD, TRI)) {
    +        Opc = ARM::VMOVD;
    +        SrcReg = SrcD;
    +        DestReg = DestD;
    +        if (KillSrc)
    +          KillSrc = I->killsRegister(SrcReg, TRI);
    +      }
    +    }
    +  } else if (GPRDest && SPRSrc)
         Opc = ARM::VMOVRS;
       else if (SPRDest && GPRSrc)
         Opc = ARM::VMOVSR;
    
    
    
    From echristo at apple.com  Tue Aug  9 18:45:56 2011
    From: echristo at apple.com (Eric Christopher)
    Date: Tue, 09 Aug 2011 23:45:56 -0000
    Subject: [llvm-commits] [llvm-gcc-4.2] r137183 - in /llvm-gcc-4.2/trunk:
     config/mh-x86-darwin configure configure.in gcc/Makefile.in
    Message-ID: <20110809234556.841582A6C12C@llvm.org>
    
    Author: echristo
    Date: Tue Aug  9 18:45:56 2011
    New Revision: 137183
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137183&view=rev
    Log:
    Allow llvm-gcc to build with clang for darwin. For hosts that have gcc
    compatible compilers this should work in general.
    
    Modified:
        llvm-gcc-4.2/trunk/config/mh-x86-darwin
        llvm-gcc-4.2/trunk/configure
        llvm-gcc-4.2/trunk/configure.in
        llvm-gcc-4.2/trunk/gcc/Makefile.in
    
    Modified: llvm-gcc-4.2/trunk/config/mh-x86-darwin
    URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/config/mh-x86-darwin?rev=137183&r1=137182&r2=137183&view=diff
    ==============================================================================
    --- llvm-gcc-4.2/trunk/config/mh-x86-darwin (original)
    +++ llvm-gcc-4.2/trunk/config/mh-x86-darwin Tue Aug  9 18:45:56 2011
    @@ -2,7 +2,7 @@
     # The -mdynamic-no-pic ensures that the compiler executable is built without
     # position-independent-code -- the usual default on Darwin.
     
    -BOOT_CFLAGS=-g -O2 -mdynamic-no-pic
    +BOOT_CFLAGS=-g -O2 -mdynamic-no-pic -std=gnu89
     
     # LLVM LOCAL
     # For hosts after darwin10 we want to pass in -no-pie
    
    Modified: llvm-gcc-4.2/trunk/configure
    URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/configure?rev=137183&r1=137182&r2=137183&view=diff
    ==============================================================================
    --- llvm-gcc-4.2/trunk/configure (original)
    +++ llvm-gcc-4.2/trunk/configure Tue Aug  9 18:45:56 2011
    @@ -7405,6 +7405,10 @@
         # that too.
         stage1_cflags="-g -no-cpp-precomp -DHAVE_DESIGNATED_INITIALIZERS=0"
         ;;
    +  *-*-darwin*)
    +    # -std=gnu89 never hurt
    +    stage1_cflags="-g -std=gnu89"
    +    ;;
     esac
     
     # LLVM LOCAL begin - LLVM uses inlined functions
    @@ -7416,9 +7420,9 @@
       # Pass -fkeep-inline-functions for stage 1 if the GCC version supports it.
       CFLAGS="$CFLAGS -fkeep-inline-functions"
       echo $ac_n "checking whether -fkeep-inline-functions is supported""... $ac_c" 1>&6
    -echo "configure:7420: checking whether -fkeep-inline-functions is supported" >&5
    +echo "configure:7424: checking whether -fkeep-inline-functions is supported" >&5
       cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then
    +if { (eval echo configure:7439: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
       rm -rf conftest*
       echo "$ac_t""yes" 1>&6; stage1_cflags="$stage1_cflags -fkeep-inline-functions"
     else
    
    Modified: llvm-gcc-4.2/trunk/configure.in
    URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/configure.in?rev=137183&r1=137182&r2=137183&view=diff
    ==============================================================================
    --- llvm-gcc-4.2/trunk/configure.in (original)
    +++ llvm-gcc-4.2/trunk/configure.in Tue Aug  9 18:45:56 2011
    @@ -2462,6 +2462,10 @@
         # that too.
         stage1_cflags="-g -no-cpp-precomp -DHAVE_DESIGNATED_INITIALIZERS=0"
         ;;
    +  *-*-darwin*)
    +    # -std=gnu89 never hurt
    +    stage1_cflags="-g -std=gnu89"
    +    ;;
     esac
     
     # LLVM LOCAL begin - LLVM uses inlined functions
    
    Modified: llvm-gcc-4.2/trunk/gcc/Makefile.in
    URL: http://llvm.org/viewvc/llvm-project/llvm-gcc-4.2/trunk/gcc/Makefile.in?rev=137183&r1=137182&r2=137183&view=diff
    ==============================================================================
    --- llvm-gcc-4.2/trunk/gcc/Makefile.in (original)
    +++ llvm-gcc-4.2/trunk/gcc/Makefile.in Tue Aug  9 18:45:56 2011
    @@ -965,8 +965,11 @@
     
     # LLVM LOCAL begin
     # Disable C-only warning flags if they are present.
    -ALL_CXXFLAGS = $(filter-out -Wstrict-prototypes -Wmissing-prototypes \
    -                            -Wold-style-definition -Wno-overlength-strings, $(ALL_CFLAGS)) -Wno-unused
    +ALL_CXXFLAGS = $(filter-out -std=gnu89 \
    +			    -Werror  -Wstrict-prototypes  \
    +			    -Wmissing-prototypes \
    +                            -Wold-style-definition -Wno-overlength-strings, \
    +		$(ALL_CFLAGS)) -Wno-unused
     ALL_CXXFLAGS += -DTARGET_NAME=\"$(target_noncanonical)\"
     ALL_CXXFLAGS += -DTARGET_CANONICAL_NAME=\"$(target)\"
     ALL_CXXFLAGS += -frandom-seed=0
    
    
    
    From stoklund at 2pi.dk  Tue Aug  9 18:49:21 2011
    From: stoklund at 2pi.dk (Jakob Stoklund Olesen)
    Date: Tue, 09 Aug 2011 23:49:21 -0000
    Subject: [llvm-commits] [llvm] r137184 - in /llvm/trunk:
     include/llvm/CodeGen/FunctionLoweringInfo.h
     include/llvm/Target/TargetRegisterInfo.h
     lib/CodeGen/StrongPHIElimination.cpp lib/CodeGen/TailDuplication.cpp
    Message-ID: <20110809234921.6695D2A6C12C@llvm.org>
    
    Author: stoklund
    Date: Tue Aug  9 18:49:21 2011
    New Revision: 137184
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137184&view=rev
    Log:
    Trim an unneeded header.
    
    Modified:
        llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h
        llvm/trunk/include/llvm/Target/TargetRegisterInfo.h
        llvm/trunk/lib/CodeGen/StrongPHIElimination.cpp
        llvm/trunk/lib/CodeGen/TailDuplication.cpp
    
    Modified: llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h?rev=137184&r1=137183&r2=137184&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h (original)
    +++ llvm/trunk/include/llvm/CodeGen/FunctionLoweringInfo.h Tue Aug  9 18:49:21 2011
    @@ -19,6 +19,7 @@
     #include "llvm/Instructions.h"
     #include "llvm/ADT/APInt.h"
     #include "llvm/ADT/DenseMap.h"
    +#include "llvm/ADT/DenseSet.h"
     #include "llvm/ADT/IndexedMap.h"
     #include "llvm/ADT/SmallVector.h"
     #ifndef NDEBUG
    
    Modified: llvm/trunk/include/llvm/Target/TargetRegisterInfo.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetRegisterInfo.h?rev=137184&r1=137183&r2=137184&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Target/TargetRegisterInfo.h (original)
    +++ llvm/trunk/include/llvm/Target/TargetRegisterInfo.h Tue Aug  9 18:49:21 2011
    @@ -20,7 +20,6 @@
     #include "llvm/CodeGen/MachineBasicBlock.h"
     #include "llvm/CodeGen/ValueTypes.h"
     #include "llvm/ADT/ArrayRef.h"
    -#include "llvm/ADT/DenseSet.h"
     #include 
     #include 
     
    
    Modified: llvm/trunk/lib/CodeGen/StrongPHIElimination.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/StrongPHIElimination.cpp?rev=137184&r1=137183&r2=137184&view=diff
    ==============================================================================
    --- llvm/trunk/lib/CodeGen/StrongPHIElimination.cpp (original)
    +++ llvm/trunk/lib/CodeGen/StrongPHIElimination.cpp Tue Aug  9 18:49:21 2011
    @@ -47,6 +47,7 @@
     #include "llvm/CodeGen/MachineInstrBuilder.h"
     #include "llvm/CodeGen/MachineRegisterInfo.h"
     #include "llvm/Target/TargetInstrInfo.h"
    +#include "llvm/ADT/DenseSet.h"
     #include "llvm/ADT/Statistic.h"
     #include "llvm/Support/Debug.h"
     using namespace llvm;
    
    Modified: llvm/trunk/lib/CodeGen/TailDuplication.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/TailDuplication.cpp?rev=137184&r1=137183&r2=137184&view=diff
    ==============================================================================
    --- llvm/trunk/lib/CodeGen/TailDuplication.cpp (original)
    +++ llvm/trunk/lib/CodeGen/TailDuplication.cpp Tue Aug  9 18:49:21 2011
    @@ -25,6 +25,7 @@
     #include "llvm/Support/Debug.h"
     #include "llvm/Support/ErrorHandling.h"
     #include "llvm/Support/raw_ostream.h"
    +#include "llvm/ADT/DenseSet.h"
     #include "llvm/ADT/SmallSet.h"
     #include "llvm/ADT/SetVector.h"
     #include "llvm/ADT/Statistic.h"
    
    
    
    From echristo at apple.com  Tue Aug  9 18:59:06 2011
    From: echristo at apple.com (Eric Christopher)
    Date: Tue, 09 Aug 2011 23:59:06 -0000
    Subject: [llvm-commits] [llvm] r137187 - /llvm/trunk/utils/buildit/build_llvm
    Message-ID: <20110809235906.2F7762A6C12E@llvm.org>
    
    Author: echristo
    Date: Tue Aug  9 18:59:05 2011
    New Revision: 137187
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137187&view=rev
    Log:
    clang is the new black.
    
    Modified:
        llvm/trunk/utils/buildit/build_llvm
    
    Modified: llvm/trunk/utils/buildit/build_llvm
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/buildit/build_llvm?rev=137187&r1=137186&r2=137187&view=diff
    ==============================================================================
    --- llvm/trunk/utils/buildit/build_llvm (original)
    +++ llvm/trunk/utils/buildit/build_llvm Tue Aug  9 18:59:05 2011
    @@ -110,15 +110,15 @@
       done
     
       PATH=$DIR/bin:$PATH
    -# otherwise, try to use llvm-gcc if it's available
    +# otherwise, try to use clang if it's available
     elif [ $DARWIN_VERS -gt 9 ]; then
       # If the user has set CC or CXX, respect their wishes.  If not,
    -  # compile with LLVM-GCC/LLVM-G++ if available; if LLVM is not
    +  # compile with clang/clang if available; if LLVM is not
       # available, fall back to usual GCC/G++ default.
       savedPATH=$PATH ; PATH="/Developer/usr/bin:$PATH"
    -  XTMPCC=$(which llvm-gcc)
    +  XTMPCC=$(which clang)
       if [ x$CC  = x -a x$XTMPCC != x ] ; then export CC=$XTMPCC  ; fi
    -  XTMPCC=$(which llvm-g++)
    +  XTMPCC=$(which clang++)
       if [ x$CXX = x -a x$XTMPCC != x ] ; then export CXX=$XTMPCC ; fi
       PATH=$savedPATH
       unset XTMPCC savedPATH
    
    
    
    From echristo at apple.com  Tue Aug  9 19:02:39 2011
    From: echristo at apple.com (Eric Christopher)
    Date: Wed, 10 Aug 2011 00:02:39 -0000
    Subject: [llvm-commits] [llvm] r137188 - /llvm/trunk/utils/buildit/build_llvm
    Message-ID: <20110810000239.AC9982A6C12C@llvm.org>
    
    Author: echristo
    Date: Tue Aug  9 19:02:39 2011
    New Revision: 137188
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137188&view=rev
    Log:
    Update comment.
    
    Modified:
        llvm/trunk/utils/buildit/build_llvm
    
    Modified: llvm/trunk/utils/buildit/build_llvm
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/buildit/build_llvm?rev=137188&r1=137187&r2=137188&view=diff
    ==============================================================================
    --- llvm/trunk/utils/buildit/build_llvm (original)
    +++ llvm/trunk/utils/buildit/build_llvm Tue Aug  9 19:02:39 2011
    @@ -113,7 +113,7 @@
     # otherwise, try to use clang if it's available
     elif [ $DARWIN_VERS -gt 9 ]; then
       # If the user has set CC or CXX, respect their wishes.  If not,
    -  # compile with clang/clang if available; if LLVM is not
    +  # compile with clang/clang++ if available; if LLVM is not
       # available, fall back to usual GCC/G++ default.
       savedPATH=$PATH ; PATH="/Developer/usr/bin:$PATH"
       XTMPCC=$(which clang)
    
    
    
    From resistor at mac.com  Tue Aug  9 19:03:03 2011
    From: resistor at mac.com (Owen Anderson)
    Date: Wed, 10 Aug 2011 00:03:03 -0000
    Subject: [llvm-commits] [llvm] r137189 - in /llvm/trunk:
     lib/Target/ARM/ARMInstrInfo.td
     lib/Target/ARM/Disassembler/ARMDisassembler.cpp
     test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
     test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
     test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
     test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
     test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
     test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
    Message-ID: <20110810000303.6E4D02A6C12C@llvm.org>
    
    Author: resistor
    Date: Tue Aug  9 19:03:03 2011
    New Revision: 137189
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137189&view=rev
    Log:
    Push GPRnopc through a large number of instruction definitions to tighten operand decoding.
    
    Modified:
        llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
        llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
        llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
        llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
    
    Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137189&r1=137188&r2=137189&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
    +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug  9 19:03:03 2011
    @@ -1061,9 +1061,9 @@
     /// register and one whose operand is a register rotated by 8/16/24.
     /// FIXME: Remove the 'r' variant. Its rot_imm is zero.
     class AI_ext_rrot opcod, string opc, PatFrag opnode>
    -  : AExtI,
    +          [(set GPRnopc:$Rd, (opnode (rotr GPRnopc:$Rm, rot_imm:$rot)))]>,
            Requires<[IsARM, HasV6]> {
       bits<4> Rd;
       bits<4> Rm;
    @@ -1075,7 +1075,7 @@
     }
     
     class AI_ext_rrot_np opcod, string opc>
    -  : AExtI,
            Requires<[IsARM, HasV6]> {
       bits<2> rot;
    @@ -1086,9 +1086,10 @@
     /// AI_exta_rrot - A binary operation with two forms: one whose operand is a
     /// register and one whose operand is a register rotated by 8/16/24.
     class AI_exta_rrot opcod, string opc, PatFrag opnode>
    -  : AExtI,
    +          [(set GPRnopc:$Rd, (opnode GPR:$Rn,
    +                                     (rotr GPRnopc:$Rm, rot_imm:$rot)))]>,
             Requires<[IsARM, HasV6]> {
       bits<4> Rd;
       bits<4> Rm;
    @@ -1102,7 +1103,7 @@
     }
     
     class AI_exta_rrot_np opcod, string opc>
    -  : AExtI,
            Requires<[IsARM, HasV6]> {
       bits<4> Rn;
    @@ -2605,10 +2606,10 @@
                                     (ins i32imm:$addr, pclabel:$id), IIC_iMOVi, []>;
     
     let Constraints = "$src = $Rd" in {
    -def MOVTi16 : AI1<0b1010, (outs GPR:$Rd), (ins GPR:$src, imm0_65535_expr:$imm),
    +def MOVTi16 : AI1<0b1010, (outs GPRnopc:$Rd), (ins GPR:$src, imm0_65535_expr:$imm),
                       DPFrm, IIC_iMOVi,
                       "movt", "\t$Rd, $imm",
    -                  [(set GPR:$Rd,
    +                  [(set GPRnopc:$Rd,
                             (or (and GPR:$src, 0xffff),
                                 lo16AllZero:$imm))]>, UnaryDP,
                       Requires<[IsARM, HasV6T2]> {
    @@ -2695,8 +2696,8 @@
     def UXTAB16 : AI_exta_rrot_np<0b01101100, "uxtab16">;
     
     
    -def SBFX  : I<(outs GPR:$Rd),
    -              (ins GPR:$Rn, imm0_31:$lsb, imm1_32:$width),
    +def SBFX  : I<(outs GPRnopc:$Rd),
    +              (ins GPRnopc:$Rn, imm0_31:$lsb, imm1_32:$width),
                    AddrMode1, 4, IndexModeNone, DPFrm, IIC_iUNAsi,
                    "sbfx", "\t$Rd, $Rn, $lsb, $width", "", []>,
                    Requires<[IsARM, HasV6T2]> {
    @@ -2937,8 +2938,9 @@
     // GPR:$dst = GPR:$a op GPR:$b
     class AAI op27_20, bits<8> op11_4, string opc,
               list pattern = [],
    -          dag iops = (ins GPR:$Rn, GPR:$Rm), string asm = "\t$Rd, $Rn, $Rm">
    -  : AI<(outs GPR:$Rd), iops, DPFrm, IIC_iALUr, opc, asm, pattern> {
    +          dag iops = (ins GPRnopc:$Rn, GPRnopc:$Rm),
    +          string asm = "\t$Rd, $Rn, $Rm">
    +  : AI<(outs GPRnopc:$Rd), iops, DPFrm, IIC_iALUr, opc, asm, pattern> {
       bits<4> Rn;
       bits<4> Rd;
       bits<4> Rm;
    @@ -2952,14 +2954,16 @@
     // Saturating add/subtract
     
     def QADD    : AAI<0b00010000, 0b00000101, "qadd",
    -                  [(set GPR:$Rd, (int_arm_qadd GPR:$Rm, GPR:$Rn))],
    -                  (ins GPR:$Rm, GPR:$Rn), "\t$Rd, $Rm, $Rn">;
    +                  [(set GPRnopc:$Rd, (int_arm_qadd GPRnopc:$Rm, GPRnopc:$Rn))],
    +                  (ins GPRnopc:$Rm, GPRnopc:$Rn), "\t$Rd, $Rm, $Rn">;
     def QSUB    : AAI<0b00010010, 0b00000101, "qsub",
    -                  [(set GPR:$Rd, (int_arm_qsub GPR:$Rm, GPR:$Rn))],
    -                  (ins GPR:$Rm, GPR:$Rn), "\t$Rd, $Rm, $Rn">;
    -def QDADD   : AAI<0b00010100, 0b00000101, "qdadd", [], (ins GPR:$Rm, GPR:$Rn),
    +                  [(set GPRnopc:$Rd, (int_arm_qsub GPRnopc:$Rm, GPRnopc:$Rn))],
    +                  (ins GPRnopc:$Rm, GPRnopc:$Rn), "\t$Rd, $Rm, $Rn">;
    +def QDADD   : AAI<0b00010100, 0b00000101, "qdadd", [],
    +                  (ins GPRnopc:$Rm, GPRnopc:$Rn),
                       "\t$Rd, $Rm, $Rn">;
    -def QDSUB   : AAI<0b00010110, 0b00000101, "qdsub", [], (ins GPR:$Rm, GPR:$Rn),
    +def QDSUB   : AAI<0b00010110, 0b00000101, "qdsub", [],
    +                  (ins GPRnopc:$Rm, GPRnopc:$Rn),
                       "\t$Rd, $Rm, $Rn">;
     
     def QADD16  : AAI<0b01100010, 0b11110001, "qadd16">;
    @@ -3039,7 +3043,8 @@
     
     // Signed/Unsigned saturate -- for disassembly only
     
    -def SSAT : AI<(outs GPR:$Rd), (ins imm1_32:$sat_imm, GPR:$Rn, shift_imm:$sh),
    +def SSAT : AI<(outs GPRnopc:$Rd),
    +              (ins imm1_32:$sat_imm, GPRnopc:$Rn, shift_imm:$sh),
                   SatFrm, NoItinerary, "ssat", "\t$Rd, $sat_imm, $Rn$sh", []> {
       bits<4> Rd;
       bits<5> sat_imm;
    @@ -3054,7 +3059,8 @@
       let Inst{3-0} = Rn;
     }
     
    -def SSAT16 : AI<(outs GPR:$Rd), (ins imm1_16:$sat_imm, GPR:$Rn), SatFrm,
    +def SSAT16 : AI<(outs GPRnopc:$Rd),
    +                (ins imm1_16:$sat_imm, GPRnopc:$Rn), SatFrm,
                     NoItinerary, "ssat16", "\t$Rd, $sat_imm, $Rn", []> {
       bits<4> Rd;
       bits<4> sat_imm;
    @@ -3066,7 +3072,8 @@
       let Inst{3-0} = Rn;
     }
     
    -def USAT : AI<(outs GPR:$Rd), (ins imm0_31:$sat_imm, GPR:$Rn, shift_imm:$sh),
    +def USAT : AI<(outs GPRnopc:$Rd),
    +              (ins imm0_31:$sat_imm, GPRnopc:$Rn, shift_imm:$sh),
                   SatFrm, NoItinerary, "usat", "\t$Rd, $sat_imm, $Rn$sh", []> {
       bits<4> Rd;
       bits<5> sat_imm;
    @@ -3081,7 +3088,8 @@
       let Inst{3-0} = Rn;
     }
     
    -def USAT16 : AI<(outs GPR:$Rd), (ins imm0_15:$sat_imm, GPR:$a), SatFrm,
    +def USAT16 : AI<(outs GPRnopc:$Rd),
    +                (ins imm0_15:$sat_imm, GPRnopc:$a), SatFrm,
                     NoItinerary, "usat16", "\t$Rd, $sat_imm, $a",
                     [/* For disassembly only; pattern left blank */]> {
       bits<4> Rd;
    @@ -3094,8 +3102,10 @@
       let Inst{3-0} = Rn;
     }
     
    -def : ARMV6Pat<(int_arm_ssat GPR:$a, imm:$pos), (SSAT imm:$pos, GPR:$a, 0)>;
    -def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USAT imm:$pos, GPR:$a, 0)>;
    +def : ARMV6Pat<(int_arm_ssat GPRnopc:$a, imm:$pos),
    +               (SSAT imm:$pos, GPRnopc:$a, 0)>;
    +def : ARMV6Pat<(int_arm_usat GPRnopc:$a, imm:$pos),
    +               (USAT imm:$pos, GPRnopc:$a, 0)>;
     
     //===----------------------------------------------------------------------===//
     //  Bitwise Instructions.
    @@ -3449,47 +3459,52 @@
     
     multiclass AI_smla {
       let DecoderMethod = "DecodeSMLAInstruction" in {
    -  def BB : AMulxyIa<0b0001000, 0b00, (outs GPR:$Rd),
    -              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    +  def BB : AMulxyIa<0b0001000, 0b00, (outs GPRnopc:$Rd),
    +              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
                   IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra",
    -              [(set GPR:$Rd, (add GPR:$Ra,
    -                               (opnode (sext_inreg GPR:$Rn, i16),
    -                                       (sext_inreg GPR:$Rm, i16))))]>,
    +              [(set GPRnopc:$Rd, (add GPR:$Ra,
    +                               (opnode (sext_inreg GPRnopc:$Rn, i16),
    +                                       (sext_inreg GPRnopc:$Rm, i16))))]>,
                Requires<[IsARM, HasV5TE]>;
     
    -  def BT : AMulxyIa<0b0001000, 0b10, (outs GPR:$Rd),
    -              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    +  def BT : AMulxyIa<0b0001000, 0b10, (outs GPRnopc:$Rd),
    +              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
                   IIC_iMAC16, !strconcat(opc, "bt"), "\t$Rd, $Rn, $Rm, $Ra",
    -              [(set GPR:$Rd, (add GPR:$Ra, (opnode (sext_inreg GPR:$Rn, i16),
    -                                                   (sra GPR:$Rm, (i32 16)))))]>,
    +              [(set GPRnopc:$Rd,
    +                    (add GPR:$Ra, (opnode (sext_inreg GPRnopc:$Rn, i16),
    +                                          (sra GPRnopc:$Rm, (i32 16)))))]>,
                Requires<[IsARM, HasV5TE]>;
     
    -  def TB : AMulxyIa<0b0001000, 0b01, (outs GPR:$Rd),
    -              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    +  def TB : AMulxyIa<0b0001000, 0b01, (outs GPRnopc:$Rd),
    +              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
                   IIC_iMAC16, !strconcat(opc, "tb"), "\t$Rd, $Rn, $Rm, $Ra",
    -              [(set GPR:$Rd, (add GPR:$Ra, (opnode (sra GPR:$Rn, (i32 16)),
    -                                                (sext_inreg GPR:$Rm, i16))))]>,
    +              [(set GPRnopc:$Rd,
    +                    (add GPR:$Ra, (opnode (sra GPRnopc:$Rn, (i32 16)),
    +                                          (sext_inreg GPRnopc:$Rm, i16))))]>,
                Requires<[IsARM, HasV5TE]>;
     
    -  def TT : AMulxyIa<0b0001000, 0b11, (outs GPR:$Rd),
    -              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    +  def TT : AMulxyIa<0b0001000, 0b11, (outs GPRnopc:$Rd),
    +              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
                   IIC_iMAC16, !strconcat(opc, "tt"), "\t$Rd, $Rn, $Rm, $Ra",
    -             [(set GPR:$Rd, (add GPR:$Ra, (opnode (sra GPR:$Rn, (i32 16)),
    -                                                   (sra GPR:$Rm, (i32 16)))))]>,
    +             [(set GPRnopc:$Rd,
    +                   (add GPR:$Ra, (opnode (sra GPRnopc:$Rn, (i32 16)),
    +                                         (sra GPRnopc:$Rm, (i32 16)))))]>,
                 Requires<[IsARM, HasV5TE]>;
     
    -  def WB : AMulxyIa<0b0001001, 0b00, (outs GPR:$Rd),
    -              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    +  def WB : AMulxyIa<0b0001001, 0b00, (outs GPRnopc:$Rd),
    +              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
                   IIC_iMAC16, !strconcat(opc, "wb"), "\t$Rd, $Rn, $Rm, $Ra",
    -              [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn,
    -                                      (sext_inreg GPR:$Rm, i16)), (i32 16))))]>,
    +              [(set GPRnopc:$Rd,
    +                    (add GPR:$Ra, (sra (opnode GPRnopc:$Rn,
    +                                  (sext_inreg GPRnopc:$Rm, i16)), (i32 16))))]>,
                Requires<[IsARM, HasV5TE]>;
     
    -  def WT : AMulxyIa<0b0001001, 0b10, (outs GPR:$Rd),
    -              (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    +  def WT : AMulxyIa<0b0001001, 0b10, (outs GPRnopc:$Rd),
    +              (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
                   IIC_iMAC16, !strconcat(opc, "wt"), "\t$Rd, $Rn, $Rm, $Ra",
    -              [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn,
    -                                        (sra GPR:$Rm, (i32 16))), (i32 16))))]>,
    +              [(set GPRnopc:$Rd,
    +                    (add GPR:$Ra, (sra (opnode GPRnopc:$Rn,
    +                                       (sra GPRnopc:$Rm, (i32 16))), (i32 16))))]>,
                 Requires<[IsARM, HasV5TE]>;
       }
     }
    @@ -3498,26 +3513,26 @@
     defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
     
     // Halfword multiply accumulate long: SMLAL -- for disassembly only
    -def SMLALBB : AMulxyI64<0b0001010, 0b00, (outs GPR:$RdLo, GPR:$RdHi),
    -                      (ins GPR:$Rn, GPR:$Rm),
    +def SMLALBB : AMulxyI64<0b0001010, 0b00, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
    +                      (ins GPRnopc:$Rn, GPRnopc:$Rm),
                           IIC_iMAC64, "smlalbb", "\t$RdLo, $RdHi, $Rn, $Rm",
                           [/* For disassembly only; pattern left blank */]>,
                   Requires<[IsARM, HasV5TE]>;
     
    -def SMLALBT : AMulxyI64<0b0001010, 0b10, (outs GPR:$RdLo, GPR:$RdHi),
    -                      (ins GPR:$Rn, GPR:$Rm),
    +def SMLALBT : AMulxyI64<0b0001010, 0b10, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
    +                      (ins GPRnopc:$Rn, GPRnopc:$Rm),
                           IIC_iMAC64, "smlalbt", "\t$RdLo, $RdHi, $Rn, $Rm",
                           [/* For disassembly only; pattern left blank */]>,
                   Requires<[IsARM, HasV5TE]>;
     
    -def SMLALTB : AMulxyI64<0b0001010, 0b01, (outs GPR:$RdLo, GPR:$RdHi),
    -                      (ins GPR:$Rn, GPR:$Rm),
    +def SMLALTB : AMulxyI64<0b0001010, 0b01, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
    +                      (ins GPRnopc:$Rn, GPRnopc:$Rm),
                           IIC_iMAC64, "smlaltb", "\t$RdLo, $RdHi, $Rn, $Rm",
                           [/* For disassembly only; pattern left blank */]>,
                   Requires<[IsARM, HasV5TE]>;
     
    -def SMLALTT : AMulxyI64<0b0001010, 0b11, (outs GPR:$RdLo, GPR:$RdHi),
    -                      (ins GPR:$Rn, GPR:$Rm),
    +def SMLALTT : AMulxyI64<0b0001010, 0b11, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
    +                      (ins GPRnopc:$Rn, GPRnopc:$Rm),
                           IIC_iMAC64, "smlaltt", "\t$RdLo, $RdHi, $Rn, $Rm",
                           [/* For disassembly only; pattern left blank */]>,
                   Requires<[IsARM, HasV5TE]>;
    @@ -3564,18 +3579,20 @@
     
     multiclass AI_smld {
     
    -  def D : AMulDualIa<0, sub, 0, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    +  def D : AMulDualIa<0, sub, 0, (outs GPRnopc:$Rd),
    +                  (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
                       NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm, $Ra">;
     
    -  def DX: AMulDualIa<0, sub, 1, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    +  def DX: AMulDualIa<0, sub, 1, (outs GPRnopc:$Rd),
    +                  (ins GPRnopc:$Rn, GPRnopc:$Rm, GPR:$Ra),
                       NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm, $Ra">;
     
    -  def LD: AMulDualI64<1, sub, 0, (outs GPR:$RdLo,GPR:$RdHi),
    -                  (ins GPR:$Rn, GPR:$Rm), NoItinerary,
    +  def LD: AMulDualI64<1, sub, 0, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
    +                  (ins GPRnopc:$Rn, GPRnopc:$Rm), NoItinerary,
                       !strconcat(opc, "ld"), "\t$RdLo, $RdHi, $Rn, $Rm">;
     
    -  def LDX : AMulDualI64<1, sub, 1, (outs GPR:$RdLo,GPR:$RdHi),
    -                  (ins GPR:$Rn, GPR:$Rm), NoItinerary,
    +  def LDX : AMulDualI64<1, sub, 1, (outs GPRnopc:$RdLo, GPRnopc:$RdHi),
    +                  (ins GPRnopc:$Rn, GPRnopc:$Rm), NoItinerary,
                       !strconcat(opc, "ldx"),"\t$RdLo, $RdHi, $Rn, $Rm">;
     
     }
    @@ -3585,9 +3602,9 @@
     
     multiclass AI_sdml {
     
    -  def D : AMulDualI<0, sub, 0, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
    +  def D : AMulDualI<0, sub, 0, (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, GPRnopc:$Rm),
                         NoItinerary, !strconcat(opc, "d"), "\t$Rd, $Rn, $Rm">;
    -  def DX : AMulDualI<0, sub, 1, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm),
    +  def DX : AMulDualI<0, sub, 1, (outs GPRnopc:$Rd), (ins GPRnopc:$Rn, GPRnopc:$Rm),
                         NoItinerary, !strconcat(opc, "dx"), "\t$Rd, $Rn, $Rm">;
     }
     
    @@ -4579,10 +4596,10 @@
     def : ARMV6Pat<(sext_inreg GPR:$Src, i8),  (SXTB GPR:$Src, 0)>;
     def : ARMV6Pat<(sext_inreg GPR:$Src, i16), (SXTH GPR:$Src, 0)>;
     
    -def : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPR:$Rm, i8)),
    -               (SXTAB GPR:$Rn, GPR:$Rm, 0)>;
    -def : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPR:$Rm, i16)),
    -               (SXTAH GPR:$Rn, GPR:$Rm, 0)>;
    +def : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPRnopc:$Rm, i8)),
    +               (SXTAB GPR:$Rn, GPRnopc:$Rm, 0)>;
    +def : ARMV6Pat<(add GPR:$Rn, (sext_inreg GPRnopc:$Rm, i16)),
    +               (SXTAH GPR:$Rn, GPRnopc:$Rm, 0)>;
     
     //===----------------------------------------------------------------------===//
     // Thumb Support
    @@ -4669,31 +4686,37 @@
     
     // SSAT/USAT optional shift operand.
     def : InstAlias<"ssat${p} $Rd, $sat_imm, $Rn",
    -                (SSAT GPR:$Rd, imm1_32:$sat_imm, GPR:$Rn, 0, pred:$p)>;
    +                (SSAT GPRnopc:$Rd, imm1_32:$sat_imm, GPRnopc:$Rn, 0, pred:$p)>;
     def : InstAlias<"usat${p} $Rd, $sat_imm, $Rn",
    -                (USAT GPR:$Rd, imm0_31:$sat_imm, GPR:$Rn, 0, pred:$p)>;
    +                (USAT GPRnopc:$Rd, imm0_31:$sat_imm, GPRnopc:$Rn, 0, pred:$p)>;
     
     
     // Extend instruction optional rotate operand.
     def : InstAlias<"sxtab${p} $Rd, $Rn, $Rm",
    -                (SXTAB GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
    +                (SXTAB GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
     def : InstAlias<"sxtah${p} $Rd, $Rn, $Rm",
    -                (SXTAH GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
    +                (SXTAH GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
     def : InstAlias<"sxtab16${p} $Rd, $Rn, $Rm",
    -                (SXTAB16 GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
    -def : InstAlias<"sxtb${p} $Rd, $Rm", (SXTB GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
    -def : InstAlias<"sxtb16${p} $Rd, $Rm", (SXTB16 GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
    -def : InstAlias<"sxth${p} $Rd, $Rm", (SXTH GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
    +                (SXTAB16 GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
    +def : InstAlias<"sxtb${p} $Rd, $Rm",
    +                (SXTB GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
    +def : InstAlias<"sxtb16${p} $Rd, $Rm",
    +                (SXTB16 GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
    +def : InstAlias<"sxth${p} $Rd, $Rm",
    +                (SXTH GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
     
     def : InstAlias<"uxtab${p} $Rd, $Rn, $Rm",
    -                (UXTAB GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
    +                (UXTAB GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
     def : InstAlias<"uxtah${p} $Rd, $Rn, $Rm",
    -                (UXTAH GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
    +                (UXTAH GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
     def : InstAlias<"uxtab16${p} $Rd, $Rn, $Rm",
    -                (UXTAB16 GPR:$Rd, GPR:$Rn, GPR:$Rm, 0, pred:$p)>;
    -def : InstAlias<"uxtb${p} $Rd, $Rm", (UXTB GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
    -def : InstAlias<"uxtb16${p} $Rd, $Rm", (UXTB16 GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
    -def : InstAlias<"uxth${p} $Rd, $Rm", (UXTH GPR:$Rd, GPR:$Rm, 0, pred:$p)>;
    +                (UXTAB16 GPRnopc:$Rd, GPR:$Rn, GPRnopc:$Rm, 0, pred:$p)>;
    +def : InstAlias<"uxtb${p} $Rd, $Rm",
    +                (UXTB GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
    +def : InstAlias<"uxtb16${p} $Rd, $Rm",
    +                (UXTB16 GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
    +def : InstAlias<"uxth${p} $Rd, $Rm",
    +                (UXTH GPRnopc:$Rd, GPRnopc:$Rm, 0, pred:$p)>;
     
     
     // RFE aliases
    
    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=137189&r1=137188&r2=137189&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
    +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug  9 19:03:03 2011
    @@ -1177,10 +1177,10 @@
       if (pred == 0xF)
         return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
     
    -  DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
    -  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    -  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    -  DecodeGPRRegisterClass(Inst, Ra, Address, Decoder);
    +  DecodeGPRnopcRegisterClass(Inst, Rd, Address, Decoder);
    +  DecodeGPRnopcRegisterClass(Inst, Rn, Address, Decoder);
    +  DecodeGPRnopcRegisterClass(Inst, Rm, Address, Decoder);
    +  DecodeGPRnopcRegisterClass(Inst, Ra, Address, Decoder);
     
       return true;
     }
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt?rev=137189&r1=137188&r2=137189&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt Tue Aug  9 19:03:03 2011
    @@ -1,11 +1,10 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=185 Name=MOVTi16 Format=ARM_FORMAT_DPFRM(4)
    -#  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 
    +#  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: 0: 1: 1| 0: 1: 0: 0| 0: 0: 0: 1| 1: 1: 1: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 0: 0|
     # -------------------------------------------------------------------------------------------------
    -# 
    +#
     # if d == 15 then UNPREDICTABLE
     0x00 0xf0 0x41 0xe3
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt?rev=137189&r1=137188&r2=137189&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt Tue Aug  9 19:03:03 2011
    @@ -1,8 +1,7 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=271 Name=SBFX Format=ARM_FORMAT_DPFRM(4)
    -#  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 
    +#  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: 0| 0: 1: 1: 1| 0: 1: 0: 1| 0: 1: 0: 0| 0: 1: 0: 1| 1: 1: 1: 1|
     # -------------------------------------------------------------------------------------------------
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt?rev=137189&r1=137188&r2=137189&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt Tue Aug  9 19:03:03 2011
    @@ -1,8 +1,7 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=284 Name=SMLAD Format=ARM_FORMAT_MULFRM(1)
    -#  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 
    +#  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: 0: 0: 1| 0: 1: 1: 1| 0: 0: 0: 0| 1: 1: 1: 1| 0: 1: 1: 0| 1: 0: 0: 0| 0: 0: 0: 1| 1: 0: 1: 1|
     # -------------------------------------------------------------------------------------------------
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt?rev=137189&r1=137188&r2=137189&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt Tue Aug  9 19:03:03 2011
    @@ -1,8 +1,7 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=322 Name=SSAT Format=ARM_FORMAT_SATFRM(13)
    -#  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 
    +#  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: 0: 1: 0| 0: 0: 0: 0| 1: 1: 1: 1| 0: 1: 0: 0| 0: 0: 0: 1| 1: 0: 1: 0|
     # -------------------------------------------------------------------------------------------------
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt?rev=137189&r1=137188&r2=137189&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt Tue Aug  9 19:03:03 2011
    @@ -1,8 +1,7 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=390 Name=SXTBr_rot Format=ARM_FORMAT_EXTFRM(14)
    -#  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 
    +#  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: 0: 1: 0| 1: 1: 1: 1| 1: 1: 1: 1| 0: 1: 0: 0| 0: 1: 1: 1| 0: 1: 0: 1|
     # -------------------------------------------------------------------------------------------------
    
    Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt?rev=137189&r1=137188&r2=137189&view=diff
    ==============================================================================
    --- llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt (original)
    +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt Tue Aug  9 19:03:03 2011
    @@ -1,12 +1,11 @@
     # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    -# XFAIL: *
     
     # Opcode=426 Name=UQADD8 Format=ARM_FORMAT_DPFRM(4)
    -#  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 
    +#  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| 0: 1: 1: 0| 0: 1: 1: 0| 0: 1: 0: 1| 1: 1: 1: 1| 1: 0: 0: 1| 1: 1: 1: 1|
     # -------------------------------------------------------------------------------------------------
    -# 
    +#
     # DPFrm with bad reg specifier(s)
     #
     # if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
    
    
    
    From stoklund at 2pi.dk  Tue Aug  9 19:11:35 2011
    From: stoklund at 2pi.dk (Jakob Stoklund Olesen)
    Date: Tue, 09 Aug 2011 17:11:35 -0700
    Subject: [llvm-commits] [llvm] r137189 - in /llvm/trunk:
     lib/Target/ARM/ARMInstrInfo.td
     lib/Target/ARM/Disassembler/ARMDisassembler.cpp
     test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
     test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
     test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
     test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
     test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
     test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
    In-Reply-To: <20110810000303.6E4D02A6C12C@llvm.org>
    References: <20110810000303.6E4D02A6C12C@llvm.org>
    Message-ID: <77C2EA3E-FE39-4C86-B4ED-AF7BEFBEEFA9@2pi.dk>
    
    
    On Aug 9, 2011, at 5:03 PM, Owen Anderson wrote:
    
    > Author: resistor
    > Date: Tue Aug  9 19:03:03 2011
    > New Revision: 137189
    > 
    > URL: http://llvm.org/viewvc/llvm-project?rev=137189&view=rev
    > Log:
    > Push GPRnopc through a large number of instruction definitions to tighten operand decoding.
    
    This is awesome.
    
    Note that we also sometimes use rGPR where we should have used GPRnopc. For example, T2I_bin_ii12rs.
    
    /jakob
    
    
    From atrick at apple.com  Tue Aug  9 19:28:10 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Wed, 10 Aug 2011 00:28:10 -0000
    Subject: [llvm-commits] [llvm] r137190 - in /llvm/trunk:
     include/llvm/Analysis/LoopInfo.h lib/Transforms/Utils/LoopUnroll.cpp
     test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
     test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    Message-ID: <20110810002810.AF3BF2A6C12C@llvm.org>
    
    Author: atrick
    Date: Tue Aug  9 19:28:10 2011
    New Revision: 137190
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137190&view=rev
    Log:
    Fix the LoopUnroller to handle nontrivial loops and partial unrolling.
    
    These are not individual bug fixes. I had to rewrite a good chunk of
    the unroller to make it sane. I think it was getting lucky on trivial
    completely unrolled loops with no early exits. I included some fairly
    simple unit tests for partial unrolling. I didn't do much stress
    testing, so it may not be perfect, but should be usable now.
    
    Added:
        llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
        llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    Modified:
        llvm/trunk/include/llvm/Analysis/LoopInfo.h
        llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    
    Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopInfo.h?rev=137190&r1=137189&r2=137190&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Analysis/LoopInfo.h (original)
    +++ llvm/trunk/include/llvm/Analysis/LoopInfo.h Tue Aug  9 19:28:10 2011
    @@ -134,6 +134,11 @@
       block_iterator block_begin() const { return Blocks.begin(); }
       block_iterator block_end() const { return Blocks.end(); }
     
    +  /// getNumBlocks - Get the number of blocks in this loop.
    +  unsigned getNumBlocks() const {
    +    return std::distance(block_begin(), block_end());
    +  }
    +
       /// isLoopExiting - True if terminator in the block can branch to another
       /// block that is outside of the current loop.
       ///
    
    Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=137190&r1=137189&r2=137190&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
    +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Tue Aug  9 19:28:10 2011
    @@ -21,6 +21,7 @@
     #include "llvm/BasicBlock.h"
     #include "llvm/ADT/Statistic.h"
     #include "llvm/Analysis/InstructionSimplify.h"
    +#include "llvm/Analysis/LoopIterator.h"
     #include "llvm/Analysis/LoopPass.h"
     #include "llvm/Analysis/ScalarEvolution.h"
     #include "llvm/Support/Debug.h"
    @@ -225,11 +226,25 @@
       Headers.push_back(Header);
       Latches.push_back(LatchBlock);
     
    +  // The current on-the-fly SSA update requires blocks to be processed in
    +  // reverse postorder so that LastValueMap contains the correct value at each
    +  // exit.
    +  LoopBlocksDFS DFS(L);
    +  {
    +    // Traverse the loop blocks using depth-first search to record RPO numbers
    +    // for each block in the DFS result.
    +    LoopBlocksTraversal Traversal(DFS, LI);
    +    for (LoopBlocksTraversal::POTIterator POI = Traversal.begin(),
    +           POE = Traversal.end(); POI != POE; ++POI);
    +  }
    +  // Stash the DFS iterators before adding blocks to the loop.
    +  LoopBlocksDFS::RPOIterator BlockBegin = DFS.beginRPO();
    +  LoopBlocksDFS::RPOIterator BlockEnd = DFS.endRPO();
    +
       for (unsigned It = 1; It != Count; ++It) {
         std::vector NewBlocks;
     
    -    for (std::vector::iterator BB = LoopBlocks.begin(),
    -         E = LoopBlocks.end(); BB != E; ++BB) {
    +    for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) {
           ValueToValueMapTy VMap;
           BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It));
           Header->getParent()->getBasicBlockList().push_back(New);
    @@ -255,35 +270,27 @@
     
           L->addBasicBlockToLoop(New, LI->getBase());
     
    -      // Add phi entries for newly created values to all exit blocks except
    -      // the successor of the latch block.  The successor of the exit block will
    -      // be updated specially after unrolling all the way.
    -      if (*BB != LatchBlock)
    -        for (succ_iterator SI = succ_begin(*BB), SE = succ_end(*BB); SI != SE;
    -             ++SI)
    -          if (!L->contains(*SI))
    -            for (BasicBlock::iterator BBI = (*SI)->begin();
    -                 PHINode *phi = dyn_cast(BBI); ++BBI) {
    -              Value *Incoming = phi->getIncomingValueForBlock(*BB);
    -              phi->addIncoming(Incoming, New);
    -            }
    -
    +      // Add phi entries for newly created values to all exit blocks.
    +      for (succ_iterator SI = succ_begin(*BB), SE = succ_end(*BB);
    +           SI != SE; ++SI) {
    +        if (L->contains(*SI))
    +          continue;
    +        for (BasicBlock::iterator BBI = (*SI)->begin();
    +             PHINode *phi = dyn_cast(BBI); ++BBI) {
    +          Value *Incoming = phi->getIncomingValueForBlock(*BB);
    +          ValueToValueMapTy::iterator It = LastValueMap.find(Incoming);
    +          if (It != LastValueMap.end())
    +            Incoming = It->second;
    +          phi->addIncoming(Incoming, New);
    +        }
    +      }
           // Keep track of new headers and latches as we create them, so that
           // we can insert the proper branches later.
           if (*BB == Header)
             Headers.push_back(New);
    -      if (*BB == LatchBlock) {
    +      if (*BB == LatchBlock)
             Latches.push_back(New);
     
    -        // Also, clear out the new latch's back edge so that it doesn't look
    -        // like a new loop, so that it's amenable to being merged with adjacent
    -        // blocks later on.
    -        TerminatorInst *Term = New->getTerminator();
    -        assert(L->contains(Term->getSuccessor(!ContinueOnTrue)));
    -        assert(Term->getSuccessor(ContinueOnTrue) == LoopExit);
    -        Term->setSuccessor(!ContinueOnTrue, NULL);
    -      }
    -
           NewBlocks.push_back(New);
         }
     
    @@ -294,36 +301,24 @@
             ::RemapInstruction(I, LastValueMap);
       }
     
    -  // The latch block exits the loop.  If there are any PHI nodes in the
    -  // successor blocks, update them to use the appropriate values computed as the
    -  // last iteration of the loop.
    -  if (Count != 1) {
    -    BasicBlock *LastIterationBB = cast(LastValueMap[LatchBlock]);
    -    for (succ_iterator SI = succ_begin(LatchBlock), SE = succ_end(LatchBlock);
    -         SI != SE; ++SI) {
    -      for (BasicBlock::iterator BBI = (*SI)->begin();
    -           PHINode *PN = dyn_cast(BBI); ++BBI) {
    -        Value *InVal = PN->removeIncomingValue(LatchBlock, false);
    -        // If this value was defined in the loop, take the value defined by the
    -        // last iteration of the loop.
    -        if (Instruction *InValI = dyn_cast(InVal)) {
    -          if (L->contains(InValI))
    -            InVal = LastValueMap[InVal];
    -        }
    -        PN->addIncoming(InVal, LastIterationBB);
    -      }
    -    }
    -  }
    -
    -  // Now, if we're doing complete unrolling, loop over the PHI nodes in the
    -  // original block, setting them to their incoming values.
    -  if (CompletelyUnroll) {
    -    BasicBlock *Preheader = L->getLoopPreheader();
    -    for (unsigned i = 0, e = OrigPHINode.size(); i != e; ++i) {
    -      PHINode *PN = OrigPHINode[i];
    +  // Loop over the PHI nodes in the original block, setting incoming values.
    +  for (unsigned i = 0, e = OrigPHINode.size(); i != e; ++i) {
    +    PHINode *PN = OrigPHINode[i];
    +    if (CompletelyUnroll) {
           PN->replaceAllUsesWith(PN->getIncomingValueForBlock(Preheader));
           Header->getInstList().erase(PN);
         }
    +    else if (Count > 1) {
    +      Value *InVal = PN->removeIncomingValue(LatchBlock, false);
    +      // If this value was defined in the loop, take the value defined by the
    +      // last iteration of the loop.
    +      if (Instruction *InValI = dyn_cast(InVal)) {
    +        if (L->contains(InValI))
    +          InVal = LastValueMap[InVal];
    +      }
    +      assert(Latches.back() == LastValueMap[LatchBlock] && "bad last latch");
    +      PN->addIncoming(InVal, Latches.back());
    +    }
       }
     
       // Now that all the basic blocks for the unrolled iterations are in place,
    @@ -355,6 +350,19 @@
           // iteration.
           Term->setSuccessor(!ContinueOnTrue, Dest);
         } else {
    +      // Remove phi operands at this loop exit
    +      if (Dest != LoopExit) {
    +        BasicBlock *BB = Latches[i];
    +        for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB);
    +             SI != SE; ++SI) {
    +          if (*SI == Headers[i])
    +            continue;
    +          for (BasicBlock::iterator BBI = (*SI)->begin();
    +               PHINode *Phi = dyn_cast(BBI); ++BBI) {
    +            Phi->removeIncomingValue(BB, false);
    +          }
    +        }
    +      }
           // Replace the conditional branch with an unconditional one.
           BranchInst::Create(Dest, Term);
           Term->eraseFromParent();
    
    Added: llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll?rev=137190&view=auto
    ==============================================================================
    --- llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll (added)
    +++ llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll Tue Aug  9 19:28:10 2011
    @@ -0,0 +1,100 @@
    +; RUN: opt < %s -loop-unroll -S -unroll-count=4 | FileCheck %s
    +; Test phi update after partial unroll.
    +
    +declare i1 @check() nounwind
    +
    +; CHECK: @test
    +; CHECK: if.else:
    +; CHECK: if.then.loopexit
    +; CHECK: %sub5.lcssa = phi i32 [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ]
    +; CHECK: if.else.3
    +define void @test1(i32 %i, i32 %j) nounwind uwtable ssp {
    +entry:
    +  %cond1 = call zeroext i1 @check()
    +  br i1 %cond1, label %if.then, label %if.else.lr.ph
    +
    +if.else.lr.ph:                                    ; preds = %entry
    +  br label %if.else
    +
    +if.else:                                          ; preds = %if.else, %if.else.lr.ph
    +  %sub = phi i32 [ %i, %if.else.lr.ph ], [ %sub5, %if.else ]
    +  %sub5 = sub i32 %sub, %j
    +  %cond2 = call zeroext i1 @check()
    +  br i1 %cond2, label %if.then, label %if.else
    +
    +if.then:                                          ; preds = %if.else, %entry
    +  %i.tr = phi i32 [ %i, %entry ], [ %sub5, %if.else ]
    +  ret void
    +
    +}
    +
    +; PR7318: assertion failure after doing a simple loop unroll
    +;
    +; CHECK: @test2
    +; CHECK: bb1.bb2_crit_edge:
    +; CHECK: %.lcssa = phi i32 [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ]
    +; CHECK: bb1.3:
    +define i32 @test2(i32* nocapture %p, i32 %n) nounwind readonly {
    +entry:
    +  %0 = icmp sgt i32 %n, 0                         ;  [#uses=1]
    +  br i1 %0, label %bb.nph, label %bb2
    +
    +bb.nph:                                           ; preds = %entry
    +  %tmp = zext i32 %n to i64                       ;  [#uses=1]
    +  br label %bb
    +
    +bb:                                               ; preds = %bb.nph, %bb1
    +  %indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ;  [#uses=2]
    +  %s.01 = phi i32 [ 0, %bb.nph ], [ %2, %bb1 ]    ;  [#uses=1]
    +  %scevgep = getelementptr i32* %p, i64 %indvar   ;  [#uses=1]
    +  %1 = load i32* %scevgep, align 1                ;  [#uses=1]
    +  %2 = add nsw i32 %1, %s.01                      ;  [#uses=2]
    +  br label %bb1
    +
    +bb1:                                              ; preds = %bb
    +  %indvar.next = add i64 %indvar, 1               ;  [#uses=2]
    +  %exitcond = icmp ne i64 %indvar.next, %tmp      ;  [#uses=1]
    +  br i1 %exitcond, label %bb, label %bb1.bb2_crit_edge
    +
    +bb1.bb2_crit_edge:                                ; preds = %bb1
    +  %.lcssa = phi i32 [ %2, %bb1 ]                  ;  [#uses=1]
    +  br label %bb2
    +
    +bb2:                                              ; preds = %bb1.bb2_crit_edge, %entry
    +  %s.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ 0, %entry ] ;  [#uses=1]
    +  ret i32 %s.0.lcssa
    +}
    +
    +; Check phi update for loop with an early-exit.
    +;
    +; CHECK: @test3
    +; CHECK: return.loopexit:
    +; CHECK: %tmp7.i.lcssa = phi i32 [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ]
    +; CHECK: exit.3:
    +define i32 @test3() nounwind uwtable ssp align 2 {
    +entry:
    +  br i1 undef, label %return, label %if.end
    +
    +if.end:                                           ; preds = %entry
    +  br label %do.body
    +
    +do.body:                                          ; preds = %do.cond, %if.end
    +  br i1 undef, label %exit, label %do.cond
    +
    +exit:                  ; preds = %do.body
    +  %tmp7.i = load i32* undef, align 8
    +  br i1 undef, label %do.cond, label %land.lhs.true
    +
    +land.lhs.true:                                    ; preds = %exit
    +  br i1 undef, label %return, label %do.cond
    +
    +do.cond:                                          ; preds = %land.lhs.true, %exit, %do.body
    +  br i1 undef, label %do.end, label %do.body
    +
    +do.end:                                           ; preds = %do.cond
    +  br label %return
    +
    +return:                                           ; preds = %do.end, %land.lhs.true, %entry
    +  %retval.0 = phi i32 [ 0, %do.end ], [ 0, %entry ], [ %tmp7.i, %land.lhs.true ]
    +  ret i32 %retval.0
    +}
    
    Added: llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll?rev=137190&view=auto
    ==============================================================================
    --- llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll (added)
    +++ llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll Tue Aug  9 19:28:10 2011
    @@ -0,0 +1,62 @@
    +; RUN: opt -S < %s -instcombine -inline -jump-threading -loop-unroll -unroll-count=4 | FileCheck %s
    +;
    +; This is a test case that required a number of setup passes because
    +; it depends on block order.
    +
    +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
    +target triple = "x86_64-apple-macosx10.6.8"
    +
    +declare i1 @check() nounwind
    +declare i32 @getval() nounwind
    +
    +; Check that the loop exit merges values from all the iterations. This
    +; could be a tad fragile, but it's a good test.
    +;
    +; CHECK: @foo
    +; CHECK: return:
    +; CHECK: %retval.0 = phi i32 [ %tmp7.i, %land.lhs.true ], [ 0, %do.cond ], [ %tmp7.i.1, %land.lhs.true.1 ], [ 0, %do.cond.1 ], [ %tmp7.i.2, %land.lhs.true.2 ], [ 0, %do.cond.2 ], [ %tmp7.i.3, %land.lhs.true.3 ], [ 0, %do.cond.3 ]
    +; CHECK-NOT: @bar
    +; CHECK: bar.exit.3
    +define i32 @foo() uwtable ssp align 2 {
    +entry:
    +  br i1 undef, label %return, label %if.end
    +
    +if.end:                                           ; preds = %entry
    +  %call2 = call i32 @getval()
    +  br label %do.body
    +
    +do.body:                                          ; preds = %do.cond, %if.end
    +  %call6 = call i32 @bar()
    +  %cmp = icmp ne i32 %call6, 0
    +  br i1 %cmp, label %land.lhs.true, label %do.cond
    +
    +land.lhs.true:                                    ; preds = %do.body
    +  %call10 = call i32 @getval()
    +  %cmp11 = icmp eq i32 0, %call10
    +  br i1 %cmp11, label %return, label %do.cond
    +
    +do.cond:                                          ; preds = %land.lhs.true, %do.body
    +  %cmp18 = icmp sle i32 0, %call2
    +  br i1 %cmp18, label %do.body, label %return
    +
    +return:                                           ; preds = %do.cond, %land.lhs.true, %entry
    +  %retval.0 = phi i32 [ 0, %entry ], [ %call6, %land.lhs.true ], [ 0, %do.cond ]
    +  ret i32 %retval.0
    +}
    +
    +define linkonce_odr i32 @bar() nounwind uwtable ssp align 2 {
    +entry:
    +  br i1 undef, label %land.lhs.true, label %cond.end
    +
    +land.lhs.true:                                    ; preds = %entry
    +  %cmp4 = call zeroext i1 @check()
    +  br i1 %cmp4, label %cond.true, label %cond.end
    +
    +cond.true:                                        ; preds = %land.lhs.true
    +  %tmp7 = call i32 @getval()
    +  br label %cond.end
    +
    +cond.end:                                         ; preds = %cond.true, %land.lhs.true, %entry
    +  %cond = phi i32 [ %tmp7, %cond.true ], [ 0, %land.lhs.true ], [ 0, %entry ]
    +  ret i32 %cond
    +}
    
    
    
    From clattner at apple.com  Tue Aug  9 19:36:12 2011
    From: clattner at apple.com (Chris Lattner)
    Date: Tue, 09 Aug 2011 17:36:12 -0700
    Subject: [llvm-commits] [llvm] r137111 -
     /llvm/trunk/lib/Support/Unix/Host.inc
    In-Reply-To: <6FB8361D-F840-41E4-A578-73319167473A@apple.com>
    References: <20110809051336.C09ED2A6C12C@llvm.org>
    	<0624A676-9485-4208-8EAC-F836B4795A39@apple.com>
    	<6FB8361D-F840-41E4-A578-73319167473A@apple.com>
    Message-ID: <0B8B0E12-8CCF-4C19-8CAB-933AD550D4B5@apple.com>
    
    
    On Aug 9, 2011, at 12:35 PM, Bob Wilson wrote:
    
    >>> Recognize the UNAME_RELEASE environment variable to match Darwin's uname.
    >>> When this variable is set, "uname -r" will return its value instead of the
    >>> real OS version.  Make this affect LLVM's triple for consistency.
    >>> 
    >> 
    >> Hi Bob,
    >> 
    >> Should this be #ifdef __APPLE__ or something?
    >> 
    >> -Chris
    > 
    > I thought about that but decided that since no one else is likely to set UNAME_RELEASE that it wasn't necessary.  I'll take your question as a hint that you would prefer it with the #ifdef.
    
    Yep, calling getenv isn't free.  Only those who get the benefit should pay the cost.
    
    -Chris
    
    From eli.friedman at gmail.com  Tue Aug  9 19:36:49 2011
    From: eli.friedman at gmail.com (Eli Friedman)
    Date: Tue, 9 Aug 2011 17:36:49 -0700
    Subject: [llvm-commits] [llvm] r137190 - in /llvm/trunk:
     include/llvm/Analysis/LoopInfo.h lib/Transforms/Utils/LoopUnroll.cpp
     test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
     test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    In-Reply-To: <20110810002810.AF3BF2A6C12C@llvm.org>
    References: <20110810002810.AF3BF2A6C12C@llvm.org>
    Message-ID: 
    
    On Tue, Aug 9, 2011 at 5:28 PM, Andrew Trick  wrote:
    > Author: atrick
    > Date: Tue Aug ?9 19:28:10 2011
    > New Revision: 137190
    >
    > URL: http://llvm.org/viewvc/llvm-project?rev=137190&view=rev
    > Log:
    > Fix the LoopUnroller to handle nontrivial loops and partial unrolling.
    >
    > These are not individual bug fixes. I had to rewrite a good chunk of
    > the unroller to make it sane. I think it was getting lucky on trivial
    > completely unrolled loops with no early exits. I included some fairly
    > simple unit tests for partial unrolling. I didn't do much stress
    > testing, so it may not be perfect, but should be usable now.
    >
    > Added:
    > ? ?llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
    > ? ?llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    > Modified:
    > ? ?llvm/trunk/include/llvm/Analysis/LoopInfo.h
    > ? ?llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    >
    > Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopInfo.h?rev=137190&r1=137189&r2=137190&view=diff
    > ==============================================================================
    > --- llvm/trunk/include/llvm/Analysis/LoopInfo.h (original)
    > +++ llvm/trunk/include/llvm/Analysis/LoopInfo.h Tue Aug ?9 19:28:10 2011
    > @@ -134,6 +134,11 @@
    > ? block_iterator block_begin() const { return Blocks.begin(); }
    > ? block_iterator block_end() const { return Blocks.end(); }
    >
    > + ?/// getNumBlocks - Get the number of blocks in this loop.
    > + ?unsigned getNumBlocks() const {
    > + ? ?return std::distance(block_begin(), block_end());
    > + ?}
    
    I do not think this is a good idea; any user that cares can write the
    expression with std::distance, and having an accessor gives the
    illusion that it's constant time.
    
    -Eli
    
    > ? /// isLoopExiting - True if terminator in the block can branch to another
    > ? /// block that is outside of the current loop.
    > ? ///
    >
    > Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=137190&r1=137189&r2=137190&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
    > +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Tue Aug ?9 19:28:10 2011
    > @@ -21,6 +21,7 @@
    > ?#include "llvm/BasicBlock.h"
    > ?#include "llvm/ADT/Statistic.h"
    > ?#include "llvm/Analysis/InstructionSimplify.h"
    > +#include "llvm/Analysis/LoopIterator.h"
    > ?#include "llvm/Analysis/LoopPass.h"
    > ?#include "llvm/Analysis/ScalarEvolution.h"
    > ?#include "llvm/Support/Debug.h"
    > @@ -225,11 +226,25 @@
    > ? Headers.push_back(Header);
    > ? Latches.push_back(LatchBlock);
    >
    > + ?// The current on-the-fly SSA update requires blocks to be processed in
    > + ?// reverse postorder so that LastValueMap contains the correct value at each
    > + ?// exit.
    > + ?LoopBlocksDFS DFS(L);
    > + ?{
    > + ? ?// Traverse the loop blocks using depth-first search to record RPO numbers
    > + ? ?// for each block in the DFS result.
    > + ? ?LoopBlocksTraversal Traversal(DFS, LI);
    > + ? ?for (LoopBlocksTraversal::POTIterator POI = Traversal.begin(),
    > + ? ? ? ? ? POE = Traversal.end(); POI != POE; ++POI);
    > + ?}
    > + ?// Stash the DFS iterators before adding blocks to the loop.
    > + ?LoopBlocksDFS::RPOIterator BlockBegin = DFS.beginRPO();
    > + ?LoopBlocksDFS::RPOIterator BlockEnd = DFS.endRPO();
    > +
    > ? for (unsigned It = 1; It != Count; ++It) {
    > ? ? std::vector NewBlocks;
    >
    > - ? ?for (std::vector::iterator BB = LoopBlocks.begin(),
    > - ? ? ? ? E = LoopBlocks.end(); BB != E; ++BB) {
    > + ? ?for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) {
    > ? ? ? ValueToValueMapTy VMap;
    > ? ? ? BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It));
    > ? ? ? Header->getParent()->getBasicBlockList().push_back(New);
    > @@ -255,35 +270,27 @@
    >
    > ? ? ? L->addBasicBlockToLoop(New, LI->getBase());
    >
    > - ? ? ?// Add phi entries for newly created values to all exit blocks except
    > - ? ? ?// the successor of the latch block. ?The successor of the exit block will
    > - ? ? ?// be updated specially after unrolling all the way.
    > - ? ? ?if (*BB != LatchBlock)
    > - ? ? ? ?for (succ_iterator SI = succ_begin(*BB), SE = succ_end(*BB); SI != SE;
    > - ? ? ? ? ? ? ++SI)
    > - ? ? ? ? ?if (!L->contains(*SI))
    > - ? ? ? ? ? ?for (BasicBlock::iterator BBI = (*SI)->begin();
    > - ? ? ? ? ? ? ? ? PHINode *phi = dyn_cast(BBI); ++BBI) {
    > - ? ? ? ? ? ? ?Value *Incoming = phi->getIncomingValueForBlock(*BB);
    > - ? ? ? ? ? ? ?phi->addIncoming(Incoming, New);
    > - ? ? ? ? ? ?}
    > -
    > + ? ? ?// Add phi entries for newly created values to all exit blocks.
    > + ? ? ?for (succ_iterator SI = succ_begin(*BB), SE = succ_end(*BB);
    > + ? ? ? ? ? SI != SE; ++SI) {
    > + ? ? ? ?if (L->contains(*SI))
    > + ? ? ? ? ?continue;
    > + ? ? ? ?for (BasicBlock::iterator BBI = (*SI)->begin();
    > + ? ? ? ? ? ? PHINode *phi = dyn_cast(BBI); ++BBI) {
    > + ? ? ? ? ?Value *Incoming = phi->getIncomingValueForBlock(*BB);
    > + ? ? ? ? ?ValueToValueMapTy::iterator It = LastValueMap.find(Incoming);
    > + ? ? ? ? ?if (It != LastValueMap.end())
    > + ? ? ? ? ? ?Incoming = It->second;
    > + ? ? ? ? ?phi->addIncoming(Incoming, New);
    > + ? ? ? ?}
    > + ? ? ?}
    > ? ? ? // Keep track of new headers and latches as we create them, so that
    > ? ? ? // we can insert the proper branches later.
    > ? ? ? if (*BB == Header)
    > ? ? ? ? Headers.push_back(New);
    > - ? ? ?if (*BB == LatchBlock) {
    > + ? ? ?if (*BB == LatchBlock)
    > ? ? ? ? Latches.push_back(New);
    >
    > - ? ? ? ?// Also, clear out the new latch's back edge so that it doesn't look
    > - ? ? ? ?// like a new loop, so that it's amenable to being merged with adjacent
    > - ? ? ? ?// blocks later on.
    > - ? ? ? ?TerminatorInst *Term = New->getTerminator();
    > - ? ? ? ?assert(L->contains(Term->getSuccessor(!ContinueOnTrue)));
    > - ? ? ? ?assert(Term->getSuccessor(ContinueOnTrue) == LoopExit);
    > - ? ? ? ?Term->setSuccessor(!ContinueOnTrue, NULL);
    > - ? ? ?}
    > -
    > ? ? ? NewBlocks.push_back(New);
    > ? ? }
    >
    > @@ -294,36 +301,24 @@
    > ? ? ? ? ::RemapInstruction(I, LastValueMap);
    > ? }
    >
    > - ?// The latch block exits the loop. ?If there are any PHI nodes in the
    > - ?// successor blocks, update them to use the appropriate values computed as the
    > - ?// last iteration of the loop.
    > - ?if (Count != 1) {
    > - ? ?BasicBlock *LastIterationBB = cast(LastValueMap[LatchBlock]);
    > - ? ?for (succ_iterator SI = succ_begin(LatchBlock), SE = succ_end(LatchBlock);
    > - ? ? ? ? SI != SE; ++SI) {
    > - ? ? ?for (BasicBlock::iterator BBI = (*SI)->begin();
    > - ? ? ? ? ? PHINode *PN = dyn_cast(BBI); ++BBI) {
    > - ? ? ? ?Value *InVal = PN->removeIncomingValue(LatchBlock, false);
    > - ? ? ? ?// If this value was defined in the loop, take the value defined by the
    > - ? ? ? ?// last iteration of the loop.
    > - ? ? ? ?if (Instruction *InValI = dyn_cast(InVal)) {
    > - ? ? ? ? ?if (L->contains(InValI))
    > - ? ? ? ? ? ?InVal = LastValueMap[InVal];
    > - ? ? ? ?}
    > - ? ? ? ?PN->addIncoming(InVal, LastIterationBB);
    > - ? ? ?}
    > - ? ?}
    > - ?}
    > -
    > - ?// Now, if we're doing complete unrolling, loop over the PHI nodes in the
    > - ?// original block, setting them to their incoming values.
    > - ?if (CompletelyUnroll) {
    > - ? ?BasicBlock *Preheader = L->getLoopPreheader();
    > - ? ?for (unsigned i = 0, e = OrigPHINode.size(); i != e; ++i) {
    > - ? ? ?PHINode *PN = OrigPHINode[i];
    > + ?// Loop over the PHI nodes in the original block, setting incoming values.
    > + ?for (unsigned i = 0, e = OrigPHINode.size(); i != e; ++i) {
    > + ? ?PHINode *PN = OrigPHINode[i];
    > + ? ?if (CompletelyUnroll) {
    > ? ? ? PN->replaceAllUsesWith(PN->getIncomingValueForBlock(Preheader));
    > ? ? ? Header->getInstList().erase(PN);
    > ? ? }
    > + ? ?else if (Count > 1) {
    > + ? ? ?Value *InVal = PN->removeIncomingValue(LatchBlock, false);
    > + ? ? ?// If this value was defined in the loop, take the value defined by the
    > + ? ? ?// last iteration of the loop.
    > + ? ? ?if (Instruction *InValI = dyn_cast(InVal)) {
    > + ? ? ? ?if (L->contains(InValI))
    > + ? ? ? ? ?InVal = LastValueMap[InVal];
    > + ? ? ?}
    > + ? ? ?assert(Latches.back() == LastValueMap[LatchBlock] && "bad last latch");
    > + ? ? ?PN->addIncoming(InVal, Latches.back());
    > + ? ?}
    > ? }
    >
    > ? // Now that all the basic blocks for the unrolled iterations are in place,
    > @@ -355,6 +350,19 @@
    > ? ? ? // iteration.
    > ? ? ? Term->setSuccessor(!ContinueOnTrue, Dest);
    > ? ? } else {
    > + ? ? ?// Remove phi operands at this loop exit
    > + ? ? ?if (Dest != LoopExit) {
    > + ? ? ? ?BasicBlock *BB = Latches[i];
    > + ? ? ? ?for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB);
    > + ? ? ? ? ? ? SI != SE; ++SI) {
    > + ? ? ? ? ?if (*SI == Headers[i])
    > + ? ? ? ? ? ?continue;
    > + ? ? ? ? ?for (BasicBlock::iterator BBI = (*SI)->begin();
    > + ? ? ? ? ? ? ? PHINode *Phi = dyn_cast(BBI); ++BBI) {
    > + ? ? ? ? ? ?Phi->removeIncomingValue(BB, false);
    > + ? ? ? ? ?}
    > + ? ? ? ?}
    > + ? ? ?}
    > ? ? ? // Replace the conditional branch with an unconditional one.
    > ? ? ? BranchInst::Create(Dest, Term);
    > ? ? ? Term->eraseFromParent();
    >
    > Added: llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll?rev=137190&view=auto
    > ==============================================================================
    > --- llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll (added)
    > +++ llvm/trunk/test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll Tue Aug ?9 19:28:10 2011
    > @@ -0,0 +1,100 @@
    > +; RUN: opt < %s -loop-unroll -S -unroll-count=4 | FileCheck %s
    > +; Test phi update after partial unroll.
    > +
    > +declare i1 @check() nounwind
    > +
    > +; CHECK: @test
    > +; CHECK: if.else:
    > +; CHECK: if.then.loopexit
    > +; CHECK: %sub5.lcssa = phi i32 [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ], [ %sub{{.*}}, %if.else{{.*}} ]
    > +; CHECK: if.else.3
    > +define void @test1(i32 %i, i32 %j) nounwind uwtable ssp {
    > +entry:
    > + ?%cond1 = call zeroext i1 @check()
    > + ?br i1 %cond1, label %if.then, label %if.else.lr.ph
    > +
    > +if.else.lr.ph: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %entry
    > + ?br label %if.else
    > +
    > +if.else: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %if.else, %if.else.lr.ph
    > + ?%sub = phi i32 [ %i, %if.else.lr.ph ], [ %sub5, %if.else ]
    > + ?%sub5 = sub i32 %sub, %j
    > + ?%cond2 = call zeroext i1 @check()
    > + ?br i1 %cond2, label %if.then, label %if.else
    > +
    > +if.then: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %if.else, %entry
    > + ?%i.tr = phi i32 [ %i, %entry ], [ %sub5, %if.else ]
    > + ?ret void
    > +
    > +}
    > +
    > +; PR7318: assertion failure after doing a simple loop unroll
    > +;
    > +; CHECK: @test2
    > +; CHECK: bb1.bb2_crit_edge:
    > +; CHECK: %.lcssa = phi i32 [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ], [ %{{[2468]}}, %bb1{{.*}} ]
    > +; CHECK: bb1.3:
    > +define i32 @test2(i32* nocapture %p, i32 %n) nounwind readonly {
    > +entry:
    > + ?%0 = icmp sgt i32 %n, 0 ? ? ? ? ? ? ? ? ? ? ? ? ;  [#uses=1]
    > + ?br i1 %0, label %bb.nph, label %bb2
    > +
    > +bb.nph: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; preds = %entry
    > + ?%tmp = zext i32 %n to i64 ? ? ? ? ? ? ? ? ? ? ? ;  [#uses=1]
    > + ?br label %bb
    > +
    > +bb: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; preds = %bb.nph, %bb1
    > + ?%indvar = phi i64 [ 0, %bb.nph ], [ %indvar.next, %bb1 ] ;  [#uses=2]
    > + ?%s.01 = phi i32 [ 0, %bb.nph ], [ %2, %bb1 ] ? ?;  [#uses=1]
    > + ?%scevgep = getelementptr i32* %p, i64 %indvar ? ;  [#uses=1]
    > + ?%1 = load i32* %scevgep, align 1 ? ? ? ? ? ? ? ?;  [#uses=1]
    > + ?%2 = add nsw i32 %1, %s.01 ? ? ? ? ? ? ? ? ? ? ?;  [#uses=2]
    > + ?br label %bb1
    > +
    > +bb1: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %bb
    > + ?%indvar.next = add i64 %indvar, 1 ? ? ? ? ? ? ? ;  [#uses=2]
    > + ?%exitcond = icmp ne i64 %indvar.next, %tmp ? ? ?;  [#uses=1]
    > + ?br i1 %exitcond, label %bb, label %bb1.bb2_crit_edge
    > +
    > +bb1.bb2_crit_edge: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %bb1
    > + ?%.lcssa = phi i32 [ %2, %bb1 ] ? ? ? ? ? ? ? ? ?;  [#uses=1]
    > + ?br label %bb2
    > +
    > +bb2: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %bb1.bb2_crit_edge, %entry
    > + ?%s.0.lcssa = phi i32 [ %.lcssa, %bb1.bb2_crit_edge ], [ 0, %entry ] ;  [#uses=1]
    > + ?ret i32 %s.0.lcssa
    > +}
    > +
    > +; Check phi update for loop with an early-exit.
    > +;
    > +; CHECK: @test3
    > +; CHECK: return.loopexit:
    > +; CHECK: %tmp7.i.lcssa = phi i32 [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ], [ %tmp7.i{{.*}}, %land.lhs.true{{.*}} ]
    > +; CHECK: exit.3:
    > +define i32 @test3() nounwind uwtable ssp align 2 {
    > +entry:
    > + ?br i1 undef, label %return, label %if.end
    > +
    > +if.end: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; preds = %entry
    > + ?br label %do.body
    > +
    > +do.body: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %do.cond, %if.end
    > + ?br i1 undef, label %exit, label %do.cond
    > +
    > +exit: ? ? ? ? ? ? ? ? ?; preds = %do.body
    > + ?%tmp7.i = load i32* undef, align 8
    > + ?br i1 undef, label %do.cond, label %land.lhs.true
    > +
    > +land.lhs.true: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %exit
    > + ?br i1 undef, label %return, label %do.cond
    > +
    > +do.cond: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %land.lhs.true, %exit, %do.body
    > + ?br i1 undef, label %do.end, label %do.body
    > +
    > +do.end: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; preds = %do.cond
    > + ?br label %return
    > +
    > +return: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; preds = %do.end, %land.lhs.true, %entry
    > + ?%retval.0 = phi i32 [ 0, %do.end ], [ 0, %entry ], [ %tmp7.i, %land.lhs.true ]
    > + ?ret i32 %retval.0
    > +}
    >
    > Added: llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll?rev=137190&view=auto
    > ==============================================================================
    > --- llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll (added)
    > +++ llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll Tue Aug ?9 19:28:10 2011
    > @@ -0,0 +1,62 @@
    > +; RUN: opt -S < %s -instcombine -inline -jump-threading -loop-unroll -unroll-count=4 | FileCheck %s
    > +;
    > +; This is a test case that required a number of setup passes because
    > +; it depends on block order.
    > +
    > +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
    > +target triple = "x86_64-apple-macosx10.6.8"
    > +
    > +declare i1 @check() nounwind
    > +declare i32 @getval() nounwind
    > +
    > +; Check that the loop exit merges values from all the iterations. This
    > +; could be a tad fragile, but it's a good test.
    > +;
    > +; CHECK: @foo
    > +; CHECK: return:
    > +; CHECK: %retval.0 = phi i32 [ %tmp7.i, %land.lhs.true ], [ 0, %do.cond ], [ %tmp7.i.1, %land.lhs.true.1 ], [ 0, %do.cond.1 ], [ %tmp7.i.2, %land.lhs.true.2 ], [ 0, %do.cond.2 ], [ %tmp7.i.3, %land.lhs.true.3 ], [ 0, %do.cond.3 ]
    > +; CHECK-NOT: @bar
    > +; CHECK: bar.exit.3
    > +define i32 @foo() uwtable ssp align 2 {
    > +entry:
    > + ?br i1 undef, label %return, label %if.end
    > +
    > +if.end: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; preds = %entry
    > + ?%call2 = call i32 @getval()
    > + ?br label %do.body
    > +
    > +do.body: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %do.cond, %if.end
    > + ?%call6 = call i32 @bar()
    > + ?%cmp = icmp ne i32 %call6, 0
    > + ?br i1 %cmp, label %land.lhs.true, label %do.cond
    > +
    > +land.lhs.true: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %do.body
    > + ?%call10 = call i32 @getval()
    > + ?%cmp11 = icmp eq i32 0, %call10
    > + ?br i1 %cmp11, label %return, label %do.cond
    > +
    > +do.cond: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %land.lhs.true, %do.body
    > + ?%cmp18 = icmp sle i32 0, %call2
    > + ?br i1 %cmp18, label %do.body, label %return
    > +
    > +return: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; preds = %do.cond, %land.lhs.true, %entry
    > + ?%retval.0 = phi i32 [ 0, %entry ], [ %call6, %land.lhs.true ], [ 0, %do.cond ]
    > + ?ret i32 %retval.0
    > +}
    > +
    > +define linkonce_odr i32 @bar() nounwind uwtable ssp align 2 {
    > +entry:
    > + ?br i1 undef, label %land.lhs.true, label %cond.end
    > +
    > +land.lhs.true: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %entry
    > + ?%cmp4 = call zeroext i1 @check()
    > + ?br i1 %cmp4, label %cond.true, label %cond.end
    > +
    > +cond.true: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?; preds = %land.lhs.true
    > + ?%tmp7 = call i32 @getval()
    > + ?br label %cond.end
    > +
    > +cond.end: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ; preds = %cond.true, %land.lhs.true, %entry
    > + ?%cond = phi i32 [ %tmp7, %cond.true ], [ 0, %land.lhs.true ], [ 0, %entry ]
    > + ?ret i32 %cond
    > +}
    >
    >
    > _______________________________________________
    > llvm-commits mailing list
    > llvm-commits at cs.uiuc.edu
    > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
    >
    
    
    From clattner at apple.com  Tue Aug  9 19:38:02 2011
    From: clattner at apple.com (Chris Lattner)
    Date: Tue, 09 Aug 2011 17:38:02 -0700
    Subject: [llvm-commits] [llvm] r137144 - in /llvm/trunk: lib/Target/ARM/
     lib/Target/ARM/Disassembler/ test/MC/Disassembler/ARM/ utils/TableGen/
    In-Reply-To: <20110809205519.AA7252A6C12E@llvm.org>
    References: <20110809205519.AA7252A6C12E@llvm.org>
    Message-ID: 
    
    
    On Aug 9, 2011, at 1:55 PM, Owen Anderson wrote:
    
    > Author: resistor
    > Date: Tue Aug  9 15:55:18 2011
    > New Revision: 137144
    > 
    > URL: http://llvm.org/viewvc/llvm-project?rev=137144&view=rev
    > Log:
    > Replace the existing ARM disassembler with a new one based on the FixedLenDecoderEmitter.
    > This new disassembler can correctly decode all the testcases that the old one did, though
    > some "expected failure" testcases are XFAIL'd for now because it is not (yet) as strict in
    > operand checking as the old one was.
    
    Woot!
    
    
    From eli.friedman at gmail.com  Tue Aug  9 19:43:15 2011
    From: eli.friedman at gmail.com (Eli Friedman)
    Date: Tue, 9 Aug 2011 17:43:15 -0700
    Subject: [llvm-commits] [llvm] r137190 - in /llvm/trunk:
     include/llvm/Analysis/LoopInfo.h lib/Transforms/Utils/LoopUnroll.cpp
     test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
     test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    In-Reply-To: <20110810002810.AF3BF2A6C12C@llvm.org>
    References: <20110810002810.AF3BF2A6C12C@llvm.org>
    Message-ID: 
    
    On Tue, Aug 9, 2011 at 5:28 PM, Andrew Trick  wrote:
    > Author: atrick
    > Date: Tue Aug ?9 19:28:10 2011
    > New Revision: 137190
    >
    > URL: http://llvm.org/viewvc/llvm-project?rev=137190&view=rev
    > Log:
    > Fix the LoopUnroller to handle nontrivial loops and partial unrolling.
    >
    > These are not individual bug fixes. I had to rewrite a good chunk of
    > the unroller to make it sane. I think it was getting lucky on trivial
    > completely unrolled loops with no early exits. I included some fairly
    > simple unit tests for partial unrolling. I didn't do much stress
    > testing, so it may not be perfect, but should be usable now.
    
    Does this address http://llvm.org/bugs/show_bug.cgi?id=2253 and/or
    http://llvm.org/bugs/show_bug.cgi?id=7318 ?
    
    -Eli
    
    
    From evan.cheng at apple.com  Tue Aug  9 19:45:36 2011
    From: evan.cheng at apple.com (Evan Cheng)
    Date: Wed, 10 Aug 2011 08:45:36 +0800
    Subject: [llvm-commits] [llvm] r137144 - in /llvm/trunk: lib/Target/ARM/
     lib/Target/ARM/Disassembler/ test/MC/Disassembler/ARM/ utils/TableGen/
    In-Reply-To: <20110809205519.AA7252A6C12E@llvm.org>
    References: <20110809205519.AA7252A6C12E@llvm.org>
    Message-ID: <57B871E6-AD07-426A-9CEC-E8488352E6EE@apple.com>
    
    Awesome. Thanks for doing this!
    
    Evan
    
    On Aug 10, 2011, at 4:55 AM, Owen Anderson  wrote:
    
    > Author: resistor
    > Date: Tue Aug  9 15:55:18 2011
    > New Revision: 137144
    > 
    > URL: http://llvm.org/viewvc/llvm-project?rev=137144&view=rev
    > Log:
    > Replace the existing ARM disassembler with a new one based on the FixedLenDecoderEmitter.
    > This new disassembler can correctly decode all the testcases that the old one did, though
    > some "expected failure" testcases are XFAIL'd for now because it is not (yet) as strict in
    > operand checking as the old one was.
    > 
    > Removed:
    >    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/lib/Target/ARM/ARMInstrFormats.td
    >    llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    >    llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
    >    llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
    >    llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    >    llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
    >    llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h
    >    llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt
    >    llvm/trunk/lib/Target/ARM/Makefile
    >    llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-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-LSL-regform.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt
    >    llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt
    >    llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp
    > 
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Tue Aug  9 15:55:18 2011
    > @@ -152,6 +152,7 @@
    >                                      (ops (i32 14), (i32 zero_reg))> {
    >   let PrintMethod = "printPredicateOperand";
    >   let ParserMatchClass = CondCodeOperand;
    > +    let DecoderMethod = "DecodePredicateOperand";
    > }
    > 
    > // Conditional code result for instructions whose 's' bit is set, e.g. subs.
    > @@ -160,6 +161,7 @@
    >   let EncoderMethod = "getCCOutOpValue";
    >   let PrintMethod = "printSBitModifierOperand";
    >   let ParserMatchClass = CCOutOperand;
    > +    let DecoderMethod = "DecodeCCOutOperand";
    > }
    > 
    > // Same as cc_out except it defaults to setting CPSR.
    > @@ -167,6 +169,7 @@
    >   let EncoderMethod = "getCCOutOpValue";
    >   let PrintMethod = "printSBitModifierOperand";
    >   let ParserMatchClass = CCOutOperand;
    > +    let DecoderMethod = "DecodeCCOutOperand";
    > }
    > 
    > // ARM special operands for disassembly only.
    > @@ -199,15 +202,19 @@
    > //     64       64 -  is encoded in imm6<5:0>
    > def shr_imm8  : Operand {
    >   let EncoderMethod = "getShiftRight8Imm";
    > +  let DecoderMethod = "DecodeShiftRight8Imm";
    > }
    > def shr_imm16 : Operand {
    >   let EncoderMethod = "getShiftRight16Imm";
    > +  let DecoderMethod = "DecodeShiftRight16Imm";
    > }
    > def shr_imm32 : Operand {
    >   let EncoderMethod = "getShiftRight32Imm";
    > +  let DecoderMethod = "DecodeShiftRight32Imm";
    > }
    > def shr_imm64 : Operand {
    >   let EncoderMethod = "getShiftRight64Imm";
    > +  let DecoderMethod = "DecodeShiftRight64Imm";
    > }
    > 
    > //===----------------------------------------------------------------------===//
    > @@ -579,6 +586,8 @@
    >   let Inst{11-8}  = addr{7-4};    // imm7_4/zero
    >   let Inst{7-4}   = op;
    >   let Inst{3-0}   = addr{3-0};    // imm3_0/Rm
    > +
    > +  let DecoderMethod = "DecodeAddrMode3Instruction";
    > }
    > 
    > class AI3ldstidx op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
    > @@ -1265,6 +1274,7 @@
    >   let AsmString = !strconcat(opc, "${p}", asm);
    >   let Pattern = pattern;
    >   let PostEncoderMethod = "VFPThumb2PostEncoder";
    > +  let DecoderNamespace = "VFP";
    >   list Predicates = [HasVFP2];
    > }
    > 
    > @@ -1280,6 +1290,7 @@
    >   let AsmString = asm;
    >   let Pattern = pattern;
    >   let PostEncoderMethod = "VFPThumb2PostEncoder";
    > +  let DecoderNamespace = "VFP";
    >   list Predicates = [HasVFP2];
    > }
    > 
    > @@ -1597,6 +1608,7 @@
    >   let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
    >   let Pattern = pattern;
    >   list Predicates = [HasNEON];
    > +  let DecoderNamespace = "NEON";
    > }
    > 
    > // Same as NeonI except it does not have a "data type" specifier.
    > @@ -1609,6 +1621,7 @@
    >   let AsmString = !strconcat(opc, "${p}", "\t", asm);
    >   let Pattern = pattern;
    >   list Predicates = [HasNEON];
    > +  let DecoderNamespace = "NEON";
    > }
    > 
    > class NLdSt op21_20, bits<4> op11_8, bits<4> op7_4,
    > @@ -1700,6 +1713,7 @@
    >   let Inst{24}    = SIMM{7};
    >   let Inst{18-16} = SIMM{6-4};
    >   let Inst{3-0}   = SIMM{3-0};
    > +  let DecoderMethod = "DecodeNEONModImmInstruction";
    > }
    > 
    > // NEON 2 vector register format.
    > 
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug  9 15:55:18 2011
    > @@ -315,6 +315,7 @@
    > def brtarget : Operand {
    >   let EncoderMethod = "getBranchTargetOpValue";
    >   let OperandType = "OPERAND_PCREL";
    > +  let DecoderMethod = "DecodeT2BROperand";
    > }
    > 
    > // FIXME: get rid of this one?
    > @@ -343,6 +344,7 @@
    >   // Encoded the same as branch targets.
    >   let EncoderMethod = "getARMBranchTargetOpValue";
    >   let OperandType = "OPERAND_PCREL";
    > +    let DecoderMethod = "DecodeBLTargetOperand";
    > }
    > 
    > 
    > @@ -352,6 +354,7 @@
    >   let EncoderMethod = "getRegisterListOpValue";
    >   let ParserMatchClass = RegListAsmOperand;
    >   let PrintMethod = "printRegisterList";
    > +  let DecoderMethod = "DecodeRegListOperand";
    > }
    > 
    > def DPRRegListAsmOperand : AsmOperandClass { let Name = "DPRRegList"; }
    > @@ -359,6 +362,7 @@
    >   let EncoderMethod = "getRegisterListOpValue";
    >   let ParserMatchClass = DPRRegListAsmOperand;
    >   let PrintMethod = "printRegisterList";
    > +  let DecoderMethod = "DecodeDPRRegListOperand";
    > }
    > 
    > def SPRRegListAsmOperand : AsmOperandClass { let Name = "SPRRegList"; }
    > @@ -366,6 +370,7 @@
    >   let EncoderMethod = "getRegisterListOpValue";
    >   let ParserMatchClass = SPRRegListAsmOperand;
    >   let PrintMethod = "printRegisterList";
    > +  let DecoderMethod = "DecodeSPRRegListOperand";
    > }
    > 
    > // An operand for the CONSTPOOL_ENTRY pseudo-instruction.
    > @@ -385,6 +390,7 @@
    > 
    > def neon_vcvt_imm32 : Operand {
    >   let EncoderMethod = "getNEONVcvtImm32OpValue";
    > +  let DecoderMethod = "DecodeVCVTImmOperand";
    > }
    > 
    > // rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24.
    > @@ -431,6 +437,7 @@
    >                                 [shl, srl, sra, rotr]> {
    >   let EncoderMethod = "getSORegRegOpValue";
    >   let PrintMethod = "printSORegRegOperand";
    > +  let DecoderMethod = "DecodeSORegRegOperand";
    >   let ParserMatchClass = ShiftedRegAsmOperand;
    >   let MIOperandInfo = (ops GPR, GPR, i32imm);
    > }
    > @@ -441,6 +448,7 @@
    >                                 [shl, srl, sra, rotr]> {
    >   let EncoderMethod = "getSORegImmOpValue";
    >   let PrintMethod = "printSORegImmOperand";
    > +  let DecoderMethod = "DecodeSORegImmOperand";
    >   let ParserMatchClass = ShiftedImmAsmOperand;
    >   let MIOperandInfo = (ops GPR, i32imm);
    > }
    > @@ -451,6 +459,7 @@
    >                                   [shl,srl,sra,rotr]> {
    >   let EncoderMethod = "getSORegRegOpValue";
    >   let PrintMethod = "printSORegRegOperand";
    > +  let DecoderMethod = "DecodeSORegRegOperand";
    >   let MIOperandInfo = (ops GPR, GPR, i32imm);
    > }
    > 
    > @@ -460,6 +469,7 @@
    >                                   [shl,srl,sra,rotr]> {
    >   let EncoderMethod = "getSORegImmOpValue";
    >   let PrintMethod = "printSORegImmOperand";
    > +  let DecoderMethod = "DecodeSORegImmOperand";
    >   let MIOperandInfo = (ops GPR, i32imm);
    > }
    > 
    > @@ -472,6 +482,7 @@
    >   }]> {
    >   let EncoderMethod = "getSOImmOpValue";
    >   let ParserMatchClass = SOImmAsmOperand;
    > +    let DecoderMethod = "DecodeSOImmOperand";
    > }
    > 
    > // Break so_imm's up into two pieces.  This handles immediates with up to 16
    > @@ -552,6 +563,7 @@
    > }] > {
    >   let EncoderMethod = "getBitfieldInvertedMaskOpValue";
    >   let PrintMethod = "printBitfieldInvMaskImmOperand";
    > +  let DecoderMethod = "DecodeBitfieldMaskOperand";
    >   let ParserMatchClass = BitfieldAsmOperand;
    > }
    > 
    > @@ -599,6 +611,7 @@
    > 
    >   let EncoderMethod = "getAddrModeImm12OpValue";
    >   let PrintMethod = "printAddrModeImm12Operand";
    > +  let DecoderMethod = "DecodeAddrModeImm12Operand";
    >   let ParserMatchClass = MemImm12OffsetAsmOperand;
    >   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
    > }
    > @@ -610,6 +623,7 @@
    >   let EncoderMethod = "getLdStSORegOpValue";
    >   // FIXME: Simplify the printer
    >   let PrintMethod = "printAddrMode2Operand";
    > +  let DecoderMethod = "DecodeSORegMemOperand";
    >   let ParserMatchClass = MemRegOffsetAsmOperand;
    >   let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$shift);
    > }
    > @@ -645,6 +659,7 @@
    > }
    > def postidx_reg : Operand {
    >   let EncoderMethod = "getPostIdxRegOpValue";
    > +  let DecoderMethod = "DecodePostIdxReg";
    >   let PrintMethod = "printPostIdxRegOperand";
    >   let ParserMatchClass = PostIdxRegAsmOperand;
    >   let MIOperandInfo = (ops GPR, i32imm);
    > @@ -707,6 +722,7 @@
    >                 ComplexPattern                                [], [SDNPWantRoot]> {
    >   let EncoderMethod = "getAddrMode3OffsetOpValue";
    > +  let DecoderMethod = "DecodeAddrMode3Offset";
    >   let PrintMethod = "printAddrMode3OffsetOperand";
    >   let MIOperandInfo = (ops GPR, i32imm);
    > }
    > @@ -725,6 +741,7 @@
    >                 ComplexPattern {
    >   let PrintMethod = "printAddrMode5Operand";
    >   let EncoderMethod = "getAddrMode5OpValue";
    > +  let DecoderMethod = "DecodeAddrMode5Operand";
    >   let ParserMatchClass = AddrMode5AsmOperand;
    >   let MIOperandInfo = (ops GPR:$base, i32imm);
    > }
    > @@ -736,6 +753,7 @@
    >   let PrintMethod = "printAddrMode6Operand";
    >   let MIOperandInfo = (ops GPR:$addr, i32imm);
    >   let EncoderMethod = "getAddrMode6AddressOpValue";
    > +  let DecoderMethod = "DecodeAddrMode6Operand";
    > }
    > 
    > def am6offset : Operand,
    > @@ -744,6 +762,7 @@
    >   let PrintMethod = "printAddrMode6OffsetOperand";
    >   let MIOperandInfo = (ops GPR);
    >   let EncoderMethod = "getAddrMode6OffsetOpValue";
    > +  let DecoderMethod = "DecodeGPRRegisterClass";
    > }
    > 
    > // Special version of addrmode6 to handle alignment encoding for VST1/VLD1
    > @@ -778,6 +797,7 @@
    > def addr_offset_none : Operand,
    >                        ComplexPattern {
    >   let PrintMethod = "printAddrMode7Operand";
    > +  let DecoderMethod = "DecodeAddrMode7Operand";
    >   let ParserMatchClass = MemNoOffsetAsmOperand;
    >   let MIOperandInfo = (ops GPR:$base);
    > }
    > @@ -793,6 +813,7 @@
    > def p_imm : Operand {
    >   let PrintMethod = "printPImmediate";
    >   let ParserMatchClass = CoprocNumAsmOperand;
    > +  let DecoderMethod = "DecodeCoprocessor";
    > }
    > 
    > def CoprocRegAsmOperand : AsmOperandClass {
    > @@ -1654,6 +1675,7 @@
    >                [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]> {
    >     bits<24> target;
    >     let Inst{23-0} = target;
    > +    let DecoderMethod = "DecodeBranchImmInstruction";
    >   }
    > 
    >   let isBarrier = 1 in {
    > @@ -1917,6 +1939,7 @@
    >     let Inst{23} = addr{12};
    >     let Inst{19-16} = addr{17-14};
    >     let Inst{11-0} = addr{11-0};
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >     let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
    >   }
    > 
    > @@ -1933,6 +1956,8 @@
    >      let Inst{23} = offset{12};
    >      let Inst{19-16} = addr;
    >      let Inst{11-0} = offset{11-0};
    > +
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >    }
    > 
    >    def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
    > @@ -1948,7 +1973,10 @@
    >     let Inst{23} = offset{12};
    >     let Inst{19-16} = addr;
    >     let Inst{11-0} = offset{11-0};
    > +
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    > +
    > }
    > 
    > let mayLoad = 1, neverHasSideEffects = 1 in {
    > @@ -2019,20 +2047,39 @@
    > 
    > // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.
    > let mayLoad = 1, neverHasSideEffects = 1 in {
    > -def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
    > -                   (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
    > +def LDRTr : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
    > +                   (ins ldst_so_reg:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
    > +                   "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
    > +  // {17-14}  Rn
    > +  // {13}     1 == Rm, 0 == imm12
    > +  // {12}     isAdd
    > +  // {11-0}   imm12/Rm
    > +  bits<18> addr;
    > +  let Inst{25} = 1;
    > +  let Inst{23} = addr{12};
    > +  let Inst{21} = 1; // overwrite
    > +  let Inst{19-16} = addr{17-14};
    > +  let Inst{11-5} = addr{11-5};
    > +  let Inst{4} = 0;
    > +  let Inst{3-0} = addr{3-0};
    > +  let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > +}
    > +def LDRTi : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
    > +                   (ins addrmode_imm12:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
    >                    "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []> {
    >   // {17-14}  Rn
    >   // {13}     1 == Rm, 0 == imm12
    >   // {12}     isAdd
    >   // {11-0}   imm12/Rm
    >   bits<18> addr;
    > -  let Inst{25} = addr{13};
    > +  let Inst{25} = 0;
    >   let Inst{23} = addr{12};
    >   let Inst{21} = 1; // overwrite
    >   let Inst{19-16} = addr{17-14};
    >   let Inst{11-0} = addr{11-0};
    >   let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > }
    > 
    > def LDRBT_POST_REG : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
    > @@ -2049,6 +2096,7 @@
    >   let Inst{21} = 1; // overwrite
    >   let Inst{19-16} = addr;
    >   let Inst{11-0} = offset{11-0};
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > }
    > 
    > def LDRBT_POST_IMM : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
    > @@ -2065,6 +2113,7 @@
    >   let Inst{21} = 1; // overwrite
    >   let Inst{19-16} = addr;
    >   let Inst{11-0} = offset{11-0};
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > }
    > 
    > multiclass AI3ldrT op, string opc> {
    > @@ -2151,6 +2200,8 @@
    >      let Inst{23} = offset{12};
    >      let Inst{19-16} = addr;
    >      let Inst{11-0} = offset{11-0};
    > +
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >    }
    > 
    >    def _POST_IMM : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb),
    > @@ -2166,6 +2217,8 @@
    >     let Inst{23} = offset{12};
    >     let Inst{19-16} = addr;
    >     let Inst{11-0} = offset{11-0};
    > +
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    > }
    > 
    > @@ -2287,6 +2340,7 @@
    >   let Inst{21} = 1; // overwrite
    >   let Inst{4} = 0;
    >   let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > }
    > 
    > def STRTi : AI2stridxT<0, 0, (outs GPR:$Rn_wb),
    > @@ -2297,6 +2351,7 @@
    >   let Inst{25} = 0;
    >   let Inst{21} = 1; // overwrite
    >   let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > }
    > 
    > 
    > @@ -2309,6 +2364,7 @@
    >   let Inst{21} = 1; // overwrite
    >   let Inst{4} = 0;
    >   let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > }
    > 
    > def STRBTi : AI2stridxT<1, 0, (outs GPR:$Rn_wb),
    > @@ -2319,6 +2375,7 @@
    >   let Inst{25} = 0;
    >   let Inst{21} = 1; // overwrite
    >   let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > }
    > 
    > multiclass AI3strT op, string opc> {
    > @@ -2373,6 +2430,8 @@
    >     let Inst{24-23} = 0b01;       // Increment After
    >     let Inst{21}    = 1;          // Writeback
    >     let Inst{20}    = L_bit;
    > +
    > +    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
    >   }
    >   def DA :
    >     AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
    > @@ -2389,6 +2448,8 @@
    >     let Inst{24-23} = 0b00;       // Decrement After
    >     let Inst{21}    = 1;          // Writeback
    >     let Inst{20}    = L_bit;
    > +
    > +    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
    >   }
    >   def DB :
    >     AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
    > @@ -2405,6 +2466,8 @@
    >     let Inst{24-23} = 0b10;       // Decrement Before
    >     let Inst{21}    = 1;          // Writeback
    >     let Inst{20}    = L_bit;
    > +
    > +    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
    >   }
    >   def IB :
    >     AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
    > @@ -2421,6 +2484,8 @@
    >     let Inst{24-23} = 0b11;       // Increment Before
    >     let Inst{21}    = 1;          // Writeback
    >     let Inst{20}    = L_bit;
    > +
    > +    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
    >   }
    > }
    > 
    > @@ -2504,8 +2569,6 @@
    >   let Inst{25} = 0;
    > }
    > 
    > -
    > -
    > let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
    > def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi,
    >                 "mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP {
    > @@ -3383,6 +3446,7 @@
    > 
    > 
    > multiclass AI_smla {
    > +  let DecoderMethod = "DecodeSMLAInstruction" in {
    >   def BB : AMulxyIa<0b0001000, 0b00, (outs GPR:$Rd),
    >               (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    >               IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra",
    > @@ -3425,6 +3489,7 @@
    >               [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn,
    >                                         (sra GPR:$Rm, (i32 16))), (i32 16))))]>,
    >             Requires<[IsARM, HasV5TE]>;
    > +  }
    > }
    > 
    > defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
    > @@ -3989,7 +4054,7 @@
    > }
    > 
    > multiclass LdStCop op31_28, bit load, dag ops, string opc, string cond>{
    > -
    > +  let DecoderNamespace = "Common" in {
    >   def _OFFSET : ACI<(outs),
    >       !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
    >       !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr"> {
    > @@ -3998,6 +4063,7 @@
    >     let Inst{21} = 0; // W = 0
    >     let Inst{22} = 0; // D = 0
    >     let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >   }
    > 
    >   def _PRE : ACI<(outs),
    > @@ -4008,6 +4074,7 @@
    >     let Inst{21} = 1; // W = 1
    >     let Inst{22} = 0; // D = 0
    >     let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >   }
    > 
    >   def _POST : ACI<(outs),
    > @@ -4018,6 +4085,7 @@
    >     let Inst{21} = 1; // W = 1
    >     let Inst{22} = 0; // D = 0
    >     let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >   }
    > 
    >   def _OPTION : ACI<(outs),
    > @@ -4030,6 +4098,7 @@
    >     let Inst{21} = 0; // W = 0
    >     let Inst{22} = 0; // D = 0
    >     let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >   }
    > 
    >   def L_OFFSET : ACI<(outs),
    > @@ -4040,6 +4109,7 @@
    >     let Inst{21} = 0; // W = 0
    >     let Inst{22} = 1; // D = 1
    >     let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >   }
    > 
    >   def L_PRE : ACI<(outs),
    > @@ -4051,6 +4121,7 @@
    >     let Inst{21} = 1; // W = 1
    >     let Inst{22} = 1; // D = 1
    >     let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >   }
    > 
    >   def L_POST : ACI<(outs),
    > @@ -4063,6 +4134,7 @@
    >     let Inst{21} = 1; // W = 1
    >     let Inst{22} = 1; // D = 1
    >     let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >   }
    > 
    >   def L_OPTION : ACI<(outs),
    > @@ -4076,6 +4148,8 @@
    >     let Inst{21} = 0; // W = 0
    >     let Inst{22} = 1; // D = 1
    >     let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    > +  }
    >   }
    > }
    > 
    > 
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrNEON.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrNEON.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrNEON.td Tue Aug  9 15:55:18 2011
    > @@ -191,6 +191,7 @@
    >           "vld1", Dt, "\\{$Vd\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > class VLD1Q op7_4, string Dt>
    >   : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2),
    > @@ -198,6 +199,7 @@
    >           "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def  VLD1d8   : VLD1D<{0,0,0,?}, "8">;
    > @@ -222,6 +224,7 @@
    >           "vld1", Dt, "\\{$Vd\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > class VLD1QWB op7_4, string Dt>
    >   : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb),
    > @@ -229,6 +232,7 @@
    >           "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def VLD1d8_UPD  : VLD1DWB<{0,0,0,?}, "8">;
    > @@ -253,12 +257,14 @@
    >           "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > class VLD1D3WB op7_4, string Dt>
    >   : NLdSt<0,0b10,0b0110,op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb),
    >           (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x3u, "vld1", Dt,
    >           "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def VLD1d8T      : VLD1D3<{0,0,0,?}, "8">;
    > @@ -281,6 +287,7 @@
    >           "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > class VLD1D4WB op7_4, string Dt>
    >   : NLdSt<0,0b10,0b0010,op7_4,
    > @@ -289,6 +296,7 @@
    >           "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb",
    >           []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def VLD1d8Q      : VLD1D4<{0,0,?,?}, "8">;
    > @@ -311,6 +319,7 @@
    >           "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > class VLD2Q op7_4, string Dt>
    >   : NLdSt<0, 0b10, 0b0011, op7_4,
    > @@ -319,6 +328,7 @@
    >           "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def  VLD2d8   : VLD2D<0b1000, {0,0,?,?}, "8">;
    > @@ -344,6 +354,7 @@
    >           "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > class VLD2QWB op7_4, string Dt>
    >   : NLdSt<0, 0b10, 0b0011, op7_4,
    > @@ -352,6 +363,7 @@
    >           "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def VLD2d8_UPD  : VLD2DWB<0b1000, {0,0,?,?}, "8">;
    > @@ -385,6 +397,7 @@
    >           "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def  VLD3d8   : VLD3D<0b0100, {0,0,0,?}, "8">;
    > @@ -403,6 +416,7 @@
    >           "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def VLD3d8_UPD  : VLD3DWB<0b0100, {0,0,0,?}, "8">;
    > @@ -442,6 +456,7 @@
    >           "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def  VLD4d8   : VLD4D<0b0000, {0,0,?,?}, "8">;
    > @@ -460,6 +475,7 @@
    >           "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    > }
    > 
    > def VLD4d8_UPD  : VLD4DWB<0b0000, {0,0,?,?}, "8">;
    > @@ -826,6 +842,7 @@
    >           [(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD1DupInstruction";
    > }
    > class VLD1QDUPPseudo : VLDQPseudo {
    >   let Pattern = [(set QPR:$dst,
    > @@ -853,6 +870,7 @@
    >           "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD1DupInstruction";
    > }
    > 
    > def VLD1DUPq8  : VLD1QDUP<{0,0,1,0}, "8">;
    > @@ -865,12 +883,14 @@
    >           (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu,
    >           "vld1", Dt, "\\{$Vd[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD1DupInstruction";
    > }
    > class VLD1QDUPWB op7_4, string Dt>
    >   : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb),
    >           (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu,
    >           "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD1DupInstruction";
    > }
    > 
    > def VLD1DUPd8_UPD  : VLD1DUPWB<{0,0,0,0}, "8">;
    > @@ -892,6 +912,7 @@
    >           "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD2DupInstruction";
    > }
    > 
    > def VLD2DUPd8  : VLD2DUP<{0,0,0,?}, "8">;
    > @@ -913,6 +934,7 @@
    >           (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD2dupu,
    >           "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD2DupInstruction";
    > }
    > 
    > def VLD2DUPd8_UPD  : VLD2DUPWB<{0,0,0,0}, "8">;
    > @@ -934,6 +956,7 @@
    >           "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD3DupInstruction";
    > }
    > 
    > def VLD3DUPd8  : VLD3DUP<{0,0,0,?}, "8">;
    > @@ -956,6 +979,7 @@
    >           "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD3DupInstruction";
    > }
    > 
    > def VLD3DUPd8_UPD  : VLD3DUPWB<{0,0,0,0}, "8">;
    > @@ -978,6 +1002,7 @@
    >           "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD4DupInstruction";
    > }
    > 
    > def VLD4DUPd8  : VLD4DUP<{0,0,0,?}, "8">;
    > @@ -1001,6 +1026,7 @@
    >           "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD4DupInstruction";
    > }
    > 
    > def VLD4DUPd8_UPD  : VLD4DUPWB<{0,0,0,0}, "8">;
    > @@ -1046,6 +1072,7 @@
    >           IIC_VST1, "vst1", Dt, "\\{$Vd\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > class VST1Q op7_4, string Dt>
    >   : NLdSt<0,0b00,0b1010,op7_4, (outs),
    > @@ -1053,6 +1080,7 @@
    >           "vst1", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def  VST1d8   : VST1D<{0,0,0,?}, "8">;
    > @@ -1076,6 +1104,7 @@
    >           (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd), IIC_VST1u,
    >           "vst1", Dt, "\\{$Vd\\}, $Rn$Rm", "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > class VST1QWB op7_4, string Dt>
    >   : NLdSt<0, 0b00, 0b1010, op7_4, (outs GPR:$wb),
    > @@ -1083,6 +1112,7 @@
    >           IIC_VST1x2u, "vst1", Dt, "\\{$Vd, $src2\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def VST1d8_UPD  : VST1DWB<{0,0,0,?}, "8">;
    > @@ -1107,6 +1137,7 @@
    >           IIC_VST1x3, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > class VST1D3WB op7_4, string Dt>
    >   : NLdSt<0, 0b00, 0b0110, op7_4, (outs GPR:$wb),
    > @@ -1115,6 +1146,7 @@
    >           IIC_VST1x3u, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def VST1d8T      : VST1D3<{0,0,0,?}, "8">;
    > @@ -1138,6 +1170,7 @@
    >           []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > class VST1D4WB op7_4, string Dt>
    >   : NLdSt<0, 0b00, 0b0010, op7_4, (outs GPR:$wb),
    > @@ -1146,6 +1179,7 @@
    >           "vst1", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def VST1d8Q      : VST1D4<{0,0,?,?}, "8">;
    > @@ -1168,6 +1202,7 @@
    >           IIC_VST2, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > class VST2Q op7_4, string Dt>
    >   : NLdSt<0, 0b00, 0b0011, op7_4, (outs),
    > @@ -1176,6 +1211,7 @@
    >           "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def  VST2d8   : VST2D<0b1000, {0,0,?,?}, "8">;
    > @@ -1201,6 +1237,7 @@
    >           IIC_VST2u, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > class VST2QWB op7_4, string Dt>
    >   : NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb),
    > @@ -1209,6 +1246,7 @@
    >           "vst2", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def VST2d8_UPD  : VST2DWB<0b1000, {0,0,?,?}, "8">;
    > @@ -1242,6 +1280,7 @@
    >           "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []> {
    >   let Rm = 0b1111;
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def  VST3d8   : VST3D<0b0100, {0,0,0,?}, "8">;
    > @@ -1260,6 +1299,7 @@
    >           "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def VST3d8_UPD  : VST3DWB<0b0100, {0,0,0,?}, "8">;
    > @@ -1299,6 +1339,7 @@
    >           "", []> {
    >   let Rm = 0b1111;
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def  VST4d8   : VST4D<0b0000, {0,0,?,?}, "8">;
    > @@ -1317,6 +1358,7 @@
    >            "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
    >           "$Rn.addr = $wb", []> {
    >   let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    > }
    > 
    > def VST4d8_UPD  : VST4DWB<0b0000, {0,0,?,?}, "8">;
    > @@ -4040,6 +4082,7 @@
    >   : N2VLSh            ResTy, OpTy, OpNode> {
    >   let Inst{21-16} = op21_16;
    > +  let DecoderMethod = "DecodeVSHLMaxInstruction";
    > }
    > def  VSHLLi8  : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8",
    >                           v8i16, v8i8, NEONvshlli>;
    > @@ -4754,6 +4797,7 @@
    > // Vector Table Lookup and Table Extension.
    > 
    > //   VTBL     : Vector Table Lookup
    > +let DecoderMethod = "DecodeTBLInstruction" in {
    > def  VTBL1
    >   : N3V<1,1,0b11,0b1000,0,0, (outs DPR:$Vd),
    >         (ins DPR:$Vn, DPR:$Vm), NVTBLFrm, IIC_VTB1,
    > @@ -4816,6 +4860,7 @@
    > def  VTBX4Pseudo
    >   : PseudoNeonI<(outs DPR:$dst), (ins DPR:$orig, QQPR:$tbl, DPR:$src),
    >                 IIC_VTBX4, "$orig = $dst", []>;
    > +} // DecoderMethod = "DecodeTBLInstruction"
    > 
    > //===----------------------------------------------------------------------===//
    > // NEON instructions for single-precision FP math
    > 
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Tue Aug  9 15:55:18 2011
    > @@ -82,14 +82,17 @@
    > let OperandType = "OPERAND_PCREL" in {
    > def t_brtarget : Operand {
    >   let EncoderMethod = "getThumbBRTargetOpValue";
    > +  let DecoderMethod = "DecodeThumbBROperand";
    > }
    > 
    > def t_bcctarget : Operand {
    >   let EncoderMethod = "getThumbBCCTargetOpValue";
    > +  let DecoderMethod = "DecodeThumbBCCTargetOperand";
    > }
    > 
    > def t_cbtarget : Operand {
    >   let EncoderMethod = "getThumbCBTargetOpValue";
    > +  let DecoderMethod = "DecodeThumbCmpBROperand";
    > }
    > 
    > def t_bltarget : Operand {
    > @@ -119,12 +122,14 @@
    >                       ComplexPattern {
    >   let EncoderMethod = "getThumbAddrModeRegRegOpValue";
    >   let PrintMethod = "printThumbAddrModeRROperand";
    > +  let DecoderMethod = "DecodeThumbAddrModeRR";
    >   let ParserMatchClass = t_addrmode_rr_asm_operand;
    >   let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
    > }
    > def t_addrmode_rrs2 : Operand,
    >                       ComplexPattern {
    >   let EncoderMethod = "getThumbAddrModeRegRegOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeRR";
    >   let PrintMethod = "printThumbAddrModeRROperand";
    >   let ParserMatchClass = t_addrmode_rr_asm_operand;
    >   let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
    > @@ -132,6 +137,7 @@
    > def t_addrmode_rrs4 : Operand,
    >                       ComplexPattern {
    >   let EncoderMethod = "getThumbAddrModeRegRegOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeRR";
    >   let PrintMethod = "printThumbAddrModeRROperand";
    >   let ParserMatchClass = t_addrmode_rr_asm_operand;
    >   let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
    > @@ -142,6 +148,7 @@
    > def t_addrmode_is4 : Operand,
    >                      ComplexPattern {
    >   let EncoderMethod = "getAddrModeISOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeIS";
    >   let PrintMethod = "printThumbAddrModeImm5S4Operand";
    >   let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
    > }
    > @@ -151,6 +158,7 @@
    > def t_addrmode_is2 : Operand,
    >                      ComplexPattern {
    >   let EncoderMethod = "getAddrModeISOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeIS";
    >   let PrintMethod = "printThumbAddrModeImm5S2Operand";
    >   let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
    > }
    > @@ -160,6 +168,7 @@
    > def t_addrmode_is1 : Operand,
    >                      ComplexPattern {
    >   let EncoderMethod = "getAddrModeISOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeIS";
    >   let PrintMethod = "printThumbAddrModeImm5S1Operand";
    >   let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
    > }
    > @@ -178,6 +187,7 @@
    > //
    > def t_addrmode_pc : Operand {
    >   let EncoderMethod = "getAddrModePCOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModePC";
    > }
    > 
    > //===----------------------------------------------------------------------===//
    > @@ -259,6 +269,7 @@
    >   let Inst{4}   = imod;
    >   let Inst{3}   = 0;
    >   let Inst{2-0} = iflags;
    > +  let DecoderMethod = "DecodeThumbCPS";
    > }
    > 
    > // For both thumb1 and thumb2.
    > @@ -272,17 +283,6 @@
    >   let Inst{2-0} = dst;
    > }
    > 
    > -// PC relative add (ADR).
    > -def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi,
    > -                   "add\t$dst, pc, $rhs", []>,
    > -               T1Encoding<{1,0,1,0,0,?}> {
    > -  // A6.2 & A8.6.10
    > -  bits<3> dst;
    > -  bits<8> rhs;
    > -  let Inst{10-8} = dst;
    > -  let Inst{7-0}  = rhs;
    > -}
    > -
    > // ADD , sp, #
    > // This is rematerializable, which is particularly useful for taking the
    > // address of locals.
    > @@ -295,6 +295,7 @@
    >   bits<8> rhs;
    >   let Inst{10-8} = dst;
    >   let Inst{7-0}  = rhs;
    > +  let DecoderMethod = "DecodeThumbAddSpecialReg";
    > }
    > 
    > // ADD sp, sp, #
    > @@ -304,6 +305,7 @@
    >   // A6.2.5 & A8.6.8
    >   bits<7> rhs;
    >   let Inst{6-0} = rhs;
    > +  let DecoderMethod = "DecodeThumbAddSPImm";
    > }
    > 
    > // SUB sp, sp, #
    > @@ -314,6 +316,7 @@
    >   // A6.2.5 & A8.6.214
    >   bits<7> rhs;
    >   let Inst{6-0} = rhs;
    > +  let DecoderMethod = "DecodeThumbAddSPImm";
    > }
    > 
    > // ADD , sp
    > @@ -325,6 +328,7 @@
    >   let Inst{7}   = dst{3};
    >   let Inst{6-3} = 0b1101;
    >   let Inst{2-0} = dst{2-0};
    > +  let DecoderMethod = "DecodeThumbAddSPReg";
    > }
    > 
    > // ADD sp, 
    > @@ -336,6 +340,7 @@
    >   let Inst{7} = 1;
    >   let Inst{6-3} = dst;
    >   let Inst{2-0} = 0b101;
    > +  let DecoderMethod = "DecodeThumbAddSPReg";
    > }
    > 
    > //===----------------------------------------------------------------------===//
    > @@ -1189,6 +1194,7 @@
    >   bits<8> addr;
    >   let Inst{10-8} = Rd;
    >   let Inst{7-0} = addr;
    > +  let DecoderMethod = "DecodeThumbAddSpecialReg";
    > }
    > 
    > let neverHasSideEffects = 1, isReMaterializable = 1 in
    > 
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Aug  9 15:55:18 2011
    > @@ -50,6 +50,7 @@
    >   }]> {
    >   let ParserMatchClass = t2_so_imm_asmoperand;
    >   let EncoderMethod = "getT2SOImmOpValue";
    > +  let DecoderMethod = "DecodeT2SOImm";
    > }
    > 
    > // t2_so_imm_not - Match an immediate that is a complement
    > @@ -100,6 +101,7 @@
    >                        ComplexPattern {
    >   let PrintMethod = "printAddrModeImm12Operand";
    >   let EncoderMethod = "getAddrModeImm12OpValue";
    > +  let DecoderMethod = "DecodeT2AddrModeImm12";
    >   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
    > }
    > 
    > @@ -121,6 +123,7 @@
    >                       ComplexPattern {
    >   let PrintMethod = "printT2AddrModeImm8Operand";
    >   let EncoderMethod = "getT2AddrModeImm8OpValue";
    > +  let DecoderMethod = "DecodeT2AddrModeImm8";
    >   let ParserMatchClass = MemImm8OffsetAsmOperand;
    >   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
    > }
    > @@ -130,12 +133,14 @@
    >                                       [], [SDNPWantRoot]> {
    >   let PrintMethod = "printT2AddrModeImm8OffsetOperand";
    >   let EncoderMethod = "getT2AddrModeImm8OffsetOpValue";
    > +  let DecoderMethod = "DecodeT2Imm8";
    > }
    > 
    > // t2addrmode_imm8s4  := reg +/- (imm8 << 2)
    > def t2addrmode_imm8s4 : Operand {
    >   let PrintMethod = "printT2AddrModeImm8s4Operand";
    >   let EncoderMethod = "getT2AddrModeImm8s4OpValue";
    > +  let DecoderMethod = "DecodeT2AddrModeImm8s4";
    >   let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
    > }
    > 
    > @@ -149,6 +154,7 @@
    >                         ComplexPattern {
    >   let PrintMethod = "printT2AddrModeSoRegOperand";
    >   let EncoderMethod = "getT2AddrModeSORegOpValue";
    > +  let DecoderMethod = "DecodeT2AddrModeSOReg";
    >   let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm);
    > }
    > 
    > @@ -158,6 +164,7 @@
    > //
    > def t2addrmode_reg : Operand {
    >   let PrintMethod = "printAddrMode7Operand";
    > +  let DecoderMethod = "DecodeGPRRegisterClass";
    >   let MIOperandInfo = (ops GPR);
    > }
    > 
    > @@ -892,6 +899,8 @@
    >     let Inst{19-16} = addr{9-6}; // Rn
    >     let Inst{3-0}   = addr{5-2}; // Rm
    >     let Inst{5-4}   = addr{1-0}; // imm
    > +
    > +    let DecoderMethod = "DecodeT2LoadShift";
    >   }
    > 
    >   // FIXME: Is the pci variant actually needed?
    > @@ -1430,6 +1439,8 @@
    >     let Inst{19-16} = addr{9-6}; // Rn
    >     let Inst{3-0}   = addr{5-2}; // Rm
    >     let Inst{5-4}   = addr{1-0}; // imm2
    > +
    > +    let DecoderMethod = "DecodeT2LoadShift";
    >   }
    > }
    > 
    > @@ -2994,6 +3005,8 @@
    >   let Inst{13} = target{18};
    >   let Inst{21-16} = target{17-12};
    >   let Inst{10-0} = target{11-1};
    > +
    > +  let DecoderMethod = "DecodeThumb2BCCInstruction";
    > }
    > 
    > // Tail calls. The Darwin version of thumb tail calls uses a t2 branch, so
    > 
    > 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
    > +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug  9 15:55:18 2011
    > @@ -6,584 +6,2328 @@
    > // License. See LICENSE.TXT for details.
    > //
    > //===----------------------------------------------------------------------===//
    > -//
    > -// This file is part of the ARM Disassembler.
    > -// It contains code to implement the public interfaces of ARMDisassembler and
    > -// ThumbDisassembler, both of which are instances of MCDisassembler.
    > -//
    > -//===----------------------------------------------------------------------===//
    > 
    > #define DEBUG_TYPE "arm-disassembler"
    > 
    > #include "ARMDisassembler.h"
    > -#include "ARMDisassemblerCore.h"
    > -
    > -#include "llvm/ADT/OwningPtr.h"
    > +#include "ARM.h"
    > +#include "ARMRegisterInfo.h"
    > +#include "MCTargetDesc/ARMAddressingModes.h"
    > +#include "MCTargetDesc/ARMBaseInfo.h"
    > #include "llvm/MC/EDInstInfo.h"
    > #include "llvm/MC/MCInst.h"
    > +#include "llvm/MC/MCExpr.h"
    > +#include "llvm/MC/MCContext.h"
    > #include "llvm/Target/TargetRegistry.h"
    > #include "llvm/Support/Debug.h"
    > #include "llvm/Support/MemoryObject.h"
    > #include "llvm/Support/ErrorHandling.h"
    > #include "llvm/Support/raw_ostream.h"
    > 
    > -//#define DEBUG(X) do { X; } while (0)
    > -
    > -/// ARMGenDecoderTables.inc - ARMDecoderTables.inc is tblgen'ed from
    > -/// ARMDecoderEmitter.cpp TableGen backend.  It contains:
    > -///
    > -/// o Mappings from opcode to ARM/Thumb instruction format
    > -///
    > -/// o static uint16_t decodeInstruction(uint32_t insn) - the decoding function
    > -/// for an ARM instruction.
    > -///
    > -/// o static uint16_t decodeThumbInstruction(field_t insn) - the decoding
    > -/// function for a Thumb instruction.
    > -///
    > -#include "ARMGenDecoderTables.inc"
    > +// Forward declare these because the autogenerated code will reference them.
    > +// Definitions are further down.
    > +static bool DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +
    > +static bool DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +
    > +static bool DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +
    > +static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst & Inst,
    > +                                                  unsigned Insn,
    > +                                                  uint64_t Adddress,
    > +                                                  const void *Decoder);
    > +static bool DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeBranchImmInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeCoprocessor(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +
    > +
    > +static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Insn,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbSRImm(llvm::MCInst &Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbBCCTargetOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > 
    > +#include "ARMGenDisassemblerTables.inc"
    > +#include "ARMGenInstrInfo.inc"
    > #include "ARMGenEDInfo.inc"
    > 
    > using namespace llvm;
    > 
    > -/// showBitVector - Use the raw_ostream to log a diagnostic message describing
    > -/// the inidividual bits of the instruction.
    > -///
    > -static inline void showBitVector(raw_ostream &os, const uint32_t &insn) {
    > -  // Split the bit position markers into more than one lines to fit 80 columns.
    > -  os << " 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 \n";
    > -  os << "---------------------------------------------------------------"
    > -     << "----------------------------------\n";
    > -  os << '|';
    > -  for (unsigned i = 32; i != 0; --i) {
    > -    if (insn >> (i - 1) & 0x01)
    > -      os << " 1";
    > -    else
    > -      os << " 0";
    > -    os << (i%4 == 1 ? '|' : ':');
    > +static MCDisassembler *createARMDisassembler(const Target &T) {
    > +  return new ARMDisassembler;
    > +}
    > +
    > +static MCDisassembler *createThumbDisassembler(const Target &T) {
    > +  return new ThumbDisassembler;
    > +}
    > +
    > +EDInstInfo *ARMDisassembler::getEDInfo() const {
    > +  return instInfoARM;
    > +}
    > +
    > +EDInstInfo *ThumbDisassembler::getEDInfo() const {
    > +  return instInfoARM;
    > +}
    > +
    > +
    > +bool ARMDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
    > +                                     const MemoryObject &Region,
    > +                                     uint64_t Address,raw_ostream &os) const {
    > +  uint8_t bytes[4];
    > +
    > +  // We want to read exactly 4 bytes of data.
    > +  if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1)
    > +    return false;
    > +
    > +  // Encoded as a small-endian 32-bit word in the stream.
    > +  uint32_t insn = (bytes[3] << 24) |
    > +                  (bytes[2] << 16) |
    > +                  (bytes[1] <<  8) |
    > +                  (bytes[0] <<  0);
    > +
    > +  // Calling the auto-generated decoder function.
    > +  bool result = decodeARMInstruction32(MI, insn, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    return true;
    >   }
    > -  os << '\n';
    > -  // Split the bit position markers into more than one lines to fit 80 columns.
    > -  os << "---------------------------------------------------------------"
    > -     << "----------------------------------\n";
    > -  os << '\n';
    > -}
    > -
    > -/// decodeARMInstruction is a decorator function which tries special cases of
    > -/// instruction matching before calling the auto-generated decoder function.
    > -static unsigned decodeARMInstruction(uint32_t &insn) {
    > -  if (slice(insn, 31, 28) == 15)
    > -    goto AutoGenedDecoder;
    > -
    > -  // Special case processing, if any, goes here....
    > -
    > -  // LLVM combines the offset mode of A8.6.197 & A8.6.198 into STRB.
    > -  // The insufficient encoding information of the combined instruction confuses
    > -  // the decoder wrt BFC/BFI.  Therefore, we try to recover here.
    > -  // For BFC, Inst{27-21} = 0b0111110 & Inst{6-0} = 0b0011111.
    > -  // For BFI, Inst{27-21} = 0b0111110 & Inst{6-4} = 0b001 & Inst{3-0} =! 0b1111.
    > -  if (slice(insn, 27, 21) == 0x3e && slice(insn, 6, 4) == 1) {
    > -    if (slice(insn, 3, 0) == 15)
    > -      return ARM::BFC;
    > -    else
    > -      return ARM::BFI;
    > +
    > +  // Instructions that are shared between ARM and Thumb modes.
    > +  // FIXME: This shouldn't really exist.  It's an artifact of the
    > +  // fact that we fail to encode a few instructions properly for Thumb.
    > +  MI.clear();
    > +  result = decodeCommonInstruction32(MI, insn, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    return true;
    >   }
    > 
    > -  // Ditto for STRBT, which is a super-instruction for A8.6.199 Encodings
    > -  // A1 & A2.
    > -  // As a result, the decoder fails to deocode USAT properly.
    > -  if (slice(insn, 27, 21) == 0x37 && slice(insn, 5, 4) == 1)
    > -    return ARM::USAT;
    > -  // As a result, the decoder fails to deocode UQADD16 properly.
    > -  if (slice(insn, 27, 20) == 0x66 && slice(insn, 7, 4) == 1)
    > -    return ARM::UQADD16;
    > -
    > -  // Ditto for ADDSrs, which is a super-instruction for A8.6.7 & A8.6.8.
    > -  // As a result, the decoder fails to decode UMULL properly.
    > -  if (slice(insn, 27, 21) == 0x04 && slice(insn, 7, 4) == 9) {
    > -    return ARM::UMULL;
    > -  }
    > -
    > -  // Ditto for STR_PRE, which is a super-instruction for A8.6.194 & A8.6.195.
    > -  // As a result, the decoder fails to decode SBFX properly.
    > -  if (slice(insn, 27, 21) == 0x3d && slice(insn, 6, 4) == 5)
    > -    return ARM::SBFX;
    > -
    > -  // And STRB_PRE, which is a super-instruction for A8.6.197 & A8.6.198.
    > -  // As a result, the decoder fails to decode UBFX properly.
    > -  if (slice(insn, 27, 21) == 0x3f && slice(insn, 6, 4) == 5)
    > -    return ARM::UBFX;
    > -
    > -  // Ditto for STRT, which is a super-instruction for A8.6.210 Encoding A1 & A2.
    > -  // As a result, the decoder fails to deocode SSAT properly.
    > -  if (slice(insn, 27, 21) == 0x35 && slice(insn, 5, 4) == 1)
    > -    return ARM::SSAT;
    > -
    > -  // Ditto for RSCrs, which is a super-instruction for A8.6.146 & A8.6.147.
    > -  // As a result, the decoder fails to decode STRHT/LDRHT/LDRSHT/LDRSBT.
    > -  if (slice(insn, 27, 24) == 0) {
    > -    switch (slice(insn, 21, 20)) {
    > -    case 2:
    > -      switch (slice(insn, 7, 4)) {
    > -      case 11:
    > -        return slice(insn, 22, 22) ? ARM::STRHTi : ARM::STRHTr;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 3:
    > -      switch (slice(insn, 7, 4)) {
    > -      case 11:
    > -        return slice(insn, 22, 22) ? ARM::LDRHTi : ARM::LDRHTr;
    > -      case 13:
    > -        return slice(insn, 22, 22) ? ARM::LDRSBTi : ARM::LDRSBTr;
    > -      case 15:
    > -        return slice(insn, 22, 22) ? ARM::LDRSHTi : ARM::LDRSHTr;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    default:
    > -      break;   // fallthrough
    > -    }
    > +  // VFP and NEON instructions, similarly, are shared between ARM
    > +  // and Thumb modes.
    > +  MI.clear();
    > +  result = decodeVFPInstruction32(MI, insn, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    return true;
    >   }
    > 
    > -  // Ditto for SBCrs, which is a super-instruction for A8.6.152 & A8.6.153.
    > -  // As a result, the decoder fails to decode STRH_Post/LDRD_POST/STRD_POST
    > -  // properly.
    > -  if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 0) {
    > -    unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21);
    > -    switch (slice(insn, 7, 4)) {
    > -    case 11:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::STRH;
    > -      case 3: // Pre-indexed
    > -        return ARM::STRH_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::STRH_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 13:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::LDRD;
    > -      case 3: // Pre-indexed
    > -        return ARM::LDRD_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::LDRD_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 15:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::STRD;
    > -      case 3: // Pre-indexed
    > -        return ARM::STRD_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::STRD_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    default:
    > -      break; // fallthrough
    > -    }
    > +  MI.clear();
    > +  result = decodeNEONInstruction32(MI, insn, Address, this);
    > +  if (result) {
    > +    // Add a fake predicate operand, because we share these instruction
    > +    // definitions with Thumb2 where these instructions are predicable.
    > +    if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false;
    > +    Size = 4;
    > +    return true;
    >   }
    > 
    > -  // Ditto for SBCSSrs, which is a super-instruction for A8.6.152 & A8.6.153.
    > -  // As a result, the decoder fails to decode LDRH_POST/LDRSB_POST/LDRSH_POST
    > -  // properly.
    > -  if (slice(insn, 27, 25) == 0 && slice(insn, 20, 20) == 1) {
    > -    unsigned PW = slice(insn, 24, 24) << 1 | slice(insn, 21, 21);
    > -    switch (slice(insn, 7, 4)) {
    > -    case 11:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::LDRH;
    > -      case 3: // Pre-indexed
    > -        return ARM::LDRH_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::LDRH_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 13:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::LDRSB;
    > -      case 3: // Pre-indexed
    > -        return ARM::LDRSB_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::LDRSB_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 15:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::LDRSH;
    > -      case 3: // Pre-indexed
    > -        return ARM::LDRSH_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::LDRSH_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    default:
    > -      break; // fallthrough
    > +  MI.clear();
    > +
    > +  return false;
    > +}
    > +
    > +namespace llvm {
    > +extern MCInstrDesc ARMInsts[];
    > +}
    > +
    > +// Thumb1 instructions don't have explicit S bits.  Rather, they
    > +// implicitly set CPSR.  Since it's not represented in the encoding, the
    > +// auto-generated decoder won't inject the CPSR operand.  We need to fix
    > +// that as a post-pass.
    > +static void AddThumb1SBit(MCInst &MI, bool InITBlock) {
    > +  const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
    > +  MCInst::iterator I = MI.begin();
    > +  for (unsigned i = 0; i < MI.size(); ++i, ++I) {
    > +    if (OpInfo[i].isOptionalDef() && OpInfo[i].RegClass == ARM::CCRRegClassID) {
    > +      MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
    > +      return;
    >     }
    >   }
    > 
    > -AutoGenedDecoder:
    > -  // Calling the auto-generated decoder function.
    > -  return decodeInstruction(insn);
    > +  if (OpInfo[MI.size()].isOptionalDef() &&
    > +      OpInfo[MI.size()].RegClass == ARM::CCRRegClassID)
    > +    MI.insert(MI.end(), MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
    > }
    > 
    > -// Helper function for special case handling of LDR (literal) and friends.
    > -// See, for example, A6.3.7 Load word: Table A6-18 Load word.
    > -// See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode
    > -// before returning it.
    > -static unsigned T2Morph2LoadLiteral(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return Opcode; // Return unmorphed opcode.
    > -
    > -  case ARM::t2LDR_POST:   case ARM::t2LDR_PRE:
    > -  case ARM::t2LDRi12:     case ARM::t2LDRi8:
    > -  case ARM::t2LDRs:       case ARM::t2LDRT:
    > -    return ARM::t2LDRpci;
    > -
    > -  case ARM::t2LDRB_POST:  case ARM::t2LDRB_PRE:
    > -  case ARM::t2LDRBi12:    case ARM::t2LDRBi8:
    > -  case ARM::t2LDRBs:      case ARM::t2LDRBT:
    > -    return ARM::t2LDRBpci;
    > -
    > -  case ARM::t2LDRH_POST:  case ARM::t2LDRH_PRE:
    > -  case ARM::t2LDRHi12:    case ARM::t2LDRHi8:
    > -  case ARM::t2LDRHs:      case ARM::t2LDRHT:
    > -    return ARM::t2LDRHpci;
    > -
    > -  case ARM::t2LDRSB_POST:  case ARM::t2LDRSB_PRE:
    > -  case ARM::t2LDRSBi12:    case ARM::t2LDRSBi8:
    > -  case ARM::t2LDRSBs:      case ARM::t2LDRSBT:
    > -    return ARM::t2LDRSBpci;
    > -
    > -  case ARM::t2LDRSH_POST:  case ARM::t2LDRSH_PRE:
    > -  case ARM::t2LDRSHi12:    case ARM::t2LDRSHi8:
    > -  case ARM::t2LDRSHs:      case ARM::t2LDRSHT:
    > -    return ARM::t2LDRSHpci;
    > -  }
    > -}
    > -
    > -// Helper function for special case handling of PLD (literal) and friends.
    > -// See A8.6.117 T1 & T2 and friends for why we morphed the opcode
    > -// before returning it.
    > -static unsigned T2Morph2PLDLiteral(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return Opcode; // Return unmorphed opcode.
    > -
    > -  case ARM::t2PLDi8:   case ARM::t2PLDs:
    > -  case ARM::t2PLDWi12: case ARM::t2PLDWi8:
    > -  case ARM::t2PLDWs:
    > -    return ARM::t2PLDi12;
    > -
    > -  case ARM::t2PLIi8:   case ARM::t2PLIs:
    > -    return ARM::t2PLIi12;
    > -  }
    > -}
    > -
    > -/// decodeThumbSideEffect is a decorator function which can potentially twiddle
    > -/// the instruction or morph the returned opcode under Thumb2.
    > -///
    > -/// First it checks whether the insn is a NEON or VFP instr; if true, bit
    > -/// twiddling could be performed on insn to turn it into an ARM NEON/VFP
    > -/// equivalent instruction and decodeInstruction is called with the transformed
    > -/// insn.
    > -///
    > -/// Next, there is special handling for Load byte/halfword/word instruction by
    > -/// checking whether Rn=0b1111 and call T2Morph2LoadLiteral() on the decoded
    > -/// Thumb2 instruction.  See comments below for further details.
    > -///
    > -/// Finally, one last check is made to see whether the insn is a NEON/VFP and
    > -/// decodeInstruction(insn) is invoked on the original insn.
    > -///
    > -/// Otherwise, decodeThumbInstruction is called with the original insn.
    > -static unsigned decodeThumbSideEffect(bool IsThumb2, unsigned &insn) {
    > -  if (IsThumb2) {
    > -    uint16_t op1 = slice(insn, 28, 27);
    > -    uint16_t op2 = slice(insn, 26, 20);
    > -
    > -    // A6.3 32-bit Thumb instruction encoding
    > -    // Table A6-9 32-bit Thumb instruction encoding
    > -
    > -    // The coprocessor instructions of interest are transformed to their ARM
    > -    // equivalents.
    > -
    > -    // --------- Transform Begin Marker ---------
    > -    if ((op1 == 1 || op1 == 3) && slice(op2, 6, 4) == 7) {
    > -      // A7.4 Advanced SIMD data-processing instructions
    > -      // U bit of Thumb corresponds to Inst{24} of ARM.
    > -      uint16_t U = slice(op1, 1, 1);
    > -
    > -      // Inst{28-24} of ARM = {1,0,0,1,U};
    > -      uint16_t bits28_24 = 9 << 1 | U;
    > -      DEBUG(showBitVector(errs(), insn));
    > -      setSlice(insn, 28, 24, bits28_24);
    > -      return decodeInstruction(insn);
    > -    }
    > -
    > -    if (op1 == 3 && slice(op2, 6, 4) == 1 && slice(op2, 0, 0) == 0) {
    > -      // A7.7 Advanced SIMD element or structure load/store instructions
    > -      // Inst{27-24} of Thumb = 0b1001
    > -      // Inst{27-24} of ARM   = 0b0100
    > -      DEBUG(showBitVector(errs(), insn));
    > -      setSlice(insn, 27, 24, 4);
    > -      return decodeInstruction(insn);
    > -    }
    > -    // --------- Transform End Marker ---------
    > -
    > -    unsigned unmorphed = decodeThumbInstruction(insn);
    > -
    > -    // See, for example, A6.3.7 Load word: Table A6-18 Load word.
    > -    // See A8.6.57 T3, T4 & A8.6.60 T2 and friends for why we morphed the opcode
    > -    // before returning it to our caller.
    > -    if (op1 == 3 && slice(op2, 6, 5) == 0 && slice(op2, 0, 0) == 1
    > -        && slice(insn, 19, 16) == 15) {
    > -      unsigned morphed = T2Morph2LoadLiteral(unmorphed);
    > -      if (morphed != unmorphed)
    > -        return morphed;
    > -    }
    > -
    > -    // See, for example, A8.6.117 PLD,PLDW (immediate) T1 & T2, and friends for
    > -    // why we morphed the opcode before returning it to our caller.
    > -    if (slice(insn, 31, 25) == 0x7C && slice(insn, 15, 12) == 0xF
    > -        && slice(insn, 22, 22) == 0 && slice(insn, 20, 20) == 1
    > -        && slice(insn, 19, 16) == 15) {
    > -      unsigned morphed = T2Morph2PLDLiteral(unmorphed);
    > -      if (morphed != unmorphed)
    > -        return morphed;
    > -    }
    > -
    > -    // One last check for NEON/VFP instructions.
    > -    if ((op1 == 1 || op1 == 3) && slice(op2, 6, 6) == 1)
    > -      return decodeInstruction(insn);
    > +// Most Thumb instructions don't have explicit predicates in the
    > +// encoding, but rather get their predicates from IT context.  We need
    > +// to fix up the predicate operands using this context information as a
    > +// post-pass.
    > +void ThumbDisassembler::AddThumbPredicate(MCInst &MI) const {
    > +  // A few instructions actually have predicates encoded in them.  Don't
    > +  // try to overwrite it if we're seeing one of those.
    > +  switch (MI.getOpcode()) {
    > +    case ARM::tBcc:
    > +    case ARM::t2Bcc:
    > +      return;
    > +    default:
    > +      break;
    > +  }
    > 
    > -    // Fall through.
    > +  // If we're in an IT block, base the predicate on that.  Otherwise,
    > +  // assume a predicate of AL.
    > +  unsigned CC;
    > +  if (ITBlock.size()) {
    > +    CC = ITBlock.back();
    > +    ITBlock.pop_back();
    > +  } else
    > +    CC = ARMCC::AL;
    > +
    > +  const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
    > +  MCInst::iterator I = MI.begin();
    > +  for (unsigned i = 0; i < MI.size(); ++i, ++I) {
    > +    if (OpInfo[i].isPredicate()) {
    > +      I = MI.insert(I, MCOperand::CreateImm(CC));
    > +      ++I;
    > +      if (CC == ARMCC::AL)
    > +        MI.insert(I, MCOperand::CreateReg(0));
    > +      else
    > +        MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
    > +      return;
    > +    }
    >   }
    > 
    > -  return decodeThumbInstruction(insn);
    > +  MI.insert(MI.end(), MCOperand::CreateImm(CC));
    > +  if (CC == ARMCC::AL)
    > +    MI.insert(MI.end(), MCOperand::CreateReg(0));
    > +  else
    > +    MI.insert(MI.end(), MCOperand::CreateReg(ARM::CPSR));
    > }
    > 
    > -//
    > -// Public interface for the disassembler
    > -//
    > +// Thumb VFP instructions are a special case.  Because we share their
    > +// encodings between ARM and Thumb modes, and they are predicable in ARM
    > +// mode, the auto-generated decoder will give them an (incorrect)
    > +// predicate operand.  We need to rewrite these operands based on the IT
    > +// context as a post-pass.
    > +void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const {
    > +  unsigned CC;
    > +  if (ITBlock.size()) {
    > +    CC = ITBlock.back();
    > +    ITBlock.pop_back();
    > +  } else
    > +    CC = ARMCC::AL;
    > +
    > +  const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
    > +  MCInst::iterator I = MI.begin();
    > +  for (unsigned i = 0; i < MI.size(); ++i, ++I) {
    > +    if (OpInfo[i].isPredicate() ) {
    > +      I->setImm(CC);
    > +      ++I;
    > +      if (CC == ARMCC::AL)
    > +        I->setReg(0);
    > +      else
    > +        I->setReg(ARM::CPSR);
    > +      return;
    > +    }
    > +  }
    > +}
    > 
    > -bool ARMDisassembler::getInstruction(MCInst &MI,
    > -                                     uint64_t &Size,
    > -                                     const MemoryObject &Region,
    > -                                     uint64_t Address,
    > -                                     raw_ostream &os) const {
    > -  // The machine instruction.
    > -  uint32_t insn;
    > +
    > +bool ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
    > +                                       const MemoryObject &Region,
    > +                                       uint64_t Address,raw_ostream &os) const {
    >   uint8_t bytes[4];
    > 
    > +  // We want to read exactly 2 bytes of data.
    > +  if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1)
    > +    return false;
    > +
    > +  uint16_t insn16 = (bytes[1] << 8) | bytes[0];
    > +  bool result = decodeThumbInstruction16(MI, insn16, Address, this);
    > +  if (result) {
    > +    Size = 2;
    > +    bool InITBlock = ITBlock.size();
    > +    AddThumbPredicate(MI);
    > +    AddThumb1SBit(MI, InITBlock);
    > +    return true;
    > +  }
    > +
    > +  MI.clear();
    > +  result = decodeThumb2Instruction16(MI, insn16, Address, this);
    > +  if (result) {
    > +    Size = 2;
    > +    AddThumbPredicate(MI);
    > +
    > +    // If we find an IT instruction, we need to parse its condition
    > +    // code and mask operands so that we can apply them correctly
    > +    // to the subsequent instructions.
    > +    if (MI.getOpcode() == ARM::t2IT) {
    > +      unsigned firstcond = MI.getOperand(0).getImm();
    > +      uint32_t mask = MI.getOperand(1).getImm();
    > +      unsigned zeros = CountTrailingZeros_32(mask);
    > +      mask >>= zeros+1;
    > +
    > +      for (unsigned i = 0; i < 4 - (zeros+1); ++i) {
    > +        if (firstcond ^ (mask & 1))
    > +          ITBlock.push_back(firstcond ^ 1);
    > +        else
    > +          ITBlock.push_back(firstcond);
    > +        mask >>= 1;
    > +      }
    > +      ITBlock.push_back(firstcond);
    > +    }
    > +
    > +    return true;
    > +  }
    > +
    >   // We want to read exactly 4 bytes of data.
    >   if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1)
    >     return false;
    > 
    > -  // Encoded as a small-endian 32-bit word in the stream.
    > -  insn = (bytes[3] << 24) |
    > -         (bytes[2] << 16) |
    > -         (bytes[1] <<  8) |
    > -         (bytes[0] <<  0);
    > +  uint32_t insn32 = (bytes[3] <<  8) |
    > +                    (bytes[2] <<  0) |
    > +                    (bytes[1] << 24) |
    > +                    (bytes[0] << 16);
    > +  MI.clear();
    > +  result = decodeThumbInstruction32(MI, insn32, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    bool InITBlock = ITBlock.size();
    > +    AddThumbPredicate(MI);
    > +    AddThumb1SBit(MI, InITBlock);
    > +    return true;
    > +  }
    > +
    > +  MI.clear();
    > +  result = decodeThumb2Instruction32(MI, insn32, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    AddThumbPredicate(MI);
    > +    return true;
    > +  }
    > +
    > +  MI.clear();
    > +  result = decodeVFPInstruction32(MI, insn32, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    UpdateThumbVFPPredicate(MI);
    > +    return true;
    > +  }
    > +
    > +  MI.clear();
    > +  result = decodeCommonInstruction32(MI, insn32, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    AddThumbPredicate(MI);
    > +    return true;
    > +  }
    > +
    > +  return false;
    > +}
    > 
    > -  unsigned Opcode = decodeARMInstruction(insn);
    > -  ARMFormat Format = ARMFormats[Opcode];
    > -  Size = 4;
    > 
    > -  DEBUG({
    > -      errs() << "\nOpcode=" << Opcode << " Name=" < -             << " Format=" << stringForARMFormat(Format) << '(' << (int)Format
    > -             << ")\n";
    > -      showBitVector(errs(), insn);
    > -    });
    > +extern "C" void LLVMInitializeARMDisassembler() {
    > +  TargetRegistry::RegisterMCDisassembler(TheARMTarget,
    > +                                         createARMDisassembler);
    > +  TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
    > +                                         createThumbDisassembler);
    > +}
    > 
    > -  OwningPtr Builder(CreateMCBuilder(Opcode, Format));
    > -  if (!Builder)
    > +static const unsigned GPRDecoderTable[] = {
    > +  ARM::R0, ARM::R1, ARM::R2, ARM::R3,
    > +  ARM::R4, ARM::R5, ARM::R6, ARM::R7,
    > +  ARM::R8, ARM::R9, ARM::R10, ARM::R11,
    > +  ARM::R12, ARM::SP, ARM::LR, ARM::PC
    > +};
    > +
    > +static bool DecodeGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo > 15)
    >     return false;
    > 
    > -  Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(),
    > -                                              getDisInfoBlock(), getMCContext(),
    > -                                              Address);
    > +  unsigned Register = GPRDecoderTable[RegNo];
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    > +  return true;
    > +}
    > 
    > -  if (!Builder->Build(MI, insn))
    > +static bool DecodetGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo > 7)
    >     return false;
    > +  return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
    > +}
    > +
    > +static bool DecodetcGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Register = 0;
    > +  switch (RegNo) {
    > +    case 0:
    > +      Register = ARM::R0;
    > +      break;
    > +    case 1:
    > +      Register = ARM::R1;
    > +      break;
    > +    case 2:
    > +      Register = ARM::R2;
    > +      break;
    > +    case 3:
    > +      Register = ARM::R3;
    > +      break;
    > +    case 9:
    > +      Register = ARM::R9;
    > +      break;
    > +    case 12:
    > +      Register = ARM::R12;
    > +      break;
    > +    default:
    > +      return false;
    > +    }
    > 
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    >   return true;
    > }
    > 
    > -bool ThumbDisassembler::getInstruction(MCInst &MI,
    > -                                       uint64_t &Size,
    > -                                       const MemoryObject &Region,
    > -                                       uint64_t Address,
    > -                                       raw_ostream &os) const {
    > -  // The Thumb instruction stream is a sequence of halfwords.
    > -
    > -  // This represents the first halfword as well as the machine instruction
    > -  // passed to decodeThumbInstruction().  For 16-bit Thumb instruction, the top
    > -  // halfword of insn is 0x00 0x00; otherwise, the first halfword is moved to
    > -  // the top half followed by the second halfword.
    > -  unsigned insn = 0;
    > -  // Possible second halfword.
    > -  uint16_t insn1 = 0;
    > -
    > -  // A6.1 Thumb instruction set encoding
    > -  //
    > -  // If bits [15:11] of the halfword being decoded take any of the following
    > -  // values, the halfword is the first halfword of a 32-bit instruction:
    > -  // o 0b11101
    > -  // o 0b11110
    > -  // o 0b11111.
    > -  //
    > -  // Otherwise, the halfword is a 16-bit instruction.
    > +static bool DecoderGPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo == 13 || RegNo == 15) return false;
    > +  return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
    > +}
    > 
    > -  // Read 2 bytes of data first.
    > -  uint8_t bytes[2];
    > -  if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1)
    > +static const unsigned SPRDecoderTable[] = { 
    > +     ARM::S0,  ARM::S1,  ARM::S2,  ARM::S3,
    > +     ARM::S4,  ARM::S5,  ARM::S6,  ARM::S7,
    > +     ARM::S8,  ARM::S9, ARM::S10, ARM::S11,
    > +    ARM::S12, ARM::S13, ARM::S14, ARM::S15,
    > +    ARM::S16, ARM::S17, ARM::S18, ARM::S19,
    > +    ARM::S20, ARM::S21, ARM::S22, ARM::S23,
    > +    ARM::S24, ARM::S25, ARM::S26, ARM::S27,
    > +    ARM::S28, ARM::S29, ARM::S30, ARM::S31
    > +};
    > +
    > +static bool DecodeSPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo > 31)
    >     return false;
    > 
    > -  // Encoded as a small-endian 16-bit halfword in the stream.
    > -  insn = (bytes[1] << 8) | bytes[0];
    > -  unsigned bits15_11 = slice(insn, 15, 11);
    > -  bool IsThumb2 = false;
    > -
    > -  // 32-bit instructions if the bits [15:11] of the halfword matches
    > -  // { 0b11101 /* 0x1D */, 0b11110 /* 0x1E */, ob11111 /* 0x1F */ }.
    > -  if (bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F) {
    > -    IsThumb2 = true;
    > -    if (Region.readBytes(Address + 2, 2, (uint8_t*)bytes, NULL) == -1)
    > -      return false;
    > -    // Encoded as a small-endian 16-bit halfword in the stream.
    > -    insn1 = (bytes[1] << 8) | bytes[0];
    > -    insn = (insn << 16 | insn1);
    > -  }
    > +  unsigned Register = SPRDecoderTable[RegNo];
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    > +  return true;
    > +}
    > 
    > -  // The insn could potentially be bit-twiddled in order to be decoded as an ARM
    > -  // NEON/VFP opcode.  In such case, the modified insn is later disassembled as
    > -  // an ARM NEON/VFP instruction.
    > -  //
    > -  // This is a short term solution for lack of encoding bits specified for the
    > -  // Thumb2 NEON/VFP instructions.  The long term solution could be adding some
    > -  // infrastructure to have each instruction support more than one encodings.
    > -  // Which encoding is used would be based on which subtarget the compiler/
    > -  // disassembler is working with at the time.  This would allow the sharing of
    > -  // the NEON patterns between ARM and Thumb2, as well as potential greater
    > -  // sharing between the regular ARM instructions and the 32-bit wide Thumb2
    > -  // instructions as well.
    > -  unsigned Opcode = decodeThumbSideEffect(IsThumb2, insn);
    > +static const unsigned DPRDecoderTable[] = { 
    > +     ARM::D0,  ARM::D1,  ARM::D2,  ARM::D3,
    > +     ARM::D4,  ARM::D5,  ARM::D6,  ARM::D7,
    > +     ARM::D8,  ARM::D9, ARM::D10, ARM::D11,
    > +    ARM::D12, ARM::D13, ARM::D14, ARM::D15,
    > +    ARM::D16, ARM::D17, ARM::D18, ARM::D19,
    > +    ARM::D20, ARM::D21, ARM::D22, ARM::D23,
    > +    ARM::D24, ARM::D25, ARM::D26, ARM::D27,
    > +    ARM::D28, ARM::D29, ARM::D30, ARM::D31
    > +};
    > +
    > +static bool DecodeDPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo > 31)
    > +    return false;
    > 
    > -  ARMFormat Format = ARMFormats[Opcode];
    > -  Size = IsThumb2 ? 4 : 2;
    > +  unsigned Register = DPRDecoderTable[RegNo];
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    > +  return true;
    > +}
    > 
    > -  DEBUG({
    > -      errs() << "Opcode=" << Opcode << " Name=" << ARMUtils::OpcodeName(Opcode)
    > -             << " Format=" << stringForARMFormat(Format) << '(' << (int)Format
    > -             << ")\n";
    > -      showBitVector(errs(), insn);
    > -    });
    > +static bool DecodeDPR_8RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo > 7)
    > +    return false;
    > +  return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
    > +}
    > 
    > -  OwningPtr Builder(CreateMCBuilder(Opcode, Format));
    > -  if (!Builder)
    > +static bool DecodeDPR_VFP2RegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo > 15)
    >     return false;
    > +  return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
    > +}
    > 
    > -  Builder->SetSession(const_cast(&SO));
    > +static const unsigned QPRDecoderTable[] = { 
    > +     ARM::Q0,  ARM::Q1,  ARM::Q2,  ARM::Q3,
    > +     ARM::Q4,  ARM::Q5,  ARM::Q6,  ARM::Q7,
    > +     ARM::Q8,  ARM::Q9, ARM::Q10, ARM::Q11,
    > +    ARM::Q12, ARM::Q13, ARM::Q14, ARM::Q15
    > +};
    > 
    > -  Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(),
    > -                                              getDisInfoBlock(), getMCContext(),
    > -                                              Address);
    > 
    > -  if (!Builder->Build(MI, insn))
    > +static bool DecodeQPRRegisterClass(llvm::MCInst &Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo > 31)
    >     return false;
    > +  RegNo >>= 1;
    > 
    > +  unsigned Register = QPRDecoderTable[RegNo];
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    >   return true;
    > }
    > 
    > -// A8.6.50
    > -// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
    > -static unsigned short CountITSize(unsigned ITMask) {
    > -  // First count the trailing zeros of the IT mask.
    > -  unsigned TZ = CountTrailingZeros_32(ITMask);
    > -  if (TZ > 3) {
    > -    DEBUG(errs() << "Encoding error: IT Mask '0000'");
    > -    return 0;
    > -  }
    > -  return (4 - TZ);
    > +static bool DecodePredicateOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  if (Val == 0xF) return false;
    > +  Inst.addOperand(MCOperand::CreateImm(Val));
    > +  if (Val == ARMCC::AL) {
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  } else
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
    > +  return true;
    > }
    > 
    > -/// Init ITState.  Note that at least one bit is always 1 in mask.
    > -bool Session::InitIT(unsigned short bits7_0) {
    > -  ITCounter = CountITSize(slice(bits7_0, 3, 0));
    > -  if (ITCounter == 0)
    > -    return false;
    > +static bool DecodeCCOutOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  if (Val)
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
    > +  else
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  return true;
    > +}
    > 
    > -  // A8.6.50 IT
    > -  unsigned short FirstCond = slice(bits7_0, 7, 4);
    > -  if (FirstCond == 0xF) {
    > -    DEBUG(errs() << "Encoding error: IT FirstCond '1111'");
    > -    return false;
    > +static bool DecodeSOImmOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  uint32_t imm = Val & 0xFF;
    > +  uint32_t rot = (Val & 0xF00) >> 7;
    > +  uint32_t rot_imm = (imm >> rot) | (imm << (32-rot));
    > +  Inst.addOperand(MCOperand::CreateImm(rot_imm));
    > +  return true;
    > +}
    > +
    > +static bool DecodeBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Val <<= 2;
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(Val)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeSORegImmOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +
    > +  unsigned Rm = fieldFromInstruction32(Val, 0, 4);
    > +  unsigned type = fieldFromInstruction32(Val, 5, 2);
    > +  unsigned imm = fieldFromInstruction32(Val, 7, 5);
    > +
    > +  // Register-immediate
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
    > +  switch (type) {
    > +    case 0:
    > +      Shift = ARM_AM::lsl;
    > +      break;
    > +    case 1:
    > +      Shift = ARM_AM::lsr;
    > +      break;
    > +    case 2:
    > +      Shift = ARM_AM::asr;
    > +      break;
    > +    case 3:
    > +      Shift = ARM_AM::ror;
    > +      break;
    >   }
    > -  if (FirstCond == 0xE && ITCounter != 1) {
    > -    DEBUG(errs() << "Encoding error: IT FirstCond '1110' && Mask != '1000'");
    > -    return false;
    > +
    > +  if (Shift == ARM_AM::ror && imm == 0)
    > +    Shift = ARM_AM::rrx;
    > +
    > +  unsigned Op = Shift | (imm << 3);
    > +  Inst.addOperand(MCOperand::CreateImm(Op));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeSORegRegOperand(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +
    > +  unsigned Rm = fieldFromInstruction32(Val, 0, 4);
    > +  unsigned type = fieldFromInstruction32(Val, 5, 2);
    > +  unsigned Rs = fieldFromInstruction32(Val, 8, 4);
    > +
    > +  // Register-register
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rs, Address, Decoder);
    > +
    > +  ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
    > +  switch (type) {
    > +    case 0:
    > +      Shift = ARM_AM::lsl;
    > +      break;
    > +    case 1:
    > +      Shift = ARM_AM::lsr;
    > +      break;
    > +    case 2:
    > +      Shift = ARM_AM::asr;
    > +      break;
    > +    case 3:
    > +      Shift = ARM_AM::ror;
    > +      break;
    >   }
    > 
    > -  ITState = bits7_0;
    > +  Inst.addOperand(MCOperand::CreateImm(Shift));
    > 
    >   return true;
    > }
    > 
    > -/// Update ITState if necessary.
    > -void Session::UpdateIT() {
    > -  assert(ITCounter);
    > -  --ITCounter;
    > -  if (ITCounter == 0)
    > -    ITState = 0;
    > -  else {
    > -    unsigned short NewITState4_0 = slice(ITState, 4, 0) << 1;
    > -    setSlice(ITState, 4, 0, NewITState4_0);
    > +static bool DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  for (unsigned i = 0; i < 16; ++i) {
    > +    if (Val & (1 << i))
    > +      DecodeGPRRegisterClass(Inst, i, Address, Decoder);
    >   }
    > +
    > +  return true;
    > }
    > 
    > -static MCDisassembler *createARMDisassembler(const Target &T) {
    > -  return new ARMDisassembler;
    > +static bool DecodeSPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Vd = fieldFromInstruction32(Val, 8, 4);
    > +  unsigned regs = Val & 0xFF;
    > +
    > +  DecodeSPRRegisterClass(Inst, Vd, Address, Decoder);
    > +  for (unsigned i = 0; i < (regs - 1); ++i)
    > +    DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder);
    > +
    > +  return true;
    > }
    > 
    > -static MCDisassembler *createThumbDisassembler(const Target &T) {
    > -  return new ThumbDisassembler;
    > +static bool DecodeDPRRegListOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Vd = fieldFromInstruction32(Val, 8, 4);
    > +  unsigned regs = (Val & 0xFF) / 2;
    > +
    > +  DecodeDPRRegisterClass(Inst, Vd, Address, Decoder);
    > +  for (unsigned i = 0; i < (regs - 1); ++i)
    > +    DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder);
    > +
    > +  return true;
    > }
    > 
    > -extern "C" void LLVMInitializeARMDisassembler() {
    > -  // Register the disassembler.
    > -  TargetRegistry::RegisterMCDisassembler(TheARMTarget,
    > -                                         createARMDisassembler);
    > -  TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
    > -                                         createThumbDisassembler);
    > +static bool DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                      uint64_t Address, const void *Decoder) {
    > +  unsigned msb = fieldFromInstruction32(Val, 5, 5);
    > +  unsigned lsb = fieldFromInstruction32(Val, 0, 5);
    > +  uint32_t msb_mask = (1 << (msb+1)) - 1;
    > +  uint32_t lsb_mask = (1 << lsb) - 1;
    > +  Inst.addOperand(MCOperand::CreateImm(~(msb_mask ^ lsb_mask)));
    > +  return true;
    > }
    > 
    > -EDInstInfo *ARMDisassembler::getEDInfo() const {
    > -  return instInfoARM;
    > +static bool DecodeCopMemInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned CRd = fieldFromInstruction32(Insn, 12, 4);
    > +  unsigned coproc = fieldFromInstruction32(Insn, 8, 4);
    > +  unsigned imm = fieldFromInstruction32(Insn, 0, 8);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned U = fieldFromInstruction32(Insn, 23, 1);
    > +
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDC_OFFSET:
    > +    case ARM::LDC_PRE:
    > +    case ARM::LDC_POST:
    > +    case ARM::LDC_OPTION:
    > +    case ARM::LDCL_OFFSET:
    > +    case ARM::LDCL_PRE:
    > +    case ARM::LDCL_POST:
    > +    case ARM::LDCL_OPTION:
    > +    case ARM::STC_OFFSET:
    > +    case ARM::STC_PRE:
    > +    case ARM::STC_POST:
    > +    case ARM::STC_OPTION:
    > +    case ARM::STCL_OFFSET:
    > +    case ARM::STCL_PRE:
    > +    case ARM::STCL_POST:
    > +    case ARM::STCL_OPTION:
    > +      if (coproc == 0xA || coproc == 0xB)
    > +        return false;
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(coproc));
    > +  Inst.addOperand(MCOperand::CreateImm(CRd));
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDC_OPTION:
    > +    case ARM::LDCL_OPTION:
    > +    case ARM::LDC2_OPTION:
    > +    case ARM::LDC2L_OPTION:
    > +    case ARM::STC_OPTION:
    > +    case ARM::STCL_OPTION:
    > +    case ARM::STC2_OPTION:
    > +    case ARM::STC2L_OPTION:
    > +    case ARM::LDCL_POST:
    > +    case ARM::STCL_POST:
    > +      break;
    > +    default:
    > +      Inst.addOperand(MCOperand::CreateReg(0));
    > +      break;
    > +  }
    > +
    > +  unsigned P = fieldFromInstruction32(Insn, 24, 1);
    > +  unsigned W = fieldFromInstruction32(Insn, 21, 1);
    > +
    > +  bool writeback = (P == 0) || (W == 1);
    > +  unsigned idx_mode = 0;
    > +  if (P && writeback)
    > +    idx_mode = ARMII::IndexModePre;
    > +  else if (!P && writeback)
    > +    idx_mode = ARMII::IndexModePost;
    > +
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDCL_POST:
    > +    case ARM::STCL_POST:
    > +      imm |= U << 8;
    > +    case ARM::LDC_OPTION:
    > +    case ARM::LDCL_OPTION:
    > +    case ARM::LDC2_OPTION:
    > +    case ARM::LDC2L_OPTION:
    > +    case ARM::STC_OPTION:
    > +    case ARM::STCL_OPTION:
    > +    case ARM::STC2_OPTION:
    > +    case ARM::STC2L_OPTION:
    > +      Inst.addOperand(MCOperand::CreateImm(imm));
    > +      break;
    > +    default:
    > +      if (U)
    > +        Inst.addOperand(MCOperand::CreateImm(
    > +            ARM_AM::getAM2Opc(ARM_AM::add, imm, ARM_AM::lsl, idx_mode)));
    > +      else
    > +        Inst.addOperand(MCOperand::CreateImm(
    > +            ARM_AM::getAM2Opc(ARM_AM::sub, imm, ARM_AM::lsl, idx_mode)));
    > +      break;
    > +  }
    > +
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDC_OFFSET:
    > +    case ARM::LDC_PRE:
    > +    case ARM::LDC_POST:
    > +    case ARM::LDC_OPTION:
    > +    case ARM::LDCL_OFFSET:
    > +    case ARM::LDCL_PRE:
    > +    case ARM::LDCL_POST:
    > +    case ARM::LDCL_OPTION:
    > +    case ARM::STC_OFFSET:
    > +    case ARM::STC_PRE:
    > +    case ARM::STC_POST:
    > +    case ARM::STC_OPTION:
    > +    case ARM::STCL_OFFSET:
    > +    case ARM::STCL_PRE:
    > +    case ARM::STCL_POST:
    > +    case ARM::STCL_OPTION:
    > +      if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  return true;
    > }
    > 
    > -EDInstInfo *ThumbDisassembler::getEDInfo() const {
    > -  return instInfoARM;
    > +static bool DecodeAddrMode2IdxInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned imm = fieldFromInstruction32(Insn, 0, 12);
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned reg = fieldFromInstruction32(Insn, 25, 1);
    > +  unsigned P = fieldFromInstruction32(Insn, 24, 1);
    > +  unsigned W = fieldFromInstruction32(Insn, 21, 1);
    > +
    > +  // On stores, the writeback operand precedes Rt.
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::STR_POST_IMM:
    > +    case ARM::STR_POST_REG:
    > +    case ARM::STRTr:
    > +    case ARM::STRTi:
    > +    case ARM::STRBTr:
    > +    case ARM::STRBTi:
    > +      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
    > +
    > +  // On loads, the writeback operand comes after Rt.
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDR_POST_IMM:
    > +    case ARM::LDR_POST_REG:
    > +    case ARM::LDR_PRE:
    > +    case ARM::LDRBT_POST_REG:
    > +    case ARM::LDRBT_POST_IMM:
    > +    case ARM::LDRTr:
    > +    case ARM::LDRTi:
    > +      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  ARM_AM::AddrOpc Op = ARM_AM::add;
    > +  if (!fieldFromInstruction32(Insn, 23, 1))
    > +    Op = ARM_AM::sub;
    > +
    > +  bool writeback = (P == 0) || (W == 1);
    > +  unsigned idx_mode = 0;
    > +  if (P && writeback)
    > +    idx_mode = ARMII::IndexModePre;
    > +  else if (!P && writeback)
    > +    idx_mode = ARMII::IndexModePost;
    > +
    > +  if (reg) {
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +    ARM_AM::ShiftOpc Opc = ARM_AM::lsl;
    > +    switch( fieldFromInstruction32(Insn, 5, 2)) {
    > +      case 0:
    > +        Opc = ARM_AM::lsl;
    > +        break;
    > +      case 1:
    > +        Opc = ARM_AM::lsr;
    > +        break;
    > +      case 2:
    > +        Opc = ARM_AM::asr;
    > +        break;
    > +      case 3:
    > +        Opc = ARM_AM::ror;
    > +        break;
    > +      default:
    > +        return false;
    > +    }
    > +    unsigned amt = fieldFromInstruction32(Insn, 7, 5);
    > +    unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode);
    > +
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +  } else {
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +    unsigned tmp = ARM_AM::getAM2Opc(Op, imm, ARM_AM::lsl, idx_mode);
    > +    Inst.addOperand(MCOperand::CreateImm(tmp));
    > +  }
    > +
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeSORegMemOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 13, 4);
    > +  unsigned Rm = fieldFromInstruction32(Val,  0, 4);
    > +  unsigned type = fieldFromInstruction32(Val, 5, 2);
    > +  unsigned imm = fieldFromInstruction32(Val, 7, 5);
    > +  unsigned U = fieldFromInstruction32(Val, 12, 1);
    > +
    > +  ARM_AM::ShiftOpc ShOp;
    > +  switch (type) {
    > +    case 0:
    > +      ShOp = ARM_AM::lsl;
    > +      break;
    > +    case 1:
    > +      ShOp = ARM_AM::lsr;
    > +      break;
    > +    case 2:
    > +      ShOp = ARM_AM::asr;
    > +      break;
    > +    case 3:
    > +      ShOp = ARM_AM::ror;
    > +      break;
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  unsigned shift;
    > +  if (U)
    > +    shift = ARM_AM::getAM2Opc(ARM_AM::add, imm, ShOp);
    > +  else
    > +    shift = ARM_AM::getAM2Opc(ARM_AM::sub, imm, ShOp);
    > +  Inst.addOperand(MCOperand::CreateImm(shift));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode3Instruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned type = fieldFromInstruction32(Insn, 22, 1);
    > +  unsigned imm = fieldFromInstruction32(Insn, 8, 4);
    > +  unsigned U = ((~fieldFromInstruction32(Insn, 23, 1)) & 1) << 8;
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned W = fieldFromInstruction32(Insn, 21, 1);
    > +  unsigned P = fieldFromInstruction32(Insn, 24, 1);
    > +
    > +  bool writeback = (W == 1) | (P == 0);
    > +  if (writeback) { // Writeback
    > +    if (P)
    > +      U |= ARMII::IndexModePre << 9;
    > +    else
    > +      U |= ARMII::IndexModePost << 9;
    > +
    > +    // On stores, the writeback operand precedes Rt.
    > +    switch (Inst.getOpcode()) {
    > +    case ARM::STRD:
    > +    case ARM::STRD_PRE:
    > +    case ARM::STRD_POST:
    > +      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +    }
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::STRD:
    > +    case ARM::STRD_PRE:
    > +    case ARM::STRD_POST:
    > +    case ARM::LDRD:
    > +    case ARM::LDRD_PRE:
    > +    case ARM::LDRD_POST:
    > +      DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  if (writeback) {
    > +    // On loads, the writeback operand comes after Rt.
    > +    switch (Inst.getOpcode()) {
    > +    case ARM::LDRD:
    > +    case ARM::LDRD_PRE:
    > +    case ARM::LDRD_POST:
    > +    case ARM::LDRHTr:
    > +    case ARM::LDRSBTr:
    > +      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +    }
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  if (type) {
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +    Inst.addOperand(MCOperand::CreateImm(U | (imm << 4) | Rm));
    > +  } else {
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +    Inst.addOperand(MCOperand::CreateImm(U));
    > +  }
    > +
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeRFEInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned mode = fieldFromInstruction32(Insn, 23, 2);
    > +
    > +  switch (mode) {
    > +    case 0:
    > +      mode = ARM_AM::da;
    > +      break;
    > +    case 1:
    > +      mode = ARM_AM::ia;
    > +      break;
    > +    case 2:
    > +      mode = ARM_AM::db;
    > +      break;
    > +    case 3:
    > +      mode = ARM_AM::ib;
    > +      break;
    > +  }
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(mode));
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst &Inst,
    > +                                  unsigned Insn,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned reglist = fieldFromInstruction32(Insn, 0, 16);
    > +
    > +  if (pred == 0xF) {
    > +    switch (Inst.getOpcode()) {
    > +      case ARM::STMDA:
    > +        Inst.setOpcode(ARM::RFEDA);
    > +        break;
    > +      case ARM::STMDA_UPD:
    > +        Inst.setOpcode(ARM::RFEDA_UPD);
    > +        break;
    > +      case ARM::STMDB:
    > +        Inst.setOpcode(ARM::RFEDB);
    > +        break;
    > +      case ARM::STMDB_UPD:
    > +        Inst.setOpcode(ARM::RFEDB_UPD);
    > +        break;
    > +      case ARM::STMIA:
    > +        Inst.setOpcode(ARM::RFEIA);
    > +        break;
    > +      case ARM::STMIA_UPD:
    > +        Inst.setOpcode(ARM::RFEIA_UPD);
    > +        break;
    > +      case ARM::STMIB:
    > +        Inst.setOpcode(ARM::RFEIB);
    > +        break;
    > +      case ARM::STMIB_UPD:
    > +        Inst.setOpcode(ARM::RFEIB_UPD);
    > +        break;
    > +
    > +    }
    > +    return DecodeRFEInstruction(Inst, Insn, Address, Decoder);
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); // Tied
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +  DecodeRegListOperand(Inst, reglist, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeCPSInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned imod = fieldFromInstruction32(Insn, 18, 2);
    > +  unsigned M = fieldFromInstruction32(Insn, 17, 1);
    > +  unsigned iflags = fieldFromInstruction32(Insn, 6, 3);
    > +  unsigned mode = fieldFromInstruction32(Insn, 0, 5);
    > +
    > +  if (M && mode && imod && iflags) {
    > +    Inst.setOpcode(ARM::CPS3p);
    > +    Inst.addOperand(MCOperand::CreateImm(imod));
    > +    Inst.addOperand(MCOperand::CreateImm(iflags));
    > +    Inst.addOperand(MCOperand::CreateImm(mode));
    > +    return true;
    > +  } else if (!mode && !M) {
    > +    Inst.setOpcode(ARM::CPS2p);
    > +    Inst.addOperand(MCOperand::CreateImm(imod));
    > +    Inst.addOperand(MCOperand::CreateImm(iflags));
    > +    return true;
    > +  } else if (!imod && !iflags && M) {
    > +    Inst.setOpcode(ARM::CPS1p);
    > +    Inst.addOperand(MCOperand::CreateImm(mode));
    > +    return true;
    > +  }
    > +
    > +  return false;
    > +}
    > +
    > +static bool DecodeSMLAInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 8, 4);
    > +  unsigned Ra = fieldFromInstruction32(Insn, 12, 4);
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +
    > +  if (pred == 0xF)
    > +    return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Ra, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrModeImm12Operand(llvm::MCInst &Inst, unsigned Val,
    > +                           uint64_t Address, const void *Decoder) {
    > +  unsigned add = fieldFromInstruction32(Val, 12, 1);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 12);
    > +  unsigned Rn = fieldFromInstruction32(Val, 13, 4);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  if (!add) imm *= -1;
    > +  if (imm == 0 && !add) imm = INT32_MIN;
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode5Operand(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 9, 4);
    > +  unsigned U = fieldFromInstruction32(Val, 8, 1);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 8);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  if (U)
    > +    Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, imm)));
    > +  else
    > +    Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub, imm)));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode7Operand(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  return DecodeGPRRegisterClass(Inst, Val, Address, Decoder);
    > +}
    > +
    > +static bool DecodeBranchImmInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned imm = fieldFromInstruction32(Insn, 0, 24) << 2;
    > +
    > +  if (pred == 0xF) {
    > +    Inst.setOpcode(ARM::BLXi);
    > +    imm |= fieldFromInstruction32(Insn, 24, 1) << 1;
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +    return true;
    > +  }
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +
    > +  return true;
    > +}
    > +
    > +
    > +static bool DecodeVCVTImmOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(64 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode6Operand(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rm = fieldFromInstruction32(Val, 0, 4);
    > +  unsigned align = fieldFromInstruction32(Val, 4, 2);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  if (!align)
    > +    Inst.addOperand(MCOperand::CreateImm(0));
    > +  else
    > +    Inst.addOperand(MCOperand::CreateImm(4 << align));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned wb = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  Rn |= fieldFromInstruction32(Insn, 4, 2) << 4;
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +
    > +  // First output register
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +
    > +  // Second output register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VLD1q8:
    > +    case ARM::VLD1q16:
    > +    case ARM::VLD1q32:
    > +    case ARM::VLD1q64:
    > +    case ARM::VLD1q8_UPD:
    > +    case ARM::VLD1q16_UPD:
    > +    case ARM::VLD1q32_UPD:
    > +    case ARM::VLD1q64_UPD:
    > +    case ARM::VLD1d8T:
    > +    case ARM::VLD1d16T:
    > +    case ARM::VLD1d32T:
    > +    case ARM::VLD1d64T:
    > +    case ARM::VLD1d8T_UPD:
    > +    case ARM::VLD1d16T_UPD:
    > +    case ARM::VLD1d32T_UPD:
    > +    case ARM::VLD1d64T_UPD:
    > +    case ARM::VLD1d8Q:
    > +    case ARM::VLD1d16Q:
    > +    case ARM::VLD1d32Q:
    > +    case ARM::VLD1d64Q:
    > +    case ARM::VLD1d8Q_UPD:
    > +    case ARM::VLD1d16Q_UPD:
    > +    case ARM::VLD1d32Q_UPD:
    > +    case ARM::VLD1d64Q_UPD:
    > +    case ARM::VLD2d8:
    > +    case ARM::VLD2d16:
    > +    case ARM::VLD2d32:
    > +    case ARM::VLD2d8_UPD:
    > +    case ARM::VLD2d16_UPD:
    > +    case ARM::VLD2d32_UPD:
    > +    case ARM::VLD2q8:
    > +    case ARM::VLD2q16:
    > +    case ARM::VLD2q32:
    > +    case ARM::VLD2q8_UPD:
    > +    case ARM::VLD2q16_UPD:
    > +    case ARM::VLD2q32_UPD:
    > +    case ARM::VLD3d8:
    > +    case ARM::VLD3d16:
    > +    case ARM::VLD3d32:
    > +    case ARM::VLD3d8_UPD:
    > +    case ARM::VLD3d16_UPD:
    > +    case ARM::VLD3d32_UPD:
    > +    case ARM::VLD4d8:
    > +    case ARM::VLD4d16:
    > +    case ARM::VLD4d32:
    > +    case ARM::VLD4d8_UPD:
    > +    case ARM::VLD4d16_UPD:
    > +    case ARM::VLD4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VLD2b8:
    > +    case ARM::VLD2b16:
    > +    case ARM::VLD2b32:
    > +    case ARM::VLD2b8_UPD:
    > +    case ARM::VLD2b16_UPD:
    > +    case ARM::VLD2b32_UPD:
    > +    case ARM::VLD3q8:
    > +    case ARM::VLD3q16:
    > +    case ARM::VLD3q32:
    > +    case ARM::VLD3q8_UPD:
    > +    case ARM::VLD3q16_UPD:
    > +    case ARM::VLD3q32_UPD:
    > +    case ARM::VLD4q8:
    > +    case ARM::VLD4q16:
    > +    case ARM::VLD4q32:
    > +    case ARM::VLD4q8_UPD:
    > +    case ARM::VLD4q16_UPD:
    > +    case ARM::VLD4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Third output register
    > +  switch(Inst.getOpcode()) {
    > +    case ARM::VLD1d8T:
    > +    case ARM::VLD1d16T:
    > +    case ARM::VLD1d32T:
    > +    case ARM::VLD1d64T:
    > +    case ARM::VLD1d8T_UPD:
    > +    case ARM::VLD1d16T_UPD:
    > +    case ARM::VLD1d32T_UPD:
    > +    case ARM::VLD1d64T_UPD:
    > +    case ARM::VLD1d8Q:
    > +    case ARM::VLD1d16Q:
    > +    case ARM::VLD1d32Q:
    > +    case ARM::VLD1d64Q:
    > +    case ARM::VLD1d8Q_UPD:
    > +    case ARM::VLD1d16Q_UPD:
    > +    case ARM::VLD1d32Q_UPD:
    > +    case ARM::VLD1d64Q_UPD:
    > +    case ARM::VLD2q8:
    > +    case ARM::VLD2q16:
    > +    case ARM::VLD2q32:
    > +    case ARM::VLD2q8_UPD:
    > +    case ARM::VLD2q16_UPD:
    > +    case ARM::VLD2q32_UPD:
    > +    case ARM::VLD3d8:
    > +    case ARM::VLD3d16:
    > +    case ARM::VLD3d32:
    > +    case ARM::VLD3d8_UPD:
    > +    case ARM::VLD3d16_UPD:
    > +    case ARM::VLD3d32_UPD:
    > +    case ARM::VLD4d8:
    > +    case ARM::VLD4d16:
    > +    case ARM::VLD4d32:
    > +    case ARM::VLD4d8_UPD:
    > +    case ARM::VLD4d16_UPD:
    > +    case ARM::VLD4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VLD3q8:
    > +    case ARM::VLD3q16:
    > +    case ARM::VLD3q32:
    > +    case ARM::VLD3q8_UPD:
    > +    case ARM::VLD3q16_UPD:
    > +    case ARM::VLD3q32_UPD:
    > +    case ARM::VLD4q8:
    > +    case ARM::VLD4q16:
    > +    case ARM::VLD4q32:
    > +    case ARM::VLD4q8_UPD:
    > +    case ARM::VLD4q16_UPD:
    > +    case ARM::VLD4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Fourth output register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VLD1d8Q:
    > +    case ARM::VLD1d16Q:
    > +    case ARM::VLD1d32Q:
    > +    case ARM::VLD1d64Q:
    > +    case ARM::VLD1d8Q_UPD:
    > +    case ARM::VLD1d16Q_UPD:
    > +    case ARM::VLD1d32Q_UPD:
    > +    case ARM::VLD1d64Q_UPD:
    > +    case ARM::VLD2q8:
    > +    case ARM::VLD2q16:
    > +    case ARM::VLD2q32:
    > +    case ARM::VLD2q8_UPD:
    > +    case ARM::VLD2q16_UPD:
    > +    case ARM::VLD2q32_UPD:
    > +    case ARM::VLD4d8:
    > +    case ARM::VLD4d16:
    > +    case ARM::VLD4d32:
    > +    case ARM::VLD4d8_UPD:
    > +    case ARM::VLD4d16_UPD:
    > +    case ARM::VLD4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VLD4q8:
    > +    case ARM::VLD4q16:
    > +    case ARM::VLD4q32:
    > +    case ARM::VLD4q8_UPD:
    > +    case ARM::VLD4q16_UPD:
    > +    case ARM::VLD4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Writeback operand
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VLD1d8_UPD:
    > +    case ARM::VLD1d16_UPD:
    > +    case ARM::VLD1d32_UPD:
    > +    case ARM::VLD1d64_UPD:
    > +    case ARM::VLD1q8_UPD:
    > +    case ARM::VLD1q16_UPD:
    > +    case ARM::VLD1q32_UPD:
    > +    case ARM::VLD1q64_UPD:
    > +    case ARM::VLD1d8T_UPD:
    > +    case ARM::VLD1d16T_UPD:
    > +    case ARM::VLD1d32T_UPD:
    > +    case ARM::VLD1d64T_UPD:
    > +    case ARM::VLD1d8Q_UPD:
    > +    case ARM::VLD1d16Q_UPD:
    > +    case ARM::VLD1d32Q_UPD:
    > +    case ARM::VLD1d64Q_UPD:
    > +    case ARM::VLD2d8_UPD:
    > +    case ARM::VLD2d16_UPD:
    > +    case ARM::VLD2d32_UPD:
    > +    case ARM::VLD2q8_UPD:
    > +    case ARM::VLD2q16_UPD:
    > +    case ARM::VLD2q32_UPD:
    > +    case ARM::VLD2b8_UPD:
    > +    case ARM::VLD2b16_UPD:
    > +    case ARM::VLD2b32_UPD:
    > +    case ARM::VLD3d8_UPD:
    > +    case ARM::VLD3d16_UPD:
    > +    case ARM::VLD3d32_UPD:
    > +    case ARM::VLD3q8_UPD:
    > +    case ARM::VLD3q16_UPD:
    > +    case ARM::VLD3q32_UPD:
    > +    case ARM::VLD4d8_UPD:
    > +    case ARM::VLD4d16_UPD:
    > +    case ARM::VLD4d32_UPD:
    > +    case ARM::VLD4q8_UPD:
    > +    case ARM::VLD4q16_UPD:
    > +    case ARM::VLD4q32_UPD:
    > +      DecodeGPRRegisterClass(Inst, wb, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // AddrMode6 Base (register+alignment)
    > +  DecodeAddrMode6Operand(Inst, Rn, Address, Decoder);
    > +
    > +  // AddrMode6 Offset (register)
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVSTInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned wb = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  Rn |= fieldFromInstruction32(Insn, 4, 2) << 4;
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +
    > +  // Writeback Operand
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VST1d8_UPD:
    > +    case ARM::VST1d16_UPD:
    > +    case ARM::VST1d32_UPD:
    > +    case ARM::VST1d64_UPD:
    > +    case ARM::VST1q8_UPD:
    > +    case ARM::VST1q16_UPD:
    > +    case ARM::VST1q32_UPD:
    > +    case ARM::VST1q64_UPD:
    > +    case ARM::VST1d8T_UPD:
    > +    case ARM::VST1d16T_UPD:
    > +    case ARM::VST1d32T_UPD:
    > +    case ARM::VST1d64T_UPD:
    > +    case ARM::VST1d8Q_UPD:
    > +    case ARM::VST1d16Q_UPD:
    > +    case ARM::VST1d32Q_UPD:
    > +    case ARM::VST1d64Q_UPD:
    > +    case ARM::VST2d8_UPD:
    > +    case ARM::VST2d16_UPD:
    > +    case ARM::VST2d32_UPD:
    > +    case ARM::VST2q8_UPD:
    > +    case ARM::VST2q16_UPD:
    > +    case ARM::VST2q32_UPD:
    > +    case ARM::VST2b8_UPD:
    > +    case ARM::VST2b16_UPD:
    > +    case ARM::VST2b32_UPD:
    > +    case ARM::VST3d8_UPD:
    > +    case ARM::VST3d16_UPD:
    > +    case ARM::VST3d32_UPD:
    > +    case ARM::VST3q8_UPD:
    > +    case ARM::VST3q16_UPD:
    > +    case ARM::VST3q32_UPD:
    > +    case ARM::VST4d8_UPD:
    > +    case ARM::VST4d16_UPD:
    > +    case ARM::VST4d32_UPD:
    > +    case ARM::VST4q8_UPD:
    > +    case ARM::VST4q16_UPD:
    > +    case ARM::VST4q32_UPD:
    > +      DecodeGPRRegisterClass(Inst, wb, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // AddrMode6 Base (register+alignment)
    > +  DecodeAddrMode6Operand(Inst, Rn, Address, Decoder);
    > +
    > +  // AddrMode6 Offset (register)
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  // First input register
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +
    > +  // Second input register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VST1q8:
    > +    case ARM::VST1q16:
    > +    case ARM::VST1q32:
    > +    case ARM::VST1q64:
    > +    case ARM::VST1q8_UPD:
    > +    case ARM::VST1q16_UPD:
    > +    case ARM::VST1q32_UPD:
    > +    case ARM::VST1q64_UPD:
    > +    case ARM::VST1d8T:
    > +    case ARM::VST1d16T:
    > +    case ARM::VST1d32T:
    > +    case ARM::VST1d64T:
    > +    case ARM::VST1d8T_UPD:
    > +    case ARM::VST1d16T_UPD:
    > +    case ARM::VST1d32T_UPD:
    > +    case ARM::VST1d64T_UPD:
    > +    case ARM::VST1d8Q:
    > +    case ARM::VST1d16Q:
    > +    case ARM::VST1d32Q:
    > +    case ARM::VST1d64Q:
    > +    case ARM::VST1d8Q_UPD:
    > +    case ARM::VST1d16Q_UPD:
    > +    case ARM::VST1d32Q_UPD:
    > +    case ARM::VST1d64Q_UPD:
    > +    case ARM::VST2d8:
    > +    case ARM::VST2d16:
    > +    case ARM::VST2d32:
    > +    case ARM::VST2d8_UPD:
    > +    case ARM::VST2d16_UPD:
    > +    case ARM::VST2d32_UPD:
    > +    case ARM::VST2q8:
    > +    case ARM::VST2q16:
    > +    case ARM::VST2q32:
    > +    case ARM::VST2q8_UPD:
    > +    case ARM::VST2q16_UPD:
    > +    case ARM::VST2q32_UPD:
    > +    case ARM::VST3d8:
    > +    case ARM::VST3d16:
    > +    case ARM::VST3d32:
    > +    case ARM::VST3d8_UPD:
    > +    case ARM::VST3d16_UPD:
    > +    case ARM::VST3d32_UPD:
    > +    case ARM::VST4d8:
    > +    case ARM::VST4d16:
    > +    case ARM::VST4d32:
    > +    case ARM::VST4d8_UPD:
    > +    case ARM::VST4d16_UPD:
    > +    case ARM::VST4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VST2b8:
    > +    case ARM::VST2b16:
    > +    case ARM::VST2b32:
    > +    case ARM::VST2b8_UPD:
    > +    case ARM::VST2b16_UPD:
    > +    case ARM::VST2b32_UPD:
    > +    case ARM::VST3q8:
    > +    case ARM::VST3q16:
    > +    case ARM::VST3q32:
    > +    case ARM::VST3q8_UPD:
    > +    case ARM::VST3q16_UPD:
    > +    case ARM::VST3q32_UPD:
    > +    case ARM::VST4q8:
    > +    case ARM::VST4q16:
    > +    case ARM::VST4q32:
    > +    case ARM::VST4q8_UPD:
    > +    case ARM::VST4q16_UPD:
    > +    case ARM::VST4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Third input register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VST1d8T:
    > +    case ARM::VST1d16T:
    > +    case ARM::VST1d32T:
    > +    case ARM::VST1d64T:
    > +    case ARM::VST1d8T_UPD:
    > +    case ARM::VST1d16T_UPD:
    > +    case ARM::VST1d32T_UPD:
    > +    case ARM::VST1d64T_UPD:
    > +    case ARM::VST1d8Q:
    > +    case ARM::VST1d16Q:
    > +    case ARM::VST1d32Q:
    > +    case ARM::VST1d64Q:
    > +    case ARM::VST1d8Q_UPD:
    > +    case ARM::VST1d16Q_UPD:
    > +    case ARM::VST1d32Q_UPD:
    > +    case ARM::VST1d64Q_UPD:
    > +    case ARM::VST2q8:
    > +    case ARM::VST2q16:
    > +    case ARM::VST2q32:
    > +    case ARM::VST2q8_UPD:
    > +    case ARM::VST2q16_UPD:
    > +    case ARM::VST2q32_UPD:
    > +    case ARM::VST3d8:
    > +    case ARM::VST3d16:
    > +    case ARM::VST3d32:
    > +    case ARM::VST3d8_UPD:
    > +    case ARM::VST3d16_UPD:
    > +    case ARM::VST3d32_UPD:
    > +    case ARM::VST4d8:
    > +    case ARM::VST4d16:
    > +    case ARM::VST4d32:
    > +    case ARM::VST4d8_UPD:
    > +    case ARM::VST4d16_UPD:
    > +    case ARM::VST4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VST3q8:
    > +    case ARM::VST3q16:
    > +    case ARM::VST3q32:
    > +    case ARM::VST3q8_UPD:
    > +    case ARM::VST3q16_UPD:
    > +    case ARM::VST3q32_UPD:
    > +    case ARM::VST4q8:
    > +    case ARM::VST4q16:
    > +    case ARM::VST4q32:
    > +    case ARM::VST4q8_UPD:
    > +    case ARM::VST4q16_UPD:
    > +    case ARM::VST4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Fourth input register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VST1d8Q:
    > +    case ARM::VST1d16Q:
    > +    case ARM::VST1d32Q:
    > +    case ARM::VST1d64Q:
    > +    case ARM::VST1d8Q_UPD:
    > +    case ARM::VST1d16Q_UPD:
    > +    case ARM::VST1d32Q_UPD:
    > +    case ARM::VST1d64Q_UPD:
    > +    case ARM::VST2q8:
    > +    case ARM::VST2q16:
    > +    case ARM::VST2q32:
    > +    case ARM::VST2q8_UPD:
    > +    case ARM::VST2q16_UPD:
    > +    case ARM::VST2q32_UPD:
    > +    case ARM::VST4d8:
    > +    case ARM::VST4d16:
    > +    case ARM::VST4d32:
    > +    case ARM::VST4d8_UPD:
    > +    case ARM::VST4d16_UPD:
    > +    case ARM::VST4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VST4q8:
    > +    case ARM::VST4q16:
    > +    case ARM::VST4q32:
    > +    case ARM::VST4q8_UPD:
    > +    case ARM::VST4q16_UPD:
    > +    case ARM::VST4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLD1DupInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                    uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned align = fieldFromInstruction32(Insn, 4, 1);
    > +  unsigned size = fieldFromInstruction32(Insn, 6, 2);
    > +  unsigned regs = fieldFromInstruction32(Insn, 5, 1) + 1;
    > +
    > +  align *= (1 << size);
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  if (regs == 2) DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
    > +  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(align));
    > +
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLD2DupInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                    uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned align = fieldFromInstruction32(Insn, 4, 1);
    > +  unsigned size = 1 << fieldFromInstruction32(Insn, 6, 2);
    > +  unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
    > +  align *= 2*size;
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
    > +  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(align));
    > +
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLD3DupInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                    uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder);
    > +  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(0));
    > +
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLD4DupInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                    uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned size = fieldFromInstruction32(Insn, 6, 2);
    > +  unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
    > +  unsigned align = fieldFromInstruction32(Insn, 4, 1);
    > +
    > +  if (size == 0x3) {
    > +    size = 4;
    > +    align = 16;
    > +  } else {
    > +    if (size == 2) {
    > +      size = 1 << size;
    > +      align *= 8;
    > +    } else {
    > +      size = 1 << size;
    > +      align *= 4*size;
    > +    }
    > +  }
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder);
    > +  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(align));
    > +
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeNEONModImmInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                        uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned imm = fieldFromInstruction32(Insn, 0, 4);
    > +  imm |= fieldFromInstruction32(Insn, 16, 3) << 4;
    > +  imm |= fieldFromInstruction32(Insn, 24, 1) << 7;
    > +  imm |= fieldFromInstruction32(Insn, 8, 4) << 8;
    > +  imm |= fieldFromInstruction32(Insn, 5, 1) << 12;
    > +  unsigned Q = fieldFromInstruction32(Insn, 6, 1);
    > +
    > +  if (Q)
    > +    DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  else
    > +    DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VORRiv4i16:
    > +    case ARM::VORRiv2i32:
    > +    case ARM::VBICiv4i16:
    > +    case ARM::VBICiv2i32:
    > +      DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +      break;
    > +    case ARM::VORRiv8i16:
    > +    case ARM::VORRiv4i32:
    > +    case ARM::VBICiv8i16:
    > +    case ARM::VBICiv4i32:
    > +      DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVSHLMaxInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                        uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
    > +  unsigned size = fieldFromInstruction32(Insn, 18, 2);
    > +
    > +  DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(8 << size));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeShiftRight8Imm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(8 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeShiftRight16Imm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(16 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeShiftRight32Imm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(32 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeShiftRight64Imm(llvm::MCInst &Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(64 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeTBLInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1) << 4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  Rn |= fieldFromInstruction32(Insn, 7, 1) << 4;
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  Rm |= fieldFromInstruction32(Insn, 5, 1) << 4;
    > +  unsigned op = fieldFromInstruction32(Insn, 6, 1);
    > +  unsigned length = fieldFromInstruction32(Insn, 8, 2) + 1;
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  if (op) DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); // Writeback
    > +
    > +  for (unsigned i = 0; i < length; ++i)
    > +    DecodeDPRRegisterClass(Inst, (Rn+i)%32, Address, Decoder);
    > +
    > +  DecodeDPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVFPfpImm(llvm::MCInst &Inst, unsigned Val,
    > +                            uint64_t Address, const void *Decoder) {
    > +  // The immediate needs to be a fully instantiated float.  However, the
    > +  // auto-generated decoder is only able to fill in some of the bits
    > +  // necessary.  For instance, the 'b' bit is replicated multiple times,
    > +  // and is even present in inverted form in one bit.  We do a little
    > +  // binary parsing here to fill in those missing bits, and then
    > +  // reinterpret it all as a float.
    > +  union {
    > +    uint32_t integer;
    > +    float fp;
    > +  } fp_conv;
    > +
    > +  fp_conv.integer = Val;
    > +  uint32_t b = fieldFromInstruction32(Val, 25, 1);
    > +  fp_conv.integer |= b << 26;
    > +  fp_conv.integer |= b << 27;
    > +  fp_conv.integer |= b << 28;
    > +  fp_conv.integer |= b << 29;
    > +  fp_conv.integer |= (~b & 0x1) << 30;
    > +
    > +  Inst.addOperand(MCOperand::CreateFPImm(fp_conv.fp));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddSpecialReg(llvm::MCInst &Inst, uint16_t Insn,
    > +                                     uint64_t Address, const void *Decoder) {
    > +  unsigned dst = fieldFromInstruction16(Insn, 8, 3);
    > +  unsigned imm = fieldFromInstruction16(Insn, 0, 8);
    > +
    > +  DecodetGPRRegisterClass(Inst, dst, Address, Decoder);
    > +
    > +  if (Inst.getOpcode() == ARM::tADR)
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::PC));
    > +  else if (Inst.getOpcode() == ARM::tADDrSPi)
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +  else
    > +    return false;
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbBROperand(llvm::MCInst &Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<12>(Val << 1)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2BROperand(llvm::MCInst &Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<21>(Val)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbCmpBROperand(llvm::MCInst &Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<7>(Val << 1)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddrModeRR(llvm::MCInst &Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 0, 3);
    > +  unsigned Rm = fieldFromInstruction32(Val, 3, 3);
    > +
    > +  DecodetGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodetGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddrModeIS(llvm::MCInst &Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 0, 3);
    > +  unsigned imm = fieldFromInstruction32(Val, 3, 5);
    > +
    > +  DecodetGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddrModePC(llvm::MCInst &Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(Val << 2));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddrModeSP(llvm::MCInst &Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +  Inst.addOperand(MCOperand::CreateImm(Val << 2));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2AddrModeSOReg(llvm::MCInst &Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 6, 4);
    > +  unsigned Rm = fieldFromInstruction32(Val, 2, 4);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 2);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecoderGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2LoadShift(llvm::MCInst &Inst, unsigned Insn,
    > +                              uint64_t Address, const void *Decoder) {
    > +  if (Inst.getOpcode() != ARM::t2PLDs) {
    > +    unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
    > +    DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
    > +  }
    > +
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  if (Rn == 0xF) {
    > +    switch (Inst.getOpcode()) {
    > +      case ARM::t2LDRBs:
    > +        Inst.setOpcode(ARM::t2LDRBpci);
    > +        break;
    > +      case ARM::t2LDRHs:
    > +        Inst.setOpcode(ARM::t2LDRHpci);
    > +        break;
    > +      case ARM::t2LDRSHs:
    > +        Inst.setOpcode(ARM::t2LDRSHpci);
    > +        break;
    > +      case ARM::t2LDRSBs:
    > +        Inst.setOpcode(ARM::t2LDRSBpci);
    > +        break;
    > +      case ARM::t2PLDs:
    > +        Inst.setOpcode(ARM::t2PLDi12);
    > +        Inst.addOperand(MCOperand::CreateReg(ARM::PC));
    > +        break;
    > +      default:
    > +        return false;
    > +    }
    > +
    > +    int imm = fieldFromInstruction32(Insn, 0, 12);
    > +    if (!fieldFromInstruction32(Insn, 23, 1)) imm *= -1;
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +    return true;
    > +  }
    > +
    > +  unsigned addrmode = fieldFromInstruction32(Insn, 4, 2);
    > +  addrmode |= fieldFromInstruction32(Insn, 0, 4) << 2;
    > +  addrmode |= fieldFromInstruction32(Insn, 16, 4) << 6;
    > +  DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  int imm = Val & 0xFF;
    > +  if (!(Val & 0x100)) imm *= -1;
    > +  Inst.addOperand(MCOperand::CreateImm(imm << 2));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2AddrModeImm8s4(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 9, 4);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 9);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeT2Imm8S4(Inst, imm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  int imm = Val & 0xFF;
    > +  if (!(Val & 0x100)) imm *= -1;
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +
    > +static bool DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 9, 4);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 9);
    > +
    > +  // Some instructions always use an additive offset.
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::t2LDRT:
    > +    case ARM::t2LDRBT:
    > +    case ARM::t2LDRHT:
    > +    case ARM::t2LDRSBT:
    > +    case ARM::t2LDRSHT:
    > +      imm |= 0x100;
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeT2Imm8(Inst, imm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +
    > +static bool DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 13, 4);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 12);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +
    > +static bool DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned imm = fieldFromInstruction16(Insn, 0, 7);
    > +
    > +  Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +  Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (Inst.getOpcode() == ARM::tADDrSP) {
    > +    unsigned Rdm = fieldFromInstruction16(Insn, 0, 3);
    > +    Rdm |= fieldFromInstruction16(Insn, 7, 1) << 3;
    > +
    > +    DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder);
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +    DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder);
    > +  } else if (Inst.getOpcode() == ARM::tADDspr) {
    > +    unsigned Rm = fieldFromInstruction16(Insn, 3, 4);
    > +
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  }
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned imod = fieldFromInstruction16(Insn, 4, 1) | 0x2;
    > +  unsigned flags = fieldFromInstruction16(Insn, 0, 3);
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(imod));
    > +  Inst.addOperand(MCOperand::CreateImm(flags));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned add = fieldFromInstruction32(Insn, 4, 1);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(add));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeCoprocessor(llvm::MCInst &Inst, unsigned Val,
    > +                              uint64_t Address, const void *Decoder) {
    > +  if (Val == 0xA || Val == 0xB)
    > +    return false;
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbSRImm(llvm::MCInst &Inst, unsigned Val,
    > +                              uint64_t Address, const void *Decoder) {
    > +  if (Val == 0)
    > +    Inst.addOperand(MCOperand::CreateImm(32));
    > +  else
    > +    Inst.addOperand(MCOperand::CreateImm(Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumb2BCCInstruction(llvm::MCInst &Inst, unsigned Insn,
    > +                                       uint64_t Address, const void *Decoder) {
    > +  unsigned pred = fieldFromInstruction32(Insn, 22, 4);
    > +  if (pred == 0xE || pred == 0xF) {
    > +    unsigned opc = fieldFromInstruction32(Insn, 4, 2);
    > +    switch (opc) {
    > +      default:
    > +        return false;
    > +      case 0:
    > +        Inst.setOpcode(ARM::t2DSB);
    > +        break;
    > +      case 1:
    > +        Inst.setOpcode(ARM::t2DMB);
    > +        break;
    > +      case 2:
    > +        Inst.setOpcode(ARM::t2ISB);
    > +        return true;
    > +    }
    > +
    > +    unsigned imm = fieldFromInstruction32(Insn, 0, 4);
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +    return true;
    > +  }
    > +
    > +  unsigned brtarget = fieldFromInstruction32(Insn, 0, 11) << 1;
    > +  brtarget |= fieldFromInstruction32(Insn, 11, 1) << 19;
    > +  brtarget |= fieldFromInstruction32(Insn, 13, 1) << 18;
    > +  brtarget |= fieldFromInstruction32(Insn, 16, 6) << 12;
    > +  brtarget |= fieldFromInstruction32(Insn, 26, 1) << 20;
    > +
    > +  DecodeT2BROperand(Inst, brtarget, Address, Decoder);
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder))
    > +    return false;
    > +
    > +  return true;
    > +}
    > +
    > +// Decode a shifted immediate operand.  These basically consist
    > +// of an 8-bit value, and a 4-bit directive that specifies either
    > +// a splat operation or a rotation.
    > +static bool DecodeT2SOImm(llvm::MCInst &Inst, unsigned Val,
    > +                          uint64_t Address, const void *Decoder) {
    > +  unsigned ctrl = fieldFromInstruction32(Val, 10, 2);
    > +  if (ctrl == 0) {
    > +    unsigned byte = fieldFromInstruction32(Val, 8, 2);
    > +    unsigned imm = fieldFromInstruction32(Val, 0, 8);
    > +    switch (byte) {
    > +      case 0:
    > +        Inst.addOperand(MCOperand::CreateImm(imm));
    > +        break;
    > +      case 1:
    > +        Inst.addOperand(MCOperand::CreateImm((imm << 16) | imm));
    > +        break;
    > +      case 2:
    > +        Inst.addOperand(MCOperand::CreateImm((imm << 24) | (imm << 8)));
    > +        break;
    > +      case 3:
    > +        Inst.addOperand(MCOperand::CreateImm((imm << 24) | (imm << 16) |
    > +                                             (imm << 8)  |  imm));
    > +        break;
    > +    }
    > +  } else {
    > +    unsigned unrot = fieldFromInstruction32(Val, 0, 7) | 0x80;
    > +    unsigned rot = fieldFromInstruction32(Val, 7, 5);
    > +    unsigned imm = (unrot >> rot) | (unrot << ((32-rot)&31));
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +  }
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbBCCTargetOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                        uint64_t Address, const void *Decoder){
    > +  Inst.addOperand(MCOperand::CreateImm(Val << 1));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val,
    > +                                        uint64_t Address, const void *Decoder){
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode3Offset(llvm::MCInst &Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  bool isImm = fieldFromInstruction32(Val, 9, 1);
    > +  bool isAdd = fieldFromInstruction32(Val, 8, 1);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 8);
    > +
    > +  if (!isImm) {
    > +    DecodeGPRRegisterClass(Inst, imm, Address, Decoder);
    > +    Inst.addOperand(MCOperand::CreateImm(!isAdd << 8));
    > +  } else {
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +    Inst.addOperand(MCOperand::CreateImm(imm | (!isAdd << 8)));
    > +  }
    > +
    > +  return true;
    > }
    > 
    > Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h (original)
    > +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h Tue Aug  9 15:55:18 2011
    > @@ -17,15 +17,16 @@
    > #define ARMDISASSEMBLER_H
    > 
    > #include "llvm/MC/MCDisassembler.h"
    > +#include 
    > 
    > namespace llvm {
    > 
    > class MCInst;
    > class MemoryObject;
    > class raw_ostream;
    > -  
    > +
    > struct EDInstInfo;
    > -  
    > +
    > /// ARMDisassembler - ARM disassembler for all ARM platforms.
    > class ARMDisassembler : public MCDisassembler {
    > public:
    > @@ -44,38 +45,19 @@
    >                       const MemoryObject ®ion,
    >                       uint64_t address,
    >                       raw_ostream &vStream) const;
    > -  
    > +
    >   /// getEDInfo - See MCDisassembler.
    >   EDInstInfo *getEDInfo() const;
    > private:
    > };
    > 
    > -// Forward declaration.
    > -class ARMBasicMCBuilder;
    > -
    > -/// Session - Keep track of the IT Block progression.
    > -class Session {
    > -  friend class ARMBasicMCBuilder;
    > -public:
    > -  Session() : ITCounter(0), ITState(0) {}
    > -  ~Session() {}
    > -  /// InitIT - Initializes ITCounter/ITState.
    > -  bool InitIT(unsigned short bits7_0);
    > -  /// UpdateIT - Updates ITCounter/ITState as IT Block progresses.
    > -  void UpdateIT();
    > -
    > -private:
    > -  unsigned ITCounter; // Possible values: 0, 1, 2, 3, 4.
    > -  unsigned ITState;   // A2.5.2 Consists of IT[7:5] and IT[4:0] initially.
    > -};
    > -
    > -/// ThumbDisassembler - Thumb disassembler for all ARM platforms.
    > +/// ARMDisassembler - ARM disassembler for all ARM platforms.
    > class ThumbDisassembler : public MCDisassembler {
    > public:
    >   /// Constructor     - Initializes the disassembler.
    >   ///
    >   ThumbDisassembler() :
    > -    MCDisassembler(), SO() {
    > +    MCDisassembler() {
    >   }
    > 
    >   ~ThumbDisassembler() {
    > @@ -87,13 +69,16 @@
    >                       const MemoryObject ®ion,
    >                       uint64_t address,
    >                       raw_ostream &vStream) const;
    > -  
    > +
    >   /// getEDInfo - See MCDisassembler.
    >   EDInstInfo *getEDInfo() const;
    > private:
    > -  Session SO;
    > +  mutable std::vector ITBlock;
    > +  void AddThumbPredicate(MCInst&) const;
    > +  void UpdateThumbVFPPredicate(MCInst&) const;
    > };
    > 
    > +
    > } // namespace llvm
    > -  
    > +
    > #endif
    > 
    > Removed: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp?rev=137143&view=auto
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (original)
    > +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp (removed)
    > @@ -1,3894 +0,0 @@
    > -//===- ARMDisassemblerCore.cpp - ARM disassembler helpers -------*- C++ -*-===//
    > -//
    > -//                     The LLVM Compiler Infrastructure
    > -//
    > -// This file is distributed under the University of Illinois Open Source
    > -// License. See LICENSE.TXT for details.
    > -//
    > -//===----------------------------------------------------------------------===//
    > -//
    > -// This file is part of the ARM Disassembler.
    > -// It contains code to represent the core concepts of Builder and DisassembleFP
    > -// to solve the problem of disassembling an ARM instr.
    > -//
    > -//===----------------------------------------------------------------------===//
    > -
    > -#define DEBUG_TYPE "arm-disassembler"
    > -
    > -#include "ARMDisassemblerCore.h"
    > -#include "MCTargetDesc/ARMAddressingModes.h"
    > -#include "MCTargetDesc/ARMMCExpr.h"
    > -#include "llvm/ADT/APInt.h"
    > -#include "llvm/ADT/APFloat.h"
    > -#include "llvm/Support/Debug.h"
    > -#include "llvm/Support/raw_ostream.h"
    > -
    > -//#define DEBUG(X) do { X; } while (0)
    > -
    > -/// ARMGenInstrInfo.inc - ARMGenInstrInfo.inc contains the static const
    > -/// MCInstrDesc ARMInsts[] definition and the MCOperandInfo[]'s describing the
    > -/// operand info for each ARMInsts[i].
    > -///
    > -/// Together with an instruction's encoding format, we can take advantage of the
    > -/// NumOperands and the OpInfo fields of the target instruction description in
    > -/// the quest to build out the MCOperand list for an MCInst.
    > -///
    > -/// The general guideline is that with a known format, the number of dst and src
    > -/// operands are well-known.  The dst is built first, followed by the src
    > -/// operand(s).  The operands not yet used at this point are for the Implicit
    > -/// Uses and Defs by this instr.  For the Uses part, the pred:$p operand is
    > -/// defined with two components:
    > -///
    > -/// def pred { // Operand PredicateOperand
    > -///   ValueType Type = OtherVT;
    > -///   string PrintMethod = "printPredicateOperand";
    > -///   string AsmOperandLowerMethod = ?;
    > -///   dag MIOperandInfo = (ops i32imm, CCR);
    > -///   AsmOperandClass ParserMatchClass = ImmAsmOperand;
    > -///   dag DefaultOps = (ops (i32 14), (i32 zero_reg));
    > -/// }
    > -///
    > -/// which is manifested by the MCOperandInfo[] of:
    > -///
    > -/// { 0, 0|(1< -/// { ARM::CCRRegClassID, 0|(1< -///
    > -/// So the first predicate MCOperand corresponds to the immediate part of the
    > -/// ARM condition field (Inst{31-28}), and the second predicate MCOperand
    > -/// corresponds to a register kind of ARM::CPSR.
    > -///
    > -/// For the Defs part, in the simple case of only cc_out:$s, we have:
    > -///
    > -/// def cc_out { // Operand OptionalDefOperand
    > -///   ValueType Type = OtherVT;
    > -///   string PrintMethod = "printSBitModifierOperand";
    > -///   string AsmOperandLowerMethod = ?;
    > -///   dag MIOperandInfo = (ops CCR);
    > -///   AsmOperandClass ParserMatchClass = ImmAsmOperand;
    > -///   dag DefaultOps = (ops (i32 zero_reg));
    > -/// }
    > -///
    > -/// which is manifested by the one MCOperandInfo of:
    > -///
    > -/// { ARM::CCRRegClassID, 0|(1< -///
    > -
    > -namespace llvm {
    > -extern MCInstrDesc ARMInsts[];
    > -}
    > -
    > -using namespace llvm;
    > -
    > -const char *ARMUtils::OpcodeName(unsigned Opcode) {
    > -  return ARMInsts[Opcode].Name;
    > -}
    > -
    > -// Return the register enum Based on RegClass and the raw register number.
    > -// FIXME: Auto-gened?
    > -static unsigned
    > -getRegisterEnum(BO B, unsigned RegClassID, unsigned RawRegister) {
    > -  if (RegClassID == ARM::rGPRRegClassID) {
    > -    // Check for The register numbers 13 and 15 that are not permitted for many
    > -    // Thumb register specifiers.
    > -    if (RawRegister == 13 || RawRegister == 15) {
    > -      B->SetErr(-1);
    > -      return 0;
    > -    }
    > -    // For this purpose, we can treat rGPR as if it were GPR.
    > -    RegClassID = ARM::GPRRegClassID;
    > -  }
    > -
    > -  // See also decodeNEONRd(), decodeNEONRn(), decodeNEONRm().
    > -  // A7.3 register encoding
    > -  //     Qd -> bit[12] == 0
    > -  //     Qn -> bit[16] == 0
    > -  //     Qm -> bit[0]  == 0
    > -  //
    > -  // If one of these bits is 1, the instruction is UNDEFINED.
    > -  if (RegClassID == ARM::QPRRegClassID && slice(RawRegister, 0, 0) == 1) {
    > -    B->SetErr(-1);
    > -    return 0;
    > -  }
    > -  unsigned RegNum =
    > -    RegClassID == ARM::QPRRegClassID ? RawRegister >> 1 : RawRegister;
    > -
    > -  switch (RegNum) {
    > -  default:
    > -    break;
    > -  case 0:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R0;
    > -    case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
    > -    case ARM::DPR_VFP2RegClassID:
    > -      return ARM::D0;
    > -    case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
    > -    case ARM::QPR_VFP2RegClassID:
    > -      return ARM::Q0;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S0;
    > -    }
    > -    break;
    > -  case 1:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R1;
    > -    case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
    > -    case ARM::DPR_VFP2RegClassID:
    > -      return ARM::D1;
    > -    case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
    > -    case ARM::QPR_VFP2RegClassID:
    > -      return ARM::Q1;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S1;
    > -    }
    > -    break;
    > -  case 2:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R2;
    > -    case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
    > -    case ARM::DPR_VFP2RegClassID:
    > -      return ARM::D2;
    > -    case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
    > -    case ARM::QPR_VFP2RegClassID:
    > -      return ARM::Q2;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S2;
    > -    }
    > -    break;
    > -  case 3:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R3;
    > -    case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
    > -    case ARM::DPR_VFP2RegClassID:
    > -      return ARM::D3;
    > -    case ARM::QPRRegClassID: case ARM::QPR_8RegClassID:
    > -    case ARM::QPR_VFP2RegClassID:
    > -      return ARM::Q3;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S3;
    > -    }
    > -    break;
    > -  case 4:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R4;
    > -    case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
    > -    case ARM::DPR_VFP2RegClassID:
    > -      return ARM::D4;
    > -    case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q4;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S4;
    > -    }
    > -    break;
    > -  case 5:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R5;
    > -    case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
    > -    case ARM::DPR_VFP2RegClassID:
    > -      return ARM::D5;
    > -    case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q5;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S5;
    > -    }
    > -    break;
    > -  case 6:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R6;
    > -    case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
    > -    case ARM::DPR_VFP2RegClassID:
    > -      return ARM::D6;
    > -    case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q6;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S6;
    > -    }
    > -    break;
    > -  case 7:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: case ARM::tGPRRegClassID: return ARM::R7;
    > -    case ARM::DPRRegClassID: case ARM::DPR_8RegClassID:
    > -    case ARM::DPR_VFP2RegClassID:
    > -      return ARM::D7;
    > -    case ARM::QPRRegClassID: case ARM::QPR_VFP2RegClassID: return ARM::Q7;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S7;
    > -    }
    > -    break;
    > -  case 8:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: return ARM::R8;
    > -    case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D8;
    > -    case ARM::QPRRegClassID: return ARM::Q8;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S8;
    > -    }
    > -    break;
    > -  case 9:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: return ARM::R9;
    > -    case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D9;
    > -    case ARM::QPRRegClassID: return ARM::Q9;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S9;
    > -    }
    > -    break;
    > -  case 10:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: return ARM::R10;
    > -    case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D10;
    > -    case ARM::QPRRegClassID: return ARM::Q10;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S10;
    > -    }
    > -    break;
    > -  case 11:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: return ARM::R11;
    > -    case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D11;
    > -    case ARM::QPRRegClassID: return ARM::Q11;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S11;
    > -    }
    > -    break;
    > -  case 12:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: return ARM::R12;
    > -    case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D12;
    > -    case ARM::QPRRegClassID: return ARM::Q12;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S12;
    > -    }
    > -    break;
    > -  case 13:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: return ARM::SP;
    > -    case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D13;
    > -    case ARM::QPRRegClassID: return ARM::Q13;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S13;
    > -    }
    > -    break;
    > -  case 14:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: return ARM::LR;
    > -    case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D14;
    > -    case ARM::QPRRegClassID: return ARM::Q14;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S14;
    > -    }
    > -    break;
    > -  case 15:
    > -    switch (RegClassID) {
    > -    case ARM::GPRRegClassID: return ARM::PC;
    > -    case ARM::DPRRegClassID: case ARM::DPR_VFP2RegClassID: return ARM::D15;
    > -    case ARM::QPRRegClassID: return ARM::Q15;
    > -    case ARM::SPRRegClassID: case ARM::SPR_8RegClassID: return ARM::S15;
    > -    }
    > -    break;
    > -  case 16:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D16;
    > -    case ARM::SPRRegClassID: return ARM::S16;
    > -    }
    > -    break;
    > -  case 17:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D17;
    > -    case ARM::SPRRegClassID: return ARM::S17;
    > -    }
    > -    break;
    > -  case 18:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D18;
    > -    case ARM::SPRRegClassID: return ARM::S18;
    > -    }
    > -    break;
    > -  case 19:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D19;
    > -    case ARM::SPRRegClassID: return ARM::S19;
    > -    }
    > -    break;
    > -  case 20:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D20;
    > -    case ARM::SPRRegClassID: return ARM::S20;
    > -    }
    > -    break;
    > -  case 21:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D21;
    > -    case ARM::SPRRegClassID: return ARM::S21;
    > -    }
    > -    break;
    > -  case 22:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D22;
    > -    case ARM::SPRRegClassID: return ARM::S22;
    > -    }
    > -    break;
    > -  case 23:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D23;
    > -    case ARM::SPRRegClassID: return ARM::S23;
    > -    }
    > -    break;
    > -  case 24:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D24;
    > -    case ARM::SPRRegClassID: return ARM::S24;
    > -    }
    > -    break;
    > -  case 25:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D25;
    > -    case ARM::SPRRegClassID: return ARM::S25;
    > -    }
    > -    break;
    > -  case 26:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D26;
    > -    case ARM::SPRRegClassID: return ARM::S26;
    > -    }
    > -    break;
    > -  case 27:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D27;
    > -    case ARM::SPRRegClassID: return ARM::S27;
    > -    }
    > -    break;
    > -  case 28:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D28;
    > -    case ARM::SPRRegClassID: return ARM::S28;
    > -    }
    > -    break;
    > -  case 29:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D29;
    > -    case ARM::SPRRegClassID: return ARM::S29;
    > -    }
    > -    break;
    > -  case 30:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D30;
    > -    case ARM::SPRRegClassID: return ARM::S30;
    > -    }
    > -    break;
    > -  case 31:
    > -    switch (RegClassID) {
    > -    case ARM::DPRRegClassID: return ARM::D31;
    > -    case ARM::SPRRegClassID: return ARM::S31;
    > -    }
    > -    break;
    > -  }
    > -  DEBUG(errs() << "Invalid (RegClassID, RawRegister) combination\n");
    > -  // Encoding error.  Mark the builder with error code != 0.
    > -  B->SetErr(-1);
    > -  return 0;
    > -}
    > -
    > -///////////////////////////////
    > -//                           //
    > -//     Utility Functions     //
    > -//                           //
    > -///////////////////////////////
    > -
    > -// Extract/Decode Rd: Inst{15-12}.
    > -static inline unsigned decodeRd(uint32_t insn) {
    > -  return (insn >> ARMII::RegRdShift) & ARMII::GPRRegMask;
    > -}
    > -
    > -// Extract/Decode Rn: Inst{19-16}.
    > -static inline unsigned decodeRn(uint32_t insn) {
    > -  return (insn >> ARMII::RegRnShift) & ARMII::GPRRegMask;
    > -}
    > -
    > -// Extract/Decode Rm: Inst{3-0}.
    > -static inline unsigned decodeRm(uint32_t insn) {
    > -  return (insn & ARMII::GPRRegMask);
    > -}
    > -
    > -// Extract/Decode Rs: Inst{11-8}.
    > -static inline unsigned decodeRs(uint32_t insn) {
    > -  return (insn >> ARMII::RegRsShift) & ARMII::GPRRegMask;
    > -}
    > -
    > -static inline unsigned getCondField(uint32_t insn) {
    > -  return (insn >> ARMII::CondShift);
    > -}
    > -
    > -static inline unsigned getIBit(uint32_t insn) {
    > -  return (insn >> ARMII::I_BitShift) & 1;
    > -}
    > -
    > -static inline unsigned getAM3IBit(uint32_t insn) {
    > -  return (insn >> ARMII::AM3_I_BitShift) & 1;
    > -}
    > -
    > -static inline unsigned getPBit(uint32_t insn) {
    > -  return (insn >> ARMII::P_BitShift) & 1;
    > -}
    > -
    > -static inline unsigned getUBit(uint32_t insn) {
    > -  return (insn >> ARMII::U_BitShift) & 1;
    > -}
    > -
    > -static inline unsigned getPUBits(uint32_t insn) {
    > -  return (insn >> ARMII::U_BitShift) & 3;
    > -}
    > -
    > -static inline unsigned getSBit(uint32_t insn) {
    > -  return (insn >> ARMII::S_BitShift) & 1;
    > -}
    > -
    > -static inline unsigned getWBit(uint32_t insn) {
    > -  return (insn >> ARMII::W_BitShift) & 1;
    > -}
    > -
    > -static inline unsigned getDBit(uint32_t insn) {
    > -  return (insn >> ARMII::D_BitShift) & 1;
    > -}
    > -
    > -static inline unsigned getNBit(uint32_t insn) {
    > -  return (insn >> ARMII::N_BitShift) & 1;
    > -}
    > -
    > -static inline unsigned getMBit(uint32_t insn) {
    > -  return (insn >> ARMII::M_BitShift) & 1;
    > -}
    > -
    > -// See A8.4 Shifts applied to a register.
    > -//     A8.4.2 Register controlled shifts.
    > -//
    > -// getShiftOpcForBits - getShiftOpcForBits translates from the ARM encoding bits
    > -// into llvm enums for shift opcode.  The API clients should pass in the value
    > -// encoded with two bits, so the assert stays to signal a wrong API usage.
    > -//
    > -// A8-12: DecodeRegShift()
    > -static inline ARM_AM::ShiftOpc getShiftOpcForBits(unsigned bits) {
    > -  switch (bits) {
    > -  default: assert(0 && "No such value"); return ARM_AM::no_shift;
    > -  case 0:  return ARM_AM::lsl;
    > -  case 1:  return ARM_AM::lsr;
    > -  case 2:  return ARM_AM::asr;
    > -  case 3:  return ARM_AM::ror;
    > -  }
    > -}
    > -
    > -// See A8.4 Shifts applied to a register.
    > -//     A8.4.1 Constant shifts.
    > -//
    > -// getImmShiftSE - getImmShiftSE translates from the raw ShiftOpc and raw Imm5
    > -// encodings into the intended ShiftOpc and shift amount.
    > -//
    > -// A8-11: DecodeImmShift()
    > -static inline void getImmShiftSE(ARM_AM::ShiftOpc &ShOp, unsigned &ShImm) {
    > -  if (ShImm != 0)
    > -    return;
    > -  switch (ShOp) {
    > -  case ARM_AM::no_shift:
    > -  case ARM_AM::rrx:
    > -    break;
    > -  case ARM_AM::lsl:
    > -    ShOp = ARM_AM::no_shift;
    > -    break;
    > -  case ARM_AM::lsr:
    > -  case ARM_AM::asr:
    > -    ShImm = 32;
    > -    break;
    > -  case ARM_AM::ror:
    > -    ShOp = ARM_AM::rrx;
    > -    break;
    > -  }
    > -}
    > -
    > -// getAMSubModeForBits - getAMSubModeForBits translates from the ARM encoding
    > -// bits Inst{24-23} (P(24) and U(23)) into llvm enums for AMSubMode.  The API
    > -// clients should pass in the value encoded with two bits, so the assert stays
    > -// to signal a wrong API usage.
    > -static inline ARM_AM::AMSubMode getAMSubModeForBits(unsigned bits) {
    > -  switch (bits) {
    > -  default: assert(0 && "No such value"); return ARM_AM::bad_am_submode;
    > -  case 1:  return ARM_AM::ia;   // P=0 U=1
    > -  case 3:  return ARM_AM::ib;   // P=1 U=1
    > -  case 0:  return ARM_AM::da;   // P=0 U=0
    > -  case 2:  return ARM_AM::db;   // P=1 U=0
    > -  }
    > -}
    > -
    > -////////////////////////////////////////////
    > -//                                        //
    > -//    Disassemble function definitions    //
    > -//                                        //
    > -////////////////////////////////////////////
    > -
    > -/// There is a separate Disassemble*Frm function entry for disassembly of an ARM
    > -/// instr into a list of MCOperands in the appropriate order, with possible dst,
    > -/// followed by possible src(s).
    > -///
    > -/// The processing of the predicate, and the 'S' modifier bit, if MI modifies
    > -/// the CPSR, is factored into ARMBasicMCBuilder's method named
    > -/// TryPredicateAndSBitModifier.
    > -
    > -static bool DisassemblePseudo(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO) {
    > -
    > -  assert(0 && "Unexpected pseudo instruction!");
    > -  return false;
    > -}
    > -
    > -// A8.6.94 MLA
    > -// if d == 15 || n == 15 || m == 15 || a == 15 then UNPREDICTABLE;
    > -//
    > -// A8.6.105 MUL
    > -// if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
    > -//
    > -// A8.6.246 UMULL
    > -// if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE;
    > -// if dHi == dLo then UNPREDICTABLE;
    > -static bool BadRegsMulFrm(unsigned Opcode, uint32_t insn) {
    > -  unsigned R19_16 = slice(insn, 19, 16);
    > -  unsigned R15_12 = slice(insn, 15, 12);
    > -  unsigned R11_8  = slice(insn, 11, 8);
    > -  unsigned R3_0   = slice(insn, 3, 0);
    > -  switch (Opcode) {
    > -  default:
    > -    // Did we miss an opcode?
    > -    DEBUG(errs() << "BadRegsMulFrm: unexpected opcode!");
    > -    return false;
    > -  case ARM::MLA:     case ARM::MLS:     case ARM::SMLABB:  case ARM::SMLABT:
    > -  case ARM::SMLATB:  case ARM::SMLATT:  case ARM::SMLAWB:  case ARM::SMLAWT:
    > -  case ARM::SMMLA:   case ARM::SMMLAR:  case ARM::SMMLS:   case ARM::SMMLSR:
    > -  case ARM::USADA8:
    > -    if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15)
    > -      return true;
    > -    return false;
    > -  case ARM::MUL:     case ARM::SMMUL:   case ARM::SMMULR:
    > -  case ARM::SMULBB:  case ARM::SMULBT:  case ARM::SMULTB:  case ARM::SMULTT:
    > -  case ARM::SMULWB:  case ARM::SMULWT:  case ARM::SMUAD:   case ARM::SMUADX:
    > -  // A8.6.167 SMLAD & A8.6.172 SMLSD
    > -  case ARM::SMLAD:   case ARM::SMLADX:  case ARM::SMLSD:   case ARM::SMLSDX:
    > -  case ARM::USAD8:
    > -    if (R19_16 == 15 || R11_8 == 15 || R3_0 == 15)
    > -      return true;
    > -    return false;
    > -  case ARM::SMLAL:   case ARM::SMULL:   case ARM::UMAAL:   case ARM::UMLAL:
    > -  case ARM::UMULL:
    > -  case ARM::SMLALBB: case ARM::SMLALBT: case ARM::SMLALTB: case ARM::SMLALTT:
    > -  case ARM::SMLALD:  case ARM::SMLALDX: case ARM::SMLSLD:  case ARM::SMLSLDX:
    > -    if (R19_16 == 15 || R15_12 == 15 || R11_8 == 15 || R3_0 == 15)
    > -      return true;
    > -    if (R19_16 == R15_12)
    > -      return true;
    > -    return false;;
    > -  }
    > -}
    > -
    > -// Multiply Instructions.
    > -// MLA, MLS, SMLABB, SMLABT, SMLATB, SMLATT, SMLAWB, SMLAWT, SMMLA, SMMLAR,
    > -// SMMLS, SMMLAR, SMLAD, SMLADX, SMLSD, SMLSDX, and USADA8 (for convenience):
    > -//     Rd{19-16} Rn{3-0} Rm{11-8} Ra{15-12}
    > -// But note that register checking for {SMLAD, SMLADX, SMLSD, SMLSDX} is
    > -// only for {d, n, m}.
    > -//
    > -// MUL, SMMUL, SMMULR, SMULBB, SMULBT, SMULTB, SMULTT, SMULWB, SMULWT, SMUAD,
    > -// SMUADX, and USAD8 (for convenience):
    > -//     Rd{19-16} Rn{3-0} Rm{11-8}
    > -//
    > -// SMLAL, SMULL, UMAAL, UMLAL, UMULL, SMLALBB, SMLALBT, SMLALTB, SMLALTT,
    > -// SMLALD, SMLADLX, SMLSLD, SMLSLDX:
    > -//     RdLo{15-12} RdHi{19-16} Rn{3-0} Rm{11-8}
    > -//
    > -// The mapping of the multiply registers to the "regular" ARM registers, where
    > -// there are convenience decoder functions, is:
    > -//
    > -// Inst{15-12} => Rd
    > -// Inst{19-16} => Rn
    > -// Inst{3-0} => Rm
    > -// Inst{11-8} => Rs
    > -static bool DisassembleMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  unsigned short NumDefs = MCID.getNumDefs();
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumDefs > 0 && "NumDefs should be greater than 0 for MulFrm");
    > -  assert(NumOps >= 3
    > -         && OpInfo[0].RegClass == ARM::GPRRegClassID
    > -         && OpInfo[1].RegClass == ARM::GPRRegClassID
    > -         && OpInfo[2].RegClass == ARM::GPRRegClassID
    > -         && "Expect three register operands");
    > -
    > -  // Sanity check for the register encodings.
    > -  if (BadRegsMulFrm(Opcode, insn))
    > -    return false;
    > -
    > -  // Instructions with two destination registers have RdLo{15-12} first.
    > -  if (NumDefs == 2) {
    > -    assert(NumOps >= 4 && OpInfo[3].RegClass == ARM::GPRRegClassID &&
    > -           "Expect 4th register operand");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // The destination register: RdHi{19-16} or Rd{19-16}.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -
    > -  // The two src regsiters: Rn{3-0}, then Rm{11-8}.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRs(insn))));
    > -  OpIdx += 3;
    > -
    > -  // Many multiply instructions (e.g., MLA) have three src registers.
    > -  // The third register operand is Ra{15-12}.
    > -  if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// Helper routines for disassembly of coprocessor instructions.
    > -
    > -static bool LdStCopOpcode(unsigned Opcode) {
    > -  if ((Opcode >= ARM::LDC2L_OFFSET && Opcode <= ARM::LDC_PRE) ||
    > -      (Opcode >= ARM::STC2L_OFFSET && Opcode <= ARM::STC_PRE))
    > -    return true;
    > -  return false;
    > -}
    > -static bool CoprocessorOpcode(unsigned Opcode) {
    > -  if (LdStCopOpcode(Opcode))
    > -    return true;
    > -
    > -  switch (Opcode) {
    > -  default:
    > -    return false;
    > -  case ARM::CDP:  case ARM::CDP2:
    > -  case ARM::MCR:  case ARM::MCR2:  case ARM::MRC:  case ARM::MRC2:
    > -  case ARM::MCRR: case ARM::MCRR2: case ARM::MRRC: case ARM::MRRC2:
    > -    return true;
    > -  }
    > -}
    > -static inline unsigned GetCoprocessor(uint32_t insn) {
    > -  return slice(insn, 11, 8);
    > -}
    > -static inline unsigned GetCopOpc1(uint32_t insn, bool CDP) {
    > -  return CDP ? slice(insn, 23, 20) : slice(insn, 23, 21);
    > -}
    > -static inline unsigned GetCopOpc2(uint32_t insn) {
    > -  return slice(insn, 7, 5);
    > -}
    > -static inline unsigned GetCopOpc(uint32_t insn) {
    > -  return slice(insn, 7, 4);
    > -}
    > -// Most of the operands are in immediate forms, except Rd and Rn, which are ARM
    > -// core registers.
    > -//
    > -// CDP, CDP2:                cop opc1 CRd CRn CRm opc2
    > -//
    > -// MCR, MCR2, MRC, MRC2:     cop opc1 Rd CRn CRm opc2
    > -//
    > -// MCRR, MCRR2, MRRC, MRRc2: cop opc Rd Rn CRm
    > -//
    > -// LDC_OFFSET, LDC_PRE, LDC_POST: cop CRd Rn R0 [+/-]imm8:00
    > -// and friends
    > -// STC_OFFSET, STC_PRE, STC_POST: cop CRd Rn R0 [+/-]imm8:00
    > -// and friends
    > -//                                        <-- addrmode2 -->
    > -//
    > -// LDC_OPTION:                    cop CRd Rn imm8
    > -// and friends
    > -// STC_OPTION:                    cop CRd Rn imm8
    > -// and friends
    > -//
    > -static bool DisassembleCoprocessor(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 4 && "Num of operands >= 4 for coprocessor instr");
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -  // A8.6.92
    > -  // if coproc == '101x' then SEE "Advanced SIMD and VFP"
    > -  // But since the special instructions have more explicit encoding bits
    > -  // specified, if coproc == 10 or 11, we should reject it as invalid.
    > -  unsigned coproc = GetCoprocessor(insn);
    > -  if ((Opcode == ARM::MCR || Opcode == ARM::MCRR ||
    > -       Opcode == ARM::MRC || Opcode == ARM::MRRC) &&
    > -      (coproc == 10 || coproc == 11)) {
    > -    DEBUG(errs() << "Encoding error: coproc == 10 or 11 for MCR[R]/MR[R]C\n");
    > -    return false;
    > -  }
    > -
    > -  bool OneCopOpc = (Opcode == ARM::MCRR || Opcode == ARM::MCRR2 ||
    > -                    Opcode == ARM::MRRC || Opcode == ARM::MRRC2);
    > -
    > -  // CDP/CDP2 has no GPR operand; the opc1 operand is also wider (Inst{23-20}).
    > -  bool NoGPR = (Opcode == ARM::CDP || Opcode == ARM::CDP2);
    > -  bool LdStCop = LdStCopOpcode(Opcode);
    > -  bool RtOut = (Opcode == ARM::MRC || Opcode == ARM::MRC2);
    > -
    > -  OpIdx = 0;
    > -
    > -  if (RtOut) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -    ++OpIdx;
    > -  }
    > -  MI.addOperand(MCOperand::CreateImm(coproc));
    > -  ++OpIdx;
    > -
    > -  if (LdStCop) {
    > -    // Unindex if P:W = 0b00 --> _OPTION variant
    > -    unsigned PW = getPBit(insn) << 1 | getWBit(insn);
    > -
    > -    MI.addOperand(MCOperand::CreateImm(decodeRd(insn)));
    > -
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    OpIdx += 2;
    > -
    > -    if (PW) {
    > -      MI.addOperand(MCOperand::CreateReg(0));
    > -      ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
    > -      const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -      unsigned IndexMode =
    > -                 (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
    > -      unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, slice(insn, 7, 0) << 2,
    > -                                          ARM_AM::no_shift, IndexMode);
    > -      MI.addOperand(MCOperand::CreateImm(Offset));
    > -      OpIdx += 2;
    > -    } else {
    > -      MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 0)));
    > -      ++OpIdx;
    > -    }
    > -  } else {
    > -    MI.addOperand(MCOperand::CreateImm(OneCopOpc ? GetCopOpc(insn)
    > -                                                 : GetCopOpc1(insn, NoGPR)));
    > -    ++OpIdx;
    > -
    > -    if (!RtOut) {
    > -      MI.addOperand(NoGPR ? MCOperand::CreateImm(decodeRd(insn))
    > -                          : MCOperand::CreateReg(
    > -                                getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                decodeRd(insn))));
    > -      ++OpIdx;
    > -    }
    > -
    > -    MI.addOperand(OneCopOpc ? MCOperand::CreateReg(
    > -                                getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                decodeRn(insn)))
    > -                            : MCOperand::CreateImm(decodeRn(insn)));
    > -
    > -    MI.addOperand(MCOperand::CreateImm(decodeRm(insn)));
    > -
    > -    OpIdx += 2;
    > -
    > -    if (!OneCopOpc) {
    > -      MI.addOperand(MCOperand::CreateImm(GetCopOpc2(insn)));
    > -      ++OpIdx;
    > -    }
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// Branch Instructions.
    > -// BL: SignExtend(Imm24:'00', 32)
    > -// Bcc, BL_pred: SignExtend(Imm24:'00', 32) Pred0 Pred1
    > -// SMC: ZeroExtend(imm4, 32)
    > -// SVC: ZeroExtend(Imm24, 32)
    > -//
    > -// Various coprocessor instructions are assigned BrFrm arbitrarily.
    > -// Delegates to DisassembleCoprocessor() helper function.
    > -//
    > -// MRS/MRSsys: Rd
    > -// MSR/MSRsys: Rm mask=Inst{19-16}
    > -// BXJ:        Rm
    > -// MSRi/MSRsysi: so_imm
    > -// SRS: mode_imm
    > -// RFE: Rn
    > -static bool DisassembleBrFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  if (CoprocessorOpcode(Opcode))
    > -    return DisassembleCoprocessor(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  // MRS and MRSsys take one GPR reg Rd.
    > -  if (Opcode == ARM::MRS || Opcode == ARM::MRSsys) {
    > -    assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -  // BXJ takes one GPR reg Rm.
    > -  if (Opcode == ARM::BXJ) {
    > -    assert(NumOps >= 1 && OpInfo[0].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -  // MSR take a mask, followed by one GPR reg Rm. The mask contains the R Bit in
    > -  // bit 4, and the special register fields in bits 3-0.
    > -  if (Opcode == ARM::MSR) {
    > -    assert(NumOps >= 1 && OpInfo[1].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ |
    > -                                       slice(insn, 19, 16) /* Special Reg */ ));
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -    NumOpsAdded = 2;
    > -    return true;
    > -  }
    > -  // MSRi take a mask, followed by one so_imm operand. The mask contains the
    > -  // R Bit in bit 4, and the special register fields in bits 3-0.
    > -  if (Opcode == ARM::MSRi) {
    > -    // A5.2.11 MSR (immediate), and hints & B6.1.6 MSR (immediate)
    > -    // The hints instructions have more specific encodings, so if mask == 0,
    > -    // we should reject this as an invalid instruction.
    > -    if (slice(insn, 19, 16) == 0)
    > -      return false;
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 22, 22) << 4 /* R Bit */ |
    > -                                       slice(insn, 19, 16) /* Special Reg */ ));
    > -    // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0.
    > -    // A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}.
    > -    // See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot().
    > -    unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF;
    > -    unsigned Imm = insn & 0xFF;
    > -    MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot)));
    > -    NumOpsAdded = 2;
    > -    return true;
    > -  }
    > -  if (Opcode == ARM::SRSDA || Opcode == ARM::SRSDB ||
    > -      Opcode == ARM::SRSIA || Opcode == ARM::SRSIB ||
    > -      Opcode == ARM::SRSDA_UPD || Opcode == ARM::SRSDB_UPD ||
    > -      Opcode == ARM::SRSIA_UPD || Opcode == ARM::SRSIB_UPD) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -  if (Opcode == ARM::RFEDA || Opcode == ARM::RFEDB ||
    > -      Opcode == ARM::RFEIA || Opcode == ARM::RFEIB ||
    > -      Opcode == ARM::RFEDA_UPD || Opcode == ARM::RFEDB_UPD ||
    > -      Opcode == ARM::RFEIA_UPD || Opcode == ARM::RFEIB_UPD) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  assert((Opcode == ARM::Bcc || Opcode == ARM::BL || Opcode == ARM::BL_pred
    > -          || Opcode == ARM::SMC || Opcode == ARM::SVC) &&
    > -         "Unexpected Opcode");
    > -
    > -  assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected");
    > -
    > -  int Imm32 = 0;
    > -  if (Opcode == ARM::SMC) {
    > -    // ZeroExtend(imm4, 32) where imm24 = Inst{3-0}.
    > -    Imm32 = slice(insn, 3, 0);
    > -  } else if (Opcode == ARM::SVC) {
    > -    // ZeroExtend(imm24, 32) where imm24 = Inst{23-0}.
    > -    Imm32 = slice(insn, 23, 0);
    > -  } else {
    > -    // SignExtend(imm24:'00', 32) where imm24 = Inst{23-0}.
    > -    unsigned Imm26 = slice(insn, 23, 0) << 2;
    > -    //Imm32 = signextend(Imm26);
    > -    Imm32 = SignExtend32<26>(Imm26);
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateImm(Imm32));
    > -  NumOpsAdded = 1;
    > -
    > -  return true;
    > -}
    > -
    > -// Misc. Branch Instructions.
    > -// BX_RET, MOVPCLR
    > -// BLX, BLX_pred, BX, BX_pred
    > -// BLXi
    > -static bool DisassembleBrMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  // BX_RET and MOVPCLR have only two predicate operands; do an early return.
    > -  if (Opcode == ARM::BX_RET || Opcode == ARM::MOVPCLR)
    > -    return true;
    > -
    > -  // BLX and BX take one GPR reg.
    > -  if (Opcode == ARM::BLX || Opcode == ARM::BLX_pred ||
    > -      Opcode == ARM::BX || Opcode == ARM::BX_pred) {
    > -    assert(NumOps >= 1 && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -    OpIdx = 1;
    > -    return true;
    > -  }
    > -
    > -  // BLXi takes imm32 (the PC offset).
    > -  if (Opcode == ARM::BLXi) {
    > -    assert(NumOps >= 1 && OpInfo[0].RegClass < 0 && "Imm operand expected");
    > -    // SignExtend(imm24:H:'0', 32) where imm24 = Inst{23-0} and H = Inst{24}.
    > -    unsigned Imm26 = slice(insn, 23, 0) << 2 | slice(insn, 24, 24) << 1;
    > -    int Imm32 = SignExtend32<26>(Imm26);
    > -    MI.addOperand(MCOperand::CreateImm(Imm32));
    > -    OpIdx = 1;
    > -    return true;
    > -  }
    > -
    > -  return false;
    > -}
    > -
    > -static inline bool getBFCInvMask(uint32_t insn, uint32_t &mask) {
    > -  uint32_t lsb = slice(insn, 11, 7);
    > -  uint32_t msb = slice(insn, 20, 16);
    > -  uint32_t Val = 0;
    > -  if (msb < lsb) {
    > -    DEBUG(errs() << "Encoding error: msb < lsb\n");
    > -    return false;
    > -  }
    > -
    > -  for (uint32_t i = lsb; i <= msb; ++i)
    > -    Val |= (1 << i);
    > -  mask = ~Val;
    > -  return true;
    > -}
    > -
    > -// Standard data-processing instructions allow PC as a register specifier,
    > -// but we should reject other DPFrm instructions with PC as registers.
    > -static bool BadRegsDPFrm(unsigned Opcode, uint32_t insn) {
    > -  switch (Opcode) {
    > -  default:
    > -    // Did we miss an opcode?
    > -    if (decodeRd(insn) == 15 || decodeRn(insn) == 15 || decodeRm(insn) == 15) {
    > -      DEBUG(errs() << "DPFrm with bad reg specifier(s)\n");
    > -      return true;
    > -    }
    > -  case ARM::ADCrr:  case ARM::ADDSrr: case ARM::ADDrr:  case ARM::ANDrr:
    > -  case ARM::BICrr:  case ARM::CMNzrr: case ARM::CMPrr:  case ARM::EORrr:
    > -  case ARM::ORRrr:  case ARM::RSBrr:  case ARM::RSCrr:  case ARM::SBCrr:
    > -  case ARM::SUBSrr: case ARM::SUBrr:  case ARM::TEQrr:  case ARM::TSTrr:
    > -    return false;
    > -  }
    > -}
    > -
    > -// A major complication is the fact that some of the saturating add/subtract
    > -// operations have Rd Rm Rn, instead of the "normal" Rd Rn Rm.
    > -// They are QADD, QDADD, QDSUB, and QSUB.
    > -static bool DisassembleDPFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  unsigned short NumDefs = MCID.getNumDefs();
    > -  bool isUnary = isUnaryDP(MCID.TSFlags);
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  // Disassemble register def if there is one.
    > -  if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Now disassemble the src operands.
    > -  if (OpIdx >= NumOps)
    > -    return false;
    > -
    > -  // Special-case handling of BFC/BFI/SBFX/UBFX.
    > -  if (Opcode == ARM::BFC || Opcode == ARM::BFI) {
    > -    // A8.6.17 BFC & A8.6.18 BFI
    > -    // Sanity check Rd.
    > -    if (decodeRd(insn) == 15)
    > -      return false;
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    if (Opcode == ARM::BFI) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                         decodeRm(insn))));
    > -      ++OpIdx;
    > -    }
    > -    uint32_t mask = 0;
    > -    if (!getBFCInvMask(insn, mask))
    > -      return false;
    > -
    > -    MI.addOperand(MCOperand::CreateImm(mask));
    > -    OpIdx += 2;
    > -    return true;
    > -  }
    > -  if (Opcode == ARM::SBFX || Opcode == ARM::UBFX) {
    > -    // Sanity check Rd and Rm.
    > -    if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
    > -      return false;
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 11, 7)));
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 16)));
    > -    OpIdx += 3;
    > -    return true;
    > -  }
    > -
    > -  bool RmRn = (Opcode == ARM::QADD || Opcode == ARM::QDADD ||
    > -               Opcode == ARM::QDSUB || Opcode == ARM::QSUB);
    > -
    > -  // BinaryDP has an Rn operand.
    > -  if (!isUnary) {
    > -    assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(
    > -                    getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                    RmRn ? decodeRm(insn) : decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // If this is a two-address operand, skip it, e.g., MOVCCr operand 1.
    > -  if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) {
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Now disassemble operand 2.
    > -  if (OpIdx >= NumOps)
    > -    return false;
    > -
    > -  if (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) {
    > -    // We have a reg/reg form.
    > -    // Assert disabled because saturating operations, e.g., A8.6.127 QASX, are
    > -    // routed here as well.
    > -    // assert(getIBit(insn) == 0 && "I_Bit != '0' reg/reg form");
    > -    if (BadRegsDPFrm(Opcode, insn))
    > -      return false;
    > -    MI.addOperand(MCOperand::CreateReg(
    > -                    getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                    RmRn? decodeRn(insn) : decodeRm(insn))));
    > -    ++OpIdx;
    > -  } else if (Opcode == ARM::MOVi16 || Opcode == ARM::MOVTi16) {
    > -    // These two instructions don't allow d as 15.
    > -    if (decodeRd(insn) == 15)
    > -      return false;
    > -    // 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);
    > -    if (!B->tryAddingSymbolicOperand(Imm16, 4, MI))
    > -      MI.addOperand(MCOperand::CreateImm(Imm16));
    > -    ++OpIdx;
    > -  } else {
    > -    // We have a reg/imm form.
    > -    // SOImm is 4-bit rotate amount in bits 11-8 with 8-bit imm in bits 7-0.
    > -    // A5.2.4 Rotate amount is twice the numeric value of Inst{11-8}.
    > -    // See also ARMAddressingModes.h: getSOImmValImm() and getSOImmValRot().
    > -    assert(getIBit(insn) == 1 && "I_Bit != '1' reg/imm form");
    > -    unsigned Rot = (insn >> ARMII::SoRotImmShift) & 0xF;
    > -    unsigned Imm = insn & 0xFF;
    > -    MI.addOperand(MCOperand::CreateImm(ARM_AM::rotr32(Imm, 2*Rot)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -static bool DisassembleDPSoRegRegFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  unsigned short NumDefs = MCID.getNumDefs();
    > -  bool isUnary = isUnaryDP(MCID.TSFlags);
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  // Disassemble register def if there is one.
    > -  if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Disassemble the src operands.
    > -  if (OpIdx >= NumOps)
    > -    return false;
    > -
    > -  // BinaryDP has an Rn operand.
    > -  if (!isUnary) {
    > -    assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // If this is a two-address operand, skip it, e.g., MOVCCs operand 1.
    > -  if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) {
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Disassemble operand 2, which consists of three components.
    > -  if (OpIdx + 2 >= NumOps)
    > -    return false;
    > -
    > -  assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) &&
    > -         (OpInfo[OpIdx+1].RegClass == ARM::GPRRegClassID) &&
    > -         (OpInfo[OpIdx+2].RegClass < 0) &&
    > -         "Expect 3 reg operands");
    > -
    > -  // Register-controlled shifts have Inst{7} = 0 and Inst{4} = 1.
    > -  unsigned Rs = slice(insn, 4, 4);
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -  if (Rs) {
    > -    // If Inst{7} != 0, we should reject this insn as an invalid encoding.
    > -    if (slice(insn, 7, 7))
    > -      return false;
    > -
    > -    // A8.6.3 ADC (register-shifted register)
    > -    // if d == 15 || n == 15 || m == 15 || s == 15 then UNPREDICTABLE;
    > -    // 
    > -    // This also accounts for shift instructions (register) where, fortunately,
    > -    // Inst{19-16} = 0b0000.
    > -    // A8.6.89 LSL (register)
    > -    // if d == 15 || n == 15 || m == 15 then UNPREDICTABLE;
    > -    if (decodeRd(insn) == 15 || decodeRn(insn) == 15 ||
    > -        decodeRm(insn) == 15 || decodeRs(insn) == 15)
    > -      return false;
    > -    
    > -    // Register-controlled shifts: [Rm, Rs, shift].
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRs(insn))));
    > -    // Inst{6-5} encodes the shift opcode.
    > -    ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
    > -    MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, 0)));
    > -  } else {
    > -    // Constant shifts: [Rm, reg0, shift_imm].
    > -    MI.addOperand(MCOperand::CreateReg(0)); // NoRegister
    > -    // Inst{6-5} encodes the shift opcode.
    > -    ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
    > -    // Inst{11-7} encodes the imm5 shift amount.
    > -    unsigned ShImm = slice(insn, 11, 7);
    > -
    > -    // A8.4.1.  Possible rrx or shift amount of 32...
    > -    getImmShiftSE(ShOp, ShImm);
    > -    MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShImm)));
    > -  }
    > -  OpIdx += 3;
    > -
    > -  return true;
    > -}
    > -
    > -static bool DisassembleDPSoRegImmFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  unsigned short NumDefs = MCID.getNumDefs();
    > -  bool isUnary = isUnaryDP(MCID.TSFlags);
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  // Disassemble register def if there is one.
    > -  if (NumDefs && (OpInfo[OpIdx].RegClass == ARM::GPRRegClassID)) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Disassemble the src operands.
    > -  if (OpIdx >= NumOps)
    > -    return false;
    > -
    > -  // BinaryDP has an Rn operand.
    > -  if (!isUnary) {
    > -    assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // If this is a two-address operand, skip it, e.g., MOVCCs operand 1.
    > -  if (isUnary && (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)) {
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Disassemble operand 2, which consists of two components.
    > -  if (OpIdx + 1 >= NumOps)
    > -    return false;
    > -
    > -  assert((OpInfo[OpIdx].RegClass == ARM::GPRRegClassID) &&
    > -         (OpInfo[OpIdx+1].RegClass < 0) &&
    > -         "Expect 2 reg operands");
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -
    > -  // Inst{6-5} encodes the shift opcode.
    > -  ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
    > -  // Inst{11-7} encodes the imm5 shift amount.
    > -  unsigned ShImm = slice(insn, 11, 7);
    > -
    > -  // A8.4.1.  Possible rrx or shift amount of 32...
    > -  getImmShiftSE(ShOp, ShImm);
    > -  MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShImm)));
    > -
    > -  OpIdx += 2;
    > -
    > -  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) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  bool isPrePost = isPrePostLdSt(MCID.TSFlags);
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(((!isStore && MCID.getNumDefs() > 0) ||
    > -          (isStore && (MCID.getNumDefs() == 0 || isPrePost)))
    > -         && "Invalid arguments");
    > -
    > -  // Operand 0 of a pre- and post-indexed store is the address base writeback.
    > -  if (isPrePost && isStore) {
    > -    assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Disassemble the dst/src operand.
    > -  if (OpIdx >= NumOps)
    > -    return false;
    > -
    > -  assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -         "Reg operand expected");
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // After dst of a pre- and post-indexed load is the address base writeback.
    > -  if (isPrePost && !isStore) {
    > -    assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Disassemble the base operand.
    > -  if (OpIdx >= NumOps)
    > -    return false;
    > -
    > -  assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -         "Reg operand expected");
    > -  assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1))
    > -         && "Index mode or tied_to operand expected");
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -  ++OpIdx;
    > -
    > -  // For reg/reg form, base reg is followed by +/- reg shop imm.
    > -  // For immediate form, it is followed by +/- imm12.
    > -  // See also ARMAddressingModes.h (Addressing Mode #2).
    > -  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 =
    > -               (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
    > -  if (getIBit(insn) == 0) {
    > -    // For pre- and post-indexed case, add a reg0 operand (Addressing Mode #2).
    > -    // Otherwise, skip the reg operand since for addrmode_imm12, Rn has already
    > -    // been populated.
    > -    if (isPrePost) {
    > -      MI.addOperand(MCOperand::CreateReg(0));
    > -      OpIdx += 1;
    > -    }
    > -
    > -    unsigned Imm12 = slice(insn, 11, 0);
    > -    if (Opcode == ARM::LDRBi12 || Opcode == ARM::LDRi12 ||
    > -        Opcode == ARM::STRBi12 || Opcode == ARM::STRi12) {
    > -      // Disassemble the 12-bit immediate offset, which is the second operand in
    > -      // $addrmode_imm12 => (ops GPR:$base, i32imm:$offsimm).
    > -      int Offset = AddrOpcode == ARM_AM::add ? 1 * Imm12 : -1 * Imm12;
    > -      MI.addOperand(MCOperand::CreateImm(Offset));
    > -    } else {
    > -      // Disassemble the 12-bit immediate offset, which is the second operand in
    > -      // $am2offset => (ops GPR, i32imm).
    > -      unsigned Offset = ARM_AM::getAM2Opc(AddrOpcode, Imm12, ARM_AM::no_shift,
    > -                                          IndexMode);
    > -      MI.addOperand(MCOperand::CreateImm(Offset));
    > -    }
    > -    OpIdx += 1;
    > -  } else {
    > -    // If Inst{25} = 1 and Inst{4} != 0, we should reject this as invalid.
    > -    if (slice(insn,4,4) == 1)
    > -      return false;
    > -
    > -    // Disassemble the offset reg (Rm), shift type, and immediate shift length.
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -    // Inst{6-5} encodes the shift opcode.
    > -    ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
    > -    // Inst{11-7} encodes the imm5 shift amount.
    > -    unsigned ShImm = slice(insn, 11, 7);
    > -
    > -    // A8.4.1.  Possible rrx or shift amount of 32...
    > -    getImmShiftSE(ShOp, ShImm);
    > -    MI.addOperand(MCOperand::CreateImm(
    > -                    ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp, IndexMode)));
    > -    OpIdx += 2;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -static bool DisassembleLdFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -  return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false, B);
    > -}
    > -
    > -static bool DisassembleStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -  return DisassembleLdStFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B);
    > -}
    > -
    > -static bool HasDualReg(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return false;
    > -  case ARM::LDRD: case ARM::LDRD_PRE: case ARM::LDRD_POST:
    > -  case ARM::STRD: case ARM::STRD_PRE: case ARM::STRD_POST:
    > -    return true;
    > -  }
    > -}
    > -
    > -static bool DisassembleLdStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, bool isStore, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  bool isPrePost = isPrePostLdSt(MCID.TSFlags);
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(((!isStore && MCID.getNumDefs() > 0) ||
    > -          (isStore && (MCID.getNumDefs() == 0 || isPrePost)))
    > -         && "Invalid arguments");
    > -
    > -  // Operand 0 of a pre- and post-indexed store is the address base writeback.
    > -  if (isPrePost && isStore) {
    > -    assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Disassemble the dst/src operand.
    > -  if (OpIdx >= NumOps)
    > -    return false;
    > -
    > -  assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -         "Reg operand expected");
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // Fill in LDRD and STRD's second operand Rt operand.
    > -  if (HasDualReg(Opcode)) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn) + 1)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // After dst of a pre- and post-indexed load is the address base writeback.
    > -  if (isPrePost && !isStore) {
    > -    assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Disassemble the base operand.
    > -  if (OpIdx >= NumOps)
    > -    return false;
    > -
    > -  assert(OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -         "Reg operand expected");
    > -  assert((!isPrePost || (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1))
    > -         && "Offset mode or tied_to operand expected");
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -  ++OpIdx;
    > -
    > -  // For reg/reg form, base reg is followed by +/- reg.
    > -  // For immediate form, it is followed by +/- imm8.
    > -  if (OpIdx + 1 >= NumOps)
    > -    return false;
    > -
    > -  unsigned IndexMode =
    > -    (MCID.TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
    > -  ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
    > -  if (getAM3IBit(insn) == 1) {
    > -    // FIXME: Conditional while in the midst of refactoring addrmode3. Will
    > -    // go away entirely when the rest are converted.
    > -    if (Opcode != ARM::STRHTi && Opcode != ARM::LDRSBTi &&
    > -        Opcode != ARM::LDRHTi && Opcode != ARM::LDRSHTi) {
    > -      MI.addOperand(MCOperand::CreateReg(0));
    > -      ++OpIdx;
    > -    }
    > -
    > -    // Disassemble the 8-bit immediate offset (postidx_imm8).
    > -    unsigned Imm4H = (insn >> ARMII::ImmHiShift) & 0xF;
    > -    unsigned Imm4L = insn & 0xF;
    > -    unsigned Offset;
    > -    // FIXME: Remove the 'else' once done w/ addrmode3 refactor.
    > -    if (Opcode == ARM::STRHTi || Opcode == ARM::LDRSBTi ||
    > -        Opcode == ARM::LDRHTi || Opcode == ARM::LDRSHTi)
    > -      Offset = (Imm4H << 4) | Imm4L | (getUBit(insn) << 8);
    > -    else
    > -      Offset = ARM_AM::getAM3Opc(AddrOpcode, (Imm4H << 4) | Imm4L,
    > -                                 IndexMode);
    > -
    > -    MI.addOperand(MCOperand::CreateImm(Offset));
    > -    ++OpIdx;
    > -  } else {
    > -    // Disassemble the offset reg (Rm).
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -    // FIXME: Remove the 'else' once done w/ addrmode3 refactor.
    > -    if (Opcode == ARM::STRHTr || Opcode == ARM::LDRSBTr ||
    > -        Opcode == ARM::LDRHTr || Opcode == ARM::LDRSHTr)
    > -      MI.addOperand(MCOperand::CreateImm(getUBit(insn)));
    > -    else {
    > -      unsigned Offset = ARM_AM::getAM3Opc(AddrOpcode, 0);
    > -      MI.addOperand(MCOperand::CreateImm(Offset));
    > -    }
    > -    OpIdx += 2;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -static bool DisassembleLdMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -  return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, false,
    > -                                B);
    > -}
    > -
    > -static bool DisassembleStMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -  return DisassembleLdStMiscFrm(MI, Opcode, insn, NumOps, NumOpsAdded, true, B);
    > -}
    > -
    > -// The algorithm for disassembly of LdStMulFrm is different from others because
    > -// it explicitly populates the two predicate operands after the base register.
    > -// After that, we need to populate the reglist with each affected register
    > -// encoded as an MCOperand.
    > -static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 4 && "LdStMulFrm expects NumOps >= 4");
    > -  NumOpsAdded = 0;
    > -
    > -  unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
    > -
    > -  // Writeback to base, if necessary.
    > -  if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::STMIA_UPD ||
    > -      Opcode == ARM::LDMDA_UPD || Opcode == ARM::STMDA_UPD ||
    > -      Opcode == ARM::LDMDB_UPD || Opcode == ARM::STMDB_UPD ||
    > -      Opcode == ARM::LDMIB_UPD || Opcode == ARM::STMIB_UPD) {
    > -    MI.addOperand(MCOperand::CreateReg(Base));
    > -    ++NumOpsAdded;
    > -  }
    > -
    > -  // Add the base register operand.
    > -  MI.addOperand(MCOperand::CreateReg(Base));
    > -
    > -  // Handling the two predicate operands before the reglist.
    > -  int64_t CondVal = getCondField(insn);
    > -  if (CondVal == 0xF)
    > -    return false;
    > -  MI.addOperand(MCOperand::CreateImm(CondVal));
    > -  MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
    > -
    > -  NumOpsAdded += 3;
    > -
    > -  // Fill the variadic part of reglist.
    > -  unsigned RegListBits = insn & ((1 << 16) - 1);
    > -  for (unsigned i = 0; i < 16; ++i) {
    > -    if ((RegListBits >> i) & 1) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                         i)));
    > -      ++NumOpsAdded;
    > -    }
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// LDREX, LDREXB, LDREXH: Rd Rn
    > -// LDREXD:                Rd Rd+1 Rn
    > -// STREX, STREXB, STREXH: Rd Rm Rn
    > -// STREXD:                Rd Rm Rm+1 Rn
    > -//
    > -// SWP, SWPB:             Rd Rm Rn
    > -static bool DisassembleLdStExFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2
    > -         && OpInfo[0].RegClass == ARM::GPRRegClassID
    > -         && OpInfo[1].RegClass == ARM::GPRRegClassID
    > -         && "Expect 2 reg operands");
    > -
    > -  bool isStore = slice(insn, 20, 20) == 0;
    > -  bool isDW = (Opcode == ARM::LDREXD || Opcode == ARM::STREXD);
    > -
    > -  // Add the destination operand.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // Store register Exclusive needs a source operand.
    > -  if (isStore) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -    ++OpIdx;
    > -
    > -    if (isDW) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                         decodeRm(insn)+1)));
    > -      ++OpIdx;
    > -    }
    > -  } else if (isDW) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRd(insn)+1)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Finally add the pointer operand.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -// Misc. Arithmetic Instructions.
    > -// CLZ: Rd Rm
    > -// PKHBT, PKHTB: Rd Rn Rm , LSL/ASR #imm5
    > -// RBIT, REV, REV16, REVSH: Rd Rm
    > -static bool DisassembleArithMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2
    > -         && OpInfo[0].RegClass == ARM::GPRRegClassID
    > -         && OpInfo[1].RegClass == ARM::GPRRegClassID
    > -         && "Expect 2 reg operands");
    > -
    > -  bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID;
    > -
    > -  // Sanity check the registers, which should not be 15.
    > -  if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
    > -    return false;
    > -  if (ThreeReg && decodeRn(insn) == 15)
    > -    return false;
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  ++OpIdx;
    > -
    > -  if (ThreeReg) {
    > -    assert(NumOps >= 4 && "Expect >= 4 operands");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -  ++OpIdx;
    > -
    > -  // If there is still an operand info left which is an immediate operand, add
    > -  // an additional imm5 LSL/ASR operand.
    > -  if (ThreeReg && OpInfo[OpIdx].RegClass < 0
    > -      && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -    // Extract the 5-bit immediate field Inst{11-7}.
    > -    unsigned ShiftAmt = (insn >> ARMII::ShiftShift) & 0x1F;
    > -    if (Opcode == ARM::PKHBT || Opcode == ARM::PKHTB)
    > -      MI.addOperand(MCOperand::CreateImm(ShiftAmt));
    > -     else
    > -      MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ARM_AM::no_shift,
    > -                                                             ShiftAmt)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -/// DisassembleSatFrm - Disassemble saturate instructions:
    > -/// SSAT, SSAT16, USAT, and USAT16.
    > -static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  // A8.6.183 SSAT
    > -  // if d == 15 || n == 15 then UNPREDICTABLE;
    > -  if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
    > -    return false;
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands
    > -
    > -  // Disassemble register def.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -
    > -  unsigned Pos = slice(insn, 20, 16);
    > -  MI.addOperand(MCOperand::CreateImm(Pos));
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -
    > -  if (NumOpsAdded == 4) {
    > -    // Inst{6} encodes the shift type.
    > -    bool isASR = slice(insn, 6, 6);
    > -    // Inst{11-7} encodes the imm5 shift amount.
    > -    unsigned ShAmt = slice(insn, 11, 7);
    > -    MI.addOperand(MCOperand::CreateImm(isASR << 5 | ShAmt));
    > -  }
    > -  return true;
    > -}
    > -
    > -// Extend instructions.
    > -// SXT* and UXT*: Rd [Rn] Rm [rot_imm].
    > -// The 2nd operand register is Rn and the 3rd operand regsiter is Rm for the
    > -// three register operand form.  Otherwise, Rn=0b1111 and only Rm is used.
    > -static bool DisassembleExtFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  // A8.6.220 SXTAB
    > -  // if d == 15 || m == 15 then UNPREDICTABLE;
    > -  if (decodeRd(insn) == 15 || decodeRm(insn) == 15)
    > -    return false;
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2
    > -         && OpInfo[0].RegClass == ARM::GPRRegClassID
    > -         && OpInfo[1].RegClass == ARM::GPRRegClassID
    > -         && "Expect 2 reg operands");
    > -
    > -  bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass == ARM::GPRRegClassID;
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  ++OpIdx;
    > -
    > -  if (ThreeReg) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -  ++OpIdx;
    > -
    > -  // If there is still an operand info left which is an immediate operand, add
    > -  // an additional rotate immediate operand.
    > -  if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
    > -      && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -    // Extract the 2-bit rotate field Inst{11-10}.
    > -    unsigned rot = (insn >> ARMII::ExtRotImmShift) & 3;
    > -    MI.addOperand(MCOperand::CreateImm(rot));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -/////////////////////////////////////
    > -//                                 //
    > -//    Utility Functions For VFP    //
    > -//                                 //
    > -/////////////////////////////////////
    > -
    > -// Extract/Decode Dd/Sd:
    > -//
    > -// SP => d = UInt(Vd:D)
    > -// DP => d = UInt(D:Vd)
    > -static unsigned decodeVFPRd(uint32_t insn, bool isSPVFP) {
    > -  return isSPVFP ? (decodeRd(insn) << 1 | getDBit(insn))
    > -                 : (decodeRd(insn) | getDBit(insn) << 4);
    > -}
    > -
    > -// Extract/Decode Dn/Sn:
    > -//
    > -// SP => n = UInt(Vn:N)
    > -// DP => n = UInt(N:Vn)
    > -static unsigned decodeVFPRn(uint32_t insn, bool isSPVFP) {
    > -  return isSPVFP ? (decodeRn(insn) << 1 | getNBit(insn))
    > -                 : (decodeRn(insn) | getNBit(insn) << 4);
    > -}
    > -
    > -// Extract/Decode Dm/Sm:
    > -//
    > -// SP => m = UInt(Vm:M)
    > -// DP => m = UInt(M:Vm)
    > -static unsigned decodeVFPRm(uint32_t insn, bool isSPVFP) {
    > -  return isSPVFP ? (decodeRm(insn) << 1 | getMBit(insn))
    > -                 : (decodeRm(insn) | getMBit(insn) << 4);
    > -}
    > -
    > -// A7.5.1
    > -static APInt VFPExpandImm(unsigned char byte, unsigned N) {
    > -  assert(N == 32 || N == 64);
    > -
    > -  uint64_t Result;
    > -  unsigned bit6 = slice(byte, 6, 6);
    > -  if (N == 32) {
    > -    Result = slice(byte, 7, 7) << 31 | slice(byte, 5, 0) << 19;
    > -    if (bit6)
    > -      Result |= 0x1f << 25;
    > -    else
    > -      Result |= 0x1 << 30;
    > -  } else {
    > -    Result = (uint64_t)slice(byte, 7, 7) << 63 |
    > -             (uint64_t)slice(byte, 5, 0) << 48;
    > -    if (bit6)
    > -      Result |= 0xffULL << 54;
    > -    else
    > -      Result |= 0x1ULL << 62;
    > -  }
    > -  return APInt(N, Result);
    > -}
    > -
    > -// VFP Unary Format Instructions:
    > -//
    > -// VCMP[E]ZD, VCMP[E]ZS: compares one floating-point register with zero
    > -// VCVTDS, VCVTSD: converts between double-precision and single-precision
    > -// The rest of the instructions have homogeneous [VFP]Rd and [VFP]Rm registers.
    > -static bool DisassembleVFPUnaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 1 && "VFPUnaryFrm expects NumOps >= 1");
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  unsigned RegClass = OpInfo[OpIdx].RegClass;
    > -  assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
    > -         "Reg operand expected");
    > -  bool isSP = (RegClass == ARM::SPRRegClassID);
    > -
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP))));
    > -  ++OpIdx;
    > -
    > -  // Early return for compare with zero instructions.
    > -  if (Opcode == ARM::VCMPEZD || Opcode == ARM::VCMPEZS
    > -      || Opcode == ARM::VCMPZD || Opcode == ARM::VCMPZS)
    > -    return true;
    > -
    > -  RegClass = OpInfo[OpIdx].RegClass;
    > -  assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
    > -         "Reg operand expected");
    > -  isSP = (RegClass == ARM::SPRRegClassID);
    > -
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP))));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -// All the instructions have homogeneous [VFP]Rd, [VFP]Rn, and [VFP]Rm regs.
    > -// Some of them have operand constraints which tie the first operand in the
    > -// InOperandList to that of the dst.  As far as asm printing is concerned, this
    > -// tied_to operand is simply skipped.
    > -static bool DisassembleVFPBinaryFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 3 && "VFPBinaryFrm expects NumOps >= 3");
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  unsigned RegClass = OpInfo[OpIdx].RegClass;
    > -  assert((RegClass == ARM::SPRRegClassID || RegClass == ARM::DPRRegClassID) &&
    > -         "Reg operand expected");
    > -  bool isSP = (RegClass == ARM::SPRRegClassID);
    > -
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, RegClass, decodeVFPRd(insn, isSP))));
    > -  ++OpIdx;
    > -
    > -  // Skip tied_to operand constraint.
    > -  if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
    > -    assert(NumOps >= 4 && "Expect >=4 operands");
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    ++OpIdx;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, RegClass, decodeVFPRn(insn, isSP))));
    > -  ++OpIdx;
    > -
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, RegClass, decodeVFPRm(insn, isSP))));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -// A8.6.295 vcvt (floating-point <-> integer)
    > -// Int to FP: VSITOD, VSITOS, VUITOD, VUITOS
    > -// FP to Int: VTOSI[Z|R]D, VTOSI[Z|R]S, VTOUI[Z|R]D, VTOUI[Z|R]S
    > -//
    > -// A8.6.297 vcvt (floating-point and fixed-point)
    > -// Dd|Sd Dd|Sd(TIED_TO) #fbits(= 16|32 - UInt(imm4:i))
    > -static bool DisassembleVFPConv1Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 2 && "VFPConv1Frm expects NumOps >= 2");
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  bool SP = slice(insn, 8, 8) == 0; // A8.6.295 & A8.6.297
    > -  bool fixed_point = slice(insn, 17, 17) == 1; // A8.6.297
    > -  unsigned RegClassID = SP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
    > -
    > -  if (fixed_point) {
    > -    // A8.6.297
    > -    assert(NumOps >= 3 && "Expect >= 3 operands");
    > -    int size = slice(insn, 7, 7) == 0 ? 16 : 32;
    > -    int fbits = size - (slice(insn,3,0) << 1 | slice(insn,5,5));
    > -    MI.addOperand(MCOperand::CreateReg(
    > -                    getRegisterEnum(B, RegClassID,
    > -                                    decodeVFPRd(insn, SP))));
    > -
    > -    assert(MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 &&
    > -           "Tied to operand expected");
    > -    MI.addOperand(MI.getOperand(0));
    > -
    > -    assert(OpInfo[2].RegClass < 0 && !OpInfo[2].isPredicate() &&
    > -           !OpInfo[2].isOptionalDef() && "Imm operand expected");
    > -    MI.addOperand(MCOperand::CreateImm(fbits));
    > -
    > -    NumOpsAdded = 3;
    > -  } else {
    > -    // A8.6.295
    > -    // The Rd (destination) and Rm (source) bits have different interpretations
    > -    // depending on their single-precisonness.
    > -    unsigned d, m;
    > -    if (slice(insn, 18, 18) == 1) { // to_integer operation
    > -      d = decodeVFPRd(insn, true /* Is Single Precision */);
    > -      MI.addOperand(MCOperand::CreateReg(
    > -                      getRegisterEnum(B, ARM::SPRRegClassID, d)));
    > -      m = decodeVFPRm(insn, SP);
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, m)));
    > -    } else {
    > -      d = decodeVFPRd(insn, SP);
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, d)));
    > -      m = decodeVFPRm(insn, true /* Is Single Precision */);
    > -      MI.addOperand(MCOperand::CreateReg(
    > -                      getRegisterEnum(B, ARM::SPRRegClassID, m)));
    > -    }
    > -    NumOpsAdded = 2;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// VMOVRS - A8.6.330
    > -// Rt => Rd; Sn => UInt(Vn:N)
    > -static bool DisassembleVFPConv2Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 2 && "VFPConv2Frm expects NumOps >= 2");
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
    > -                                                     decodeVFPRn(insn, true))));
    > -  NumOpsAdded = 2;
    > -  return true;
    > -}
    > -
    > -// VMOVRRD - A8.6.332
    > -// Rt => Rd; Rt2 => Rn; Dm => UInt(M:Vm)
    > -//
    > -// VMOVRRS - A8.6.331
    > -// Rt => Rd; Rt2 => Rn; Sm => UInt(Vm:M); Sm1 = Sm+1
    > -static bool DisassembleVFPConv3Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 3 && "VFPConv3Frm expects NumOps >= 3");
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -  OpIdx = 2;
    > -
    > -  if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) {
    > -    unsigned Sm = decodeVFPRm(insn, true);
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
    > -                                                       Sm)));
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
    > -                                                       Sm+1)));
    > -    OpIdx += 2;
    > -  } else {
    > -    MI.addOperand(MCOperand::CreateReg(
    > -                    getRegisterEnum(B, ARM::DPRRegClassID,
    > -                                    decodeVFPRm(insn, false))));
    > -    ++OpIdx;
    > -  }
    > -  return true;
    > -}
    > -
    > -// VMOVSR - A8.6.330
    > -// Rt => Rd; Sn => UInt(Vn:N)
    > -static bool DisassembleVFPConv4Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 2 && "VFPConv4Frm expects NumOps >= 2");
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
    > -                                                     decodeVFPRn(insn, true))));
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  NumOpsAdded = 2;
    > -  return true;
    > -}
    > -
    > -// VMOVDRR - A8.6.332
    > -// Rt => Rd; Rt2 => Rn; Dm => UInt(M:Vm)
    > -//
    > -// VMOVRRS - A8.6.331
    > -// Rt => Rd; Rt2 => Rn; Sm => UInt(Vm:M); Sm1 = Sm+1
    > -static bool DisassembleVFPConv5Frm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 3 && "VFPConv5Frm expects NumOps >= 3");
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  if (OpInfo[OpIdx].RegClass == ARM::SPRRegClassID) {
    > -    unsigned Sm = decodeVFPRm(insn, true);
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
    > -                                                       Sm)));
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::SPRRegClassID,
    > -                                                       Sm+1)));
    > -    OpIdx += 2;
    > -  } else {
    > -    MI.addOperand(MCOperand::CreateReg(
    > -                    getRegisterEnum(B, ARM::DPRRegClassID,
    > -                                    decodeVFPRm(insn, false))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -  OpIdx += 2;
    > -  return true;
    > -}
    > -
    > -// VFP Load/Store Instructions.
    > -// VLDRD, VLDRS, VSTRD, VSTRS
    > -static bool DisassembleVFPLdStFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 3 && "VFPLdStFrm expects NumOps >= 3");
    > -
    > -  bool isSPVFP = (Opcode == ARM::VLDRS || Opcode == ARM::VSTRS);
    > -  unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
    > -
    > -  // Extract Dd/Sd for operand 0.
    > -  unsigned RegD = decodeVFPRd(insn, isSPVFP);
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID, RegD)));
    > -
    > -  unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
    > -  MI.addOperand(MCOperand::CreateReg(Base));
    > -
    > -  // Next comes the AM5 Opcode.
    > -  ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
    > -  unsigned char Imm8 = insn & 0xFF;
    > -  MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(AddrOpcode, Imm8)));
    > -
    > -  NumOpsAdded = 3;
    > -
    > -  return true;
    > -}
    > -
    > -// VFP Load/Store Multiple Instructions.
    > -// We have an optional write back reg, the base, and two predicate operands.
    > -// It is then followed by a reglist of either DPR(s) or SPR(s).
    > -//
    > -// VLDMD[_UPD], VLDMS[_UPD], VSTMD[_UPD], VSTMS[_UPD]
    > -static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 4 && "VFPLdStMulFrm expects NumOps >= 4");
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
    > -
    > -  // Writeback to base, if necessary.
    > -  if (Opcode == ARM::VLDMDIA_UPD || Opcode == ARM::VLDMSIA_UPD ||
    > -      Opcode == ARM::VLDMDDB_UPD || Opcode == ARM::VLDMSDB_UPD ||
    > -      Opcode == ARM::VSTMDIA_UPD || Opcode == ARM::VSTMSIA_UPD ||
    > -      Opcode == ARM::VSTMDDB_UPD || Opcode == ARM::VSTMSDB_UPD) {
    > -    MI.addOperand(MCOperand::CreateReg(Base));
    > -    ++OpIdx;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(Base));
    > -
    > -  // Handling the two predicate operands before the reglist.
    > -  int64_t CondVal = getCondField(insn);
    > -  if (CondVal == 0xF)
    > -    return false;
    > -  MI.addOperand(MCOperand::CreateImm(CondVal));
    > -  MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
    > -
    > -  OpIdx += 3;
    > -
    > -  bool isSPVFP = (Opcode == ARM::VLDMSIA     ||
    > -                  Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMSDB_UPD ||
    > -                  Opcode == ARM::VSTMSIA     ||
    > -                  Opcode == ARM::VSTMSIA_UPD || Opcode == ARM::VSTMSDB_UPD);
    > -  unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID;
    > -
    > -  // Extract Dd/Sd.
    > -  unsigned RegD = decodeVFPRd(insn, isSPVFP);
    > -
    > -  // Fill the variadic part of reglist.
    > -  unsigned char Imm8 = insn & 0xFF;
    > -  unsigned Regs = isSPVFP ? Imm8 : Imm8/2;
    > -
    > -  // Apply some sanity checks before proceeding.
    > -  if (Regs == 0 || (RegD + Regs) > 32 || (!isSPVFP && Regs > 16))
    > -    return false;
    > -
    > -  for (unsigned i = 0; i < Regs; ++i) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassID,
    > -                                                       RegD + i)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// Misc. VFP Instructions.
    > -// FMSTAT (vmrs with Rt=0b1111, i.e., to apsr_nzcv and no register operand)
    > -// FCONSTD (DPR and a VFPf64Imm operand)
    > -// FCONSTS (SPR and a VFPf32Imm operand)
    > -// VMRS/VMSR (GPR operand)
    > -static bool DisassembleVFPMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  if (Opcode == ARM::FMSTAT)
    > -    return true;
    > -
    > -  assert(NumOps >= 2 && "VFPMiscFrm expects >=2 operands");
    > -
    > -  unsigned RegEnum = 0;
    > -  switch (OpInfo[0].RegClass) {
    > -  case ARM::DPRRegClassID:
    > -    RegEnum = getRegisterEnum(B, ARM::DPRRegClassID, decodeVFPRd(insn, false));
    > -    break;
    > -  case ARM::SPRRegClassID:
    > -    RegEnum = getRegisterEnum(B, ARM::SPRRegClassID, decodeVFPRd(insn, true));
    > -    break;
    > -  case ARM::GPRRegClassID:
    > -    RegEnum = getRegisterEnum(B, ARM::GPRRegClassID, decodeRd(insn));
    > -    break;
    > -  default:
    > -    assert(0 && "Invalid reg class id");
    > -    return false;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(RegEnum));
    > -  ++OpIdx;
    > -
    > -  // Extract/decode the f64/f32 immediate.
    > -  if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
    > -        && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -    // The asm syntax specifies the floating point value, not the 8-bit literal.
    > -    APInt immRaw = VFPExpandImm(slice(insn,19,16) << 4 | slice(insn, 3, 0),
    > -                             Opcode == ARM::FCONSTD ? 64 : 32);
    > -    APFloat immFP = APFloat(immRaw, true);
    > -    double imm = Opcode == ARM::FCONSTD ? immFP.convertToDouble() :
    > -      immFP.convertToFloat();
    > -    MI.addOperand(MCOperand::CreateFPImm(imm));
    > -
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// DisassembleThumbFrm() is defined in ThumbDisassemblerCore.h file.
    > -#include "ThumbDisassemblerCore.h"
    > -
    > -/////////////////////////////////////////////////////
    > -//                                                 //
    > -//     Utility Functions For ARM Advanced SIMD     //
    > -//                                                 //
    > -/////////////////////////////////////////////////////
    > -
    > -// The following NEON namings are based on A8.6.266 VABA, VABAL.  Notice that
    > -// A8.6.303 VDUP (ARM core register)'s D/Vd pair is the N/Vn pair of VABA/VABAL.
    > -
    > -// A7.3 Register encoding
    > -
    > -// Extract/Decode NEON D/Vd:
    > -//
    > -// Note that for quadword, Qd = UInt(D:Vd<3:1>) = Inst{22:15-13}, whereas for
    > -// doubleword, Dd = UInt(D:Vd).  We compensate for this difference by
    > -// handling it in the getRegisterEnum() utility function.
    > -// D = Inst{22}, Vd = Inst{15-12}
    > -static unsigned decodeNEONRd(uint32_t insn) {
    > -  return ((insn >> ARMII::NEON_D_BitShift) & 1) << 4
    > -    | ((insn >> ARMII::NEON_RegRdShift) & ARMII::NEONRegMask);
    > -}
    > -
    > -// Extract/Decode NEON N/Vn:
    > -//
    > -// Note that for quadword, Qn = UInt(N:Vn<3:1>) = Inst{7:19-17}, whereas for
    > -// doubleword, Dn = UInt(N:Vn).  We compensate for this difference by
    > -// handling it in the getRegisterEnum() utility function.
    > -// N = Inst{7}, Vn = Inst{19-16}
    > -static unsigned decodeNEONRn(uint32_t insn) {
    > -  return ((insn >> ARMII::NEON_N_BitShift) & 1) << 4
    > -    | ((insn >> ARMII::NEON_RegRnShift) & ARMII::NEONRegMask);
    > -}
    > -
    > -// Extract/Decode NEON M/Vm:
    > -//
    > -// Note that for quadword, Qm = UInt(M:Vm<3:1>) = Inst{5:3-1}, whereas for
    > -// doubleword, Dm = UInt(M:Vm).  We compensate for this difference by
    > -// handling it in the getRegisterEnum() utility function.
    > -// M = Inst{5}, Vm = Inst{3-0}
    > -static unsigned decodeNEONRm(uint32_t insn) {
    > -  return ((insn >> ARMII::NEON_M_BitShift) & 1) << 4
    > -    | ((insn >> ARMII::NEON_RegRmShift) & ARMII::NEONRegMask);
    > -}
    > -
    > -namespace {
    > -enum ElemSize {
    > -  ESizeNA = 0,
    > -  ESize8 = 8,
    > -  ESize16 = 16,
    > -  ESize32 = 32,
    > -  ESize64 = 64
    > -};
    > -} // End of unnamed namespace
    > -
    > -// size        field -> Inst{11-10}
    > -// index_align field -> Inst{7-4}
    > -//
    > -// The Lane Index interpretation depends on the Data Size:
    > -//   8  (encoded as size = 0b00) -> Index = index_align[3:1]
    > -//   16 (encoded as size = 0b01) -> Index = index_align[3:2]
    > -//   32 (encoded as size = 0b10) -> Index = index_align[3]
    > -//
    > -// Ref: A8.6.317 VLD4 (single 4-element structure to one lane).
    > -static unsigned decodeLaneIndex(uint32_t insn) {
    > -  unsigned size = insn >> 10 & 3;
    > -  assert((size == 0 || size == 1 || size == 2) &&
    > -         "Encoding error: size should be either 0, 1, or 2");
    > -
    > -  unsigned index_align = insn >> 4 & 0xF;
    > -  return (index_align >> 1) >> size;
    > -}
    > -
    > -// imm64 = AdvSIMDExpandImm(op, cmode, i:imm3:imm4)
    > -// op = Inst{5}, cmode = Inst{11-8}
    > -// i = Inst{24} (ARM architecture)
    > -// imm3 = Inst{18-16}, imm4 = Inst{3-0}
    > -// Ref: Table A7-15 Modified immediate values for Advanced SIMD instructions.
    > -static uint64_t decodeN1VImm(uint32_t insn, ElemSize esize) {
    > -  unsigned char op = (insn >> 5) & 1;
    > -  unsigned char cmode = (insn >> 8) & 0xF;
    > -  unsigned char Imm8 = ((insn >> 24) & 1) << 7 |
    > -                       ((insn >> 16) & 7) << 4 |
    > -                       (insn & 0xF);
    > -  return (op << 12) | (cmode << 8) | Imm8;
    > -}
    > -
    > -// A8.6.339 VMUL, VMULL (by scalar)
    > -// ESize16 => m = Inst{2-0} (Vm<2:0>) D0-D7
    > -// ESize32 => m = Inst{3-0} (Vm<3:0>) D0-D15
    > -static unsigned decodeRestrictedDm(uint32_t insn, ElemSize esize) {
    > -  switch (esize) {
    > -  case ESize16:
    > -    return insn & 7;
    > -  case ESize32:
    > -    return insn & 0xF;
    > -  default:
    > -    assert(0 && "Unreachable code!");
    > -    return 0;
    > -  }
    > -}
    > -
    > -// A8.6.339 VMUL, VMULL (by scalar)
    > -// ESize16 => index = Inst{5:3} (M:Vm<3>) D0-D7
    > -// ESize32 => index = Inst{5}   (M)       D0-D15
    > -static unsigned decodeRestrictedDmIndex(uint32_t insn, ElemSize esize) {
    > -  switch (esize) {
    > -  case ESize16:
    > -    return (((insn >> 5) & 1) << 1) | ((insn >> 3) & 1);
    > -  case ESize32:
    > -    return (insn >> 5) & 1;
    > -  default:
    > -    assert(0 && "Unreachable code!");
    > -    return 0;
    > -  }
    > -}
    > -
    > -// A8.6.296 VCVT (between floating-point and fixed-point, Advanced SIMD)
    > -// (64 - ) is encoded as imm6, i.e., Inst{21-16}.
    > -static unsigned decodeVCVTFractionBits(uint32_t insn) {
    > -  return 64 - ((insn >> 16) & 0x3F);
    > -}
    > -
    > -// A8.6.302 VDUP (scalar)
    > -// ESize8  => index = Inst{19-17}
    > -// ESize16 => index = Inst{19-18}
    > -// ESize32 => index = Inst{19}
    > -static unsigned decodeNVLaneDupIndex(uint32_t insn, ElemSize esize) {
    > -  switch (esize) {
    > -  case ESize8:
    > -    return (insn >> 17) & 7;
    > -  case ESize16:
    > -    return (insn >> 18) & 3;
    > -  case ESize32:
    > -    return (insn >> 19) & 1;
    > -  default:
    > -    assert(0 && "Unspecified element size!");
    > -    return 0;
    > -  }
    > -}
    > -
    > -// A8.6.328 VMOV (ARM core register to scalar)
    > -// A8.6.329 VMOV (scalar to ARM core register)
    > -// ESize8  => index = Inst{21:6-5}
    > -// ESize16 => index = Inst{21:6}
    > -// ESize32 => index = Inst{21}
    > -static unsigned decodeNVLaneOpIndex(uint32_t insn, ElemSize esize) {
    > -  switch (esize) {
    > -  case ESize8:
    > -    return ((insn >> 21) & 1) << 2 | ((insn >> 5) & 3);
    > -  case ESize16:
    > -    return ((insn >> 21) & 1) << 1 | ((insn >> 6) & 1);
    > -  case ESize32:
    > -    return ((insn >> 21) & 1);
    > -  default:
    > -    assert(0 && "Unspecified element size!");
    > -    return 0;
    > -  }
    > -}
    > -
    > -// Imm6 = Inst{21-16}, L = Inst{7}
    > -//
    > -// LeftShift == true (A8.6.367 VQSHL, A8.6.387 VSLI):
    > -// case L:imm6 of
    > -//   '0001xxx' => esize = 8; shift_amount = imm6 - 8
    > -//   '001xxxx' => esize = 16; shift_amount = imm6 - 16
    > -//   '01xxxxx' => esize = 32; shift_amount = imm6 - 32
    > -//   '1xxxxxx' => esize = 64; shift_amount = imm6
    > -//
    > -// LeftShift == false (A8.6.376 VRSHR, A8.6.368 VQSHRN):
    > -// case L:imm6 of
    > -//   '0001xxx' => esize = 8; shift_amount = 16 - imm6
    > -//   '001xxxx' => esize = 16; shift_amount = 32 - imm6
    > -//   '01xxxxx' => esize = 32; shift_amount = 64 - imm6
    > -//   '1xxxxxx' => esize = 64; shift_amount = 64 - imm6
    > -//
    > -static unsigned decodeNVSAmt(uint32_t insn, bool LeftShift) {
    > -  ElemSize esize = ESizeNA;
    > -  unsigned L = (insn >> 7) & 1;
    > -  unsigned imm6 = (insn >> 16) & 0x3F;
    > -  if (L == 0) {
    > -    if (imm6 >> 3 == 1)
    > -      esize = ESize8;
    > -    else if (imm6 >> 4 == 1)
    > -      esize = ESize16;
    > -    else if (imm6 >> 5 == 1)
    > -      esize = ESize32;
    > -    else
    > -      assert(0 && "Wrong encoding of Inst{7:21-16}!");
    > -  } else
    > -    esize = ESize64;
    > -
    > -  if (LeftShift)
    > -    return esize == ESize64 ? imm6 : (imm6 - esize);
    > -  else
    > -    return esize == ESize64 ? (esize - imm6) : (2*esize - imm6);
    > -}
    > -
    > -// A8.6.305 VEXT
    > -// Imm4 = Inst{11-8}
    > -static unsigned decodeN3VImm(uint32_t insn) {
    > -  return (insn >> 8) & 0xF;
    > -}
    > -
    > -// VLD*
    > -//   D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm]
    > -// VLD*LN*
    > -//   D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm] TIED_TO ... imm(idx)
    > -// VST*
    > -//   Rn [TIED_TO Rn] align [Rm] D[d] D[d2] ...
    > -// VST*LN*
    > -//   Rn [TIED_TO Rn] align [Rm] D[d] D[d2] ... [imm(idx)]
    > -//
    > -// Correctly set VLD*/VST*'s TIED_TO GPR, as the asm printer needs it.
    > -static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, bool Store, bool DblSpaced,
    > -    unsigned alignment, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -
    > -  // At least one DPR register plus addressing mode #6.
    > -  assert(NumOps >= 3 && "Expect >= 3 operands");
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  // We have homogeneous NEON registers for Load/Store.
    > -  unsigned RegClass = 0;
    > -
    > -  // Double-spaced registers have increments of 2.
    > -  unsigned Inc = DblSpaced ? 2 : 1;
    > -
    > -  unsigned Rn = decodeRn(insn);
    > -  unsigned Rm = decodeRm(insn);
    > -  unsigned Rd = decodeNEONRd(insn);
    > -
    > -  // A7.7.1 Advanced SIMD addressing mode.
    > -  bool WB = Rm != 15;
    > -
    > -  // LLVM Addressing Mode #6.
    > -  unsigned RmEnum = 0;
    > -  if (WB && Rm != 13)
    > -    RmEnum = getRegisterEnum(B, ARM::GPRRegClassID, Rm);
    > -
    > -  if (Store) {
    > -    // Consume possible WB, AddrMode6, possible increment reg, the DPR/QPR's,
    > -    // then possible lane index.
    > -    assert(OpIdx < NumOps && OpInfo[0].RegClass == ARM::GPRRegClassID &&
    > -           "Reg operand expected");
    > -
    > -    if (WB) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                         Rn)));
    > -      ++OpIdx;
    > -    }
    > -
    > -    assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected");
    > -    // addrmode6 := (ops GPR:$addr, i32imm)
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       Rn)));
    > -    MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment
    > -    OpIdx += 2;
    > -
    > -    if (WB) {
    > -      MI.addOperand(MCOperand::CreateReg(RmEnum));
    > -      ++OpIdx;
    > -    }
    > -
    > -    assert(OpIdx < NumOps &&
    > -           (OpInfo[OpIdx].RegClass == ARM::DPRRegClassID ||
    > -            OpInfo[OpIdx].RegClass == ARM::QPRRegClassID) &&
    > -           "Reg operand expected");
    > -
    > -    RegClass = OpInfo[OpIdx].RegClass;
    > -    while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
    > -      MI.addOperand(MCOperand::CreateReg(
    > -                      getRegisterEnum(B, RegClass, Rd)));
    > -      Rd += Inc;
    > -      ++OpIdx;
    > -    }
    > -
    > -    // Handle possible lane index.
    > -    if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
    > -        && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -      MI.addOperand(MCOperand::CreateImm(decodeLaneIndex(insn)));
    > -      ++OpIdx;
    > -    }
    > -
    > -  } else {
    > -    // Consume the DPR/QPR's, possible WB, AddrMode6, possible incrment reg,
    > -    // possible TIED_TO DPR/QPR's (ignored), then possible lane index.
    > -    RegClass = OpInfo[0].RegClass;
    > -
    > -    while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
    > -      MI.addOperand(MCOperand::CreateReg(
    > -                      getRegisterEnum(B, RegClass, Rd)));
    > -      Rd += Inc;
    > -      ++OpIdx;
    > -    }
    > -
    > -    if (WB) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                         Rn)));
    > -      ++OpIdx;
    > -    }
    > -
    > -    assert((OpIdx+1) < NumOps && OpInfo[OpIdx].RegClass == ARM::GPRRegClassID &&
    > -           OpInfo[OpIdx + 1].RegClass < 0 && "Addrmode #6 Operands expected");
    > -    // addrmode6 := (ops GPR:$addr, i32imm)
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       Rn)));
    > -    MI.addOperand(MCOperand::CreateImm(alignment)); // Alignment
    > -    OpIdx += 2;
    > -
    > -    if (WB) {
    > -      MI.addOperand(MCOperand::CreateReg(RmEnum));
    > -      ++OpIdx;
    > -    }
    > -
    > -    while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) {
    > -      assert(MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1 &&
    > -             "Tied to operand expected");
    > -      MI.addOperand(MCOperand::CreateReg(0));
    > -      ++OpIdx;
    > -    }
    > -
    > -    // Handle possible lane index.
    > -    if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
    > -        && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -      MI.addOperand(MCOperand::CreateImm(decodeLaneIndex(insn)));
    > -      ++OpIdx;
    > -    }
    > -  }
    > -
    > -  // Accessing registers past the end of the NEON register file is not
    > -  // defined.
    > -  if (Rd > 32)
    > -    return false;
    > -
    > -  return true;
    > -}
    > -
    > -// A8.6.308, A8.6.311, A8.6.314, A8.6.317.
    > -static bool Align4OneLaneInst(unsigned elem, unsigned size,
    > -    unsigned index_align, unsigned & alignment) {
    > -  unsigned bits = 0;
    > -  switch (elem) {
    > -  default:
    > -    return false;
    > -  case 1:
    > -    // A8.6.308
    > -    if (size == 0)
    > -      return slice(index_align, 0, 0) == 0;
    > -    else if (size == 1) {
    > -      bits = slice(index_align, 1, 0);
    > -      if (bits != 0 && bits != 1)
    > -        return false;
    > -      if (bits == 1)
    > -        alignment = 16;
    > -      return true;
    > -    } else if (size == 2) {
    > -      bits = slice(index_align, 2, 0);
    > -      if (bits != 0 && bits != 3)
    > -        return false;
    > -      if (bits == 3)
    > -        alignment = 32;
    > -      return true;;
    > -    }
    > -    return true;
    > -  case 2:
    > -    // A8.6.311
    > -    if (size == 0) {
    > -      if (slice(index_align, 0, 0) == 1)
    > -        alignment = 16;
    > -      return true;
    > -    } if (size == 1) {
    > -      if (slice(index_align, 0, 0) == 1)
    > -        alignment = 32;
    > -      return true;
    > -    } else if (size == 2) {
    > -      if (slice(index_align, 1, 1) != 0)
    > -        return false;
    > -      if (slice(index_align, 0, 0) == 1)
    > -        alignment = 64;
    > -      return true;;
    > -    }
    > -    return true;
    > -  case 3:
    > -    // A8.6.314
    > -    if (size == 0) {
    > -      if (slice(index_align, 0, 0) != 0)
    > -        return false;
    > -      return true;
    > -    } if (size == 1) {
    > -      if (slice(index_align, 0, 0) != 0)
    > -        return false;
    > -      return true;
    > -      return true;
    > -    } else if (size == 2) {
    > -      if (slice(index_align, 1, 0) != 0)
    > -        return false;
    > -      return true;;
    > -    }
    > -    return true;
    > -  case 4:
    > -    // A8.6.317
    > -    if (size == 0) {
    > -      if (slice(index_align, 0, 0) == 1)
    > -        alignment = 32;
    > -      return true;
    > -    } if (size == 1) {
    > -      if (slice(index_align, 0, 0) == 1)
    > -        alignment = 64;
    > -      return true;
    > -    } else if (size == 2) {
    > -      bits = slice(index_align, 1, 0);
    > -      if (bits == 3)
    > -        return false;
    > -      if (bits == 1)
    > -        alignment = 64;
    > -      else if (bits == 2)
    > -        alignment = 128;
    > -      return true;;
    > -    }
    > -    return true;
    > -  }
    > -}
    > -
    > -// A7.7
    > -// If L (Inst{21}) == 0, store instructions.
    > -// Find out about double-spaced-ness of the Opcode and pass it on to
    > -// DisassembleNLdSt0().
    > -static bool DisassembleNLdSt(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const StringRef Name = ARMInsts[Opcode].Name;
    > -  bool DblSpaced = false;
    > -  // 0 represents standard alignment, i.e., unaligned data access.
    > -  unsigned alignment = 0;
    > -
    > -  unsigned elem = 0; // legal values: {1, 2, 3, 4}
    > -  if (Name.startswith("VST1") || Name.startswith("VLD1"))
    > -    elem = 1;
    > -
    > -  if (Name.startswith("VST2") || Name.startswith("VLD2"))
    > -    elem = 2;
    > -
    > -  if (Name.startswith("VST3") || Name.startswith("VLD3"))
    > -    elem = 3;
    > -
    > -  if (Name.startswith("VST4") || Name.startswith("VLD4"))
    > -    elem = 4;
    > -
    > -  if (Name.find("LN") != std::string::npos) {
    > -    // To one lane instructions.
    > -    // See, for example, 8.6.317 VLD4 (single 4-element structure to one lane).
    > -
    > -    // Utility function takes number of elements, size, and index_align.
    > -    if (!Align4OneLaneInst(elem,
    > -                           slice(insn, 11, 10),
    > -                           slice(insn, 7, 4),
    > -                           alignment))
    > -      return false;
    > -
    > -    //  == 16 && Inst{5} == 1 --> DblSpaced = true
    > -    if (Name.endswith("16") || Name.endswith("16_UPD"))
    > -      DblSpaced = slice(insn, 5, 5) == 1;
    > -
    > -    //  == 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 {
    > -      if (a) {
    > -        // A8.6.315 VLD3 (single 3-element structure to all lanes)
    > -        // The a bit must be encoded as 0.
    > -        return false;
    > -      }
    > -    }
    > -  } else {
    > -    // Multiple n-element structures with type encoded as Inst{11-8}.
    > -    // See, for example, A8.6.316 VLD4 (multiple 4-element structures).
    > -
    > -    // Inst{5-4} encodes alignment.
    > -    unsigned align = slice(insn, 5, 4);
    > -    switch (align) {
    > -    default:
    > -      break;
    > -    case 1:
    > -      alignment = 64; break;
    > -    case 2:
    > -      alignment = 128; break;
    > -    case 3:
    > -      alignment = 256; break;
    > -    }
    > -
    > -    unsigned type = slice(insn, 11, 8);
    > -    // Reject UNDEFINED instructions based on type and align.
    > -    // Plus set DblSpaced flag where appropriate.
    > -    switch (elem) {
    > -    default:
    > -      break;
    > -    case 1:
    > -      // n == 1
    > -      // A8.6.307 & A8.6.391
    > -      if ((type == 7  && slice(align, 1, 1) == 1) ||
    > -          (type == 10 && align == 3) ||
    > -          (type == 6  && slice(align, 1, 1) == 1))
    > -        return false;
    > -      break;
    > -    case 2:
    > -      // n == 2 && type == 0b1001 -> DblSpaced = true
    > -      // A8.6.310 & A8.6.393
    > -      if ((type == 8 || type == 9) && align == 3)
    > -        return false;
    > -      DblSpaced = (type == 9);
    > -      break;
    > -    case 3:
    > -      // n == 3 && type == 0b0101 -> DblSpaced = true
    > -      // A8.6.313 & A8.6.395
    > -      if (slice(insn, 7, 6) == 3 || slice(align, 1, 1) == 1)
    > -        return false;
    > -      DblSpaced = (type == 5);
    > -      break;
    > -    case 4:
    > -      // n == 4 && type == 0b0001 -> DblSpaced = true
    > -      // A8.6.316 & A8.6.397
    > -      if (slice(insn, 7, 6) == 3)
    > -        return false;
    > -      DblSpaced = (type == 1);
    > -      break;
    > -    }
    > -  }
    > -  return DisassembleNLdSt0(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                           slice(insn, 21, 21) == 0, DblSpaced, alignment/8, B);
    > -}
    > -
    > -// VMOV (immediate)
    > -//   Qd/Dd imm
    > -// VBIC (immediate)
    > -// VORR (immediate)
    > -//   Qd/Dd imm src(=Qd/Dd)
    > -static bool DisassembleN1RegModImmFrm(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -
    > -  assert(NumOps >= 2 &&
    > -         (OpInfo[0].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[0].RegClass == ARM::QPRRegClassID) &&
    > -         (OpInfo[1].RegClass < 0) &&
    > -         "Expect 1 reg operand followed by 1 imm operand");
    > -
    > -  // Qd/Dd = Inst{22:15-12} => NEON Rd
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass,
    > -                                                     decodeNEONRd(insn))));
    > -
    > -  ElemSize esize = ESizeNA;
    > -  switch (Opcode) {
    > -  case ARM::VMOVv8i8:
    > -  case ARM::VMOVv16i8:
    > -    esize = ESize8;
    > -    break;
    > -  case ARM::VMOVv4i16:
    > -  case ARM::VMOVv8i16:
    > -  case ARM::VMVNv4i16:
    > -  case ARM::VMVNv8i16:
    > -  case ARM::VBICiv4i16:
    > -  case ARM::VBICiv8i16:
    > -  case ARM::VORRiv4i16:
    > -  case ARM::VORRiv8i16:
    > -    esize = ESize16;
    > -    break;
    > -  case ARM::VMOVv2i32:
    > -  case ARM::VMOVv4i32:
    > -  case ARM::VMVNv2i32:
    > -  case ARM::VMVNv4i32:
    > -  case ARM::VBICiv2i32:
    > -  case ARM::VBICiv4i32:
    > -  case ARM::VORRiv2i32:
    > -  case ARM::VORRiv4i32:
    > -    esize = ESize32;
    > -    break;
    > -  case ARM::VMOVv1i64:
    > -  case ARM::VMOVv2i64:
    > -    esize = ESize64;
    > -    break;
    > -  default:
    > -    assert(0 && "Unexpected opcode!");
    > -    return false;
    > -  }
    > -
    > -  // One register and a modified immediate value.
    > -  // Add the imm operand.
    > -  MI.addOperand(MCOperand::CreateImm(decodeN1VImm(insn, esize)));
    > -
    > -  NumOpsAdded = 2;
    > -
    > -  // VBIC/VORRiv*i* variants have an extra $src = $Vd to be filled in.
    > -  if (NumOps >= 3 &&
    > -      (OpInfo[2].RegClass == ARM::DPRRegClassID ||
    > -       OpInfo[2].RegClass == ARM::QPRRegClassID)) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[0].RegClass,
    > -                                                     decodeNEONRd(insn))));
    > -    NumOpsAdded += 1;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -namespace {
    > -enum N2VFlag {
    > -  N2V_None,
    > -  N2V_VectorDupLane,
    > -  N2V_VectorConvert_Between_Float_Fixed
    > -};
    > -} // End of unnamed namespace
    > -
    > -// Vector Convert [between floating-point and fixed-point]
    > -//   Qd/Dd Qm/Dm [fbits]
    > -//
    > -// Vector Duplicate Lane (from scalar to all elements) Instructions.
    > -// VDUPLN16d, VDUPLN16q, VDUPLN32d, VDUPLN32q, VDUPLN8d, VDUPLN8q:
    > -//   Qd/Dd Dm index
    > -//
    > -// Vector Move Long:
    > -//   Qd Dm
    > -//
    > -// Vector Move Narrow:
    > -//   Dd Qm
    > -//
    > -// Others
    > -static bool DisassembleNVdVmOptImm(MCInst &MI, unsigned Opc, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, N2VFlag Flag, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opc];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -
    > -  assert(NumOps >= 2 &&
    > -         (OpInfo[0].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[0].RegClass == ARM::QPRRegClassID) &&
    > -         (OpInfo[1].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[1].RegClass == ARM::QPRRegClassID) &&
    > -         "Expect >= 2 operands and first 2 as reg operands");
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  ElemSize esize = ESizeNA;
    > -  if (Flag == N2V_VectorDupLane) {
    > -    // VDUPLN has its index embedded.  Its size can be inferred from the Opcode.
    > -    assert(Opc >= ARM::VDUPLN16d && Opc <= ARM::VDUPLN8q &&
    > -           "Unexpected Opcode");
    > -    esize = (Opc == ARM::VDUPLN8d || Opc == ARM::VDUPLN8q) ? ESize8
    > -       : ((Opc == ARM::VDUPLN16d || Opc == ARM::VDUPLN16q) ? ESize16
    > -                                                           : ESize32);
    > -  }
    > -
    > -  // Qd/Dd = Inst{22:15-12} => NEON Rd
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     decodeNEONRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // VPADAL...
    > -  if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
    > -    // TIED_TO operand.
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Dm = Inst{5:3-0} => NEON Rm
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     decodeNEONRm(insn))));
    > -  ++OpIdx;
    > -
    > -  // VZIP and others have two TIED_TO reg operands.
    > -  int Idx;
    > -  while (OpIdx < NumOps &&
    > -         (Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
    > -    // Add TIED_TO operand.
    > -    MI.addOperand(MI.getOperand(Idx));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Add the imm operand, if required.
    > -  if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
    > -      && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -
    > -    unsigned imm = 0xFFFFFFFF;
    > -
    > -    if (Flag == N2V_VectorDupLane)
    > -      imm = decodeNVLaneDupIndex(insn, esize);
    > -    if (Flag == N2V_VectorConvert_Between_Float_Fixed)
    > -      imm = decodeVCVTFractionBits(insn);
    > -
    > -    assert(imm != 0xFFFFFFFF && "Internal error");
    > -    MI.addOperand(MCOperand::CreateImm(imm));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -static bool DisassembleN2RegFrm(MCInst &MI, unsigned Opc, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
    > -                                N2V_None, B);
    > -}
    > -static bool DisassembleNVCVTFrm(MCInst &MI, unsigned Opc, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
    > -                                N2V_VectorConvert_Between_Float_Fixed, B);
    > -}
    > -static bool DisassembleNVecDupLnFrm(MCInst &MI, unsigned Opc, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVdVmOptImm(MI, Opc, insn, NumOps, NumOpsAdded,
    > -                                N2V_VectorDupLane, B);
    > -}
    > -
    > -// Vector Shift [Accumulate] Instructions.
    > -// Qd/Dd [Qd/Dd (TIED_TO)] Qm/Dm ShiftAmt
    > -//
    > -// Vector Shift Left Long (with maximum shift count) Instructions.
    > -// VSHLLi16, VSHLLi32, VSHLLi8: Qd Dm imm (== size)
    > -//
    > -static bool DisassembleNVectorShift(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, bool LeftShift, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -
    > -  assert(NumOps >= 3 &&
    > -         (OpInfo[0].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[0].RegClass == ARM::QPRRegClassID) &&
    > -         (OpInfo[1].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[1].RegClass == ARM::QPRRegClassID) &&
    > -         "Expect >= 3 operands and first 2 as reg operands");
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  // Qd/Dd = Inst{22:15-12} => NEON Rd
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     decodeNEONRd(insn))));
    > -  ++OpIdx;
    > -
    > -  if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
    > -    // TIED_TO operand.
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    ++OpIdx;
    > -  }
    > -
    > -  assert((OpInfo[OpIdx].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[OpIdx].RegClass == ARM::QPRRegClassID) &&
    > -         "Reg operand expected");
    > -
    > -  // Qm/Dm = Inst{5:3-0} => NEON Rm
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     decodeNEONRm(insn))));
    > -  ++OpIdx;
    > -
    > -  assert(OpInfo[OpIdx].RegClass < 0 && "Imm operand expected");
    > -
    > -  // Add the imm operand.
    > -
    > -  // VSHLL has maximum shift count as the imm, inferred from its size.
    > -  unsigned Imm;
    > -  switch (Opcode) {
    > -  default:
    > -    Imm = decodeNVSAmt(insn, LeftShift);
    > -    break;
    > -  case ARM::VSHLLi8:
    > -    Imm = 8;
    > -    break;
    > -  case ARM::VSHLLi16:
    > -    Imm = 16;
    > -    break;
    > -  case ARM::VSHLLi32:
    > -    Imm = 32;
    > -    break;
    > -  }
    > -  MI.addOperand(MCOperand::CreateImm(Imm));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -// Left shift instructions.
    > -static bool DisassembleN2RegVecShLFrm(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, true,
    > -                                 B);
    > -}
    > -// Right shift instructions have different shift amount interpretation.
    > -static bool DisassembleN2RegVecShRFrm(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVectorShift(MI, Opcode, insn, NumOps, NumOpsAdded, false,
    > -                                 B);
    > -}
    > -
    > -namespace {
    > -enum N3VFlag {
    > -  N3V_None,
    > -  N3V_VectorExtract,
    > -  N3V_VectorShift,
    > -  N3V_Multiply_By_Scalar
    > -};
    > -} // End of unnamed namespace
    > -
    > -// NEON Three Register Instructions with Optional Immediate Operand
    > -//
    > -// Vector Extract Instructions.
    > -// Qd/Dd Qn/Dn Qm/Dm imm4
    > -//
    > -// Vector Shift (Register) Instructions.
    > -// Qd/Dd Qm/Dm Qn/Dn (notice the order of m, n)
    > -//
    > -// Vector Multiply [Accumulate/Subtract] [Long] By Scalar Instructions.
    > -// Qd/Dd Qn/Dn RestrictedDm index
    > -//
    > -// Others
    > -static bool DisassembleNVdVnVmOptImm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, N3VFlag Flag, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -
    > -  // No checking for OpInfo[2] because of MOVDneon/MOVQ with only two regs.
    > -  assert(NumOps >= 3 &&
    > -         (OpInfo[0].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[0].RegClass == ARM::QPRRegClassID) &&
    > -         (OpInfo[1].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[1].RegClass == ARM::QPRRegClassID) &&
    > -         "Expect >= 3 operands and first 2 as reg operands");
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  bool VdVnVm = Flag == N3V_VectorShift ? false : true;
    > -  bool IsImm4 = Flag == N3V_VectorExtract ? true : false;
    > -  bool IsDmRestricted = Flag == N3V_Multiply_By_Scalar ? true : false;
    > -  ElemSize esize = ESizeNA;
    > -  if (Flag == N3V_Multiply_By_Scalar) {
    > -    unsigned size = (insn >> 20) & 3;
    > -    if (size == 1) esize = ESize16;
    > -    if (size == 2) esize = ESize32;
    > -    assert (esize == ESize16 || esize == ESize32);
    > -  }
    > -
    > -  // Qd/Dd = Inst{22:15-12} => NEON Rd
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     decodeNEONRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // VABA, VABAL, VBSLd, VBSLq, ...
    > -  if (MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1) {
    > -    // TIED_TO operand.
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Dn = Inst{7:19-16} => NEON Rn
    > -  // or
    > -  // Dm = Inst{5:3-0} => NEON Rm
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                  VdVnVm ? decodeNEONRn(insn)
    > -                                         : decodeNEONRm(insn))));
    > -  ++OpIdx;
    > -
    > -  // Dm = Inst{5:3-0} => NEON Rm
    > -  // or
    > -  // Dm is restricted to D0-D7 if size is 16, D0-D15 otherwise
    > -  // or
    > -  // Dn = Inst{7:19-16} => NEON Rn
    > -  unsigned m = VdVnVm ? (IsDmRestricted ? decodeRestrictedDm(insn, esize)
    > -                                        : decodeNEONRm(insn))
    > -                      : decodeNEONRn(insn);
    > -
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, OpInfo[OpIdx].RegClass, m)));
    > -  ++OpIdx;
    > -
    > -  if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
    > -      && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -    // Add the imm operand.
    > -    unsigned Imm = 0;
    > -    if (IsImm4)
    > -      Imm = decodeN3VImm(insn);
    > -    else if (IsDmRestricted)
    > -      Imm = decodeRestrictedDmIndex(insn, esize);
    > -    else {
    > -      assert(0 && "Internal error: unreachable code!");
    > -      return false;
    > -    }
    > -
    > -    MI.addOperand(MCOperand::CreateImm(Imm));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -static bool DisassembleN3RegFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                  N3V_None, B);
    > -}
    > -static bool DisassembleN3RegVecShFrm(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                  N3V_VectorShift, B);
    > -}
    > -static bool DisassembleNVecExtractFrm(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                  N3V_VectorExtract, B);
    > -}
    > -static bool DisassembleNVecMulScalarFrm(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  return DisassembleNVdVnVmOptImm(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                  N3V_Multiply_By_Scalar, B);
    > -}
    > -
    > -// Vector Table Lookup
    > -//
    > -// VTBL1, VTBX1: Dd [Dd(TIED_TO)] Dn Dm
    > -// VTBL2, VTBX2: Dd [Dd(TIED_TO)] Dn Dn+1 Dm
    > -// VTBL3, VTBX3: Dd [Dd(TIED_TO)] Dn Dn+1 Dn+2 Dm
    > -// VTBL4, VTBX4: Dd [Dd(TIED_TO)] Dn Dn+1 Dn+2 Dn+3 Dm
    > -static bool DisassembleNVTBLFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(NumOps >= 3 &&
    > -         OpInfo[0].RegClass == ARM::DPRRegClassID &&
    > -         OpInfo[1].RegClass == ARM::DPRRegClassID &&
    > -         OpInfo[2].RegClass == ARM::DPRRegClassID &&
    > -         "Expect >= 3 operands and first 3 as reg operands");
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  unsigned Rn = decodeNEONRn(insn);
    > -
    > -  // {Dn} encoded as len = 0b00
    > -  // {Dn Dn+1} encoded as len = 0b01
    > -  // {Dn Dn+1 Dn+2 } encoded as len = 0b10
    > -  // {Dn Dn+1 Dn+2 Dn+3} encoded as len = 0b11
    > -  unsigned Len = slice(insn, 9, 8) + 1;
    > -
    > -  // Dd (the destination vector)
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
    > -                                                     decodeNEONRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // Process tied_to operand constraint.
    > -  int Idx;
    > -  if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
    > -    MI.addOperand(MI.getOperand(Idx));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Do the  now.
    > -  for (unsigned i = 0; i < Len; ++i) {
    > -    assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID &&
    > -           "Reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
    > -                                                       Rn + i)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Dm (the index vector)
    > -  assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::DPRRegClassID &&
    > -         "Reg operand (index vector) expected");
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
    > -                                                     decodeNEONRm(insn))));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -// Vector Get Lane (move scalar to ARM core register) Instructions.
    > -// VGETLNi32, VGETLNs16, VGETLNs8, VGETLNu16, VGETLNu8: Rt Dn index
    > -static bool DisassembleNGetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(MCID.getNumDefs() == 1 && NumOps >= 3 &&
    > -         OpInfo[0].RegClass == ARM::GPRRegClassID &&
    > -         OpInfo[1].RegClass == ARM::DPRRegClassID &&
    > -         OpInfo[2].RegClass < 0 &&
    > -         "Expect >= 3 operands with one dst operand");
    > -
    > -  ElemSize esize =
    > -    Opcode == ARM::VGETLNi32 ? ESize32
    > -      : ((Opcode == ARM::VGETLNs16 || Opcode == ARM::VGETLNu16) ? ESize16
    > -                                                                : ESize8);
    > -
    > -  // Rt = Inst{15-12} => ARM Rd
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -
    > -  // Dn = Inst{7:19-16} => NEON Rn
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
    > -                                                     decodeNEONRn(insn))));
    > -
    > -  MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize)));
    > -
    > -  NumOpsAdded = 3;
    > -  return true;
    > -}
    > -
    > -// Vector Set Lane (move ARM core register to scalar) Instructions.
    > -// VSETLNi16, VSETLNi32, VSETLNi8: Dd Dd (TIED_TO) Rt index
    > -static bool DisassembleNSetLnFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(MCID.getNumDefs() == 1 && NumOps >= 3 &&
    > -         OpInfo[0].RegClass == ARM::DPRRegClassID &&
    > -         OpInfo[1].RegClass == ARM::DPRRegClassID &&
    > -         MCID.getOperandConstraint(1, MCOI::TIED_TO) != -1 &&
    > -         OpInfo[2].RegClass == ARM::GPRRegClassID &&
    > -         OpInfo[3].RegClass < 0 &&
    > -         "Expect >= 3 operands with one dst operand");
    > -
    > -  ElemSize esize =
    > -    Opcode == ARM::VSETLNi8 ? ESize8
    > -                            : (Opcode == ARM::VSETLNi16 ? ESize16
    > -                                                        : ESize32);
    > -
    > -  // Dd = Inst{7:19-16} => NEON Rn
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::DPRRegClassID,
    > -                                                     decodeNEONRn(insn))));
    > -
    > -  // TIED_TO operand.
    > -  MI.addOperand(MCOperand::CreateReg(0));
    > -
    > -  // Rt = Inst{15-12} => ARM Rd
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -
    > -  MI.addOperand(MCOperand::CreateImm(decodeNVLaneOpIndex(insn, esize)));
    > -
    > -  NumOpsAdded = 4;
    > -  return true;
    > -}
    > -
    > -// Vector Duplicate Instructions (from ARM core register to all elements).
    > -// VDUP8d, VDUP16d, VDUP32d, VDUP8q, VDUP16q, VDUP32q: Qd/Dd Rt
    > -static bool DisassembleNDupFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -
    > -  assert(NumOps >= 2 &&
    > -         (OpInfo[0].RegClass == ARM::DPRRegClassID ||
    > -          OpInfo[0].RegClass == ARM::QPRRegClassID) &&
    > -         OpInfo[1].RegClass == ARM::GPRRegClassID &&
    > -         "Expect >= 2 operands and first 2 as reg operand");
    > -
    > -  unsigned RegClass = OpInfo[0].RegClass;
    > -
    > -  // Qd/Dd = Inst{7:19-16} => NEON Rn
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClass,
    > -                                                     decodeNEONRn(insn))));
    > -
    > -  // Rt = Inst{15-12} => ARM Rd
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -
    > -  NumOpsAdded = 2;
    > -  return true;
    > -}
    > -
    > -static inline bool PreLoadOpcode(unsigned Opcode) {
    > -  switch(Opcode) {
    > -  case ARM::PLDi12:  case ARM::PLDrs:
    > -  case ARM::PLDWi12: case ARM::PLDWrs:
    > -  case ARM::PLIi12:  case ARM::PLIrs:
    > -    return true;
    > -  default:
    > -    return false;
    > -  }
    > -}
    > -
    > -static bool DisassemblePreLoadFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  // Preload Data/Instruction requires either 2 or 3 operands.
    > -  // PLDi12, PLDWi12, PLIi12: addrmode_imm12
    > -  // PLDrs, PLDWrs, PLIrs:    ldst_so_reg
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -
    > -  if (Opcode == ARM::PLDi12 || Opcode == ARM::PLDWi12
    > -      || Opcode == ARM::PLIi12) {
    > -    unsigned Imm12 = slice(insn, 11, 0);
    > -    bool Negative = getUBit(insn) == 0;
    > -
    > -    // A8.6.118 PLD (literal) PLDWi12 with Rn=PC is transformed to PLDi12.
    > -    if (Opcode == ARM::PLDWi12 && slice(insn, 19, 16) == 0xF) {
    > -      DEBUG(errs() << "Rn == '1111': PLDWi12 morphed to PLDi12\n");
    > -      MI.setOpcode(ARM::PLDi12);
    > -    }
    > -    
    > -    // -0 is represented specially. All other values are as normal.
    > -    int Offset = Negative ? -1 * Imm12 : Imm12;
    > -    if (Imm12 == 0 && Negative)
    > -      Offset = INT32_MIN;
    > -
    > -    MI.addOperand(MCOperand::CreateImm(Offset));
    > -    NumOpsAdded = 2;
    > -  } else {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -
    > -    ARM_AM::AddrOpc AddrOpcode = getUBit(insn) ? ARM_AM::add : ARM_AM::sub;
    > -
    > -    // Inst{6-5} encodes the shift opcode.
    > -    ARM_AM::ShiftOpc ShOp = getShiftOpcForBits(slice(insn, 6, 5));
    > -    // Inst{11-7} encodes the imm5 shift amount.
    > -    unsigned ShImm = slice(insn, 11, 7);
    > -
    > -    // A8.4.1.  Possible rrx or shift amount of 32...
    > -    getImmShiftSE(ShOp, ShImm);
    > -    MI.addOperand(MCOperand::CreateImm(
    > -                    ARM_AM::getAM2Opc(AddrOpcode, ShImm, ShOp)));
    > -    NumOpsAdded = 3;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -static bool DisassembleMiscFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  if (Opcode == ARM::DMB || Opcode == ARM::DSB || Opcode == ARM::ISB) {
    > -    // Inst{3-0} encodes the memory barrier option for the variants.
    > -    unsigned opt = slice(insn, 3, 0);
    > -    switch (opt) {
    > -    case ARM_MB::SY:  case ARM_MB::ST:
    > -    case ARM_MB::ISH: case ARM_MB::ISHST:
    > -    case ARM_MB::NSH: case ARM_MB::NSHST:
    > -    case ARM_MB::OSH: case ARM_MB::OSHST:
    > -      MI.addOperand(MCOperand::CreateImm(opt));
    > -      NumOpsAdded = 1;
    > -      return true;
    > -    default:
    > -      return false;
    > -    }
    > -  }
    > -
    > -  switch (Opcode) {
    > -  case ARM::CLREX:
    > -  case ARM::NOP:
    > -  case ARM::TRAP:
    > -  case ARM::YIELD:
    > -  case ARM::WFE:
    > -  case ARM::WFI:
    > -  case ARM::SEV:
    > -    return true;
    > -  case ARM::SWP:
    > -  case ARM::SWPB:
    > -    // SWP, SWPB: Rd Rm Rn
    > -    // Delegate to DisassembleLdStExFrm()....
    > -    return DisassembleLdStExFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -  default:
    > -    break;
    > -  }
    > -
    > -  if (Opcode == ARM::SETEND) {
    > -    NumOpsAdded = 1;
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 9, 9)));
    > -    return true;
    > -  }
    > -
    > -  // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different
    > -  // opcodes which match the same real instruction. This is needed since there's
    > -  // no current handling of optional arguments. Fix here when a better handling
    > -  // of optional arguments is implemented.
    > -  if (Opcode == ARM::CPS3p) {   // M = 1
    > -    // Let's reject these impossible imod values by returning false:
    > -    // 1. (imod=0b01)
    > -    //
    > -    // AsmPrinter cannot handle imod=0b00, plus (imod=0b00,M=1,iflags!=0) is an
    > -    // invalid combination, so we just check for imod=0b00 here.
    > -    if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1)
    > -      return false;
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6)));   // iflags
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));   // mode
    > -    NumOpsAdded = 3;
    > -    return true;
    > -  }
    > -  if (Opcode == ARM::CPS2p) { // mode = 0, M = 0
    > -    // Let's reject these impossible imod values by returning false:
    > -    // 1. (imod=0b00,M=0)
    > -    // 2. (imod=0b01)
    > -    if (slice(insn, 19, 18) == 0 || slice(insn, 19, 18) == 1)
    > -      return false;
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 18))); // imod
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 8, 6)));   // iflags
    > -    NumOpsAdded = 2;
    > -    return true;
    > -  }
    > -  if (Opcode == ARM::CPS1p) { // imod = 0, iflags = 0, M = 1
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  // DBG has its option specified in Inst{3-0}.
    > -  if (Opcode == ARM::DBG) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0)));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  // BKPT takes an imm32 val equal to ZeroExtend(Inst{19-8:3-0}).
    > -  if (Opcode == ARM::BKPT) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 8) << 4 |
    > -                                       slice(insn, 3, 0)));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  if (PreLoadOpcode(Opcode))
    > -    return DisassemblePreLoadFrm(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -
    > -  assert(0 && "Unexpected misc instruction!");
    > -  return false;
    > -}
    > -
    > -/// FuncPtrs - FuncPtrs maps ARMFormat to its corresponding DisassembleFP.
    > -/// We divide the disassembly task into different categories, with each one
    > -/// corresponding to a specific instruction encoding format.  There could be
    > -/// exceptions when handling a specific format, and that is why the Opcode is
    > -/// also present in the function prototype.
    > -static const DisassembleFP FuncPtrs[] = {
    > -  &DisassemblePseudo,
    > -  &DisassembleMulFrm,
    > -  &DisassembleBrFrm,
    > -  &DisassembleBrMiscFrm,
    > -  &DisassembleDPFrm,
    > -  &DisassembleDPSoRegRegFrm,
    > -  &DisassembleLdFrm,
    > -  &DisassembleStFrm,
    > -  &DisassembleLdMiscFrm,
    > -  &DisassembleStMiscFrm,
    > -  &DisassembleLdStMulFrm,
    > -  &DisassembleLdStExFrm,
    > -  &DisassembleArithMiscFrm,
    > -  &DisassembleSatFrm,
    > -  &DisassembleExtFrm,
    > -  &DisassembleVFPUnaryFrm,
    > -  &DisassembleVFPBinaryFrm,
    > -  &DisassembleVFPConv1Frm,
    > -  &DisassembleVFPConv2Frm,
    > -  &DisassembleVFPConv3Frm,
    > -  &DisassembleVFPConv4Frm,
    > -  &DisassembleVFPConv5Frm,
    > -  &DisassembleVFPLdStFrm,
    > -  &DisassembleVFPLdStMulFrm,
    > -  &DisassembleVFPMiscFrm,
    > -  &DisassembleThumbFrm,
    > -  &DisassembleMiscFrm,
    > -  &DisassembleNGetLnFrm,
    > -  &DisassembleNSetLnFrm,
    > -  &DisassembleNDupFrm,
    > -
    > -  // VLD and VST (including one lane) Instructions.
    > -  &DisassembleNLdSt,
    > -
    > -  // A7.4.6 One register and a modified immediate value
    > -  // 1-Register Instructions with imm.
    > -  // LLVM only defines VMOVv instructions.
    > -  &DisassembleN1RegModImmFrm,
    > -
    > -  // 2-Register Instructions with no imm.
    > -  &DisassembleN2RegFrm,
    > -
    > -  // 2-Register Instructions with imm (vector convert float/fixed point).
    > -  &DisassembleNVCVTFrm,
    > -
    > -  // 2-Register Instructions with imm (vector dup lane).
    > -  &DisassembleNVecDupLnFrm,
    > -
    > -  // Vector Shift Left Instructions.
    > -  &DisassembleN2RegVecShLFrm,
    > -
    > -  // Vector Shift Righ Instructions, which has different interpretation of the
    > -  // shift amount from the imm6 field.
    > -  &DisassembleN2RegVecShRFrm,
    > -
    > -  // 3-Register Data-Processing Instructions.
    > -  &DisassembleN3RegFrm,
    > -
    > -  // Vector Shift (Register) Instructions.
    > -  // D:Vd M:Vm N:Vn (notice that M:Vm is the first operand)
    > -  &DisassembleN3RegVecShFrm,
    > -
    > -  // Vector Extract Instructions.
    > -  &DisassembleNVecExtractFrm,
    > -
    > -  // Vector [Saturating Rounding Doubling] Multiply [Accumulate/Subtract] [Long]
    > -  // By Scalar Instructions.
    > -  &DisassembleNVecMulScalarFrm,
    > -
    > -  // Vector Table Lookup uses byte indexes in a control vector to look up byte
    > -  // values in a table and generate a new vector.
    > -  &DisassembleNVTBLFrm,
    > -
    > -  &DisassembleDPSoRegImmFrm,
    > -
    > -
    > -  NULL
    > -};
    > -
    > -/// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
    > -/// The general idea is to set the Opcode for the MCInst, followed by adding
    > -/// the appropriate MCOperands to the MCInst.  ARM Basic MC Builder delegates
    > -/// to the Format-specific disassemble function for disassembly, followed by
    > -/// TryPredicateAndSBitModifier() to do PredicateOperand and OptionalDefOperand
    > -/// which follow the Dst/Src Operands.
    > -bool ARMBasicMCBuilder::BuildIt(MCInst &MI, uint32_t insn) {
    > -  // Stage 1 sets the Opcode.
    > -  MI.setOpcode(Opcode);
    > -  // If the number of operands is zero, we're done!
    > -  if (NumOps == 0)
    > -    return true;
    > -
    > -  // Stage 2 calls the format-specific disassemble function to build the operand
    > -  // list.
    > -  if (Disasm == NULL)
    > -    return false;
    > -  unsigned NumOpsAdded = 0;
    > -  bool OK = (*Disasm)(MI, Opcode, insn, NumOps, NumOpsAdded, this);
    > -
    > -  if (!OK || this->Err != 0) return false;
    > -  if (NumOpsAdded >= NumOps)
    > -    return true;
    > -
    > -  // Stage 3 deals with operands unaccounted for after stage 2 is finished.
    > -  // FIXME: Should this be done selectively?
    > -  return TryPredicateAndSBitModifier(MI, Opcode, insn, NumOps - NumOpsAdded);
    > -}
    > -
    > -// A8.3 Conditional execution
    > -// A8.3.1 Pseudocode details of conditional execution
    > -// Condition bits '111x' indicate the instruction is always executed.
    > -static uint32_t CondCode(uint32_t CondField) {
    > -  if (CondField == 0xF)
    > -    return ARMCC::AL;
    > -  return CondField;
    > -}
    > -
    > -/// DoPredicateOperands - DoPredicateOperands process the predicate operands
    > -/// of some Thumb instructions which come before the reglist operands.  It
    > -/// returns true if the two predicate operands have been processed.
    > -bool ARMBasicMCBuilder::DoPredicateOperands(MCInst& MI, unsigned Opcode,
    > -    uint32_t /* insn */, unsigned short NumOpsRemaining) {
    > -
    > -  assert(NumOpsRemaining > 0 && "Invalid argument");
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  unsigned Idx = MI.getNumOperands();
    > -
    > -  // First, we check whether this instr specifies the PredicateOperand through
    > -  // a pair of MCOperandInfos with isPredicate() property.
    > -  if (NumOpsRemaining >= 2 &&
    > -      OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() &&
    > -      OpInfo[Idx].RegClass < 0 &&
    > -      OpInfo[Idx+1].RegClass == ARM::CCRRegClassID)
    > -  {
    > -    // If we are inside an IT block, get the IT condition bits maintained via
    > -    // ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond().
    > -    // See also A2.5.2.
    > -    if (InITBlock())
    > -      MI.addOperand(MCOperand::CreateImm(GetITCond()));
    > -    else
    > -      MI.addOperand(MCOperand::CreateImm(ARMCC::AL));
    > -    MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
    > -    return true;
    > -  }
    > -
    > -  return false;
    > -}
    > -
    > -/// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
    > -/// the possible Predicate and SBitModifier, to build the remaining MCOperand
    > -/// constituents.
    > -bool ARMBasicMCBuilder::TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOpsRemaining) {
    > -
    > -  assert(NumOpsRemaining > 0 && "Invalid argument");
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  const std::string &Name = ARMInsts[Opcode].Name;
    > -  unsigned Idx = MI.getNumOperands();
    > -  uint64_t TSFlags = ARMInsts[Opcode].TSFlags;
    > -
    > -  // First, we check whether this instr specifies the PredicateOperand through
    > -  // a pair of MCOperandInfos with isPredicate() property.
    > -  if (NumOpsRemaining >= 2 &&
    > -      OpInfo[Idx].isPredicate() && OpInfo[Idx+1].isPredicate() &&
    > -      OpInfo[Idx].RegClass < 0 &&
    > -      OpInfo[Idx+1].RegClass == ARM::CCRRegClassID)
    > -  {
    > -    // If we are inside an IT block, get the IT condition bits maintained via
    > -    // ARMBasicMCBuilder::ITState[7:0], through ARMBasicMCBuilder::GetITCond().
    > -    // See also A2.5.2.
    > -    if (InITBlock())
    > -      MI.addOperand(MCOperand::CreateImm(GetITCond()));
    > -    else {
    > -      if (Name.length() > 1 && Name[0] == 't') {
    > -        // Thumb conditional branch instructions have their cond field embedded,
    > -        // like ARM.
    > -        //
    > -        // A8.6.16 B
    > -        // 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}.
    > -        // We should reject Inst{31-28} = 0b1111 as invalid encoding.
    > -        if (!isNEONDomain(TSFlags) && getCondField(insn) == 0xF)
    > -          return false;
    > -        MI.addOperand(MCOperand::CreateImm(CondCode(getCondField(insn))));
    > -      }
    > -    }
    > -    MI.addOperand(MCOperand::CreateReg(ARM::CPSR));
    > -    Idx += 2;
    > -    NumOpsRemaining -= 2;
    > -  }
    > -
    > -  if (NumOpsRemaining == 0)
    > -    return true;
    > -
    > -  // Next, if OptionalDefOperand exists, we check whether the 'S' bit is set.
    > -  if (OpInfo[Idx].isOptionalDef() && OpInfo[Idx].RegClass==ARM::CCRRegClassID) {
    > -    MI.addOperand(MCOperand::CreateReg(getSBit(insn) == 1 ? ARM::CPSR : 0));
    > -    --NumOpsRemaining;
    > -  }
    > -
    > -  if (NumOpsRemaining == 0)
    > -    return true;
    > -  else
    > -    return false;
    > -}
    > -
    > -/// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
    > -/// after BuildIt is finished.
    > -bool ARMBasicMCBuilder::RunBuildAfterHook(bool Status, MCInst &MI,
    > -    uint32_t insn) {
    > -
    > -  if (!SP) return Status;
    > -
    > -  if (Opcode == ARM::t2IT)
    > -    Status = SP->InitIT(slice(insn, 7, 0)) ? Status : false;
    > -  else if (InITBlock())
    > -    SP->UpdateIT();
    > -
    > -  return Status;
    > -}
    > -
    > -/// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder.
    > -ARMBasicMCBuilder::ARMBasicMCBuilder(unsigned opc, ARMFormat format,
    > -                                     unsigned short num)
    > -  : Opcode(opc), Format(format), NumOps(num), SP(0), Err(0) {
    > -  unsigned Idx = (unsigned)format;
    > -  assert(Idx < (array_lengthof(FuncPtrs) - 1) && "Unknown format");
    > -  Disasm = FuncPtrs[Idx];
    > -}
    > -
    > -/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC
    > -/// infrastructure of an MCInst given the Opcode and Format of the instr.
    > -/// Return NULL if it fails to create/return a proper builder.  API clients
    > -/// are responsible for freeing up of the allocated memory.  Cacheing can be
    > -/// performed by the API clients to improve performance.
    > -ARMBasicMCBuilder *llvm::CreateMCBuilder(unsigned Opcode, ARMFormat Format) {
    > -  // For "Unknown format", fail by returning a NULL pointer.
    > -  if ((unsigned)Format >= (array_lengthof(FuncPtrs) - 1)) {
    > -    DEBUG(errs() << "Unknown format\n");
    > -    return 0;
    > -  }
    > -
    > -  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 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,
    > -                                                 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 {
    > -    if (Off != 0)
    > -      Expr = Off;
    > -    else
    > -      Expr = MCConstantExpr::Create(0, *Ctx);
    > -  }
    > -
    > -  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;
    > -}
    > 
    > Removed: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h?rev=137143&view=auto
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (original)
    > +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassemblerCore.h (removed)
    > @@ -1,337 +0,0 @@
    > -//===- ARMDisassemblerCore.h - ARM disassembler helpers ---------*- C++ -*-===//
    > -//
    > -//                     The LLVM Compiler Infrastructure
    > -//
    > -// This file is distributed under the University of Illinois Open Source
    > -// License. See LICENSE.TXT for details.
    > -//
    > -//===----------------------------------------------------------------------===//
    > -//
    > -// This file is part of the ARM Disassembler.
    > -//
    > -// The first part defines the enumeration type of ARM instruction format, which
    > -// specifies the encoding used by the instruction, as well as a helper function
    > -// to convert the enums to printable char strings.
    > -//
    > -// It also contains code to represent the concepts of Builder and DisassembleFP
    > -// to solve the problem of disassembling an ARM instr.
    > -//
    > -//===----------------------------------------------------------------------===//
    > -
    > -#ifndef ARMDISASSEMBLERCORE_H
    > -#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:
    > -  static const char *OpcodeName(unsigned Opcode);
    > -};
    > -
    > -/////////////////////////////////////////////////////
    > -//                                                 //
    > -//  Enums and Utilities for ARM Instruction Format //
    > -//                                                 //
    > -/////////////////////////////////////////////////////
    > -
    > -#define ARM_FORMATS                   \
    > -  ENTRY(ARM_FORMAT_PSEUDO,         0) \
    > -  ENTRY(ARM_FORMAT_MULFRM,         1) \
    > -  ENTRY(ARM_FORMAT_BRFRM,          2) \
    > -  ENTRY(ARM_FORMAT_BRMISCFRM,      3) \
    > -  ENTRY(ARM_FORMAT_DPFRM,          4) \
    > -  ENTRY(ARM_FORMAT_DPSOREGREGFRM,     5) \
    > -  ENTRY(ARM_FORMAT_LDFRM,          6) \
    > -  ENTRY(ARM_FORMAT_STFRM,          7) \
    > -  ENTRY(ARM_FORMAT_LDMISCFRM,      8) \
    > -  ENTRY(ARM_FORMAT_STMISCFRM,      9) \
    > -  ENTRY(ARM_FORMAT_LDSTMULFRM,    10) \
    > -  ENTRY(ARM_FORMAT_LDSTEXFRM,     11) \
    > -  ENTRY(ARM_FORMAT_ARITHMISCFRM,  12) \
    > -  ENTRY(ARM_FORMAT_SATFRM,        13) \
    > -  ENTRY(ARM_FORMAT_EXTFRM,        14) \
    > -  ENTRY(ARM_FORMAT_VFPUNARYFRM,   15) \
    > -  ENTRY(ARM_FORMAT_VFPBINARYFRM,  16) \
    > -  ENTRY(ARM_FORMAT_VFPCONV1FRM,   17) \
    > -  ENTRY(ARM_FORMAT_VFPCONV2FRM,   18) \
    > -  ENTRY(ARM_FORMAT_VFPCONV3FRM,   19) \
    > -  ENTRY(ARM_FORMAT_VFPCONV4FRM,   20) \
    > -  ENTRY(ARM_FORMAT_VFPCONV5FRM,   21) \
    > -  ENTRY(ARM_FORMAT_VFPLDSTFRM,    22) \
    > -  ENTRY(ARM_FORMAT_VFPLDSTMULFRM, 23) \
    > -  ENTRY(ARM_FORMAT_VFPMISCFRM,    24) \
    > -  ENTRY(ARM_FORMAT_THUMBFRM,      25) \
    > -  ENTRY(ARM_FORMAT_MISCFRM,       26) \
    > -  ENTRY(ARM_FORMAT_NEONGETLNFRM,  27) \
    > -  ENTRY(ARM_FORMAT_NEONSETLNFRM,  28) \
    > -  ENTRY(ARM_FORMAT_NEONDUPFRM,    29) \
    > -  ENTRY(ARM_FORMAT_NLdSt,         30) \
    > -  ENTRY(ARM_FORMAT_N1RegModImm,   31) \
    > -  ENTRY(ARM_FORMAT_N2Reg,         32) \
    > -  ENTRY(ARM_FORMAT_NVCVT,         33) \
    > -  ENTRY(ARM_FORMAT_NVecDupLn, 34) \
    > -  ENTRY(ARM_FORMAT_N2RegVecShL,   35) \
    > -  ENTRY(ARM_FORMAT_N2RegVecShR,   36) \
    > -  ENTRY(ARM_FORMAT_N3Reg,         37) \
    > -  ENTRY(ARM_FORMAT_N3RegVecSh,    38) \
    > -  ENTRY(ARM_FORMAT_NVecExtract,   39) \
    > -  ENTRY(ARM_FORMAT_NVecMulScalar, 40) \
    > -  ENTRY(ARM_FORMAT_NVTBL,         41) \
    > -  ENTRY(ARM_FORMAT_DPSOREGIMMFRM, 42)
    > -
    > -// ARM instruction format specifies the encoding used by the instruction.
    > -#define ENTRY(n, v) n = v,
    > -typedef enum {
    > -  ARM_FORMATS
    > -  ARM_FORMAT_NA
    > -} ARMFormat;
    > -#undef ENTRY
    > -
    > -// Converts enum to const char*.
    > -static const inline char *stringForARMFormat(ARMFormat form) {
    > -#define ENTRY(n, v) case n: return #n;
    > -  switch(form) {
    > -    ARM_FORMATS
    > -  case ARM_FORMAT_NA:
    > -  default:
    > -    return "";
    > -  }
    > -#undef ENTRY
    > -}
    > -
    > -/// Expands on the enum definitions from ARMBaseInstrInfo.h.
    > -/// They are being used by the disassembler implementation.
    > -namespace ARMII {
    > -  enum {
    > -    NEONRegMask = 15,
    > -    GPRRegMask = 15,
    > -    NEON_RegRdShift = 12,
    > -    NEON_D_BitShift = 22,
    > -    NEON_RegRnShift = 16,
    > -    NEON_N_BitShift = 7,
    > -    NEON_RegRmShift = 0,
    > -    NEON_M_BitShift = 5
    > -  };
    > -}
    > -
    > -/// Utility function for extracting [From, To] bits from a uint32_t.
    > -static inline unsigned slice(uint32_t Bits, unsigned From, unsigned To) {
    > -  assert(From < 32 && To < 32 && From >= To);
    > -  return (Bits >> To) & ((1 << (From - To + 1)) - 1);
    > -}
    > -
    > -/// Utility function for setting [From, To] bits to Val for a uint32_t.
    > -static inline void setSlice(unsigned &Bits, unsigned From, unsigned To,
    > -                            unsigned Val) {
    > -  assert(From < 32 && To < 32 && From >= To);
    > -  uint32_t Mask = ((1 << (From - To + 1)) - 1);
    > -  Bits &= ~(Mask << To);
    > -  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.
    > -static inline bool isUnaryDP(uint64_t TSFlags) {
    > -  return (TSFlags & ARMII::UnaryDP);
    > -}
    > -
    > -/// A NEON Domain instruction has cond field (Inst{31-28}) as 0b1111.
    > -static inline bool isNEONDomain(uint64_t TSFlags) {
    > -  return (TSFlags & ARMII::DomainNEON) ||
    > -         (TSFlags & ARMII::DomainNEONA8);
    > -}
    > -
    > -/// This four-bit field describes the addressing mode used.
    > -/// See also ARMBaseInstrInfo.h.
    > -static inline unsigned getAddrMode(uint64_t TSFlags) {
    > -  return (TSFlags & ARMII::AddrModeMask);
    > -}
    > -
    > -/// {IndexModePre, IndexModePost}
    > -/// Only valid for load and store ops.
    > -/// See also ARMBaseInstrInfo.h.
    > -static inline unsigned getIndexMode(uint64_t TSFlags) {
    > -  return (TSFlags & ARMII::IndexModeMask) >> ARMII::IndexModeShift;
    > -}
    > -
    > -/// Pre-/post-indexed operations define an extra $base_wb in the OutOperandList.
    > -static inline bool isPrePostLdSt(uint64_t TSFlags) {
    > -  return (TSFlags & ARMII::IndexModeMask) != 0;
    > -}
    > -
    > -// Forward declaration.
    > -class ARMBasicMCBuilder;
    > -
    > -// Builder Object is mostly ignored except in some Thumb disassemble functions.
    > -typedef ARMBasicMCBuilder *BO;
    > -
    > -/// DisassembleFP - DisassembleFP points to a function that disassembles an insn
    > -/// and builds the MCOperand list upon disassembly.  It returns false on failure
    > -/// or true on success.  The number of operands added is updated upon success.
    > -typedef bool (*DisassembleFP)(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO Builder);
    > -
    > -/// CreateMCBuilder - Return an ARMBasicMCBuilder that can build up the MC
    > -/// infrastructure of an MCInst given the Opcode and Format of the instr.
    > -/// Return NULL if it fails to create/return a proper builder.  API clients
    > -/// are responsible for freeing up of the allocated memory.  Cacheing can be
    > -/// performed by the API clients to improve performance.
    > -extern ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format);
    > -
    > -/// ARMBasicMCBuilder - ARMBasicMCBuilder represents an ARM MCInst builder that
    > -/// knows how to build up the MCOperand list.
    > -class ARMBasicMCBuilder {
    > -  friend ARMBasicMCBuilder *CreateMCBuilder(unsigned Opcode, ARMFormat Format);
    > -  unsigned Opcode;
    > -  ARMFormat Format;
    > -  unsigned short NumOps;
    > -  DisassembleFP Disasm;
    > -  Session *SP;
    > -  int Err; // !=0 if the builder encounters some error condition during build.
    > -
    > -private:
    > -  /// Opcode, Format, and NumOperands make up an ARM Basic MCBuilder.
    > -  ARMBasicMCBuilder(unsigned opc, ARMFormat format, unsigned short num);
    > -
    > -public:
    > -  ARMBasicMCBuilder(ARMBasicMCBuilder &B)
    > -    : Opcode(B.Opcode), Format(B.Format), NumOps(B.NumOps), Disasm(B.Disasm),
    > -      SP(B.SP), GetOpInfo(0), DisInfo(0), Ctx(0) {
    > -    Err = 0;
    > -  }
    > -
    > -  virtual ~ARMBasicMCBuilder() {}
    > -
    > -  void SetSession(Session *sp) {
    > -    SP = sp;
    > -  }
    > -
    > -  void SetErr(int ErrCode) {
    > -    Err = ErrCode;
    > -  }
    > -
    > -  /// DoPredicateOperands - DoPredicateOperands process the predicate operands
    > -  /// of some Thumb instructions which come before the reglist operands.  It
    > -  /// returns true if the two predicate operands have been processed.
    > -  bool DoPredicateOperands(MCInst& MI, unsigned Opcode,
    > -      uint32_t insn, unsigned short NumOpsRemaning);
    > -  
    > -  /// TryPredicateAndSBitModifier - TryPredicateAndSBitModifier tries to process
    > -  /// the possible Predicate and SBitModifier, to build the remaining MCOperand
    > -  /// constituents.
    > -  bool TryPredicateAndSBitModifier(MCInst& MI, unsigned Opcode,
    > -      uint32_t insn, unsigned short NumOpsRemaning);
    > -
    > -  /// InITBlock - InITBlock returns true if we are inside an IT block.
    > -  bool InITBlock() {
    > -    if (SP)
    > -      return SP->ITCounter > 0;
    > -
    > -    return false;
    > -  }
    > -
    > -  /// Build - Build delegates to BuildIt to perform the heavy liftling.  After
    > -  /// that, it invokes RunBuildAfterHook where some housekeepings can be done.
    > -  virtual bool Build(MCInst &MI, uint32_t insn) {
    > -    bool Status = BuildIt(MI, insn);
    > -    return RunBuildAfterHook(Status, MI, insn);
    > -  }
    > -
    > -  /// BuildIt - BuildIt performs the build step for this ARM Basic MC Builder.
    > -  /// The general idea is to set the Opcode for the MCInst, followed by adding
    > -  /// the appropriate MCOperands to the MCInst.  ARM Basic MC Builder delegates
    > -  /// to the Format-specific disassemble function for disassembly, followed by
    > -  /// TryPredicateAndSBitModifier() for PredicateOperand and OptionalDefOperand
    > -  /// which follow the Dst/Src Operands.
    > -  virtual bool BuildIt(MCInst &MI, uint32_t insn);
    > -
    > -  /// RunBuildAfterHook - RunBuildAfterHook performs operations deemed necessary
    > -  /// after BuildIt is finished.
    > -  virtual bool RunBuildAfterHook(bool Status, MCInst &MI, uint32_t insn);
    > -
    > -private:
    > -  /// Get condition of the current IT instruction.
    > -  unsigned GetITCond() {
    > -    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 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);
    > -
    > -};
    > -
    > -} // namespace llvm
    > -
    > -#endif
    > 
    > Modified: llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt (original)
    > +++ llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt Tue Aug  9 15:55:18 2011
    > @@ -2,7 +2,6 @@
    > 
    > add_llvm_library(LLVMARMDisassembler
    >   ARMDisassembler.cpp
    > -  ARMDisassemblerCore.cpp
    >   )
    > # workaround for hanging compilation on MSVC8, 9 and 10
    > if( MSVC_VERSION EQUAL 1400 OR MSVC_VERSION EQUAL 1500 OR MSVC_VERSION EQUAL 1600 )
    > 
    > Removed: llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h?rev=137143&view=auto
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (original)
    > +++ llvm/trunk/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h (removed)
    > @@ -1,2461 +0,0 @@
    > -//===- ThumbDisassemblerCore.h - Thumb disassembler helpers -----*- C++ -*-===//
    > -//
    > -//                     The LLVM Compiler Infrastructure
    > -//
    > -// This file is distributed under the University of Illinois Open Source
    > -// License. See LICENSE.TXT for details.
    > -//
    > -//===----------------------------------------------------------------------===//
    > -//
    > -// This file is part of the ARM Disassembler.
    > -// It contains code for disassembling a Thumb instr.  It is to be included by
    > -// ARMDisassemblerCore.cpp because it contains the static DisassembleThumbFrm()
    > -// function which acts as the dispatcher to disassemble a Thumb instruction.
    > -//
    > -//===----------------------------------------------------------------------===//
    > -
    > -///////////////////////////////
    > -//                           //
    > -//     Utility Functions     //
    > -//                           //
    > -///////////////////////////////
    > -
    > -// Utilities for 16-bit Thumb instructions.
    > -/*
    > -15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
    > -               [  tRt ]
    > -                      [ tRm ]  [ tRn ]  [ tRd ]
    > -                         D  [   Rm   ]  [  Rd ]
    > -
    > -                      [ imm3]
    > -               [    imm5    ]
    > -                   i     [    imm5   ]
    > -                            [       imm7      ]
    > -                         [       imm8         ]
    > -               [             imm11            ]
    > -
    > -            [   cond  ]
    > -*/
    > -
    > -// Extract tRt: Inst{10-8}.
    > -static inline unsigned getT1tRt(uint32_t insn) {
    > -  return slice(insn, 10, 8);
    > -}
    > -
    > -// Extract tRm: Inst{8-6}.
    > -static inline unsigned getT1tRm(uint32_t insn) {
    > -  return slice(insn, 8, 6);
    > -}
    > -
    > -// Extract tRn: Inst{5-3}.
    > -static inline unsigned getT1tRn(uint32_t insn) {
    > -  return slice(insn, 5, 3);
    > -}
    > -
    > -// Extract tRd: Inst{2-0}.
    > -static inline unsigned getT1tRd(uint32_t insn) {
    > -  return slice(insn, 2, 0);
    > -}
    > -
    > -// Extract [D:Rd]: Inst{7:2-0}.
    > -static inline unsigned getT1Rd(uint32_t insn) {
    > -  return slice(insn, 7, 7) << 3 | slice(insn, 2, 0);
    > -}
    > -
    > -// Extract Rm: Inst{6-3}.
    > -static inline unsigned getT1Rm(uint32_t insn) {
    > -  return slice(insn, 6, 3);
    > -}
    > -
    > -// Extract imm3: Inst{8-6}.
    > -static inline unsigned getT1Imm3(uint32_t insn) {
    > -  return slice(insn, 8, 6);
    > -}
    > -
    > -// Extract imm5: Inst{10-6}.
    > -static inline unsigned getT1Imm5(uint32_t insn) {
    > -  return slice(insn, 10, 6);
    > -}
    > -
    > -// Extract i:imm5: Inst{9:7-3}.
    > -static inline unsigned getT1Imm6(uint32_t insn) {
    > -  return slice(insn, 9, 9) << 5 | slice(insn, 7, 3);
    > -}
    > -
    > -// Extract imm7: Inst{6-0}.
    > -static inline unsigned getT1Imm7(uint32_t insn) {
    > -  return slice(insn, 6, 0);
    > -}
    > -
    > -// Extract imm8: Inst{7-0}.
    > -static inline unsigned getT1Imm8(uint32_t insn) {
    > -  return slice(insn, 7, 0);
    > -}
    > -
    > -// Extract imm11: Inst{10-0}.
    > -static inline unsigned getT1Imm11(uint32_t insn) {
    > -  return slice(insn, 10, 0);
    > -}
    > -
    > -// Extract cond: Inst{11-8}.
    > -static inline unsigned getT1Cond(uint32_t insn) {
    > -  return slice(insn, 11, 8);
    > -}
    > -
    > -static inline bool IsGPR(unsigned RegClass) {
    > -  return RegClass == ARM::GPRRegClassID || RegClass == ARM::rGPRRegClassID;
    > -}
    > -
    > -// 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);
    > -}
    > -
    > -// Extract imm3: Inst{14-12}.
    > -static inline unsigned getImm3(uint32_t insn) {
    > -  return slice(insn, 14, 12);
    > -}
    > -
    > -// Extract imm8: Inst{7-0}.
    > -static inline unsigned getImm8(uint32_t insn) {
    > -  return slice(insn, 7, 0);
    > -}
    > -
    > -// A8.6.61 LDRB (immediate, Thumb) and friends
    > -// +/-: Inst{9}
    > -// imm8: Inst{7-0}
    > -static inline int decodeImm8(uint32_t insn) {
    > -  int Offset = getImm8(insn);
    > -  return slice(insn, 9, 9) ? Offset : -Offset;
    > -}
    > -
    > -// Extract imm12: Inst{11-0}.
    > -static inline unsigned getImm12(uint32_t insn) {
    > -  return slice(insn, 11, 0);
    > -}
    > -
    > -// A8.6.63 LDRB (literal) and friends
    > -// +/-: Inst{23}
    > -// imm12: Inst{11-0}
    > -static inline int decodeImm12(uint32_t insn) {
    > -  int Offset = getImm12(insn);
    > -  return slice(insn, 23, 23) ? Offset : -Offset;
    > -}
    > -
    > -// Extract imm2: Inst{7-6}.
    > -static inline unsigned getImm2(uint32_t insn) {
    > -  return slice(insn, 7, 6);
    > -}
    > -
    > -// For BFI, BFC, t2SBFX, and t2UBFX.
    > -// Extract lsb: Inst{14-12:7-6}.
    > -static inline unsigned getLsb(uint32_t insn) {
    > -  return getImm3(insn) << 2 | getImm2(insn);
    > -}
    > -
    > -// For BFI and BFC.
    > -// Extract msb: Inst{4-0}.
    > -static inline unsigned getMsb(uint32_t insn) {
    > -  return slice(insn, 4, 0);
    > -}
    > -
    > -// For t2SBFX and t2UBFX.
    > -// Extract widthminus1: Inst{4-0}.
    > -static inline unsigned getWidthMinus1(uint32_t insn) {
    > -  return slice(insn, 4, 0);
    > -}
    > -
    > -// For t2ADDri12 and t2SUBri12.
    > -// imm12 = i:imm3:imm8;
    > -static inline unsigned getIImm3Imm8(uint32_t insn) {
    > -  return slice(insn, 26, 26) << 11 | getImm3(insn) << 8 | getImm8(insn);
    > -}
    > -
    > -// For t2MOVi16 and t2MOVTi16.
    > -// imm16 = imm4:i:imm3:imm8;
    > -static inline unsigned getImm16(uint32_t insn) {
    > -  return getImm4(insn) << 12 | slice(insn, 26, 26) << 11 |
    > -    getImm3(insn) << 8 | getImm8(insn);
    > -}
    > -
    > -// Inst{5-4} encodes the shift type.
    > -static inline unsigned getShiftTypeBits(uint32_t insn) {
    > -  return slice(insn, 5, 4);
    > -}
    > -
    > -// Inst{14-12}:Inst{7-6} encodes the imm5 shift amount.
    > -static inline unsigned getShiftAmtBits(uint32_t insn) {
    > -  return getImm3(insn) << 2 | getImm2(insn);
    > -}
    > -
    > -// A8.6.17 BFC
    > -// Encoding T1 ARMv6T2, ARMv7
    > -// LLVM-specific encoding for # and #
    > -static inline bool getBitfieldInvMask(uint32_t insn, uint32_t &mask) {
    > -  uint32_t lsb = getImm3(insn) << 2 | getImm2(insn);
    > -  uint32_t msb = getMsb(insn);
    > -  uint32_t Val = 0;
    > -  if (msb < lsb) {
    > -    DEBUG(errs() << "Encoding error: msb < lsb\n");
    > -    return false;
    > -  }
    > -  for (uint32_t i = lsb; i <= msb; ++i)
    > -    Val |= (1 << i);
    > -  mask = ~Val;
    > -  return true;
    > -}
    > -
    > -// A8.4 Shifts applied to a register
    > -// A8.4.1 Constant shifts
    > -// A8.4.3 Pseudocode details of instruction-specified shifts and rotates
    > -//
    > -// decodeImmShift() returns the shift amount and the the shift opcode.
    > -// Note that, as of Jan-06-2010, LLVM does not support rrx shifted operands yet.
    > -static inline unsigned decodeImmShift(unsigned bits2, unsigned imm5,
    > -                                      ARM_AM::ShiftOpc &ShOp) {
    > -
    > -  assert(imm5 < 32 && "Invalid imm5 argument");
    > -  switch (bits2) {
    > -  default: assert(0 && "No such value");
    > -  case 0:
    > -    ShOp = (imm5 == 0 ? ARM_AM::no_shift : ARM_AM::lsl);
    > -    return imm5;
    > -  case 1:
    > -    ShOp = ARM_AM::lsr;
    > -    return (imm5 == 0 ? 32 : imm5);
    > -  case 2:
    > -    ShOp = ARM_AM::asr;
    > -    return (imm5 == 0 ? 32 : imm5);
    > -  case 3:
    > -    ShOp = (imm5 == 0 ? ARM_AM::rrx : ARM_AM::ror);
    > -    return (imm5 == 0 ? 1 : imm5);
    > -  }
    > -}
    > -
    > -// A6.3.2 Modified immediate constants in Thumb instructions
    > -//
    > -// ThumbExpandImm() returns the modified immediate constant given an imm12 for
    > -// Thumb data-processing instructions with modified immediate.
    > -// See also A6.3.1 Data-processing (modified immediate).
    > -static inline unsigned ThumbExpandImm(unsigned imm12) {
    > -  assert(imm12 <= 0xFFF && "Invalid imm12 argument");
    > -
    > -  // If the leading two bits is 0b00, the modified immediate constant is
    > -  // obtained by splatting the low 8 bits into the first byte, every other byte,
    > -  // or every byte of a 32-bit value.
    > -  //
    > -  // Otherwise, a rotate right of '1':imm12<6:0> by the amount imm12<11:7> is
    > -  // performed.
    > -
    > -  if (slice(imm12, 11, 10) == 0) {
    > -    unsigned short control = slice(imm12, 9, 8);
    > -    unsigned imm8 = slice(imm12, 7, 0);
    > -    switch (control) {
    > -    default:
    > -      assert(0 && "No such value");
    > -      return 0;
    > -    case 0:
    > -      return imm8;
    > -    case 1:
    > -      return imm8 << 16 | imm8;
    > -    case 2:
    > -      return imm8 << 24 | imm8 << 8;
    > -    case 3:
    > -      return imm8 << 24 | imm8 << 16 | imm8 << 8 | imm8;
    > -    }
    > -  } else {
    > -    // A rotate is required.
    > -    unsigned Val = 1 << 7 | slice(imm12, 6, 0);
    > -    unsigned Amt = slice(imm12, 11, 7);
    > -    return ARM_AM::rotr32(Val, Amt);
    > -  }
    > -}
    > -
    > -static inline int decodeImm32_B_EncodingT3(uint32_t insn) {
    > -  bool S = slice(insn, 26, 26);
    > -  bool J1 = slice(insn, 13, 13);
    > -  bool J2 = slice(insn, 11, 11);
    > -  unsigned Imm21 = slice(insn, 21, 16) << 12 | slice(insn, 10, 0) << 1;
    > -  if (S) Imm21 |= 1 << 20;
    > -  if (J2) Imm21 |= 1 << 19;
    > -  if (J1) Imm21 |= 1 << 18;
    > -
    > -  return SignExtend32<21>(Imm21);
    > -}
    > -
    > -static inline int decodeImm32_B_EncodingT4(uint32_t insn) {
    > -  unsigned S = slice(insn, 26, 26);
    > -  bool I1 = slice(insn, 13, 13) == S;
    > -  bool I2 = slice(insn, 11, 11) == S;
    > -  unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 0) << 1;
    > -  if (S) Imm25 |= 1 << 24;
    > -  if (I1) Imm25 |= 1 << 23;
    > -  if (I2) Imm25 |= 1 << 22;
    > -
    > -  return SignExtend32<25>(Imm25);
    > -}
    > -
    > -static inline int decodeImm32_BL(uint32_t insn) {
    > -  unsigned S = slice(insn, 26, 26);
    > -  bool I1 = slice(insn, 13, 13) == S;
    > -  bool I2 = slice(insn, 11, 11) == S;
    > -  unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 0) << 1;
    > -  if (S) Imm25 |= 1 << 24;
    > -  if (I1) Imm25 |= 1 << 23;
    > -  if (I2) Imm25 |= 1 << 22;
    > -
    > -  return SignExtend32<25>(Imm25);
    > -}
    > -
    > -static inline int decodeImm32_BLX(uint32_t insn) {
    > -  unsigned S = slice(insn, 26, 26);
    > -  bool I1 = slice(insn, 13, 13) == S;
    > -  bool I2 = slice(insn, 11, 11) == S;
    > -  unsigned Imm25 = slice(insn, 25, 16) << 12 | slice(insn, 10, 1) << 2;
    > -  if (S) Imm25 |= 1 << 24;
    > -  if (I1) Imm25 |= 1 << 23;
    > -  if (I2) Imm25 |= 1 << 22;
    > -
    > -  return SignExtend32<25>(Imm25);
    > -}
    > -
    > -///////////////////////////////////////////////
    > -//                                           //
    > -// Thumb1 instruction disassembly functions. //
    > -//                                           //
    > -///////////////////////////////////////////////
    > -
    > -// See "Utilities for 16-bit Thumb instructions" for register naming convention.
    > -
    > -// A6.2.1 Shift (immediate), add, subtract, move, and compare
    > -//
    > -// shift immediate:         tRd CPSR tRn imm5
    > -// add/sub register:        tRd CPSR tRn tRm
    > -// add/sub 3-bit immediate: tRd CPSR tRn imm3
    > -// add/sub 8-bit immediate: tRt CPSR tRt(TIED_TO) imm8
    > -// mov/cmp immediate:       tRt [CPSR] imm8 (CPSR present for mov)
    > -//
    > -// Special case:
    > -// tMOVSr:                  tRd tRn
    > -static bool DisassembleThumb1General(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID
    > -         && "Invalid arguments");
    > -
    > -  bool Imm3 = (Opcode == ARM::tADDi3 || Opcode == ARM::tSUBi3);
    > -
    > -  // Use Rt implies use imm8.
    > -  bool UseRt = (Opcode == ARM::tADDi8 || Opcode == ARM::tSUBi8 ||
    > -                Opcode == ARM::tMOVi8 || Opcode == ARM::tCMPi8);
    > -
    > -  // Add the destination operand.
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                  UseRt ? getT1tRt(insn) : getT1tRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // Check whether the next operand to be added is a CCR Register.
    > -  if (OpInfo[OpIdx].RegClass == ARM::CCRRegClassID) {
    > -    assert(OpInfo[OpIdx].isOptionalDef() && "Optional def operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(B->InITBlock() ? 0 : ARM::CPSR));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Check whether the next operand to be added is a Thumb1 Register.
    > -  assert(OpIdx < NumOps && "More operands expected");
    > -  if (OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
    > -    // For UseRt, the reg operand is tied to the first reg operand.
    > -    MI.addOperand(MCOperand::CreateReg(
    > -                    getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                    UseRt ? getT1tRt(insn) : getT1tRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Special case for tMOVSr.
    > -  if (OpIdx == NumOps)
    > -    return true;
    > -
    > -  // The next available operand is either a reg operand or an imm operand.
    > -  if (OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
    > -    // Three register operand instructions.
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                       getT1tRm(insn))));
    > -  } else {
    > -    assert(OpInfo[OpIdx].RegClass < 0 &&
    > -           !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()
    > -           && "Pure imm operand expected");
    > -    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;
    > -
    > -  return true;
    > -}
    > -
    > -// A6.2.2 Data-processing
    > -//
    > -// tCMPr, tTST, tCMN: tRd tRn
    > -// tMVN, tRSB:        tRd CPSR tRn
    > -// Others:            tRd CPSR tRd(TIED_TO) tRn
    > -static bool DisassembleThumb1DP(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
    > -         (OpInfo[1].RegClass == ARM::CCRRegClassID
    > -          || OpInfo[1].RegClass == ARM::tGPRRegClassID)
    > -         && "Invalid arguments");
    > -
    > -  // Add the destination operand.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                     getT1tRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // Check whether the next operand to be added is a CCR Register.
    > -  if (OpInfo[OpIdx].RegClass == ARM::CCRRegClassID) {
    > -    assert(OpInfo[OpIdx].isOptionalDef() && "Optional def operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(B->InITBlock() ? 0 : ARM::CPSR));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // We have either { tRd(TIED_TO), tRn } or { tRn } remaining.
    > -  // Process the TIED_TO operand first.
    > -
    > -  assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID
    > -         && "Thumb reg operand expected");
    > -  int Idx;
    > -  if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
    > -    // The reg operand is tied to the first reg operand.
    > -    MI.addOperand(MI.getOperand(Idx));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Process possible next reg operand.
    > -  if (OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID) {
    > -    // Add tRn operand.
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                       getT1tRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// A6.2.3 Special data instructions and branch and exchange
    > -//
    > -// tADDhirr: Rd Rd(TIED_TO) Rm
    > -// tCMPhir:  Rd Rm
    > -// tMOVr, tMOVgpr2gpr, tMOVgpr2tgpr, tMOVtgpr2gpr: Rd|tRd Rm|tRn
    > -// tBX: Rm
    > -// tBX_RET: 0 operand
    > -// tBX_RET_vararg: Rm
    > -// tBLXr: Rm
    > -// tBRIND: Rm
    > -static bool DisassembleThumb1Special(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  // tBX_RET has 0 operand.
    > -  if (NumOps == 0)
    > -    return true;
    > -
    > -  // BX/BLX/tBRIND (indirect branch, i.e, mov pc, Rm) has 1 reg operand: Rm.
    > -  if (Opcode==ARM::tBLXr || Opcode==ARM::tBX || Opcode==ARM::tBRIND) {
    > -    if (Opcode == ARM::tBLXr) {
    > -      // 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 += 1;
    > -
    > -    if (Opcode == ARM::tBX) {
    > -      // Handling the two predicate operands after the reg operand.
    > -      if (!B->DoPredicateOperands(MI, Opcode, insn, NumOps))
    > -        return false;
    > -      NumOpsAdded += 2;
    > -    }
    > -
    > -    return true;
    > -  }
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  // Add the destination operand.
    > -  unsigned RegClass = OpInfo[OpIdx].RegClass;
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, RegClass,
    > -                                  IsGPR(RegClass) ? getT1Rd(insn)
    > -                                                  : getT1tRd(insn))));
    > -  ++OpIdx;
    > -
    > -  // We have either { Rd(TIED_TO), Rm } or { Rm|tRn } remaining.
    > -  // Process the TIED_TO operand first.
    > -
    > -  assert(OpIdx < NumOps && "More operands expected");
    > -  int Idx;
    > -  if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
    > -    // The reg operand is tied to the first reg operand.
    > -    MI.addOperand(MI.getOperand(Idx));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // The next reg operand is either Rm or tRn.
    > -  assert(OpIdx < NumOps && "More operands expected");
    > -  RegClass = OpInfo[OpIdx].RegClass;
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, RegClass,
    > -                                  IsGPR(RegClass) ? getT1Rm(insn)
    > -                                                  : getT1tRn(insn))));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -// A8.6.59 LDR (literal)
    > -//
    > -// tLDRpci: tRt imm8*4
    > -static bool DisassembleThumb1LdPC(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
    > -         (OpInfo[1].RegClass < 0 &&
    > -          !OpInfo[1].isPredicate() &&
    > -          !OpInfo[1].isOptionalDef())
    > -         && "Invalid arguments");
    > -
    > -  // Add the destination operand.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                     getT1tRt(insn))));
    > -
    > -  // And the (imm8 << 2) operand.
    > -  MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn) << 2));
    > -
    > -  NumOpsAdded = 2;
    > -
    > -  return true;
    > -}
    > -
    > -// Thumb specific addressing modes (see ARMInstrThumb.td):
    > -//
    > -// t_addrmode_rr := reg + reg
    > -//
    > -// t_addrmode_s4 := reg + reg
    > -//                  reg + imm5 * 4
    > -//
    > -// t_addrmode_s2 := reg + reg
    > -//                  reg + imm5 * 2
    > -//
    > -// t_addrmode_s1 := reg + reg
    > -//                  reg + imm5
    > -//
    > -// t_addrmode_sp := sp + imm8 * 4
    > -//
    > -
    > -// A8.6.63 LDRB (literal)
    > -// A8.6.79 LDRSB (literal)
    > -// A8.6.75 LDRH (literal)
    > -// A8.6.83 LDRSH (literal)
    > -// A8.6.59 LDR (literal)
    > -//
    > -// These instrs calculate an address from the PC value and an immediate offset.
    > -// Rd Rn=PC (+/-)imm12 (+ if Inst{23} == 0b1)
    > -static bool DisassembleThumb2Ldpci(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(NumOps >= 2 &&
    > -         OpInfo[0].RegClass == ARM::GPRRegClassID &&
    > -         OpInfo[1].RegClass < 0 &&
    > -         "Expect >= 2 operands, first as reg, and second as imm operand");
    > -
    > -  // Build the register operand, followed by the (+/-)imm12 immediate.
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRd(insn))));
    > -
    > -  MI.addOperand(MCOperand::CreateImm(decodeImm12(insn)));
    > -
    > -  NumOpsAdded = 2;
    > -
    > -  return true;
    > -}
    > -
    > -
    > -// A6.2.4 Load/store single data item
    > -//
    > -// Load/Store Register (reg|imm):      tRd tRn imm5|tRm
    > -// Load Register Signed Byte|Halfword: tRd tRn tRm
    > -static bool DisassembleThumb1LdSt(unsigned opA, MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  assert(NumOps >= 2
    > -         && OpInfo[0].RegClass == ARM::tGPRRegClassID
    > -         && OpInfo[1].RegClass == ARM::tGPRRegClassID
    > -         && "Expect >= 2 operands and first two as thumb reg operands");
    > -
    > -  // Add the destination reg and the base reg.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                     getT1tRd(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                     getT1tRn(insn))));
    > -  OpIdx = 2;
    > -
    > -  // We have either { imm5 } or { tRm } remaining.
    > -  // Note that STR/LDR (register) should skip the imm5 offset operand for
    > -  // t_addrmode_s[1|2|4].
    > -
    > -  assert(OpIdx < NumOps && "More operands expected");
    > -
    > -  if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate() &&
    > -      !OpInfo[OpIdx].isOptionalDef()) {
    > -    // Table A6-5 16-bit Thumb Load/store instructions
    > -    // opA = 0b0101 for STR/LDR (register) and friends.
    > -    // Otherwise, we have STR/LDR (immediate) and friends.
    > -    assert(opA != 5 && "Immediate operand expected for this opcode");
    > -    MI.addOperand(MCOperand::CreateImm(getT1Imm5(insn)));
    > -    ++OpIdx;
    > -  } else {
    > -    // The next reg operand is tRm, the offset.
    > -    assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass == ARM::tGPRRegClassID
    > -           && "Thumb reg operand expected");
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                       getT1tRm(insn))));
    > -    ++OpIdx;
    > -  }
    > -  return true;
    > -}
    > -
    > -// A6.2.4 Load/store single data item
    > -//
    > -// Load/Store Register SP relative: tRt ARM::SP imm8
    > -static bool DisassembleThumb1LdStSP(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert((Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi)
    > -         && "Unexpected opcode");
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(NumOps >= 3 &&
    > -         OpInfo[0].RegClass == ARM::tGPRRegClassID &&
    > -         OpInfo[1].RegClass == ARM::GPRRegClassID &&
    > -         (OpInfo[2].RegClass < 0 &&
    > -          !OpInfo[2].isPredicate() &&
    > -          !OpInfo[2].isOptionalDef())
    > -         && "Invalid arguments");
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                     getT1tRt(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(ARM::SP));
    > -  MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
    > -  NumOpsAdded = 3;
    > -  return true;
    > -}
    > -
    > -// Table A6-1 16-bit Thumb instruction encoding
    > -// A8.6.10 ADR
    > -//
    > -// tADDrPCi: tRt imm8
    > -static bool DisassembleThumb1AddPCi(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(Opcode == ARM::tADDrPCi && "Unexpected opcode");
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
    > -         (OpInfo[1].RegClass < 0 &&
    > -          !OpInfo[1].isPredicate() &&
    > -          !OpInfo[1].isOptionalDef())
    > -         && "Invalid arguments");
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                     getT1tRt(insn))));
    > -  MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
    > -  NumOpsAdded = 2;
    > -  return true;
    > -}
    > -
    > -// Table A6-1 16-bit Thumb instruction encoding
    > -// A8.6.8 ADD (SP plus immediate)
    > -//
    > -// tADDrSPi: tRt ARM::SP imm8
    > -static bool DisassembleThumb1AddSPi(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(Opcode == ARM::tADDrSPi && "Unexpected opcode");
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(NumOps >= 3 &&
    > -         OpInfo[0].RegClass == ARM::tGPRRegClassID &&
    > -         OpInfo[1].RegClass == ARM::GPRRegClassID &&
    > -         (OpInfo[2].RegClass < 0 &&
    > -          !OpInfo[2].isPredicate() &&
    > -          !OpInfo[2].isOptionalDef())
    > -         && "Invalid arguments");
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                     getT1tRt(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(ARM::SP));
    > -  MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn)));
    > -  NumOpsAdded = 3;
    > -  return true;
    > -}
    > -
    > -// tPUSH, tPOP: Pred-Imm Pred-CCR register_list
    > -//
    > -// where register_list = low registers + [lr] for PUSH or
    > -//                       low registers + [pc] for POP
    > -//
    > -// "low registers" is specified by Inst{7-0}
    > -// lr|pc is specified by Inst{8}
    > -static bool DisassembleThumb1PushPop(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert((Opcode == ARM::tPUSH || Opcode == ARM::tPOP) && "Unexpected opcode");
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  // Handling the two predicate operands before the reglist.
    > -  if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
    > -    OpIdx += 2;
    > -  else {
    > -    DEBUG(errs() << "Expected predicate operands not found.\n");
    > -    return false;
    > -  }
    > -
    > -  unsigned RegListBits = slice(insn, 8, 8) << (Opcode == ARM::tPUSH ? 14 : 15)
    > -    | slice(insn, 7, 0);
    > -
    > -  // Fill the variadic part of reglist.
    > -  for (unsigned i = 0; i < 16; ++i) {
    > -    if ((RegListBits >> i) & 1) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                         i)));
    > -      ++OpIdx;
    > -    }
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// A6.2.5 Miscellaneous 16-bit instructions
    > -// Delegate to DisassembleThumb1PushPop() for tPUSH & tPOP.
    > -//
    > -// tADDspi, tSUBspi: ARM::SP ARM::SP(TIED_TO) imm7
    > -// t2IT:             firstcond=Inst{7-4} mask=Inst{3-0}
    > -// tCBNZ, tCBZ:      tRd imm6*2
    > -// tBKPT:            imm8
    > -// tNOP, tSEV, tYIELD, tWFE, tWFI:
    > -//   no operand (except predicate pair)
    > -// tSETEND: i1
    > -// Others:           tRd tRn
    > -static bool DisassembleThumb1Misc(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  if (NumOps == 0)
    > -    return true;
    > -
    > -  if (Opcode == ARM::tPUSH || Opcode == ARM::tPOP)
    > -    return DisassembleThumb1PushPop(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -
    > -  // Predicate operands are handled elsewhere.
    > -  if (NumOps == 2 &&
    > -      OpInfo[0].isPredicate() && OpInfo[1].isPredicate() &&
    > -      OpInfo[0].RegClass < 0 && OpInfo[1].RegClass == ARM::CCRRegClassID) {
    > -    return true;
    > -  }
    > -
    > -  if (Opcode == ARM::tADDspi || Opcode == ARM::tSUBspi) {
    > -    // Special case handling for tADDspi and tSUBspi.
    > -    // A8.6.8 ADD (SP plus immediate) & A8.6.215 SUB (SP minus immediate)
    > -    MI.addOperand(MCOperand::CreateReg(ARM::SP));
    > -    MI.addOperand(MCOperand::CreateReg(ARM::SP));
    > -    MI.addOperand(MCOperand::CreateImm(getT1Imm7(insn)));
    > -    NumOpsAdded = 3;
    > -    return true;
    > -  }
    > -
    > -  if (Opcode == ARM::t2IT) {
    > -    // Special case handling for If-Then.
    > -    // A8.6.50 IT
    > -    // Tag the (firstcond[0] bit << 4) along with mask.
    > -
    > -    // firstcond
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 4)));
    > -
    > -    // firstcond[0] and mask
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
    > -    NumOpsAdded = 2;
    > -    return true;
    > -  }
    > -
    > -  if (Opcode == ARM::tBKPT) {
    > -    MI.addOperand(MCOperand::CreateImm(getT1Imm8(insn))); // breakpoint value
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  // CPS has a singleton $opt operand that contains the following information:
    > -  // The first op would be 0b10 as enable and 0b11 as disable in regular ARM,
    > -  // but in Thumb it's is 0 as enable and 1 as disable. So map it to ARM's
    > -  // default one. The second get the AIF flags from Inst{2-0}.
    > -  if (Opcode == ARM::tCPS) {
    > -    MI.addOperand(MCOperand::CreateImm(2 + slice(insn, 4, 4)));
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 2, 0)));
    > -    NumOpsAdded = 2;
    > -    return true;
    > -  }
    > -
    > -  if (Opcode == ARM::tSETEND) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 1)));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  assert(NumOps >= 2 && OpInfo[0].RegClass == ARM::tGPRRegClassID &&
    > -         (OpInfo[1].RegClass < 0 || OpInfo[1].RegClass==ARM::tGPRRegClassID)
    > -         && "Expect >=2 operands");
    > -
    > -  // Add the destination operand.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                     getT1tRd(insn))));
    > -
    > -  if (OpInfo[1].RegClass == ARM::tGPRRegClassID) {
    > -    // Two register instructions.
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                       getT1tRn(insn))));
    > -  } else {
    > -    // CBNZ, CBZ
    > -    assert((Opcode == ARM::tCBNZ || Opcode == ARM::tCBZ) &&"Unexpected opcode");
    > -    MI.addOperand(MCOperand::CreateImm(getT1Imm6(insn) * 2));
    > -  }
    > -
    > -  NumOpsAdded = 2;
    > -
    > -  return true;
    > -}
    > -
    > -// A8.6.53  LDM / LDMIA
    > -// A8.6.189 STM / STMIA
    > -//
    > -// tLDMIA_UPD/tSTMIA_UPD: tRt tRt AM4ModeImm Pred-Imm Pred-CCR register_list
    > -// tLDMIA:                tRt AM4ModeImm Pred-Imm Pred-CCR register_list
    > -static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode,
    > -                                     uint32_t insn, unsigned short NumOps,
    > -                                     unsigned &NumOpsAdded, BO B) {
    > -  assert((Opcode == ARM::tLDMIA || Opcode == ARM::tSTMIA) &&
    > -         "Unexpected opcode");
    > -
    > -  unsigned tRt = getT1tRt(insn);
    > -  NumOpsAdded = 0;
    > -
    > -  // WB register, if necessary.
    > -  if (Opcode == ARM::tLDMIA_UPD || Opcode == ARM::tSTMIA_UPD) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       tRt)));
    > -    ++NumOpsAdded;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     tRt)));
    > -  ++NumOpsAdded;
    > -
    > -  // Handling the two predicate operands before the reglist.
    > -  if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) {
    > -    NumOpsAdded += 2;
    > -  } else {
    > -    DEBUG(errs() << "Expected predicate operands not found.\n");
    > -    return false;
    > -  }
    > -
    > -  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)
    > -    if ((RegListBits >> i) & 1) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID,
    > -                                                         i)));
    > -      ++NumOpsAdded;
    > -    }
    > -
    > -  return true;
    > -}
    > -
    > -static bool DisassembleThumb1LdMul(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -  return DisassembleThumb1LdStMul(true, MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                  B);
    > -}
    > -
    > -static bool DisassembleThumb1StMul(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -  return DisassembleThumb1LdStMul(false, MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                  B);
    > -}
    > -
    > -// A8.6.16 B Encoding T1
    > -// cond = Inst{11-8} & imm8 = Inst{7-0}
    > -// imm32 = SignExtend(imm8:'0', 32)
    > -//
    > -// tBcc: offset Pred-Imm Pred-CCR
    > -// tSVC: imm8 Pred-Imm Pred-CCR
    > -// tTRAP: 0 operand (early return)
    > -static bool DisassembleThumb1CondBr(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO) {
    > -
    > -  if (Opcode == ARM::tTRAP)
    > -    return true;
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(NumOps == 3 && OpInfo[0].RegClass < 0 &&
    > -         OpInfo[1].isPredicate() && OpInfo[2].RegClass == ARM::CCRRegClassID
    > -         && "Exactly 3 operands expected");
    > -
    > -  unsigned Imm8 = getT1Imm8(insn);
    > -  MI.addOperand(MCOperand::CreateImm(
    > -                  Opcode == ARM::tBcc ? SignExtend32<9>(Imm8 << 1)
    > -                                      : (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;
    > -}
    > -
    > -// A8.6.16 B Encoding T2
    > -// imm11 = Inst{10-0}
    > -// imm32 = SignExtend(imm11:'0', 32)
    > -//
    > -// tB: offset
    > -static bool DisassembleThumb1Br(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  assert(NumOps == 1 && OpInfo[0].RegClass < 0 && "1 imm operand expected");
    > -
    > -  unsigned Imm11 = getT1Imm11(insn);
    > -
    > -  MI.addOperand(MCOperand::CreateImm(SignExtend32<12>(Imm11 << 1)));
    > -
    > -  NumOpsAdded = 1;
    > -
    > -  return true;
    > -
    > -}
    > -
    > -// See A6.2 16-bit Thumb instruction encoding for instruction classes
    > -// corresponding to op.
    > -//
    > -// Table A6-1 16-bit Thumb instruction encoding (abridged)
    > -// op    Instruction or instruction class
    > -// ------  --------------------------------------------------------------------
    > -// 00xxxx  Shift (immediate), add, subtract, move, and compare on page A6-7
    > -// 010000  Data-processing on page A6-8
    > -// 010001  Special data instructions and branch and exchange on page A6-9
    > -// 01001x  Load from Literal Pool, see LDR (literal) on page A8-122
    > -// 0101xx  Load/store single data item on page A6-10
    > -// 011xxx
    > -// 100xxx
    > -// 10100x  Generate PC-relative address, see ADR on page A8-32
    > -// 10101x  Generate SP-relative address, see ADD (SP plus immediate) on
    > -//         page A8-28
    > -// 1011xx  Miscellaneous 16-bit instructions on page A6-11
    > -// 11000x  Store multiple registers, see STM / STMIA / STMEA on page A8-374
    > -// 11001x  Load multiple registers, see LDM / LDMIA / LDMFD on page A8-110 a
    > -// 1101xx  Conditional branch, and Supervisor Call on page A6-13
    > -// 11100x  Unconditional Branch, see B on page A8-44
    > -//
    > -static bool DisassembleThumb1(uint16_t op, MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  unsigned op1 = slice(op, 5, 4);
    > -  unsigned op2 = slice(op, 3, 2);
    > -  unsigned op3 = slice(op, 1, 0);
    > -  unsigned opA = slice(op, 5, 2);
    > -  switch (op1) {
    > -  case 0:
    > -    // A6.2.1 Shift (immediate), add, subtract, move, and compare
    > -    return DisassembleThumb1General(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -  case 1:
    > -    switch (op2) {
    > -    case 0:
    > -      switch (op3) {
    > -      case 0:
    > -        // A6.2.2 Data-processing
    > -        return DisassembleThumb1DP(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -      case 1:
    > -        // A6.2.3 Special data instructions and branch and exchange
    > -        return DisassembleThumb1Special(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                        B);
    > -      default:
    > -        // A8.6.59 LDR (literal)
    > -        return DisassembleThumb1LdPC(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -      }
    > -      break;
    > -    default:
    > -      // A6.2.4 Load/store single data item
    > -      return DisassembleThumb1LdSt(opA, MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                   B);
    > -      break;
    > -    }
    > -    break;
    > -  case 2:
    > -    switch (op2) {
    > -    case 0:
    > -      // A6.2.4 Load/store single data item
    > -      return DisassembleThumb1LdSt(opA, MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                   B);
    > -    case 1:
    > -      // A6.2.4 Load/store single data item
    > -      return DisassembleThumb1LdStSP(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -    case 2:
    > -      if (op3 <= 1) {
    > -        // A8.6.10 ADR
    > -        return DisassembleThumb1AddPCi(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                       B);
    > -      } else {
    > -        // A8.6.8 ADD (SP plus immediate)
    > -        return DisassembleThumb1AddSPi(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                       B);
    > -      }
    > -    default:
    > -      // A6.2.5 Miscellaneous 16-bit instructions
    > -      return DisassembleThumb1Misc(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -    }
    > -    break;
    > -  case 3:
    > -    switch (op2) {
    > -    case 0:
    > -      if (op3 <= 1) {
    > -        // A8.6.189 STM / STMIA / STMEA
    > -        return DisassembleThumb1StMul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -      } else {
    > -        // A8.6.53 LDM / LDMIA / LDMFD
    > -        return DisassembleThumb1LdMul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -      }
    > -    case 1:
    > -      // A6.2.6 Conditional branch, and Supervisor Call
    > -      return DisassembleThumb1CondBr(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -    case 2:
    > -      // Unconditional Branch, see B on page A8-44
    > -      return DisassembleThumb1Br(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -    default:
    > -      assert(0 && "Unreachable code");
    > -      break;
    > -    }
    > -    break;
    > -  default:
    > -    assert(0 && "Unreachable code");
    > -    break;
    > -  }
    > -
    > -  return false;
    > -}
    > -
    > -///////////////////////////////////////////////
    > -//                                           //
    > -// Thumb2 instruction disassembly functions. //
    > -//                                           //
    > -///////////////////////////////////////////////
    > -
    > -///////////////////////////////////////////////////////////
    > -//                                                       //
    > -// Note: the register naming follows the ARM convention! //
    > -//                                                       //
    > -///////////////////////////////////////////////////////////
    > -
    > -static inline bool Thumb2SRSOpcode(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return false;
    > -  case ARM::t2SRSDBW: case ARM::t2SRSDB:
    > -  case ARM::t2SRSIAW: case ARM::t2SRSIA:
    > -    return true;
    > -  }
    > -}
    > -
    > -static inline bool Thumb2RFEOpcode(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return false;
    > -  case ARM::t2RFEDBW: case ARM::t2RFEDB:
    > -  case ARM::t2RFEIAW: case ARM::t2RFEIA:
    > -    return true;
    > -  }
    > -}
    > -
    > -// t2SRS[IA|DB]W/t2SRS[IA|DB]: mode_imm = Inst{4-0}
    > -static bool DisassembleThumb2SRS(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded) {
    > -  MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));
    > -  NumOpsAdded = 1;
    > -  return true;
    > -}
    > -
    > -// 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) {
    > -  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;
    > -}
    > -
    > -static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  if (Thumb2SRSOpcode(Opcode))
    > -    return DisassembleThumb2SRS(MI, Opcode, insn, NumOps, NumOpsAdded);
    > -
    > -  if (Thumb2RFEOpcode(Opcode))
    > -    return DisassembleThumb2RFE(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -
    > -  assert((Opcode == ARM::t2LDMIA || Opcode == ARM::t2LDMIA_UPD ||
    > -          Opcode == ARM::t2LDMDB || Opcode == ARM::t2LDMDB_UPD ||
    > -          Opcode == ARM::t2STMIA || Opcode == ARM::t2STMIA_UPD ||
    > -          Opcode == ARM::t2STMDB || Opcode == ARM::t2STMDB_UPD)
    > -         && "Unexpected opcode");
    > -  assert(NumOps >= 4 && "Thumb2 LdStMul expects NumOps >= 4");
    > -
    > -  NumOpsAdded = 0;
    > -
    > -  unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn));
    > -
    > -  // Writeback to base.
    > -  if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD ||
    > -      Opcode == ARM::t2STMIA_UPD || Opcode == ARM::t2STMDB_UPD) {
    > -    MI.addOperand(MCOperand::CreateReg(Base));
    > -    ++NumOpsAdded;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(Base));
    > -  ++NumOpsAdded;
    > -
    > -  // Handling the two predicate operands before the reglist.
    > -  if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) {
    > -    NumOpsAdded += 2;
    > -  } else {
    > -    DEBUG(errs() << "Expected predicate operands not found.\n");
    > -    return false;
    > -  }
    > -
    > -  unsigned RegListBits = insn & ((1 << 16) - 1);
    > -
    > -  // Fill the variadic part of reglist.
    > -  for (unsigned i = 0; i < 16; ++i)
    > -    if ((RegListBits >> i) & 1) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                         i)));
    > -      ++NumOpsAdded;
    > -    }
    > -
    > -  return true;
    > -}
    > -
    > -// t2LDREX: Rd Rn
    > -// t2LDREXD: Rd Rs Rn
    > -// t2LDREXB, t2LDREXH: Rd Rn
    > -// t2STREX: Rs Rd Rn
    > -// t2STREXD: Rm Rd Rs Rn
    > -// t2STREXB, t2STREXH: Rm Rd Rn
    > -static bool DisassembleThumb2LdStEx(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2
    > -         && OpInfo[0].RegClass > 0
    > -         && OpInfo[1].RegClass > 0
    > -         && "Expect >=2 operands and first two as reg operands");
    > -
    > -  bool isStore = (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH);
    > -  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 ? Rt2 : Rd)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Source operand for store and destination operand for load.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     Rt)));
    > -  ++OpIdx;
    > -
    > -  // Thumb2 doubleword complication: with an extra source/destination operand.
    > -  if (isDW) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
    > -                                                       Rt2)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  // Finally add the pointer operand.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     Rn)));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -// t2LDRDi8: Rd Rs Rn imm8s4 (offset mode)
    > -// t2LDRDpci: Rd Rs imm8s4 (Not decoded, prefer the generic t2LDRDi8 version)
    > -// t2STRDi8: Rd Rs Rn imm8s4 (offset mode)
    > -//
    > -// Ditto for t2LDRD_PRE, t2LDRD_POST, t2STRD_PRE, t2STRD_POST, which are for
    > -// disassembly only and do not have a tied_to writeback base register operand.
    > -static bool DisassembleThumb2LdStDual(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -  if (!OpInfo) return false;
    > -
    > -  // 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;
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair,
    > -                                                     decodeRd(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassPair,
    > -                                                     decodeRs(insn))));
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassBase,
    > -                                                     decodeRn(insn))));
    > -  unsigned Added = 4;
    > -  switch (MI.getOpcode()) {
    > -    case ARM::t2LDRD_PRE:
    > -    case ARM::t2LDRD_POST:
    > -    case ARM::t2STRD_PRE:
    > -    case ARM::t2STRD_POST:
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RegClassBase,
    > -                                                         decodeRn(insn))));
    > -      Added = 5;
    > -    default:
    > -      break;
    > -  }
    > -
    > -  // Finally add (+/-)imm8*4, depending on the U bit.
    > -  int Offset = getImm8(insn) * 4;
    > -  if (getUBit(insn) == 0)
    > -    Offset = -Offset;
    > -  MI.addOperand(MCOperand::CreateImm(Offset));
    > -  NumOpsAdded = Added;
    > -
    > -  return true;
    > -}
    > -
    > -// t2TBB, t2TBH: Rn Rm Pred-Imm Pred-CCR
    > -static bool DisassembleThumb2TB(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  assert(NumOps >= 2 && "Expect >= 2 operands");
    > -
    > -  // The generic version of TBB/TBH needs a base register.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -  // Add the index register.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -  NumOpsAdded = 2;
    > -
    > -  return true;
    > -}
    > -
    > -static inline bool Thumb2ShiftOpcode(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return false;
    > -  case ARM::t2MOVCClsl: case ARM::t2MOVCClsr:
    > -  case ARM::t2MOVCCasr: case ARM::t2MOVCCror:
    > -  case ARM::t2LSLri:    case ARM::t2LSRri:
    > -  case ARM::t2ASRri:    case ARM::t2RORri:
    > -    return true;
    > -  }
    > -}
    > -
    > -// A6.3.11 Data-processing (shifted register)
    > -//
    > -// Two register operands (Rn=0b1111 no 1st operand reg): Rs Rm
    > -// Two register operands (Rs=0b1111 no dst operand reg): Rn Rm
    > -// Three register operands: Rs Rn Rm
    > -// Three register operands: (Rn=0b1111 Conditional Move) Rs Ro(TIED_TO) Rm
    > -//
    > -// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
    > -// register with shift forms: (Rm, ConstantShiftSpecifier).
    > -// Constant shift specifier: Imm = (ShOp | ShAmt<<3).
    > -//
    > -// There are special instructions, like t2MOVsra_flag and t2MOVsrl_flag, which
    > -// only require two register operands: Rd, Rm in ARM Reference Manual terms, and
    > -// nothing else, because the shift amount is already specified.
    > -// Similar case holds for t2MOVrx, t2ADDrr, ..., etc.
    > -static bool DisassembleThumb2DPSoReg(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  // Special case handling.
    > -  if (Opcode == ARM::t2BR_JT) {
    > -    assert(NumOps == 4
    > -           && OpInfo[0].RegClass == ARM::GPRRegClassID
    > -           && OpInfo[1].RegClass == ARM::GPRRegClassID
    > -           && OpInfo[2].RegClass < 0
    > -           && OpInfo[3].RegClass < 0
    > -           && "Exactly 4 operands expect and first two as reg operands");
    > -    // Only need to populate the src reg operand.
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -    MI.addOperand(MCOperand::CreateReg(0));
    > -    MI.addOperand(MCOperand::CreateImm(0));
    > -    MI.addOperand(MCOperand::CreateImm(0));
    > -    NumOpsAdded = 4;
    > -    return true;
    > -  }
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2
    > -         && (OpInfo[0].RegClass == ARM::GPRRegClassID ||
    > -             OpInfo[0].RegClass == ARM::rGPRRegClassID)
    > -         && (OpInfo[1].RegClass == ARM::GPRRegClassID ||
    > -             OpInfo[1].RegClass == ARM::rGPRRegClassID)
    > -         && "Expect >= 2 operands and first two as reg operands");
    > -
    > -  bool ThreeReg = (NumOps > 2 && (OpInfo[2].RegClass == ARM::GPRRegClassID ||
    > -                                  OpInfo[2].RegClass == ARM::rGPRRegClassID));
    > -  bool NoDstReg = (decodeRs(insn) == 0xF);
    > -
    > -  // Build the register operands, followed by the constant shift specifier.
    > -
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, OpInfo[0].RegClass,
    > -                                  NoDstReg ? decodeRn(insn) : decodeRs(insn))));
    > -  ++OpIdx;
    > -
    > -  if (ThreeReg) {
    > -    int Idx;
    > -    if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
    > -      // Process tied_to operand constraint.
    > -      MI.addOperand(MI.getOperand(Idx));
    > -      ++OpIdx;
    > -    } else if (!NoDstReg) {
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[1].RegClass,
    > -                                                         decodeRn(insn))));
    > -      ++OpIdx;
    > -    } else {
    > -      DEBUG(errs() << "Thumb2 encoding error: d==15 for three-reg operands.\n");
    > -      return false;
    > -    }
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     decodeRm(insn))));
    > -  ++OpIdx;
    > -
    > -  if (NumOps == OpIdx)
    > -    return true;
    > -
    > -  if (OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
    > -      && !OpInfo[OpIdx].isOptionalDef()) {
    > -
    > -    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 imm5 = getShiftAmtBits(insn);
    > -      // The PKHBT/PKHTB instructions have an implied shift type and so just
    > -      // use a plain immediate for the amount.
    > -      if (Opcode == ARM::t2PKHBT || Opcode == ARM::t2PKHTB)
    > -        MI.addOperand(MCOperand::CreateImm(imm5));
    > -      else {
    > -        ARM_AM::ShiftOpc ShOp = ARM_AM::no_shift;
    > -        unsigned bits2 = getShiftTypeBits(insn);
    > -        unsigned ShAmt = decodeImmShift(bits2, imm5, ShOp);
    > -        MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(ShOp, ShAmt)));
    > -      }
    > -    }
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// A6.3.1 Data-processing (modified immediate)
    > -//
    > -// Two register operands: Rs Rn ModImm
    > -// One register operands (Rs=0b1111 no explicit dest reg): Rn ModImm
    > -// One register operands (Rn=0b1111 no explicit src reg): Rs ModImm -
    > -// {t2MOVi, t2MVNi}
    > -//
    > -// ModImm = ThumbExpandImm(i:imm3:imm8)
    > -static bool DisassembleThumb2DPModImm(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  unsigned RdRegClassID = OpInfo[0].RegClass;
    > -  assert(NumOps >= 2 && (RdRegClassID == ARM::GPRRegClassID ||
    > -                         RdRegClassID == ARM::rGPRRegClassID)
    > -         && "Expect >= 2 operands and first one as reg operand");
    > -
    > -  unsigned RnRegClassID = OpInfo[1].RegClass;
    > -  bool TwoReg = (RnRegClassID == ARM::GPRRegClassID
    > -                 || RnRegClassID == ARM::rGPRRegClassID);
    > -  bool NoDstReg = (decodeRs(insn) == 0xF);
    > -
    > -  // Build the register operands, followed by the modified immediate.
    > -
    > -  MI.addOperand(MCOperand::CreateReg(
    > -                  getRegisterEnum(B, RdRegClassID,
    > -                                  NoDstReg ? decodeRn(insn) : decodeRs(insn))));
    > -  ++OpIdx;
    > -
    > -  if (TwoReg) {
    > -    if (NoDstReg) {
    > -      DEBUG(errs()<<"Thumb2 encoding error: d==15 for DPModImm 2-reg instr.\n");
    > -      return false;
    > -    }
    > -    int Idx;
    > -    if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::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;
    > -  }
    > -
    > -  // The modified immediate operand should come next.
    > -  assert(OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 &&
    > -         !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()
    > -         && "Pure imm operand expected");
    > -
    > -  // i:imm3:imm8
    > -  // A6.3.2 Modified immediate constants in Thumb instructions
    > -  unsigned imm12 = getIImm3Imm8(insn);
    > -  MI.addOperand(MCOperand::CreateImm(ThumbExpandImm(imm12)));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -static inline bool Thumb2SaturateOpcode(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  case ARM::t2SSAT: case ARM::t2SSAT16:
    > -  case ARM::t2USAT: case ARM::t2USAT16:
    > -    return true;
    > -  default:
    > -    return false;
    > -  }
    > -}
    > -
    > -/// DisassembleThumb2Sat - Disassemble Thumb2 saturate instructions:
    > -/// o t2SSAT, t2USAT: Rs sat_pos Rn shamt
    > -/// o t2SSAT16, t2USAT16: Rs sat_pos Rn
    > -static bool DisassembleThumb2Sat(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -                                 unsigned &NumOpsAdded, BO B) {
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  NumOpsAdded = MCID.getNumOperands() - 2; // ignore predicate operands
    > -
    > -  // Disassemble the register def.
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                     decodeRs(insn))));
    > -
    > -  unsigned Pos = slice(insn, 4, 0);
    > -  MI.addOperand(MCOperand::CreateImm(Pos));
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -
    > -  if (NumOpsAdded == 4) {
    > -    // Inst{6} encodes the shift type.
    > -    bool isASR = slice(insn, 6, 6);
    > -    // Inst{11-7} encodes the imm5 shift amount.
    > -    unsigned ShAmt = slice(insn, 11, 7);
    > -    MI.addOperand(MCOperand::CreateImm(isASR << 5 | ShAmt));
    > -  }
    > -  return true;
    > -}
    > -
    > -// A6.3.3 Data-processing (plain binary immediate)
    > -//
    > -// o t2ADDri12, t2SUBri12: Rs Rn imm12
    > -// o t2LEApcrel (ADR): Rs imm12
    > -// o t2BFC (BFC): Rs Ro(TIED_TO) bf_inv_mask_imm
    > -// o t2BFI (BFI): Rs Ro(TIED_TO) Rn bf_inv_mask_imm
    > -// o t2MOVi16: Rs imm16
    > -// o t2MOVTi16: Rs imm16
    > -// o t2SBFX (SBFX): Rs Rn lsb width
    > -// o t2UBFX (UBFX): Rs Rn lsb width
    > -// o t2BFI (BFI): Rs Rn lsb width
    > -static bool DisassembleThumb2DPBinImm(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  unsigned RdRegClassID = OpInfo[0].RegClass;
    > -  assert(NumOps >= 2 && (RdRegClassID == ARM::GPRRegClassID ||
    > -                         RdRegClassID == ARM::rGPRRegClassID)
    > -         && "Expect >= 2 operands and first one as reg operand");
    > -
    > -  unsigned RnRegClassID = OpInfo[1].RegClass;
    > -  bool TwoReg = (RnRegClassID == ARM::GPRRegClassID
    > -                 || RnRegClassID == ARM::rGPRRegClassID);
    > -
    > -  // Build the register operand(s), followed by the immediate(s).
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RdRegClassID,
    > -                                                     decodeRs(insn))));
    > -  ++OpIdx;
    > -
    > -  if (TwoReg) {
    > -    assert(NumOps >= 3 && "Expect >= 3 operands");
    > -    int Idx;
    > -    if ((Idx = MCID.getOperandConstraint(OpIdx, MCOI::TIED_TO)) != -1) {
    > -      // Process tied_to operand constraint.
    > -      MI.addOperand(MI.getOperand(Idx));
    > -    } else {
    > -      // Add src reg operand.
    > -      MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID,
    > -                                                         decodeRn(insn))));
    > -    }
    > -    ++OpIdx;
    > -  }
    > -
    > -  if (Opcode == ARM::t2BFI) {
    > -    // Add val reg operand.
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, RnRegClassID,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
    > -         && !OpInfo[OpIdx].isOptionalDef()
    > -         && "Pure imm operand expected");
    > -
    > -  // Pre-increment OpIdx.
    > -  ++OpIdx;
    > -
    > -  if (Opcode == ARM::t2ADDri12 || Opcode == ARM::t2SUBri12
    > -      || Opcode == ARM::t2LEApcrel)
    > -    MI.addOperand(MCOperand::CreateImm(getIImm3Imm8(insn)));
    > -  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));
    > -    else
    > -      return false;
    > -  } else {
    > -    // Handle the case of: lsb width
    > -    assert((Opcode == ARM::t2SBFX || Opcode == ARM::t2UBFX)
    > -            && "Unexpected opcode");
    > -    MI.addOperand(MCOperand::CreateImm(getLsb(insn)));
    > -    MI.addOperand(MCOperand::CreateImm(getWidthMinus1(insn)));
    > -
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// A6.3.4 Table A6-15 Miscellaneous control instructions
    > -// A8.6.41 DMB
    > -// A8.6.42 DSB
    > -// A8.6.49 ISB
    > -static inline bool t2MiscCtrlInstr(uint32_t insn) {
    > -  if (slice(insn, 31, 20) == 0xf3b && slice(insn, 15, 14) == 2 &&
    > -      slice(insn, 12, 12) == 0)
    > -    return true;
    > -
    > -  return false;
    > -}
    > -
    > -// A6.3.4 Branches and miscellaneous control
    > -//
    > -// A8.6.16 B
    > -// Branches: t2B, t2Bcc -> imm operand
    > -//
    > -// Branches: t2TPsoft -> no operand
    > -//
    > -// A8.6.23 BL, BLX (immediate)
    > -// Branches (defined in ARMInstrThumb.td): tBL, tBLXi -> imm operand
    > -//
    > -// A8.6.26
    > -// t2BXJ -> Rn
    > -//
    > -// Miscellaneous control:
    > -//   -> no operand (except pred-imm pred-ccr for CLREX, memory barrier variants)
    > -//
    > -// Hint: t2NOP, t2YIELD, t2WFE, t2WFI, t2SEV
    > -//   -> no operand (except pred-imm pred-ccr)
    > -//
    > -// t2DBG -> imm4 = Inst{3-0}
    > -//
    > -// t2MRS/t2MRSsys -> Rs
    > -// t2MSR/t2MSRsys -> Rn mask=Inst{11-8}
    > -// t2SMC -> imm4 = Inst{19-16}
    > -static bool DisassembleThumb2BrMiscCtrl(MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  if (NumOps == 0)
    > -    return true;
    > -
    > -  if (Opcode == ARM::t2DMB || Opcode == ARM::t2DSB) {
    > -    // Inst{3-0} encodes the memory barrier option for the variants.
    > -    unsigned opt = slice(insn, 3, 0);
    > -    switch (opt) {
    > -    case ARM_MB::SY:  case ARM_MB::ST:
    > -    case ARM_MB::ISH: case ARM_MB::ISHST:
    > -    case ARM_MB::NSH: case ARM_MB::NSHST:
    > -    case ARM_MB::OSH: case ARM_MB::OSHST:
    > -      MI.addOperand(MCOperand::CreateImm(opt));
    > -      NumOpsAdded = 1;
    > -      return true;
    > -    default:
    > -      return false;
    > -    }
    > -  }
    > -
    > -  if (t2MiscCtrlInstr(insn))
    > -    return true;
    > -
    > -  switch (Opcode) {
    > -  case ARM::t2CLREX:
    > -  case ARM::t2NOP:
    > -  case ARM::t2YIELD:
    > -  case ARM::t2WFE:
    > -  case ARM::t2WFI:
    > -  case ARM::t2SEV:
    > -    return true;
    > -  default:
    > -    break;
    > -  }
    > -
    > -  // FIXME: To enable correct asm parsing and disasm of CPS we need 3 different
    > -  // opcodes which match the same real instruction. This is needed since there's
    > -  // no current handling of optional arguments. Fix here when a better handling
    > -  // of optional arguments is implemented.
    > -  if (Opcode == ARM::t2CPS3p) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5)));  // iflags
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0)));  // mode
    > -    NumOpsAdded = 3;
    > -    return true;
    > -  }
    > -  if (Opcode == ARM::t2CPS2p) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 10, 9))); // imod
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 7, 5)));  // iflags
    > -    NumOpsAdded = 2;
    > -    return true;
    > -  }
    > -  if (Opcode == ARM::t2CPS1p) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 4, 0))); // mode
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  // DBG has its option specified in Inst{3-0}.
    > -  if (Opcode == ARM::t2DBG) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 3, 0)));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  // MRS and MRSsys take one GPR reg Rs.
    > -  if (Opcode == ARM::t2MRS || Opcode == ARM::t2MRSsys) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRs(insn))));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -  // BXJ takes one GPR reg Rn.
    > -  if (Opcode == ARM::t2BXJ) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -  // MSR take a mask, followed by one GPR reg Rn. The mask contains the R Bit in
    > -  // bit 4, and the special register fields in bits 3-0.
    > -  if (Opcode == ARM::t2MSR) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 20, 20) << 4 /* R Bit */ |
    > -                                       slice(insn, 11, 8) /* Special Reg */));
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRn(insn))));
    > -    NumOpsAdded = 2;
    > -    return true;
    > -  }
    > -  // SMC take imm4.
    > -  if (Opcode == ARM::t2SMC) {
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 19, 16)));
    > -    NumOpsAdded = 1;
    > -    return true;
    > -  }
    > -
    > -  // Some instructions have predicate operands first before the immediate.
    > -  if (Opcode == ARM::tBLXi || Opcode == ARM::tBL) {
    > -    // Handling the two predicate operands before the imm operand.
    > -    if (B->DoPredicateOperands(MI, Opcode, insn, NumOps))
    > -      NumOpsAdded += 2;
    > -    else {
    > -      DEBUG(errs() << "Expected predicate operands not found.\n");
    > -      return false;
    > -    }
    > -  }
    > -
    > -  // Add the imm operand.
    > -  int Offset = 0;
    > -
    > -  switch (Opcode) {
    > -  default:
    > -    assert(0 && "Unexpected opcode");
    > -    return false;
    > -  case ARM::t2B:
    > -    Offset = decodeImm32_B_EncodingT4(insn);
    > -    break;
    > -  case ARM::t2Bcc:
    > -    Offset = decodeImm32_B_EncodingT3(insn);
    > -    break;
    > -  case ARM::tBL:
    > -    Offset = decodeImm32_BL(insn);
    > -    break;
    > -  case ARM::tBLXi:
    > -    Offset = decodeImm32_BLX(insn);
    > -    break;
    > -  }
    > -
    > -  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;
    > -
    > -  return true;
    > -}
    > -
    > -static inline bool Thumb2PreloadOpcode(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return false;
    > -  case ARM::t2PLDi12:   case ARM::t2PLDi8:
    > -  case ARM::t2PLDs:
    > -  case ARM::t2PLDWi12:  case ARM::t2PLDWi8:
    > -  case ARM::t2PLDWs:
    > -  case ARM::t2PLIi12:   case ARM::t2PLIi8:
    > -  case ARM::t2PLIs:
    > -    return true;
    > -  }
    > -}
    > -
    > -static bool DisassembleThumb2PreLoad(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  // Preload Data/Instruction requires either 2 or 3 operands.
    > -  // t2PLDi12, t2PLDi8, t2PLDpci: Rn [+/-]imm12/imm8
    > -  // t2PLDr:                      Rn Rm
    > -  // t2PLDs:                      Rn Rm imm2=Inst{5-4}
    > -  // Same pattern applies for t2PLDW* and t2PLI*.
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2 &&
    > -         OpInfo[0].RegClass == ARM::GPRRegClassID &&
    > -         "Expect >= 2 operands and first one as reg operand");
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -  ++OpIdx;
    > -
    > -  if (OpInfo[OpIdx].RegClass == ARM::rGPRRegClassID) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID,
    > -                                                       decodeRm(insn))));
    > -  } else {
    > -    assert(OpInfo[OpIdx].RegClass < 0 && !OpInfo[OpIdx].isPredicate()
    > -           && !OpInfo[OpIdx].isOptionalDef()
    > -           && "Pure imm operand expected");
    > -    int Offset = 0;
    > -    if (Opcode == ARM::t2PLDi8 || Opcode == ARM::t2PLDWi8 ||
    > -        Opcode == ARM::t2PLIi8) {
    > -      // A8.6.117 Encoding T2: add = FALSE
    > -      unsigned Imm8 = getImm8(insn);
    > -      Offset = -1 * Imm8;
    > -    } else {
    > -      // The i12 forms.  See, for example, A8.6.117 Encoding T1.
    > -      // Note that currently t2PLDi12 also handles the previously named t2PLDpci
    > -      // opcode, that's why we use decodeImm12(insn) which returns +/- imm12.
    > -      Offset = decodeImm12(insn);
    > -    }
    > -    MI.addOperand(MCOperand::CreateImm(Offset));
    > -  }
    > -  ++OpIdx;
    > -
    > -  if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0 &&
    > -      !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -    // Fills in the shift amount for t2PLDs, t2PLDWs, t2PLIs.
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 5, 4)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  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);
    > -  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");
    > -    return true;
    > -  }
    > -
    > -  if (Load) {
    > -    if (!Word && R0 == 13) {
    > -      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
    > -    if (Half) {
    > -      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");
    > -      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
    > -// A6.3.7 Load word
    > -//
    > -// For example,
    > -//
    > -// t2LDRi12:   Rd Rn (+)imm12
    > -// t2LDRi8:    Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1)
    > -// t2LDRs:     Rd Rn Rm ConstantShiftSpecifier (see also
    > -//             DisassembleThumb2DPSoReg)
    > -// t2LDR_POST: Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
    > -// t2LDR_PRE:  Rd Rn Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
    > -//
    > -// t2STRi12:   Rd Rn (+)imm12
    > -// t2STRi8:    Rd Rn (+/-)imm8 (+ if Inst{9} == 0b1)
    > -// t2STRs:     Rd Rn Rm ConstantShiftSpecifier (see also
    > -//             DisassembleThumb2DPSoReg)
    > -// t2STR_POST: Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
    > -// t2STR_PRE:  Rn Rd Rn(TIED_TO) (+/-)imm8 (+ if Inst{9} == 0b1)
    > -//
    > -// Note that for indexed modes, the Rn(TIED_TO) operand needs to be populated
    > -// correctly, as LLVM AsmPrinter depends on it.  For indexed stores, the first
    > -// operand is Rn; for all the other instructions, Rd is the first operand.
    > -//
    > -// Delegates to DisassembleThumb2PreLoad() for preload data/instruction.
    > -// Delegates to DisassembleThumb2Ldpci() for load * literal operations.
    > -static bool DisassembleThumb2LdSt(bool Load, MCInst &MI, unsigned Opcode,
    > -    uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  unsigned Rn = decodeRn(insn);
    > -
    > -  if (Thumb2PreloadOpcode(Opcode))
    > -    return DisassembleThumb2PreLoad(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -
    > -  // See, for example, A6.3.7 Load word: Table A6-18 Load word.
    > -  if (Load && Rn == 15)
    > -    return DisassembleThumb2Ldpci(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 3 &&
    > -         OpInfo[0].RegClass > 0 &&
    > -         OpInfo[1].RegClass > 0 &&
    > -         "Expect >= 3 operands and first two as reg operands");
    > -
    > -  bool ThreeReg = (OpInfo[2].RegClass > 0);
    > -  bool TIED_TO = ThreeReg && MCID.getOperandConstraint(2, MCOI::TIED_TO) != -1;
    > -  bool Imm12 = !ThreeReg && slice(insn, 23, 23) == 1; // ARMInstrThumb2.td
    > -
    > -  // Build the register operands, followed by the immediate.
    > -  unsigned R0 = 0, R1 = 0, R2 = 0;
    > -  unsigned Rd = decodeRd(insn);
    > -  int Imm = 0;
    > -
    > -  if (!Load && TIED_TO) {
    > -    R0 = Rn;
    > -    R1 = Rd;
    > -  } else {
    > -    R0 = Rd;
    > -    R1 = Rn;
    > -  }
    > -  if (ThreeReg) {
    > -    if (TIED_TO) {
    > -      R2 = Rn;
    > -      Imm = decodeImm8(insn);
    > -    } else {
    > -      R2 = decodeRm(insn);
    > -      // See, for example, A8.6.64 LDRB (register).
    > -      // And ARMAsmPrinter::printT2AddrModeSoRegOperand().
    > -      // LSL is the default shift opc, and LLVM does not expect it to be encoded
    > -      // as part of the immediate operand.
    > -      // Imm = ARM_AM::getSORegOpc(ARM_AM::lsl, slice(insn, 5, 4));
    > -      Imm = slice(insn, 5, 4);
    > -    }
    > -  } else {
    > -    if (Imm12)
    > -      Imm = getImm12(insn);
    > -    else
    > -      Imm = decodeImm8(insn);
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     R0)));
    > -  ++OpIdx;
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     R1)));
    > -  ++OpIdx;
    > -
    > -  if (ThreeReg) {
    > -    // This could be an offset register or a TIED_TO register.
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
    > -                                                       R2)));
    > -    ++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");
    > -
    > -  MI.addOperand(MCOperand::CreateImm(Imm));
    > -  ++OpIdx;
    > -
    > -  return true;
    > -}
    > -
    > -// A6.3.12 Data-processing (register)
    > -//
    > -// Two register operands [rotate]:   Rs Rm [rotation(= (rotate:'000'))]
    > -// Three register operands only:     Rs Rn Rm
    > -// Three register operands [rotate]: Rs Rn Rm [rotation(= (rotate:'000'))]
    > -//
    > -// Parallel addition and subtraction 32-bit Thumb instructions: Rs Rn Rm
    > -//
    > -// Miscellaneous operations: Rs [Rn] Rm
    > -static bool DisassembleThumb2DPReg(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCInstrDesc &MCID = ARMInsts[Opcode];
    > -  const MCOperandInfo *OpInfo = MCID.OpInfo;
    > -  unsigned &OpIdx = NumOpsAdded;
    > -
    > -  OpIdx = 0;
    > -
    > -  assert(NumOps >= 2 &&
    > -         OpInfo[0].RegClass > 0 &&
    > -         OpInfo[1].RegClass > 0 &&
    > -         "Expect >= 2 operands and first two as reg operands");
    > -
    > -  // Build the register operands, followed by the optional rotation amount.
    > -
    > -  bool ThreeReg = NumOps > 2 && OpInfo[2].RegClass > 0;
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     decodeRs(insn))));
    > -  ++OpIdx;
    > -
    > -  if (ThreeReg) {
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B,OpInfo[OpIdx].RegClass,
    > -                                                       decodeRn(insn))));
    > -    ++OpIdx;
    > -  }
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, OpInfo[OpIdx].RegClass,
    > -                                                     decodeRm(insn))));
    > -  ++OpIdx;
    > -
    > -  if (OpIdx < NumOps && OpInfo[OpIdx].RegClass < 0
    > -      && !OpInfo[OpIdx].isPredicate() && !OpInfo[OpIdx].isOptionalDef()) {
    > -    // Add the rotation amount immediate.
    > -    MI.addOperand(MCOperand::CreateImm(slice(insn, 5, 4)));
    > -    ++OpIdx;
    > -  }
    > -
    > -  return true;
    > -}
    > -
    > -// A6.3.16 Multiply, multiply accumulate, and absolute difference
    > -//
    > -// t2MLA, t2MLS, t2SMMLA, t2SMMLS: Rs Rn Rm Ra=Inst{15-12}
    > -// t2MUL, t2SMMUL:                 Rs Rn Rm
    > -// t2SMLA[BB|BT|TB|TT|WB|WT]:      Rs Rn Rm Ra=Inst{15-12}
    > -// t2SMUL[BB|BT|TB|TT|WB|WT]:      Rs Rn Rm
    > -//
    > -// Dual halfword multiply: t2SMUAD[X], t2SMUSD[X], t2SMLAD[X], t2SMLSD[X]:
    > -//   Rs Rn Rm Ra=Inst{15-12}
    > -//
    > -// Unsigned Sum of Absolute Differences [and Accumulate]
    > -//    Rs Rn Rm [Ra=Inst{15-12}]
    > -static bool DisassembleThumb2Mul(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -
    > -  assert(NumOps >= 3 &&
    > -         OpInfo[0].RegClass == ARM::rGPRRegClassID &&
    > -         OpInfo[1].RegClass == ARM::rGPRRegClassID &&
    > -         OpInfo[2].RegClass == ARM::rGPRRegClassID &&
    > -         "Expect >= 3 operands and first three as reg operands");
    > -
    > -  // Build the register operands.
    > -
    > -  bool FourReg = NumOps > 3 && OpInfo[3].RegClass == ARM::rGPRRegClassID;
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                     decodeRs(insn))));
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -
    > -  if (FourReg)
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -
    > -  NumOpsAdded = FourReg ? 4 : 3;
    > -
    > -  return true;
    > -}
    > -
    > -// A6.3.17 Long multiply, long multiply accumulate, and divide
    > -//
    > -// t2SMULL, t2UMULL, t2SMLAL, t2UMLAL, t2UMAAL: RdLo RdHi Rn Rm
    > -// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
    > -//
    > -// Halfword multiple accumulate long: t2SMLAL: RdLo RdHi Rn Rm
    > -// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
    > -//
    > -// Dual halfword multiple: t2SMLALD[X], t2SMLSLD[X]: RdLo RdHi Rn Rm
    > -// where RdLo = Inst{15-12} and RdHi = Inst{11-8}
    > -//
    > -// Signed/Unsigned divide: t2SDIV, t2UDIV: Rs Rn Rm
    > -static bool DisassembleThumb2LongMul(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO B) {
    > -
    > -  const MCOperandInfo *OpInfo = ARMInsts[Opcode].OpInfo;
    > -
    > -  assert(NumOps >= 3 &&
    > -         OpInfo[0].RegClass == ARM::rGPRRegClassID &&
    > -         OpInfo[1].RegClass == ARM::rGPRRegClassID &&
    > -         OpInfo[2].RegClass == ARM::rGPRRegClassID &&
    > -         "Expect >= 3 operands and first three as reg operands");
    > -
    > -  bool FourReg = NumOps > 3 && OpInfo[3].RegClass == ARM::rGPRRegClassID;
    > -
    > -  // Build the register operands.
    > -
    > -  if (FourReg)
    > -    MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                       decodeRd(insn))));
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                     decodeRs(insn))));
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                     decodeRn(insn))));
    > -
    > -  MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::rGPRRegClassID,
    > -                                                     decodeRm(insn))));
    > -
    > -  if (FourReg)
    > -    NumOpsAdded = 4;
    > -  else
    > -    NumOpsAdded = 3;
    > -
    > -  return true;
    > -}
    > -
    > -// See A6.3 32-bit Thumb instruction encoding for instruction classes
    > -// corresponding to (op1, op2, op).
    > -//
    > -// Table A6-9 32-bit Thumb instruction encoding
    > -// op1  op2    op  Instruction class, see
    > -// ---  -------  --  -----------------------------------------------------------
    > -// 01  00xx0xx  -  Load/store multiple on page A6-23
    > -//     00xx1xx  -  Load/store dual, load/store exclusive, table branch on
    > -//                 page A6-24
    > -//     01xxxxx  -  Data-processing (shifted register) on page A6-31
    > -//     1xxxxxx  -  Coprocessor instructions on page A6-40
    > -// 10  x0xxxxx  0  Data-processing (modified immediate) on page A6-15
    > -//     x1xxxxx  0  Data-processing (plain binary immediate) on page A6-19
    > -//         -    1  Branches and miscellaneous control on page A6-20
    > -// 11  000xxx0  -  Store single data item on page A6-30
    > -//     001xxx0  -  Advanced SIMD element or structure load/store instructions
    > -//                 on page A7-27
    > -//     00xx001  - Load byte, memory hints on page A6-28
    > -//     00xx011  -  Load halfword, memory hints on page A6-26
    > -//     00xx101  -  Load word on page A6-25
    > -//     00xx111  -  UNDEFINED
    > -//     010xxxx  -  Data-processing (register) on page A6-33
    > -//     0110xxx  -  Multiply, multiply accumulate, and absolute difference on
    > -//                 page A6-38
    > -//     0111xxx  -  Long multiply, long multiply accumulate, and divide on
    > -//                 page A6-39
    > -//     1xxxxxx  -  Coprocessor instructions on page A6-40
    > -//
    > -static bool DisassembleThumb2(uint16_t op1, uint16_t op2, uint16_t op,
    > -    MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps,
    > -    unsigned &NumOpsAdded, BO B) {
    > -
    > -  switch (op1) {
    > -  case 1:
    > -    if (slice(op2, 6, 5) == 0) {
    > -      if (slice(op2, 2, 2) == 0) {
    > -        // Load/store multiple.
    > -        return DisassembleThumb2LdStMul(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                        B);
    > -      }
    > -
    > -      // Load/store dual, load/store exclusive, table branch, otherwise.
    > -      assert(slice(op2, 2, 2) == 1 && "Thumb2 encoding error!");
    > -      if ((ARM::t2LDREX <= Opcode && Opcode <= ARM::t2LDREXH) ||
    > -          (ARM::t2STREX <= Opcode && Opcode <= ARM::t2STREXH)) {
    > -        // Load/store exclusive.
    > -        return DisassembleThumb2LdStEx(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                       B);
    > -      }
    > -      if (Opcode == ARM::t2LDRDi8 ||
    > -          Opcode == ARM::t2LDRD_PRE || Opcode == ARM::t2LDRD_POST ||
    > -          Opcode == ARM::t2STRDi8 ||
    > -          Opcode == ARM::t2STRD_PRE || Opcode == ARM::t2STRD_POST) {
    > -        // Load/store dual.
    > -        return DisassembleThumb2LdStDual(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                         B);
    > -      }
    > -      if (Opcode == ARM::t2TBB || Opcode == ARM::t2TBH) {
    > -        // Table branch.
    > -        return DisassembleThumb2TB(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -      }
    > -    } else if (slice(op2, 6, 5) == 1) {
    > -      // Data-processing (shifted register).
    > -      return DisassembleThumb2DPSoReg(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -    }
    > -
    > -    // FIXME: A6.3.18 Coprocessor instructions
    > -    // But see ThumbDisassembler::getInstruction().
    > -
    > -    break;
    > -  case 2:
    > -    if (op == 0) {
    > -      if (slice(op2, 5, 5) == 0)
    > -        // Data-processing (modified immediate)
    > -        return DisassembleThumb2DPModImm(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                         B);
    > -      if (Thumb2SaturateOpcode(Opcode))
    > -        return DisassembleThumb2Sat(MI, Opcode, insn, NumOpsAdded, B);
    > -
    > -      // Data-processing (plain binary immediate)
    > -      return DisassembleThumb2DPBinImm(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                       B);
    > -    }
    > -    // Branches and miscellaneous control on page A6-20.
    > -    return DisassembleThumb2BrMiscCtrl(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                       B);
    > -  case 3:
    > -    switch (slice(op2, 6, 5)) {
    > -    case 0:
    > -      // Load/store instructions...
    > -      if (slice(op2, 0, 0) == 0) {
    > -        if (slice(op2, 4, 4) == 0) {
    > -          // Store single data item on page A6-30
    > -          return DisassembleThumb2LdSt(false, MI,Opcode,insn,NumOps,NumOpsAdded,
    > -                                       B);
    > -        } else {
    > -          // FIXME: Advanced SIMD element or structure load/store instructions.
    > -          // But see ThumbDisassembler::getInstruction().
    > -          ;
    > -        }
    > -      } else {
    > -        // Table A6-9 32-bit Thumb instruction encoding: Load byte|halfword|word
    > -        return DisassembleThumb2LdSt(true, MI, Opcode, insn, NumOps,
    > -                                     NumOpsAdded, B);
    > -      }
    > -      break;
    > -    case 1:
    > -      if (slice(op2, 4, 4) == 0) {
    > -        // A6.3.12 Data-processing (register)
    > -        return DisassembleThumb2DPReg(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -      } else if (slice(op2, 3, 3) == 0) {
    > -        // A6.3.16 Multiply, multiply accumulate, and absolute difference
    > -        return DisassembleThumb2Mul(MI, Opcode, insn, NumOps, NumOpsAdded, B);
    > -      } else {
    > -        // A6.3.17 Long multiply, long multiply accumulate, and divide
    > -        return DisassembleThumb2LongMul(MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                                        B);
    > -      }
    > -      break;
    > -    default:
    > -      // FIXME: A6.3.18 Coprocessor instructions
    > -      // But see ThumbDisassembler::getInstruction().
    > -      ;
    > -      break;
    > -    }
    > -
    > -    break;
    > -  default:
    > -    assert(0 && "Thumb2 encoding error!");
    > -    break;
    > -  }
    > -
    > -  return false;
    > -}
    > -
    > -static bool DisassembleThumbFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
    > -    unsigned short NumOps, unsigned &NumOpsAdded, BO Builder) {
    > -
    > -  uint16_t HalfWord = slice(insn, 31, 16);
    > -
    > -  if (HalfWord == 0) {
    > -    // A6.2 16-bit Thumb instruction encoding
    > -    // op = bits[15:10]
    > -    uint16_t op = slice(insn, 15, 10);
    > -    return DisassembleThumb1(op, MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                             Builder);
    > -  }
    > -
    > -  unsigned bits15_11 = slice(HalfWord, 15, 11);
    > -
    > -  // A6.1 Thumb instruction set encoding
    > -  if (!(bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F)) {
    > -    assert("Bits[15:11] first halfword of Thumb2 instruction is out of range");
    > -    return false;
    > -  }
    > -
    > -  // A6.3 32-bit Thumb instruction encoding
    > -
    > -  uint16_t op1 = slice(HalfWord, 12, 11);
    > -  uint16_t op2 = slice(HalfWord, 10, 4);
    > -  uint16_t op = slice(insn, 15, 15);
    > -
    > -  return DisassembleThumb2(op1, op2, op, MI, Opcode, insn, NumOps, NumOpsAdded,
    > -                           Builder);
    > -}
    > 
    > Modified: llvm/trunk/lib/Target/ARM/Makefile
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/Makefile?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/Makefile (original)
    > +++ llvm/trunk/lib/Target/ARM/Makefile Tue Aug  9 15:55:18 2011
    > @@ -18,7 +18,7 @@
    >                 ARMGenCodeEmitter.inc ARMGenCallingConv.inc \
    >                 ARMGenDecoderTables.inc ARMGenEDInfo.inc \
    >                 ARMGenFastISel.inc ARMGenMCCodeEmitter.inc \
    > -        ARMGenMCPseudoLowering.inc
    > +        ARMGenMCPseudoLowering.inc ARMGenDisassemblerTables.inc
    > 
    > DIRS = InstPrinter AsmParser Disassembler TargetInfo MCTargetDesc
    > 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt Tue Aug  9 15:55:18 2011
    > @@ -60,11 +60,14 @@
    > # CHECK:    ldrh    r0, [r2], #0
    > 0xb0 0x00 0xd2 0xe0
    > 
    > +# CHECK:    ldrh    r0, [r2]
    > +0xb0 0x00 0xd2 0xe1
    > +
    > # CHECK:    ldrht    r0, [r2], #15
    > 0xbf 0x00 0xf2 0xe0
    > 
    > # CHECK:    ldrsbtvs    lr, [r2], -r9
    > -0xd9 0xe9 0x32 0x60
    > +0xd9 0xe0 0x32 0x60
    > 
    > # CHECK:    lsls    r0, r2, #31
    > 0x82 0x0f 0xb0 0xe1
    > @@ -177,7 +180,7 @@
    > 0x15 0xff 0x2f 0x01
    > 
    > # CHECK:    uqadd16mi    r6, r11, r8
    > -0x18 0x60 0x6b 0x46
    > +0x18 0x6F 0x6b 0x46
    > 
    > # CHECK:    str    r0, [sp, #4]
    > 0x04 0x00 0x8d 0xe5
    > @@ -230,7 +233,7 @@
    > # CHECK:    umull    r1, r2, r3, r4
    > 0x93 0x14 0x82 0xe0
    > 
    > -# CHECK:    pld    [pc, #-0]
    > +# CHECK:    pldw    [pc, #-0]
    > 0x00 0xf0 0x1f 0xf5
    > 
    > # CHECK:    pli    [pc, #-0]
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,8 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=60 Name=BFI Format=ARM_FORMAT_DPFRM(4)
    > -#  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 
    > +#  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: 1| 0: 1: 1: 0|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,10 +1,11 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > +#  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
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # invalid imod value (0b01)
    > 0xc0 0x67 0x4 0xf1
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # invalid (imod, M, iflags) combination
    > 0x93 0x1c 0x02 0xf1
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=1908 Name=t2DMB 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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=102 Name=DSB Format=ARM_FORMAT_MISCFRM(26)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,7 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=0 Name=PHI Format=(42)
    > -#  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 
    > +#  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: 0: 1| 1: 1: 0: 0| 0: 0: 0: 1| 1: 1: 1: 1| 1: 0: 1: 1| 0: 1: 0: 0| 1: 0: 0: 1| 0: 0: 1: 0|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,7 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=0 Name=PHI Format=(42)
    > -#  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 
    > +#  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| 0: 0: 1: 1| 0: 1: 1: 1| 0: 1: 0: 1| 0: 0: 0: 1| 0: 0: 0: 1| 0: 0: 0: 0|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_POST-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # LDR_PRE/POST has encoding Inst{4} = 0.
    > 0xde 0x69 0x18 0x46
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LDR_PRE-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-LSL-regform.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,7 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=171 Name=MCR Format=ARM_FORMAT_BRFRM(2)
    > -#  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 
    > +#  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: 1: 0| 1: 1: 1: 0| 1: 0: 1: 0| 0: 0: 0: 0| 0: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 1| 1: 0: 1: 1|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=185 Name=MOVTi16 Format=ARM_FORMAT_DPFRM(4)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,7 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=0 Name=PHI Format=(42)
    > -#  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 
    > +#  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: 0: 0: 1| 1: 0: 1: 1| 1: 1: 0: 0| 1: 1: 0: 1| 0: 0: 0: 0| 0: 0: 0: 0| 0: 0: 1: 0|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,7 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=196 Name=MOVs Format=ARM_FORMAT_DPSOREGFRM(5)
    > -#  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 
    > +#  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: 0: 1| 0: 0: 0: 1| 1: 0: 1: 0| 0: 0: 0: 0| 0: 1: 0: 0| 0: 0: 1: 0| 1: 0: 0: 1| 0: 0: 1: 1|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,7 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=0 Name=PHI Format=(42)
    > -#  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 
    > +#  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: 0: 0: 1| 1: 0: 1: 1| 1: 1: 0: 0| 1: 1: 0: 1| 0: 0: 0: 1| 0: 0: 0: 0| 0: 0: 1: 0|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=206 Name=MSRi Format=ARM_FORMAT_BRFRM(2)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,7 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=134 Name=LDMIA Format=ARM_FORMAT_LDSTMULFRM(10)
    > -# 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 
    > +# 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| 1: 0: 0: 1| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 0: 1| 0: 0: 1: 1| 0: 0: 1: 0|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=261 Name=RSCrs Format=ARM_FORMAT_DPSOREGFRM(5)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=271 Name=SBFX Format=ARM_FORMAT_DPFRM(4)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=284 Name=SMLAD Format=ARM_FORMAT_MULFRM(1)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,7 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=0 Name=PHI Format=(42)
    > -#  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 
    > +#  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| 1: 1: 0: 0| 0: 1: 0: 1| 0: 0: 0: 1| 1: 1: 0: 0| 1: 0: 0: 0| 0: 0: 1: 1|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=322 Name=SSAT Format=ARM_FORMAT_SATFRM(13)
    > #  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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=390 Name=SXTBr_rot Format=ARM_FORMAT_EXTFRM(14)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,11 +1,11 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=419 Name=UMAAL Format=ARM_FORMAT_MULFRM(1)
    > -#  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 
    > +#  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: 0: 0: 0| 0: 1: 0: 0| 1: 1: 1: 1| 1: 0: 1: 1| 1: 1: 1: 1| 1: 0: 0: 1| 1: 0: 0: 0|
    > # -------------------------------------------------------------------------------------------------
    > #
    > # A8.6.244 UMAAL
    > # if dLo == 15 || dHi == 15 || n == 15 || m == 15 then UNPREDICTABLE;
    > -0x98 0xbf 0x4f 0xf0 
    > +0x98 0xbf 0x4f 0xf0
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=426 Name=UQADD8 Format=ARM_FORMAT_DPFRM(4)
    > #  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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,11 +1,11 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > 
    > # Opcode=871 Name=VLD3DUPd32_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 
    > +#  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: 1: 0| 0: 0: 1: 0| 1: 1: 1: 0| 1: 0: 0: 1| 0: 0: 1: 0|
    > # -------------------------------------------------------------------------------------------------
    > -# 
    > +#
    > # A8.6.315 VLD3 (single 3-element structure to all lanes)
    > # The a bit must be encoded as 0.
    > 0xa2 0xf9 0x92 0x2e
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # core registers out of range
    > 0xa5 0xba 0x72 0xed
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=1225 Name=VQADDsv16i8 Format=ARM_FORMAT_N3Reg(37)
    > #  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 
    > 
    > Modified: llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt Tue Aug  9 15:55:18 2011
    > @@ -1,7 +1,8 @@
    > # RUN: llvm-mc --disassemble %s -triple=arm-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # Opcode=1641 Name=VST2b32_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 
    > +#  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| 0: 0: 0: 0| 0: 0: 1: 1| 0: 0: 0: 0| 1: 0: 0: 1| 1: 0: 1: 1| 0: 0: 1: 1|
    > # -------------------------------------------------------------------------------------------------
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,10 +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 
    > +#  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
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > Modified: 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,10 +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 
    > +#  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/invalid-t2STR_POST-thumb.txt
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt Tue Aug  9 15:55:18 2011
    > @@ -1,4 +1,5 @@
    > # RUN: llvm-mc --disassemble %s -triple=thumb-apple-darwin9 |& grep {invalid instruction encoding}
    > +# XFAIL: *
    > 
    > # 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 
    > 
    > 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt (original)
    > +++ llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt Tue Aug  9 15:55:18 2011
    > @@ -24,7 +24,7 @@
    > # CHECK:    vld1.32    {d3[], d4[]}, [r0, :32]!
    > 0xbd 0x3c 0xa0 0xf4
    > 
    > -# CHECK:    vld4.16    {d3[], d4[], d5[], d6[]}, [r0, :64]!
    > +# CHECK:    vld4.16    {d3[], d5[], d7[], d9[]}, [r0, :64]!
    > 0x7d 0x3f 0xa0 0xf4
    > 
    > # CHECK:    vorr    d0, d15, d15
    > @@ -87,5 +87,5 @@
    > # CHECK:    usada8mi    r8, r9, r5, r9
    > 0x19 0x95 0x88 0x47
    > 
    > -# CHECK:    vext.8    q4, q2, q1, #4
    > +# CHECK:    vext.32    q4, q2, q1, #1
    > 0x42 0x84 0xb4 0xf2
    > 
    > Modified: llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp (original)
    > +++ llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp Tue Aug  9 15:55:18 2011
    > @@ -128,12 +128,5 @@
    >     return;
    >   }
    > 
    > -  // Fixed-instruction-length targets use a common disassembler.
    > -  // ARM use its own implementation for now.
    > -  if (Target.getName() == "ARM") {
    > -    ARMDecoderEmitter(Records).run(OS);
    > -    return;
    > -  }  
    > -
    >   FixedLenDecoderEmitter(Records).run(OS);
    > }
    > 
    > 
    > _______________________________________________
    > 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 Aug  9 19:49:13 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Wed, 10 Aug 2011 00:49:13 -0000
    Subject: [llvm-commits] [llvm] r137191 -
    	/llvm/trunk/include/llvm/Analysis/LoopInfo.h
    Message-ID: <20110810004913.21E552A6C12C@llvm.org>
    
    Author: atrick
    Date: Tue Aug  9 19:49:12 2011
    New Revision: 137191
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137191&view=rev
    Log:
    Cleanup. Avoid relying on specialization of std::distance.
    
    Modified:
        llvm/trunk/include/llvm/Analysis/LoopInfo.h
    
    Modified: llvm/trunk/include/llvm/Analysis/LoopInfo.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopInfo.h?rev=137191&r1=137190&r2=137191&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Analysis/LoopInfo.h (original)
    +++ llvm/trunk/include/llvm/Analysis/LoopInfo.h Tue Aug  9 19:49:12 2011
    @@ -134,9 +134,9 @@
       block_iterator block_begin() const { return Blocks.begin(); }
       block_iterator block_end() const { return Blocks.end(); }
     
    -  /// getNumBlocks - Get the number of blocks in this loop.
    +  /// getNumBlocks - Get the number of blocks in this loop in constant time.
       unsigned getNumBlocks() const {
    -    return std::distance(block_begin(), block_end());
    +    return Blocks.size();
       }
     
       /// isLoopExiting - True if terminator in the block can branch to another
    
    
    
    From atrick at apple.com  Tue Aug  9 19:53:46 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Tue, 09 Aug 2011 17:53:46 -0700
    Subject: [llvm-commits] [llvm] r137190 - in /llvm/trunk:
     include/llvm/Analysis/LoopInfo.h lib/Transforms/Utils/LoopUnroll.cpp
     test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
     test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    In-Reply-To: 
    References: <20110810002810.AF3BF2A6C12C@llvm.org>
    	
    Message-ID: <46911817-BCDE-42DB-BB8E-5A5C5505ED9D@apple.com>
    
    
    On Aug 9, 2011, at 5:36 PM, Eli Friedman wrote:
    
    >> +  /// getNumBlocks - Get the number of blocks in this loop.
    >> +  unsigned getNumBlocks() const {
    >> +    return std::distance(block_begin(), block_end());
    >> +  }
    > 
    > I do not think this is a good idea; any user that cares can write the
    > expression with std::distance, and having an accessor gives the
    > illusion that it's constant time.
    
    I wanted a way to stress that Loop needs to provide a constant-time accessor for number of blocks. It's an assumption made by LoopIterator and a few other places (some I have not checked in yet).
    
    Using std::distance was unnecessary, I cleaned it up. I also didn't notice the getBlocks() accessor. Feel free to replace uses of getNumBlocks with it, although I was trying not to expose the Blocks type to the client code.
    
    -Andy
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110809/54221bc7/attachment.html 
    
    From peter at pcc.me.uk  Tue Aug  9 20:10:08 2011
    From: peter at pcc.me.uk (Peter Collingbourne)
    Date: Wed, 10 Aug 2011 01:10:08 -0000
    Subject: [llvm-commits] [llvm] r137192 -
    	/llvm/trunk/include/llvm/Support/IRBuilder.h
    Message-ID: <20110810011008.ABE512A6C12C@llvm.org>
    
    Author: pcc
    Date: Tue Aug  9 20:10:08 2011
    New Revision: 137192
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137192&view=rev
    Log:
    Preserve the name for this variant of IRBuilder::CreateCall
    
    Modified:
        llvm/trunk/include/llvm/Support/IRBuilder.h
    
    Modified: llvm/trunk/include/llvm/Support/IRBuilder.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/IRBuilder.h?rev=137192&r1=137191&r2=137192&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Support/IRBuilder.h (original)
    +++ llvm/trunk/include/llvm/Support/IRBuilder.h Tue Aug  9 20:10:08 2011
    @@ -1145,7 +1145,7 @@
     
       CallInst *CreateCall(Value *Callee, ArrayRef Args,
                            const Twine &Name = "") {
    -    return Insert(CallInst::Create(Callee, Args, Name));
    +    return Insert(CallInst::Create(Callee, Args), Name);
       }
     
       Value *CreateSelect(Value *C, Value *True, Value *False,
    
    
    
    From peter at pcc.me.uk  Tue Aug  9 20:10:17 2011
    From: peter at pcc.me.uk (Peter Collingbourne)
    Date: Wed, 10 Aug 2011 01:10:17 -0000
    Subject: [llvm-commits] [llvm] r137193 - in /llvm/trunk:
     bindings/ocaml/llvm/llvm.ml bindings/ocaml/llvm/llvm.mli
     bindings/ocaml/llvm/llvm_ocaml.c test/Bindings/Ocaml/vmcore.ml
    Message-ID: <20110810011017.CB5102A6C12C@llvm.org>
    
    Author: pcc
    Date: Tue Aug  9 20:10:17 2011
    New Revision: 137193
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137193&view=rev
    Log:
    Remove the build_unwind function from the OCaml bindings.
    
    Modified:
        llvm/trunk/bindings/ocaml/llvm/llvm.ml
        llvm/trunk/bindings/ocaml/llvm/llvm.mli
        llvm/trunk/bindings/ocaml/llvm/llvm_ocaml.c
        llvm/trunk/test/Bindings/Ocaml/vmcore.ml
    
    Modified: llvm/trunk/bindings/ocaml/llvm/llvm.ml
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/bindings/ocaml/llvm/llvm.ml?rev=137193&r1=137192&r2=137193&view=diff
    ==============================================================================
    --- llvm/trunk/bindings/ocaml/llvm/llvm.ml (original)
    +++ llvm/trunk/bindings/ocaml/llvm/llvm.ml Tue Aug  9 20:10:17 2011
    @@ -820,7 +820,6 @@
     external build_invoke : llvalue -> llvalue array -> llbasicblock ->
                             llbasicblock -> string -> llbuilder -> llvalue
                           = "llvm_build_invoke_bc" "llvm_build_invoke_nat"
    -external build_unwind : llbuilder -> llvalue = "llvm_build_unwind"
     external build_unreachable : llbuilder -> llvalue = "llvm_build_unreachable"
     
     (*--... Arithmetic .........................................................--*)
    
    Modified: llvm/trunk/bindings/ocaml/llvm/llvm.mli
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/bindings/ocaml/llvm/llvm.mli?rev=137193&r1=137192&r2=137193&view=diff
    ==============================================================================
    --- llvm/trunk/bindings/ocaml/llvm/llvm.mli (original)
    +++ llvm/trunk/bindings/ocaml/llvm/llvm.mli Tue Aug  9 20:10:17 2011
    @@ -1616,12 +1616,6 @@
                             llbasicblock -> string -> llbuilder -> llvalue
     
     
    -(** [build_unwind b] creates an
    -    [unwind]
    -    instruction at the position specified by the instruction builder [b].
    -    See the method [llvm::LLVMBuilder::CreateUnwind]. *)
    -val build_unwind : llbuilder -> llvalue
    -
     (** [build_unreachable b] creates an
         [unreachable]
         instruction at the position specified by the instruction builder [b].
    
    Modified: llvm/trunk/bindings/ocaml/llvm/llvm_ocaml.c
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/bindings/ocaml/llvm/llvm_ocaml.c?rev=137193&r1=137192&r2=137193&view=diff
    ==============================================================================
    --- llvm/trunk/bindings/ocaml/llvm/llvm_ocaml.c (original)
    +++ llvm/trunk/bindings/ocaml/llvm/llvm_ocaml.c Tue Aug  9 20:10:17 2011
    @@ -1213,11 +1213,6 @@
     }
     
     /* llbuilder -> llvalue */
    -CAMLprim LLVMValueRef llvm_build_unwind(value B) {
    -  return LLVMBuildUnwind(Builder_val(B));
    -}
    -
    -/* llbuilder -> llvalue */
     CAMLprim LLVMValueRef llvm_build_unreachable(value B) {
       return LLVMBuildUnreachable(Builder_val(B));
     }
    
    Modified: llvm/trunk/test/Bindings/Ocaml/vmcore.ml
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bindings/Ocaml/vmcore.ml?rev=137193&r1=137192&r2=137193&view=diff
    ==============================================================================
    --- llvm/trunk/test/Bindings/Ocaml/vmcore.ml (original)
    +++ llvm/trunk/test/Bindings/Ocaml/vmcore.ml Tue Aug  9 20:10:17 2011
    @@ -898,14 +898,6 @@
         ignore (build_invoke fn [| p1; p2 |] bb04 bb00 "build_invoke" b)
       end;
       
    -  group "unwind"; begin
    -    (* RUN: grep {unwind} < %t.ll
    -     *)
    -    let bb05 = append_block context "Bb05" fn in
    -    let b = builder_at_end context bb05 in
    -    ignore (build_unwind b)
    -  end;
    -  
       group "unreachable"; begin
         (* RUN: grep {unreachable} < %t.ll
          *)
    
    
    
    From atrick at apple.com  Tue Aug  9 20:25:47 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Tue, 09 Aug 2011 18:25:47 -0700
    Subject: [llvm-commits] [llvm] r137190 - in /llvm/trunk:
     include/llvm/Analysis/LoopInfo.h lib/Transforms/Utils/LoopUnroll.cpp
     test/Transforms/LoopUnroll/2011-08-08-PhiUpdate.ll
     test/Transforms/LoopUnroll/2011-08-09-PhiUpdate.ll
    In-Reply-To: 
    References: <20110810002810.AF3BF2A6C12C@llvm.org>
    	
    Message-ID: <432ABC46-243F-4580-BED0-B4BDF24CC12E@apple.com>
    
    On Aug 9, 2011, at 5:43 PM, Eli Friedman wrote:
    
    > On Tue, Aug 9, 2011 at 5:28 PM, Andrew Trick  wrote:
    >> Author: atrick
    >> Date: Tue Aug  9 19:28:10 2011
    >> New Revision: 137190
    >> 
    >> URL: http://llvm.org/viewvc/llvm-project?rev=137190&view=rev
    >> Log:
    >> Fix the LoopUnroller to handle nontrivial loops and partial unrolling.
    >> 
    >> These are not individual bug fixes. I had to rewrite a good chunk of
    >> the unroller to make it sane. I think it was getting lucky on trivial
    >> completely unrolled loops with no early exits. I included some fairly
    >> simple unit tests for partial unrolling. I didn't do much stress
    >> testing, so it may not be perfect, but should be usable now.
    > 
    > Does this address http://llvm.org/bugs/show_bug.cgi?id=2253 and/or
    > http://llvm.org/bugs/show_bug.cgi?id=7318 ?
    > 
    > -Eli
    
    Yes and Yes. Closing them soon. Just making sure I don't have to revert.
    
    -Andy
    
    From peter at pcc.me.uk  Tue Aug  9 20:30:33 2011
    From: peter at pcc.me.uk (Peter Collingbourne)
    Date: Wed, 10 Aug 2011 02:30:33 +0100
    Subject: [llvm-commits] [PATCH] [dragonegg] Support default definition
     of RESULT_DECL
    In-Reply-To: <4E3BF561.1010507@free.fr>
    References: <20110805134138.GA15794@pcc.me.uk>
     <4E3BF561.1010507@free.fr>
    Message-ID: <20110810013032.GA13197@pcc.me.uk>
    
    On Fri, Aug 05, 2011 at 03:51:29PM +0200, Duncan Sands wrote:
    > Hi Peter, thanks for working on dragonegg.
    > 
    > > OK to commit?
    > 
    > I see where you are coming from but I'd like to see a testcase before
    > going the go ahead.
    
    I came up with a test case, see attached.  Note that I can only get it
    to fail without my patch applied using gcc 4.6 (i.e. gcc-4_6-branch).
    I guess we can put this in test/FrontendC++, but it looks like the
    test/Frontend* tests are slowly being moved to clang or deleted.
    I suppose dragonegg should get its own test suite at some point?
    
    Thanks,
    -- 
    Peter
    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: nrvo.cpp
    Type: text/x-c++src
    Size: 346 bytes
    Desc: not available
    Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/87f59280/attachment.bin 
    
    From peter at pcc.me.uk  Tue Aug  9 20:35:27 2011
    From: peter at pcc.me.uk (Peter Collingbourne)
    Date: Wed, 10 Aug 2011 02:35:27 +0100
    Subject: [llvm-commits] [PATCH] [dragonegg] Basic support for assembling
    	constants
    Message-ID: <20110810013526.GB13197@pcc.me.uk>
    
    OK to commit?
    -- 
    Peter
    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: 0001-If-the-frontend-assembles-a-constant-directly-using-.patch
    Type: text/x-diff
    Size: 3203 bytes
    Desc: not available
    Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/cd7a346e/attachment.bin 
    
    From bruno.cardoso at gmail.com  Tue Aug  9 20:54:17 2011
    From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes)
    Date: Wed, 10 Aug 2011 01:54:17 -0000
    Subject: [llvm-commits] [llvm] r137194 - in /llvm/trunk:
     lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/avx-vpermil.ll
    Message-ID: <20110810015418.18FC02A6C12C@llvm.org>
    
    Author: bruno
    Date: Tue Aug  9 20:54:17 2011
    New Revision: 137194
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137194&view=rev
    Log:
    Fix a bug in vpermilps mask checking. Fix PR10560
    
    Modified:
        llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
        llvm/trunk/test/CodeGen/X86/avx-vpermil.ll
    
    Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137194&r1=137193&r2=137194&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
    +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Aug  9 20:54:17 2011
    @@ -3509,9 +3509,12 @@
       int LaneSize = NumElts/NumLanes;
       for (int i = 0; i < LaneSize; ++i) {
         int HighElt = i+LaneSize;
    -    if (Mask[i] < 0 && (isUndefOrInRange(Mask[HighElt], LaneSize, NumElts)))
    -      continue;
    -    if (Mask[HighElt] < 0 && (isUndefOrInRange(Mask[i], 0, LaneSize)))
    +    bool HighValid = isUndefOrInRange(Mask[HighElt], LaneSize, NumElts);
    +    bool LowValid = isUndefOrInRange(Mask[i], 0, LaneSize);
    +
    +    if (!HighValid || !LowValid)
    +      return false;
    +    if (Mask[i] < 0 || Mask[HighElt] < 0)
           continue;
         if (Mask[HighElt]-Mask[i] != LaneSize)
           return false;
    
    Modified: llvm/trunk/test/CodeGen/X86/avx-vpermil.ll
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/avx-vpermil.ll?rev=137194&r1=137193&r2=137194&view=diff
    ==============================================================================
    --- llvm/trunk/test/CodeGen/X86/avx-vpermil.ll (original)
    +++ llvm/trunk/test/CodeGen/X86/avx-vpermil.ll Tue Aug  9 20:54:17 2011
    @@ -37,3 +37,9 @@
       ret <8 x float> %shuffle
     }
     
    +; CHECK-NOT: vpermilps
    +define <8 x float> @funcF(<8 x float> %a) nounwind uwtable readnone ssp {
    +entry:
    +  %shuffle = shufflevector <8 x float> %a, <8 x float> zeroinitializer, <8 x i32> 
    +  ret <8 x float> %shuffle
    +}
    
    
    
    From atrick at apple.com  Tue Aug  9 20:59:05 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Wed, 10 Aug 2011 01:59:05 -0000
    Subject: [llvm-commits] [llvm] r137195 - in /llvm/trunk:
     include/llvm/Analysis/LoopIterator.h lib/Analysis/LoopInfo.cpp
     lib/Transforms/Utils/LoopUnroll.cpp
    Message-ID: <20110810015905.F336B2A6C12C@llvm.org>
    
    Author: atrick
    Date: Tue Aug  9 20:59:05 2011
    New Revision: 137195
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137195&view=rev
    Log:
    Cleanup. Added LoopBlocksDFS::perform for simple clients.
    
    Modified:
        llvm/trunk/include/llvm/Analysis/LoopIterator.h
        llvm/trunk/lib/Analysis/LoopInfo.cpp
        llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    
    Modified: llvm/trunk/include/llvm/Analysis/LoopIterator.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LoopIterator.h?rev=137195&r1=137194&r2=137195&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Analysis/LoopIterator.h (original)
    +++ llvm/trunk/include/llvm/Analysis/LoopIterator.h Tue Aug  9 20:59:05 2011
    @@ -61,6 +61,9 @@
     
       Loop *getLoop() const { return L; }
     
    +  /// Traverse the loop blocks and store the DFS result.
    +  void perform(LoopInfo *LI);
    +
       /// Return true if postorder numbers are assigned to all loop blocks.
       bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); }
     
    
    Modified: llvm/trunk/lib/Analysis/LoopInfo.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LoopInfo.cpp?rev=137195&r1=137194&r2=137195&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Analysis/LoopInfo.cpp (original)
    +++ llvm/trunk/lib/Analysis/LoopInfo.cpp Tue Aug  9 20:59:05 2011
    @@ -18,6 +18,7 @@
     #include "llvm/Constants.h"
     #include "llvm/Instructions.h"
     #include "llvm/Analysis/Dominators.h"
    +#include "llvm/Analysis/LoopIterator.h"
     #include "llvm/Assembly/Writer.h"
     #include "llvm/Support/CFG.h"
     #include "llvm/Support/CommandLine.h"
    @@ -417,3 +418,15 @@
       LI.print(OS);
     }
     
    +//===----------------------------------------------------------------------===//
    +// LoopBlocksDFS implementation
    +//
    +
    +/// Traverse the loop blocks and store the DFS result.
    +/// Useful for clients that just want the final DFS result and don't need to
    +/// visit blocks during the initial traversal.
    +void LoopBlocksDFS::perform(LoopInfo *LI) {
    +  LoopBlocksTraversal Traversal(*this, LI);
    +  for (LoopBlocksTraversal::POTIterator POI = Traversal.begin(),
    +         POE = Traversal.end(); POI != POE; ++POI) ;
    +}
    
    Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=137195&r1=137194&r2=137195&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
    +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Tue Aug  9 20:59:05 2011
    @@ -230,13 +230,8 @@
       // reverse postorder so that LastValueMap contains the correct value at each
       // exit.
       LoopBlocksDFS DFS(L);
    -  {
    -    // Traverse the loop blocks using depth-first search to record RPO numbers
    -    // for each block in the DFS result.
    -    LoopBlocksTraversal Traversal(DFS, LI);
    -    for (LoopBlocksTraversal::POTIterator POI = Traversal.begin(),
    -           POE = Traversal.end(); POI != POE; ++POI);
    -  }
    +  DFS.perform(LI);
    +
       // Stash the DFS iterators before adding blocks to the loop.
       LoopBlocksDFS::RPOIterator BlockBegin = DFS.beginRPO();
       LoopBlocksDFS::RPOIterator BlockEnd = DFS.endRPO();
    
    
    
    From atrick at apple.com  Tue Aug  9 22:46:27 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Wed, 10 Aug 2011 03:46:27 -0000
    Subject: [llvm-commits] [llvm] r137197 - in /llvm/trunk:
     include/llvm/Analysis/IVUsers.h
     include/llvm/Transforms/Utils/SimplifyIndVar.h
     lib/Transforms/Scalar/IndVarSimplify.cpp
     lib/Transforms/Utils/SimplifyIndVar.cpp
    Message-ID: <20110810034627.AE1072A6C12D@llvm.org>
    
    Author: atrick
    Date: Tue Aug  9 22:46:27 2011
    New Revision: 137197
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137197&view=rev
    Log:
    Added a SimplifyIndVar utility to simplify induction variable users
    based on ScalarEvolution without changing the induction variable phis.
    
    This utility is the main tool of IndVarSimplifyPass, but the pass also
    restructures induction variables in strange ways that are sensitive to
    pass ordering. This provides a way for other loop passes to simplify
    new uses of induction variables created during transformation. The
    utility may be used by any pass that preserves ScalarEvolution. Soon
    LoopUnroll will use it.
    
    The net effect in this checkin is to cleanup the IndVarSimplify pass
    by factoring out the SimplifyIndVar algorithm into a standalone utility.
    
    Added:
        llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h
        llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    Modified:
        llvm/trunk/include/llvm/Analysis/IVUsers.h
        llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    
    Modified: llvm/trunk/include/llvm/Analysis/IVUsers.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/IVUsers.h?rev=137197&r1=137196&r2=137197&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Analysis/IVUsers.h (original)
    +++ llvm/trunk/include/llvm/Analysis/IVUsers.h Tue Aug  9 22:46:27 2011
    @@ -140,6 +140,8 @@
       static char ID; // Pass ID, replacement for typeid
       IVUsers();
     
    +  Loop *getLoop() const { return L; }
    +
       /// AddUsersIfInteresting - Inspect the specified Instruction.  If it is a
       /// reducible SCEV, recursively add its users to the IVUsesByStride set and
       /// return true.  Otherwise, return false.
    
    Added: llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h?rev=137197&view=auto
    ==============================================================================
    --- llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h (added)
    +++ llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h Tue Aug  9 22:46:27 2011
    @@ -0,0 +1,58 @@
    +//===-- llvm/Transforms/Utils/SimplifyIndVar.h - Indvar Utils ---*- C++ -*-===//
    +//
    +//                     The LLVM Compiler Infrastructure
    +//
    +// This file is distributed under the University of Illinois Open Source
    +// License. See LICENSE.TXT for details.
    +//
    +//===----------------------------------------------------------------------===//
    +//
    +// This file defines in interface for induction variable simplification. It does
    +// not define any actual pass or policy, but provides a single function to
    +// simplify a loop's induction variables based on ScalarEvolution.
    +//
    +//===----------------------------------------------------------------------===//
    +
    +#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H
    +#define LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H
    +
    +#include "llvm/Support/CommandLine.h"
    +
    +namespace llvm {
    +
    +extern cl::opt DisableIVRewrite;
    +
    +class Loop;
    +class LoopInfo;
    +class DominatorTree;
    +class ScalarEvolution;
    +class LPPassManager;
    +class IVUsers;
    +
    +/// Interface for visiting interesting IV users that are recognized but not
    +/// simplified by this utility.
    +class IVVisitor {
    +public:
    +  virtual ~IVVisitor() {}
    +  virtual void visitCast(CastInst *Cast) = 0;
    +};
    +
    +/// simplifyUsersOfIV - Simplify instructions that use this induction variable
    +/// by using ScalarEvolution to analyze the IV's recurrence.
    +bool simplifyUsersOfIV(PHINode *CurrIV, LPPassManager *LPM,
    +                       SmallVectorImpl &Dead, IVVisitor *V = NULL);
    +
    +/// SimplifyLoopIVs - Simplify users of induction variables within this
    +/// loop. This does not actually change or add IVs.
    +bool simplifyLoopIVs(Loop *L, LPPassManager *LPM,
    +                     SmallVectorImpl &Dead);
    +
    +/// simplifyIVUsers - Simplify instructions recorded by the IVUsers pass.
    +/// This is a legacy implementation to reproduce the behavior of the
    +/// IndVarSimplify pass prior to DisableIVRewrite.
    +bool simplifyIVUsers(IVUsers *IU, LPPassManager *LPM,
    +                     SmallVectorImpl &Dead);
    +
    +} // namespace llvm
    +
    +#endif
    
    Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=137197&r1=137196&r2=137197&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
    +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Tue Aug  9 22:46:27 2011
    @@ -11,8 +11,8 @@
     // computations derived from them) into simpler forms suitable for subsequent
     // analysis and transformation.
     //
    -// This transformation makes the following changes to each loop with an
    -// identifiable induction variable:
    +// Additionally, unless -disable-iv-rewrite is on, this transformation makes the
    +// following changes to each loop with an identifiable induction variable:
     //   1. All loops are transformed to have a SINGLE canonical induction variable
     //      which starts at zero and steps by one.
     //   2. The canonical induction variable is guaranteed to be the first PHI node
    @@ -57,11 +57,11 @@
     #include "llvm/Support/raw_ostream.h"
     #include "llvm/Transforms/Utils/Local.h"
     #include "llvm/Transforms/Utils/BasicBlockUtils.h"
    +#include "llvm/Transforms/Utils/SimplifyIndVar.h"
     #include "llvm/Target/TargetData.h"
     #include "llvm/ADT/DenseMap.h"
     #include "llvm/ADT/SmallVector.h"
     #include "llvm/ADT/Statistic.h"
    -#include "llvm/ADT/STLExtras.h"
     using namespace llvm;
     
     STATISTIC(NumRemoved     , "Number of aux indvars removed");
    @@ -69,16 +69,14 @@
     STATISTIC(NumInserted    , "Number of canonical indvars added");
     STATISTIC(NumReplaced    , "Number of exit values replaced");
     STATISTIC(NumLFTR        , "Number of loop exit tests replaced");
    -STATISTIC(NumElimIdentity, "Number of IV identities eliminated");
    -STATISTIC(NumElimOperand,  "Number of IV operands folded into a use");
     STATISTIC(NumElimExt     , "Number of IV sign/zero extends eliminated");
    -STATISTIC(NumElimRem     , "Number of IV remainder operations eliminated");
    -STATISTIC(NumElimCmp     , "Number of IV comparisons eliminated");
     STATISTIC(NumElimIV      , "Number of congruent IVs eliminated");
     
    -static cl::opt DisableIVRewrite(
    -  "disable-iv-rewrite", cl::Hidden,
    -  cl::desc("Disable canonical induction variable rewriting"));
    +namespace llvm {
    +  cl::opt DisableIVRewrite(
    +    "disable-iv-rewrite", cl::Hidden,
    +    cl::desc("Disable canonical induction variable rewriting"));
    +}
     
     // Temporary flag for use with -disable-iv-rewrite to force a canonical IV for
     // LFTR purposes.
    @@ -132,21 +130,12 @@
         void HandleFloatingPointIV(Loop *L, PHINode *PH);
         void RewriteNonIntegerIVs(Loop *L);
     
    -    void RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter);
    -
    -    void SimplifyIVUsers(SCEVExpander &Rewriter);
    -    void SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter);
    -
    -    bool EliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
    -    void EliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
    -    void EliminateIVRemainder(BinaryOperator *Rem,
    -                              Value *IVOperand,
    -                              bool IsSigned);
    -
    -    bool FoldIVUser(Instruction *UseInst, Instruction *IVOperand);
    +    void SimplifyAndExtend(Loop *L, SCEVExpander &Rewriter, LPPassManager &LPM);
     
         void SimplifyCongruentIVs(Loop *L);
     
    +    void RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter);
    +
         void RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter);
     
         Value *LinearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount,
    @@ -475,6 +464,8 @@
       // Add a new IVUsers entry for the newly-created integer PHI.
       if (IU)
         IU->AddUsersIfInteresting(NewPHI);
    +
    +  Changed = true;
     }
     
     void IndVarSimplify::RewriteNonIntegerIVs(Loop *L) {
    @@ -623,36 +614,6 @@
     //  To be replaced by -disable-iv-rewrite.
     //===----------------------------------------------------------------------===//
     
    -/// SimplifyIVUsers - Iteratively perform simplification on IVUsers within this
    -/// loop. IVUsers is treated as a worklist. Each successive simplification may
    -/// push more users which may themselves be candidates for simplification.
    -///
    -/// This is the old approach to IV simplification to be replaced by
    -/// SimplifyIVUsersNoRewrite.
    -///
    -void IndVarSimplify::SimplifyIVUsers(SCEVExpander &Rewriter) {
    -  // Each round of simplification involves a round of eliminating operations
    -  // followed by a round of widening IVs. A single IVUsers worklist is used
    -  // across all rounds. The inner loop advances the user. If widening exposes
    -  // more uses, then another pass through the outer loop is triggered.
    -  for (IVUsers::iterator I = IU->begin(); I != IU->end(); ++I) {
    -    Instruction *UseInst = I->getUser();
    -    Value *IVOperand = I->getOperandValToReplace();
    -
    -    if (ICmpInst *ICmp = dyn_cast(UseInst)) {
    -      EliminateIVComparison(ICmp, IVOperand);
    -      continue;
    -    }
    -    if (BinaryOperator *Rem = dyn_cast(UseInst)) {
    -      bool IsSigned = Rem->getOpcode() == Instruction::SRem;
    -      if (IsSigned || Rem->getOpcode() == Instruction::URem) {
    -        EliminateIVRemainder(Rem, IVOperand, IsSigned);
    -        continue;
    -      }
    -    }
    -  }
    -}
    -
     // FIXME: It is an extremely bad idea to indvar substitute anything more
     // complex than affine induction variables.  Doing so will put expensive
     // polynomial evaluations inside of the loop, and the str reduction pass
    @@ -775,17 +736,34 @@
       // provides the input to WidenIV.
       struct WideIVInfo {
         Type *WidestNativeType; // Widest integer type created [sz]ext
    -    bool IsSigned;                // Was an sext user seen before a zext?
    +    bool IsSigned;          // Was an sext user seen before a zext?
     
         WideIVInfo() : WidestNativeType(0), IsSigned(false) {}
       };
    +
    +  class WideIVVisitor : public IVVisitor {
    +    ScalarEvolution *SE;
    +    const TargetData *TD;
    +
    +  public:
    +    WideIVInfo WI;
    +
    +    WideIVVisitor(ScalarEvolution *SCEV, const TargetData *TData) :
    +      SE(SCEV), TD(TData) {}
    +
    +    // Implement the interface used by simplifyUsersOfIV.
    +    virtual void visitCast(CastInst *Cast);
    +  };
     }
     
    -/// CollectExtend - Update information about the induction variable that is
    +/// visitCast - Update information about the induction variable that is
     /// extended by this sign or zero extend operation. This is used to determine
     /// the final width of the IV before actually widening it.
    -static void CollectExtend(CastInst *Cast, bool IsSigned, WideIVInfo &WI,
    -                          ScalarEvolution *SE, const TargetData *TD) {
    +void WideIVVisitor::visitCast(CastInst *Cast) {
    +  bool IsSigned = Cast->getOpcode() == Instruction::SExt;
    +  if (!IsSigned && Cast->getOpcode() != Instruction::ZExt)
    +    return;
    +
       Type *Ty = Cast->getType();
       uint64_t Width = SE->getTypeSizeInBits(Ty);
       if (TD && !TD->isLegalInteger(Width))
    @@ -1181,242 +1159,16 @@
     //  Simplification of IV users based on SCEV evaluation.
     //===----------------------------------------------------------------------===//
     
    -void IndVarSimplify::EliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
    -  unsigned IVOperIdx = 0;
    -  ICmpInst::Predicate Pred = ICmp->getPredicate();
    -  if (IVOperand != ICmp->getOperand(0)) {
    -    // Swapped
    -    assert(IVOperand == ICmp->getOperand(1) && "Can't find IVOperand");
    -    IVOperIdx = 1;
    -    Pred = ICmpInst::getSwappedPredicate(Pred);
    -  }
    -
    -  // Get the SCEVs for the ICmp operands.
    -  const SCEV *S = SE->getSCEV(ICmp->getOperand(IVOperIdx));
    -  const SCEV *X = SE->getSCEV(ICmp->getOperand(1 - IVOperIdx));
    -
    -  // Simplify unnecessary loops away.
    -  const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
    -  S = SE->getSCEVAtScope(S, ICmpLoop);
    -  X = SE->getSCEVAtScope(X, ICmpLoop);
    -
    -  // If the condition is always true or always false, replace it with
    -  // a constant value.
    -  if (SE->isKnownPredicate(Pred, S, X))
    -    ICmp->replaceAllUsesWith(ConstantInt::getTrue(ICmp->getContext()));
    -  else if (SE->isKnownPredicate(ICmpInst::getInversePredicate(Pred), S, X))
    -    ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
    -  else
    -    return;
    -
    -  DEBUG(dbgs() << "INDVARS: Eliminated comparison: " << *ICmp << '\n');
    -  ++NumElimCmp;
    -  Changed = true;
    -  DeadInsts.push_back(ICmp);
    -}
    -
    -void IndVarSimplify::EliminateIVRemainder(BinaryOperator *Rem,
    -                                          Value *IVOperand,
    -                                          bool IsSigned) {
    -  // We're only interested in the case where we know something about
    -  // the numerator.
    -  if (IVOperand != Rem->getOperand(0))
    -    return;
    -
    -  // Get the SCEVs for the ICmp operands.
    -  const SCEV *S = SE->getSCEV(Rem->getOperand(0));
    -  const SCEV *X = SE->getSCEV(Rem->getOperand(1));
    -
    -  // Simplify unnecessary loops away.
    -  const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
    -  S = SE->getSCEVAtScope(S, ICmpLoop);
    -  X = SE->getSCEVAtScope(X, ICmpLoop);
    -
    -  // i % n  -->  i  if i is in [0,n).
    -  if ((!IsSigned || SE->isKnownNonNegative(S)) &&
    -      SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
    -                           S, X))
    -    Rem->replaceAllUsesWith(Rem->getOperand(0));
    -  else {
    -    // (i+1) % n  -->  (i+1)==n?0:(i+1)  if i is in [0,n).
    -    const SCEV *LessOne =
    -      SE->getMinusSCEV(S, SE->getConstant(S->getType(), 1));
    -    if (IsSigned && !SE->isKnownNonNegative(LessOne))
    -      return;
    -
    -    if (!SE->isKnownPredicate(IsSigned ?
    -                              ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
    -                              LessOne, X))
    -      return;
    -
    -    ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
    -                                  Rem->getOperand(0), Rem->getOperand(1),
    -                                  "tmp");
    -    SelectInst *Sel =
    -      SelectInst::Create(ICmp,
    -                         ConstantInt::get(Rem->getType(), 0),
    -                         Rem->getOperand(0), "tmp", Rem);
    -    Rem->replaceAllUsesWith(Sel);
    -  }
    -
    -  // Inform IVUsers about the new users.
    -  if (IU) {
    -    if (Instruction *I = dyn_cast(Rem->getOperand(0)))
    -      IU->AddUsersIfInteresting(I);
    -  }
    -  DEBUG(dbgs() << "INDVARS: Simplified rem: " << *Rem << '\n');
    -  ++NumElimRem;
    -  Changed = true;
    -  DeadInsts.push_back(Rem);
    -}
    -
    -/// EliminateIVUser - Eliminate an operation that consumes a simple IV and has
    -/// no observable side-effect given the range of IV values.
    -bool IndVarSimplify::EliminateIVUser(Instruction *UseInst,
    -                                     Instruction *IVOperand) {
    -  if (ICmpInst *ICmp = dyn_cast(UseInst)) {
    -    EliminateIVComparison(ICmp, IVOperand);
    -    return true;
    -  }
    -  if (BinaryOperator *Rem = dyn_cast(UseInst)) {
    -    bool IsSigned = Rem->getOpcode() == Instruction::SRem;
    -    if (IsSigned || Rem->getOpcode() == Instruction::URem) {
    -      EliminateIVRemainder(Rem, IVOperand, IsSigned);
    -      return true;
    -    }
    -  }
    -
    -  // Eliminate any operation that SCEV can prove is an identity function.
    -  if (!SE->isSCEVable(UseInst->getType()) ||
    -      (UseInst->getType() != IVOperand->getType()) ||
    -      (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
    -    return false;
    -
    -  DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n');
    -
    -  UseInst->replaceAllUsesWith(IVOperand);
    -  ++NumElimIdentity;
    -  Changed = true;
    -  DeadInsts.push_back(UseInst);
    -  return true;
    -}
    -
    -/// FoldIVUser - Fold an IV operand into its use.  This removes increments of an
    -/// aligned IV when used by a instruction that ignores the low bits.
    -bool IndVarSimplify::FoldIVUser(Instruction *UseInst, Instruction *IVOperand) {
    -  Value *IVSrc = 0;
    -  unsigned OperIdx = 0;
    -  const SCEV *FoldedExpr = 0;
    -  switch (UseInst->getOpcode()) {
    -  default:
    -    return false;
    -  case Instruction::UDiv:
    -  case Instruction::LShr:
    -    // We're only interested in the case where we know something about
    -    // the numerator and have a constant denominator.
    -    if (IVOperand != UseInst->getOperand(OperIdx) ||
    -        !isa(UseInst->getOperand(1)))
    -      return false;
    -
    -    // Attempt to fold a binary operator with constant operand.
    -    // e.g. ((I + 1) >> 2) => I >> 2
    -    if (IVOperand->getNumOperands() != 2 ||
    -        !isa(IVOperand->getOperand(1)))
    -      return false;
    -
    -    IVSrc = IVOperand->getOperand(0);
    -    // IVSrc must be the (SCEVable) IV, since the other operand is const.
    -    assert(SE->isSCEVable(IVSrc->getType()) && "Expect SCEVable IV operand");
    -
    -    ConstantInt *D = cast(UseInst->getOperand(1));
    -    if (UseInst->getOpcode() == Instruction::LShr) {
    -      // Get a constant for the divisor. See createSCEV.
    -      uint32_t BitWidth = cast(UseInst->getType())->getBitWidth();
    -      if (D->getValue().uge(BitWidth))
    -        return false;
    -
    -      D = ConstantInt::get(UseInst->getContext(),
    -                           APInt(BitWidth, 1).shl(D->getZExtValue()));
    -    }
    -    FoldedExpr = SE->getUDivExpr(SE->getSCEV(IVSrc), SE->getSCEV(D));
    -  }
    -  // We have something that might fold it's operand. Compare SCEVs.
    -  if (!SE->isSCEVable(UseInst->getType()))
    -    return false;
    -
    -  // Bypass the operand if SCEV can prove it has no effect.
    -  if (SE->getSCEV(UseInst) != FoldedExpr)
    -    return false;
    -
    -  DEBUG(dbgs() << "INDVARS: Eliminated IV operand: " << *IVOperand
    -        << " -> " << *UseInst << '\n');
    -
    -  UseInst->setOperand(OperIdx, IVSrc);
    -  assert(SE->getSCEV(UseInst) == FoldedExpr && "bad SCEV with folded oper");
    -
    -  ++NumElimOperand;
    -  Changed = true;
    -  if (IVOperand->use_empty())
    -    DeadInsts.push_back(IVOperand);
    -  return true;
    -}
    -
    -/// pushIVUsers - Add all uses of Def to the current IV's worklist.
    -///
    -static void pushIVUsers(
    -  Instruction *Def,
    -  SmallPtrSet &Simplified,
    -  SmallVectorImpl< std::pair > &SimpleIVUsers) {
    -
    -  for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end();
    -       UI != E; ++UI) {
    -    Instruction *User = cast(*UI);
    -
    -    // Avoid infinite or exponential worklist processing.
    -    // Also ensure unique worklist users.
    -    // If Def is a LoopPhi, it may not be in the Simplified set, so check for
    -    // self edges first.
    -    if (User != Def && Simplified.insert(User))
    -      SimpleIVUsers.push_back(std::make_pair(User, Def));
    -  }
    -}
    -
    -/// isSimpleIVUser - Return true if this instruction generates a simple SCEV
    -/// expression in terms of that IV.
    -///
    -/// This is similar to IVUsers' isInsteresting() but processes each instruction
    -/// non-recursively when the operand is already known to be a simpleIVUser.
    -///
    -static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) {
    -  if (!SE->isSCEVable(I->getType()))
    -    return false;
    -
    -  // Get the symbolic expression for this instruction.
    -  const SCEV *S = SE->getSCEV(I);
    -
    -  // Only consider affine recurrences.
    -  const SCEVAddRecExpr *AR = dyn_cast(S);
    -  if (AR && AR->getLoop() == L)
    -    return true;
    -
    -  return false;
    -}
     
    -/// SimplifyIVUsersNoRewrite - Iteratively perform simplification on a worklist
    -/// of IV users. Each successive simplification may push more users which may
    +/// SimplifyAndExtend - Iteratively perform simplification on a worklist of IV
    +/// users. Each successive simplification may push more users which may
     /// themselves be candidates for simplification.
     ///
    -/// The "NoRewrite" algorithm does not require IVUsers analysis. Instead, it
    -/// simplifies instructions in-place during analysis. Rather than rewriting
    -/// induction variables bottom-up from their users, it transforms a chain of
    -/// IVUsers top-down, updating the IR only when it encouters a clear
    -/// optimization opportunitiy. A SCEVExpander "Rewriter" instance is still
    -/// needed, but only used to generate a new IV (phi) of wider type for sign/zero
    -/// extend elimination.
    +/// Sign/Zero extend elimination is interleaved with IV simplification.
     ///
    -/// Once DisableIVRewrite is default, LSR will be the only client of IVUsers.
    -///
    -void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) {
    +void IndVarSimplify::SimplifyAndExtend(Loop *L,
    +                                       SCEVExpander &Rewriter,
    +                                       LPPassManager &LPM) {
       std::map WideIVMap;
     
       SmallVector LoopPhis;
    @@ -1433,49 +1185,17 @@
         // extension. The first time SCEV attempts to normalize sign/zero extension,
         // the result becomes final. So for the most predictable results, we delay
         // evaluation of sign/zero extend evaluation until needed, and avoid running
    -    // other SCEV based analysis prior to SimplifyIVUsersNoRewrite.
    +    // other SCEV based analysis prior to SimplifyAndExtend.
         do {
           PHINode *CurrIV = LoopPhis.pop_back_val();
     
           // Information about sign/zero extensions of CurrIV.
    -      WideIVInfo WI;
    -
    -      // Instructions processed by SimplifyIVUsers for CurrIV.
    -      SmallPtrSet Simplified;
    -
    -      // Use-def pairs if IV users waiting to be processed for CurrIV.
    -      SmallVector, 8> SimpleIVUsers;
    -
    -      // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
    -      // called multiple times for the same LoopPhi. This is the proper thing to
    -      // do for loop header phis that use each other.
    -      pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
    -
    -      while (!SimpleIVUsers.empty()) {
    -        std::pair UseOper =
    -          SimpleIVUsers.pop_back_val();
    -        // Bypass back edges to avoid extra work.
    -        if (UseOper.first == CurrIV) continue;
    +      WideIVVisitor WIV(SE, TD);
     
    -        FoldIVUser(UseOper.first, UseOper.second);
    +      Changed |= simplifyUsersOfIV(CurrIV, &LPM, DeadInsts, &WIV);
     
    -        if (EliminateIVUser(UseOper.first, UseOper.second)) {
    -          pushIVUsers(UseOper.second, Simplified, SimpleIVUsers);
    -          continue;
    -        }
    -        if (CastInst *Cast = dyn_cast(UseOper.first)) {
    -          bool IsSigned = Cast->getOpcode() == Instruction::SExt;
    -          if (IsSigned || Cast->getOpcode() == Instruction::ZExt) {
    -            CollectExtend(Cast, IsSigned, WI, SE, TD);
    -          }
    -          continue;
    -        }
    -        if (isSimpleIVUser(UseOper.first, L, SE)) {
    -          pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
    -        }
    -      }
    -      if (WI.WidestNativeType) {
    -        WideIVMap[CurrIV] = WI;
    +      if (WIV.WI.WidestNativeType) {
    +        WideIVMap[CurrIV] = WIV.WI;
           }
         } while(!LoopPhis.empty());
     
    @@ -1492,7 +1212,7 @@
     }
     
     /// SimplifyCongruentIVs - Check for congruent phis in this loop header and
    -/// populate ExprToIVMap for use later.
    +/// replace them with their chosen representative.
     ///
     void IndVarSimplify::SimplifyCongruentIVs(Loop *L) {
       DenseMap ExprToIVMap;
    @@ -2097,7 +1817,7 @@
       // set no-wrap flags before normalizing sign/zero extension.
       if (DisableIVRewrite) {
         Rewriter.disableCanonicalMode();
    -    SimplifyIVUsersNoRewrite(L, Rewriter);
    +    SimplifyAndExtend(L, Rewriter, LPM);
       }
     
       // Check to see if this loop has a computable loop-invariant execution count.
    @@ -2111,7 +1831,7 @@
     
       // Eliminate redundant IV users.
       if (!DisableIVRewrite)
    -    SimplifyIVUsers(Rewriter);
    +    Changed |= simplifyIVUsers(IU, &LPM, DeadInsts);
     
       // Eliminate redundant IV cycles.
       if (DisableIVRewrite)
    
    Added: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=137197&view=auto
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (added)
    +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Tue Aug  9 22:46:27 2011
    @@ -0,0 +1,413 @@
    +//===-- SimplifyIndVar.cpp - Induction variable simplification ------------===//
    +//
    +//                     The LLVM Compiler Infrastructure
    +//
    +// This file is distributed under the University of Illinois Open Source
    +// License. See LICENSE.TXT for details.
    +//
    +//===----------------------------------------------------------------------===//
    +//
    +// This file implements induction variable simplification. It does
    +// not define any actual pass or policy, but provides a single function to
    +// simplify a loop's induction variables based on ScalarEvolution.
    +//
    +//===----------------------------------------------------------------------===//
    +
    +#define DEBUG_TYPE "indvars"
    +
    +#include "llvm/Instructions.h"
    +#include "llvm/Analysis/Dominators.h"
    +#include "llvm/Analysis/IVUsers.h"
    +#include "llvm/Analysis/LoopInfo.h"
    +#include "llvm/Analysis/LoopPass.h"
    +#include "llvm/Analysis/ScalarEvolutionExpressions.h"
    +#include "llvm/Support/CommandLine.h"
    +#include "llvm/Support/Debug.h"
    +#include "llvm/Support/raw_ostream.h"
    +#include "llvm/Transforms/Utils/SimplifyIndVar.h"
    +#include "llvm/Target/TargetData.h"
    +#include "llvm/ADT/SmallVector.h"
    +#include "llvm/ADT/Statistic.h"
    +
    +using namespace llvm;
    +
    +STATISTIC(NumElimIdentity, "Number of IV identities eliminated");
    +STATISTIC(NumElimOperand,  "Number of IV operands folded into a use");
    +STATISTIC(NumElimRem     , "Number of IV remainder operations eliminated");
    +STATISTIC(NumElimCmp     , "Number of IV comparisons eliminated");
    +
    +namespace {
    +  /// SimplifyIndvar - This is a utility for simplifying induction variables
    +  /// based on ScalarEvolution. It is the primary instrument of the
    +  /// IndvarSimplify pass, but it may also be directly invoked to cleanup after
    +  /// other loop passes that preserve SCEV.
    +  class SimplifyIndvar {
    +    Loop             *L;
    +    LoopInfo         *LI;
    +    DominatorTree    *DT;
    +    ScalarEvolution  *SE;
    +    IVUsers          *IU; // NULL for DisableIVRewrite
    +    const TargetData *TD; // May be NULL
    +
    +    SmallVectorImpl &DeadInsts;
    +
    +    bool Changed;
    +
    +  public:
    +    SimplifyIndvar(Loop *Loop, LPPassManager *LPM,
    +                   SmallVectorImpl &Dead, IVUsers *IVU = NULL) :
    +      L(Loop),
    +      LI(LPM->getAnalysisIfAvailable()),
    +      SE(LPM->getAnalysisIfAvailable()),
    +      IU(IVU),
    +      TD(LPM->getAnalysisIfAvailable()),
    +      DeadInsts(Dead),
    +      Changed(false) {
    +      assert(LI && SE && "IV simplification requires ScalarEvolution");
    +    }
    +
    +    bool hasChanged() const { return Changed; }
    +
    +    /// Iteratively perform simplification on a worklist of users of the
    +    /// specified induction variable. This is the top-level driver that applies
    +    /// all simplicitions to users of an IV.
    +    void simplifyUsers(PHINode *CurrIV, IVVisitor *V = NULL);
    +
    +    bool foldIVUser(Instruction *UseInst, Instruction *IVOperand);
    +
    +    bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
    +    void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
    +    void eliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand,
    +                              bool IsSigned);
    +  };
    +}
    +
    +/// foldIVUser - Fold an IV operand into its use.  This removes increments of an
    +/// aligned IV when used by a instruction that ignores the low bits.
    +bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
    +  Value *IVSrc = 0;
    +  unsigned OperIdx = 0;
    +  const SCEV *FoldedExpr = 0;
    +  switch (UseInst->getOpcode()) {
    +  default:
    +    return false;
    +  case Instruction::UDiv:
    +  case Instruction::LShr:
    +    // We're only interested in the case where we know something about
    +    // the numerator and have a constant denominator.
    +    if (IVOperand != UseInst->getOperand(OperIdx) ||
    +        !isa(UseInst->getOperand(1)))
    +      return false;
    +
    +    // Attempt to fold a binary operator with constant operand.
    +    // e.g. ((I + 1) >> 2) => I >> 2
    +    if (IVOperand->getNumOperands() != 2 ||
    +        !isa(IVOperand->getOperand(1)))
    +      return false;
    +
    +    IVSrc = IVOperand->getOperand(0);
    +    // IVSrc must be the (SCEVable) IV, since the other operand is const.
    +    assert(SE->isSCEVable(IVSrc->getType()) && "Expect SCEVable IV operand");
    +
    +    ConstantInt *D = cast(UseInst->getOperand(1));
    +    if (UseInst->getOpcode() == Instruction::LShr) {
    +      // Get a constant for the divisor. See createSCEV.
    +      uint32_t BitWidth = cast(UseInst->getType())->getBitWidth();
    +      if (D->getValue().uge(BitWidth))
    +        return false;
    +
    +      D = ConstantInt::get(UseInst->getContext(),
    +                           APInt(BitWidth, 1).shl(D->getZExtValue()));
    +    }
    +    FoldedExpr = SE->getUDivExpr(SE->getSCEV(IVSrc), SE->getSCEV(D));
    +  }
    +  // We have something that might fold it's operand. Compare SCEVs.
    +  if (!SE->isSCEVable(UseInst->getType()))
    +    return false;
    +
    +  // Bypass the operand if SCEV can prove it has no effect.
    +  if (SE->getSCEV(UseInst) != FoldedExpr)
    +    return false;
    +
    +  DEBUG(dbgs() << "INDVARS: Eliminated IV operand: " << *IVOperand
    +        << " -> " << *UseInst << '\n');
    +
    +  UseInst->setOperand(OperIdx, IVSrc);
    +  assert(SE->getSCEV(UseInst) == FoldedExpr && "bad SCEV with folded oper");
    +
    +  ++NumElimOperand;
    +  Changed = true;
    +  if (IVOperand->use_empty())
    +    DeadInsts.push_back(IVOperand);
    +  return true;
    +}
    +
    +/// eliminateIVComparison - SimplifyIVUsers helper for eliminating useless
    +/// comparisons against an induction variable.
    +void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
    +  unsigned IVOperIdx = 0;
    +  ICmpInst::Predicate Pred = ICmp->getPredicate();
    +  if (IVOperand != ICmp->getOperand(0)) {
    +    // Swapped
    +    assert(IVOperand == ICmp->getOperand(1) && "Can't find IVOperand");
    +    IVOperIdx = 1;
    +    Pred = ICmpInst::getSwappedPredicate(Pred);
    +  }
    +
    +  // Get the SCEVs for the ICmp operands.
    +  const SCEV *S = SE->getSCEV(ICmp->getOperand(IVOperIdx));
    +  const SCEV *X = SE->getSCEV(ICmp->getOperand(1 - IVOperIdx));
    +
    +  // Simplify unnecessary loops away.
    +  const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
    +  S = SE->getSCEVAtScope(S, ICmpLoop);
    +  X = SE->getSCEVAtScope(X, ICmpLoop);
    +
    +  // If the condition is always true or always false, replace it with
    +  // a constant value.
    +  if (SE->isKnownPredicate(Pred, S, X))
    +    ICmp->replaceAllUsesWith(ConstantInt::getTrue(ICmp->getContext()));
    +  else if (SE->isKnownPredicate(ICmpInst::getInversePredicate(Pred), S, X))
    +    ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
    +  else
    +    return;
    +
    +  DEBUG(dbgs() << "INDVARS: Eliminated comparison: " << *ICmp << '\n');
    +  ++NumElimCmp;
    +  Changed = true;
    +  DeadInsts.push_back(ICmp);
    +}
    +
    +/// eliminateIVRemainder - SimplifyIVUsers helper for eliminating useless
    +/// remainder operations operating on an induction variable.
    +void SimplifyIndvar::eliminateIVRemainder(BinaryOperator *Rem,
    +                                      Value *IVOperand,
    +                                      bool IsSigned) {
    +  // We're only interested in the case where we know something about
    +  // the numerator.
    +  if (IVOperand != Rem->getOperand(0))
    +    return;
    +
    +  // Get the SCEVs for the ICmp operands.
    +  const SCEV *S = SE->getSCEV(Rem->getOperand(0));
    +  const SCEV *X = SE->getSCEV(Rem->getOperand(1));
    +
    +  // Simplify unnecessary loops away.
    +  const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
    +  S = SE->getSCEVAtScope(S, ICmpLoop);
    +  X = SE->getSCEVAtScope(X, ICmpLoop);
    +
    +  // i % n  -->  i  if i is in [0,n).
    +  if ((!IsSigned || SE->isKnownNonNegative(S)) &&
    +      SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
    +                           S, X))
    +    Rem->replaceAllUsesWith(Rem->getOperand(0));
    +  else {
    +    // (i+1) % n  -->  (i+1)==n?0:(i+1)  if i is in [0,n).
    +    const SCEV *LessOne =
    +      SE->getMinusSCEV(S, SE->getConstant(S->getType(), 1));
    +    if (IsSigned && !SE->isKnownNonNegative(LessOne))
    +      return;
    +
    +    if (!SE->isKnownPredicate(IsSigned ?
    +                              ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
    +                              LessOne, X))
    +      return;
    +
    +    ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
    +                                  Rem->getOperand(0), Rem->getOperand(1),
    +                                  "tmp");
    +    SelectInst *Sel =
    +      SelectInst::Create(ICmp,
    +                         ConstantInt::get(Rem->getType(), 0),
    +                         Rem->getOperand(0), "tmp", Rem);
    +    Rem->replaceAllUsesWith(Sel);
    +  }
    +
    +  // Inform IVUsers about the new users.
    +  if (IU) {
    +    if (Instruction *I = dyn_cast(Rem->getOperand(0)))
    +      IU->AddUsersIfInteresting(I);
    +  }
    +  DEBUG(dbgs() << "INDVARS: Simplified rem: " << *Rem << '\n');
    +  ++NumElimRem;
    +  Changed = true;
    +  DeadInsts.push_back(Rem);
    +}
    +
    +/// eliminateIVUser - Eliminate an operation that consumes a simple IV and has
    +/// no observable side-effect given the range of IV values.
    +bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst,
    +                                     Instruction *IVOperand) {
    +  if (ICmpInst *ICmp = dyn_cast(UseInst)) {
    +    eliminateIVComparison(ICmp, IVOperand);
    +    return true;
    +  }
    +  if (BinaryOperator *Rem = dyn_cast(UseInst)) {
    +    bool IsSigned = Rem->getOpcode() == Instruction::SRem;
    +    if (IsSigned || Rem->getOpcode() == Instruction::URem) {
    +      eliminateIVRemainder(Rem, IVOperand, IsSigned);
    +      return true;
    +    }
    +  }
    +
    +  // Eliminate any operation that SCEV can prove is an identity function.
    +  if (!SE->isSCEVable(UseInst->getType()) ||
    +      (UseInst->getType() != IVOperand->getType()) ||
    +      (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
    +    return false;
    +
    +  DEBUG(dbgs() << "INDVARS: Eliminated identity: " << *UseInst << '\n');
    +
    +  UseInst->replaceAllUsesWith(IVOperand);
    +  ++NumElimIdentity;
    +  Changed = true;
    +  DeadInsts.push_back(UseInst);
    +  return true;
    +}
    +
    +/// pushIVUsers - Add all uses of Def to the current IV's worklist.
    +///
    +static void pushIVUsers(
    +  Instruction *Def,
    +  SmallPtrSet &Simplified,
    +  SmallVectorImpl< std::pair > &SimpleIVUsers) {
    +
    +  for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end();
    +       UI != E; ++UI) {
    +    Instruction *User = cast(*UI);
    +
    +    // Avoid infinite or exponential worklist processing.
    +    // Also ensure unique worklist users.
    +    // If Def is a LoopPhi, it may not be in the Simplified set, so check for
    +    // self edges first.
    +    if (User != Def && Simplified.insert(User))
    +      SimpleIVUsers.push_back(std::make_pair(User, Def));
    +  }
    +}
    +
    +/// isSimpleIVUser - Return true if this instruction generates a simple SCEV
    +/// expression in terms of that IV.
    +///
    +/// This is similar to IVUsers' isInsteresting() but processes each instruction
    +/// non-recursively when the operand is already known to be a simpleIVUser.
    +///
    +static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) {
    +  if (!SE->isSCEVable(I->getType()))
    +    return false;
    +
    +  // Get the symbolic expression for this instruction.
    +  const SCEV *S = SE->getSCEV(I);
    +
    +  // Only consider affine recurrences.
    +  const SCEVAddRecExpr *AR = dyn_cast(S);
    +  if (AR && AR->getLoop() == L)
    +    return true;
    +
    +  return false;
    +}
    +
    +/// simplifyUsers - Iteratively perform simplification on a worklist of users
    +/// of the specified induction variable. Each successive simplification may push
    +/// more users which may themselves be candidates for simplification.
    +///
    +/// This algorithm does not require IVUsers analysis. Instead, it simplifies
    +/// instructions in-place during analysis. Rather than rewriting induction
    +/// variables bottom-up from their users, it transforms a chain of IVUsers
    +/// top-down, updating the IR only when it encouters a clear optimization
    +/// opportunitiy.
    +///
    +/// Once DisableIVRewrite is default, LSR will be the only client of IVUsers.
    +///
    +void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
    +  // Instructions processed by SimplifyIndvar for CurrIV.
    +  SmallPtrSet Simplified;
    +
    +  // Use-def pairs if IV users waiting to be processed for CurrIV.
    +  SmallVector, 8> SimpleIVUsers;
    +
    +  // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
    +  // called multiple times for the same LoopPhi. This is the proper thing to
    +  // do for loop header phis that use each other.
    +  pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
    +
    +  while (!SimpleIVUsers.empty()) {
    +    std::pair UseOper =
    +      SimpleIVUsers.pop_back_val();
    +    // Bypass back edges to avoid extra work.
    +    if (UseOper.first == CurrIV) continue;
    +
    +    foldIVUser(UseOper.first, UseOper.second);
    +
    +    if (eliminateIVUser(UseOper.first, UseOper.second)) {
    +      pushIVUsers(UseOper.second, Simplified, SimpleIVUsers);
    +      continue;
    +    }
    +    CastInst *Cast = dyn_cast(UseOper.first);
    +    if (V && Cast) {
    +      V->visitCast(Cast);
    +      continue;
    +    }
    +    if (isSimpleIVUser(UseOper.first, L, SE)) {
    +      pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
    +    }
    +  }
    +}
    +
    +namespace llvm {
    +
    +/// simplifyUsersOfIV - Simplify instructions that use this induction variable
    +/// by using ScalarEvolution to analyze the IV's recurrence.
    +bool simplifyUsersOfIV(PHINode *CurrIV, LPPassManager *LPM,
    +                       SmallVectorImpl &Dead, IVVisitor *V)
    +{
    +  LoopInfo *LI = &LPM->getAnalysis();
    +  SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), LPM, Dead);
    +  SIV.simplifyUsers(CurrIV, V);
    +  return SIV.hasChanged();
    +}
    +
    +/// simplifyLoopIVs - Simplify users of induction variables within this
    +/// loop. This does not actually change or add IVs.
    +bool simplifyLoopIVs(Loop *L, LPPassManager *LPM,
    +                     SmallVectorImpl &Dead) {
    +  bool Changed = false;
    +  for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) {
    +    Changed |= simplifyUsersOfIV(cast(I), LPM, Dead);
    +  }
    +  return Changed;
    +}
    +
    +/// simplifyIVUsers - Perform simplification on instructions recorded by the
    +/// IVUsers pass.
    +///
    +/// This is the old approach to IV simplification to be replaced by
    +/// SimplifyLoopIVs.
    +bool simplifyIVUsers(IVUsers *IU, LPPassManager *LPM,
    +                     SmallVectorImpl &Dead) {
    +  SimplifyIndvar SIV(IU->getLoop(), LPM, Dead);
    +
    +  // Each round of simplification involves a round of eliminating operations
    +  // followed by a round of widening IVs. A single IVUsers worklist is used
    +  // across all rounds. The inner loop advances the user. If widening exposes
    +  // more uses, then another pass through the outer loop is triggered.
    +  for (IVUsers::iterator I = IU->begin(); I != IU->end(); ++I) {
    +    Instruction *UseInst = I->getUser();
    +    Value *IVOperand = I->getOperandValToReplace();
    +
    +    if (ICmpInst *ICmp = dyn_cast(UseInst)) {
    +      SIV.eliminateIVComparison(ICmp, IVOperand);
    +      continue;
    +    }
    +    if (BinaryOperator *Rem = dyn_cast(UseInst)) {
    +      bool IsSigned = Rem->getOpcode() == Instruction::SRem;
    +      if (IsSigned || Rem->getOpcode() == Instruction::URem) {
    +        SIV.eliminateIVRemainder(Rem, IVOperand, IsSigned);
    +        continue;
    +      }
    +    }
    +  }
    +  return SIV.hasChanged();
    +}
    +
    +} // namespace llvm
    
    
    
    From benny.kra at googlemail.com  Tue Aug  9 22:51:58 2011
    From: benny.kra at googlemail.com (Benjamin Kramer)
    Date: Wed, 10 Aug 2011 03:51:58 -0000
    Subject: [llvm-commits] [llvm] r137198 -
    	/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
    Message-ID: <20110810035158.8D2CF2A6C12D@llvm.org>
    
    Author: d0k
    Date: Tue Aug  9 22:51:58 2011
    New Revision: 137198
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137198&view=rev
    Log:
    Update CMake build.
    
    Modified:
        llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
    
    Modified: llvm/trunk/lib/Transforms/Utils/CMakeLists.txt
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/CMakeLists.txt?rev=137198&r1=137197&r2=137198&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Utils/CMakeLists.txt (original)
    +++ llvm/trunk/lib/Transforms/Utils/CMakeLists.txt Tue Aug  9 22:51:58 2011
    @@ -21,6 +21,7 @@
       PromoteMemoryToRegister.cpp
       SSAUpdater.cpp
       SimplifyCFG.cpp
    +  SimplifyIndVar.cpp
       SimplifyInstructions.cpp
       UnifyFunctionExitNodes.cpp
       Utils.cpp
    
    
    
    From atrick at apple.com  Tue Aug  9 23:01:31 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Wed, 10 Aug 2011 04:01:31 -0000
    Subject: [llvm-commits] [llvm] r137199 -
    	/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    Message-ID: <20110810040131.922742A6C12D@llvm.org>
    
    Author: atrick
    Date: Tue Aug  9 23:01:31 2011
    New Revision: 137199
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137199&view=rev
    Log:
    SimplifyIndVar: make foldIVUser iterative to fold a chain of operands.
    
    Modified:
        llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    
    Modified: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=137199&r1=137198&r2=137199&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (original)
    +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Tue Aug  9 23:01:31 2011
    @@ -73,7 +73,7 @@
         /// all simplicitions to users of an IV.
         void simplifyUsers(PHINode *CurrIV, IVVisitor *V = NULL);
     
    -    bool foldIVUser(Instruction *UseInst, Instruction *IVOperand);
    +    Value *foldIVUser(Instruction *UseInst, Instruction *IVOperand);
     
         bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
         void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
    @@ -84,26 +84,30 @@
     
     /// foldIVUser - Fold an IV operand into its use.  This removes increments of an
     /// aligned IV when used by a instruction that ignores the low bits.
    -bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
    +///
    +/// Return the operand of IVOperand for this induction variable if IVOperand can
    +/// be folded (in case more folding opportunity has been exposed).
    +/// Otherwise return null.
    +Value *SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
       Value *IVSrc = 0;
       unsigned OperIdx = 0;
       const SCEV *FoldedExpr = 0;
       switch (UseInst->getOpcode()) {
       default:
    -    return false;
    +    return 0;
       case Instruction::UDiv:
       case Instruction::LShr:
         // We're only interested in the case where we know something about
         // the numerator and have a constant denominator.
         if (IVOperand != UseInst->getOperand(OperIdx) ||
             !isa(UseInst->getOperand(1)))
    -      return false;
    +      return 0;
     
         // Attempt to fold a binary operator with constant operand.
         // e.g. ((I + 1) >> 2) => I >> 2
         if (IVOperand->getNumOperands() != 2 ||
             !isa(IVOperand->getOperand(1)))
    -      return false;
    +      return 0;
     
         IVSrc = IVOperand->getOperand(0);
         // IVSrc must be the (SCEVable) IV, since the other operand is const.
    @@ -114,7 +118,7 @@
           // Get a constant for the divisor. See createSCEV.
           uint32_t BitWidth = cast(UseInst->getType())->getBitWidth();
           if (D->getValue().uge(BitWidth))
    -        return false;
    +        return 0;
     
           D = ConstantInt::get(UseInst->getContext(),
                                APInt(BitWidth, 1).shl(D->getZExtValue()));
    @@ -123,11 +127,11 @@
       }
       // We have something that might fold it's operand. Compare SCEVs.
       if (!SE->isSCEVable(UseInst->getType()))
    -    return false;
    +    return 0;
     
       // Bypass the operand if SCEV can prove it has no effect.
       if (SE->getSCEV(UseInst) != FoldedExpr)
    -    return false;
    +    return 0;
     
       DEBUG(dbgs() << "INDVARS: Eliminated IV operand: " << *IVOperand
             << " -> " << *UseInst << '\n');
    @@ -139,7 +143,7 @@
       Changed = true;
       if (IVOperand->use_empty())
         DeadInsts.push_back(IVOperand);
    -  return true;
    +  return IVSrc;
     }
     
     /// eliminateIVComparison - SimplifyIVUsers helper for eliminating useless
    @@ -337,10 +341,20 @@
         // Bypass back edges to avoid extra work.
         if (UseOper.first == CurrIV) continue;
     
    -    foldIVUser(UseOper.first, UseOper.second);
    +    Instruction *IVOperand = UseOper.second;
    +    for (unsigned N = 0; IVOperand; ++N) {
    +      assert(N <= Simplified.size() && "runaway iteration");
    +
    +      Value *NewOper = foldIVUser(UseOper.first, IVOperand);
    +      if (!NewOper)
    +        break; // done folding
    +      IVOperand = dyn_cast(NewOper);
    +    }
    +    if (!IVOperand)
    +      continue;
     
    -    if (eliminateIVUser(UseOper.first, UseOper.second)) {
    -      pushIVUsers(UseOper.second, Simplified, SimpleIVUsers);
    +    if (eliminateIVUser(UseOper.first, IVOperand)) {
    +      pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
           continue;
         }
         CastInst *Cast = dyn_cast(UseOper.first);
    
    
    
    From atrick at apple.com  Tue Aug  9 23:22:26 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Wed, 10 Aug 2011 04:22:26 -0000
    Subject: [llvm-commits] [llvm] r137202 - in /llvm/trunk:
     include/llvm/Transforms/Utils/SimplifyIndVar.h
     lib/Transforms/Scalar/IndVarSimplify.cpp
     lib/Transforms/Utils/SimplifyIndVar.cpp
    Message-ID: <20110810042226.80B6D2A6C12C@llvm.org>
    
    Author: atrick
    Date: Tue Aug  9 23:22:26 2011
    New Revision: 137202
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137202&view=rev
    Log:
    Cleanup. Make ScalarEvolution an explicit argument of the
    SimplifyIndVar utility since it is required.
    
    Modified:
        llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h
        llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
        llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    
    Modified: llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h?rev=137202&r1=137201&r2=137202&view=diff
    ==============================================================================
    --- llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h (original)
    +++ llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h Tue Aug  9 23:22:26 2011
    @@ -39,18 +39,18 @@
     
     /// simplifyUsersOfIV - Simplify instructions that use this induction variable
     /// by using ScalarEvolution to analyze the IV's recurrence.
    -bool simplifyUsersOfIV(PHINode *CurrIV, LPPassManager *LPM,
    +bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, LPPassManager *LPM,
                            SmallVectorImpl &Dead, IVVisitor *V = NULL);
     
     /// SimplifyLoopIVs - Simplify users of induction variables within this
     /// loop. This does not actually change or add IVs.
    -bool simplifyLoopIVs(Loop *L, LPPassManager *LPM,
    +bool simplifyLoopIVs(Loop *L, ScalarEvolution *SE, LPPassManager *LPM,
                          SmallVectorImpl &Dead);
     
     /// simplifyIVUsers - Simplify instructions recorded by the IVUsers pass.
     /// This is a legacy implementation to reproduce the behavior of the
     /// IndVarSimplify pass prior to DisableIVRewrite.
    -bool simplifyIVUsers(IVUsers *IU, LPPassManager *LPM,
    +bool simplifyIVUsers(IVUsers *IU, ScalarEvolution *SE, LPPassManager *LPM,
                          SmallVectorImpl &Dead);
     
     } // namespace llvm
    
    Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=137202&r1=137201&r2=137202&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
    +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Tue Aug  9 23:22:26 2011
    @@ -1192,7 +1192,7 @@
           // Information about sign/zero extensions of CurrIV.
           WideIVVisitor WIV(SE, TD);
     
    -      Changed |= simplifyUsersOfIV(CurrIV, &LPM, DeadInsts, &WIV);
    +      Changed |= simplifyUsersOfIV(CurrIV, SE, &LPM, DeadInsts, &WIV);
     
           if (WIV.WI.WidestNativeType) {
             WideIVMap[CurrIV] = WIV.WI;
    @@ -1831,7 +1831,7 @@
     
       // Eliminate redundant IV users.
       if (!DisableIVRewrite)
    -    Changed |= simplifyIVUsers(IU, &LPM, DeadInsts);
    +    Changed |= simplifyIVUsers(IU, SE, &LPM, DeadInsts);
     
       // Eliminate redundant IV cycles.
       if (DisableIVRewrite)
    
    Modified: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=137202&r1=137201&r2=137202&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (original)
    +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Tue Aug  9 23:22:26 2011
    @@ -54,16 +54,16 @@
         bool Changed;
     
       public:
    -    SimplifyIndvar(Loop *Loop, LPPassManager *LPM,
    +    SimplifyIndvar(Loop *Loop, ScalarEvolution *SE, LPPassManager *LPM,
                        SmallVectorImpl &Dead, IVUsers *IVU = NULL) :
           L(Loop),
           LI(LPM->getAnalysisIfAvailable()),
    -      SE(LPM->getAnalysisIfAvailable()),
    +      SE(SE),
           IU(IVU),
           TD(LPM->getAnalysisIfAvailable()),
           DeadInsts(Dead),
           Changed(false) {
    -      assert(LI && SE && "IV simplification requires ScalarEvolution");
    +      assert(LI && "IV simplification requires LoopInfo");
         }
     
         bool hasChanged() const { return Changed; }
    @@ -372,22 +372,22 @@
     
     /// simplifyUsersOfIV - Simplify instructions that use this induction variable
     /// by using ScalarEvolution to analyze the IV's recurrence.
    -bool simplifyUsersOfIV(PHINode *CurrIV, LPPassManager *LPM,
    +bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, LPPassManager *LPM,
                            SmallVectorImpl &Dead, IVVisitor *V)
     {
       LoopInfo *LI = &LPM->getAnalysis();
    -  SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), LPM, Dead);
    +  SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, LPM, Dead);
       SIV.simplifyUsers(CurrIV, V);
       return SIV.hasChanged();
     }
     
     /// simplifyLoopIVs - Simplify users of induction variables within this
     /// loop. This does not actually change or add IVs.
    -bool simplifyLoopIVs(Loop *L, LPPassManager *LPM,
    +bool simplifyLoopIVs(Loop *L, ScalarEvolution *SE, LPPassManager *LPM,
                          SmallVectorImpl &Dead) {
       bool Changed = false;
       for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) {
    -    Changed |= simplifyUsersOfIV(cast(I), LPM, Dead);
    +    Changed |= simplifyUsersOfIV(cast(I), SE, LPM, Dead);
       }
       return Changed;
     }
    @@ -397,9 +397,9 @@
     ///
     /// This is the old approach to IV simplification to be replaced by
     /// SimplifyLoopIVs.
    -bool simplifyIVUsers(IVUsers *IU, LPPassManager *LPM,
    +bool simplifyIVUsers(IVUsers *IU, ScalarEvolution *SE, LPPassManager *LPM,
                          SmallVectorImpl &Dead) {
    -  SimplifyIndvar SIV(IU->getLoop(), LPM, Dead);
    +  SimplifyIndvar SIV(IU->getLoop(), SE, LPM, Dead);
     
       // Each round of simplification involves a round of eliminating operations
       // followed by a round of widening IVs. A single IVUsers worklist is used
    
    
    
    From atrick at apple.com  Tue Aug  9 23:29:49 2011
    From: atrick at apple.com (Andrew Trick)
    Date: Wed, 10 Aug 2011 04:29:49 -0000
    Subject: [llvm-commits] [llvm] r137203 - in /llvm/trunk:
     lib/Transforms/Scalar/LoopUnrollPass.cpp
     lib/Transforms/Utils/LoopUnroll.cpp
     test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll
    Message-ID: <20110810042949.62A0B2A6C12D@llvm.org>
    
    Author: atrick
    Date: Tue Aug  9 23:29:49 2011
    New Revision: 137203
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137203&view=rev
    Log:
    Invoke SimplifyIndVar when we partially unroll a loop. Fixes PR10534.
    
    Added:
        llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll
    Modified:
        llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
        llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    
    Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=137203&r1=137202&r2=137203&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original)
    +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Tue Aug  9 23:29:49 2011
    @@ -79,6 +79,7 @@
           AU.addPreservedID(LoopSimplifyID);
           AU.addRequiredID(LCSSAID);
           AU.addPreservedID(LCSSAID);
    +      AU.addRequired();
           AU.addPreserved();
           // FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info.
           // If loop unroll does not preserve dom info then LCSSA pass on next
    @@ -187,12 +188,8 @@
       }
     
       // Unroll the loop.
    -  Function *F = L->getHeader()->getParent();
       if (!UnrollLoop(L, Count, TripCount, TripMultiple, LI, &LPM))
         return false;
     
    -  // FIXME: Reconstruct dom info, because it is not preserved properly.
    -  if (DominatorTree *DT = getAnalysisIfAvailable())
    -    DT->runOnFunction(*F);
       return true;
     }
    
    Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=137203&r1=137202&r2=137203&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
    +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Tue Aug  9 23:29:49 2011
    @@ -29,6 +29,7 @@
     #include "llvm/Transforms/Utils/BasicBlockUtils.h"
     #include "llvm/Transforms/Utils/Cloning.h"
     #include "llvm/Transforms/Utils/Local.h"
    +#include "llvm/Transforms/Utils/SimplifyIndVar.h"
     using namespace llvm;
     
     // TODO: Should these be here or in LoopUnroll?
    @@ -130,6 +131,9 @@
     ///
     /// If a LoopPassManager is passed in, and the loop is fully removed, it will be
     /// removed from the LoopPassManager as well. LPM can also be NULL.
    +///
    +/// This utility preserves LoopInfo. If DominatorTree or ScalarEvolution are
    +/// available it must also preseve those analyses.
     bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount,
                           unsigned TripMultiple, LoopInfo *LI, LPPassManager *LPM) {
       BasicBlock *Preheader = L->getLoopPreheader();
    @@ -163,7 +167,8 @@
     
       // Notify ScalarEvolution that the loop will be substantially changed,
       // if not outright eliminated.
    -  if (ScalarEvolution *SE = LPM->getAnalysisIfAvailable())
    +  ScalarEvolution *SE = LPM->getAnalysisIfAvailable();
    +  if (SE)
         SE->forgetLoop(L);
     
       if (TripCount != 0)
    @@ -374,6 +379,24 @@
         }
       }
     
    +  // FIXME: Reconstruct dom info, because it is not preserved properly.
    +  // Incrementally updating domtree after loop unrolling woud be easy.
    +  if (DominatorTree *DT = LPM->getAnalysisIfAvailable())
    +    DT->runOnFunction(*L->getHeader()->getParent());
    +
    +  // Simplify any new induction variables in the partially unrolled loop.
    +  if (SE && !CompletelyUnroll) {
    +    SmallVector DeadInsts;
    +    simplifyLoopIVs(L, SE, LPM, DeadInsts);
    +
    +    // Aggressively clean up dead instructions that simplifyLoopIVs already
    +    // identified. Any remaining should be cleaned up below.
    +    while (!DeadInsts.empty())
    +      if (Instruction *Inst =
    +          dyn_cast_or_null(&*DeadInsts.pop_back_val()))
    +        RecursivelyDeleteTriviallyDeadInstructions(Inst);
    +  }
    +
       // At this point, the code is well formed.  We now do a quick sweep over the
       // inserted code, doing constant propagation and dead code elimination as we
       // go.
    
    Added: llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll?rev=137203&view=auto
    ==============================================================================
    --- llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll (added)
    +++ llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll Tue Aug  9 23:29:49 2011
    @@ -0,0 +1,39 @@
    +; RUN: opt -S < %s -loop-unroll -unroll-count=4 -disable-iv-rewrite | FileCheck %s
    +;
    +; Test induction variable simplify after loop unrolling. It should
    +; expose nice opportunities for GVN.
    +
    +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
    +
    +; PR10534: LoopUnroll not keeping canonical induction variable...
    +; CHECK: while.body.1:
    +; CHECK: %shr.1 = lshr i32 %bit_addr.addr.01, 5
    +; CHECK: %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1
    +; CHECK: while.body.2:
    +; CHECK: %shr.2 = lshr i32 %bit_addr.addr.01, 5
    +; CHECK: %arrayidx.2 = getelementptr inbounds i32* %bitmap, i32 %shr.2
    +; CHECK: while.body.3:
    +; CHECK: %shr.3 = lshr i32 %bit_addr.addr.01, 5
    +; CHECK: %arrayidx.3 = getelementptr inbounds i32* %bitmap, i32 %shr.3
    +define void @FlipBit(i32* nocapture %bitmap, i32 %bit_addr, i32 %nbits) nounwind {
    +entry:
    +  br label %while.body
    +
    +while.body:
    +  %nbits.addr.02 = phi i32 [ 128, %entry ], [ %dec, %while.body ]
    +  %bit_addr.addr.01 = phi i32 [ 0, %entry ], [ %inc, %while.body ]
    +  %dec = add i32 %nbits.addr.02, -1
    +  %shr = lshr i32 %bit_addr.addr.01, 5
    +  %rem = and i32 %bit_addr.addr.01, 31
    +  %shl = shl i32 1, %rem
    +  %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr
    +  %tmp6 = load i32* %arrayidx, align 4
    +  %xor = xor i32 %tmp6, %shl
    +  store i32 %xor, i32* %arrayidx, align 4
    +  %inc = add i32 %bit_addr.addr.01, 1
    +  %tobool = icmp eq i32 %dec, 0
    +  br i1 %tobool, label %while.end, label %while.body
    +
    +while.end:
    +  ret void
    +}
    
    
    
    From nicholas at mxc.ca  Tue Aug  9 23:35:27 2011
    From: nicholas at mxc.ca (Nick Lewycky)
    Date: Tue, 09 Aug 2011 21:35:27 -0700
    Subject: [llvm-commits] [llvm] r137170 - in /llvm/trunk:
     docs/Atomics.html docs/LangRef.html include/llvm/Bitcode/LLVMBitCodes.h
     include/llvm/Instructions.h lib/AsmParser/LLParser.cpp
     lib/AsmParser/LLParser.h lib/Bitcode/Reader/BitcodeReader.cpp
     lib/Bitcode/Writer/BitcodeWriter.cpp lib/Transforms/Scalar/LowerAtomic.cpp
     lib/VMCore/AsmWriter.cpp lib/VMCore/Instructions.cpp
     lib/VMCore/Verifier.cpp
    In-Reply-To: <20110809230254.7D1AD2A6C12C@llvm.org>
    References: <20110809230254.7D1AD2A6C12C@llvm.org>
    Message-ID: <4E420A8F.90803@mxc.ca>
    
    Eli Friedman wrote:
    > Author: efriedma
    > Date: Tue Aug  9 18:02:53 2011
    > New Revision: 137170
    >
    > URL: http://llvm.org/viewvc/llvm-project?rev=137170&view=rev
    > Log:
    > Representation of 'atomic load' and 'atomic store' in IR.
    >
    >
    > Modified:
    >      llvm/trunk/docs/Atomics.html
    >      llvm/trunk/docs/LangRef.html
    >      llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    >      llvm/trunk/include/llvm/Instructions.h
    >      llvm/trunk/lib/AsmParser/LLParser.cpp
    >      llvm/trunk/lib/AsmParser/LLParser.h
    >      llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    >      llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    >      llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp
    >      llvm/trunk/lib/VMCore/AsmWriter.cpp
    >      llvm/trunk/lib/VMCore/Instructions.cpp
    >      llvm/trunk/lib/VMCore/Verifier.cpp
    >
    > Modified: llvm/trunk/docs/Atomics.html
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/Atomics.html?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/docs/Atomics.html (original)
    > +++ llvm/trunk/docs/Atomics.html Tue Aug  9 18:02:53 2011
    > @@ -3,6 +3,7 @@
    >   
    >   
    >     LLVM Atomic Instructions and Concurrency Guide
    > +
    >     
    >   
    >   
    >
    > Modified: llvm/trunk/docs/LangRef.html
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.html?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/docs/LangRef.html (original)
    > +++ llvm/trunk/docs/LangRef.html Tue Aug  9 18:02:53 2011
    > @@ -1583,8 +1583,10 @@
    >   
    > >

    Atomic instructions (cmpxchg, > -atomicrmw, and > -fence) take an ordering parameter > +atomicrmw, > +fence, > +atomic load, and > +atomic store) take an ordering parameter > that determines which other atomic instructions on the same address they > synchronize with. These semantics are borrowed from Java and C++0x, > but are somewhat more colloquial. If these descriptions aren't precise enough, > @@ -1592,11 +1594,7 @@ > treat these orderings somewhat differently since they don't take an address. > See that instruction's documentation for details.

    > > - > - >
    > - >
    unordered
    >
    The set of values that can be read is governed by the happens-before > partial order. A value cannot be read unless some operation wrote it. > @@ -4572,8 +4570,8 @@ > >
    Syntax:
    >
    > -<result> = load<ty>*<pointer>[, align<alignment>][, !nontemporal !<index>]
    > -<result> = volatile load<ty>*<pointer>[, align<alignment>][, !nontemporal !<index>]
    > +<result> = [volatile] load<ty>*<pointer>[, align<alignment>][, !nontemporal !<index>]
    > +<result> = atomic [volatile] load<ty>*<pointer> [singlethread]<ordering>, align<alignment>
    >     !<index> = !{ i32 1 }
    >   
    > > @@ -4588,6 +4586,19 @@ > number or order of execution of thisload with other href="#volatile">volatile operations.

    > > +

    If theload is marked asatomic, it takes an extra > +ordering and optionalsinglethread > + argument. Therelease andacq_rel orderings are > + not valid onload instructions. Atomic loads produce + href="#memorymodel">defined results when they may see multiple atomic > + stores. The type of the pointee must be an integer type whose bit width > + is a power of two greater than or equal to eight and less than or equal > + to a target-specific size limit.align must be explicitly > + specified on atomic loads, and the load has undefined behavior if the > + alignment is not set to a value which is at least the size in bytes of > + the pointee.!nontemporal does not have any defined semantics > + for atomic loads.

    > + >

    The optional constantalign argument specifies the alignment of the > operation (that is, the alignment of the memory address). A value of 0 or an > omittedalign argument means that the operation has the preferential > @@ -4631,8 +4642,8 @@ > >

    Syntax:
    >
    > -  store<ty><value>,<ty>*<pointer>[, align<alignment>][, !nontemporal !<index>]; yields {void}
    > -  volatile store<ty><value>,<ty>*<pointer>[, align<alignment>][, !nontemporal !<index>]; yields {void}
    > +  [volatile] store<ty><value>,<ty>*<pointer>[, align<alignment>][, !nontemporal !<index>]; yields {void}
    > +  atomic [volatile] store<ty><value>,<ty>*<pointer> [singlethread]<ordering>, align<alignment>; yields {void}
    >   
    > >
    Overview:
    > @@ -4648,6 +4659,19 @@ > order of execution of thisstore with other href="#volatile">volatile operations.

    > > +

    If thestore is marked asatomic, it takes an extra > +ordering and optionalsinglethread > + argument. Theacquire andacq_rel orderings aren't > + valid onstore instructions. Atomic loads produce + href="#memorymodel">defined results when they may see multiple atomic > + stores. The type of the pointee must be an integer type whose bit width > + is a power of two greater than or equal to eight and less than or equal > + to a target-specific size limit.align must be explicitly > + specified on atomic stores, and the store has undefined behavior if the > + alignment is not set to a value which is at least the size in bytes of > + the pointee.!nontemporal does not have any defined semantics > + for atomic stores.

    > + >

    The optional constant "align" argument specifies the alignment of the > operation (that is, the alignment of the memory address). A value of 0 or an > omitted "align" argument means that the operation has the preferential > @@ -4730,9 +4754,6 @@ > specifies that the fence only synchronizes with other fences in the same > thread. (This is useful for interacting with signal handlers.)

    > > -

    FIXME: This instruction is a work in progress; until it is finished, use > - llvm.memory.barrier. > - >

    Example:
    >
    >     fence acquire; yields {void}
    >
    > Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
    > +++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Tue Aug  9 18:02:53 2011
    > @@ -307,7 +307,11 @@
    >       FUNC_CODE_INST_ATOMICRMW   = 38, // ATOMICRMW: [ptrty,ptr,val, operation,
    >                                        //             align, vol,
    >                                        //             ordering, synchscope]
    > -    FUNC_CODE_INST_RESUME      = 39  // RESUME:     [opval]
    > +    FUNC_CODE_INST_RESUME      = 39, // RESUME:     [opval]
    > +    FUNC_CODE_INST_LOADATOMIC  = 40, // LOAD: [opty, op, align, vol,
    > +                                     //        ordering, synchscope]
    > +    FUNC_CODE_INST_STOREATOMIC = 41  // STORE: [ptrty,ptr,val, align, vol
    > +                                     //         ordering, synchscope]
    >     };
    >   } // End bitc namespace
    >   } // End llvm namespace
    >
    > Modified: llvm/trunk/include/llvm/Instructions.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Instructions.h?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/include/llvm/Instructions.h (original)
    > +++ llvm/trunk/include/llvm/Instructions.h Tue Aug  9 18:02:53 2011
    > @@ -143,11 +143,19 @@
    >     LoadInst(Value *Ptr, const Twine&NameStr, bool isVolatile = false,
    >              Instruction *InsertBefore = 0);
    >     LoadInst(Value *Ptr, const Twine&NameStr, bool isVolatile,
    > -           unsigned Align, Instruction *InsertBefore = 0);
    > -  LoadInst(Value *Ptr, const Twine&NameStr, bool isVolatile,
    >              BasicBlock *InsertAtEnd);
    >     LoadInst(Value *Ptr, const Twine&NameStr, bool isVolatile,
    > +           unsigned Align, Instruction *InsertBefore = 0);
    > +  LoadInst(Value *Ptr, const Twine&NameStr, bool isVolatile,
    >              unsigned Align, BasicBlock *InsertAtEnd);
    > +  LoadInst(Value *Ptr, const Twine&NameStr, bool isVolatile,
    > +           unsigned Align, AtomicOrdering Order,
    > +           SynchronizationScope SynchScope = CrossThread,
    > +           Instruction *InsertBefore = 0);
    > +  LoadInst(Value *Ptr, const Twine&NameStr, bool isVolatile,
    > +           unsigned Align, AtomicOrdering Order,
    > +           SynchronizationScope SynchScope,
    > +           BasicBlock *InsertAtEnd);
    >
    >     LoadInst(Value *Ptr, const char *NameStr, Instruction *InsertBefore);
    >     LoadInst(Value *Ptr, const char *NameStr, BasicBlock *InsertAtEnd);
    > @@ -171,11 +179,47 @@
    >     /// getAlignment - Return the alignment of the access that is being performed
    >     ///
    >     unsigned getAlignment() const {
    > -    return (1<<  (getSubclassDataFromInstruction()>>  1))>>  1;
    > +    return (1<<  ((getSubclassDataFromInstruction()>>  1)&  31))>>  1;
    >     }
    >
    >     void setAlignment(unsigned Align);
    >
    > +  /// Returns the ordering effect of this fence.
    > +  AtomicOrdering getOrdering() const {
    > +    return AtomicOrdering((getSubclassDataFromInstruction()>>  7)&  7);
    > +  }
    > +
    > +  /// Set the ordering constraint on this load. May not be Release or
    > +  /// AcquireRelease.
    > +  void setOrdering(AtomicOrdering Ordering) {
    > +    setInstructionSubclassData((getSubclassDataFromInstruction()&  ~(7<<  7)) |
    > +                               (Ordering<<  7));
    > +  }
    > +
    > +  SynchronizationScope getSynchScope() const {
    > +    return SynchronizationScope((getSubclassDataFromInstruction()>>  6)&  1);
    > +  }
    > +
    > +  /// Specify whether this load is ordered with respect to all
    > +  /// concurrently executing threads, or only with respect to signal handlers
    > +  /// executing in the same thread.
    > +  void setSynchScope(SynchronizationScope xthread) {
    > +    setInstructionSubclassData((getSubclassDataFromInstruction()&  ~(1<<  6)) |
    > +                               (xthread<<  6));
    > +  }
    > +
    > +  bool isAtomic() const { return getOrdering() != NotAtomic; }
    > +  void setAtomic(AtomicOrdering Ordering,
    > +                 SynchronizationScope SynchScope = CrossThread) {
    > +    setOrdering(Ordering);
    > +    setSynchScope(SynchScope);
    > +  }
    > +
    > +  bool isSimple() const { return !isAtomic()&&  !isVolatile(); }
    > +  bool isUnordered() const {
    > +    return getOrdering()<= Unordered&&  !isVolatile();
    > +  }
    > +
    >     Value *getPointerOperand() { return getOperand(0); }
    >     const Value *getPointerOperand() const { return getOperand(0); }
    >     static unsigned getPointerOperandIndex() { return 0U; }
    > @@ -222,19 +266,27 @@
    >     StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd);
    >     StoreInst(Value *Val, Value *Ptr, bool isVolatile = false,
    >               Instruction *InsertBefore = 0);
    > +  StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd);
    >     StoreInst(Value *Val, Value *Ptr, bool isVolatile,
    >               unsigned Align, Instruction *InsertBefore = 0);
    > -  StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd);
    >     StoreInst(Value *Val, Value *Ptr, bool isVolatile,
    >               unsigned Align, BasicBlock *InsertAtEnd);
    > +  StoreInst(Value *Val, Value *Ptr, bool isVolatile,
    > +            unsigned Align, AtomicOrdering Order,
    > +            SynchronizationScope SynchScope = CrossThread,
    > +            Instruction *InsertBefore = 0);
    > +  StoreInst(Value *Val, Value *Ptr, bool isVolatile,
    > +            unsigned Align, AtomicOrdering Order,
    > +            SynchronizationScope SynchScope,
    > +            BasicBlock *InsertAtEnd);
    > +
    >
    > -
    > -  /// isVolatile - Return true if this is a load from a volatile memory
    > +  /// isVolatile - Return true if this is a store to a volatile memory
    >     /// location.
    >     ///
    >     bool isVolatile() const { return getSubclassDataFromInstruction()&  1; }
    >
    > -  /// setVolatile - Specify whether this is a volatile load or not.
    > +  /// setVolatile - Specify whether this is a volatile store or not.
    >     ///
    >     void setVolatile(bool V) {
    >       setInstructionSubclassData((getSubclassDataFromInstruction()&  ~1) |
    > @@ -247,11 +299,47 @@
    >     /// getAlignment - Return the alignment of the access that is being performed
    >     ///
    >     unsigned getAlignment() const {
    > -    return (1<<  (getSubclassDataFromInstruction()>>  1))>>  1;
    > +    return (1<<  ((getSubclassDataFromInstruction()>>  1)&  31))>>  1;
    >     }
    >
    >     void setAlignment(unsigned Align);
    >
    > +  /// Returns the ordering effect of this store.
    > +  AtomicOrdering getOrdering() const {
    > +    return AtomicOrdering((getSubclassDataFromInstruction()>>  7)&  7);
    > +  }
    > +
    > +  /// Set the ordering constraint on this store.  May not be Acquire or
    > +  /// AcquireRelease.
    > +  void setOrdering(AtomicOrdering Ordering) {
    > +    setInstructionSubclassData((getSubclassDataFromInstruction()&  ~(7<<  7)) |
    > +                               (Ordering<<  7));
    > +  }
    > +
    > +  SynchronizationScope getSynchScope() const {
    > +    return SynchronizationScope((getSubclassDataFromInstruction()>>  6)&  1);
    > +  }
    > +
    > +  /// Specify whether this store instruction is ordered with respect to all
    > +  /// concurrently executing threads, or only with respect to signal handlers
    > +  /// executing in the same thread.
    > +  void setSynchScope(SynchronizationScope xthread) {
    > +    setInstructionSubclassData((getSubclassDataFromInstruction()&  ~(1<<  6)) |
    > +                               (xthread<<  6));
    > +  }
    > +
    > +  bool isAtomic() const { return getOrdering() != NotAtomic; }
    > +  void setAtomic(AtomicOrdering Ordering,
    > +                 SynchronizationScope SynchScope = CrossThread) {
    > +    setOrdering(Ordering);
    > +    setSynchScope(SynchScope);
    > +  }
    > +
    > +  bool isSimple() const { return !isAtomic()&&  !isVolatile(); }
    > +  bool isUnordered() const {
    > +    return getOrdering()<= Unordered&&  !isVolatile();
    > +  }
    > +
    >     Value *getValueOperand() { return getOperand(0); }
    >     const Value *getValueOperand() const { return getOperand(0); }
    >
    > @@ -319,18 +407,8 @@
    >     /// Set the ordering constraint on this fence.  May only be Acquire, Release,
    >     /// AcquireRelease, or SequentiallyConsistent.
    >     void setOrdering(AtomicOrdering Ordering) {
    > -    switch (Ordering) {
    > -    case Acquire:
    > -    case Release:
    > -    case AcquireRelease:
    > -    case SequentiallyConsistent:
    > -      setInstructionSubclassData((getSubclassDataFromInstruction()&  1) |
    > -                                 (Ordering<<  1));
    > -      return;
    > -    default:
    > -      llvm_unreachable("FenceInst ordering must be Acquire, Release,"
    > -                       " AcquireRelease, or SequentiallyConsistent");
    > -    }
    > +    setInstructionSubclassData((getSubclassDataFromInstruction()&  1) |
    > +                               (Ordering<<  1));
    >     }
    >
    >     SynchronizationScope getSynchScope() const {
    > @@ -555,7 +633,7 @@
    >     void setOrdering(AtomicOrdering Ordering) {
    >       assert(Ordering != NotAtomic&&
    >              "atomicrmw instructions can only be atomic.");
    > -    setInstructionSubclassData((getSubclassDataFromInstruction()&  ~28) |
    > +    setInstructionSubclassData((getSubclassDataFromInstruction()&  ~(7<<  2)) |
    >                                  (Ordering<<  2));
    >     }
    >
    > @@ -569,7 +647,7 @@
    >
    >     /// Returns the ordering constraint on this RMW.
    >     AtomicOrdering getOrdering() const {
    > -    return AtomicOrdering((getSubclassDataFromInstruction()&  28)>>  2);
    > +    return AtomicOrdering((getSubclassDataFromInstruction()>>  2)&  7);
    >     }
    >
    >     /// Returns whether this RMW is atomic between threads or only within a
    >
    > Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
    > +++ llvm/trunk/lib/AsmParser/LLParser.cpp Tue Aug  9 18:02:53 2011
    > @@ -2949,16 +2949,23 @@
    >     case lltok::kw_tail:           return ParseCall(Inst, PFS, true);
    >     // Memory.
    >     case lltok::kw_alloca:         return ParseAlloc(Inst, PFS);
    > -  case lltok::kw_load:           return ParseLoad(Inst, PFS, false);
    > -  case lltok::kw_store:          return ParseStore(Inst, PFS, false);
    > +  case lltok::kw_load:           return ParseLoad(Inst, PFS, false, false);
    > +  case lltok::kw_store:          return ParseStore(Inst, PFS, false, false);
    >     case lltok::kw_cmpxchg:        return ParseCmpXchg(Inst, PFS, false);
    >     case lltok::kw_atomicrmw:      return ParseAtomicRMW(Inst, PFS, false);
    >     case lltok::kw_fence:          return ParseFence(Inst, PFS);
    > +  case lltok::kw_atomic: {
    > +    bool isVolatile = EatIfPresent(lltok::kw_volatile);
    > +    if (EatIfPresent(lltok::kw_load))
    > +      return ParseLoad(Inst, PFS, true, isVolatile);
    > +    else if (EatIfPresent(lltok::kw_store))
    > +      return ParseStore(Inst, PFS, true, isVolatile);
    > +  }
    >     case lltok::kw_volatile:
    >       if (EatIfPresent(lltok::kw_load))
    > -      return ParseLoad(Inst, PFS, true);
    > +      return ParseLoad(Inst, PFS, false, true);
    >       else if (EatIfPresent(lltok::kw_store))
    > -      return ParseStore(Inst, PFS, true);
    > +      return ParseStore(Inst, PFS, false, true);
    >       else if (EatIfPresent(lltok::kw_cmpxchg))
    >         return ParseCmpXchg(Inst, PFS, true);
    >       else if (EatIfPresent(lltok::kw_atomicrmw))
    > @@ -3635,34 +3642,48 @@
    >   }
    >
    >   /// ParseLoad
    > -///   ::= 'volatile'? 'load' TypeAndValue (',' OptionalInfo)?
    > +///   ::= 'volatile'? 'load' TypeAndValue (',' 'align' i32)?
    > +//    ::= 'atomic' 'volatile'? 'load' TypeAndValue
    > +//        'singlethread'? AtomicOrdering (',' 'align' i32)?
    >   int LLParser::ParseLoad(Instruction *&Inst, PerFunctionState&PFS,
    > -                        bool isVolatile) {
    > +                        bool isAtomic, bool isVolatile) {
    >     Value *Val; LocTy Loc;
    >     unsigned Alignment = 0;
    >     bool AteExtraComma = false;
    > +  AtomicOrdering Ordering = NotAtomic;
    > +  SynchronizationScope Scope = CrossThread;
    >     if (ParseTypeAndValue(Val, Loc, PFS) ||
    > +      ParseScopeAndOrdering(isAtomic, Scope, Ordering) ||
    >         ParseOptionalCommaAlign(Alignment, AteExtraComma))
    >       return true;
    >
    >     if (!Val->getType()->isPointerTy() ||
    >         !cast(Val->getType())->getElementType()->isFirstClassType())
    >       return Error(Loc, "load operand must be a pointer to a first class type");
    > +  if (isAtomic&&  !Alignment)
    > +    return Error(Loc, "atomic load must have explicit non-zero alignment");
    > +  if (Ordering == Release || Ordering == AcquireRelease)
    > +    return Error(Loc, "atomic load cannot use Release ordering");
    >
    > -  Inst = new LoadInst(Val, "", isVolatile, Alignment);
    > +  Inst = new LoadInst(Val, "", isVolatile, Alignment, Ordering, Scope);
    >     return AteExtraComma ? InstExtraComma : InstNormal;
    >   }
    >
    >   /// ParseStore
    >   ///   ::= 'volatile'? 'store' TypeAndValue ',' TypeAndValue (',' 'align' i32)?
    > +///   ::= 'atomic' 'volatile'? 'store' TypeAndValue ',' TypeAndValue
    > +///       'singlethread'? AtomicOrdering (',' 'align' i32)?
    >   int LLParser::ParseStore(Instruction *&Inst, PerFunctionState&PFS,
    > -                         bool isVolatile) {
    > +                         bool isAtomic, bool isVolatile) {
    >     Value *Val, *Ptr; LocTy Loc, PtrLoc;
    >     unsigned Alignment = 0;
    >     bool AteExtraComma = false;
    > +  AtomicOrdering Ordering = NotAtomic;
    > +  SynchronizationScope Scope = CrossThread;
    >     if (ParseTypeAndValue(Val, Loc, PFS) ||
    >         ParseToken(lltok::comma, "expected ',' after store operand") ||
    >         ParseTypeAndValue(Ptr, PtrLoc, PFS) ||
    > +      ParseScopeAndOrdering(isAtomic, Scope, Ordering) ||
    >         ParseOptionalCommaAlign(Alignment, AteExtraComma))
    >       return true;
    >
    > @@ -3672,8 +3693,12 @@
    >       return Error(Loc, "store operand must be a first class value");
    >     if (cast(Ptr->getType())->getElementType() != Val->getType())
    >       return Error(Loc, "stored value and pointer type do not match");
    > +  if (isAtomic&&  !Alignment)
    > +    return Error(Loc, "atomic store must have explicit non-zero alignment");
    > +  if (Ordering == Acquire || Ordering == AcquireRelease)
    > +    return Error(Loc, "atomic store cannot use Acquire ordering");
    >
    > -  Inst = new StoreInst(Val, Ptr, isVolatile, Alignment);
    > +  Inst = new StoreInst(Val, Ptr, isVolatile, Alignment, Ordering, Scope);
    >     return AteExtraComma ? InstExtraComma : InstNormal;
    >   }
    >
    >
    > Modified: llvm/trunk/lib/AsmParser/LLParser.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.h?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/AsmParser/LLParser.h (original)
    > +++ llvm/trunk/lib/AsmParser/LLParser.h Tue Aug  9 18:02:53 2011
    > @@ -362,8 +362,10 @@
    >       int ParsePHI(Instruction *&I, PerFunctionState&PFS);
    >       bool ParseCall(Instruction *&I, PerFunctionState&PFS, bool isTail);
    >       int ParseAlloc(Instruction *&I, PerFunctionState&PFS);
    > -    int ParseLoad(Instruction *&I, PerFunctionState&PFS, bool isVolatile);
    > -    int ParseStore(Instruction *&I, PerFunctionState&PFS, bool isVolatile);
    > +    int ParseLoad(Instruction *&I, PerFunctionState&PFS,
    > +                  bool isAtomic, bool isVolatile);
    > +    int ParseStore(Instruction *&I, PerFunctionState&PFS,
    > +                   bool isAtomic, bool isVolatile);
    >       int ParseCmpXchg(Instruction *&I, PerFunctionState&PFS, bool isVolatile);
    >       int ParseAtomicRMW(Instruction *&I, PerFunctionState&PFS, bool isVolatile);
    >       int ParseFence(Instruction *&I, PerFunctionState&PFS);
    >
    > Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
    > +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Tue Aug  9 18:02:53 2011
    > @@ -2567,6 +2567,28 @@
    >         InstructionList.push_back(I);
    >         break;
    >       }
    > +    case bitc::FUNC_CODE_INST_LOADATOMIC: {
    > +       // LOADATOMIC: [opty, op, align, vol, ordering, synchscope]
    > +      unsigned OpNum = 0;
    > +      Value *Op;
    > +      if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
    > +          OpNum+4 != Record.size())
    > +        return Error("Invalid LOADATOMIC record");
    > +
    > +
    > +      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
    > +      if (Ordering == NotAtomic || Ordering == Release ||
    > +          Ordering == AcquireRelease)
    > +        return Error("Invalid LOADATOMIC record");
    > +      if (Ordering != NotAtomic&&  Record[OpNum] == 0)
    > +        return Error("Invalid LOADATOMIC record");
    > +      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
    > +
    > +      I = new LoadInst(Op, "", Record[OpNum+1], (1<<  Record[OpNum])>>  1,
    > +                       Ordering, SynchScope);
    > +      InstructionList.push_back(I);
    > +      break;
    > +    }
    >       case bitc::FUNC_CODE_INST_STORE: { // STORE2:[ptrty, ptr, val, align, vol]
    >         unsigned OpNum = 0;
    >         Value *Val, *Ptr;
    > @@ -2580,6 +2602,29 @@
    >         InstructionList.push_back(I);
    >         break;
    >       }
    > +    case bitc::FUNC_CODE_INST_STOREATOMIC: {
    > +      // STOREATOMIC: [ptrty, ptr, val, align, vol, ordering, synchscope]
    > +      unsigned OpNum = 0;
    > +      Value *Val, *Ptr;
    > +      if (getValueTypePair(Record, OpNum, NextValueNo, Ptr) ||
    > +          getValue(Record, OpNum,
    > +                    cast(Ptr->getType())->getElementType(), Val) ||
    > +          OpNum+4 != Record.size())
    > +        return Error("Invalid STOREATOMIC record");
    > +
    > +      AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
    > +      if (Ordering == NotAtomic || Ordering == Release ||
    > +          Ordering == AcquireRelease)
    > +        return Error("Invalid STOREATOMIC record");
    > +      SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
    > +      if (Ordering != NotAtomic&&  Record[OpNum] == 0)
    > +        return Error("Invalid STOREATOMIC record");
    > +
    > +      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1<<  Record[OpNum])>>  1,
    > +                        Ordering, SynchScope);
    > +      InstructionList.push_back(I);
    > +      break;
    > +    }
    >       case bitc::FUNC_CODE_INST_CMPXCHG: {
    >         // CMPXCHG:[ptrty, ptr, cmp, new, vol, ordering, synchscope]
    >         unsigned OpNum = 0;
    > @@ -2592,7 +2637,7 @@
    >             OpNum+3 != Record.size())
    >           return Error("Invalid CMPXCHG record");
    >         AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+1]);
    > -      if (Ordering == NotAtomic)
    > +      if (Ordering == NotAtomic || Ordering == Unordered)
    >           return Error("Invalid CMPXCHG record");
    >         SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+2]);
    >         I = new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope);
    > @@ -2614,7 +2659,7 @@
    >             Operation>  AtomicRMWInst::LAST_BINOP)
    >           return Error("Invalid ATOMICRMW record");
    >         AtomicOrdering Ordering = GetDecodedOrdering(Record[OpNum+2]);
    > -      if (Ordering == NotAtomic)
    > +      if (Ordering == NotAtomic || Ordering == Unordered)
    >           return Error("Invalid ATOMICRMW record");
    >         SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
    >         I = new AtomicRMWInst(Operation, Ptr, Val, Ordering, SynchScope);
    >
    > Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
    > +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Tue Aug  9 18:02:53 2011
    > @@ -1175,19 +1175,34 @@
    >       break;
    >
    >     case Instruction::Load:
    > -    Code = bitc::FUNC_CODE_INST_LOAD;
    > -    if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))  // ptr
    > -      AbbrevToUse = FUNCTION_INST_LOAD_ABBREV;
    > -
    > +    if (cast(I).isAtomic()) {
    > +      Code = bitc::FUNC_CODE_INST_LOADATOMIC;
    > +      PushValueAndType(I.getOperand(0), InstID, Vals, VE);
    > +    } else {
    > +      Code = bitc::FUNC_CODE_INST_LOAD;
    > +      if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))  // ptr
    > +        AbbrevToUse = FUNCTION_INST_LOAD_ABBREV;
    > +    }
    >       Vals.push_back(Log2_32(cast(I).getAlignment())+1);
    >       Vals.push_back(cast(I).isVolatile());
    > +    if (cast(I).isAtomic()) {
    > +      Vals.push_back(GetEncodedOrdering(cast(I).getOrdering()));
    > +      Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope()));
    > +    }
    >       break;
    >     case Instruction::Store:
    > -    Code = bitc::FUNC_CODE_INST_STORE;
    > +    if (cast(I).isAtomic())
    > +      Code = bitc::FUNC_CODE_INST_STOREATOMIC;
    > +    else
    > +      Code = bitc::FUNC_CODE_INST_STORE;
    >       PushValueAndType(I.getOperand(1), InstID, Vals, VE);  // ptrty + ptr
    >       Vals.push_back(VE.getValueID(I.getOperand(0)));       // val.
    >       Vals.push_back(Log2_32(cast(I).getAlignment())+1);
    >       Vals.push_back(cast(I).isVolatile());
    > +    if (cast(I).isAtomic()) {
    > +      Vals.push_back(GetEncodedOrdering(cast(I).getOrdering()));
    > +      Vals.push_back(GetEncodedSynchScope(cast(I).getSynchScope()));
    > +    }
    >       break;
    >     case Instruction::AtomicCmpXchg:
    >       Code = bitc::FUNC_CODE_INST_CMPXCHG;
    >
    > Modified: llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp (original)
    > +++ llvm/trunk/lib/Transforms/Scalar/LowerAtomic.cpp Tue Aug  9 18:02:53 2011
    > @@ -190,6 +190,16 @@
    >     return true;
    >   }
    >
    > +static bool LowerLoadInst(LoadInst *LI) {
    > +  LI->setAtomic(NotAtomic);
    > +  return true;
    > +}
    > +
    > +static bool LowerStoreInst(StoreInst *SI) {
    > +  SI->setAtomic(NotAtomic);
    > +  return true;
    > +}
    > +
    >   namespace {
    >     struct LowerAtomic : public BasicBlockPass {
    >       static char ID;
    > @@ -208,6 +218,13 @@
    >             Changed |= LowerAtomicCmpXchgInst(CXI);
    >           else if (AtomicRMWInst *RMWI = dyn_cast(Inst))
    >             Changed |= LowerAtomicRMWInst(RMWI);
    > +        else if (LoadInst *LI = dyn_cast(Inst)) {
    > +          if (LI->isAtomic())
    > +            LowerLoadInst(LI);
    > +        } else if (StoreInst *SI = dyn_cast(Inst)) {
    > +          if (SI->isAtomic())
    > +            LowerStoreInst(SI);
    > +        }
    >         }
    >         return Changed;
    >       }
    >
    > Modified: llvm/trunk/lib/VMCore/AsmWriter.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/AsmWriter.cpp?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/VMCore/AsmWriter.cpp (original)
    > +++ llvm/trunk/lib/VMCore/AsmWriter.cpp Tue Aug  9 18:02:53 2011
    > @@ -1659,14 +1659,18 @@
    >         Out<<  '%'<<  SlotNum<<  " = ";
    >     }
    >
    > +  // If this is an atomic load or store, print out the atomic marker.
    > +  if ((isa(I)&&  cast(I).isAtomic()) ||
    > +      (isa(I)&&  cast(I).isAtomic()))
    > +    Out<<  "atomic ";
    > +
    >     // If this is a volatile load or store, print out the volatile marker.
    >     if ((isa(I)&&  cast(I).isVolatile()) ||
    > -      (isa(I)&&  cast(I).isVolatile())) {
    > -      Out<<  "volatile ";
    > -  } else if (isa(I)&&  cast(I).isTailCall()) {
    > -    // If this is a call, check if it's a tail call.
    > +      (isa(I)&&  cast(I).isVolatile()))
    > +    Out<<  "volatile ";
    > +
    > +  if (isa(I)&&  cast(I).isTailCall())
    >       Out<<  "tail ";
    > -  }
    >
    >     // Print out the opcode...
    >     Out<<  I.getOpcodeName();
    > @@ -1913,11 +1917,17 @@
    >       }
    >     }
    >
    > -  // Print post operand alignment for load/store.
    > -  if (isa(I)&&  cast(I).getAlignment()) {
    > -    Out<<  ", align "<<  cast(I).getAlignment();
    > -  } else if (isa(I)&&  cast(I).getAlignment()) {
    > -    Out<<  ", align "<<  cast(I).getAlignment();
    > +  // Print atomic ordering/alignment for memory operations
    > +  if (const LoadInst *LI = dyn_cast(&I)) {
    > +    if (LI->isAtomic())
    > +      writeAtomic(LI->getOrdering(), LI->getSynchScope());
    > +    if (LI->getAlignment())
    > +      Out<<  ", align "<<  LI->getAlignment();
    > +  } else if (const StoreInst *SI = dyn_cast(&I)) {
    > +    if (SI->isAtomic())
    > +      writeAtomic(SI->getOrdering(), SI->getSynchScope());
    > +    if (SI->getAlignment())
    > +      Out<<  ", align "<<  SI->getAlignment();
    >     } else if (const AtomicCmpXchgInst *CXI = dyn_cast(&I)) {
    >       writeAtomic(CXI->getOrdering(), CXI->getSynchScope());
    >     } else if (const AtomicRMWInst *RMWI = dyn_cast(&I)) {
    >
    > Modified: llvm/trunk/lib/VMCore/Instructions.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Instructions.cpp?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/VMCore/Instructions.cpp (original)
    > +++ llvm/trunk/lib/VMCore/Instructions.cpp Tue Aug  9 18:02:53 2011
    > @@ -822,6 +822,8 @@
    >   void LoadInst::AssertOK() {
    >     assert(getOperand(0)->getType()->isPointerTy()&&
    >            "Ptr must have pointer type.");
    > +  assert(!(isAtomic()&&  getAlignment() == 0)&&
    > +         "Alignment required for atomic load");
    >   }
    >
    >   LoadInst::LoadInst(Value *Ptr, const Twine&Name, Instruction *InsertBef)
    > @@ -829,6 +831,7 @@
    >                        Load, Ptr, InsertBef) {
    >     setVolatile(false);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     setName(Name);
    >   }
    > @@ -838,6 +841,7 @@
    >                        Load, Ptr, InsertAE) {
    >     setVolatile(false);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     setName(Name);
    >   }
    > @@ -848,6 +852,18 @@
    >                        Load, Ptr, InsertBef) {
    >     setVolatile(isVolatile);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    > +  AssertOK();
    > +  setName(Name);
    > +}
    > +
    > +LoadInst::LoadInst(Value *Ptr, const Twine&Name, bool isVolatile,
    > +                   BasicBlock *InsertAE)
    > +  : UnaryInstruction(cast(Ptr->getType())->getElementType(),
    > +                     Load, Ptr, InsertAE) {
    > +  setVolatile(isVolatile);
    > +  setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     setName(Name);
    >   }
    > @@ -858,6 +874,7 @@
    >                        Load, Ptr, InsertBef) {
    >     setVolatile(isVolatile);
    >     setAlignment(Align);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     setName(Name);
    >   }
    > @@ -868,27 +885,43 @@
    >                        Load, Ptr, InsertAE) {
    >     setVolatile(isVolatile);
    >     setAlignment(Align);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     setName(Name);
    >   }
    >
    > -LoadInst::LoadInst(Value *Ptr, const Twine&Name, bool isVolatile,
    > +LoadInst::LoadInst(Value *Ptr, const Twine&Name, bool isVolatile,
    > +                   unsigned Align, AtomicOrdering Order,
    > +                   SynchronizationScope SynchScope,
    > +                   Instruction *InsertBef)
    > +  : UnaryInstruction(cast(Ptr->getType())->getElementType(),
    > +                     Load, Ptr, InsertBef) {
    > +  setVolatile(isVolatile);
    > +  setAlignment(Align);
    > +  setAtomic(Order, SynchScope);
    > +  AssertOK();
    > +  setName(Name);
    > +}
    > +
    > +LoadInst::LoadInst(Value *Ptr, const Twine&Name, bool isVolatile,
    > +                   unsigned Align, AtomicOrdering Order,
    > +                   SynchronizationScope SynchScope,
    >                      BasicBlock *InsertAE)
    >     : UnaryInstruction(cast(Ptr->getType())->getElementType(),
    >                        Load, Ptr, InsertAE) {
    >     setVolatile(isVolatile);
    > -  setAlignment(0);
    > +  setAlignment(Align);
    > +  setAtomic(Order, SynchScope);
    >     AssertOK();
    >     setName(Name);
    >   }
    >
    > -
    > -
    >   LoadInst::LoadInst(Value *Ptr, const char *Name, Instruction *InsertBef)
    >     : UnaryInstruction(cast(Ptr->getType())->getElementType(),
    >                        Load, Ptr, InsertBef) {
    >     setVolatile(false);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     if (Name&&  Name[0]) setName(Name);
    >   }
    > @@ -898,6 +931,7 @@
    >                        Load, Ptr, InsertAE) {
    >     setVolatile(false);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     if (Name&&  Name[0]) setName(Name);
    >   }
    > @@ -908,6 +942,7 @@
    >                      Load, Ptr, InsertBef) {
    >     setVolatile(isVolatile);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     if (Name&&  Name[0]) setName(Name);
    >   }
    > @@ -918,6 +953,7 @@
    >                        Load, Ptr, InsertAE) {
    >     setVolatile(isVolatile);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >     if (Name&&  Name[0]) setName(Name);
    >   }
    > @@ -926,7 +962,7 @@
    >     assert((Align&  (Align-1)) == 0&&  "Alignment is not a power of 2!");
    >     assert(Align<= MaximumAlignment&&
    >            "Alignment is greater than MaximumAlignment!");
    > -  setInstructionSubclassData((getSubclassDataFromInstruction()&  1) |
    > +  setInstructionSubclassData((getSubclassDataFromInstruction()&  ~(31<<  1)) |
    >                                ((Log2_32(Align)+1)<<1));
    >     assert(getAlignment() == Align&&  "Alignment representation error!");
    >   }
    > @@ -942,6 +978,8 @@
    >     assert(getOperand(0)->getType() ==
    >                    cast(getOperand(1)->getType())->getElementType()
    >            &&  "Ptr must be a pointer to Val type!");
    > +  assert(!(isAtomic()&&  getAlignment() == 0)&&
    > +         "Alignment required for atomic load");
    >   }
    >
    >
    > @@ -954,6 +992,7 @@
    >     Op<1>() = addr;
    >     setVolatile(false);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >   }
    >
    > @@ -966,6 +1005,7 @@
    >     Op<1>() = addr;
    >     setVolatile(false);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >   }
    >
    > @@ -979,6 +1019,7 @@
    >     Op<1>() = addr;
    >     setVolatile(isVolatile);
    >     setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >   }
    >
    > @@ -992,6 +1033,37 @@
    >     Op<1>() = addr;
    >     setVolatile(isVolatile);
    >     setAlignment(Align);
    > +  setAtomic(NotAtomic);
    > +  AssertOK();
    > +}
    > +
    > +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
    > +                     unsigned Align, AtomicOrdering Order,
    > +                     SynchronizationScope SynchScope,
    > +                     Instruction *InsertBefore)
    > +  : Instruction(Type::getVoidTy(val->getContext()), Store,
    > +                OperandTraits::op_begin(this),
    > +                OperandTraits::operands(this),
    > +                InsertBefore) {
    > +  Op<0>() = val;
    > +  Op<1>() = addr;
    > +  setVolatile(isVolatile);
    > +  setAlignment(Align);
    > +  setAtomic(Order, SynchScope);
    > +  AssertOK();
    > +}
    > +
    > +StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
    > +                     BasicBlock *InsertAtEnd)
    > +  : Instruction(Type::getVoidTy(val->getContext()), Store,
    > +                OperandTraits::op_begin(this),
    > +                OperandTraits::operands(this),
    > +                InsertAtEnd) {
    > +  Op<0>() = val;
    > +  Op<1>() = addr;
    > +  setVolatile(isVolatile);
    > +  setAlignment(0);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >   }
    >
    > @@ -1005,10 +1077,13 @@
    >     Op<1>() = addr;
    >     setVolatile(isVolatile);
    >     setAlignment(Align);
    > +  setAtomic(NotAtomic);
    >     AssertOK();
    >   }
    >
    >   StoreInst::StoreInst(Value *val, Value *addr, bool isVolatile,
    > +                     unsigned Align, AtomicOrdering Order,
    > +                     SynchronizationScope SynchScope,
    >                        BasicBlock *InsertAtEnd)
    >     : Instruction(Type::getVoidTy(val->getContext()), Store,
    >                   OperandTraits::op_begin(this),
    > @@ -1017,7 +1092,8 @@
    >     Op<0>() = val;
    >     Op<1>() = addr;
    >     setVolatile(isVolatile);
    > -  setAlignment(0);
    > +  setAlignment(Align);
    > +  setAtomic(Order, SynchScope);
    >     AssertOK();
    >   }
    >
    > @@ -1025,7 +1101,7 @@
    >     assert((Align&  (Align-1)) == 0&&  "Alignment is not a power of 2!");
    >     assert(Align<= MaximumAlignment&&
    >            "Alignment is greater than MaximumAlignment!");
    > -  setInstructionSubclassData((getSubclassDataFromInstruction()&  1) |
    > +  setInstructionSubclassData((getSubclassDataFromInstruction()&  ~(31<<  1)) |
    >                                ((Log2_32(Align)+1)<<  1));
    >     assert(getAlignment() == Align&&  "Alignment representation error!");
    >   }
    > @@ -3158,14 +3234,14 @@
    >   }
    >
    >   LoadInst *LoadInst::clone_impl() const {
    > -  return new LoadInst(getOperand(0),
    > -                      Twine(), isVolatile(),
    > -                      getAlignment());
    > +  return new LoadInst(getOperand(0), Twine(), isVolatile(),
    > +                      getAlignment(), getOrdering(), getSynchScope());
    >   }
    >
    >   StoreInst *StoreInst::clone_impl() const {
    > -  return new StoreInst(getOperand(0), getOperand(1),
    > -                       isVolatile(), getAlignment());
    > +  return new StoreInst(getOperand(0), getOperand(1),isVolatile(),
    
    Missing space after comma.
    
    Nick
    
    > +                       getAlignment(), getOrdering(), getSynchScope());
    > +
    >   }
    >
    >   AtomicCmpXchgInst *AtomicCmpXchgInst::clone_impl() const {
    >
    > Modified: llvm/trunk/lib/VMCore/Verifier.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Verifier.cpp?rev=137170&r1=137169&r2=137170&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/VMCore/Verifier.cpp (original)
    > +++ llvm/trunk/lib/VMCore/Verifier.cpp Tue Aug  9 18:02:53 2011
    > @@ -1297,6 +1297,15 @@
    >     Type *ElTy = PTy->getElementType();
    >     Assert2(ElTy == LI.getType(),
    >             "Load result type does not match pointer operand type!",&LI, ElTy);
    > +  if (LI.isAtomic()) {
    > +    Assert1(LI.getOrdering() != Release&&  LI.getOrdering() != AcquireRelease,
    > +            "Load cannot have Release ordering",&LI);
    > +    Assert1(LI.getAlignment() != 0,
    > +            "Atomic load must specify explicit alignment",&LI);
    > +  } else {
    > +    Assert1(LI.getSynchScope() == CrossThread,
    > +            "Non-atomic load cannot have SynchronizationScope specified",&LI);
    > +  }
    >     visitInstruction(LI);
    >   }
    >
    > @@ -1307,6 +1316,15 @@
    >     Assert2(ElTy == SI.getOperand(0)->getType(),
    >             "Stored value type does not match pointer operand type!",
    >             &SI, ElTy);
    > +  if (SI.isAtomic()) {
    > +    Assert1(SI.getOrdering() != Acquire&&  SI.getOrdering() != AcquireRelease,
    > +            "Store cannot have Acquire ordering",&SI);
    > +    Assert1(SI.getAlignment() != 0,
    > +            "Atomic store must specify explicit alignment",&SI);
    > +  } else {
    > +    Assert1(SI.getSynchScope() == CrossThread,
    > +            "Non-atomic store cannot have SynchronizationScope specified",&SI);
    > +  }
    >     visitInstruction(SI);
    >   }
    >
    >
    >
    > _______________________________________________
    > llvm-commits mailing list
    > llvm-commits at cs.uiuc.edu
    > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
    >
    
    
    From bob.wilson at apple.com  Wed Aug 10 00:02:22 2011
    From: bob.wilson at apple.com (Bob Wilson)
    Date: Wed, 10 Aug 2011 05:02:22 -0000
    Subject: [llvm-commits] [llvm] r137204 -
    	/llvm/trunk/lib/Support/Unix/Host.inc
    Message-ID: <20110810050222.8888F2A6C12C@llvm.org>
    
    Author: bwilson
    Date: Wed Aug 10 00:02:22 2011
    New Revision: 137204
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137204&view=rev
    Log:
    Clarify a comment.
    
    Modified:
        llvm/trunk/lib/Support/Unix/Host.inc
    
    Modified: llvm/trunk/lib/Support/Unix/Host.inc
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Host.inc?rev=137204&r1=137203&r2=137204&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Support/Unix/Host.inc (original)
    +++ llvm/trunk/lib/Support/Unix/Host.inc Wed Aug 10 00:02:22 2011
    @@ -30,7 +30,9 @@
       struct utsname info;
     
     #ifdef __APPLE__
    -  // Recognize UNAME_RELEASE environment variable to match Darwin uname.
    +  // Recognize UNAME_RELEASE environment variable to match Darwin's uname,
    +  // where the value of this variable sets the OS release version
    +  // reported by "uname -r".
       const char *UnameOverride = ::getenv("UNAME_RELEASE");
       if (UnameOverride && UnameOverride[0] != '\0')
         return UnameOverride;
    
    
    
    From nicholas at mxc.ca  Wed Aug 10 00:06:37 2011
    From: nicholas at mxc.ca (Nick Lewycky)
    Date: Tue, 09 Aug 2011 22:06:37 -0700
    Subject: [llvm-commits] [llvm] r137144 - in /llvm/trunk: lib/Target/ARM/
     lib/Target/ARM/Disassembler/ test/MC/Disassembler/ARM/ utils/TableGen/
    In-Reply-To: <20110809205519.AA7252A6C12E@llvm.org>
    References: <20110809205519.AA7252A6C12E@llvm.org>
    Message-ID: <4E4211DD.8080909@mxc.ca>
    
    Owen Anderson wrote:
    > Author: resistor
    > Date: Tue Aug  9 15:55:18 2011
    > New Revision: 137144
    >
    > URL: http://llvm.org/viewvc/llvm-project?rev=137144&view=rev
    > Log:
    > Replace the existing ARM disassembler with a new one based on the FixedLenDecoderEmitter.
    > This new disassembler can correctly decode all the testcases that the old one did, though
    > some "expected failure" testcases are XFAIL'd for now because it is not (yet) as strict in
    > operand checking as the old one was.
    >
    > Removed:
    >      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/lib/Target/ARM/ARMInstrFormats.td
    >      llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    >      llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
    >      llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
    >      llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    >      llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp
    >      llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.h
    >      llvm/trunk/lib/Target/ARM/Disassembler/CMakeLists.txt
    >      llvm/trunk/lib/Target/ARM/Makefile
    >      llvm/trunk/test/MC/Disassembler/ARM/arm-tests.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-BFI-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-Bcc-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS2p-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-CPS3p-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-DMB-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-DSB-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-LDC-form-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRB_POST-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRD_PRE-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-LDRT-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-LSL-regform.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-MCR-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVTi16-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVr-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-LSL-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-MOVs-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-MSRi-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-RFEorLDMIA-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-RSC-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-SBFX-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-SMLAD-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-SRS-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-SSAT-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-STMIA_UPD-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-STRBrs-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-SXTB-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-UMAAL-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-UQADD8-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD1DUPq8_UPD-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-VLD3DUPd32_UPD-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-VLDMSDB_UPD-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-VQADD-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-VST2b32_UPD-arm.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2Bcc-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRBT-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDREXD-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi12-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2LDRSHi8-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STRD_PRE-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXB-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STREXD-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/invalid-t2STR_POST-thumb.txt
    >      llvm/trunk/test/MC/Disassembler/ARM/neon-tests.txt
    >      llvm/trunk/utils/TableGen/DisassemblerEmitter.cpp
    >
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Tue Aug  9 15:55:18 2011
    > @@ -152,6 +152,7 @@
    >                                        (ops (i32 14), (i32 zero_reg))>  {
    >     let PrintMethod = "printPredicateOperand";
    >     let ParserMatchClass = CondCodeOperand;
    > +	let DecoderMethod = "DecodePredicateOperand";
    
    Tab.
    
    >   }
    >
    >   // Conditional code result for instructions whose 's' bit is set, e.g. subs.
    > @@ -160,6 +161,7 @@
    >     let EncoderMethod = "getCCOutOpValue";
    >     let PrintMethod = "printSBitModifierOperand";
    >     let ParserMatchClass = CCOutOperand;
    > +	let DecoderMethod = "DecodeCCOutOperand";
    
    Tab.
    
    >   }
    >
    >   // Same as cc_out except it defaults to setting CPSR.
    > @@ -167,6 +169,7 @@
    >     let EncoderMethod = "getCCOutOpValue";
    >     let PrintMethod = "printSBitModifierOperand";
    >     let ParserMatchClass = CCOutOperand;
    > +	let DecoderMethod = "DecodeCCOutOperand";
    
    Tab.
    
    >   }
    >
    >   // ARM special operands for disassembly only.
    > @@ -199,15 +202,19 @@
    >   //     64       64 -  is encoded in imm6<5:0>
    >   def shr_imm8  : Operand  {
    >     let EncoderMethod = "getShiftRight8Imm";
    > +  let DecoderMethod = "DecodeShiftRight8Imm";
    >   }
    >   def shr_imm16 : Operand  {
    >     let EncoderMethod = "getShiftRight16Imm";
    > +  let DecoderMethod = "DecodeShiftRight16Imm";
    >   }
    >   def shr_imm32 : Operand  {
    >     let EncoderMethod = "getShiftRight32Imm";
    > +  let DecoderMethod = "DecodeShiftRight32Imm";
    >   }
    >   def shr_imm64 : Operand  {
    >     let EncoderMethod = "getShiftRight64Imm";
    > +  let DecoderMethod = "DecodeShiftRight64Imm";
    >   }
    >
    >   //===----------------------------------------------------------------------===//
    > @@ -579,6 +586,8 @@
    >     let Inst{11-8}  = addr{7-4};    // imm7_4/zero
    >     let Inst{7-4}   = op;
    >     let Inst{3-0}   = addr{3-0};    // imm3_0/Rm
    > +
    > +  let DecoderMethod = "DecodeAddrMode3Instruction";
    >   }
    >
    >   class AI3ldstidx  op, bit op20, bit isLd, bit isPre, dag oops, dag iops,
    > @@ -1265,6 +1274,7 @@
    >     let AsmString = !strconcat(opc, "${p}", asm);
    >     let Pattern = pattern;
    >     let PostEncoderMethod = "VFPThumb2PostEncoder";
    > +  let DecoderNamespace = "VFP";
    >     list  Predicates = [HasVFP2];
    >   }
    >
    > @@ -1280,6 +1290,7 @@
    >     let AsmString = asm;
    >     let Pattern = pattern;
    >     let PostEncoderMethod = "VFPThumb2PostEncoder";
    > +  let DecoderNamespace = "VFP";
    >     list  Predicates = [HasVFP2];
    >   }
    >
    > @@ -1597,6 +1608,7 @@
    >     let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm);
    >     let Pattern = pattern;
    >     list  Predicates = [HasNEON];
    > +  let DecoderNamespace = "NEON";
    >   }
    >
    >   // Same as NeonI except it does not have a "data type" specifier.
    > @@ -1609,6 +1621,7 @@
    >     let AsmString = !strconcat(opc, "${p}", "\t", asm);
    >     let Pattern = pattern;
    >     list  Predicates = [HasNEON];
    > +  let DecoderNamespace = "NEON";
    >   }
    >
    >   class NLdSt  op21_20, bits<4>  op11_8, bits<4>  op7_4,
    > @@ -1700,6 +1713,7 @@
    >     let Inst{24}    = SIMM{7};
    >     let Inst{18-16} = SIMM{6-4};
    >     let Inst{3-0}   = SIMM{3-0};
    > +  let DecoderMethod = "DecodeNEONModImmInstruction";
    >   }
    >
    >   // NEON 2 vector register format.
    >
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue Aug  9 15:55:18 2011
    > @@ -315,6 +315,7 @@
    >   def brtarget : Operand  {
    >     let EncoderMethod = "getBranchTargetOpValue";
    >     let OperandType = "OPERAND_PCREL";
    > +  let DecoderMethod = "DecodeT2BROperand";
    >   }
    >
    >   // FIXME: get rid of this one?
    > @@ -343,6 +344,7 @@
    >     // Encoded the same as branch targets.
    >     let EncoderMethod = "getARMBranchTargetOpValue";
    >     let OperandType = "OPERAND_PCREL";
    > +	let DecoderMethod = "DecodeBLTargetOperand";
    
    Tab.
    
    >   }
    >
    >
    > @@ -352,6 +354,7 @@
    >     let EncoderMethod = "getRegisterListOpValue";
    >     let ParserMatchClass = RegListAsmOperand;
    >     let PrintMethod = "printRegisterList";
    > +  let DecoderMethod = "DecodeRegListOperand";
    >   }
    >
    >   def DPRRegListAsmOperand : AsmOperandClass { let Name = "DPRRegList"; }
    > @@ -359,6 +362,7 @@
    >     let EncoderMethod = "getRegisterListOpValue";
    >     let ParserMatchClass = DPRRegListAsmOperand;
    >     let PrintMethod = "printRegisterList";
    > +  let DecoderMethod = "DecodeDPRRegListOperand";
    >   }
    >
    >   def SPRRegListAsmOperand : AsmOperandClass { let Name = "SPRRegList"; }
    > @@ -366,6 +370,7 @@
    >     let EncoderMethod = "getRegisterListOpValue";
    >     let ParserMatchClass = SPRRegListAsmOperand;
    >     let PrintMethod = "printRegisterList";
    > +  let DecoderMethod = "DecodeSPRRegListOperand";
    >   }
    >
    >   // An operand for the CONSTPOOL_ENTRY pseudo-instruction.
    > @@ -385,6 +390,7 @@
    >
    >   def neon_vcvt_imm32 : Operand  {
    >     let EncoderMethod = "getNEONVcvtImm32OpValue";
    > +  let DecoderMethod = "DecodeVCVTImmOperand";
    >   }
    >
    >   // rot_imm: An integer that encodes a rotate amount. Must be 8, 16, or 24.
    > @@ -431,6 +437,7 @@
    >                                   [shl, srl, sra, rotr]>  {
    >     let EncoderMethod = "getSORegRegOpValue";
    >     let PrintMethod = "printSORegRegOperand";
    > +  let DecoderMethod = "DecodeSORegRegOperand";
    >     let ParserMatchClass = ShiftedRegAsmOperand;
    >     let MIOperandInfo = (ops GPR, GPR, i32imm);
    >   }
    > @@ -441,6 +448,7 @@
    >                                   [shl, srl, sra, rotr]>  {
    >     let EncoderMethod = "getSORegImmOpValue";
    >     let PrintMethod = "printSORegImmOperand";
    > +  let DecoderMethod = "DecodeSORegImmOperand";
    >     let ParserMatchClass = ShiftedImmAsmOperand;
    >     let MIOperandInfo = (ops GPR, i32imm);
    >   }
    > @@ -451,6 +459,7 @@
    >                                     [shl,srl,sra,rotr]>  {
    >     let EncoderMethod = "getSORegRegOpValue";
    >     let PrintMethod = "printSORegRegOperand";
    > +  let DecoderMethod = "DecodeSORegRegOperand";
    >     let MIOperandInfo = (ops GPR, GPR, i32imm);
    >   }
    >
    > @@ -460,6 +469,7 @@
    >                                     [shl,srl,sra,rotr]>  {
    >     let EncoderMethod = "getSORegImmOpValue";
    >     let PrintMethod = "printSORegImmOperand";
    > +  let DecoderMethod = "DecodeSORegImmOperand";
    >     let MIOperandInfo = (ops GPR, i32imm);
    >   }
    >
    > @@ -472,6 +482,7 @@
    >     }]>  {
    >     let EncoderMethod = "getSOImmOpValue";
    >     let ParserMatchClass = SOImmAsmOperand;
    > +	let DecoderMethod = "DecodeSOImmOperand";
    
    Tab.
    
    >   }
    >
    >   // Break so_imm's up into two pieces.  This handles immediates with up to 16
    > @@ -552,6 +563,7 @@
    >   }]>  {
    >     let EncoderMethod = "getBitfieldInvertedMaskOpValue";
    >     let PrintMethod = "printBitfieldInvMaskImmOperand";
    > +  let DecoderMethod = "DecodeBitfieldMaskOperand";
    >     let ParserMatchClass = BitfieldAsmOperand;
    >   }
    >
    > @@ -599,6 +611,7 @@
    >
    >     let EncoderMethod = "getAddrModeImm12OpValue";
    >     let PrintMethod = "printAddrModeImm12Operand";
    > +  let DecoderMethod = "DecodeAddrModeImm12Operand";
    >     let ParserMatchClass = MemImm12OffsetAsmOperand;
    >     let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
    >   }
    > @@ -610,6 +623,7 @@
    >     let EncoderMethod = "getLdStSORegOpValue";
    >     // FIXME: Simplify the printer
    >     let PrintMethod = "printAddrMode2Operand";
    > +  let DecoderMethod = "DecodeSORegMemOperand";
    >     let ParserMatchClass = MemRegOffsetAsmOperand;
    >     let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$shift);
    >   }
    > @@ -645,6 +659,7 @@
    >   }
    >   def postidx_reg : Operand  {
    >     let EncoderMethod = "getPostIdxRegOpValue";
    > +  let DecoderMethod = "DecodePostIdxReg";
    >     let PrintMethod = "printPostIdxRegOperand";
    >     let ParserMatchClass = PostIdxRegAsmOperand;
    >     let MIOperandInfo = (ops GPR, i32imm);
    > @@ -707,6 +722,7 @@
    >                   ComplexPattern                                  [], [SDNPWantRoot]>  {
    >     let EncoderMethod = "getAddrMode3OffsetOpValue";
    > +  let DecoderMethod = "DecodeAddrMode3Offset";
    >     let PrintMethod = "printAddrMode3OffsetOperand";
    >     let MIOperandInfo = (ops GPR, i32imm);
    >   }
    > @@ -725,6 +741,7 @@
    >                   ComplexPattern  {
    >     let PrintMethod = "printAddrMode5Operand";
    >     let EncoderMethod = "getAddrMode5OpValue";
    > +  let DecoderMethod = "DecodeAddrMode5Operand";
    >     let ParserMatchClass = AddrMode5AsmOperand;
    >     let MIOperandInfo = (ops GPR:$base, i32imm);
    >   }
    > @@ -736,6 +753,7 @@
    >     let PrintMethod = "printAddrMode6Operand";
    >     let MIOperandInfo = (ops GPR:$addr, i32imm);
    >     let EncoderMethod = "getAddrMode6AddressOpValue";
    > +  let DecoderMethod = "DecodeAddrMode6Operand";
    >   }
    >
    >   def am6offset : Operand,
    > @@ -744,6 +762,7 @@
    >     let PrintMethod = "printAddrMode6OffsetOperand";
    >     let MIOperandInfo = (ops GPR);
    >     let EncoderMethod = "getAddrMode6OffsetOpValue";
    > +  let DecoderMethod = "DecodeGPRRegisterClass";
    >   }
    >
    >   // Special version of addrmode6 to handle alignment encoding for VST1/VLD1
    > @@ -778,6 +797,7 @@
    >   def addr_offset_none : Operand,
    >                          ComplexPattern  {
    >     let PrintMethod = "printAddrMode7Operand";
    > +  let DecoderMethod = "DecodeAddrMode7Operand";
    >     let ParserMatchClass = MemNoOffsetAsmOperand;
    >     let MIOperandInfo = (ops GPR:$base);
    >   }
    > @@ -793,6 +813,7 @@
    >   def p_imm : Operand  {
    >     let PrintMethod = "printPImmediate";
    >     let ParserMatchClass = CoprocNumAsmOperand;
    > +  let DecoderMethod = "DecodeCoprocessor";
    >   }
    >
    >   def CoprocRegAsmOperand : AsmOperandClass {
    > @@ -1654,6 +1675,7 @@
    >                  [/*(ARMbrcond bb:$target, imm:$cc, CCR:$ccr)*/]>  {
    >       bits<24>  target;
    >       let Inst{23-0} = target;
    > +    let DecoderMethod = "DecodeBranchImmInstruction";
    >     }
    >
    >     let isBarrier = 1 in {
    > @@ -1917,6 +1939,7 @@
    >       let Inst{23} = addr{12};
    >       let Inst{19-16} = addr{17-14};
    >       let Inst{11-0} = addr{11-0};
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >       let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
    >     }
    >
    > @@ -1933,6 +1956,8 @@
    >        let Inst{23} = offset{12};
    >        let Inst{19-16} = addr;
    >        let Inst{11-0} = offset{11-0};
    > +
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >      }
    >
    >      def _POST_IMM : AI2ldstidx<1, isByte, 0, (outs GPR:$Rt, GPR:$Rn_wb),
    > @@ -1948,7 +1973,10 @@
    >       let Inst{23} = offset{12};
    >       let Inst{19-16} = addr;
    >       let Inst{11-0} = offset{11-0};
    > +
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >     }
    > +
    >   }
    >
    >   let mayLoad = 1, neverHasSideEffects = 1 in {
    > @@ -2019,20 +2047,39 @@
    >
    >   // LDRT, LDRBT, LDRSBT, LDRHT, LDRSHT are for disassembly only.
    >   let mayLoad = 1, neverHasSideEffects = 1 in {
    > -def LDRT : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
    > -                   (ins addrmode2:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
    > +def LDRTr : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
    > +                   (ins ldst_so_reg:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
    > +                   "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []>  {
    > +  // {17-14}  Rn
    > +  // {13}     1 == Rm, 0 == imm12
    > +  // {12}     isAdd
    > +  // {11-0}   imm12/Rm
    > +  bits<18>  addr;
    > +  let Inst{25} = 1;
    > +  let Inst{23} = addr{12};
    > +  let Inst{21} = 1; // overwrite
    > +  let Inst{19-16} = addr{17-14};
    > +  let Inst{11-5} = addr{11-5};
    > +  let Inst{4} = 0;
    > +  let Inst{3-0} = addr{3-0};
    > +  let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    > +}
    > +def LDRTi : AI2ldstidx<1, 0, 0, (outs GPR:$Rt, GPR:$base_wb),
    > +                   (ins addrmode_imm12:$addr), IndexModePost, LdFrm, IIC_iLoad_ru,
    >                      "ldrt", "\t$Rt, $addr", "$addr.base = $base_wb", []>  {
    >     // {17-14}  Rn
    >     // {13}     1 == Rm, 0 == imm12
    >     // {12}     isAdd
    >     // {11-0}   imm12/Rm
    >     bits<18>  addr;
    > -  let Inst{25} = addr{13};
    > +  let Inst{25} = 0;
    >     let Inst{23} = addr{12};
    >     let Inst{21} = 1; // overwrite
    >     let Inst{19-16} = addr{17-14};
    >     let Inst{11-0} = addr{11-0};
    >     let AsmMatchConverter = "cvtLdWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    >
    >   def LDRBT_POST_REG : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
    > @@ -2049,6 +2096,7 @@
    >     let Inst{21} = 1; // overwrite
    >     let Inst{19-16} = addr;
    >     let Inst{11-0} = offset{11-0};
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    >
    >   def LDRBT_POST_IMM : AI2ldstidx<1, 1, 0, (outs GPR:$Rt, GPR:$Rn_wb),
    > @@ -2065,6 +2113,7 @@
    >     let Inst{21} = 1; // overwrite
    >     let Inst{19-16} = addr;
    >     let Inst{11-0} = offset{11-0};
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    >
    >   multiclass AI3ldrT  op, string opc>  {
    > @@ -2151,6 +2200,8 @@
    >        let Inst{23} = offset{12};
    >        let Inst{19-16} = addr;
    >        let Inst{11-0} = offset{11-0};
    > +
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >      }
    >
    >      def _POST_IMM : AI2ldstidx<0, isByte, 0, (outs GPR:$Rn_wb),
    > @@ -2166,6 +2217,8 @@
    >       let Inst{23} = offset{12};
    >       let Inst{19-16} = addr;
    >       let Inst{11-0} = offset{11-0};
    > +
    > +    let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >     }
    >   }
    >
    > @@ -2287,6 +2340,7 @@
    >     let Inst{21} = 1; // overwrite
    >     let Inst{4} = 0;
    >     let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    >
    >   def STRTi : AI2stridxT<0, 0, (outs GPR:$Rn_wb),
    > @@ -2297,6 +2351,7 @@
    >     let Inst{25} = 0;
    >     let Inst{21} = 1; // overwrite
    >     let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    >
    >
    > @@ -2309,6 +2364,7 @@
    >     let Inst{21} = 1; // overwrite
    >     let Inst{4} = 0;
    >     let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    >
    >   def STRBTi : AI2stridxT<1, 0, (outs GPR:$Rn_wb),
    > @@ -2319,6 +2375,7 @@
    >     let Inst{25} = 0;
    >     let Inst{21} = 1; // overwrite
    >     let AsmMatchConverter = "cvtStWriteBackRegAddrMode2";
    > +  let DecoderMethod = "DecodeAddrMode2IdxInstruction";
    >   }
    >
    >   multiclass AI3strT  op, string opc>  {
    > @@ -2373,6 +2430,8 @@
    >       let Inst{24-23} = 0b01;       // Increment After
    >       let Inst{21}    = 1;          // Writeback
    >       let Inst{20}    = L_bit;
    > +
    > +    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
    >     }
    >     def DA :
    >       AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
    > @@ -2389,6 +2448,8 @@
    >       let Inst{24-23} = 0b00;       // Decrement After
    >       let Inst{21}    = 1;          // Writeback
    >       let Inst{20}    = L_bit;
    > +
    > +    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
    >     }
    >     def DB :
    >       AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
    > @@ -2405,6 +2466,8 @@
    >       let Inst{24-23} = 0b10;       // Decrement Before
    >       let Inst{21}    = 1;          // Writeback
    >       let Inst{20}    = L_bit;
    > +
    > +    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
    >     }
    >     def IB :
    >       AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops),
    > @@ -2421,6 +2484,8 @@
    >       let Inst{24-23} = 0b11;       // Increment Before
    >       let Inst{21}    = 1;          // Writeback
    >       let Inst{20}    = L_bit;
    > +
    > +    let DecoderMethod = "DecodeMemMultipleWritebackInstruction";
    >     }
    >   }
    >
    > @@ -2504,8 +2569,6 @@
    >     let Inst{25} = 0;
    >   }
    >
    > -
    > -
    >   let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in
    >   def MOVi : AsI1<0b1101, (outs GPR:$Rd), (ins so_imm:$imm), DPFrm, IIC_iMOVi,
    >                   "mov", "\t$Rd, $imm", [(set GPR:$Rd, so_imm:$imm)]>, UnaryDP {
    > @@ -3383,6 +3446,7 @@
    >
    >
    >   multiclass AI_smla  {
    > +  let DecoderMethod = "DecodeSMLAInstruction" in {
    >     def BB : AMulxyIa<0b0001000, 0b00, (outs GPR:$Rd),
    >                 (ins GPR:$Rn, GPR:$Rm, GPR:$Ra),
    >                 IIC_iMAC16, !strconcat(opc, "bb"), "\t$Rd, $Rn, $Rm, $Ra",
    > @@ -3425,6 +3489,7 @@
    >                 [(set GPR:$Rd, (add GPR:$Ra, (sra (opnode GPR:$Rn,
    >                                           (sra GPR:$Rm, (i32 16))), (i32 16))))]>,
    >               Requires<[IsARM, HasV5TE]>;
    > +  }
    >   }
    >
    >   defm SMUL : AI_smul<"smul", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
    > @@ -3989,7 +4054,7 @@
    >   }
    >
    >   multiclass LdStCop  op31_28, bit load, dag ops, string opc, string cond>{
    > -
    > +  let DecoderNamespace = "Common" in {
    >     def _OFFSET : ACI<(outs),
    >         !con((ins nohash_imm:$cop, nohash_imm:$CRd, addrmode2:$addr), ops),
    >         !strconcat(opc, cond), "\tp$cop, cr$CRd, $addr">  {
    > @@ -3998,6 +4063,7 @@
    >       let Inst{21} = 0; // W = 0
    >       let Inst{22} = 0; // D = 0
    >       let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >     }
    >
    >     def _PRE : ACI<(outs),
    > @@ -4008,6 +4074,7 @@
    >       let Inst{21} = 1; // W = 1
    >       let Inst{22} = 0; // D = 0
    >       let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >     }
    >
    >     def _POST : ACI<(outs),
    > @@ -4018,6 +4085,7 @@
    >       let Inst{21} = 1; // W = 1
    >       let Inst{22} = 0; // D = 0
    >       let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >     }
    >
    >     def _OPTION : ACI<(outs),
    > @@ -4030,6 +4098,7 @@
    >       let Inst{21} = 0; // W = 0
    >       let Inst{22} = 0; // D = 0
    >       let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >     }
    >
    >     def L_OFFSET : ACI<(outs),
    > @@ -4040,6 +4109,7 @@
    >       let Inst{21} = 0; // W = 0
    >       let Inst{22} = 1; // D = 1
    >       let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >     }
    >
    >     def L_PRE : ACI<(outs),
    > @@ -4051,6 +4121,7 @@
    >       let Inst{21} = 1; // W = 1
    >       let Inst{22} = 1; // D = 1
    >       let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >     }
    >
    >     def L_POST : ACI<(outs),
    > @@ -4063,6 +4134,7 @@
    >       let Inst{21} = 1; // W = 1
    >       let Inst{22} = 1; // D = 1
    >       let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    >     }
    >
    >     def L_OPTION : ACI<(outs),
    > @@ -4076,6 +4148,8 @@
    >       let Inst{21} = 0; // W = 0
    >       let Inst{22} = 1; // D = 1
    >       let Inst{20} = load;
    > +    let DecoderMethod = "DecodeCopMemInstruction";
    > +  }
    >     }
    >   }
    >
    >
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrNEON.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrNEON.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrNEON.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrNEON.td Tue Aug  9 15:55:18 2011
    > @@ -191,6 +191,7 @@
    >             "vld1", Dt, "\\{$Vd\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >   class VLD1Q  op7_4, string Dt>
    >     : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2),
    > @@ -198,6 +199,7 @@
    >             "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def  VLD1d8   : VLD1D<{0,0,0,?}, "8">;
    > @@ -222,6 +224,7 @@
    >             "vld1", Dt, "\\{$Vd\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >   class VLD1QWB  op7_4, string Dt>
    >     : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb),
    > @@ -229,6 +232,7 @@
    >             "vld1", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def VLD1d8_UPD  : VLD1DWB<{0,0,0,?}, "8">;
    > @@ -253,12 +257,14 @@
    >             "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >   class VLD1D3WB  op7_4, string Dt>
    >     : NLdSt<0,0b10,0b0110,op7_4, (outs DPR:$Vd, DPR:$dst2, DPR:$dst3, GPR:$wb),
    >             (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x3u, "vld1", Dt,
    >             "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm", "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def VLD1d8T      : VLD1D3<{0,0,0,?}, "8">;
    > @@ -281,6 +287,7 @@
    >             "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >   class VLD1D4WB  op7_4, string Dt>
    >     : NLdSt<0,0b10,0b0010,op7_4,
    > @@ -289,6 +296,7 @@
    >             "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm", "$Rn.addr = $wb",
    >             []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def VLD1d8Q      : VLD1D4<{0,0,?,?}, "8">;
    > @@ -311,6 +319,7 @@
    >             "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >   class VLD2Q  op7_4, string Dt>
    >     : NLdSt<0, 0b10, 0b0011, op7_4,
    > @@ -319,6 +328,7 @@
    >             "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def  VLD2d8   : VLD2D<0b1000, {0,0,?,?}, "8">;
    > @@ -344,6 +354,7 @@
    >             "vld2", Dt, "\\{$Vd, $dst2\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >   class VLD2QWB  op7_4, string Dt>
    >     : NLdSt<0, 0b10, 0b0011, op7_4,
    > @@ -352,6 +363,7 @@
    >             "vld2", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def VLD2d8_UPD  : VLD2DWB<0b1000, {0,0,?,?}, "8">;
    > @@ -385,6 +397,7 @@
    >             "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def  VLD3d8   : VLD3D<0b0100, {0,0,0,?}, "8">;
    > @@ -403,6 +416,7 @@
    >             "vld3", Dt, "\\{$Vd, $dst2, $dst3\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def VLD3d8_UPD  : VLD3DWB<0b0100, {0,0,0,?}, "8">;
    > @@ -442,6 +456,7 @@
    >             "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def  VLD4d8   : VLD4D<0b0000, {0,0,?,?}, "8">;
    > @@ -460,6 +475,7 @@
    >             "vld4", Dt, "\\{$Vd, $dst2, $dst3, $dst4\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVLDInstruction";
    >   }
    >
    >   def VLD4d8_UPD  : VLD4DWB<0b0000, {0,0,?,?}, "8">;
    > @@ -826,6 +842,7 @@
    >             [(set DPR:$Vd, (Ty (NEONvdup (i32 (LoadOp addrmode6dup:$Rn)))))]>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD1DupInstruction";
    >   }
    >   class VLD1QDUPPseudo  : VLDQPseudo  {
    >     let Pattern = [(set QPR:$dst,
    > @@ -853,6 +870,7 @@
    >             "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD1DupInstruction";
    >   }
    >
    >   def VLD1DUPq8  : VLD1QDUP<{0,0,1,0}, "8">;
    > @@ -865,12 +883,14 @@
    >             (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu,
    >             "vld1", Dt, "\\{$Vd[]\\}, $Rn$Rm", "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD1DupInstruction";
    >   }
    >   class VLD1QDUPWB  op7_4, string Dt>
    >     : NLdSt<1, 0b10, 0b1100, op7_4, (outs DPR:$Vd, DPR:$dst2, GPR:$wb),
    >             (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD1dupu,
    >             "vld1", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD1DupInstruction";
    >   }
    >
    >   def VLD1DUPd8_UPD  : VLD1DUPWB<{0,0,0,0}, "8">;
    > @@ -892,6 +912,7 @@
    >             "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD2DupInstruction";
    >   }
    >
    >   def VLD2DUPd8  : VLD2DUP<{0,0,0,?}, "8">;
    > @@ -913,6 +934,7 @@
    >             (ins addrmode6dup:$Rn, am6offset:$Rm), IIC_VLD2dupu,
    >             "vld2", Dt, "\\{$Vd[], $dst2[]\\}, $Rn$Rm", "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD2DupInstruction";
    >   }
    >
    >   def VLD2DUPd8_UPD  : VLD2DUPWB<{0,0,0,0}, "8">;
    > @@ -934,6 +956,7 @@
    >             "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD3DupInstruction";
    >   }
    >
    >   def VLD3DUPd8  : VLD3DUP<{0,0,0,?}, "8">;
    > @@ -956,6 +979,7 @@
    >             "vld3", Dt, "\\{$Vd[], $dst2[], $dst3[]\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD3DupInstruction";
    >   }
    >
    >   def VLD3DUPd8_UPD  : VLD3DUPWB<{0,0,0,0}, "8">;
    > @@ -978,6 +1002,7 @@
    >             "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD4DupInstruction";
    >   }
    >
    >   def VLD4DUPd8  : VLD4DUP<{0,0,0,?}, "8">;
    > @@ -1001,6 +1026,7 @@
    >             "vld4", Dt, "\\{$Vd[], $dst2[], $dst3[], $dst4[]\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVLD4DupInstruction";
    >   }
    >
    >   def VLD4DUPd8_UPD  : VLD4DUPWB<{0,0,0,0}, "8">;
    > @@ -1046,6 +1072,7 @@
    >             IIC_VST1, "vst1", Dt, "\\{$Vd\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >   class VST1Q  op7_4, string Dt>
    >     : NLdSt<0,0b00,0b1010,op7_4, (outs),
    > @@ -1053,6 +1080,7 @@
    >             "vst1", Dt, "\\{$Vd, $src2\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def  VST1d8   : VST1D<{0,0,0,?}, "8">;
    > @@ -1076,6 +1104,7 @@
    >             (ins addrmode6:$Rn, am6offset:$Rm, DPR:$Vd), IIC_VST1u,
    >             "vst1", Dt, "\\{$Vd\\}, $Rn$Rm", "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >   class VST1QWB  op7_4, string Dt>
    >     : NLdSt<0, 0b00, 0b1010, op7_4, (outs GPR:$wb),
    > @@ -1083,6 +1112,7 @@
    >             IIC_VST1x2u, "vst1", Dt, "\\{$Vd, $src2\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def VST1d8_UPD  : VST1DWB<{0,0,0,?}, "8">;
    > @@ -1107,6 +1137,7 @@
    >             IIC_VST1x3, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >   class VST1D3WB  op7_4, string Dt>
    >     : NLdSt<0, 0b00, 0b0110, op7_4, (outs GPR:$wb),
    > @@ -1115,6 +1146,7 @@
    >             IIC_VST1x3u, "vst1", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def VST1d8T      : VST1D3<{0,0,0,?}, "8">;
    > @@ -1138,6 +1170,7 @@
    >             []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >   class VST1D4WB  op7_4, string Dt>
    >     : NLdSt<0, 0b00, 0b0010, op7_4, (outs GPR:$wb),
    > @@ -1146,6 +1179,7 @@
    >             "vst1", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def VST1d8Q      : VST1D4<{0,0,?,?}, "8">;
    > @@ -1168,6 +1202,7 @@
    >             IIC_VST2, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >   class VST2Q  op7_4, string Dt>
    >     : NLdSt<0, 0b00, 0b0011, op7_4, (outs),
    > @@ -1176,6 +1211,7 @@
    >             "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def  VST2d8   : VST2D<0b1000, {0,0,?,?}, "8">;
    > @@ -1201,6 +1237,7 @@
    >             IIC_VST2u, "vst2", Dt, "\\{$Vd, $src2\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >   class VST2QWB  op7_4, string Dt>
    >     : NLdSt<0, 0b00, 0b0011, op7_4, (outs GPR:$wb),
    > @@ -1209,6 +1246,7 @@
    >             "vst2", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def VST2d8_UPD  : VST2DWB<0b1000, {0,0,?,?}, "8">;
    > @@ -1242,6 +1280,7 @@
    >             "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn", "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def  VST3d8   : VST3D<0b0100, {0,0,0,?}, "8">;
    > @@ -1260,6 +1299,7 @@
    >             "vst3", Dt, "\\{$Vd, $src2, $src3\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{4} = Rn{4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def VST3d8_UPD  : VST3DWB<0b0100, {0,0,0,?}, "8">;
    > @@ -1299,6 +1339,7 @@
    >             "", []>  {
    >     let Rm = 0b1111;
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def  VST4d8   : VST4D<0b0000, {0,0,?,?}, "8">;
    > @@ -1317,6 +1358,7 @@
    >              "vst4", Dt, "\\{$Vd, $src2, $src3, $src4\\}, $Rn$Rm",
    >             "$Rn.addr = $wb", []>  {
    >     let Inst{5-4} = Rn{5-4};
    > +  let DecoderMethod = "DecodeVSTInstruction";
    >   }
    >
    >   def VST4d8_UPD  : VST4DWB<0b0000, {0,0,?,?}, "8">;
    > @@ -4040,6 +4082,7 @@
    >     : N2VLSh              ResTy, OpTy, OpNode>  {
    >     let Inst{21-16} = op21_16;
    > +  let DecoderMethod = "DecodeVSHLMaxInstruction";
    >   }
    >   def  VSHLLi8  : N2VLShMax<1, 1, 0b110010, 0b0011, 0, 0, 0, "vshll", "i8",
    >                             v8i16, v8i8, NEONvshlli>;
    > @@ -4754,6 +4797,7 @@
    >   // Vector Table Lookup and Table Extension.
    >
    >   //   VTBL     : Vector Table Lookup
    > +let DecoderMethod = "DecodeTBLInstruction" in {
    >   def  VTBL1
    >     : N3V<1,1,0b11,0b1000,0,0, (outs DPR:$Vd),
    >           (ins DPR:$Vn, DPR:$Vm), NVTBLFrm, IIC_VTB1,
    > @@ -4816,6 +4860,7 @@
    >   def  VTBX4Pseudo
    >     : PseudoNeonI<(outs DPR:$dst), (ins DPR:$orig, QQPR:$tbl, DPR:$src),
    >                   IIC_VTBX4, "$orig = $dst", []>;
    > +} // DecoderMethod = "DecodeTBLInstruction"
    >
    >   //===----------------------------------------------------------------------===//
    >   // NEON instructions for single-precision FP math
    >
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrThumb.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb.td Tue Aug  9 15:55:18 2011
    > @@ -82,14 +82,17 @@
    >   let OperandType = "OPERAND_PCREL" in {
    >   def t_brtarget : Operand  {
    >     let EncoderMethod = "getThumbBRTargetOpValue";
    > +  let DecoderMethod = "DecodeThumbBROperand";
    >   }
    >
    >   def t_bcctarget : Operand  {
    >     let EncoderMethod = "getThumbBCCTargetOpValue";
    > +  let DecoderMethod = "DecodeThumbBCCTargetOperand";
    >   }
    >
    >   def t_cbtarget : Operand  {
    >     let EncoderMethod = "getThumbCBTargetOpValue";
    > +  let DecoderMethod = "DecodeThumbCmpBROperand";
    >   }
    >
    >   def t_bltarget : Operand  {
    > @@ -119,12 +122,14 @@
    >                         ComplexPattern  {
    >     let EncoderMethod = "getThumbAddrModeRegRegOpValue";
    >     let PrintMethod = "printThumbAddrModeRROperand";
    > +  let DecoderMethod = "DecodeThumbAddrModeRR";
    >     let ParserMatchClass = t_addrmode_rr_asm_operand;
    >     let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
    >   }
    >   def t_addrmode_rrs2 : Operand,
    >                         ComplexPattern  {
    >     let EncoderMethod = "getThumbAddrModeRegRegOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeRR";
    >     let PrintMethod = "printThumbAddrModeRROperand";
    >     let ParserMatchClass = t_addrmode_rr_asm_operand;
    >     let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
    > @@ -132,6 +137,7 @@
    >   def t_addrmode_rrs4 : Operand,
    >                         ComplexPattern  {
    >     let EncoderMethod = "getThumbAddrModeRegRegOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeRR";
    >     let PrintMethod = "printThumbAddrModeRROperand";
    >     let ParserMatchClass = t_addrmode_rr_asm_operand;
    >     let MIOperandInfo = (ops tGPR:$base, tGPR:$offsreg);
    > @@ -142,6 +148,7 @@
    >   def t_addrmode_is4 : Operand,
    >                        ComplexPattern  {
    >     let EncoderMethod = "getAddrModeISOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeIS";
    >     let PrintMethod = "printThumbAddrModeImm5S4Operand";
    >     let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
    >   }
    > @@ -151,6 +158,7 @@
    >   def t_addrmode_is2 : Operand,
    >                        ComplexPattern  {
    >     let EncoderMethod = "getAddrModeISOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeIS";
    >     let PrintMethod = "printThumbAddrModeImm5S2Operand";
    >     let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
    >   }
    > @@ -160,6 +168,7 @@
    >   def t_addrmode_is1 : Operand,
    >                        ComplexPattern  {
    >     let EncoderMethod = "getAddrModeISOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModeIS";
    >     let PrintMethod = "printThumbAddrModeImm5S1Operand";
    >     let MIOperandInfo = (ops tGPR:$base, i32imm:$offsimm);
    >   }
    > @@ -178,6 +187,7 @@
    >   //
    >   def t_addrmode_pc : Operand  {
    >     let EncoderMethod = "getAddrModePCOpValue";
    > +  let DecoderMethod = "DecodeThumbAddrModePC";
    >   }
    >
    >   //===----------------------------------------------------------------------===//
    > @@ -259,6 +269,7 @@
    >     let Inst{4}   = imod;
    >     let Inst{3}   = 0;
    >     let Inst{2-0} = iflags;
    > +  let DecoderMethod = "DecodeThumbCPS";
    >   }
    >
    >   // For both thumb1 and thumb2.
    > @@ -272,17 +283,6 @@
    >     let Inst{2-0} = dst;
    >   }
    >
    > -// PC relative add (ADR).
    > -def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi,
    > -                   "add\t$dst, pc, $rhs", []>,
    > -               T1Encoding<{1,0,1,0,0,?}>  {
    > -  // A6.2&  A8.6.10
    > -  bits<3>  dst;
    > -  bits<8>  rhs;
    > -  let Inst{10-8} = dst;
    > -  let Inst{7-0}  = rhs;
    > -}
    > -
    
    What replaced this?
    
    >   // ADD, sp, #
    >   // This is rematerializable, which is particularly useful for taking the
    >   // address of locals.
    > @@ -295,6 +295,7 @@
    >     bits<8>  rhs;
    >     let Inst{10-8} = dst;
    >     let Inst{7-0}  = rhs;
    > +  let DecoderMethod = "DecodeThumbAddSpecialReg";
    >   }
    >
    >   // ADD sp, sp, #
    > @@ -304,6 +305,7 @@
    >     // A6.2.5&  A8.6.8
    >     bits<7>  rhs;
    >     let Inst{6-0} = rhs;
    > +  let DecoderMethod = "DecodeThumbAddSPImm";
    >   }
    >
    >   // SUB sp, sp, #
    > @@ -314,6 +316,7 @@
    >     // A6.2.5&  A8.6.214
    >     bits<7>  rhs;
    >     let Inst{6-0} = rhs;
    > +  let DecoderMethod = "DecodeThumbAddSPImm";
    >   }
    >
    >   // ADD, sp
    > @@ -325,6 +328,7 @@
    >     let Inst{7}   = dst{3};
    >     let Inst{6-3} = 0b1101;
    >     let Inst{2-0} = dst{2-0};
    > +  let DecoderMethod = "DecodeThumbAddSPReg";
    >   }
    >
    >   // ADD sp,
    > @@ -336,6 +340,7 @@
    >     let Inst{7} = 1;
    >     let Inst{6-3} = dst;
    >     let Inst{2-0} = 0b101;
    > +  let DecoderMethod = "DecodeThumbAddSPReg";
    >   }
    >
    >   //===----------------------------------------------------------------------===//
    > @@ -1189,6 +1194,7 @@
    >     bits<8>  addr;
    >     let Inst{10-8} = Rd;
    >     let Inst{7-0} = addr;
    > +  let DecoderMethod = "DecodeThumbAddSpecialReg";
    >   }
    >
    >   let neverHasSideEffects = 1, isReMaterializable = 1 in
    >
    > Modified: llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td?rev=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td (original)
    > +++ llvm/trunk/lib/Target/ARM/ARMInstrThumb2.td Tue Aug  9 15:55:18 2011
    > @@ -50,6 +50,7 @@
    >     }]>  {
    >     let ParserMatchClass = t2_so_imm_asmoperand;
    >     let EncoderMethod = "getT2SOImmOpValue";
    > +  let DecoderMethod = "DecodeT2SOImm";
    >   }
    >
    >   // t2_so_imm_not - Match an immediate that is a complement
    > @@ -100,6 +101,7 @@
    >                          ComplexPattern  {
    >     let PrintMethod = "printAddrModeImm12Operand";
    >     let EncoderMethod = "getAddrModeImm12OpValue";
    > +  let DecoderMethod = "DecodeT2AddrModeImm12";
    >     let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
    >   }
    >
    > @@ -121,6 +123,7 @@
    >                         ComplexPattern  {
    >     let PrintMethod = "printT2AddrModeImm8Operand";
    >     let EncoderMethod = "getT2AddrModeImm8OpValue";
    > +  let DecoderMethod = "DecodeT2AddrModeImm8";
    >     let ParserMatchClass = MemImm8OffsetAsmOperand;
    >     let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
    >   }
    > @@ -130,12 +133,14 @@
    >                                         [], [SDNPWantRoot]>  {
    >     let PrintMethod = "printT2AddrModeImm8OffsetOperand";
    >     let EncoderMethod = "getT2AddrModeImm8OffsetOpValue";
    > +  let DecoderMethod = "DecodeT2Imm8";
    >   }
    >
    >   // t2addrmode_imm8s4  := reg +/- (imm8<<  2)
    >   def t2addrmode_imm8s4 : Operand  {
    >     let PrintMethod = "printT2AddrModeImm8s4Operand";
    >     let EncoderMethod = "getT2AddrModeImm8s4OpValue";
    > +  let DecoderMethod = "DecodeT2AddrModeImm8s4";
    >     let MIOperandInfo = (ops GPR:$base, i32imm:$offsimm);
    >   }
    >
    > @@ -149,6 +154,7 @@
    >                           ComplexPattern  {
    >     let PrintMethod = "printT2AddrModeSoRegOperand";
    >     let EncoderMethod = "getT2AddrModeSORegOpValue";
    > +  let DecoderMethod = "DecodeT2AddrModeSOReg";
    >     let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm);
    >   }
    >
    > @@ -158,6 +164,7 @@
    >   //
    >   def t2addrmode_reg : Operand  {
    >     let PrintMethod = "printAddrMode7Operand";
    > +  let DecoderMethod = "DecodeGPRRegisterClass";
    >     let MIOperandInfo = (ops GPR);
    >   }
    >
    > @@ -892,6 +899,8 @@
    >       let Inst{19-16} = addr{9-6}; // Rn
    >       let Inst{3-0}   = addr{5-2}; // Rm
    >       let Inst{5-4}   = addr{1-0}; // imm
    > +
    > +    let DecoderMethod = "DecodeT2LoadShift";
    >     }
    >
    >     // FIXME: Is the pci variant actually needed?
    > @@ -1430,6 +1439,8 @@
    >       let Inst{19-16} = addr{9-6}; // Rn
    >       let Inst{3-0}   = addr{5-2}; // Rm
    >       let Inst{5-4}   = addr{1-0}; // imm2
    > +
    > +    let DecoderMethod = "DecodeT2LoadShift";
    >     }
    >   }
    >
    > @@ -2994,6 +3005,8 @@
    >     let Inst{13} = target{18};
    >     let Inst{21-16} = target{17-12};
    >     let Inst{10-0} = target{11-1};
    > +
    > +  let DecoderMethod = "DecodeThumb2BCCInstruction";
    >   }
    >
    >   // Tail calls. The Darwin version of thumb tail calls uses a t2 branch, so
    >
    > 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=137144&r1=137143&r2=137144&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original)
    > +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Tue Aug  9 15:55:18 2011
    > @@ -6,584 +6,2328 @@
    >   // License. See LICENSE.TXT for details.
    >   //
    >   //===----------------------------------------------------------------------===//
    > -//
    > -// This file is part of the ARM Disassembler.
    > -// It contains code to implement the public interfaces of ARMDisassembler and
    > -// ThumbDisassembler, both of which are instances of MCDisassembler.
    > -//
    > -//===----------------------------------------------------------------------===//
    >
    >   #define DEBUG_TYPE "arm-disassembler"
    >
    >   #include "ARMDisassembler.h"
    > -#include "ARMDisassemblerCore.h"
    > -
    > -#include "llvm/ADT/OwningPtr.h"
    > +#include "ARM.h"
    > +#include "ARMRegisterInfo.h"
    > +#include "MCTargetDesc/ARMAddressingModes.h"
    > +#include "MCTargetDesc/ARMBaseInfo.h"
    >   #include "llvm/MC/EDInstInfo.h"
    >   #include "llvm/MC/MCInst.h"
    > +#include "llvm/MC/MCExpr.h"
    > +#include "llvm/MC/MCContext.h"
    >   #include "llvm/Target/TargetRegistry.h"
    >   #include "llvm/Support/Debug.h"
    >   #include "llvm/Support/MemoryObject.h"
    >   #include "llvm/Support/ErrorHandling.h"
    >   #include "llvm/Support/raw_ostream.h"
    >
    > -//#define DEBUG(X) do { X; } while (0)
    > -
    > -/// ARMGenDecoderTables.inc - ARMDecoderTables.inc is tblgen'ed from
    > -/// ARMDecoderEmitter.cpp TableGen backend.  It contains:
    > -///
    > -/// o Mappings from opcode to ARM/Thumb instruction format
    > -///
    > -/// o static uint16_t decodeInstruction(uint32_t insn) - the decoding function
    > -/// for an ARM instruction.
    > -///
    > -/// o static uint16_t decodeThumbInstruction(field_t insn) - the decoding
    > -/// function for a Thumb instruction.
    > -///
    > -#include "ARMGenDecoderTables.inc"
    > +// Forward declare these because the autogenerated code will reference them.
    > +// Definitions are further down.
    > +static bool DecodeGPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodetGPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodetcGPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecoderGPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeSPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeDPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeDPR_8RegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeDPR_VFP2RegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +static bool DecodeQPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder);
    > +
    > +static bool DecodePredicateOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeCCOutOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSOImmOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeBLTargetOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeRegListOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSPRRegListOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeDPRRegListOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +
    > +static bool DecodeBitfieldMaskOperand(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeCopMemInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode2IdxInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSORegMemOperand(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode3Instruction(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSORegImmOperand(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeSORegRegOperand(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +
    > +static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst&  Inst,
    > +                                                  unsigned Insn,
    > +                                                  uint64_t Adddress,
    > +                                                  const void *Decoder);
    > +static bool DecodeSMLAInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrModeImm12Operand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode5Operand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode7Operand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeBranchImmInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVCVTImmOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode6Operand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLDInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVSTInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLD1DupInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLD2DupInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLD3DupInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVLD4DupInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeNEONModImmInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVSHLMaxInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeShiftRight8Imm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeShiftRight16Imm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeShiftRight32Imm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeShiftRight64Imm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeTBLInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeVFPfpImm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodePostIdxReg(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeCoprocessor(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeAddrMode3Offset(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +
    > +
    > +static bool DecodeThumbAddSpecialReg(llvm::MCInst&Inst, uint16_t Insn,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbBROperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2BROperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbCmpBROperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddrModeRR(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddrModeIS(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddrModePC(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddrModeSP(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2AddrModeSOReg(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2LoadShift(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2Imm8S4(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2AddrModeImm8s4(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2Imm8(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeT2AddrModeImm8(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddSPImm(llvm::MCInst&Inst, uint16_t Val,
    > +                               uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbAddSPReg(llvm::MCInst&Inst, uint16_t Insn,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbCPS(llvm::MCInst&Inst, uint16_t Insn,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbBLXOffset(llvm::MCInst&Inst, unsigned Insn,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeT2AddrModeImm12(llvm::MCInst&Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbSRImm(llvm::MCInst&Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumb2BCCInstruction(llvm::MCInst&Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeT2SOImm(llvm::MCInst&Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbBCCTargetOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    > +static bool DecodeThumbBLTargetOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                uint64_t Address, const void *Decoder);
    >
    > +#include "ARMGenDisassemblerTables.inc"
    > +#include "ARMGenInstrInfo.inc"
    >   #include "ARMGenEDInfo.inc"
    >
    >   using namespace llvm;
    >
    > -/// showBitVector - Use the raw_ostream to log a diagnostic message describing
    > -/// the inidividual bits of the instruction.
    > -///
    > -static inline void showBitVector(raw_ostream&os, const uint32_t&insn) {
    > -  // Split the bit position markers into more than one lines to fit 80 columns.
    > -  os<<  " 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 \n";
    > -  os<<  "---------------------------------------------------------------"
    > -<<  "----------------------------------\n";
    > -  os<<  '|';
    > -  for (unsigned i = 32; i != 0; --i) {
    > -    if (insn>>  (i - 1)&  0x01)
    > -      os<<  " 1";
    > -    else
    > -      os<<  " 0";
    > -    os<<  (i%4 == 1 ? '|' : ':');
    > +static MCDisassembler *createARMDisassembler(const Target&T) {
    > +  return new ARMDisassembler;
    > +}
    > +
    > +static MCDisassembler *createThumbDisassembler(const Target&T) {
    > +  return new ThumbDisassembler;
    > +}
    > +
    > +EDInstInfo *ARMDisassembler::getEDInfo() const {
    > +  return instInfoARM;
    > +}
    > +
    > +EDInstInfo *ThumbDisassembler::getEDInfo() const {
    > +  return instInfoARM;
    > +}
    > +
    > +
    > +bool ARMDisassembler::getInstruction(MCInst&MI, uint64_t&Size,
    > +                                     const MemoryObject&Region,
    > +                                     uint64_t Address,raw_ostream&os) const {
    > +  uint8_t bytes[4];
    > +
    > +  // We want to read exactly 4 bytes of data.
    > +  if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1)
    > +    return false;
    > +
    > +  // Encoded as a small-endian 32-bit word in the stream.
    > +  uint32_t insn = (bytes[3]<<  24) |
    > +                  (bytes[2]<<  16) |
    > +                  (bytes[1]<<   8) |
    > +                  (bytes[0]<<   0);
    > +
    > +  // Calling the auto-generated decoder function.
    > +  bool result = decodeARMInstruction32(MI, insn, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    return true;
    >     }
    > -  os<<  '\n';
    > -  // Split the bit position markers into more than one lines to fit 80 columns.
    > -  os<<  "---------------------------------------------------------------"
    > -<<  "----------------------------------\n";
    > -  os<<  '\n';
    > -}
    > -
    > -/// decodeARMInstruction is a decorator function which tries special cases of
    > -/// instruction matching before calling the auto-generated decoder function.
    > -static unsigned decodeARMInstruction(uint32_t&insn) {
    > -  if (slice(insn, 31, 28) == 15)
    > -    goto AutoGenedDecoder;
    > -
    > -  // Special case processing, if any, goes here....
    > -
    > -  // LLVM combines the offset mode of A8.6.197&  A8.6.198 into STRB.
    > -  // The insufficient encoding information of the combined instruction confuses
    > -  // the decoder wrt BFC/BFI.  Therefore, we try to recover here.
    > -  // For BFC, Inst{27-21} = 0b0111110&  Inst{6-0} = 0b0011111.
    > -  // For BFI, Inst{27-21} = 0b0111110&  Inst{6-4} = 0b001&  Inst{3-0} =! 0b1111.
    > -  if (slice(insn, 27, 21) == 0x3e&&  slice(insn, 6, 4) == 1) {
    > -    if (slice(insn, 3, 0) == 15)
    > -      return ARM::BFC;
    > -    else
    > -      return ARM::BFI;
    > +
    > +  // Instructions that are shared between ARM and Thumb modes.
    > +  // FIXME: This shouldn't really exist.  It's an artifact of the
    > +  // fact that we fail to encode a few instructions properly for Thumb.
    > +  MI.clear();
    > +  result = decodeCommonInstruction32(MI, insn, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    return true;
    >     }
    >
    > -  // Ditto for STRBT, which is a super-instruction for A8.6.199 Encodings
    > -  // A1&  A2.
    > -  // As a result, the decoder fails to deocode USAT properly.
    > -  if (slice(insn, 27, 21) == 0x37&&  slice(insn, 5, 4) == 1)
    > -    return ARM::USAT;
    > -  // As a result, the decoder fails to deocode UQADD16 properly.
    > -  if (slice(insn, 27, 20) == 0x66&&  slice(insn, 7, 4) == 1)
    > -    return ARM::UQADD16;
    > -
    > -  // Ditto for ADDSrs, which is a super-instruction for A8.6.7&  A8.6.8.
    > -  // As a result, the decoder fails to decode UMULL properly.
    > -  if (slice(insn, 27, 21) == 0x04&&  slice(insn, 7, 4) == 9) {
    > -    return ARM::UMULL;
    > -  }
    > -
    > -  // Ditto for STR_PRE, which is a super-instruction for A8.6.194&  A8.6.195.
    > -  // As a result, the decoder fails to decode SBFX properly.
    > -  if (slice(insn, 27, 21) == 0x3d&&  slice(insn, 6, 4) == 5)
    > -    return ARM::SBFX;
    > -
    > -  // And STRB_PRE, which is a super-instruction for A8.6.197&  A8.6.198.
    > -  // As a result, the decoder fails to decode UBFX properly.
    > -  if (slice(insn, 27, 21) == 0x3f&&  slice(insn, 6, 4) == 5)
    > -    return ARM::UBFX;
    > -
    > -  // Ditto for STRT, which is a super-instruction for A8.6.210 Encoding A1&  A2.
    > -  // As a result, the decoder fails to deocode SSAT properly.
    > -  if (slice(insn, 27, 21) == 0x35&&  slice(insn, 5, 4) == 1)
    > -    return ARM::SSAT;
    > -
    > -  // Ditto for RSCrs, which is a super-instruction for A8.6.146&  A8.6.147.
    > -  // As a result, the decoder fails to decode STRHT/LDRHT/LDRSHT/LDRSBT.
    > -  if (slice(insn, 27, 24) == 0) {
    > -    switch (slice(insn, 21, 20)) {
    > -    case 2:
    > -      switch (slice(insn, 7, 4)) {
    > -      case 11:
    > -        return slice(insn, 22, 22) ? ARM::STRHTi : ARM::STRHTr;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 3:
    > -      switch (slice(insn, 7, 4)) {
    > -      case 11:
    > -        return slice(insn, 22, 22) ? ARM::LDRHTi : ARM::LDRHTr;
    > -      case 13:
    > -        return slice(insn, 22, 22) ? ARM::LDRSBTi : ARM::LDRSBTr;
    > -      case 15:
    > -        return slice(insn, 22, 22) ? ARM::LDRSHTi : ARM::LDRSHTr;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    default:
    > -      break;   // fallthrough
    > -    }
    > +  // VFP and NEON instructions, similarly, are shared between ARM
    > +  // and Thumb modes.
    > +  MI.clear();
    > +  result = decodeVFPInstruction32(MI, insn, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    return true;
    >     }
    >
    > -  // Ditto for SBCrs, which is a super-instruction for A8.6.152&  A8.6.153.
    > -  // As a result, the decoder fails to decode STRH_Post/LDRD_POST/STRD_POST
    > -  // properly.
    > -  if (slice(insn, 27, 25) == 0&&  slice(insn, 20, 20) == 0) {
    > -    unsigned PW = slice(insn, 24, 24)<<  1 | slice(insn, 21, 21);
    > -    switch (slice(insn, 7, 4)) {
    > -    case 11:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::STRH;
    > -      case 3: // Pre-indexed
    > -        return ARM::STRH_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::STRH_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 13:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::LDRD;
    > -      case 3: // Pre-indexed
    > -        return ARM::LDRD_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::LDRD_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 15:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::STRD;
    > -      case 3: // Pre-indexed
    > -        return ARM::STRD_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::STRD_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    default:
    > -      break; // fallthrough
    > -    }
    > +  MI.clear();
    > +  result = decodeNEONInstruction32(MI, insn, Address, this);
    > +  if (result) {
    > +    // Add a fake predicate operand, because we share these instruction
    > +    // definitions with Thumb2 where these instructions are predicable.
    > +    if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false;
    > +    Size = 4;
    > +    return true;
    >     }
    >
    > -  // Ditto for SBCSSrs, which is a super-instruction for A8.6.152&  A8.6.153.
    > -  // As a result, the decoder fails to decode LDRH_POST/LDRSB_POST/LDRSH_POST
    > -  // properly.
    > -  if (slice(insn, 27, 25) == 0&&  slice(insn, 20, 20) == 1) {
    > -    unsigned PW = slice(insn, 24, 24)<<  1 | slice(insn, 21, 21);
    > -    switch (slice(insn, 7, 4)) {
    > -    case 11:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::LDRH;
    > -      case 3: // Pre-indexed
    > -        return ARM::LDRH_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::LDRH_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 13:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::LDRSB;
    > -      case 3: // Pre-indexed
    > -        return ARM::LDRSB_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::LDRSB_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    case 15:
    > -      switch (PW) {
    > -      case 2: // Offset
    > -        return ARM::LDRSH;
    > -      case 3: // Pre-indexed
    > -        return ARM::LDRSH_PRE;
    > -      case 0: // Post-indexed
    > -        return ARM::LDRSH_POST;
    > -      default:
    > -        break; // fallthrough
    > -      }
    > -      break;
    > -    default:
    > -      break; // fallthrough
    > +  MI.clear();
    > +
    > +  return false;
    > +}
    > +
    > +namespace llvm {
    > +extern MCInstrDesc ARMInsts[];
    > +}
    > +
    > +// Thumb1 instructions don't have explicit S bits.  Rather, they
    > +// implicitly set CPSR.  Since it's not represented in the encoding, the
    > +// auto-generated decoder won't inject the CPSR operand.  We need to fix
    > +// that as a post-pass.
    > +static void AddThumb1SBit(MCInst&MI, bool InITBlock) {
    > +  const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
    > +  MCInst::iterator I = MI.begin();
    > +  for (unsigned i = 0; i<  MI.size(); ++i, ++I) {
    > +    if (OpInfo[i].isOptionalDef()&&  OpInfo[i].RegClass == ARM::CCRRegClassID) {
    > +      MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
    > +      return;
    
    Please don't re-test MI.size() each loop iteration.
    
    >       }
    >     }
    >
    > -AutoGenedDecoder:
    > -  // Calling the auto-generated decoder function.
    > -  return decodeInstruction(insn);
    > +  if (OpInfo[MI.size()].isOptionalDef()&&
    > +      OpInfo[MI.size()].RegClass == ARM::CCRRegClassID)
    > +    MI.insert(MI.end(), MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR));
    >   }
    >
    > -// Helper function for special case handling of LDR (literal) and friends.
    > -// See, for example, A6.3.7 Load word: Table A6-18 Load word.
    > -// See A8.6.57 T3, T4&  A8.6.60 T2 and friends for why we morphed the opcode
    > -// before returning it.
    > -static unsigned T2Morph2LoadLiteral(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return Opcode; // Return unmorphed opcode.
    > -
    > -  case ARM::t2LDR_POST:   case ARM::t2LDR_PRE:
    > -  case ARM::t2LDRi12:     case ARM::t2LDRi8:
    > -  case ARM::t2LDRs:       case ARM::t2LDRT:
    > -    return ARM::t2LDRpci;
    > -
    > -  case ARM::t2LDRB_POST:  case ARM::t2LDRB_PRE:
    > -  case ARM::t2LDRBi12:    case ARM::t2LDRBi8:
    > -  case ARM::t2LDRBs:      case ARM::t2LDRBT:
    > -    return ARM::t2LDRBpci;
    > -
    > -  case ARM::t2LDRH_POST:  case ARM::t2LDRH_PRE:
    > -  case ARM::t2LDRHi12:    case ARM::t2LDRHi8:
    > -  case ARM::t2LDRHs:      case ARM::t2LDRHT:
    > -    return ARM::t2LDRHpci;
    > -
    > -  case ARM::t2LDRSB_POST:  case ARM::t2LDRSB_PRE:
    > -  case ARM::t2LDRSBi12:    case ARM::t2LDRSBi8:
    > -  case ARM::t2LDRSBs:      case ARM::t2LDRSBT:
    > -    return ARM::t2LDRSBpci;
    > -
    > -  case ARM::t2LDRSH_POST:  case ARM::t2LDRSH_PRE:
    > -  case ARM::t2LDRSHi12:    case ARM::t2LDRSHi8:
    > -  case ARM::t2LDRSHs:      case ARM::t2LDRSHT:
    > -    return ARM::t2LDRSHpci;
    > -  }
    > -}
    > -
    > -// Helper function for special case handling of PLD (literal) and friends.
    > -// See A8.6.117 T1&  T2 and friends for why we morphed the opcode
    > -// before returning it.
    > -static unsigned T2Morph2PLDLiteral(unsigned Opcode) {
    > -  switch (Opcode) {
    > -  default:
    > -    return Opcode; // Return unmorphed opcode.
    > -
    > -  case ARM::t2PLDi8:   case ARM::t2PLDs:
    > -  case ARM::t2PLDWi12: case ARM::t2PLDWi8:
    > -  case ARM::t2PLDWs:
    > -    return ARM::t2PLDi12;
    > -
    > -  case ARM::t2PLIi8:   case ARM::t2PLIs:
    > -    return ARM::t2PLIi12;
    > -  }
    > -}
    > -
    > -/// decodeThumbSideEffect is a decorator function which can potentially twiddle
    > -/// the instruction or morph the returned opcode under Thumb2.
    > -///
    > -/// First it checks whether the insn is a NEON or VFP instr; if true, bit
    > -/// twiddling could be performed on insn to turn it into an ARM NEON/VFP
    > -/// equivalent instruction and decodeInstruction is called with the transformed
    > -/// insn.
    > -///
    > -/// Next, there is special handling for Load byte/halfword/word instruction by
    > -/// checking whether Rn=0b1111 and call T2Morph2LoadLiteral() on the decoded
    > -/// Thumb2 instruction.  See comments below for further details.
    > -///
    > -/// Finally, one last check is made to see whether the insn is a NEON/VFP and
    > -/// decodeInstruction(insn) is invoked on the original insn.
    > -///
    > -/// Otherwise, decodeThumbInstruction is called with the original insn.
    > -static unsigned decodeThumbSideEffect(bool IsThumb2, unsigned&insn) {
    > -  if (IsThumb2) {
    > -    uint16_t op1 = slice(insn, 28, 27);
    > -    uint16_t op2 = slice(insn, 26, 20);
    > -
    > -    // A6.3 32-bit Thumb instruction encoding
    > -    // Table A6-9 32-bit Thumb instruction encoding
    > -
    > -    // The coprocessor instructions of interest are transformed to their ARM
    > -    // equivalents.
    > -
    > -    // --------- Transform Begin Marker ---------
    > -    if ((op1 == 1 || op1 == 3)&&  slice(op2, 6, 4) == 7) {
    > -      // A7.4 Advanced SIMD data-processing instructions
    > -      // U bit of Thumb corresponds to Inst{24} of ARM.
    > -      uint16_t U = slice(op1, 1, 1);
    > -
    > -      // Inst{28-24} of ARM = {1,0,0,1,U};
    > -      uint16_t bits28_24 = 9<<  1 | U;
    > -      DEBUG(showBitVector(errs(), insn));
    > -      setSlice(insn, 28, 24, bits28_24);
    > -      return decodeInstruction(insn);
    > -    }
    > -
    > -    if (op1 == 3&&  slice(op2, 6, 4) == 1&&  slice(op2, 0, 0) == 0) {
    > -      // A7.7 Advanced SIMD element or structure load/store instructions
    > -      // Inst{27-24} of Thumb = 0b1001
    > -      // Inst{27-24} of ARM   = 0b0100
    > -      DEBUG(showBitVector(errs(), insn));
    > -      setSlice(insn, 27, 24, 4);
    > -      return decodeInstruction(insn);
    > -    }
    > -    // --------- Transform End Marker ---------
    > -
    > -    unsigned unmorphed = decodeThumbInstruction(insn);
    > -
    > -    // See, for example, A6.3.7 Load word: Table A6-18 Load word.
    > -    // See A8.6.57 T3, T4&  A8.6.60 T2 and friends for why we morphed the opcode
    > -    // before returning it to our caller.
    > -    if (op1 == 3&&  slice(op2, 6, 5) == 0&&  slice(op2, 0, 0) == 1
    > -&&  slice(insn, 19, 16) == 15) {
    > -      unsigned morphed = T2Morph2LoadLiteral(unmorphed);
    > -      if (morphed != unmorphed)
    > -        return morphed;
    > -    }
    > -
    > -    // See, for example, A8.6.117 PLD,PLDW (immediate) T1&  T2, and friends for
    > -    // why we morphed the opcode before returning it to our caller.
    > -    if (slice(insn, 31, 25) == 0x7C&&  slice(insn, 15, 12) == 0xF
    > -&&  slice(insn, 22, 22) == 0&&  slice(insn, 20, 20) == 1
    > -&&  slice(insn, 19, 16) == 15) {
    > -      unsigned morphed = T2Morph2PLDLiteral(unmorphed);
    > -      if (morphed != unmorphed)
    > -        return morphed;
    > -    }
    > -
    > -    // One last check for NEON/VFP instructions.
    > -    if ((op1 == 1 || op1 == 3)&&  slice(op2, 6, 6) == 1)
    > -      return decodeInstruction(insn);
    > +// Most Thumb instructions don't have explicit predicates in the
    > +// encoding, but rather get their predicates from IT context.  We need
    > +// to fix up the predicate operands using this context information as a
    > +// post-pass.
    > +void ThumbDisassembler::AddThumbPredicate(MCInst&MI) const {
    > +  // A few instructions actually have predicates encoded in them.  Don't
    > +  // try to overwrite it if we're seeing one of those.
    > +  switch (MI.getOpcode()) {
    > +    case ARM::tBcc:
    > +    case ARM::t2Bcc:
    > +      return;
    > +    default:
    > +      break;
    > +  }
    >
    > -    // Fall through.
    > +  // If we're in an IT block, base the predicate on that.  Otherwise,
    > +  // assume a predicate of AL.
    > +  unsigned CC;
    > +  if (ITBlock.size()) {
    
    ITBlock.empty()? It's an std::vector.
    
    > +    CC = ITBlock.back();
    > +    ITBlock.pop_back();
    > +  } else
    > +    CC = ARMCC::AL;
    > +
    > +  const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
    > +  MCInst::iterator I = MI.begin();
    > +  for (unsigned i = 0; i<  MI.size(); ++i, ++I) {
    > +    if (OpInfo[i].isPredicate()) {
    > +      I = MI.insert(I, MCOperand::CreateImm(CC));
    > +      ++I;
    > +      if (CC == ARMCC::AL)
    > +        MI.insert(I, MCOperand::CreateReg(0));
    > +      else
    > +        MI.insert(I, MCOperand::CreateReg(ARM::CPSR));
    > +      return;
    > +    }
    
    This can be written without testing MI.size() every iteration.
    
    >     }
    >
    > -  return decodeThumbInstruction(insn);
    > +  MI.insert(MI.end(), MCOperand::CreateImm(CC));
    > +  if (CC == ARMCC::AL)
    > +    MI.insert(MI.end(), MCOperand::CreateReg(0));
    > +  else
    > +    MI.insert(MI.end(), MCOperand::CreateReg(ARM::CPSR));
    >   }
    >
    > -//
    > -// Public interface for the disassembler
    > -//
    > +// Thumb VFP instructions are a special case.  Because we share their
    > +// encodings between ARM and Thumb modes, and they are predicable in ARM
    > +// mode, the auto-generated decoder will give them an (incorrect)
    > +// predicate operand.  We need to rewrite these operands based on the IT
    > +// context as a post-pass.
    > +void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst&MI) const {
    > +  unsigned CC;
    > +  if (ITBlock.size()) {
    
    ITBlock.empty().
    
    > +    CC = ITBlock.back();
    > +    ITBlock.pop_back();
    > +  } else
    > +    CC = ARMCC::AL;
    > +
    > +  const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo;
    > +  MCInst::iterator I = MI.begin();
    > +  for (unsigned i = 0; i<  MI.size(); ++i, ++I) {
    
    MI.size().
    
    > +    if (OpInfo[i].isPredicate() ) {
    > +      I->setImm(CC);
    > +      ++I;
    > +      if (CC == ARMCC::AL)
    > +        I->setReg(0);
    > +      else
    > +        I->setReg(ARM::CPSR);
    > +      return;
    > +    }
    > +  }
    > +}
    >
    > -bool ARMDisassembler::getInstruction(MCInst&MI,
    > -                                     uint64_t&Size,
    > -                                     const MemoryObject&Region,
    > -                                     uint64_t Address,
    > -                                     raw_ostream&os) const {
    > -  // The machine instruction.
    > -  uint32_t insn;
    > +
    > +bool ThumbDisassembler::getInstruction(MCInst&MI, uint64_t&Size,
    > +                                       const MemoryObject&Region,
    > +                                       uint64_t Address,raw_ostream&os) const {
    >     uint8_t bytes[4];
    >
    > +  // We want to read exactly 2 bytes of data.
    > +  if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1)
    > +    return false;
    > +
    > +  uint16_t insn16 = (bytes[1]<<  8) | bytes[0];
    > +  bool result = decodeThumbInstruction16(MI, insn16, Address, this);
    > +  if (result) {
    > +    Size = 2;
    > +    bool InITBlock = ITBlock.size();
    
    ITBlock.empty? :)
    
    > +    AddThumbPredicate(MI);
    > +    AddThumb1SBit(MI, InITBlock);
    > +    return true;
    > +  }
    > +
    > +  MI.clear();
    > +  result = decodeThumb2Instruction16(MI, insn16, Address, this);
    > +  if (result) {
    > +    Size = 2;
    > +    AddThumbPredicate(MI);
    > +
    > +    // If we find an IT instruction, we need to parse its condition
    > +    // code and mask operands so that we can apply them correctly
    > +    // to the subsequent instructions.
    > +    if (MI.getOpcode() == ARM::t2IT) {
    > +      unsigned firstcond = MI.getOperand(0).getImm();
    > +      uint32_t mask = MI.getOperand(1).getImm();
    > +      unsigned zeros = CountTrailingZeros_32(mask);
    > +      mask>>= zeros+1;
    > +
    > +      for (unsigned i = 0; i<  4 - (zeros+1); ++i) {
    > +        if (firstcond ^ (mask&  1))
    > +          ITBlock.push_back(firstcond ^ 1);
    > +        else
    > +          ITBlock.push_back(firstcond);
    > +        mask>>= 1;
    > +      }
    > +      ITBlock.push_back(firstcond);
    > +    }
    > +
    > +    return true;
    > +  }
    > +
    >     // We want to read exactly 4 bytes of data.
    >     if (Region.readBytes(Address, 4, (uint8_t*)bytes, NULL) == -1)
    >       return false;
    >
    > -  // Encoded as a small-endian 32-bit word in the stream.
    > -  insn = (bytes[3]<<  24) |
    > -         (bytes[2]<<  16) |
    > -         (bytes[1]<<   8) |
    > -         (bytes[0]<<   0);
    > +  uint32_t insn32 = (bytes[3]<<   8) |
    > +                    (bytes[2]<<   0) |
    > +                    (bytes[1]<<  24) |
    > +                    (bytes[0]<<  16);
    > +  MI.clear();
    > +  result = decodeThumbInstruction32(MI, insn32, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    bool InITBlock = ITBlock.size();
    > +    AddThumbPredicate(MI);
    > +    AddThumb1SBit(MI, InITBlock);
    > +    return true;
    > +  }
    > +
    > +  MI.clear();
    > +  result = decodeThumb2Instruction32(MI, insn32, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    AddThumbPredicate(MI);
    > +    return true;
    > +  }
    > +
    > +  MI.clear();
    > +  result = decodeVFPInstruction32(MI, insn32, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    UpdateThumbVFPPredicate(MI);
    > +    return true;
    > +  }
    > +
    > +  MI.clear();
    > +  result = decodeCommonInstruction32(MI, insn32, Address, this);
    > +  if (result) {
    > +    Size = 4;
    > +    AddThumbPredicate(MI);
    > +    return true;
    > +  }
    > +
    > +  return false;
    > +}
    >
    > -  unsigned Opcode = decodeARMInstruction(insn);
    > -  ARMFormat Format = ARMFormats[Opcode];
    > -  Size = 4;
    >
    > -  DEBUG({
    > -      errs()<<  "\nOpcode="<<  Opcode<<  " Name="< -<<  " Format="<<  stringForARMFormat(Format)<<  '('<<  (int)Format
    > -<<  ")\n";
    > -      showBitVector(errs(), insn);
    > -    });
    > +extern "C" void LLVMInitializeARMDisassembler() {
    > +  TargetRegistry::RegisterMCDisassembler(TheARMTarget,
    > +                                         createARMDisassembler);
    > +  TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
    > +                                         createThumbDisassembler);
    > +}
    >
    > -  OwningPtr  Builder(CreateMCBuilder(Opcode, Format));
    > -  if (!Builder)
    > +static const unsigned GPRDecoderTable[] = {
    > +  ARM::R0, ARM::R1, ARM::R2, ARM::R3,
    > +  ARM::R4, ARM::R5, ARM::R6, ARM::R7,
    > +  ARM::R8, ARM::R9, ARM::R10, ARM::R11,
    > +  ARM::R12, ARM::SP, ARM::LR, ARM::PC
    > +};
    > +
    > +static bool DecodeGPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo>  15)
    >       return false;
    >
    > -  Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(),
    > -                                              getDisInfoBlock(), getMCContext(),
    > -                                              Address);
    > +  unsigned Register = GPRDecoderTable[RegNo];
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    > +  return true;
    > +}
    >
    > -  if (!Builder->Build(MI, insn))
    > +static bool DecodetGPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo>  7)
    >       return false;
    > +  return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
    > +}
    > +
    > +static bool DecodetcGPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Register = 0;
    > +  switch (RegNo) {
    > +    case 0:
    > +      Register = ARM::R0;
    > +      break;
    > +    case 1:
    > +      Register = ARM::R1;
    > +      break;
    > +    case 2:
    > +      Register = ARM::R2;
    > +      break;
    > +    case 3:
    > +      Register = ARM::R3;
    > +      break;
    > +    case 9:
    > +      Register = ARM::R9;
    > +      break;
    > +    case 12:
    > +      Register = ARM::R12;
    > +      break;
    > +    default:
    > +      return false;
    > +    }
    >
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    >     return true;
    >   }
    >
    > -bool ThumbDisassembler::getInstruction(MCInst&MI,
    > -                                       uint64_t&Size,
    > -                                       const MemoryObject&Region,
    > -                                       uint64_t Address,
    > -                                       raw_ostream&os) const {
    > -  // The Thumb instruction stream is a sequence of halfwords.
    > -
    > -  // This represents the first halfword as well as the machine instruction
    > -  // passed to decodeThumbInstruction().  For 16-bit Thumb instruction, the top
    > -  // halfword of insn is 0x00 0x00; otherwise, the first halfword is moved to
    > -  // the top half followed by the second halfword.
    > -  unsigned insn = 0;
    > -  // Possible second halfword.
    > -  uint16_t insn1 = 0;
    > -
    > -  // A6.1 Thumb instruction set encoding
    > -  //
    > -  // If bits [15:11] of the halfword being decoded take any of the following
    > -  // values, the halfword is the first halfword of a 32-bit instruction:
    > -  // o 0b11101
    > -  // o 0b11110
    > -  // o 0b11111.
    > -  //
    > -  // Otherwise, the halfword is a 16-bit instruction.
    > +static bool DecoderGPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo == 13 || RegNo == 15) return false;
    > +  return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
    > +}
    >
    > -  // Read 2 bytes of data first.
    > -  uint8_t bytes[2];
    > -  if (Region.readBytes(Address, 2, (uint8_t*)bytes, NULL) == -1)
    > +static const unsigned SPRDecoderTable[] = {
    > +     ARM::S0,  ARM::S1,  ARM::S2,  ARM::S3,
    > +     ARM::S4,  ARM::S5,  ARM::S6,  ARM::S7,
    > +     ARM::S8,  ARM::S9, ARM::S10, ARM::S11,
    > +    ARM::S12, ARM::S13, ARM::S14, ARM::S15,
    > +    ARM::S16, ARM::S17, ARM::S18, ARM::S19,
    > +    ARM::S20, ARM::S21, ARM::S22, ARM::S23,
    > +    ARM::S24, ARM::S25, ARM::S26, ARM::S27,
    > +    ARM::S28, ARM::S29, ARM::S30, ARM::S31
    > +};
    > +
    > +static bool DecodeSPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo>  31)
    >       return false;
    >
    > -  // Encoded as a small-endian 16-bit halfword in the stream.
    > -  insn = (bytes[1]<<  8) | bytes[0];
    > -  unsigned bits15_11 = slice(insn, 15, 11);
    > -  bool IsThumb2 = false;
    > -
    > -  // 32-bit instructions if the bits [15:11] of the halfword matches
    > -  // { 0b11101 /* 0x1D */, 0b11110 /* 0x1E */, ob11111 /* 0x1F */ }.
    > -  if (bits15_11 == 0x1D || bits15_11 == 0x1E || bits15_11 == 0x1F) {
    > -    IsThumb2 = true;
    > -    if (Region.readBytes(Address + 2, 2, (uint8_t*)bytes, NULL) == -1)
    > -      return false;
    > -    // Encoded as a small-endian 16-bit halfword in the stream.
    > -    insn1 = (bytes[1]<<  8) | bytes[0];
    > -    insn = (insn<<  16 | insn1);
    > -  }
    > +  unsigned Register = SPRDecoderTable[RegNo];
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    > +  return true;
    > +}
    >
    > -  // The insn could potentially be bit-twiddled in order to be decoded as an ARM
    > -  // NEON/VFP opcode.  In such case, the modified insn is later disassembled as
    > -  // an ARM NEON/VFP instruction.
    > -  //
    > -  // This is a short term solution for lack of encoding bits specified for the
    > -  // Thumb2 NEON/VFP instructions.  The long term solution could be adding some
    > -  // infrastructure to have each instruction support more than one encodings.
    > -  // Which encoding is used would be based on which subtarget the compiler/
    > -  // disassembler is working with at the time.  This would allow the sharing of
    > -  // the NEON patterns between ARM and Thumb2, as well as potential greater
    > -  // sharing between the regular ARM instructions and the 32-bit wide Thumb2
    > -  // instructions as well.
    > -  unsigned Opcode = decodeThumbSideEffect(IsThumb2, insn);
    > +static const unsigned DPRDecoderTable[] = {
    > +     ARM::D0,  ARM::D1,  ARM::D2,  ARM::D3,
    > +     ARM::D4,  ARM::D5,  ARM::D6,  ARM::D7,
    > +     ARM::D8,  ARM::D9, ARM::D10, ARM::D11,
    > +    ARM::D12, ARM::D13, ARM::D14, ARM::D15,
    > +    ARM::D16, ARM::D17, ARM::D18, ARM::D19,
    > +    ARM::D20, ARM::D21, ARM::D22, ARM::D23,
    > +    ARM::D24, ARM::D25, ARM::D26, ARM::D27,
    > +    ARM::D28, ARM::D29, ARM::D30, ARM::D31
    > +};
    > +
    > +static bool DecodeDPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo>  31)
    > +    return false;
    >
    > -  ARMFormat Format = ARMFormats[Opcode];
    > -  Size = IsThumb2 ? 4 : 2;
    > +  unsigned Register = DPRDecoderTable[RegNo];
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    > +  return true;
    > +}
    >
    > -  DEBUG({
    > -      errs()<<  "Opcode="<<  Opcode<<  " Name="<<  ARMUtils::OpcodeName(Opcode)
    > -<<  " Format="<<  stringForARMFormat(Format)<<  '('<<  (int)Format
    > -<<  ")\n";
    > -      showBitVector(errs(), insn);
    > -    });
    > +static bool DecodeDPR_8RegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo>  7)
    > +    return false;
    > +  return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
    > +}
    >
    > -  OwningPtr  Builder(CreateMCBuilder(Opcode, Format));
    > -  if (!Builder)
    > +static bool DecodeDPR_VFP2RegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo>  15)
    >       return false;
    > +  return DecodeDPRRegisterClass(Inst, RegNo, Address, Decoder);
    > +}
    >
    > -  Builder->SetSession(const_cast(&SO));
    > +static const unsigned QPRDecoderTable[] = {
    > +     ARM::Q0,  ARM::Q1,  ARM::Q2,  ARM::Q3,
    > +     ARM::Q4,  ARM::Q5,  ARM::Q6,  ARM::Q7,
    > +     ARM::Q8,  ARM::Q9, ARM::Q10, ARM::Q11,
    > +    ARM::Q12, ARM::Q13, ARM::Q14, ARM::Q15
    > +};
    >
    > -  Builder->setupBuilderForSymbolicDisassembly(getLLVMOpInfoCallback(),
    > -                                              getDisInfoBlock(), getMCContext(),
    > -                                              Address);
    >
    > -  if (!Builder->Build(MI, insn))
    > +static bool DecodeQPRRegisterClass(llvm::MCInst&Inst, unsigned RegNo,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  if (RegNo>  31)
    >       return false;
    > +  RegNo>>= 1;
    >
    > +  unsigned Register = QPRDecoderTable[RegNo];
    > +  Inst.addOperand(MCOperand::CreateReg(Register));
    >     return true;
    >   }
    >
    > -// A8.6.50
    > -// Valid return values are {1, 2, 3, 4}, with 0 signifying an error condition.
    > -static unsigned short CountITSize(unsigned ITMask) {
    > -  // First count the trailing zeros of the IT mask.
    > -  unsigned TZ = CountTrailingZeros_32(ITMask);
    > -  if (TZ>  3) {
    > -    DEBUG(errs()<<  "Encoding error: IT Mask '0000'");
    > -    return 0;
    > -  }
    > -  return (4 - TZ);
    > +static bool DecodePredicateOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  if (Val == 0xF) return false;
    > +  Inst.addOperand(MCOperand::CreateImm(Val));
    > +  if (Val == ARMCC::AL) {
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  } else
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
    > +  return true;
    >   }
    >
    > -/// Init ITState.  Note that at least one bit is always 1 in mask.
    > -bool Session::InitIT(unsigned short bits7_0) {
    > -  ITCounter = CountITSize(slice(bits7_0, 3, 0));
    > -  if (ITCounter == 0)
    > -    return false;
    > +static bool DecodeCCOutOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  if (Val)
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::CPSR));
    > +  else
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  return true;
    > +}
    >
    > -  // A8.6.50 IT
    > -  unsigned short FirstCond = slice(bits7_0, 7, 4);
    > -  if (FirstCond == 0xF) {
    > -    DEBUG(errs()<<  "Encoding error: IT FirstCond '1111'");
    > -    return false;
    > +static bool DecodeSOImmOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  uint32_t imm = Val&  0xFF;
    > +  uint32_t rot = (Val&  0xF00)>>  7;
    > +  uint32_t rot_imm = (imm>>  rot) | (imm<<  (32-rot));
    > +  Inst.addOperand(MCOperand::CreateImm(rot_imm));
    > +  return true;
    > +}
    > +
    > +static bool DecodeBLTargetOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Val<<= 2;
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<26>(Val)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeSORegImmOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +
    > +  unsigned Rm = fieldFromInstruction32(Val, 0, 4);
    > +  unsigned type = fieldFromInstruction32(Val, 5, 2);
    > +  unsigned imm = fieldFromInstruction32(Val, 7, 5);
    > +
    > +  // Register-immediate
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
    > +  switch (type) {
    > +    case 0:
    > +      Shift = ARM_AM::lsl;
    > +      break;
    > +    case 1:
    > +      Shift = ARM_AM::lsr;
    > +      break;
    > +    case 2:
    > +      Shift = ARM_AM::asr;
    > +      break;
    > +    case 3:
    > +      Shift = ARM_AM::ror;
    > +      break;
    >     }
    > -  if (FirstCond == 0xE&&  ITCounter != 1) {
    > -    DEBUG(errs()<<  "Encoding error: IT FirstCond '1110'&&  Mask != '1000'");
    > -    return false;
    > +
    > +  if (Shift == ARM_AM::ror&&  imm == 0)
    > +    Shift = ARM_AM::rrx;
    > +
    > +  unsigned Op = Shift | (imm<<  3);
    > +  Inst.addOperand(MCOperand::CreateImm(Op));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeSORegRegOperand(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +
    > +  unsigned Rm = fieldFromInstruction32(Val, 0, 4);
    > +  unsigned type = fieldFromInstruction32(Val, 5, 2);
    > +  unsigned Rs = fieldFromInstruction32(Val, 8, 4);
    > +
    > +  // Register-register
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rs, Address, Decoder);
    > +
    > +  ARM_AM::ShiftOpc Shift = ARM_AM::lsl;
    > +  switch (type) {
    > +    case 0:
    > +      Shift = ARM_AM::lsl;
    > +      break;
    > +    case 1:
    > +      Shift = ARM_AM::lsr;
    > +      break;
    > +    case 2:
    > +      Shift = ARM_AM::asr;
    > +      break;
    > +    case 3:
    > +      Shift = ARM_AM::ror;
    > +      break;
    >     }
    >
    > -  ITState = bits7_0;
    > +  Inst.addOperand(MCOperand::CreateImm(Shift));
    >
    >     return true;
    >   }
    >
    > -/// Update ITState if necessary.
    > -void Session::UpdateIT() {
    > -  assert(ITCounter);
    > -  --ITCounter;
    > -  if (ITCounter == 0)
    > -    ITState = 0;
    > -  else {
    > -    unsigned short NewITState4_0 = slice(ITState, 4, 0)<<  1;
    > -    setSlice(ITState, 4, 0, NewITState4_0);
    > +static bool DecodeRegListOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  for (unsigned i = 0; i<  16; ++i) {
    > +    if (Val&  (1<<  i))
    > +      DecodeGPRRegisterClass(Inst, i, Address, Decoder);
    >     }
    > +
    > +  return true;
    >   }
    >
    > -static MCDisassembler *createARMDisassembler(const Target&T) {
    > -  return new ARMDisassembler;
    > +static bool DecodeSPRRegListOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Vd = fieldFromInstruction32(Val, 8, 4);
    > +  unsigned regs = Val&  0xFF;
    > +
    > +  DecodeSPRRegisterClass(Inst, Vd, Address, Decoder);
    > +  for (unsigned i = 0; i<  (regs - 1); ++i)
    > +    DecodeSPRRegisterClass(Inst, ++Vd, Address, Decoder);
    > +
    > +  return true;
    >   }
    >
    > -static MCDisassembler *createThumbDisassembler(const Target&T) {
    > -  return new ThumbDisassembler;
    > +static bool DecodeDPRRegListOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Vd = fieldFromInstruction32(Val, 8, 4);
    > +  unsigned regs = (Val&  0xFF) / 2;
    > +
    > +  DecodeDPRRegisterClass(Inst, Vd, Address, Decoder);
    > +  for (unsigned i = 0; i<  (regs - 1); ++i)
    > +    DecodeDPRRegisterClass(Inst, ++Vd, Address, Decoder);
    > +
    > +  return true;
    >   }
    >
    > -extern "C" void LLVMInitializeARMDisassembler() {
    > -  // Register the disassembler.
    > -  TargetRegistry::RegisterMCDisassembler(TheARMTarget,
    > -                                         createARMDisassembler);
    > -  TargetRegistry::RegisterMCDisassembler(TheThumbTarget,
    > -                                         createThumbDisassembler);
    > +static bool DecodeBitfieldMaskOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                      uint64_t Address, const void *Decoder) {
    > +  unsigned msb = fieldFromInstruction32(Val, 5, 5);
    > +  unsigned lsb = fieldFromInstruction32(Val, 0, 5);
    > +  uint32_t msb_mask = (1<<  (msb+1)) - 1;
    > +  uint32_t lsb_mask = (1<<  lsb) - 1;
    > +  Inst.addOperand(MCOperand::CreateImm(~(msb_mask ^ lsb_mask)));
    
    What? I think this code has earned some comments. :)
    
    > +  return true;
    >   }
    >
    > -EDInstInfo *ARMDisassembler::getEDInfo() const {
    > -  return instInfoARM;
    > +static bool DecodeCopMemInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned CRd = fieldFromInstruction32(Insn, 12, 4);
    > +  unsigned coproc = fieldFromInstruction32(Insn, 8, 4);
    > +  unsigned imm = fieldFromInstruction32(Insn, 0, 8);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned U = fieldFromInstruction32(Insn, 23, 1);
    > +
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDC_OFFSET:
    > +    case ARM::LDC_PRE:
    > +    case ARM::LDC_POST:
    > +    case ARM::LDC_OPTION:
    > +    case ARM::LDCL_OFFSET:
    > +    case ARM::LDCL_PRE:
    > +    case ARM::LDCL_POST:
    > +    case ARM::LDCL_OPTION:
    > +    case ARM::STC_OFFSET:
    > +    case ARM::STC_PRE:
    > +    case ARM::STC_POST:
    > +    case ARM::STC_OPTION:
    > +    case ARM::STCL_OFFSET:
    > +    case ARM::STCL_PRE:
    > +    case ARM::STCL_POST:
    > +    case ARM::STCL_OPTION:
    > +      if (coproc == 0xA || coproc == 0xB)
    > +        return false;
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(coproc));
    > +  Inst.addOperand(MCOperand::CreateImm(CRd));
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDC_OPTION:
    > +    case ARM::LDCL_OPTION:
    > +    case ARM::LDC2_OPTION:
    > +    case ARM::LDC2L_OPTION:
    > +    case ARM::STC_OPTION:
    > +    case ARM::STCL_OPTION:
    > +    case ARM::STC2_OPTION:
    > +    case ARM::STC2L_OPTION:
    > +    case ARM::LDCL_POST:
    > +    case ARM::STCL_POST:
    > +      break;
    > +    default:
    > +      Inst.addOperand(MCOperand::CreateReg(0));
    > +      break;
    > +  }
    > +
    > +  unsigned P = fieldFromInstruction32(Insn, 24, 1);
    > +  unsigned W = fieldFromInstruction32(Insn, 21, 1);
    > +
    > +  bool writeback = (P == 0) || (W == 1);
    > +  unsigned idx_mode = 0;
    > +  if (P&&  writeback)
    > +    idx_mode = ARMII::IndexModePre;
    > +  else if (!P&&  writeback)
    > +    idx_mode = ARMII::IndexModePost;
    > +
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDCL_POST:
    > +    case ARM::STCL_POST:
    > +      imm |= U<<  8;
    > +    case ARM::LDC_OPTION:
    > +    case ARM::LDCL_OPTION:
    > +    case ARM::LDC2_OPTION:
    > +    case ARM::LDC2L_OPTION:
    > +    case ARM::STC_OPTION:
    > +    case ARM::STCL_OPTION:
    > +    case ARM::STC2_OPTION:
    > +    case ARM::STC2L_OPTION:
    > +      Inst.addOperand(MCOperand::CreateImm(imm));
    > +      break;
    > +    default:
    > +      if (U)
    > +        Inst.addOperand(MCOperand::CreateImm(
    > +            ARM_AM::getAM2Opc(ARM_AM::add, imm, ARM_AM::lsl, idx_mode)));
    > +      else
    > +        Inst.addOperand(MCOperand::CreateImm(
    > +            ARM_AM::getAM2Opc(ARM_AM::sub, imm, ARM_AM::lsl, idx_mode)));
    > +      break;
    > +  }
    > +
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDC_OFFSET:
    > +    case ARM::LDC_PRE:
    > +    case ARM::LDC_POST:
    > +    case ARM::LDC_OPTION:
    > +    case ARM::LDCL_OFFSET:
    > +    case ARM::LDCL_PRE:
    > +    case ARM::LDCL_POST:
    > +    case ARM::LDCL_OPTION:
    > +    case ARM::STC_OFFSET:
    > +    case ARM::STC_PRE:
    > +    case ARM::STC_POST:
    > +    case ARM::STC_OPTION:
    > +    case ARM::STCL_OFFSET:
    > +    case ARM::STCL_PRE:
    > +    case ARM::STCL_POST:
    > +    case ARM::STCL_OPTION:
    > +      if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  return true;
    >   }
    >
    > -EDInstInfo *ThumbDisassembler::getEDInfo() const {
    > -  return instInfoARM;
    > +static bool DecodeAddrMode2IdxInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned imm = fieldFromInstruction32(Insn, 0, 12);
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned reg = fieldFromInstruction32(Insn, 25, 1);
    > +  unsigned P = fieldFromInstruction32(Insn, 24, 1);
    > +  unsigned W = fieldFromInstruction32(Insn, 21, 1);
    > +
    > +  // On stores, the writeback operand precedes Rt.
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::STR_POST_IMM:
    > +    case ARM::STR_POST_REG:
    > +    case ARM::STRTr:
    > +    case ARM::STRTi:
    > +    case ARM::STRBTr:
    > +    case ARM::STRBTi:
    > +      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
    > +
    > +  // On loads, the writeback operand comes after Rt.
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::LDR_POST_IMM:
    > +    case ARM::LDR_POST_REG:
    > +    case ARM::LDR_PRE:
    > +    case ARM::LDRBT_POST_REG:
    > +    case ARM::LDRBT_POST_IMM:
    > +    case ARM::LDRTr:
    > +    case ARM::LDRTi:
    > +      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  ARM_AM::AddrOpc Op = ARM_AM::add;
    > +  if (!fieldFromInstruction32(Insn, 23, 1))
    > +    Op = ARM_AM::sub;
    > +
    > +  bool writeback = (P == 0) || (W == 1);
    > +  unsigned idx_mode = 0;
    > +  if (P&&  writeback)
    > +    idx_mode = ARMII::IndexModePre;
    > +  else if (!P&&  writeback)
    > +    idx_mode = ARMII::IndexModePost;
    > +
    > +  if (reg) {
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +    ARM_AM::ShiftOpc Opc = ARM_AM::lsl;
    > +    switch( fieldFromInstruction32(Insn, 5, 2)) {
    > +      case 0:
    > +        Opc = ARM_AM::lsl;
    > +        break;
    > +      case 1:
    > +        Opc = ARM_AM::lsr;
    > +        break;
    > +      case 2:
    > +        Opc = ARM_AM::asr;
    > +        break;
    > +      case 3:
    > +        Opc = ARM_AM::ror;
    > +        break;
    > +      default:
    > +        return false;
    > +    }
    > +    unsigned amt = fieldFromInstruction32(Insn, 7, 5);
    > +    unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode);
    > +
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +  } else {
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +    unsigned tmp = ARM_AM::getAM2Opc(Op, imm, ARM_AM::lsl, idx_mode);
    > +    Inst.addOperand(MCOperand::CreateImm(tmp));
    > +  }
    > +
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeSORegMemOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 13, 4);
    > +  unsigned Rm = fieldFromInstruction32(Val,  0, 4);
    > +  unsigned type = fieldFromInstruction32(Val, 5, 2);
    > +  unsigned imm = fieldFromInstruction32(Val, 7, 5);
    > +  unsigned U = fieldFromInstruction32(Val, 12, 1);
    > +
    > +  ARM_AM::ShiftOpc ShOp;
    > +  switch (type) {
    > +    case 0:
    > +      ShOp = ARM_AM::lsl;
    > +      break;
    > +    case 1:
    > +      ShOp = ARM_AM::lsr;
    > +      break;
    > +    case 2:
    > +      ShOp = ARM_AM::asr;
    > +      break;
    > +    case 3:
    > +      ShOp = ARM_AM::ror;
    > +      break;
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  unsigned shift;
    > +  if (U)
    > +    shift = ARM_AM::getAM2Opc(ARM_AM::add, imm, ShOp);
    > +  else
    > +    shift = ARM_AM::getAM2Opc(ARM_AM::sub, imm, ShOp);
    > +  Inst.addOperand(MCOperand::CreateImm(shift));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode3Instruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned type = fieldFromInstruction32(Insn, 22, 1);
    > +  unsigned imm = fieldFromInstruction32(Insn, 8, 4);
    > +  unsigned U = ((~fieldFromInstruction32(Insn, 23, 1))&  1)<<  8;
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned W = fieldFromInstruction32(Insn, 21, 1);
    > +  unsigned P = fieldFromInstruction32(Insn, 24, 1);
    > +
    > +  bool writeback = (W == 1) | (P == 0);
    > +  if (writeback) { // Writeback
    > +    if (P)
    > +      U |= ARMII::IndexModePre<<  9;
    > +    else
    > +      U |= ARMII::IndexModePost<<  9;
    > +
    > +    // On stores, the writeback operand precedes Rt.
    > +    switch (Inst.getOpcode()) {
    > +    case ARM::STRD:
    > +    case ARM::STRD_PRE:
    > +    case ARM::STRD_POST:
    > +      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +    }
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::STRD:
    > +    case ARM::STRD_PRE:
    > +    case ARM::STRD_POST:
    > +    case ARM::LDRD:
    > +    case ARM::LDRD_PRE:
    > +    case ARM::LDRD_POST:
    > +      DecodeGPRRegisterClass(Inst, Rt+1, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  if (writeback) {
    > +    // On loads, the writeback operand comes after Rt.
    > +    switch (Inst.getOpcode()) {
    > +    case ARM::LDRD:
    > +    case ARM::LDRD_PRE:
    > +    case ARM::LDRD_POST:
    > +    case ARM::LDRHTr:
    > +    case ARM::LDRSBTr:
    > +      DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +    }
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  if (type) {
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +    Inst.addOperand(MCOperand::CreateImm(U | (imm<<  4) | Rm));
    > +  } else {
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +    Inst.addOperand(MCOperand::CreateImm(U));
    > +  }
    > +
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeRFEInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned mode = fieldFromInstruction32(Insn, 23, 2);
    > +
    > +  switch (mode) {
    > +    case 0:
    > +      mode = ARM_AM::da;
    > +      break;
    > +    case 1:
    > +      mode = ARM_AM::ia;
    > +      break;
    > +    case 2:
    > +      mode = ARM_AM::db;
    > +      break;
    > +    case 3:
    > +      mode = ARM_AM::ib;
    > +      break;
    > +  }
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(mode));
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeMemMultipleWritebackInstruction(llvm::MCInst&Inst,
    > +                                  unsigned Insn,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned reglist = fieldFromInstruction32(Insn, 0, 16);
    > +
    > +  if (pred == 0xF) {
    > +    switch (Inst.getOpcode()) {
    > +      case ARM::STMDA:
    > +        Inst.setOpcode(ARM::RFEDA);
    > +        break;
    > +      case ARM::STMDA_UPD:
    > +        Inst.setOpcode(ARM::RFEDA_UPD);
    > +        break;
    > +      case ARM::STMDB:
    > +        Inst.setOpcode(ARM::RFEDB);
    > +        break;
    > +      case ARM::STMDB_UPD:
    > +        Inst.setOpcode(ARM::RFEDB_UPD);
    > +        break;
    > +      case ARM::STMIA:
    > +        Inst.setOpcode(ARM::RFEIA);
    > +        break;
    > +      case ARM::STMIA_UPD:
    > +        Inst.setOpcode(ARM::RFEIA_UPD);
    > +        break;
    > +      case ARM::STMIB:
    > +        Inst.setOpcode(ARM::RFEIB);
    > +        break;
    > +      case ARM::STMIB_UPD:
    > +        Inst.setOpcode(ARM::RFEIB_UPD);
    > +        break;
    > +
    
    Extra newline.
    
    > +    }
    > +    return DecodeRFEInstruction(Inst, Insn, Address, Decoder);
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder); // Tied
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +  DecodeRegListOperand(Inst, reglist, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeCPSInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned imod = fieldFromInstruction32(Insn, 18, 2);
    > +  unsigned M = fieldFromInstruction32(Insn, 17, 1);
    > +  unsigned iflags = fieldFromInstruction32(Insn, 6, 3);
    > +  unsigned mode = fieldFromInstruction32(Insn, 0, 5);
    > +
    > +  if (M&&  mode&&  imod&&  iflags) {
    > +    Inst.setOpcode(ARM::CPS3p);
    > +    Inst.addOperand(MCOperand::CreateImm(imod));
    > +    Inst.addOperand(MCOperand::CreateImm(iflags));
    > +    Inst.addOperand(MCOperand::CreateImm(mode));
    > +    return true;
    > +  } else if (!mode&&  !M) {
    > +    Inst.setOpcode(ARM::CPS2p);
    > +    Inst.addOperand(MCOperand::CreateImm(imod));
    > +    Inst.addOperand(MCOperand::CreateImm(iflags));
    > +    return true;
    > +  } else if (!imod&&  !iflags&&  M) {
    > +    Inst.setOpcode(ARM::CPS1p);
    > +    Inst.addOperand(MCOperand::CreateImm(mode));
    > +    return true;
    > +  }
    > +
    > +  return false;
    > +}
    > +
    > +static bool DecodeSMLAInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 8, 4);
    > +  unsigned Ra = fieldFromInstruction32(Insn, 12, 4);
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +
    > +  if (pred == 0xF)
    > +    return DecodeCPSInstruction(Inst, Insn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  DecodeGPRRegisterClass(Inst, Ra, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrModeImm12Operand(llvm::MCInst&Inst, unsigned Val,
    > +                           uint64_t Address, const void *Decoder) {
    > +  unsigned add = fieldFromInstruction32(Val, 12, 1);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 12);
    > +  unsigned Rn = fieldFromInstruction32(Val, 13, 4);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  if (!add) imm *= -1;
    > +  if (imm == 0&&  !add) imm = INT32_MIN;
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode5Operand(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 9, 4);
    > +  unsigned U = fieldFromInstruction32(Val, 8, 1);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 8);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  if (U)
    > +    Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add, imm)));
    > +  else
    > +    Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub, imm)));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode7Operand(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  return DecodeGPRRegisterClass(Inst, Val, Address, Decoder);
    > +}
    > +
    > +static bool DecodeBranchImmInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned pred = fieldFromInstruction32(Insn, 28, 4);
    > +  unsigned imm = fieldFromInstruction32(Insn, 0, 24)<<  2;
    > +
    > +  if (pred == 0xF) {
    > +    Inst.setOpcode(ARM::BLXi);
    > +    imm |= fieldFromInstruction32(Insn, 24, 1)<<  1;
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +    return true;
    > +  }
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder)) return false;
    > +
    > +  return true;
    > +}
    > +
    > +
    > +static bool DecodeVCVTImmOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(64 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeAddrMode6Operand(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rm = fieldFromInstruction32(Val, 0, 4);
    > +  unsigned align = fieldFromInstruction32(Val, 4, 2);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  if (!align)
    > +    Inst.addOperand(MCOperand::CreateImm(0));
    > +  else
    > +    Inst.addOperand(MCOperand::CreateImm(4<<  align));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLDInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned wb = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  Rn |= fieldFromInstruction32(Insn, 4, 2)<<  4;
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +
    > +  // First output register
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +
    > +  // Second output register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VLD1q8:
    > +    case ARM::VLD1q16:
    > +    case ARM::VLD1q32:
    > +    case ARM::VLD1q64:
    > +    case ARM::VLD1q8_UPD:
    > +    case ARM::VLD1q16_UPD:
    > +    case ARM::VLD1q32_UPD:
    > +    case ARM::VLD1q64_UPD:
    > +    case ARM::VLD1d8T:
    > +    case ARM::VLD1d16T:
    > +    case ARM::VLD1d32T:
    > +    case ARM::VLD1d64T:
    > +    case ARM::VLD1d8T_UPD:
    > +    case ARM::VLD1d16T_UPD:
    > +    case ARM::VLD1d32T_UPD:
    > +    case ARM::VLD1d64T_UPD:
    > +    case ARM::VLD1d8Q:
    > +    case ARM::VLD1d16Q:
    > +    case ARM::VLD1d32Q:
    > +    case ARM::VLD1d64Q:
    > +    case ARM::VLD1d8Q_UPD:
    > +    case ARM::VLD1d16Q_UPD:
    > +    case ARM::VLD1d32Q_UPD:
    > +    case ARM::VLD1d64Q_UPD:
    > +    case ARM::VLD2d8:
    > +    case ARM::VLD2d16:
    > +    case ARM::VLD2d32:
    > +    case ARM::VLD2d8_UPD:
    > +    case ARM::VLD2d16_UPD:
    > +    case ARM::VLD2d32_UPD:
    > +    case ARM::VLD2q8:
    > +    case ARM::VLD2q16:
    > +    case ARM::VLD2q32:
    > +    case ARM::VLD2q8_UPD:
    > +    case ARM::VLD2q16_UPD:
    > +    case ARM::VLD2q32_UPD:
    > +    case ARM::VLD3d8:
    > +    case ARM::VLD3d16:
    > +    case ARM::VLD3d32:
    > +    case ARM::VLD3d8_UPD:
    > +    case ARM::VLD3d16_UPD:
    > +    case ARM::VLD3d32_UPD:
    > +    case ARM::VLD4d8:
    > +    case ARM::VLD4d16:
    > +    case ARM::VLD4d32:
    > +    case ARM::VLD4d8_UPD:
    > +    case ARM::VLD4d16_UPD:
    > +    case ARM::VLD4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VLD2b8:
    > +    case ARM::VLD2b16:
    > +    case ARM::VLD2b32:
    > +    case ARM::VLD2b8_UPD:
    > +    case ARM::VLD2b16_UPD:
    > +    case ARM::VLD2b32_UPD:
    > +    case ARM::VLD3q8:
    > +    case ARM::VLD3q16:
    > +    case ARM::VLD3q32:
    > +    case ARM::VLD3q8_UPD:
    > +    case ARM::VLD3q16_UPD:
    > +    case ARM::VLD3q32_UPD:
    > +    case ARM::VLD4q8:
    > +    case ARM::VLD4q16:
    > +    case ARM::VLD4q32:
    > +    case ARM::VLD4q8_UPD:
    > +    case ARM::VLD4q16_UPD:
    > +    case ARM::VLD4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Third output register
    > +  switch(Inst.getOpcode()) {
    > +    case ARM::VLD1d8T:
    > +    case ARM::VLD1d16T:
    > +    case ARM::VLD1d32T:
    > +    case ARM::VLD1d64T:
    > +    case ARM::VLD1d8T_UPD:
    > +    case ARM::VLD1d16T_UPD:
    > +    case ARM::VLD1d32T_UPD:
    > +    case ARM::VLD1d64T_UPD:
    > +    case ARM::VLD1d8Q:
    > +    case ARM::VLD1d16Q:
    > +    case ARM::VLD1d32Q:
    > +    case ARM::VLD1d64Q:
    > +    case ARM::VLD1d8Q_UPD:
    > +    case ARM::VLD1d16Q_UPD:
    > +    case ARM::VLD1d32Q_UPD:
    > +    case ARM::VLD1d64Q_UPD:
    > +    case ARM::VLD2q8:
    > +    case ARM::VLD2q16:
    > +    case ARM::VLD2q32:
    > +    case ARM::VLD2q8_UPD:
    > +    case ARM::VLD2q16_UPD:
    > +    case ARM::VLD2q32_UPD:
    > +    case ARM::VLD3d8:
    > +    case ARM::VLD3d16:
    > +    case ARM::VLD3d32:
    > +    case ARM::VLD3d8_UPD:
    > +    case ARM::VLD3d16_UPD:
    > +    case ARM::VLD3d32_UPD:
    > +    case ARM::VLD4d8:
    > +    case ARM::VLD4d16:
    > +    case ARM::VLD4d32:
    > +    case ARM::VLD4d8_UPD:
    > +    case ARM::VLD4d16_UPD:
    > +    case ARM::VLD4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VLD3q8:
    > +    case ARM::VLD3q16:
    > +    case ARM::VLD3q32:
    > +    case ARM::VLD3q8_UPD:
    > +    case ARM::VLD3q16_UPD:
    > +    case ARM::VLD3q32_UPD:
    > +    case ARM::VLD4q8:
    > +    case ARM::VLD4q16:
    > +    case ARM::VLD4q32:
    > +    case ARM::VLD4q8_UPD:
    > +    case ARM::VLD4q16_UPD:
    > +    case ARM::VLD4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Fourth output register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VLD1d8Q:
    > +    case ARM::VLD1d16Q:
    > +    case ARM::VLD1d32Q:
    > +    case ARM::VLD1d64Q:
    > +    case ARM::VLD1d8Q_UPD:
    > +    case ARM::VLD1d16Q_UPD:
    > +    case ARM::VLD1d32Q_UPD:
    > +    case ARM::VLD1d64Q_UPD:
    > +    case ARM::VLD2q8:
    > +    case ARM::VLD2q16:
    > +    case ARM::VLD2q32:
    > +    case ARM::VLD2q8_UPD:
    > +    case ARM::VLD2q16_UPD:
    > +    case ARM::VLD2q32_UPD:
    > +    case ARM::VLD4d8:
    > +    case ARM::VLD4d16:
    > +    case ARM::VLD4d32:
    > +    case ARM::VLD4d8_UPD:
    > +    case ARM::VLD4d16_UPD:
    > +    case ARM::VLD4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VLD4q8:
    > +    case ARM::VLD4q16:
    > +    case ARM::VLD4q32:
    > +    case ARM::VLD4q8_UPD:
    > +    case ARM::VLD4q16_UPD:
    > +    case ARM::VLD4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Writeback operand
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VLD1d8_UPD:
    > +    case ARM::VLD1d16_UPD:
    > +    case ARM::VLD1d32_UPD:
    > +    case ARM::VLD1d64_UPD:
    > +    case ARM::VLD1q8_UPD:
    > +    case ARM::VLD1q16_UPD:
    > +    case ARM::VLD1q32_UPD:
    > +    case ARM::VLD1q64_UPD:
    > +    case ARM::VLD1d8T_UPD:
    > +    case ARM::VLD1d16T_UPD:
    > +    case ARM::VLD1d32T_UPD:
    > +    case ARM::VLD1d64T_UPD:
    > +    case ARM::VLD1d8Q_UPD:
    > +    case ARM::VLD1d16Q_UPD:
    > +    case ARM::VLD1d32Q_UPD:
    > +    case ARM::VLD1d64Q_UPD:
    > +    case ARM::VLD2d8_UPD:
    > +    case ARM::VLD2d16_UPD:
    > +    case ARM::VLD2d32_UPD:
    > +    case ARM::VLD2q8_UPD:
    > +    case ARM::VLD2q16_UPD:
    > +    case ARM::VLD2q32_UPD:
    > +    case ARM::VLD2b8_UPD:
    > +    case ARM::VLD2b16_UPD:
    > +    case ARM::VLD2b32_UPD:
    > +    case ARM::VLD3d8_UPD:
    > +    case ARM::VLD3d16_UPD:
    > +    case ARM::VLD3d32_UPD:
    > +    case ARM::VLD3q8_UPD:
    > +    case ARM::VLD3q16_UPD:
    > +    case ARM::VLD3q32_UPD:
    > +    case ARM::VLD4d8_UPD:
    > +    case ARM::VLD4d16_UPD:
    > +    case ARM::VLD4d32_UPD:
    > +    case ARM::VLD4q8_UPD:
    > +    case ARM::VLD4q16_UPD:
    > +    case ARM::VLD4q32_UPD:
    > +      DecodeGPRRegisterClass(Inst, wb, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // AddrMode6 Base (register+alignment)
    > +  DecodeAddrMode6Operand(Inst, Rn, Address, Decoder);
    > +
    > +  // AddrMode6 Offset (register)
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVSTInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned wb = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  Rn |= fieldFromInstruction32(Insn, 4, 2)<<  4;
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +
    > +  // Writeback Operand
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VST1d8_UPD:
    > +    case ARM::VST1d16_UPD:
    > +    case ARM::VST1d32_UPD:
    > +    case ARM::VST1d64_UPD:
    > +    case ARM::VST1q8_UPD:
    > +    case ARM::VST1q16_UPD:
    > +    case ARM::VST1q32_UPD:
    > +    case ARM::VST1q64_UPD:
    > +    case ARM::VST1d8T_UPD:
    > +    case ARM::VST1d16T_UPD:
    > +    case ARM::VST1d32T_UPD:
    > +    case ARM::VST1d64T_UPD:
    > +    case ARM::VST1d8Q_UPD:
    > +    case ARM::VST1d16Q_UPD:
    > +    case ARM::VST1d32Q_UPD:
    > +    case ARM::VST1d64Q_UPD:
    > +    case ARM::VST2d8_UPD:
    > +    case ARM::VST2d16_UPD:
    > +    case ARM::VST2d32_UPD:
    > +    case ARM::VST2q8_UPD:
    > +    case ARM::VST2q16_UPD:
    > +    case ARM::VST2q32_UPD:
    > +    case ARM::VST2b8_UPD:
    > +    case ARM::VST2b16_UPD:
    > +    case ARM::VST2b32_UPD:
    > +    case ARM::VST3d8_UPD:
    > +    case ARM::VST3d16_UPD:
    > +    case ARM::VST3d32_UPD:
    > +    case ARM::VST3q8_UPD:
    > +    case ARM::VST3q16_UPD:
    > +    case ARM::VST3q32_UPD:
    > +    case ARM::VST4d8_UPD:
    > +    case ARM::VST4d16_UPD:
    > +    case ARM::VST4d32_UPD:
    > +    case ARM::VST4q8_UPD:
    > +    case ARM::VST4q16_UPD:
    > +    case ARM::VST4q32_UPD:
    > +      DecodeGPRRegisterClass(Inst, wb, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // AddrMode6 Base (register+alignment)
    > +  DecodeAddrMode6Operand(Inst, Rn, Address, Decoder);
    > +
    > +  // AddrMode6 Offset (register)
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  // First input register
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +
    > +  // Second input register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VST1q8:
    > +    case ARM::VST1q16:
    > +    case ARM::VST1q32:
    > +    case ARM::VST1q64:
    > +    case ARM::VST1q8_UPD:
    > +    case ARM::VST1q16_UPD:
    > +    case ARM::VST1q32_UPD:
    > +    case ARM::VST1q64_UPD:
    > +    case ARM::VST1d8T:
    > +    case ARM::VST1d16T:
    > +    case ARM::VST1d32T:
    > +    case ARM::VST1d64T:
    > +    case ARM::VST1d8T_UPD:
    > +    case ARM::VST1d16T_UPD:
    > +    case ARM::VST1d32T_UPD:
    > +    case ARM::VST1d64T_UPD:
    > +    case ARM::VST1d8Q:
    > +    case ARM::VST1d16Q:
    > +    case ARM::VST1d32Q:
    > +    case ARM::VST1d64Q:
    > +    case ARM::VST1d8Q_UPD:
    > +    case ARM::VST1d16Q_UPD:
    > +    case ARM::VST1d32Q_UPD:
    > +    case ARM::VST1d64Q_UPD:
    > +    case ARM::VST2d8:
    > +    case ARM::VST2d16:
    > +    case ARM::VST2d32:
    > +    case ARM::VST2d8_UPD:
    > +    case ARM::VST2d16_UPD:
    > +    case ARM::VST2d32_UPD:
    > +    case ARM::VST2q8:
    > +    case ARM::VST2q16:
    > +    case ARM::VST2q32:
    > +    case ARM::VST2q8_UPD:
    > +    case ARM::VST2q16_UPD:
    > +    case ARM::VST2q32_UPD:
    > +    case ARM::VST3d8:
    > +    case ARM::VST3d16:
    > +    case ARM::VST3d32:
    > +    case ARM::VST3d8_UPD:
    > +    case ARM::VST3d16_UPD:
    > +    case ARM::VST3d32_UPD:
    > +    case ARM::VST4d8:
    > +    case ARM::VST4d16:
    > +    case ARM::VST4d32:
    > +    case ARM::VST4d8_UPD:
    > +    case ARM::VST4d16_UPD:
    > +    case ARM::VST4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VST2b8:
    > +    case ARM::VST2b16:
    > +    case ARM::VST2b32:
    > +    case ARM::VST2b8_UPD:
    > +    case ARM::VST2b16_UPD:
    > +    case ARM::VST2b32_UPD:
    > +    case ARM::VST3q8:
    > +    case ARM::VST3q16:
    > +    case ARM::VST3q32:
    > +    case ARM::VST3q8_UPD:
    > +    case ARM::VST3q16_UPD:
    > +    case ARM::VST3q32_UPD:
    > +    case ARM::VST4q8:
    > +    case ARM::VST4q16:
    > +    case ARM::VST4q32:
    > +    case ARM::VST4q8_UPD:
    > +    case ARM::VST4q16_UPD:
    > +    case ARM::VST4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Third input register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VST1d8T:
    > +    case ARM::VST1d16T:
    > +    case ARM::VST1d32T:
    > +    case ARM::VST1d64T:
    > +    case ARM::VST1d8T_UPD:
    > +    case ARM::VST1d16T_UPD:
    > +    case ARM::VST1d32T_UPD:
    > +    case ARM::VST1d64T_UPD:
    > +    case ARM::VST1d8Q:
    > +    case ARM::VST1d16Q:
    > +    case ARM::VST1d32Q:
    > +    case ARM::VST1d64Q:
    > +    case ARM::VST1d8Q_UPD:
    > +    case ARM::VST1d16Q_UPD:
    > +    case ARM::VST1d32Q_UPD:
    > +    case ARM::VST1d64Q_UPD:
    > +    case ARM::VST2q8:
    > +    case ARM::VST2q16:
    > +    case ARM::VST2q32:
    > +    case ARM::VST2q8_UPD:
    > +    case ARM::VST2q16_UPD:
    > +    case ARM::VST2q32_UPD:
    > +    case ARM::VST3d8:
    > +    case ARM::VST3d16:
    > +    case ARM::VST3d32:
    > +    case ARM::VST3d8_UPD:
    > +    case ARM::VST3d16_UPD:
    > +    case ARM::VST3d32_UPD:
    > +    case ARM::VST4d8:
    > +    case ARM::VST4d16:
    > +    case ARM::VST4d32:
    > +    case ARM::VST4d8_UPD:
    > +    case ARM::VST4d16_UPD:
    > +    case ARM::VST4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+2)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VST3q8:
    > +    case ARM::VST3q16:
    > +    case ARM::VST3q32:
    > +    case ARM::VST3q8_UPD:
    > +    case ARM::VST3q16_UPD:
    > +    case ARM::VST3q32_UPD:
    > +    case ARM::VST4q8:
    > +    case ARM::VST4q16:
    > +    case ARM::VST4q32:
    > +    case ARM::VST4q8_UPD:
    > +    case ARM::VST4q16_UPD:
    > +    case ARM::VST4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+4)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  // Fourth input register
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VST1d8Q:
    > +    case ARM::VST1d16Q:
    > +    case ARM::VST1d32Q:
    > +    case ARM::VST1d64Q:
    > +    case ARM::VST1d8Q_UPD:
    > +    case ARM::VST1d16Q_UPD:
    > +    case ARM::VST1d32Q_UPD:
    > +    case ARM::VST1d64Q_UPD:
    > +    case ARM::VST2q8:
    > +    case ARM::VST2q16:
    > +    case ARM::VST2q32:
    > +    case ARM::VST2q8_UPD:
    > +    case ARM::VST2q16_UPD:
    > +    case ARM::VST2q32_UPD:
    > +    case ARM::VST4d8:
    > +    case ARM::VST4d16:
    > +    case ARM::VST4d32:
    > +    case ARM::VST4d8_UPD:
    > +    case ARM::VST4d16_UPD:
    > +    case ARM::VST4d32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+3)%32, Address, Decoder);
    > +      break;
    > +    case ARM::VST4q8:
    > +    case ARM::VST4q16:
    > +    case ARM::VST4q32:
    > +    case ARM::VST4q8_UPD:
    > +    case ARM::VST4q16_UPD:
    > +    case ARM::VST4q32_UPD:
    > +      DecodeDPRRegisterClass(Inst, (Rd+6)%32, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLD1DupInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                    uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned align = fieldFromInstruction32(Insn, 4, 1);
    > +  unsigned size = fieldFromInstruction32(Insn, 6, 2);
    > +  unsigned regs = fieldFromInstruction32(Insn, 5, 1) + 1;
    > +
    > +  align *= (1<<  size);
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  if (regs == 2) DecodeDPRRegisterClass(Inst, (Rd+1)%32, Address, Decoder);
    > +  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(align));
    > +
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLD2DupInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                    uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned align = fieldFromInstruction32(Insn, 4, 1);
    > +  unsigned size = 1<<  fieldFromInstruction32(Insn, 6, 2);
    > +  unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
    > +  align *= 2*size;
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
    > +  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(align));
    > +
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLD3DupInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                    uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder);
    > +  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(0));
    > +
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVLD4DupInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                    uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned size = fieldFromInstruction32(Insn, 6, 2);
    > +  unsigned inc = fieldFromInstruction32(Insn, 5, 1) + 1;
    > +  unsigned align = fieldFromInstruction32(Insn, 4, 1);
    > +
    > +  if (size == 0x3) {
    > +    size = 4;
    > +    align = 16;
    > +  } else {
    > +    if (size == 2) {
    > +      size = 1<<  size;
    > +      align *= 8;
    > +    } else {
    > +      size = 1<<  size;
    > +      align *= 4*size;
    > +    }
    > +  }
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+inc)%32, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+2*inc)%32, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, (Rd+3*inc)%32, Address, Decoder);
    > +  if (Rm == 0xD) DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(align));
    > +
    > +  if (Rm == 0xD)
    > +    Inst.addOperand(MCOperand::CreateReg(0));
    > +  else if (Rm != 0xF)
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeNEONModImmInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                        uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned imm = fieldFromInstruction32(Insn, 0, 4);
    > +  imm |= fieldFromInstruction32(Insn, 16, 3)<<  4;
    > +  imm |= fieldFromInstruction32(Insn, 24, 1)<<  7;
    > +  imm |= fieldFromInstruction32(Insn, 8, 4)<<  8;
    > +  imm |= fieldFromInstruction32(Insn, 5, 1)<<  12;
    > +  unsigned Q = fieldFromInstruction32(Insn, 6, 1);
    > +
    > +  if (Q)
    > +    DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  else
    > +    DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::VORRiv4i16:
    > +    case ARM::VORRiv2i32:
    > +    case ARM::VBICiv4i16:
    > +    case ARM::VBICiv2i32:
    > +      DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +      break;
    > +    case ARM::VORRiv8i16:
    > +    case ARM::VORRiv4i32:
    > +    case ARM::VBICiv8i16:
    > +    case ARM::VBICiv4i32:
    > +      DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +
    
    Extra newline.
    
    > +  return true;
    > +}
    > +
    > +static bool DecodeVSHLMaxInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                        uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  Rm |= fieldFromInstruction32(Insn, 5, 1)<<  4;
    > +  unsigned size = fieldFromInstruction32(Insn, 18, 2);
    > +
    > +  DecodeQPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  DecodeDPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(8<<  size));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeShiftRight8Imm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(8 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeShiftRight16Imm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(16 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeShiftRight32Imm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(32 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeShiftRight64Imm(llvm::MCInst&Inst, unsigned Val,
    > +                               uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(64 - Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeTBLInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                               uint64_t Address, const void *Decoder) {
    > +  unsigned Rd = fieldFromInstruction32(Insn, 12, 4);
    > +  Rd |= fieldFromInstruction32(Insn, 22, 1)<<  4;
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  Rn |= fieldFromInstruction32(Insn, 7, 1)<<  4;
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  Rm |= fieldFromInstruction32(Insn, 5, 1)<<  4;
    > +  unsigned op = fieldFromInstruction32(Insn, 6, 1);
    > +  unsigned length = fieldFromInstruction32(Insn, 8, 2) + 1;
    > +
    > +  DecodeDPRRegisterClass(Inst, Rd, Address, Decoder);
    > +  if (op) DecodeDPRRegisterClass(Inst, Rd, Address, Decoder); // Writeback
    > +
    > +  for (unsigned i = 0; i<  length; ++i)
    > +    DecodeDPRRegisterClass(Inst, (Rn+i)%32, Address, Decoder);
    > +
    > +  DecodeDPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeVFPfpImm(llvm::MCInst&Inst, unsigned Val,
    > +                            uint64_t Address, const void *Decoder) {
    > +  // The immediate needs to be a fully instantiated float.  However, the
    > +  // auto-generated decoder is only able to fill in some of the bits
    > +  // necessary.  For instance, the 'b' bit is replicated multiple times,
    > +  // and is even present in inverted form in one bit.  We do a little
    > +  // binary parsing here to fill in those missing bits, and then
    > +  // reinterpret it all as a float.
    > +  union {
    > +    uint32_t integer;
    > +    float fp;
    > +  } fp_conv;
    > +
    > +  fp_conv.integer = Val;
    > +  uint32_t b = fieldFromInstruction32(Val, 25, 1);
    > +  fp_conv.integer |= b<<  26;
    > +  fp_conv.integer |= b<<  27;
    > +  fp_conv.integer |= b<<  28;
    > +  fp_conv.integer |= b<<  29;
    > +  fp_conv.integer |= (~b&  0x1)<<  30;
    > +
    > +  Inst.addOperand(MCOperand::CreateFPImm(fp_conv.fp));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddSpecialReg(llvm::MCInst&Inst, uint16_t Insn,
    > +                                     uint64_t Address, const void *Decoder) {
    > +  unsigned dst = fieldFromInstruction16(Insn, 8, 3);
    > +  unsigned imm = fieldFromInstruction16(Insn, 0, 8);
    > +
    > +  DecodetGPRRegisterClass(Inst, dst, Address, Decoder);
    > +
    > +  if (Inst.getOpcode() == ARM::tADR)
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::PC));
    > +  else if (Inst.getOpcode() == ARM::tADDrSPi)
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +  else
    > +    return false;
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbBROperand(llvm::MCInst&Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<12>(Val<<  1)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2BROperand(llvm::MCInst&Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<21>(Val)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbCmpBROperand(llvm::MCInst&Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<7>(Val<<  1)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddrModeRR(llvm::MCInst&Inst, unsigned Val,
    > +                                 uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 0, 3);
    > +  unsigned Rm = fieldFromInstruction32(Val, 3, 3);
    > +
    > +  DecodetGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodetGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddrModeIS(llvm::MCInst&Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 0, 3);
    > +  unsigned imm = fieldFromInstruction32(Val, 3, 5);
    > +
    > +  DecodetGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddrModePC(llvm::MCInst&Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateImm(Val<<  2));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddrModeSP(llvm::MCInst&Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +  Inst.addOperand(MCOperand::CreateImm(Val<<  2));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2AddrModeSOReg(llvm::MCInst&Inst, unsigned Val,
    > +                                  uint64_t Address, const void *Decoder) {
    > +  unsigned Rn = fieldFromInstruction32(Val, 6, 4);
    > +  unsigned Rm = fieldFromInstruction32(Val, 2, 4);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 2);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecoderGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2LoadShift(llvm::MCInst&Inst, unsigned Insn,
    > +                              uint64_t Address, const void *Decoder) {
    > +  if (Inst.getOpcode() != ARM::t2PLDs) {
    > +    unsigned Rt = fieldFromInstruction32(Insn, 12, 4);
    > +    DecodeGPRRegisterClass(Inst, Rt, Address, Decoder);
    > +  }
    > +
    > +  unsigned Rn = fieldFromInstruction32(Insn, 16, 4);
    > +  if (Rn == 0xF) {
    > +    switch (Inst.getOpcode()) {
    > +      case ARM::t2LDRBs:
    > +        Inst.setOpcode(ARM::t2LDRBpci);
    > +        break;
    > +      case ARM::t2LDRHs:
    > +        Inst.setOpcode(ARM::t2LDRHpci);
    > +        break;
    > +      case ARM::t2LDRSHs:
    > +        Inst.setOpcode(ARM::t2LDRSHpci);
    > +        break;
    > +      case ARM::t2LDRSBs:
    > +        Inst.setOpcode(ARM::t2LDRSBpci);
    > +        break;
    > +      case ARM::t2PLDs:
    > +        Inst.setOpcode(ARM::t2PLDi12);
    > +        Inst.addOperand(MCOperand::CreateReg(ARM::PC));
    > +        break;
    > +      default:
    > +        return false;
    > +    }
    > +
    > +    int imm = fieldFromInstruction32(Insn, 0, 12);
    > +    if (!fieldFromInstruction32(Insn, 23, 1)) imm *= -1;
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +    return true;
    > +  }
    > +
    > +  unsigned addrmode = fieldFromInstruction32(Insn, 4, 2);
    > +  addrmode |= fieldFromInstruction32(Insn, 0, 4)<<  2;
    > +  addrmode |= fieldFromInstruction32(Insn, 16, 4)<<  6;
    > +  DecodeT2AddrModeSOReg(Inst, addrmode, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2Imm8S4(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    
    Please fix whitespace!
    
    > +  int imm = Val&  0xFF;
    > +  if (!(Val&  0x100)) imm *= -1;
    > +  Inst.addOperand(MCOperand::CreateImm(imm<<  2));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2AddrModeImm8s4(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    
    Whitespace.
    
    > +  unsigned Rn = fieldFromInstruction32(Val, 9, 4);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 9);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeT2Imm8S4(Inst, imm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeT2Imm8(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    
    Whitespace!
    
    > +  int imm = Val&  0xFF;
    > +  if (!(Val&  0x100)) imm *= -1;
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +
    > +static bool DecodeT2AddrModeImm8(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    
    Spacing.
    
    > +  unsigned Rn = fieldFromInstruction32(Val, 9, 4);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 9);
    > +
    > +  // Some instructions always use an additive offset.
    > +  switch (Inst.getOpcode()) {
    > +    case ARM::t2LDRT:
    > +    case ARM::t2LDRBT:
    > +    case ARM::t2LDRHT:
    > +    case ARM::t2LDRSBT:
    > +    case ARM::t2LDRSHT:
    > +      imm |= 0x100;
    > +      break;
    > +    default:
    > +      break;
    > +  }
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  DecodeT2Imm8(Inst, imm, Address, Decoder);
    > +
    > +  return true;
    > +}
    > +
    > +
    > +static bool DecodeT2AddrModeImm12(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    
    Spacing.
    
    > +  unsigned Rn = fieldFromInstruction32(Val, 13, 4);
    > +  unsigned imm = fieldFromInstruction32(Val, 0, 12);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rn, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +
    > +static bool DecodeThumbAddSPImm(llvm::MCInst&Inst, uint16_t Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    
    Spacing.
    
    > +  unsigned imm = fieldFromInstruction16(Insn, 0, 7);
    > +
    > +  Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +  Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +  Inst.addOperand(MCOperand::CreateImm(imm));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbAddSPReg(llvm::MCInst&Inst, uint16_t Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    
    Spacing?
    
    > +  if (Inst.getOpcode() == ARM::tADDrSP) {
    > +    unsigned Rdm = fieldFromInstruction16(Insn, 0, 3);
    > +    Rdm |= fieldFromInstruction16(Insn, 7, 1)<<  3;
    > +
    > +    DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder);
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +    DecodeGPRRegisterClass(Inst, Rdm, Address, Decoder);
    > +  } else if (Inst.getOpcode() == ARM::tADDspr) {
    > +    unsigned Rm = fieldFromInstruction16(Insn, 3, 4);
    > +
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +    Inst.addOperand(MCOperand::CreateReg(ARM::SP));
    > +    DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  }
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbCPS(llvm::MCInst&Inst, uint16_t Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    
    Spacing!
    
    > +  unsigned imod = fieldFromInstruction16(Insn, 4, 1) | 0x2;
    > +  unsigned flags = fieldFromInstruction16(Insn, 0, 3);
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(imod));
    > +  Inst.addOperand(MCOperand::CreateImm(flags));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodePostIdxReg(llvm::MCInst&Inst, unsigned Insn,
    > +                                   uint64_t Address, const void *Decoder) {
    
    whitespace
    
    > +  unsigned Rm = fieldFromInstruction32(Insn, 0, 4);
    > +  unsigned add = fieldFromInstruction32(Insn, 4, 1);
    > +
    > +  DecodeGPRRegisterClass(Inst, Rm, Address, Decoder);
    > +  Inst.addOperand(MCOperand::CreateImm(add));
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbBLXOffset(llvm::MCInst&Inst, unsigned Val,
    > +                                   uint64_t Address, const void *Decoder) {
    
    whitespace
    
    > +  Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val<<  1)));
    > +  return true;
    > +}
    > +
    > +static bool DecodeCoprocessor(llvm::MCInst&Inst, unsigned Val,
    > +                              uint64_t Address, const void *Decoder) {
    > +  if (Val == 0xA || Val == 0xB)
    > +    return false;
    > +
    > +  Inst.addOperand(MCOperand::CreateImm(Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbSRImm(llvm::MCInst&Inst, unsigned Val,
    > +                              uint64_t Address, const void *Decoder) {
    
    whitespace
    
    > +  if (Val == 0)
    > +    Inst.addOperand(MCOperand::CreateImm(32));
    > +  else
    > +    Inst.addOperand(MCOperand::CreateImm(Val));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumb2BCCInstruction(llvm::MCInst&Inst, unsigned Insn,
    > +                                       uint64_t Address, const void *Decoder) {
    > +  unsigned pred = fieldFromInstruction32(Insn, 22, 4);
    > +  if (pred == 0xE || pred == 0xF) {
    > +    unsigned opc = fieldFromInstruction32(Insn, 4, 2);
    > +    switch (opc) {
    > +      default:
    > +        return false;
    > +      case 0:
    > +        Inst.setOpcode(ARM::t2DSB);
    > +        break;
    > +      case 1:
    > +        Inst.setOpcode(ARM::t2DMB);
    > +        break;
    > +      case 2:
    > +        Inst.setOpcode(ARM::t2ISB);
    > +        return true;
    > +    }
    > +
    > +    unsigned imm = fieldFromInstruction32(Insn, 0, 4);
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +    return true;
    > +  }
    > +
    > +  unsigned brtarget = fieldFromInstruction32(Insn, 0, 11)<<  1;
    > +  brtarget |= fieldFromInstruction32(Insn, 11, 1)<<  19;
    > +  brtarget |= fieldFromInstruction32(Insn, 13, 1)<<  18;
    > +  brtarget |= fieldFromInstruction32(Insn, 16, 6)<<  12;
    > +  brtarget |= fieldFromInstruction32(Insn, 26, 1)<<  20;
    > +
    > +  DecodeT2BROperand(Inst, brtarget, Address, Decoder);
    > +  if (!DecodePredicateOperand(Inst, pred, Address, Decoder))
    > +    return false;
    > +
    > +  return true;
    > +}
    > +
    > +// Decode a shifted immediate operand.  These basically consist
    > +// of an 8-bit value, and a 4-bit directive that specifies either
    > +// a splat operation or a rotation.
    > +static bool DecodeT2SOImm(llvm::MCInst&Inst, unsigned Val,
    > +                          uint64_t Address, const void *Decoder) {
    > +  unsigned ctrl = fieldFromInstruction32(Val, 10, 2);
    > +  if (ctrl == 0) {
    > +    unsigned byte = fieldFromInstruction32(Val, 8, 2);
    > +    unsigned imm = fieldFromInstruction32(Val, 0, 8);
    > +    switch (byte) {
    > +      case 0:
    > +        Inst.addOperand(MCOperand::CreateImm(imm));
    > +        break;
    > +      case 1:
    > +        Inst.addOperand(MCOperand::CreateImm((imm<<  16) | imm));
    > +        break;
    > +      case 2:
    > +        Inst.addOperand(MCOperand::CreateImm((imm<<  24) | (imm<<  8)));
    > +        break;
    > +      case 3:
    > +        Inst.addOperand(MCOperand::CreateImm((imm<<  24) | (imm<<  16) |
    > +                                             (imm<<  8)  |  imm));
    > +        break;
    > +    }
    > +  } else {
    > +    unsigned unrot = fieldFromInstruction32(Val, 0, 7) | 0x80;
    > +    unsigned rot = fieldFromInstruction32(Val, 7, 5);
    > +    unsigned imm = (unrot>>  rot) | (unrot<<  ((32-rot)&31));
    > +    Inst.addOperand(MCOperand::CreateImm(imm));
    > +  }
    > +
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbBCCTargetOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                        uint64_t Address, const void *Decoder){
    > +  Inst.addOperand(MCOperand::CreateImm(Val<<  1));
    > +  return true;
    > +}
    > +
    > +static bool DecodeThumbBLTargetOperand(llvm::MCInst&Inst, unsigned Val,
    > +                                        uint64_t Address, const void *Decoder){
    
    Whitespace.
    
    Nick
    
    From nicholas at mxc.ca  Wed Aug 10 00:14:38 2011
    From: nicholas at mxc.ca (Nick Lewycky)
    Date: Tue, 09 Aug 2011 22:14:38 -0700
    Subject: [llvm-commits] [llvm] r137197 - in /llvm/trunk:
     include/llvm/Analysis/IVUsers.h
     include/llvm/Transforms/Utils/SimplifyIndVar.h
     lib/Transforms/Scalar/IndVarSimplify.cpp
     lib/Transforms/Utils/SimplifyIndVar.cpp
    In-Reply-To: <20110810034627.AE1072A6C12D@llvm.org>
    References: <20110810034627.AE1072A6C12D@llvm.org>
    Message-ID: <4E4213BE.9030905@mxc.ca>
    
    Andrew Trick wrote:
    > Author: atrick
    > Date: Tue Aug  9 22:46:27 2011
    > New Revision: 137197
    >
    > URL: http://llvm.org/viewvc/llvm-project?rev=137197&view=rev
    > Log:
    > Added a SimplifyIndVar utility to simplify induction variable users
    > based on ScalarEvolution without changing the induction variable phis.
    >
    > This utility is the main tool of IndVarSimplifyPass, but the pass also
    > restructures induction variables in strange ways that are sensitive to
    > pass ordering. This provides a way for other loop passes to simplify
    > new uses of induction variables created during transformation. The
    > utility may be used by any pass that preserves ScalarEvolution. Soon
    > LoopUnroll will use it.
    >
    > The net effect in this checkin is to cleanup the IndVarSimplify pass
    > by factoring out the SimplifyIndVar algorithm into a standalone utility.
    >
    > Added:
    >      llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h
    >      llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    > Modified:
    >      llvm/trunk/include/llvm/Analysis/IVUsers.h
    >      llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    >
    > Modified: llvm/trunk/include/llvm/Analysis/IVUsers.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/IVUsers.h?rev=137197&r1=137196&r2=137197&view=diff
    > ==============================================================================
    > --- llvm/trunk/include/llvm/Analysis/IVUsers.h (original)
    > +++ llvm/trunk/include/llvm/Analysis/IVUsers.h Tue Aug  9 22:46:27 2011
    > @@ -140,6 +140,8 @@
    >     static char ID; // Pass ID, replacement for typeid
    >     IVUsers();
    >
    > +  Loop *getLoop() const { return L; }
    > +
    >     /// AddUsersIfInteresting - Inspect the specified Instruction.  If it is a
    >     /// reducible SCEV, recursively add its users to the IVUsesByStride set and
    >     /// return true.  Otherwise, return false.
    >
    > Added: llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h?rev=137197&view=auto
    > ==============================================================================
    > --- llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h (added)
    > +++ llvm/trunk/include/llvm/Transforms/Utils/SimplifyIndVar.h Tue Aug  9 22:46:27 2011
    > @@ -0,0 +1,58 @@
    > +//===-- llvm/Transforms/Utils/SimplifyIndVar.h - Indvar Utils ---*- C++ -*-===//
    > +//
    > +//                     The LLVM Compiler Infrastructure
    > +//
    > +// This file is distributed under the University of Illinois Open Source
    > +// License. See LICENSE.TXT for details.
    > +//
    > +//===----------------------------------------------------------------------===//
    > +//
    > +// This file defines in interface for induction variable simplification. It does
    > +// not define any actual pass or policy, but provides a single function to
    > +// simplify a loop's induction variables based on ScalarEvolution.
    > +//
    > +//===----------------------------------------------------------------------===//
    > +
    > +#ifndef LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H
    > +#define LLVM_TRANSFORMS_UTILS_SIMPLIFYINDVAR_H
    > +
    > +#include "llvm/Support/CommandLine.h"
    > +
    > +namespace llvm {
    > +
    > +extern cl::opt  DisableIVRewrite;
    > +
    > +class Loop;
    > +class LoopInfo;
    > +class DominatorTree;
    > +class ScalarEvolution;
    > +class LPPassManager;
    > +class IVUsers;
    > +
    > +/// Interface for visiting interesting IV users that are recognized but not
    > +/// simplified by this utility.
    > +class IVVisitor {
    > +public:
    > +  virtual ~IVVisitor() {}
    > +  virtual void visitCast(CastInst *Cast) = 0;
    > +};
    > +
    > +/// simplifyUsersOfIV - Simplify instructions that use this induction variable
    > +/// by using ScalarEvolution to analyze the IV's recurrence.
    > +bool simplifyUsersOfIV(PHINode *CurrIV, LPPassManager *LPM,
    > +                       SmallVectorImpl  &Dead, IVVisitor *V = NULL);
    > +
    > +/// SimplifyLoopIVs - Simplify users of induction variables within this
    > +/// loop. This does not actually change or add IVs.
    > +bool simplifyLoopIVs(Loop *L, LPPassManager *LPM,
    > +                     SmallVectorImpl  &Dead);
    > +
    > +/// simplifyIVUsers - Simplify instructions recorded by the IVUsers pass.
    > +/// This is a legacy implementation to reproduce the behavior of the
    > +/// IndVarSimplify pass prior to DisableIVRewrite.
    > +bool simplifyIVUsers(IVUsers *IU, LPPassManager *LPM,
    > +                     SmallVectorImpl  &Dead);
    > +
    > +} // namespace llvm
    > +
    > +#endif
    >
    > Modified: llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp?rev=137197&r1=137196&r2=137197&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp (original)
    > +++ llvm/trunk/lib/Transforms/Scalar/IndVarSimplify.cpp Tue Aug  9 22:46:27 2011
    > @@ -11,8 +11,8 @@
    >   // computations derived from them) into simpler forms suitable for subsequent
    >   // analysis and transformation.
    >   //
    > -// This transformation makes the following changes to each loop with an
    > -// identifiable induction variable:
    > +// Additionally, unless -disable-iv-rewrite is on, this transformation makes the
    > +// following changes to each loop with an identifiable induction variable:
    >   //   1. All loops are transformed to have a SINGLE canonical induction variable
    >   //      which starts at zero and steps by one.
    >   //   2. The canonical induction variable is guaranteed to be the first PHI node
    > @@ -57,11 +57,11 @@
    >   #include "llvm/Support/raw_ostream.h"
    >   #include "llvm/Transforms/Utils/Local.h"
    >   #include "llvm/Transforms/Utils/BasicBlockUtils.h"
    > +#include "llvm/Transforms/Utils/SimplifyIndVar.h"
    >   #include "llvm/Target/TargetData.h"
    >   #include "llvm/ADT/DenseMap.h"
    >   #include "llvm/ADT/SmallVector.h"
    >   #include "llvm/ADT/Statistic.h"
    > -#include "llvm/ADT/STLExtras.h"
    >   using namespace llvm;
    >
    >   STATISTIC(NumRemoved     , "Number of aux indvars removed");
    > @@ -69,16 +69,14 @@
    >   STATISTIC(NumInserted    , "Number of canonical indvars added");
    >   STATISTIC(NumReplaced    , "Number of exit values replaced");
    >   STATISTIC(NumLFTR        , "Number of loop exit tests replaced");
    > -STATISTIC(NumElimIdentity, "Number of IV identities eliminated");
    > -STATISTIC(NumElimOperand,  "Number of IV operands folded into a use");
    >   STATISTIC(NumElimExt     , "Number of IV sign/zero extends eliminated");
    > -STATISTIC(NumElimRem     , "Number of IV remainder operations eliminated");
    > -STATISTIC(NumElimCmp     , "Number of IV comparisons eliminated");
    >   STATISTIC(NumElimIV      , "Number of congruent IVs eliminated");
    >
    > -static cl::opt  DisableIVRewrite(
    > -  "disable-iv-rewrite", cl::Hidden,
    > -  cl::desc("Disable canonical induction variable rewriting"));
    > +namespace llvm {
    > +  cl::opt  DisableIVRewrite(
    > +    "disable-iv-rewrite", cl::Hidden,
    > +    cl::desc("Disable canonical induction variable rewriting"));
    > +}
    >
    >   // Temporary flag for use with -disable-iv-rewrite to force a canonical IV for
    >   // LFTR purposes.
    > @@ -132,21 +130,12 @@
    >       void HandleFloatingPointIV(Loop *L, PHINode *PH);
    >       void RewriteNonIntegerIVs(Loop *L);
    >
    > -    void RewriteLoopExitValues(Loop *L, SCEVExpander&Rewriter);
    > -
    > -    void SimplifyIVUsers(SCEVExpander&Rewriter);
    > -    void SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander&Rewriter);
    > -
    > -    bool EliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
    > -    void EliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
    > -    void EliminateIVRemainder(BinaryOperator *Rem,
    > -                              Value *IVOperand,
    > -                              bool IsSigned);
    > -
    > -    bool FoldIVUser(Instruction *UseInst, Instruction *IVOperand);
    > +    void SimplifyAndExtend(Loop *L, SCEVExpander&Rewriter, LPPassManager&LPM);
    >
    >       void SimplifyCongruentIVs(Loop *L);
    >
    > +    void RewriteLoopExitValues(Loop *L, SCEVExpander&Rewriter);
    > +
    >       void RewriteIVExpressions(Loop *L, SCEVExpander&Rewriter);
    >
    >       Value *LinearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount,
    > @@ -475,6 +464,8 @@
    >     // Add a new IVUsers entry for the newly-created integer PHI.
    >     if (IU)
    >       IU->AddUsersIfInteresting(NewPHI);
    > +
    > +  Changed = true;
    >   }
    >
    >   void IndVarSimplify::RewriteNonIntegerIVs(Loop *L) {
    > @@ -623,36 +614,6 @@
    >   //  To be replaced by -disable-iv-rewrite.
    >   //===----------------------------------------------------------------------===//
    >
    > -/// SimplifyIVUsers - Iteratively perform simplification on IVUsers within this
    > -/// loop. IVUsers is treated as a worklist. Each successive simplification may
    > -/// push more users which may themselves be candidates for simplification.
    > -///
    > -/// This is the old approach to IV simplification to be replaced by
    > -/// SimplifyIVUsersNoRewrite.
    > -///
    > -void IndVarSimplify::SimplifyIVUsers(SCEVExpander&Rewriter) {
    > -  // Each round of simplification involves a round of eliminating operations
    > -  // followed by a round of widening IVs. A single IVUsers worklist is used
    > -  // across all rounds. The inner loop advances the user. If widening exposes
    > -  // more uses, then another pass through the outer loop is triggered.
    > -  for (IVUsers::iterator I = IU->begin(); I != IU->end(); ++I) {
    > -    Instruction *UseInst = I->getUser();
    > -    Value *IVOperand = I->getOperandValToReplace();
    > -
    > -    if (ICmpInst *ICmp = dyn_cast(UseInst)) {
    > -      EliminateIVComparison(ICmp, IVOperand);
    > -      continue;
    > -    }
    > -    if (BinaryOperator *Rem = dyn_cast(UseInst)) {
    > -      bool IsSigned = Rem->getOpcode() == Instruction::SRem;
    > -      if (IsSigned || Rem->getOpcode() == Instruction::URem) {
    > -        EliminateIVRemainder(Rem, IVOperand, IsSigned);
    > -        continue;
    > -      }
    > -    }
    > -  }
    > -}
    > -
    >   // FIXME: It is an extremely bad idea to indvar substitute anything more
    >   // complex than affine induction variables.  Doing so will put expensive
    >   // polynomial evaluations inside of the loop, and the str reduction pass
    > @@ -775,17 +736,34 @@
    >     // provides the input to WidenIV.
    >     struct WideIVInfo {
    >       Type *WidestNativeType; // Widest integer type created [sz]ext
    > -    bool IsSigned;                // Was an sext user seen before a zext?
    > +    bool IsSigned;          // Was an sext user seen before a zext?
    >
    >       WideIVInfo() : WidestNativeType(0), IsSigned(false) {}
    >     };
    > +
    > +  class WideIVVisitor : public IVVisitor {
    > +    ScalarEvolution *SE;
    > +    const TargetData *TD;
    > +
    > +  public:
    > +    WideIVInfo WI;
    > +
    > +    WideIVVisitor(ScalarEvolution *SCEV, const TargetData *TData) :
    > +      SE(SCEV), TD(TData) {}
    > +
    > +    // Implement the interface used by simplifyUsersOfIV.
    > +    virtual void visitCast(CastInst *Cast);
    > +  };
    >   }
    >
    > -/// CollectExtend - Update information about the induction variable that is
    > +/// visitCast - Update information about the induction variable that is
    >   /// extended by this sign or zero extend operation. This is used to determine
    >   /// the final width of the IV before actually widening it.
    > -static void CollectExtend(CastInst *Cast, bool IsSigned, WideIVInfo&WI,
    > -                          ScalarEvolution *SE, const TargetData *TD) {
    > +void WideIVVisitor::visitCast(CastInst *Cast) {
    > +  bool IsSigned = Cast->getOpcode() == Instruction::SExt;
    > +  if (!IsSigned&&  Cast->getOpcode() != Instruction::ZExt)
    > +    return;
    > +
    >     Type *Ty = Cast->getType();
    >     uint64_t Width = SE->getTypeSizeInBits(Ty);
    >     if (TD&&  !TD->isLegalInteger(Width))
    > @@ -1181,242 +1159,16 @@
    >   //  Simplification of IV users based on SCEV evaluation.
    >   //===----------------------------------------------------------------------===//
    >
    > -void IndVarSimplify::EliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
    > -  unsigned IVOperIdx = 0;
    > -  ICmpInst::Predicate Pred = ICmp->getPredicate();
    > -  if (IVOperand != ICmp->getOperand(0)) {
    > -    // Swapped
    > -    assert(IVOperand == ICmp->getOperand(1)&&  "Can't find IVOperand");
    > -    IVOperIdx = 1;
    > -    Pred = ICmpInst::getSwappedPredicate(Pred);
    > -  }
    > -
    > -  // Get the SCEVs for the ICmp operands.
    > -  const SCEV *S = SE->getSCEV(ICmp->getOperand(IVOperIdx));
    > -  const SCEV *X = SE->getSCEV(ICmp->getOperand(1 - IVOperIdx));
    > -
    > -  // Simplify unnecessary loops away.
    > -  const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
    > -  S = SE->getSCEVAtScope(S, ICmpLoop);
    > -  X = SE->getSCEVAtScope(X, ICmpLoop);
    > -
    > -  // If the condition is always true or always false, replace it with
    > -  // a constant value.
    > -  if (SE->isKnownPredicate(Pred, S, X))
    > -    ICmp->replaceAllUsesWith(ConstantInt::getTrue(ICmp->getContext()));
    > -  else if (SE->isKnownPredicate(ICmpInst::getInversePredicate(Pred), S, X))
    > -    ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
    > -  else
    > -    return;
    > -
    > -  DEBUG(dbgs()<<  "INDVARS: Eliminated comparison: "<<  *ICmp<<  '\n');
    > -  ++NumElimCmp;
    > -  Changed = true;
    > -  DeadInsts.push_back(ICmp);
    > -}
    > -
    > -void IndVarSimplify::EliminateIVRemainder(BinaryOperator *Rem,
    > -                                          Value *IVOperand,
    > -                                          bool IsSigned) {
    > -  // We're only interested in the case where we know something about
    > -  // the numerator.
    > -  if (IVOperand != Rem->getOperand(0))
    > -    return;
    > -
    > -  // Get the SCEVs for the ICmp operands.
    > -  const SCEV *S = SE->getSCEV(Rem->getOperand(0));
    > -  const SCEV *X = SE->getSCEV(Rem->getOperand(1));
    > -
    > -  // Simplify unnecessary loops away.
    > -  const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
    > -  S = SE->getSCEVAtScope(S, ICmpLoop);
    > -  X = SE->getSCEVAtScope(X, ICmpLoop);
    > -
    > -  // i % n  -->   i  if i is in [0,n).
    > -  if ((!IsSigned || SE->isKnownNonNegative(S))&&
    > -      SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
    > -                           S, X))
    > -    Rem->replaceAllUsesWith(Rem->getOperand(0));
    > -  else {
    > -    // (i+1) % n  -->   (i+1)==n?0:(i+1)  if i is in [0,n).
    > -    const SCEV *LessOne =
    > -      SE->getMinusSCEV(S, SE->getConstant(S->getType(), 1));
    > -    if (IsSigned&&  !SE->isKnownNonNegative(LessOne))
    > -      return;
    > -
    > -    if (!SE->isKnownPredicate(IsSigned ?
    > -                              ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
    > -                              LessOne, X))
    > -      return;
    > -
    > -    ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
    > -                                  Rem->getOperand(0), Rem->getOperand(1),
    > -                                  "tmp");
    > -    SelectInst *Sel =
    > -      SelectInst::Create(ICmp,
    > -                         ConstantInt::get(Rem->getType(), 0),
    > -                         Rem->getOperand(0), "tmp", Rem);
    > -    Rem->replaceAllUsesWith(Sel);
    > -  }
    > -
    > -  // Inform IVUsers about the new users.
    > -  if (IU) {
    > -    if (Instruction *I = dyn_cast(Rem->getOperand(0)))
    > -      IU->AddUsersIfInteresting(I);
    > -  }
    > -  DEBUG(dbgs()<<  "INDVARS: Simplified rem: "<<  *Rem<<  '\n');
    > -  ++NumElimRem;
    > -  Changed = true;
    > -  DeadInsts.push_back(Rem);
    > -}
    > -
    > -/// EliminateIVUser - Eliminate an operation that consumes a simple IV and has
    > -/// no observable side-effect given the range of IV values.
    > -bool IndVarSimplify::EliminateIVUser(Instruction *UseInst,
    > -                                     Instruction *IVOperand) {
    > -  if (ICmpInst *ICmp = dyn_cast(UseInst)) {
    > -    EliminateIVComparison(ICmp, IVOperand);
    > -    return true;
    > -  }
    > -  if (BinaryOperator *Rem = dyn_cast(UseInst)) {
    > -    bool IsSigned = Rem->getOpcode() == Instruction::SRem;
    > -    if (IsSigned || Rem->getOpcode() == Instruction::URem) {
    > -      EliminateIVRemainder(Rem, IVOperand, IsSigned);
    > -      return true;
    > -    }
    > -  }
    > -
    > -  // Eliminate any operation that SCEV can prove is an identity function.
    > -  if (!SE->isSCEVable(UseInst->getType()) ||
    > -      (UseInst->getType() != IVOperand->getType()) ||
    > -      (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
    > -    return false;
    > -
    > -  DEBUG(dbgs()<<  "INDVARS: Eliminated identity: "<<  *UseInst<<  '\n');
    > -
    > -  UseInst->replaceAllUsesWith(IVOperand);
    > -  ++NumElimIdentity;
    > -  Changed = true;
    > -  DeadInsts.push_back(UseInst);
    > -  return true;
    > -}
    > -
    > -/// FoldIVUser - Fold an IV operand into its use.  This removes increments of an
    > -/// aligned IV when used by a instruction that ignores the low bits.
    > -bool IndVarSimplify::FoldIVUser(Instruction *UseInst, Instruction *IVOperand) {
    > -  Value *IVSrc = 0;
    > -  unsigned OperIdx = 0;
    > -  const SCEV *FoldedExpr = 0;
    > -  switch (UseInst->getOpcode()) {
    > -  default:
    > -    return false;
    > -  case Instruction::UDiv:
    > -  case Instruction::LShr:
    > -    // We're only interested in the case where we know something about
    > -    // the numerator and have a constant denominator.
    > -    if (IVOperand != UseInst->getOperand(OperIdx) ||
    > -        !isa(UseInst->getOperand(1)))
    > -      return false;
    > -
    > -    // Attempt to fold a binary operator with constant operand.
    > -    // e.g. ((I + 1)>>  2) =>  I>>  2
    > -    if (IVOperand->getNumOperands() != 2 ||
    > -        !isa(IVOperand->getOperand(1)))
    > -      return false;
    > -
    > -    IVSrc = IVOperand->getOperand(0);
    > -    // IVSrc must be the (SCEVable) IV, since the other operand is const.
    > -    assert(SE->isSCEVable(IVSrc->getType())&&  "Expect SCEVable IV operand");
    > -
    > -    ConstantInt *D = cast(UseInst->getOperand(1));
    > -    if (UseInst->getOpcode() == Instruction::LShr) {
    > -      // Get a constant for the divisor. See createSCEV.
    > -      uint32_t BitWidth = cast(UseInst->getType())->getBitWidth();
    > -      if (D->getValue().uge(BitWidth))
    > -        return false;
    > -
    > -      D = ConstantInt::get(UseInst->getContext(),
    > -                           APInt(BitWidth, 1).shl(D->getZExtValue()));
    > -    }
    > -    FoldedExpr = SE->getUDivExpr(SE->getSCEV(IVSrc), SE->getSCEV(D));
    > -  }
    > -  // We have something that might fold it's operand. Compare SCEVs.
    > -  if (!SE->isSCEVable(UseInst->getType()))
    > -    return false;
    > -
    > -  // Bypass the operand if SCEV can prove it has no effect.
    > -  if (SE->getSCEV(UseInst) != FoldedExpr)
    > -    return false;
    > -
    > -  DEBUG(dbgs()<<  "INDVARS: Eliminated IV operand: "<<  *IVOperand
    > -<<  " ->  "<<  *UseInst<<  '\n');
    > -
    > -  UseInst->setOperand(OperIdx, IVSrc);
    > -  assert(SE->getSCEV(UseInst) == FoldedExpr&&  "bad SCEV with folded oper");
    > -
    > -  ++NumElimOperand;
    > -  Changed = true;
    > -  if (IVOperand->use_empty())
    > -    DeadInsts.push_back(IVOperand);
    > -  return true;
    > -}
    > -
    > -/// pushIVUsers - Add all uses of Def to the current IV's worklist.
    > -///
    > -static void pushIVUsers(
    > -  Instruction *Def,
    > -  SmallPtrSet  &Simplified,
    > -  SmallVectorImpl<  std::pair  >  &SimpleIVUsers) {
    > -
    > -  for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end();
    > -       UI != E; ++UI) {
    > -    Instruction *User = cast(*UI);
    > -
    > -    // Avoid infinite or exponential worklist processing.
    > -    // Also ensure unique worklist users.
    > -    // If Def is a LoopPhi, it may not be in the Simplified set, so check for
    > -    // self edges first.
    > -    if (User != Def&&  Simplified.insert(User))
    > -      SimpleIVUsers.push_back(std::make_pair(User, Def));
    > -  }
    > -}
    > -
    > -/// isSimpleIVUser - Return true if this instruction generates a simple SCEV
    > -/// expression in terms of that IV.
    > -///
    > -/// This is similar to IVUsers' isInsteresting() but processes each instruction
    
    Typo, "isInsteresting".
    
    Nick
    
    > -/// non-recursively when the operand is already known to be a simpleIVUser.
    > -///
    > -static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) {
    > -  if (!SE->isSCEVable(I->getType()))
    > -    return false;
    > -
    > -  // Get the symbolic expression for this instruction.
    > -  const SCEV *S = SE->getSCEV(I);
    > -
    > -  // Only consider affine recurrences.
    > -  const SCEVAddRecExpr *AR = dyn_cast(S);
    > -  if (AR&&  AR->getLoop() == L)
    > -    return true;
    > -
    > -  return false;
    > -}
    >
    > -/// SimplifyIVUsersNoRewrite - Iteratively perform simplification on a worklist
    > -/// of IV users. Each successive simplification may push more users which may
    > +/// SimplifyAndExtend - Iteratively perform simplification on a worklist of IV
    > +/// users. Each successive simplification may push more users which may
    >   /// themselves be candidates for simplification.
    >   ///
    > -/// The "NoRewrite" algorithm does not require IVUsers analysis. Instead, it
    > -/// simplifies instructions in-place during analysis. Rather than rewriting
    > -/// induction variables bottom-up from their users, it transforms a chain of
    > -/// IVUsers top-down, updating the IR only when it encouters a clear
    > -/// optimization opportunitiy. A SCEVExpander "Rewriter" instance is still
    > -/// needed, but only used to generate a new IV (phi) of wider type for sign/zero
    > -/// extend elimination.
    > +/// Sign/Zero extend elimination is interleaved with IV simplification.
    >   ///
    > -/// Once DisableIVRewrite is default, LSR will be the only client of IVUsers.
    > -///
    > -void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander&Rewriter) {
    > +void IndVarSimplify::SimplifyAndExtend(Loop *L,
    > +                                       SCEVExpander&Rewriter,
    > +                                       LPPassManager&LPM) {
    >     std::map  WideIVMap;
    >
    >     SmallVector  LoopPhis;
    > @@ -1433,49 +1185,17 @@
    >       // extension. The first time SCEV attempts to normalize sign/zero extension,
    >       // the result becomes final. So for the most predictable results, we delay
    >       // evaluation of sign/zero extend evaluation until needed, and avoid running
    > -    // other SCEV based analysis prior to SimplifyIVUsersNoRewrite.
    > +    // other SCEV based analysis prior to SimplifyAndExtend.
    >       do {
    >         PHINode *CurrIV = LoopPhis.pop_back_val();
    >
    >         // Information about sign/zero extensions of CurrIV.
    > -      WideIVInfo WI;
    > -
    > -      // Instructions processed by SimplifyIVUsers for CurrIV.
    > -      SmallPtrSet  Simplified;
    > -
    > -      // Use-def pairs if IV users waiting to be processed for CurrIV.
    > -      SmallVector, 8>  SimpleIVUsers;
    > -
    > -      // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
    > -      // called multiple times for the same LoopPhi. This is the proper thing to
    > -      // do for loop header phis that use each other.
    > -      pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
    > -
    > -      while (!SimpleIVUsers.empty()) {
    > -        std::pair  UseOper =
    > -          SimpleIVUsers.pop_back_val();
    > -        // Bypass back edges to avoid extra work.
    > -        if (UseOper.first == CurrIV) continue;
    > +      WideIVVisitor WIV(SE, TD);
    >
    > -        FoldIVUser(UseOper.first, UseOper.second);
    > +      Changed |= simplifyUsersOfIV(CurrIV,&LPM, DeadInsts,&WIV);
    >
    > -        if (EliminateIVUser(UseOper.first, UseOper.second)) {
    > -          pushIVUsers(UseOper.second, Simplified, SimpleIVUsers);
    > -          continue;
    > -        }
    > -        if (CastInst *Cast = dyn_cast(UseOper.first)) {
    > -          bool IsSigned = Cast->getOpcode() == Instruction::SExt;
    > -          if (IsSigned || Cast->getOpcode() == Instruction::ZExt) {
    > -            CollectExtend(Cast, IsSigned, WI, SE, TD);
    > -          }
    > -          continue;
    > -        }
    > -        if (isSimpleIVUser(UseOper.first, L, SE)) {
    > -          pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
    > -        }
    > -      }
    > -      if (WI.WidestNativeType) {
    > -        WideIVMap[CurrIV] = WI;
    > +      if (WIV.WI.WidestNativeType) {
    > +        WideIVMap[CurrIV] = WIV.WI;
    >         }
    >       } while(!LoopPhis.empty());
    >
    > @@ -1492,7 +1212,7 @@
    >   }
    >
    >   /// SimplifyCongruentIVs - Check for congruent phis in this loop header and
    > -/// populate ExprToIVMap for use later.
    > +/// replace them with their chosen representative.
    >   ///
    >   void IndVarSimplify::SimplifyCongruentIVs(Loop *L) {
    >     DenseMap  ExprToIVMap;
    > @@ -2097,7 +1817,7 @@
    >     // set no-wrap flags before normalizing sign/zero extension.
    >     if (DisableIVRewrite) {
    >       Rewriter.disableCanonicalMode();
    > -    SimplifyIVUsersNoRewrite(L, Rewriter);
    > +    SimplifyAndExtend(L, Rewriter, LPM);
    >     }
    >
    >     // Check to see if this loop has a computable loop-invariant execution count.
    > @@ -2111,7 +1831,7 @@
    >
    >     // Eliminate redundant IV users.
    >     if (!DisableIVRewrite)
    > -    SimplifyIVUsers(Rewriter);
    > +    Changed |= simplifyIVUsers(IU,&LPM, DeadInsts);
    >
    >     // Eliminate redundant IV cycles.
    >     if (DisableIVRewrite)
    >
    > Added: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=137197&view=auto
    > ==============================================================================
    > --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (added)
    > +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Tue Aug  9 22:46:27 2011
    > @@ -0,0 +1,413 @@
    > +//===-- SimplifyIndVar.cpp - Induction variable simplification ------------===//
    > +//
    > +//                     The LLVM Compiler Infrastructure
    > +//
    > +// This file is distributed under the University of Illinois Open Source
    > +// License. See LICENSE.TXT for details.
    > +//
    > +//===----------------------------------------------------------------------===//
    > +//
    > +// This file implements induction variable simplification. It does
    > +// not define any actual pass or policy, but provides a single function to
    > +// simplify a loop's induction variables based on ScalarEvolution.
    > +//
    > +//===----------------------------------------------------------------------===//
    > +
    > +#define DEBUG_TYPE "indvars"
    > +
    > +#include "llvm/Instructions.h"
    > +#include "llvm/Analysis/Dominators.h"
    > +#include "llvm/Analysis/IVUsers.h"
    > +#include "llvm/Analysis/LoopInfo.h"
    > +#include "llvm/Analysis/LoopPass.h"
    > +#include "llvm/Analysis/ScalarEvolutionExpressions.h"
    > +#include "llvm/Support/CommandLine.h"
    > +#include "llvm/Support/Debug.h"
    > +#include "llvm/Support/raw_ostream.h"
    > +#include "llvm/Transforms/Utils/SimplifyIndVar.h"
    > +#include "llvm/Target/TargetData.h"
    > +#include "llvm/ADT/SmallVector.h"
    > +#include "llvm/ADT/Statistic.h"
    > +
    > +using namespace llvm;
    > +
    > +STATISTIC(NumElimIdentity, "Number of IV identities eliminated");
    > +STATISTIC(NumElimOperand,  "Number of IV operands folded into a use");
    > +STATISTIC(NumElimRem     , "Number of IV remainder operations eliminated");
    > +STATISTIC(NumElimCmp     , "Number of IV comparisons eliminated");
    > +
    > +namespace {
    > +  /// SimplifyIndvar - This is a utility for simplifying induction variables
    > +  /// based on ScalarEvolution. It is the primary instrument of the
    > +  /// IndvarSimplify pass, but it may also be directly invoked to cleanup after
    > +  /// other loop passes that preserve SCEV.
    > +  class SimplifyIndvar {
    > +    Loop             *L;
    > +    LoopInfo         *LI;
    > +    DominatorTree    *DT;
    > +    ScalarEvolution  *SE;
    > +    IVUsers          *IU; // NULL for DisableIVRewrite
    > +    const TargetData *TD; // May be NULL
    > +
    > +    SmallVectorImpl  &DeadInsts;
    > +
    > +    bool Changed;
    > +
    > +  public:
    > +    SimplifyIndvar(Loop *Loop, LPPassManager *LPM,
    > +                   SmallVectorImpl  &Dead, IVUsers *IVU = NULL) :
    > +      L(Loop),
    > +      LI(LPM->getAnalysisIfAvailable()),
    > +      SE(LPM->getAnalysisIfAvailable()),
    > +      IU(IVU),
    > +      TD(LPM->getAnalysisIfAvailable()),
    > +      DeadInsts(Dead),
    > +      Changed(false) {
    > +      assert(LI&&  SE&&  "IV simplification requires ScalarEvolution");
    > +    }
    > +
    > +    bool hasChanged() const { return Changed; }
    > +
    > +    /// Iteratively perform simplification on a worklist of users of the
    > +    /// specified induction variable. This is the top-level driver that applies
    > +    /// all simplicitions to users of an IV.
    > +    void simplifyUsers(PHINode *CurrIV, IVVisitor *V = NULL);
    > +
    > +    bool foldIVUser(Instruction *UseInst, Instruction *IVOperand);
    > +
    > +    bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
    > +    void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
    > +    void eliminateIVRemainder(BinaryOperator *Rem, Value *IVOperand,
    > +                              bool IsSigned);
    > +  };
    > +}
    > +
    > +/// foldIVUser - Fold an IV operand into its use.  This removes increments of an
    > +/// aligned IV when used by a instruction that ignores the low bits.
    > +bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
    > +  Value *IVSrc = 0;
    > +  unsigned OperIdx = 0;
    > +  const SCEV *FoldedExpr = 0;
    > +  switch (UseInst->getOpcode()) {
    > +  default:
    > +    return false;
    > +  case Instruction::UDiv:
    > +  case Instruction::LShr:
    > +    // We're only interested in the case where we know something about
    > +    // the numerator and have a constant denominator.
    > +    if (IVOperand != UseInst->getOperand(OperIdx) ||
    > +        !isa(UseInst->getOperand(1)))
    > +      return false;
    > +
    > +    // Attempt to fold a binary operator with constant operand.
    > +    // e.g. ((I + 1)>>  2) =>  I>>  2
    > +    if (IVOperand->getNumOperands() != 2 ||
    > +        !isa(IVOperand->getOperand(1)))
    > +      return false;
    > +
    > +    IVSrc = IVOperand->getOperand(0);
    > +    // IVSrc must be the (SCEVable) IV, since the other operand is const.
    > +    assert(SE->isSCEVable(IVSrc->getType())&&  "Expect SCEVable IV operand");
    > +
    > +    ConstantInt *D = cast(UseInst->getOperand(1));
    > +    if (UseInst->getOpcode() == Instruction::LShr) {
    > +      // Get a constant for the divisor. See createSCEV.
    > +      uint32_t BitWidth = cast(UseInst->getType())->getBitWidth();
    > +      if (D->getValue().uge(BitWidth))
    > +        return false;
    > +
    > +      D = ConstantInt::get(UseInst->getContext(),
    > +                           APInt(BitWidth, 1).shl(D->getZExtValue()));
    > +    }
    > +    FoldedExpr = SE->getUDivExpr(SE->getSCEV(IVSrc), SE->getSCEV(D));
    > +  }
    > +  // We have something that might fold it's operand. Compare SCEVs.
    > +  if (!SE->isSCEVable(UseInst->getType()))
    > +    return false;
    > +
    > +  // Bypass the operand if SCEV can prove it has no effect.
    > +  if (SE->getSCEV(UseInst) != FoldedExpr)
    > +    return false;
    > +
    > +  DEBUG(dbgs()<<  "INDVARS: Eliminated IV operand: "<<  *IVOperand
    > +<<  " ->  "<<  *UseInst<<  '\n');
    > +
    > +  UseInst->setOperand(OperIdx, IVSrc);
    > +  assert(SE->getSCEV(UseInst) == FoldedExpr&&  "bad SCEV with folded oper");
    > +
    > +  ++NumElimOperand;
    > +  Changed = true;
    > +  if (IVOperand->use_empty())
    > +    DeadInsts.push_back(IVOperand);
    > +  return true;
    > +}
    > +
    > +/// eliminateIVComparison - SimplifyIVUsers helper for eliminating useless
    > +/// comparisons against an induction variable.
    > +void SimplifyIndvar::eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand) {
    > +  unsigned IVOperIdx = 0;
    > +  ICmpInst::Predicate Pred = ICmp->getPredicate();
    > +  if (IVOperand != ICmp->getOperand(0)) {
    > +    // Swapped
    > +    assert(IVOperand == ICmp->getOperand(1)&&  "Can't find IVOperand");
    > +    IVOperIdx = 1;
    > +    Pred = ICmpInst::getSwappedPredicate(Pred);
    > +  }
    > +
    > +  // Get the SCEVs for the ICmp operands.
    > +  const SCEV *S = SE->getSCEV(ICmp->getOperand(IVOperIdx));
    > +  const SCEV *X = SE->getSCEV(ICmp->getOperand(1 - IVOperIdx));
    > +
    > +  // Simplify unnecessary loops away.
    > +  const Loop *ICmpLoop = LI->getLoopFor(ICmp->getParent());
    > +  S = SE->getSCEVAtScope(S, ICmpLoop);
    > +  X = SE->getSCEVAtScope(X, ICmpLoop);
    > +
    > +  // If the condition is always true or always false, replace it with
    > +  // a constant value.
    > +  if (SE->isKnownPredicate(Pred, S, X))
    > +    ICmp->replaceAllUsesWith(ConstantInt::getTrue(ICmp->getContext()));
    > +  else if (SE->isKnownPredicate(ICmpInst::getInversePredicate(Pred), S, X))
    > +    ICmp->replaceAllUsesWith(ConstantInt::getFalse(ICmp->getContext()));
    > +  else
    > +    return;
    > +
    > +  DEBUG(dbgs()<<  "INDVARS: Eliminated comparison: "<<  *ICmp<<  '\n');
    > +  ++NumElimCmp;
    > +  Changed = true;
    > +  DeadInsts.push_back(ICmp);
    > +}
    > +
    > +/// eliminateIVRemainder - SimplifyIVUsers helper for eliminating useless
    > +/// remainder operations operating on an induction variable.
    > +void SimplifyIndvar::eliminateIVRemainder(BinaryOperator *Rem,
    > +                                      Value *IVOperand,
    > +                                      bool IsSigned) {
    > +  // We're only interested in the case where we know something about
    > +  // the numerator.
    > +  if (IVOperand != Rem->getOperand(0))
    > +    return;
    > +
    > +  // Get the SCEVs for the ICmp operands.
    > +  const SCEV *S = SE->getSCEV(Rem->getOperand(0));
    > +  const SCEV *X = SE->getSCEV(Rem->getOperand(1));
    > +
    > +  // Simplify unnecessary loops away.
    > +  const Loop *ICmpLoop = LI->getLoopFor(Rem->getParent());
    > +  S = SE->getSCEVAtScope(S, ICmpLoop);
    > +  X = SE->getSCEVAtScope(X, ICmpLoop);
    > +
    > +  // i % n  -->   i  if i is in [0,n).
    > +  if ((!IsSigned || SE->isKnownNonNegative(S))&&
    > +      SE->isKnownPredicate(IsSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
    > +                           S, X))
    > +    Rem->replaceAllUsesWith(Rem->getOperand(0));
    > +  else {
    > +    // (i+1) % n  -->   (i+1)==n?0:(i+1)  if i is in [0,n).
    > +    const SCEV *LessOne =
    > +      SE->getMinusSCEV(S, SE->getConstant(S->getType(), 1));
    > +    if (IsSigned&&  !SE->isKnownNonNegative(LessOne))
    > +      return;
    > +
    > +    if (!SE->isKnownPredicate(IsSigned ?
    > +                              ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT,
    > +                              LessOne, X))
    > +      return;
    > +
    > +    ICmpInst *ICmp = new ICmpInst(Rem, ICmpInst::ICMP_EQ,
    > +                                  Rem->getOperand(0), Rem->getOperand(1),
    > +                                  "tmp");
    > +    SelectInst *Sel =
    > +      SelectInst::Create(ICmp,
    > +                         ConstantInt::get(Rem->getType(), 0),
    > +                         Rem->getOperand(0), "tmp", Rem);
    > +    Rem->replaceAllUsesWith(Sel);
    > +  }
    > +
    > +  // Inform IVUsers about the new users.
    > +  if (IU) {
    > +    if (Instruction *I = dyn_cast(Rem->getOperand(0)))
    > +      IU->AddUsersIfInteresting(I);
    > +  }
    > +  DEBUG(dbgs()<<  "INDVARS: Simplified rem: "<<  *Rem<<  '\n');
    > +  ++NumElimRem;
    > +  Changed = true;
    > +  DeadInsts.push_back(Rem);
    > +}
    > +
    > +/// eliminateIVUser - Eliminate an operation that consumes a simple IV and has
    > +/// no observable side-effect given the range of IV values.
    > +bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst,
    > +                                     Instruction *IVOperand) {
    > +  if (ICmpInst *ICmp = dyn_cast(UseInst)) {
    > +    eliminateIVComparison(ICmp, IVOperand);
    > +    return true;
    > +  }
    > +  if (BinaryOperator *Rem = dyn_cast(UseInst)) {
    > +    bool IsSigned = Rem->getOpcode() == Instruction::SRem;
    > +    if (IsSigned || Rem->getOpcode() == Instruction::URem) {
    > +      eliminateIVRemainder(Rem, IVOperand, IsSigned);
    > +      return true;
    > +    }
    > +  }
    > +
    > +  // Eliminate any operation that SCEV can prove is an identity function.
    > +  if (!SE->isSCEVable(UseInst->getType()) ||
    > +      (UseInst->getType() != IVOperand->getType()) ||
    > +      (SE->getSCEV(UseInst) != SE->getSCEV(IVOperand)))
    > +    return false;
    > +
    > +  DEBUG(dbgs()<<  "INDVARS: Eliminated identity: "<<  *UseInst<<  '\n');
    > +
    > +  UseInst->replaceAllUsesWith(IVOperand);
    > +  ++NumElimIdentity;
    > +  Changed = true;
    > +  DeadInsts.push_back(UseInst);
    > +  return true;
    > +}
    > +
    > +/// pushIVUsers - Add all uses of Def to the current IV's worklist.
    > +///
    > +static void pushIVUsers(
    > +  Instruction *Def,
    > +  SmallPtrSet  &Simplified,
    > +  SmallVectorImpl<  std::pair  >  &SimpleIVUsers) {
    > +
    > +  for (Value::use_iterator UI = Def->use_begin(), E = Def->use_end();
    > +       UI != E; ++UI) {
    > +    Instruction *User = cast(*UI);
    > +
    > +    // Avoid infinite or exponential worklist processing.
    > +    // Also ensure unique worklist users.
    > +    // If Def is a LoopPhi, it may not be in the Simplified set, so check for
    > +    // self edges first.
    > +    if (User != Def&&  Simplified.insert(User))
    > +      SimpleIVUsers.push_back(std::make_pair(User, Def));
    > +  }
    > +}
    > +
    > +/// isSimpleIVUser - Return true if this instruction generates a simple SCEV
    > +/// expression in terms of that IV.
    > +///
    > +/// This is similar to IVUsers' isInsteresting() but processes each instruction
    > +/// non-recursively when the operand is already known to be a simpleIVUser.
    > +///
    > +static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) {
    > +  if (!SE->isSCEVable(I->getType()))
    > +    return false;
    > +
    > +  // Get the symbolic expression for this instruction.
    > +  const SCEV *S = SE->getSCEV(I);
    > +
    > +  // Only consider affine recurrences.
    > +  const SCEVAddRecExpr *AR = dyn_cast(S);
    > +  if (AR&&  AR->getLoop() == L)
    > +    return true;
    > +
    > +  return false;
    > +}
    > +
    > +/// simplifyUsers - Iteratively perform simplification on a worklist of users
    > +/// of the specified induction variable. Each successive simplification may push
    > +/// more users which may themselves be candidates for simplification.
    > +///
    > +/// This algorithm does not require IVUsers analysis. Instead, it simplifies
    > +/// instructions in-place during analysis. Rather than rewriting induction
    > +/// variables bottom-up from their users, it transforms a chain of IVUsers
    > +/// top-down, updating the IR only when it encouters a clear optimization
    > +/// opportunitiy.
    > +///
    > +/// Once DisableIVRewrite is default, LSR will be the only client of IVUsers.
    > +///
    > +void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
    > +  // Instructions processed by SimplifyIndvar for CurrIV.
    > +  SmallPtrSet  Simplified;
    > +
    > +  // Use-def pairs if IV users waiting to be processed for CurrIV.
    > +  SmallVector, 8>  SimpleIVUsers;
    > +
    > +  // Push users of the current LoopPhi. In rare cases, pushIVUsers may be
    > +  // called multiple times for the same LoopPhi. This is the proper thing to
    > +  // do for loop header phis that use each other.
    > +  pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
    > +
    > +  while (!SimpleIVUsers.empty()) {
    > +    std::pair  UseOper =
    > +      SimpleIVUsers.pop_back_val();
    > +    // Bypass back edges to avoid extra work.
    > +    if (UseOper.first == CurrIV) continue;
    > +
    > +    foldIVUser(UseOper.first, UseOper.second);
    > +
    > +    if (eliminateIVUser(UseOper.first, UseOper.second)) {
    > +      pushIVUsers(UseOper.second, Simplified, SimpleIVUsers);
    > +      continue;
    > +    }
    > +    CastInst *Cast = dyn_cast(UseOper.first);
    > +    if (V&&  Cast) {
    > +      V->visitCast(Cast);
    > +      continue;
    > +    }
    > +    if (isSimpleIVUser(UseOper.first, L, SE)) {
    > +      pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
    > +    }
    > +  }
    > +}
    > +
    > +namespace llvm {
    > +
    > +/// simplifyUsersOfIV - Simplify instructions that use this induction variable
    > +/// by using ScalarEvolution to analyze the IV's recurrence.
    > +bool simplifyUsersOfIV(PHINode *CurrIV, LPPassManager *LPM,
    > +                       SmallVectorImpl  &Dead, IVVisitor *V)
    > +{
    > +  LoopInfo *LI =&LPM->getAnalysis();
    > +  SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), LPM, Dead);
    > +  SIV.simplifyUsers(CurrIV, V);
    > +  return SIV.hasChanged();
    > +}
    > +
    > +/// simplifyLoopIVs - Simplify users of induction variables within this
    > +/// loop. This does not actually change or add IVs.
    > +bool simplifyLoopIVs(Loop *L, LPPassManager *LPM,
    > +                     SmallVectorImpl  &Dead) {
    > +  bool Changed = false;
    > +  for (BasicBlock::iterator I = L->getHeader()->begin(); isa(I); ++I) {
    > +    Changed |= simplifyUsersOfIV(cast(I), LPM, Dead);
    > +  }
    > +  return Changed;
    > +}
    > +
    > +/// simplifyIVUsers - Perform simplification on instructions recorded by the
    > +/// IVUsers pass.
    > +///
    > +/// This is the old approach to IV simplification to be replaced by
    > +/// SimplifyLoopIVs.
    > +bool simplifyIVUsers(IVUsers *IU, LPPassManager *LPM,
    > +                     SmallVectorImpl  &Dead) {
    > +  SimplifyIndvar SIV(IU->getLoop(), LPM, Dead);
    > +
    > +  // Each round of simplification involves a round of eliminating operations
    > +  // followed by a round of widening IVs. A single IVUsers worklist is used
    > +  // across all rounds. The inner loop advances the user. If widening exposes
    > +  // more uses, then another pass through the outer loop is triggered.
    > +  for (IVUsers::iterator I = IU->begin(); I != IU->end(); ++I) {
    > +    Instruction *UseInst = I->getUser();
    > +    Value *IVOperand = I->getOperandValToReplace();
    > +
    > +    if (ICmpInst *ICmp = dyn_cast(UseInst)) {
    > +      SIV.eliminateIVComparison(ICmp, IVOperand);
    > +      continue;
    > +    }
    > +    if (BinaryOperator *Rem = dyn_cast(UseInst)) {
    > +      bool IsSigned = Rem->getOpcode() == Instruction::SRem;
    > +      if (IsSigned || Rem->getOpcode() == Instruction::URem) {
    > +        SIV.eliminateIVRemainder(Rem, IVOperand, IsSigned);
    > +        continue;
    > +      }
    > +    }
    > +  }
    > +  return SIV.hasChanged();
    > +}
    > +
    > +} // namespace llvm
    >
    >
    > _______________________________________________
    > llvm-commits mailing list
    > llvm-commits at cs.uiuc.edu
    > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
    >
    
    
    From nicholas at mxc.ca  Wed Aug 10 00:18:46 2011
    From: nicholas at mxc.ca (Nick Lewycky)
    Date: Tue, 09 Aug 2011 22:18:46 -0700
    Subject: [llvm-commits] [llvm] r137199
    	-	/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    In-Reply-To: <20110810040131.922742A6C12D@llvm.org>
    References: <20110810040131.922742A6C12D@llvm.org>
    Message-ID: <4E4214B6.9000700@mxc.ca>
    
    Andrew Trick wrote:
    > Author: atrick
    > Date: Tue Aug  9 23:01:31 2011
    > New Revision: 137199
    >
    > URL: http://llvm.org/viewvc/llvm-project?rev=137199&view=rev
    > Log:
    > SimplifyIndVar: make foldIVUser iterative to fold a chain of operands.
    >
    > Modified:
    >      llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    >
    > Modified: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=137199&r1=137198&r2=137199&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (original)
    > +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Tue Aug  9 23:01:31 2011
    > @@ -73,7 +73,7 @@
    >       /// all simplicitions to users of an IV.
    >       void simplifyUsers(PHINode *CurrIV, IVVisitor *V = NULL);
    >
    > -    bool foldIVUser(Instruction *UseInst, Instruction *IVOperand);
    > +    Value *foldIVUser(Instruction *UseInst, Instruction *IVOperand);
    >
    >       bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
    >       void eliminateIVComparison(ICmpInst *ICmp, Value *IVOperand);
    > @@ -84,26 +84,30 @@
    >
    >   /// foldIVUser - Fold an IV operand into its use.  This removes increments of an
    >   /// aligned IV when used by a instruction that ignores the low bits.
    > -bool SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
    > +///
    > +/// Return the operand of IVOperand for this induction variable if IVOperand can
    > +/// be folded (in case more folding opportunity has been exposed).
    
    "folding opportunity has" --> "folding opportunities have"?
    
    > +/// Otherwise return null.
    > +Value *SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) {
    >     Value *IVSrc = 0;
    >     unsigned OperIdx = 0;
    >     const SCEV *FoldedExpr = 0;
    >     switch (UseInst->getOpcode()) {
    >     default:
    > -    return false;
    > +    return 0;
    >     case Instruction::UDiv:
    >     case Instruction::LShr:
    >       // We're only interested in the case where we know something about
    >       // the numerator and have a constant denominator.
    >       if (IVOperand != UseInst->getOperand(OperIdx) ||
    >           !isa(UseInst->getOperand(1)))
    > -      return false;
    > +      return 0;
    >
    >       // Attempt to fold a binary operator with constant operand.
    >       // e.g. ((I + 1)>>  2) =>  I>>  2
    >       if (IVOperand->getNumOperands() != 2 ||
    >           !isa(IVOperand->getOperand(1)))
    > -      return false;
    > +      return 0;
    >
    >       IVSrc = IVOperand->getOperand(0);
    >       // IVSrc must be the (SCEVable) IV, since the other operand is const.
    > @@ -114,7 +118,7 @@
    >         // Get a constant for the divisor. See createSCEV.
    >         uint32_t BitWidth = cast(UseInst->getType())->getBitWidth();
    >         if (D->getValue().uge(BitWidth))
    > -        return false;
    > +        return 0;
    >
    >         D = ConstantInt::get(UseInst->getContext(),
    >                              APInt(BitWidth, 1).shl(D->getZExtValue()));
    > @@ -123,11 +127,11 @@
    >     }
    >     // We have something that might fold it's operand. Compare SCEVs.
    >     if (!SE->isSCEVable(UseInst->getType()))
    > -    return false;
    > +    return 0;
    >
    >     // Bypass the operand if SCEV can prove it has no effect.
    >     if (SE->getSCEV(UseInst) != FoldedExpr)
    > -    return false;
    > +    return 0;
    >
    >     DEBUG(dbgs()<<  "INDVARS: Eliminated IV operand: "<<  *IVOperand
    >           <<  " ->  "<<  *UseInst<<  '\n');
    > @@ -139,7 +143,7 @@
    >     Changed = true;
    >     if (IVOperand->use_empty())
    >       DeadInsts.push_back(IVOperand);
    > -  return true;
    > +  return IVSrc;
    >   }
    >
    >   /// eliminateIVComparison - SimplifyIVUsers helper for eliminating useless
    > @@ -337,10 +341,20 @@
    >       // Bypass back edges to avoid extra work.
    >       if (UseOper.first == CurrIV) continue;
    >
    > -    foldIVUser(UseOper.first, UseOper.second);
    > +    Instruction *IVOperand = UseOper.second;
    > +    for (unsigned N = 0; IVOperand; ++N) {
    > +      assert(N<= Simplified.size()&&  "runaway iteration");
    > +
    > +      Value *NewOper = foldIVUser(UseOper.first, IVOperand);
    > +      if (!NewOper)
    > +        break; // done folding
    > +      IVOperand = dyn_cast(NewOper);
    > +    }
    > +    if (!IVOperand)
    > +      continue;
    >
    > -    if (eliminateIVUser(UseOper.first, UseOper.second)) {
    > -      pushIVUsers(UseOper.second, Simplified, SimpleIVUsers);
    > +    if (eliminateIVUser(UseOper.first, IVOperand)) {
    > +      pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
    >         continue;
    >       }
    >       CastInst *Cast = dyn_cast(UseOper.first);
    >
    >
    > _______________________________________________
    > llvm-commits mailing list
    > llvm-commits at cs.uiuc.edu
    > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
    >
    
    
    From nicholas at mxc.ca  Wed Aug 10 00:18:48 2011
    From: nicholas at mxc.ca (Nick Lewycky)
    Date: Tue, 09 Aug 2011 22:18:48 -0700
    Subject: [llvm-commits] [llvm] r137203 - in /llvm/trunk:
     lib/Transforms/Scalar/LoopUnrollPass.cpp
     lib/Transforms/Utils/LoopUnroll.cpp
     test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll
    In-Reply-To: <20110810042949.62A0B2A6C12D@llvm.org>
    References: <20110810042949.62A0B2A6C12D@llvm.org>
    Message-ID: <4E4214B8.2050603@mxc.ca>
    
    Andrew Trick wrote:
    > Author: atrick
    > Date: Tue Aug  9 23:29:49 2011
    > New Revision: 137203
    >
    > URL: http://llvm.org/viewvc/llvm-project?rev=137203&view=rev
    > Log:
    > Invoke SimplifyIndVar when we partially unroll a loop. Fixes PR10534.
    >
    > Added:
    >      llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll
    > Modified:
    >      llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
    >      llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    >
    > Modified: llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp?rev=137203&r1=137202&r2=137203&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp (original)
    > +++ llvm/trunk/lib/Transforms/Scalar/LoopUnrollPass.cpp Tue Aug  9 23:29:49 2011
    > @@ -79,6 +79,7 @@
    >         AU.addPreservedID(LoopSimplifyID);
    >         AU.addRequiredID(LCSSAID);
    >         AU.addPreservedID(LCSSAID);
    > +      AU.addRequired();
    >         AU.addPreserved();
    >         // FIXME: Loop unroll requires LCSSA. And LCSSA requires dom info.
    >         // If loop unroll does not preserve dom info then LCSSA pass on next
    > @@ -187,12 +188,8 @@
    >     }
    >
    >     // Unroll the loop.
    > -  Function *F = L->getHeader()->getParent();
    >     if (!UnrollLoop(L, Count, TripCount, TripMultiple, LI,&LPM))
    >       return false;
    >
    > -  // FIXME: Reconstruct dom info, because it is not preserved properly.
    > -  if (DominatorTree *DT = getAnalysisIfAvailable())
    > -    DT->runOnFunction(*F);
    >     return true;
    >   }
    >
    > Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=137203&r1=137202&r2=137203&view=diff
    > ==============================================================================
    > --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original)
    > +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Tue Aug  9 23:29:49 2011
    > @@ -29,6 +29,7 @@
    >   #include "llvm/Transforms/Utils/BasicBlockUtils.h"
    >   #include "llvm/Transforms/Utils/Cloning.h"
    >   #include "llvm/Transforms/Utils/Local.h"
    > +#include "llvm/Transforms/Utils/SimplifyIndVar.h"
    >   using namespace llvm;
    >
    >   // TODO: Should these be here or in LoopUnroll?
    > @@ -130,6 +131,9 @@
    >   ///
    >   /// If a LoopPassManager is passed in, and the loop is fully removed, it will be
    >   /// removed from the LoopPassManager as well. LPM can also be NULL.
    > +///
    > +/// This utility preserves LoopInfo. If DominatorTree or ScalarEvolution are
    > +/// available it must also preseve those analyses.
    
    Typo, "preseve".
    
    >   bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount,
    >                         unsigned TripMultiple, LoopInfo *LI, LPPassManager *LPM) {
    >     BasicBlock *Preheader = L->getLoopPreheader();
    > @@ -163,7 +167,8 @@
    >
    >     // Notify ScalarEvolution that the loop will be substantially changed,
    >     // if not outright eliminated.
    > -  if (ScalarEvolution *SE = LPM->getAnalysisIfAvailable())
    > +  ScalarEvolution *SE = LPM->getAnalysisIfAvailable();
    > +  if (SE)
    >       SE->forgetLoop(L);
    >
    >     if (TripCount != 0)
    > @@ -374,6 +379,24 @@
    >       }
    >     }
    >
    > +  // FIXME: Reconstruct dom info, because it is not preserved properly.
    > +  // Incrementally updating domtree after loop unrolling woud be easy.
    
    Typo, "woud".
    
    Nick
    
    > +  if (DominatorTree *DT = LPM->getAnalysisIfAvailable())
    > +    DT->runOnFunction(*L->getHeader()->getParent());
    > +
    > +  // Simplify any new induction variables in the partially unrolled loop.
    > +  if (SE&&  !CompletelyUnroll) {
    > +    SmallVector  DeadInsts;
    > +    simplifyLoopIVs(L, SE, LPM, DeadInsts);
    > +
    > +    // Aggressively clean up dead instructions that simplifyLoopIVs already
    > +    // identified. Any remaining should be cleaned up below.
    > +    while (!DeadInsts.empty())
    > +      if (Instruction *Inst =
    > +          dyn_cast_or_null(&*DeadInsts.pop_back_val()))
    > +        RecursivelyDeleteTriviallyDeadInstructions(Inst);
    > +  }
    > +
    >     // At this point, the code is well formed.  We now do a quick sweep over the
    >     // inserted code, doing constant propagation and dead code elimination as we
    >     // go.
    >
    > Added: llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll
    > URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll?rev=137203&view=auto
    > ==============================================================================
    > --- llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll (added)
    > +++ llvm/trunk/test/Transforms/LoopUnroll/2011-08-09-IVSimplify.ll Tue Aug  9 23:29:49 2011
    > @@ -0,0 +1,39 @@
    > +; RUN: opt -S<  %s -loop-unroll -unroll-count=4 -disable-iv-rewrite | FileCheck %s
    > +;
    > +; Test induction variable simplify after loop unrolling. It should
    > +; expose nice opportunities for GVN.
    > +
    > +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
    > +
    > +; PR10534: LoopUnroll not keeping canonical induction variable...
    > +; CHECK: while.body.1:
    > +; CHECK: %shr.1 = lshr i32 %bit_addr.addr.01, 5
    > +; CHECK: %arrayidx.1 = getelementptr inbounds i32* %bitmap, i32 %shr.1
    > +; CHECK: while.body.2:
    > +; CHECK: %shr.2 = lshr i32 %bit_addr.addr.01, 5
    > +; CHECK: %arrayidx.2 = getelementptr inbounds i32* %bitmap, i32 %shr.2
    > +; CHECK: while.body.3:
    > +; CHECK: %shr.3 = lshr i32 %bit_addr.addr.01, 5
    > +; CHECK: %arrayidx.3 = getelementptr inbounds i32* %bitmap, i32 %shr.3
    > +define void @FlipBit(i32* nocapture %bitmap, i32 %bit_addr, i32 %nbits) nounwind {
    > +entry:
    > +  br label %while.body
    > +
    > +while.body:
    > +  %nbits.addr.02 = phi i32 [ 128, %entry ], [ %dec, %while.body ]
    > +  %bit_addr.addr.01 = phi i32 [ 0, %entry ], [ %inc, %while.body ]
    > +  %dec = add i32 %nbits.addr.02, -1
    > +  %shr = lshr i32 %bit_addr.addr.01, 5
    > +  %rem = and i32 %bit_addr.addr.01, 31
    > +  %shl = shl i32 1, %rem
    > +  %arrayidx = getelementptr inbounds i32* %bitmap, i32 %shr
    > +  %tmp6 = load i32* %arrayidx, align 4
    > +  %xor = xor i32 %tmp6, %shl
    > +  store i32 %xor, i32* %arrayidx, align 4
    > +  %inc = add i32 %bit_addr.addr.01, 1
    > +  %tobool = icmp eq i32 %dec, 0
    > +  br i1 %tobool, label %while.end, label %while.body
    > +
    > +while.end:
    > +  ret void
    > +}
    >
    >
    > _______________________________________________
    > llvm-commits mailing list
    > llvm-commits at cs.uiuc.edu
    > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
    >
    
    
    From lattner at apple.com  Wed Aug 10 00:52:10 2011
    From: lattner at apple.com (Tanya Lattner)
    Date: Tue, 09 Aug 2011 22:52:10 -0700
    Subject: [llvm-commits] [PATCH] miscompile due to incorrect MOVSS pattern
    Message-ID: <54051C17-30B3-4118-BBE8-C407A1571C2C@apple.com>
    
    I believe the following X86 pattern is incorrect:
    def : Pat<(X86Movss VR128:$src1,
                        (bc_v4i32 (v2i64 (load addr:$src2)))),
              (MOVLPSrm VR128:$src1, addr:$src2)>;
    
    This matches a MOVSS dag with a MOVLPS instruction. However, MOVSS will replace only the low 32 bits of the register, while the MOVLPS instruction will replace the low 64 bits.
    
    I've added my test case that illustrates the bug and also modified the one that was already present.
    
    Bruno - You seem to have added this pattern, so let me know if this is supposed to use some other instruction. It's not clear what you're trying to achieve with this pattern, so  my patch just removes it.
    
    Thanks,
    Tanya
    
    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: badMOVSSpat.patch
    Type: application/octet-stream
    Size: 2463 bytes
    Desc: not available
    Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110809/43f7ec4c/attachment.obj 
    
    From baldrick at free.fr  Wed Aug 10 02:43:08 2011
    From: baldrick at free.fr (Duncan Sands)
    Date: Wed, 10 Aug 2011 09:43:08 +0200
    Subject: [llvm-commits] [llvm-gcc-4.2] r136345 -
    	/llvm-gcc-4.2/trunk/gcc/llvm-convert.cpp
    In-Reply-To: 
    References: <20110728091343.E09F02A6C12C@llvm.org>
    	<515E325F-1081-4CB8-8296-C8D1F5F06E8C@apple.com>
    	<4E35A51A.6050009@free.fr>
    	
    	<4E36E21A.2050103@free.fr>
    	
    Message-ID: <4E42368C.9020705@free.fr>
    
    Hi Bob, after thinking about this some more, I think it is reasonable to add
    support for a new global variable initializer having a different type to the
    original (i.e. directly addressing the ObjC problem).  Right now, places that
    directly convert a T* will get a convert(T)*; it's only a T* that occurs inside
    a struct that might get converted oddly.  Code like the COMPONENT_REF logic
    that dig down into structs do the right thing because they only convert
    pointers directly, and don't assume that struct fields of pointer type have the
    right type.  So I don't think anything can go wrong.
    
    I will try to do something within the next few days.
    
    Ciao, Duncan.
    
    >>>>> commit 136600 hopefully fixed these failures.
    >>>>
    >>>> I haven't confirmed yet whether it fixed the ARM problems (due to other issues),
    >>>> but it seems to be causing massive failures on i386:
    >>>>
    >>>> http://llvm.org/perf/db_default/simple/nts/263/
    >>>>
    >>>> I can reproduce some of those failures with -O0 and we're not seeing any issues
    >>>> with clang, so I think it's due to your change. I'm going to revert it for now
    >>>> and re-run the tests to confirm that.
    >>>
    >>> OK, sorry for the breakage.  I only tested on x86-64, I will take a look at
    >>> i386.
    >>
    >> Duncan, are you still planning to get to this?  Those ObjC unit tests are still failing.
    >
    > not really.  The basic problem is that the same GCC pointer type is
    > converted into more than one LLVM type, depending on whether it is
    > converted as part of converting an enclosing struct or not.  In the
    > ObjC testcases this results in an apparent change in the initializer:
    > the initializer is basically unchanged, only the type of some pointers
    > changed.
    >
    > This can be fixed by caching the result of the pointer conversion the
    > first time it happens, and then using that everywhere.  This resulted
    > in miscompiles on x86 (and presumably elsewhere, only less spectacular),
    > because code in various parts of llvm-gcc assumes that if you convert
    > a T*, then you get a pointer to convert(T).  For example, to evaluate
    > p + n where p is a T*, it (IIRC) just does a "GEP p, n".  But if sometimes
    > T* is converted to i8*, then "GEP p, n" advances by n bytes rather than
    > by n * sizeof(T) bytes.
    >
    > In fact, if you think about it, if ever convert(T*) != convert(T)*, then
    > there is a chance of things going wrong.  Unfortunately the new type
    > system requires that occasionally T* not be converted to convert(T)*.
    >
    > The right thing to do is to audit all of the llvm-gcc code for places
    > where it makes assumptions about how T* is converted, and fix them all.
    > I actually did this in dragonegg some time ago, which is why it doesn't
    > suffer like llvm-gcc does from the new type system.
    >
    > The quick and nasty thing to do is to paper over problems until you don't
    > notice problems any more.  For example, fix the objc testcases by handling the
    > case where the new initializer doesn't have the same type as the old one.
    >
    > I'm not interested in auditing llvm-gcc's code (though probably there wouldn't
    > be too much to check).  I'm also not interested in hacking in a nasty "fix".
    > Thus I'm not planning to do anything about this.
    >
    > Ciao, Duncan.
    >
    > PS: You could revert the change that fixed the Fortran builders, and stop
    > those builders from building Fortran.  That would also just be papering over
    > the underlying problem, but maybe is acceptable.
    
    
    From nadav.rotem at intel.com  Wed Aug 10 02:53:47 2011
    From: nadav.rotem at intel.com (Rotem, Nadav)
    Date: Wed, 10 Aug 2011 10:53:47 +0300
    Subject: [llvm-commits] [PATCH] Optimize trunc store
    In-Reply-To: <6594DDFF12B03D4E89690887C24869940296EB851B@hasmsx504.ger.corp.intel.com>
    References: <6594DDFF12B03D4E89690887C24869940296EB851B@hasmsx504.ger.corp.intel.com>
    Message-ID: <6594DDFF12B03D4E89690887C24869940296F2C0BC@hasmsx504.ger.corp.intel.com>
    
    ping
    
    From: llvm-commits-bounces at cs.uiuc.edu [mailto:llvm-commits-bounces at cs.uiuc.edu] On Behalf Of Rotem, Nadav
    Sent: Monday, August 08, 2011 21:44
    To: llvm-commits at cs.uiuc.edu
    Subject: [llvm-commits] [PATCH] Optimize trunc store
    
    Hi,
    
    Please review the attached patch. When performing a truncating store, it is sometimes possible to rearrange the data in-register prior to saving to memory.  When we reorder the data in memory we prevent the need to save multiple scalars to memory, making a single regular store.
    
    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.
    ---------------------------------------------------------------------
    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 --------------
    An HTML attachment was scrubbed...
    URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/9f15487e/attachment.html 
    
    From baldrick at free.fr  Wed Aug 10 02:57:11 2011
    From: baldrick at free.fr (Duncan Sands)
    Date: Wed, 10 Aug 2011 09:57:11 +0200
    Subject: [llvm-commits] [PATCH] [dragonegg] Basic support for assembling
     constants
    In-Reply-To: <20110810013526.GB13197@pcc.me.uk>
    References: <20110810013526.GB13197@pcc.me.uk>
    Message-ID: <4E4239D7.2030403@free.fr>
    
    Hi Peter,
    
    > OK to commit?
    
    what's it for?  Also, please provide a testcase [*].
    
    Ciao, Duncan.
    
    [*] In spite of appearances there is a dragonegg testsuite, I just didn't make
    it public yet.
    
    From zwarich at apple.com  Wed Aug 10 03:15:27 2011
    From: zwarich at apple.com (Cameron Zwarich)
    Date: Wed, 10 Aug 2011 01:15:27 -0700
    Subject: [llvm-commits] [PATCH] Optimize trunc store
    In-Reply-To: <6594DDFF12B03D4E89690887C24869940296EB851B@hasmsx504.ger.corp.intel.com>
    References: <6594DDFF12B03D4E89690887C24869940296EB851B@hasmsx504.ger.corp.intel.com>
    Message-ID: 
    
    Is this safe to do for volatile stores?
    
    Cameron
    
    From nadav.rotem at intel.com  Wed Aug 10 03:27:02 2011
    From: nadav.rotem at intel.com (Rotem, Nadav)
    Date: Wed, 10 Aug 2011 11:27:02 +0300
    Subject: [llvm-commits] [PATCH] Optimize trunc store
    In-Reply-To: 
    References: <6594DDFF12B03D4E89690887C24869940296EB851B@hasmsx504.ger.corp.intel.com>
    	
    Message-ID: <6594DDFF12B03D4E89690887C24869940296F2C124@hasmsx504.ger.corp.intel.com>
    
    I think it's okay. The value has to be written to memory. Does it matter if it is saved as a sequence of scalars or as one big word ?
    
    -----Original Message-----
    From: Cameron Zwarich [mailto:zwarich at apple.com] 
    Sent: Wednesday, August 10, 2011 11:15
    To: Rotem, Nadav
    Cc: llvm-commits at cs.uiuc.edu
    Subject: Re: [llvm-commits] [PATCH] Optimize trunc store
    
    Is this safe to do for volatile stores?
    
    Cameron
    ---------------------------------------------------------------------
    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.
    
    
    
    From baldrick at free.fr  Wed Aug 10 06:08:30 2011
    From: baldrick at free.fr (Duncan Sands)
    Date: Wed, 10 Aug 2011 11:08:30 -0000
    Subject: [llvm-commits] [dragonegg] r137209 -
    	/dragonegg/trunk/src/Convert.cpp
    Message-ID: <20110810110830.19BDB2A6C12C@llvm.org>
    
    Author: baldrick
    Date: Wed Aug 10 06:08:29 2011
    New Revision: 137209
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137209&view=rev
    Log:
    With gcc-4.6, when a C++ class is returned by value it may be that
    the address to return it in is provided in the RESULT_DECL, in which
    case reading from the RESULT_DECL can result in something other than
    undef.  Based on a patch by Peter Collingbourne.
    
    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=137209&r1=137208&r2=137209&view=diff
    ==============================================================================
    --- dragonegg/trunk/src/Convert.cpp (original)
    +++ dragonegg/trunk/src/Convert.cpp Wed Aug 10 06:08:29 2011
    @@ -6499,8 +6499,11 @@
       // 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)
    +  // read, it has an undefined value for VAR_DECLs (a RESULT_DECL can have
    +  // an initial value if the function returns a class by value).
    +  assert((TREE_CODE(var) == PARM_DECL || TREE_CODE(var) == RESULT_DECL ||
    +          TREE_CODE(var) == VAR_DECL) && "Unsupported SSA name definition!");
    +  if (TREE_CODE(var) == VAR_DECL)
         return DefineSSAName(reg, UndefValue::get(getRegType(TREE_TYPE(reg))));
     
       // Read the initial value of the parameter and associate it with the ssa name.
    
    
    
    From baldrick at free.fr  Wed Aug 10 06:42:57 2011
    From: baldrick at free.fr (Duncan Sands)
    Date: Wed, 10 Aug 2011 13:42:57 +0200
    Subject: [llvm-commits] [PATCH] [dragonegg] Support default definition
     of RESULT_DECL
    In-Reply-To: <20110805134138.GA15794@pcc.me.uk>
    References: <20110805134138.GA15794@pcc.me.uk>
    Message-ID: <4E426EC1.9060402@free.fr>
    
    Hi Peter, I applied a variant of this patch.  Thanks for working on dragonegg!
    
    Ciao, Duncan.
    
    From baldrick at free.fr  Wed Aug 10 06:43:40 2011
    From: baldrick at free.fr (Duncan Sands)
    Date: Wed, 10 Aug 2011 13:43:40 +0200
    Subject: [llvm-commits] [PATCH] [dragonegg] Support default definition
     of RESULT_DECL
    In-Reply-To: <20110810013032.GA13197@pcc.me.uk>
    References: <20110805134138.GA15794@pcc.me.uk> <4E3BF561.1010507@free.fr>
    	<20110810013032.GA13197@pcc.me.uk>
    Message-ID: <4E426EEC.7060707@free.fr>
    
    Hi Peter,
    
    > I came up with a test case, see attached.  Note that I can only get it
    > to fail without my patch applied using gcc 4.6 (i.e. gcc-4_6-branch).
    > I guess we can put this in test/FrontendC++, but it looks like the
    > test/Frontend* tests are slowly being moved to clang or deleted.
    > I suppose dragonegg should get its own test suite at some point?
    
    thanks for the testcase, I've added it to the dragonegg testsuite (which is
    not yet public).
    
    Ciao, Duncan.
    
    From baldrick at free.fr  Wed Aug 10 07:18:40 2011
    From: baldrick at free.fr (Duncan Sands)
    Date: Wed, 10 Aug 2011 12:18:40 -0000
    Subject: [llvm-commits] [dragonegg] r137210 - in /dragonegg/trunk:
     include/dragonegg/Types.h src/Constants.cpp src/Convert.cpp src/Types.cpp
    Message-ID: <20110810121840.2B46C2A6C12C@llvm.org>
    
    Author: baldrick
    Date: Wed Aug 10 07:18:39 2011
    New Revision: 137210
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137210&view=rev
    Log:
    Get rid of isSequentialCompatible, replacing it with isSizeCompatible [the
    relationship is: isSequentialCompatible(t) = isSizeCompatible(TREE_TYPE(t))].
    
    Modified:
        dragonegg/trunk/include/dragonegg/Types.h
        dragonegg/trunk/src/Constants.cpp
        dragonegg/trunk/src/Convert.cpp
        dragonegg/trunk/src/Types.cpp
    
    Modified: dragonegg/trunk/include/dragonegg/Types.h
    URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/include/dragonegg/Types.h?rev=137210&r1=137209&r2=137210&view=diff
    ==============================================================================
    --- dragonegg/trunk/include/dragonegg/Types.h (original)
    +++ dragonegg/trunk/include/dragonegg/Types.h Wed Aug 10 07:18:39 2011
    @@ -65,11 +65,10 @@
     extern llvm::Type *GetUnitPointerType(llvm::LLVMContext &C,
                                           unsigned AddrSpace = 0);
     
    -/// 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.
    -extern bool isSequentialCompatible(tree_node *type);
    +/// isSizeCompatible - Return true if the specified gcc type is guaranteed to be
    +/// turned by ConvertType into an LLVM type of the same size (i.e. TYPE_SIZE the
    +/// same as getTypeAllocSizeInBits).
    +extern bool isSizeCompatible(tree_node *type);
     
     /// 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
    
    Modified: dragonegg/trunk/src/Constants.cpp
    URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Constants.cpp?rev=137210&r1=137209&r2=137210&view=diff
    ==============================================================================
    --- dragonegg/trunk/src/Constants.cpp (original)
    +++ dragonegg/trunk/src/Constants.cpp Wed Aug 10 07:18:39 2011
    @@ -804,7 +804,7 @@
       Type *EltTy = ConvertType(elt_type);
     
       // Check that the element type has a known, constant size.
    -  assert(isSequentialCompatible(init_type) && "Variable sized array element!");
    +  assert(isSizeCompatible(elt_type) && "Variable sized array element!");
       uint64_t EltSize = TD.getTypeAllocSizeInBits(EltTy);
     
       /// Elts - The initial values to use for the array elements.  A null entry
    @@ -1397,7 +1397,7 @@
       assert(TREE_CODE(TREE_TYPE(array)) == ARRAY_TYPE && "Unknown ARRAY_REF!");
     
       // Check for variable sized reference.
    -  assert(isSequentialCompatible(TREE_TYPE(array)) &&
    +  assert(isSizeCompatible(TREE_TYPE(TREE_TYPE(array))) &&
              "Global with variable size?");
     
       // Get the index into the array as an LLVM integer constant.
    
    Modified: dragonegg/trunk/src/Convert.cpp
    URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Convert.cpp?rev=137210&r1=137209&r2=137210&view=diff
    ==============================================================================
    --- dragonegg/trunk/src/Convert.cpp (original)
    +++ dragonegg/trunk/src/Convert.cpp Wed Aug 10 07:18:39 2011
    @@ -1466,7 +1466,7 @@
       // For array types, multiply the array length by the component cost.
       if (TREE_CODE(type) == ARRAY_TYPE) {
         // If this is an array with a funky component type then just give up.
    -    if (!isSequentialCompatible(type))
    +    if (!isSizeCompatible(TREE_TYPE(type)))
           return TooCostly;
         uint64_t ArrayLength = ArrayLengthOf(type);
         if (ArrayLength >= TooCostly)
    @@ -5636,7 +5636,7 @@
                                        /*isSigned*/!TYPE_UNSIGNED(IndexType));
     
       // If we are indexing over a fixed-size type, just use a GEP.
    -  if (isSequentialCompatible(ArrayTreeType)) {
    +  if (isSizeCompatible(ElementType)) {
         // Avoid any assumptions about how the array type is represented in LLVM by
         // doing the GEP on a pointer to the first array element.
         Type *EltTy = ConvertType(ElementType);
    
    Modified: dragonegg/trunk/src/Types.cpp
    URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Types.cpp?rev=137210&r1=137209&r2=137210&view=diff
    ==============================================================================
    --- dragonegg/trunk/src/Types.cpp (original)
    +++ dragonegg/trunk/src/Types.cpp Wed Aug 10 07:18:39 2011
    @@ -285,21 +285,14 @@
       return GetUnitType(C)->getPointerTo(AddrSpace);
     }
     
    -/// 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);
    +/// isSizeCompatible - Return true if the specified gcc type is guaranteed to be
    +/// turned by ConvertType into an LLVM type of the same size (i.e. TYPE_SIZE the
    +/// same as getTypeAllocSizeInBits).
    +bool isSizeCompatible(tree type) {
    +  return isInt64(TYPE_SIZE(type), true);
     }
     
    +
     //===----------------------------------------------------------------------===//
     //                   Matching LLVM types with GCC trees
     //===----------------------------------------------------------------------===//
    @@ -310,11 +303,11 @@
     static Type *llvm_set_type(tree Tr, Type *Ty) {
       assert(TYPE_P(Tr) && "Expected a gcc type!");
     
    +#ifndef NDEBUG
       // 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)) {
    +  if (Ty->isSized() && isSizeCompatible(Tr)) {
         uint64_t LLVMSize = getTargetData().getTypeAllocSizeInBits(Ty);
         if (getInt64(TYPE_SIZE(Tr), true) != LLVMSize) {
           errs() << "GCC: ";
    
    
    
    From kristof.beyls at arm.com  Wed Aug 10 08:41:28 2011
    From: kristof.beyls at arm.com (Kristof Beyls)
    Date: Wed, 10 Aug 2011 14:41:28 +0100
    Subject: [llvm-commits] [PATCH] Fix NOP encodings in ARM backend.
    In-Reply-To: 
    References: <001001cc55d2$c1c4e020$454ea060$%beyls@arm.com>
    	
    Message-ID: <000001cc5763$35a7ccf0$a0f766d0$@beyls@arm.com>
    
    Hi Jim,
    
    Thanks to have a look!
    
    1.  I need the exact functionality provided by ARMSubTarget::HasV6T2Ops.
    Therefore, in trying not to reinvent the wheel, and 
    to avoid code duplication, I'm trying to use ARMSubTarget::HasV6T2Ops. I
    think I've found a way to create an ARMSubTarget object from the Triple, so
    that it doesn't have to be passed across a lot of interfaces. The patch now
    only changes lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp (see attachment).
    Since it no longer touches Clang, I dropped the cfe-commits list. Could you
    have another look and see if this patch is closer to being acceptable?
    
    2. I've created the following bug report:
    http://llvm.org/bugs/show_bug.cgi?id=10632
    
    
    Thanks,
    
    Kristof
    
    -----Original Message-----
    From: Jim Grosbach [mailto:grosbach at apple.com] 
    Sent: 10 August 2011 00:08
    To: Kristof Beyls
    Cc: llvm-commits at cs.uiuc.edu; cfe-commits at cs.uiuc.edu
    Subject: Re: [llvm-commits] [PATCH] Fix NOP encodings in ARM backend.
    
    Hi Kristof,
    
    Thanks for looking at this.
    
    1. You should be able to derive the needed information from the Triple,
    which is already passed in. There's already some code there that does
    something similar to set the CPU Subtype correctly for Darwin MachO files.
    See the factory method createARMAsmBackend() for details. There shouldn't be
    any need to change the top level constructors or the target-independent
    bits.
    
    2. That sounds like a nasty bug. A bugzilla with a test case would be great.
    
    -Jim
    
    On Aug 8, 2011, at 6:54 AM, Kristof Beyls wrote:
    
    > Hi,
    > 
    > With the attached patch, I'm trying to fix a FIXME in the ARM backend.
    This
    > patch fixes ARMAsmBackend::WriteNopData, so that it takes into account the
    > version of the ARM architecture that is being targeted. For versions
    before
    > ARMv6T2, there is no NOP instruction, and NOPs are encoded as MOV r0,r0
    (in
    > ARM
    > mode) or MOV r8,r8 (in Thumb mode). For targets later than ARMv6T2, the
    > encoding for the NOP instruction is created.
    > 
    > I have a few questions about this patch:
    > 
    > 1. To make sure that ARMAsmBackend::WriteNopData can figure out which ARM
    >   sub-target it compiles for, I had to adapt the
    Target::MCAsmBackendCtorTy
    > to
    >   also pass on an MCSubtargetInfo argument. Is this the best way to get
    >   sub-target information to the ARMAsmBackend object?
    >   (this change results in a few function signature changes in the
    >    ARM, PowerPC, X86 and MBlaze backends).
    > 
    > 2. It's hard to create test cases to test this properly, since I think
    >   that there is another bug in lib/MC/MCAssembler.cpp, where processing 
    >   an alignment fragment results in calling ARMAsmBackend::WriteNopData,
    but
    >   without putting the ARMAsmBackend in the right ARM or Thumb state.
    >   Therefore, e.g. when processing an assembler file with .align directives
    >   in the middle of a Thumb code section, still ARM NOP encodings are 
    >   generated instead of Thumb NOP encodings.
    >   Question 2a: Is it OK to write a FIXME to indicate this brokenness?
    > Should
    >   I also file a bugzilla issue?
    >   Question 2b: Is it OK to leave that fix for a later, separate, patch?
    For
    >   that fix, it will be easier to create good test cases that will also
    test
    >   this patch.
    > 
    > Thanks,
    > 
    > Kristof
    > 
    > PS. I'm cc-ing to the cfe-commits list because the change in
    > Target::MCAsmBackendCtorTy requires 2 lines to change in Clang too, see
    > attached file
    clang_arm_nop_encoding.patch._______________________________________________
    > llvm-commits mailing list
    > llvm-commits at cs.uiuc.edu
    > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
    
    
    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: llvm_arm_nop_encoding_v2.patch
    Type: application/octet-stream
    Size: 5099 bytes
    Desc: not available
    Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/0212da88/attachment.obj 
    
    From baldrick at free.fr  Wed Aug 10 10:59:56 2011
    From: baldrick at free.fr (Duncan Sands)
    Date: Wed, 10 Aug 2011 15:59:56 -0000
    Subject: [llvm-commits] [dragonegg] r137215 -
    	/dragonegg/trunk/src/Backend.cpp
    Message-ID: <20110810155956.E92292A6C12C@llvm.org>
    
    Author: baldrick
    Date: Wed Aug 10 10:59:56 2011
    New Revision: 137215
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137215&view=rev
    Log:
    Moving output of externally visible global variables into the
    PLUGIN_ALL_IPA_PASSES_END hook means it runs just before cgraph
    removes unneeded variables (while before it was running after).
    This results in lots of extra variables being output with gcc-4.6,
    causing link failures due to linkage not being output quite right.
    This patch tweaks linkage, making that part of things a bit better
    (I'm not convinced it is completely correct though); and it uses a
    more powerful test for which variables need to be output, resulting
    in essentially the same output as if cgraph variable removal had
    been done first.
    
    Modified:
        dragonegg/trunk/src/Backend.cpp
    
    Modified: dragonegg/trunk/src/Backend.cpp
    URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Backend.cpp?rev=137215&r1=137214&r2=137215&view=diff
    ==============================================================================
    --- dragonegg/trunk/src/Backend.cpp (original)
    +++ dragonegg/trunk/src/Backend.cpp Wed Aug 10 10:59:56 2011
    @@ -863,25 +863,23 @@
       // Set the linkage.
       GlobalValue::LinkageTypes Linkage;
     
    -  if (CODE_CONTAINS_STRUCT (TREE_CODE (decl), TS_DECL_WITH_VIS)
    -      && false) {// FIXME DECL_LLVM_PRIVATE(decl)) {
    +  if (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)) {
    +  } else if (false) {//FIXME DECL_LLVM_LINKER_PRIVATE(decl)) {
         Linkage = GlobalValue::LinkerPrivateLinkage;
       } else if (!TREE_PUBLIC(decl)) {
         Linkage = GlobalValue::InternalLinkage;
    +  } else if (DECL_COMDAT(decl)) {
    +    Linkage = GlobalValue::getLinkOnceLinkage(flag_odr);
    +  } else if (DECL_ONE_ONLY(decl)) {
    +    Linkage = GlobalValue::getWeakLinkage(flag_odr);
       } 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();
       }
    @@ -1664,11 +1662,17 @@
       for (struct varpool_node *vnode = varpool_nodes; vnode; vnode = vnode->next) {
         if (!vnode->needed || vnode->alias)
           continue;
    +    tree decl = vnode->decl;
    +    // If this variable need not be output if unused, then skip it.
    +    if (!vnode->force_output && vnode->analyzed &&
     #if (GCC_MINOR > 5)
    -    if (vnode->in_other_partition)
    -      continue;
    +        varpool_can_remove_if_no_refs(vnode)
    +#else
    +        (DECL_COMDAT(decl) || (DECL_ARTIFICIAL(decl) &&
    +                               !vnode->externally_visible))
     #endif
    -    tree decl = vnode->decl;
    +       )
    +      continue;
         if (TREE_CODE(decl) == VAR_DECL && !DECL_EXTERNAL(decl) &&
             (TREE_PUBLIC(decl) || DECL_PRESERVE_P(decl) ||
              TREE_THIS_VOLATILE(decl)))
    
    
    
    From justin.holewinski at gmail.com  Wed Aug 10 11:05:28 2011
    From: justin.holewinski at gmail.com (Justin Holewinski)
    Date: Wed, 10 Aug 2011 12:05:28 -0400
    Subject: [llvm-commits] [PATCH] Add basic documentation for PTX back-end in
    	HTML docs
    Message-ID: 
    
    This patch adds some basic documentation on the in-progress PTX back-end
    (part of my Google Summer of Code project).
    
    Is this okay to commit?
    
    -- 
    
    Thanks,
    
    Justin Holewinski
    -------------- next part --------------
    An HTML attachment was scrubbed...
    URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/c050f7d0/attachment.html 
    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: 0001-PTX-Add-basic-documentation-to-CodeGenerator.html.patch
    Type: application/octet-stream
    Size: 2970 bytes
    Desc: not available
    Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/c050f7d0/attachment.obj 
    
    From pranavb at codeaurora.org  Wed Aug 10 08:07:39 2011
    From: pranavb at codeaurora.org (Pranav Bhandarkar)
    Date: Wed, 10 Aug 2011 08:07:39 -0500
    Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction
    	combiner.
    Message-ID: <000d01cc575e$7c2c1d70$74845850$@org>
    
    Hi,
    
    Subsequent to a discussion on the 'nsw' flag on llvm dev
    (http://lists.cs.uiuc.edu/pipermail/llvmdev/2011-June/040856.html), I have
    written a small function that allows the instruction combiner to preserve
    the 'nsw' flag under certain conditions. Preserving this flag allows
    optimization passes down the pipeline to be more aggressive.
    
    For instance, consider this synthetic test case.
    int foo (int x)
    {     int j = x + 2;
          int y = j + 3;
    
          if (j < y) return 1;
          else return 0;
    }
    This can be reduced to always return 1. However LLVM does not do this
    transformation. Consider the following piece of code
    
    1 %add = add nsw i32 %tmp, 2
    2 %add3 = add nsw i32 %add, 3
    3 %cmp = icmp slt i32 %add, %add3
    4 br i1 %cmp, label %if.then, label %if.else
    
    Here add = tmp + 2 and add3 is effectively tmp + 5 and the comparison "slt
    %add, %add3" is always true. However, the instruction combiner combines
    instructions 1 and 2 to produce
    
    2 %add3 = add i32 %tmp, 5
    
    Note the 'nsw' flag is dropped because the combiner does not reason about
    the applicability of the 'nsw' flag in the new combined instruction. If now
    the simplifycfg pass is run it does not simplify the comparison because one
    of its operands has the 'nsw' flag while the other does not. The attached
    patch checks the resulting constant in the new instruction for overflow. If
    not, it keeps the flag. This allows the "simplifycfg" pass to simplify the
    comparison and reduces the above function to return 1.
    
    I have three attachments - The patch, a testcase that should be added to
    test/Transforms/InstCombine and my regression report. This patch was
    successfully regression tested on x86_64.
    
    Pranav
    -------------- next part --------------
    An embedded and charset-unspecified text was scrubbed...
    Name: MaintainNoSignedWrap.txt
    Url: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/fff2afbb/attachment.txt 
    -------------- next part --------------
    A non-text attachment was scrubbed...
    Name: nsw_preserve.ll
    Type: application/octet-stream
    Size: 613 bytes
    Desc: not available
    Url : http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/fff2afbb/attachment.obj 
    -------------- next part --------------
    An embedded and charset-unspecified text was scrubbed...
    Name: RegressionReport.txt
    Url: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/fff2afbb/attachment-0001.txt 
    
    From rafael.espindola at gmail.com  Wed Aug 10 11:16:00 2011
    From: rafael.espindola at gmail.com (=?ISO-8859-1?Q?Rafael_=C1vila_de_Esp=EDndola?=)
    Date: Wed, 10 Aug 2011 12:16:00 -0400
    Subject: [llvm-commits] [patch][arm] Implement support for the Q,
     R and H modifiers
    In-Reply-To: 
    References: <4E3AFA25.6040300@gmail.com>
    	<27F14F88-6F43-4A4F-9F53-280370D1CC57@apple.com>
    	<1E673A39-42C2-400D-8C77-D43D014E1ABF@2pi.dk>
    	<4E4000A6.1070908@gmail.com>
    	<23DF2B59-63B7-4334-8B06-4AC2BAF43D56@2pi.dk>
    	<4E401109.1050203@gmail.com>
    	
    	<4E401D24.4060605@gmail.com>
    	
    	<4E4032A3.4050608@gmail.com>
    	
    Message-ID: <4E42AEC0.6020909@gmail.com>
    
    >>> This means that in the case of stm/ldm instructions with the 'Q'
    >>> and 'R' modifiers that we'd get registers that weren't meant,
    >>> leading to subtle problems that users would need to debug. When
    >>> we get support for assigning values into consecutive registers
    >>> this won't be a problem.
    >>>
    >>> What are your thoughts?
    >>
    >> This is the first time I have seen these constraints, so I don't
    >> know how common they are and of those uses which ones assume
    >> sequential registers.
    >>
    >
    > Btw, these are modifiers not constraints just to be careful about
    > it.
    
    Well, they will be both once we implement the constraint that the 
    arguments must be paired.
    
    >> So, I guess this is a judgment call. The current patch allows us to
    >> handle some inline asm but causes us to miscompile others that we
    >> currently reject.
    >
    > I'm going to say we should add them for now. People that are using it
    > incorrectly may get a hard to debug problem, but the use case you
    > guys have totally makes sense and isn't necessarily easy to rewrite
    > to make more sense. Though, seriously, what's wrong with a .s file
    > for that function?
    
    I would probably have used a .s file myself. I think in this case the 
    preference was for inline assembly because the full function looks like
    
    #if x86
    ...
    #else if arm
    ...
    #else
    C fallback
    #endif
    
    > -eric
    
    Thanks,
    Rafael
    
    From rafael.espindola at gmail.com  Wed Aug 10 11:26:42 2011
    From: rafael.espindola at gmail.com (Rafael Espindola)
    Date: Wed, 10 Aug 2011 16:26:42 -0000
    Subject: [llvm-commits] [llvm] r137217 - in /llvm/trunk:
     lib/Target/ARM/ARMAsmPrinter.cpp test/CodeGen/ARM/inlineasm4.ll
    Message-ID: <20110810162642.65DBA2A6C12C@llvm.org>
    
    Author: rafael
    Date: Wed Aug 10 11:26:42 2011
    New Revision: 137217
    
    URL: http://llvm.org/viewvc/llvm-project?rev=137217&view=rev
    Log:
    Add support for the R and Q constraints.
    
    Added:
        llvm/trunk/test/CodeGen/ARM/inlineasm4.ll
    Modified:
        llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
    
    Modified: llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp?rev=137217&r1=137216&r2=137217&view=diff
    ==============================================================================
    --- llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp (original)
    +++ llvm/trunk/lib/Target/ARM/ARMAsmPrinter.cpp Wed Aug 10 11:26:42 2011
    @@ -469,14 +469,34 @@
     
           return false;
         }
    +    case 'R': // The most significant register of a pair.
    +    case 'Q': { // The least significant register of a pair.
    +      if (OpNum == 0)
    +        return true;
    +      const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
    +      if (!FlagsOP.isImm())
    +        return true;
    +      unsigned Flags = FlagsOP.getImm();
    +      unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
    +      if (NumVals != 2)
    +        return true;
    +      unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1;
    +      if (RegOp >= MI->getNumOperands())
    +        return true;
    +      const MachineOperand &MO = MI->getOperand(RegOp);
    +      if (!MO.isReg())
    +        return true;
    +      unsigned Reg = MO.getReg();
    +      O << ARMInstPrinter::getRegisterName(Reg);
    +      return false;
    +    }
    +
         // These modifiers are not yet supported.
         case 'p': // The high single-precision register of a VFP double-precision
                   // register.
         case 'e': // The low doubleword register of a NEON quad register.
         case 'f': // The high doubleword register of a NEON quad register.
         case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
    -    case 'Q': // The least significant register of a pair.
    -    case 'R': // The most significant register of a pair.
         case 'H': // The highest-numbered register of a pair.
           return true;
         }
    
    Added: llvm/trunk/test/CodeGen/ARM/inlineasm4.ll
    URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/inlineasm4.ll?rev=137217&view=auto
    ==============================================================================
    --- llvm/trunk/test/CodeGen/ARM/inlineasm4.ll (added)
    +++ llvm/trunk/test/CodeGen/ARM/inlineasm4.ll Wed Aug 10 11:26:42 2011
    @@ -0,0 +1,17 @@
    +; RUN: llc < %s -march=arm | FileCheck %s
    +
    +define double @f(double %x) {
    +entry:
    +  %0 = tail call double asm "mov     ${0:R}, #4\0A", "=&r"()
    +  ret double %0
    +; CHECK: f:
    +; CHECK:	mov     r1, #4
    +}
    +
    +define double @g(double %x) {
    +entry:
    +  %0 = tail call double asm "mov     ${0:Q}, #4\0A", "=&r"()
    +  ret double %0
    +; CHECK: g:
    +; CHECK:	mov     r0, #4
    +}
    
    
    
    From jyasskin at google.com  Wed Aug 10 12:05:47 2011
    From: jyasskin at google.com (Jeffrey Yasskin)
    Date: Wed, 10 Aug 2011 10:05:47 -0700
    Subject: [llvm-commits] [llvm] r137145 - /llvm/trunk/docs/Atomics.html
    In-Reply-To: <20110809210711.371622A6C12E@llvm.org>
    References: <20110809210711.371622A6C12E@llvm.org>
    Message-ID: 
    
    On Tue, Aug 9, 2011 at 2:07 PM, Eli Friedman  wrote:
    > +
    > +

    > + ?Atomic orderings > +

    > + > + > +
    > + > +

    In order to achieve a balance between performance and necessary guarantees, > + ? there are six levels of atomicity. They are listed in order of strength; Do you want to mention that we've intentionally skipped memory_order_consume for now? > + ? each level includes all the guarantees of the previous level except for > + ? Acquire/Release.

    > + > +

    Unordered is the lowest level of atomicity. It essentially guarantees that > + ? races produce somewhat sane results instead of having undefined behavior. > + ? This is intended to match the Java memory model for shared variables. It > + ? cannot be used for synchronization, but is useful for Java and other > + ? "safe" languages which need to guarantee that the generated code never > + ? exhibits undefined behavior. ?Note that this guarantee is cheap on common > + ? platforms for loads of a native width, but can be expensive or unavailable > + ? for wider loads, like a 64-bit load on ARM. (A frontend for a "safe" > + ? language would normally split a 64-bit load on ARM into two 32-bit > + ? unordered loads.) In terms of the optimizer, this prohibits any > + ? transformation that transforms a single load into multiple loads, > + ? transforms a store into multiple stores, narrows a store, or stores a > + ? value which would not be stored otherwise. ?Some examples of unsafe > + ? optimizations are narrowing an assignment into a bitfield, rematerializing > + ? a load, and turning loads and stores into a memcpy call. Reordering > + ? unordered operations is safe, though, and optimizers should take > + ? advantage of that because unordered operations are common in > + ? languages that need them.

    > + > +

    Monotonic is the weakest level of atomicity that can be used in > + ? synchronization primitives, although it does not provide any general > + ? synchronization. It essentially guarantees that if you take all the > + ? operations affecting a specific address, a consistent ordering exists. > + ? This corresponds to the C++0x/C1x memory_order_relaxed; see > + ? those standards for the exact definition. ?If you are writing a frontend, do > + ? not use the low-level synchronization primitives unless you are compiling > + ? a language which requires it or are sure a given pattern is correct. In > + ? terms of the optimizer, this can be treated as a read+write on the relevant > + ? memory location (and alias analysis will take advantage of that). ?In > + ? addition, it is legal to reorder non-atomic and Unordered loads around > + ? Monotonic loads. CSE/DSE and a few other optimizations are allowed, but It's also legal to reorder monotonic operations around each other as long as you can prove they don't alias. (Think 'load a; load b; load a" -> Normally it'd be fine to collapse the two 'load a's with no aliasing check, but with monotonic atomics, you can only do that if a!=b.) > + ? Monotonic operations are unlikely to be used in ways which would make > + ? those optimizations useful.

    > + > +

    Acquire provides a barrier of the sort necessary to acquire a lock to access > + ? other memory with normal loads and stores. ?This corresponds to the > + ? C++0x/C1x memory_order_acquire. ?This is a low-level > + ? synchronization primitive. In general, optimizers should treat this like > + ? a nothrow call.

    > + > +

    Release is similar to Acquire, but with a barrier of the sort necessary to > + ? release a lock.This corresponds to the C++0x/C1x > + ? memory_order_release.

    Did you want to say, "In general, optimizers should treat this like a nothrow call." for Release too? Of course, optimizers might be able to do better by knowing it's a release, but doing that would probably take a lot more infrastructure work. > + > +

    AcquireRelease (acq_rel in IR) provides both an Acquire and a Release barrier. > + ? This corresponds to the C++0x/C1x memory_order_acq_rel. In general, > + ? optimizers should treat this like a nothrow call.

    > + > +

    SequentiallyConsistent (seq_cst in IR) provides Acquire and/or > + ? Release semantics, and in addition guarantees a total ordering exists with > + ? all other SequentiallyConsistent operations. This corresponds to the > + ? C++0x/C1x memory_order_seq_cst, and Java volatile. ?The intent > + ? of this ordering level is to provide a programming model which is relatively > + ? easy to understand. In general, optimizers should treat this like a > + ? nothrow call.

    > + > +
    > + > + > +

    > + ?Other atomic instructions > +

    > + > + > +
    > + > +

    cmpxchg and atomicrmw are essentially like an > + ? atomic load followed by an atomic store (where the store is conditional for > + ? cmpxchg), but no other memory operation operation can happen duplicate "operation" > + ? between the load and store.

    Do you want to mention that we've intentionally skipped "weak" cmpxchgs and cmpxchgs with different success and failure ordering constraints? > + > +

    > + ?Atomics and IR optimization > +

    > + > + > +
    > + > +

    Predicates for optimizer writers to query: > +

      > + ?
    • isSimple(): A load or store which is not volatile or atomic. ?This is > + ? ? ?what, for example, memcpyopt would check for operations it might > + ? ? ?transform. > + ?
    • isUnordered(): A load or store which is not volatile and at most > + ? ? ?Unordered. This would be checked, for example, by LICM before hoisting > + ? ? ?an operation. > + ?
    • mayReadFromMemory()/mayWriteToMemory(): Existing predicate, but note > + ? ? ?that they returns true for any operation which is volatile or at least s/returns/return/ > + ? ? ?Monotonic. From resistor at mac.com Wed Aug 10 12:21:20 2011 From: resistor at mac.com (Owen Anderson) Date: Wed, 10 Aug 2011 17:21:20 -0000 Subject: [llvm-commits] [llvm] r137223 - /llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Message-ID: <20110810172120.CC0552A6C12C@llvm.org> Author: resistor Date: Wed Aug 10 12:21:20 2011 New Revision: 137223 URL: http://llvm.org/viewvc/llvm-project?rev=137223&view=rev Log: Rewrite some ARM InstrInfo functions to be most accepting of arbitrary register subclasses. Hopefully this fixes some buildbots. Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=137223&r1=137222&r2=137223&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original) +++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Wed Aug 10 12:21:20 2011 @@ -711,82 +711,84 @@ MFI.getObjectSize(FI), Align); - // tGPR is used sometimes in ARM instructions that need to avoid using - // certain registers. Just treat it as GPR here. Likewise, rGPR. - if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass - || RC == ARM::rGPRRegisterClass) - RC = ARM::GPRRegisterClass; - - switch (RC->getID()) { - case ARM::GPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STRi12)) + switch (RC->getSize()) { + case 4: + if (ARM::GPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::STRi12)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); - break; - case ARM::SPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS)) + } else if (ARM::SPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRS)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); - break; - case ARM::DPRRegClassID: - case ARM::DPR_VFP2RegClassID: - case ARM::DPR_8RegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRD)) + } else + llvm_unreachable("Unknown reg class!"); + break; + case 8: + if (ARM::DPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTRD)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); - break; - case ARM::QPRRegClassID: - case ARM::QPR_VFP2RegClassID: - case ARM::QPR_8RegClassID: - if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64Pseudo)) + } else + llvm_unreachable("Unknown reg class!"); + break; + case 16: + if (ARM::QPRRegClass.hasSubClassEq(RC)) { + if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64Pseudo)) .addFrameIndex(FI).addImm(16) .addReg(SrcReg, getKillRegState(isKill)) .addMemOperand(MMO)); - } else { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQIA)) + } else { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQIA)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI) .addMemOperand(MMO)); - } - break; - case ARM::QQPRRegClassID: - case ARM::QQPR_VFP2RegClassID: - if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { - // FIXME: It's possible to only store part of the QQ register if the - // spilled def has a sub-register index. - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1d64QPseudo)) + } + } else + llvm_unreachable("Unknown reg class!"); + break; + case 32: + if (ARM::QQPRRegClass.hasSubClassEq(RC)) { + if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { + // FIXME: It's possible to only store part of the QQ register if the + // spilled def has a sub-register index. + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1d64QPseudo)) .addFrameIndex(FI).addImm(16) .addReg(SrcReg, getKillRegState(isKill)) .addMemOperand(MMO)); - } else { - MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) + } else { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) .addFrameIndex(FI)) - .addMemOperand(MMO); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); - AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); - } - break; - case ARM::QQQQPRRegClassID: { - MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) - .addFrameIndex(FI)) - .addMemOperand(MMO); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_4, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_5, 0, TRI); - MIB = AddDReg(MIB, SrcReg, ARM::dsub_6, 0, TRI); - AddDReg(MIB, SrcReg, ARM::dsub_7, 0, TRI); - break; - } - default: - llvm_unreachable("Unknown regclass!"); + .addMemOperand(MMO); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); + AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); + } + } else + llvm_unreachable("Unknown reg class!"); + break; + case 64: + if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) { + MachineInstrBuilder MIB = + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) + .addFrameIndex(FI)) + .addMemOperand(MMO); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_2, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_3, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_4, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_5, 0, TRI); + MIB = AddDReg(MIB, SrcReg, ARM::dsub_6, 0, TRI); + AddDReg(MIB, SrcReg, ARM::dsub_7, 0, TRI); + } else + llvm_unreachable("Unknown reg class!"); + break; + default: + llvm_unreachable("Unknown reg class!"); } } @@ -860,72 +862,75 @@ MFI.getObjectSize(FI), Align); - // tGPR is used sometimes in ARM instructions that need to avoid using - // certain registers. Just treat it as GPR here. - if (RC == ARM::tGPRRegisterClass || RC == ARM::tcGPRRegisterClass - || RC == ARM::rGPRRegisterClass) - RC = ARM::GPRRegisterClass; - - switch (RC->getID()) { - case ARM::GPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDRi12), DestReg) + switch (RC->getSize()) { + case 4: + if (ARM::GPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::LDRi12), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); - break; - case ARM::SPRRegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg) + + } else if (ARM::SPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRS), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } else + llvm_unreachable("Unknown reg class!"); break; - case ARM::DPRRegClassID: - case ARM::DPR_VFP2RegClassID: - case ARM::DPR_8RegClassID: - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRD), DestReg) + case 8: + if (ARM::DPRRegClass.hasSubClassEq(RC)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRD), DestReg) .addFrameIndex(FI).addImm(0).addMemOperand(MMO)); + } else + llvm_unreachable("Unknown reg class!"); break; - case ARM::QPRRegClassID: - case ARM::QPR_VFP2RegClassID: - case ARM::QPR_8RegClassID: - if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64Pseudo), DestReg) + case 16: + if (ARM::QPRRegClass.hasSubClassEq(RC)) { + if (Align >= 16 && getRegisterInfo().needsStackRealignment(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64Pseudo), DestReg) .addFrameIndex(FI).addImm(16) .addMemOperand(MMO)); - } else { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQIA), DestReg) - .addFrameIndex(FI) - .addMemOperand(MMO)); - } + } else { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQIA), DestReg) + .addFrameIndex(FI) + .addMemOperand(MMO)); + } + } else + llvm_unreachable("Unknown reg class!"); break; - case ARM::QQPRRegClassID: - case ARM::QQPR_VFP2RegClassID: - if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1d64QPseudo), DestReg) + case 32: + if (ARM::QQPRRegClass.hasSubClassEq(RC)) { + if (Align >= 16 && getRegisterInfo().canRealignStack(MF)) { + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1d64QPseudo), DestReg) .addFrameIndex(FI).addImm(16) .addMemOperand(MMO)); - } else { - MachineInstrBuilder MIB = + } else { + MachineInstrBuilder MIB = AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA)) .addFrameIndex(FI)) - .addMemOperand(MMO); - MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); - AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); - } + .addMemOperand(MMO); + MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); + AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); + } + } else + llvm_unreachable("Unknown reg class!"); break; - case ARM::QQQQPRRegClassID: { - MachineInstrBuilder MIB = + case 64: + if (ARM::QQQQPRRegClass.hasSubClassEq(RC)) { + MachineInstrBuilder MIB = AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA)) .addFrameIndex(FI)) - .addMemOperand(MMO); - MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_4, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_5, RegState::Define, TRI); - MIB = AddDReg(MIB, DestReg, ARM::dsub_6, RegState::Define, TRI); - AddDReg(MIB, DestReg, ARM::dsub_7, RegState::Define, TRI); + .addMemOperand(MMO); + MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_2, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_3, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_4, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_5, RegState::Define, TRI); + MIB = AddDReg(MIB, DestReg, ARM::dsub_6, RegState::Define, TRI); + AddDReg(MIB, DestReg, ARM::dsub_7, RegState::Define, TRI); + } else + llvm_unreachable("Unknown reg class!"); break; - } default: llvm_unreachable("Unknown regclass!"); } From resistor at mac.com Wed Aug 10 12:28:26 2011 From: resistor at mac.com (Owen Anderson) Date: Wed, 10 Aug 2011 10:28:26 -0700 Subject: [llvm-commits] [llvm] r137144 - in /llvm/trunk: lib/Target/ARM/ lib/Target/ARM/Disassembler/ test/MC/Disassembler/ARM/ utils/TableGen/ In-Reply-To: <4E4211DD.8080909@mxc.ca> References: <20110809205519.AA7252A6C12E@llvm.org> <4E4211DD.8080909@mxc.ca> Message-ID: <15D1ADBF-FD06-4B19-8D8F-8C6A1EC807DA@mac.com> On Aug 9, 2011, at 10:06 PM, Nick Lewycky wrote: >> -// PC relative add (ADR). >> -def tADDrPCi : T1I<(outs tGPR:$dst), (ins t_imm_s4:$rhs), IIC_iALUi, >> - "add\t$dst, pc, $rhs", []>, >> - T1Encoding<{1,0,1,0,0,?}> { >> - // A6.2& A8.6.10 >> - bits<3> dst; >> - bits<8> rhs; >> - let Inst{10-8} = dst; >> - let Inst{7-0} = rhs; >> -} >> - > > What replaced this? It was already duplicated by tADR. Jim's looking at the asm parser hacks to get us to parse both forms with a single instruction definition. --Owen -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/de66e721/attachment.html From resistor at mac.com Wed Aug 10 12:36:48 2011 From: resistor at mac.com (Owen Anderson) Date: Wed, 10 Aug 2011 17:36:48 -0000 Subject: [llvm-commits] [llvm] r137224 - /llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Message-ID: <20110810173649.05C292A6C12C@llvm.org> Author: resistor Date: Wed Aug 10 12:36:48 2011 New Revision: 137224 URL: http://llvm.org/viewvc/llvm-project?rev=137224&view=rev Log: Cleanups based on Nick Lewycky's feedback. Modified: llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp 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=137224&r1=137223&r2=137224&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Wed Aug 10 12:36:48 2011 @@ -274,7 +274,7 @@ static void AddThumb1SBit(MCInst &MI, bool InITBlock) { const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo; MCInst::iterator I = MI.begin(); - for (unsigned i = 0; i < MI.size(); ++i, ++I) { + for (unsigned i = 0, e = MI.size(); i < e; ++i, ++I) { if (OpInfo[i].isOptionalDef() && OpInfo[i].RegClass == ARM::CCRRegClassID) { MI.insert(I, MCOperand::CreateReg(InITBlock ? 0 : ARM::CPSR)); return; @@ -304,7 +304,7 @@ // If we're in an IT block, base the predicate on that. Otherwise, // assume a predicate of AL. unsigned CC; - if (ITBlock.size()) { + if (!ITBlock.empty()) { CC = ITBlock.back(); ITBlock.pop_back(); } else @@ -312,7 +312,7 @@ const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo; MCInst::iterator I = MI.begin(); - for (unsigned i = 0; i < MI.size(); ++i, ++I) { + for (unsigned i = 0, e = MI.size(); i < e; ++i, ++I) { if (OpInfo[i].isPredicate()) { I = MI.insert(I, MCOperand::CreateImm(CC)); ++I; @@ -338,7 +338,7 @@ // context as a post-pass. void ThumbDisassembler::UpdateThumbVFPPredicate(MCInst &MI) const { unsigned CC; - if (ITBlock.size()) { + if (!ITBlock.empty()) { CC = ITBlock.back(); ITBlock.pop_back(); } else @@ -346,7 +346,7 @@ const MCOperandInfo *OpInfo = ARMInsts[MI.getOpcode()].OpInfo; MCInst::iterator I = MI.begin(); - for (unsigned i = 0; i < MI.size(); ++i, ++I) { + for (unsigned i = 0, e = MI.size(); i < e; ++i, ++I) { if (OpInfo[i].isPredicate() ) { I->setImm(CC); ++I; @@ -373,7 +373,7 @@ bool result = decodeThumbInstruction16(MI, insn16, Address, this); if (result) { Size = 2; - bool InITBlock = ITBlock.size(); + bool InITBlock = !ITBlock.empty(); AddThumbPredicate(MI); AddThumb1SBit(MI, InITBlock); return true; @@ -743,6 +743,11 @@ static bool DecodeBitfieldMaskOperand(llvm::MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { + // This operand encodes a mask of contiguous zeros between a specified MSB + // and LSB. To decode it, we create the mask of all bits MSB-and-lower, + // the mask of all bits LSB-and-lower, and then xor them to create + // the mask of that's all ones on [msb, lsb]. Finally we not it to + // create the final mask. unsigned msb = fieldFromInstruction32(Val, 5, 5); unsigned lsb = fieldFromInstruction32(Val, 0, 5); uint32_t msb_mask = (1 << (msb+1)) - 1; @@ -1123,7 +1128,6 @@ case ARM::STMIB_UPD: Inst.setOpcode(ARM::RFEIB_UPD); break; - } return DecodeRFEInstruction(Inst, Insn, Address, Decoder); } @@ -1885,7 +1889,6 @@ break; } - return true; } @@ -2107,7 +2110,7 @@ } static bool DecodeT2Imm8S4(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { int imm = Val & 0xFF; if (!(Val & 0x100)) imm *= -1; Inst.addOperand(MCOperand::CreateImm(imm << 2)); @@ -2127,7 +2130,7 @@ } static bool DecodeT2Imm8(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { int imm = Val & 0xFF; if (!(Val & 0x100)) imm *= -1; Inst.addOperand(MCOperand::CreateImm(imm)); @@ -2137,7 +2140,7 @@ static bool DecodeT2AddrModeImm8(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { unsigned Rn = fieldFromInstruction32(Val, 9, 4); unsigned imm = fieldFromInstruction32(Val, 0, 9); @@ -2162,7 +2165,7 @@ static bool DecodeT2AddrModeImm12(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { unsigned Rn = fieldFromInstruction32(Val, 13, 4); unsigned imm = fieldFromInstruction32(Val, 0, 12); @@ -2174,7 +2177,7 @@ static bool DecodeThumbAddSPImm(llvm::MCInst &Inst, uint16_t Insn, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { unsigned imm = fieldFromInstruction16(Insn, 0, 7); Inst.addOperand(MCOperand::CreateReg(ARM::SP)); @@ -2185,7 +2188,7 @@ } static bool DecodeThumbAddSPReg(llvm::MCInst &Inst, uint16_t Insn, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { if (Inst.getOpcode() == ARM::tADDrSP) { unsigned Rdm = fieldFromInstruction16(Insn, 0, 3); Rdm |= fieldFromInstruction16(Insn, 7, 1) << 3; @@ -2205,7 +2208,7 @@ } static bool DecodeThumbCPS(llvm::MCInst &Inst, uint16_t Insn, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { unsigned imod = fieldFromInstruction16(Insn, 4, 1) | 0x2; unsigned flags = fieldFromInstruction16(Insn, 0, 3); @@ -2216,7 +2219,7 @@ } static bool DecodePostIdxReg(llvm::MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { unsigned Rm = fieldFromInstruction32(Insn, 0, 4); unsigned add = fieldFromInstruction32(Insn, 4, 1); @@ -2227,7 +2230,7 @@ } static bool DecodeThumbBLXOffset(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1))); return true; } @@ -2242,7 +2245,7 @@ } static bool DecodeThumbSRImm(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder) { + uint64_t Address, const void *Decoder) { if (Val == 0) Inst.addOperand(MCOperand::CreateImm(32)); else @@ -2327,7 +2330,7 @@ } static bool DecodeThumbBLTargetOperand(llvm::MCInst &Inst, unsigned Val, - uint64_t Address, const void *Decoder){ + uint64_t Address, const void *Decoder){ Inst.addOperand(MCOperand::CreateImm(SignExtend32<22>(Val << 1))); return true; } From resistor at mac.com Wed Aug 10 12:38:05 2011 From: resistor at mac.com (Owen Anderson) Date: Wed, 10 Aug 2011 17:38:05 -0000 Subject: [llvm-commits] [llvm] r137225 - /llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Message-ID: <20110810173805.47BC12A6C12C@llvm.org> Author: resistor Date: Wed Aug 10 12:38:05 2011 New Revision: 137225 URL: http://llvm.org/viewvc/llvm-project?rev=137225&view=rev Log: Tabs --> spaces. 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=137225&r1=137224&r2=137225&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Wed Aug 10 12:38:05 2011 @@ -344,7 +344,7 @@ // Encoded the same as branch targets. let EncoderMethod = "getARMBranchTargetOpValue"; let OperandType = "OPERAND_PCREL"; - let DecoderMethod = "DecodeBLTargetOperand"; + let DecoderMethod = "DecodeBLTargetOperand"; } @@ -482,7 +482,7 @@ }]> { let EncoderMethod = "getSOImmOpValue"; let ParserMatchClass = SOImmAsmOperand; - let DecoderMethod = "DecodeSOImmOperand"; + let DecoderMethod = "DecodeSOImmOperand"; } // Break so_imm's up into two pieces. This handles immediates with up to 16 From eli.friedman at gmail.com Wed Aug 10 12:39:11 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 10 Aug 2011 17:39:11 -0000 Subject: [llvm-commits] [llvm] r137226 - /llvm/trunk/lib/VMCore/Instructions.cpp Message-ID: <20110810173911.3FC192A6C12C@llvm.org> Author: efriedma Date: Wed Aug 10 12:39:11 2011 New Revision: 137226 URL: http://llvm.org/viewvc/llvm-project?rev=137226&view=rev Log: Whitespace. 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=137226&r1=137225&r2=137226&view=diff ============================================================================== --- llvm/trunk/lib/VMCore/Instructions.cpp (original) +++ llvm/trunk/lib/VMCore/Instructions.cpp Wed Aug 10 12:39:11 2011 @@ -3239,7 +3239,7 @@ } StoreInst *StoreInst::clone_impl() const { - return new StoreInst(getOperand(0), getOperand(1),isVolatile(), + return new StoreInst(getOperand(0), getOperand(1), isVolatile(), getAlignment(), getOrdering(), getSynchScope()); } From nlewycky at google.com Wed Aug 10 12:40:12 2011 From: nlewycky at google.com (Nick Lewycky) Date: Wed, 10 Aug 2011 10:40:12 -0700 Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner. In-Reply-To: <000d01cc575e$7c2c1d70$74845850$@org> References: <000d01cc575e$7c2c1d70$74845850$@org> Message-ID: On 10 August 2011 06:07, Pranav Bhandarkar wrote: > Hi, > > Subsequent to a discussion on the 'nsw' flag on llvm dev > (http://lists.cs.uiuc.edu/pipermail/llvmdev/2011-June/040856.html), I have > written a small function that allows the instruction combiner to preserve > the 'nsw' flag under certain conditions. Preserving this flag allows > optimization passes down the pipeline to be more aggressive. > > For instance, consider this synthetic test case. > int foo (int x) > { int j = x + 2; > int y = j + 3; > > if (j < y) return 1; > else return 0; > } > This can be reduced to always return 1. However LLVM does not do this > transformation. Consider the following piece of code > > 1 %add = add nsw i32 %tmp, 2 > 2 %add3 = add nsw i32 %add, 3 > 3 %cmp = icmp slt i32 %add, %add3 > 4 br i1 %cmp, label %if.then, label %if.else > > Here add = tmp + 2 and add3 is effectively tmp + 5 and the comparison "slt > %add, %add3" is always true. However, the instruction combiner combines > instructions 1 and 2 to produce > > 2 %add3 = add i32 %tmp, 5 > > Note the 'nsw' flag is dropped because the combiner does not reason about > the applicability of the 'nsw' flag in the new combined instruction. If now > the simplifycfg pass is run it does not simplify the comparison because one > of its operands has the 'nsw' flag while the other does not. The attached > patch checks the resulting constant in the new instruction for overflow. If > not, it keeps the flag. This allows the "simplifycfg" pass to simplify the > comparison and reduces the above function to return 1. > Hi Pranav, Thanks for working on this! Firstly, I have a high-level question: why can't (X +nsw (C1 +nsw C2) always become (X +nsw C3)? Your patch spends a lot of time verifying that overflow couldn't occur, but you're given an assumption a priori that it can't because the nsw flag is present. Sure it can overflow the unsigned wrap point (crossing between -1 to 0) but when merging two adds or two subs, does that ever matter? If I'm right and you don't need to test for overflow then you should be able to extend this to nuw and exact too. Then I have some comments on your patch. This code: + if (!isa(B) || !isa(C) || !isa(V)) { + return false; + } [...] + + ConstantInt *CV = dyn_cast(V); + ConstantInt *CB = dyn_cast(B); + ConstantInt *CC = dyn_cast(C); + + if (!CV || !CB || !CC) { + return false; + } is redundant. You don't need the first test because the second one will catch a superset of all the cases. + if (!I.isAssociative()) { + return false; + } + + // We will not reason about Mul for now. + if (Opcode == Instruction::Mul) { + return false; + } How about just "if (Opcode != Instruction::Add && Opcode != Instruction::Sub) { return false; }"? That makes it clear that the function only handles add and sub. Nick I have three attachments - The patch, a testcase that should be added to > test/Transforms/InstCombine and my regression report. This patch was > successfully regression tested on x86_64. > > Pranav > > _______________________________________________ > 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/20110810/0b9fd2c3/attachment.html From bruno.cardoso at gmail.com Wed Aug 10 12:45:17 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Wed, 10 Aug 2011 17:45:17 -0000 Subject: [llvm-commits] [llvm] r137227 - in /llvm/trunk: lib/Target/X86/X86InstrSSE.td test/CodeGen/X86/vec_shuffle-37.ll Message-ID: <20110810174517.C9B172A6C12C@llvm.org> Author: bruno Date: Wed Aug 10 12:45:17 2011 New Revision: 137227 URL: http://llvm.org/viewvc/llvm-project?rev=137227&view=rev Log: The following X86 pattern is incorrect: def : Pat<(X86Movss VR128:$src1, (bc_v4i32 (v2i64 (load addr:$src2)))), (MOVLPSrm VR128:$src1, addr:$src2)>; This matches a MOVSS dag with a MOVLPS instruction. However, MOVSS will replace only the low 32 bits of the register, while the MOVLPS instruction will replace the low 64 bits. A testcase is added and illustrates the bug and also modified the one that was already present. Patch by Tanya Lattner. Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td llvm/trunk/test/CodeGen/X86/vec_shuffle-37.ll Modified: llvm/trunk/lib/Target/X86/X86InstrSSE.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrSSE.td?rev=137227&r1=137226&r2=137227&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86InstrSSE.td (original) +++ llvm/trunk/lib/Target/X86/X86InstrSSE.td Wed Aug 10 12:45:17 2011 @@ -5933,13 +5933,6 @@ def : Pat<(v4f32 (X86Movss VR128:$src1, VR128:$src2)), (MOVSSrr (v4f32 VR128:$src1), (EXTRACT_SUBREG (v4f32 VR128:$src2), sub_ss))>; -// FIXME: Instead of a X86Movss there should be a X86Movlps here, the problem -// is during lowering, where it's not possible to recognize the load fold cause -// it has two uses through a bitcast. One use disappears at isel time and the -// fold opportunity reappears. -def : Pat<(X86Movss VR128:$src1, - (bc_v4i32 (v2i64 (load addr:$src2)))), - (MOVLPSrm VR128:$src1, addr:$src2)>; // Shuffle with MOVSD def : Pat<(v2f64 (X86Movsd VR128:$src1, (scalar_to_vector FR64:$src2))), Modified: llvm/trunk/test/CodeGen/X86/vec_shuffle-37.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/vec_shuffle-37.ll?rev=137227&r1=137226&r2=137227&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/vec_shuffle-37.ll (original) +++ llvm/trunk/test/CodeGen/X86/vec_shuffle-37.ll Wed Aug 10 12:45:17 2011 @@ -5,8 +5,8 @@ define <4 x i32> @t00(<4 x i32>* %a0) nounwind ssp { entry: ; CHECK: movaps ({{%rdi|%rcx}}), %xmm0 -; CHECK-NEXT: movaps %xmm0, %xmm1 -; CHECK-NEXT: movlps (%rax), %xmm1 +; CHECK: movaps %xmm0, %xmm1 +; CHECK-NEXT: movss %xmm2, %xmm1 ; CHECK-NEXT: shufps $36, %xmm1, %xmm0 %0 = load <4 x i32>* undef, align 16 %1 = load <4 x i32>* %a0, align 16 @@ -23,3 +23,23 @@ store <2 x double> %vecinit94, <2 x double>* undef ret void } + +define void @t02(<8 x i32>* %source, <2 x i32>* %dest) nounwind noinline { +entry: +; CHECK: movaps 32({{%rdi|%rcx}}), %xmm0 +; CHECK-NEXT: movaps 48({{%rdi|%rcx}}), %xmm1 +; CHECK-NEXT: movss %xmm1, %xmm0 +; CHECK-NEXT: movq %xmm0, ({{%rsi|%rdx}}) + %0 = bitcast <8 x i32>* %source to <4 x i32>* + %arrayidx = getelementptr inbounds <4 x i32>* %0, i64 3 + %tmp2 = load <4 x i32>* %arrayidx, align 16 + %tmp3 = extractelement <4 x i32> %tmp2, i32 0 + %tmp5 = insertelement <2 x i32> , i32 %tmp3, i32 0 + %arrayidx7 = getelementptr inbounds <8 x i32>* %source, i64 1 + %1 = bitcast <8 x i32>* %arrayidx7 to <4 x i32>* + %tmp8 = load <4 x i32>* %1, align 16 + %tmp9 = extractelement <4 x i32> %tmp8, i32 1 + %tmp11 = insertelement <2 x i32> %tmp5, i32 %tmp9, i32 1 + store <2 x i32> %tmp11, <2 x i32>* %dest, align 8 + ret void +} From bruno.cardoso at gmail.com Wed Aug 10 12:48:06 2011 From: bruno.cardoso at gmail.com (Bruno Cardoso Lopes) Date: Wed, 10 Aug 2011 10:48:06 -0700 Subject: [llvm-commits] [PATCH] miscompile due to incorrect MOVSS pattern In-Reply-To: <54051C17-30B3-4118-BBE8-C407A1571C2C@apple.com> References: <54051C17-30B3-4118-BBE8-C407A1571C2C@apple.com> Message-ID: Hi Tanya, On Tue, Aug 9, 2011 at 10:52 PM, Tanya Lattner wrote: > I believe the following X86 pattern is incorrect: > def : Pat<(X86Movss VR128:$src1, > ? ? ? ? ? ? ? ? ? ?(bc_v4i32 (v2i64 (load addr:$src2)))), > ? ? ? ? ?(MOVLPSrm VR128:$src1, addr:$src2)>; > > This matches a MOVSS dag with a MOVLPS instruction. However, MOVSS will replace only the low 32 bits of the register, while the MOVLPS instruction will replace the low 64 bits. > > I've added my test case that illustrates the bug and also modified the one that was already present. > > Bruno - You seem to have added this pattern, so let me know if this is supposed to use some other instruction. It's not clear what you're trying to achieve with this pattern, so ?my patch just removes it. This happened to trigger some testcases, but since it doesn't anymore and you have testcases where this is yielding wrong behavior it's better just to apply this, if this come back during shuffle rewriting I'll provide a fix. Thanks. Applied in r137227! -- Bruno Cardoso Lopes http://www.brunocardoso.cc From atrick at apple.com Wed Aug 10 13:07:06 2011 From: atrick at apple.com (Andrew Trick) Date: Wed, 10 Aug 2011 18:07:06 -0000 Subject: [llvm-commits] [llvm] r137229 - in /llvm/trunk/lib/Transforms/Utils: LoopUnroll.cpp SimplifyIndVar.cpp Message-ID: <20110810180706.258182A6C12C@llvm.org> Author: atrick Date: Wed Aug 10 13:07:05 2011 New Revision: 137229 URL: http://llvm.org/viewvc/llvm-project?rev=137229&view=rev Log: Comments. Thanks for the spell check Nick! Also, my apologies for spoiling the autocomplete on SimplifyInstructions.cpp. I couldn't think of a better filename. Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Modified: llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp?rev=137229&r1=137228&r2=137229&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/LoopUnroll.cpp Wed Aug 10 13:07:05 2011 @@ -133,7 +133,7 @@ /// removed from the LoopPassManager as well. LPM can also be NULL. /// /// This utility preserves LoopInfo. If DominatorTree or ScalarEvolution are -/// available it must also preseve those analyses. +/// available it must also preserve those analyses. bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, unsigned TripMultiple, LoopInfo *LI, LPPassManager *LPM) { BasicBlock *Preheader = L->getLoopPreheader(); @@ -380,7 +380,7 @@ } // FIXME: Reconstruct dom info, because it is not preserved properly. - // Incrementally updating domtree after loop unrolling woud be easy. + // Incrementally updating domtree after loop unrolling would be easy. if (DominatorTree *DT = LPM->getAnalysisIfAvailable()) DT->runOnFunction(*L->getHeader()->getParent()); Modified: llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp?rev=137229&r1=137228&r2=137229&view=diff ============================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp (original) +++ llvm/trunk/lib/Transforms/Utils/SimplifyIndVar.cpp Wed Aug 10 13:07:05 2011 @@ -86,7 +86,7 @@ /// aligned IV when used by a instruction that ignores the low bits. /// /// Return the operand of IVOperand for this induction variable if IVOperand can -/// be folded (in case more folding opportunity has been exposed). +/// be folded (in case more folding opportunities have been exposed). /// Otherwise return null. Value *SimplifyIndvar::foldIVUser(Instruction *UseInst, Instruction *IVOperand) { Value *IVSrc = 0; @@ -293,7 +293,7 @@ /// isSimpleIVUser - Return true if this instruction generates a simple SCEV /// expression in terms of that IV. /// -/// This is similar to IVUsers' isInsteresting() but processes each instruction +/// This is similar to IVUsers' isInteresting() but processes each instruction /// non-recursively when the operand is already known to be a simpleIVUser. /// static bool isSimpleIVUser(Instruction *I, const Loop *L, ScalarEvolution *SE) { From greened at obbligato.org Wed Aug 10 13:27:45 2011 From: greened at obbligato.org (David Greene) Date: Wed, 10 Aug 2011 18:27:45 -0000 Subject: [llvm-commits] [llvm] r137231 - /llvm/trunk/utils/TableGen/Record.h Message-ID: <20110810182745.3A0E22A6C12C@llvm.org> Author: greened Date: Wed Aug 10 13:27:45 2011 New Revision: 137231 URL: http://llvm.org/viewvc/llvm-project?rev=137231&view=rev Log: Add getAsUnquotedString Add a method to return an Init as an unquoted string. This primarily affects StringInit where we return the value without surrounding it with quotes. This is in preparation for removing the ugly #NAME# hack and replacing it with standard TabelGen operators. Modified: llvm/trunk/utils/TableGen/Record.h Modified: llvm/trunk/utils/TableGen/Record.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.h?rev=137231&r1=137230&r2=137231&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/Record.h (original) +++ llvm/trunk/utils/TableGen/Record.h Wed Aug 10 13:27:45 2011 @@ -506,6 +506,11 @@ /// getAsString - Convert this value to a string form. virtual std::string getAsString() const = 0; + /// getAsUnquotedString - Convert this value to a string form, + /// without adding quote markers. This primaruly affects + /// StringInits where we will not surround the string value with + /// quotes. + virtual std::string getAsUnquotedString() const { return getAsString(); } /// dump - Debugging method that may be called through a debugger, just /// invokes print on stderr. @@ -757,6 +762,7 @@ } virtual std::string getAsString() const { return "\"" + Value + "\""; } + virtual std::string getAsUnquotedString() const { return Value; } /// resolveBitReference - This method is used to implement /// VarBitInit::resolveReferences. If the bit is able to be resolved, we From greened at obbligato.org Wed Aug 10 13:27:47 2011 From: greened at obbligato.org (David Greene) Date: Wed, 10 Aug 2011 18:27:47 -0000 Subject: [llvm-commits] [llvm] r137232 - in /llvm/trunk/utils/TableGen: Record.cpp Record.h TGParser.cpp Message-ID: <20110810182747.24D1D2A6C12D@llvm.org> Author: greened Date: Wed Aug 10 13:27:46 2011 New Revision: 137232 URL: http://llvm.org/viewvc/llvm-project?rev=137232&view=rev Log: Make Record Name an Init Use an Init (ultimately a StringInit) to represent the Record name. This allows the name to be composed by standard TableGen operators. This will enable us to get rid of the ugly #NAME# hack processing and naturally replace it with operators. It also increases flexibility and power of the TableGen language by allowing record identifiers to be computed dynamically. Modified: llvm/trunk/utils/TableGen/Record.cpp llvm/trunk/utils/TableGen/Record.h llvm/trunk/utils/TableGen/TGParser.cpp Modified: llvm/trunk/utils/TableGen/Record.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.cpp?rev=137232&r1=137231&r2=137232&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/Record.cpp (original) +++ llvm/trunk/utils/TableGen/Record.cpp Wed Aug 10 13:27:46 2011 @@ -14,6 +14,7 @@ #include "Record.h" #include "Error.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -1638,22 +1639,61 @@ unsigned Record::LastID = 0; +void Record::checkName() { + // Ensure the record name has string type. + const TypedInit *TypedName = dynamic_cast(Name); + assert(TypedName && "Record name is not typed!"); + RecTy *Type = TypedName->getType(); + if (dynamic_cast(Type) == 0) { + llvm_unreachable("Record name is not a string!"); + } +} + DefInit *Record::getDefInit() { if (!TheInit) TheInit = new DefInit(this, new RecordRecTy(this)); return TheInit; } -void Record::setName(const std::string &Name) { - if (TrackedRecords.getDef(getName()) == this) { - TrackedRecords.removeDef(getName()); - this->Name = Name; +const std::string &Record::getName() const { + const StringInit *NameString = + dynamic_cast(Name); + assert(NameString && "Record name is not a string!"); + return NameString->getValue(); +} + +void Record::setName(Init *NewName) { + if (TrackedRecords.getDef(Name->getAsUnquotedString()) == this) { + TrackedRecords.removeDef(Name->getAsUnquotedString()); + Name = NewName; TrackedRecords.addDef(this); } else { - TrackedRecords.removeClass(getName()); - this->Name = Name; + TrackedRecords.removeClass(Name->getAsUnquotedString()); + Name = NewName; TrackedRecords.addClass(this); } + checkName(); + // Since the Init for the name was changed, see if we can resolve + // any of it using members of the Record. + Init *ComputedName = Name->resolveReferences(*this, 0); + if (ComputedName != Name) { + setName(ComputedName); + } + // DO NOT resolve record values to the name at this point because + // there might be default values for arguments of this def. Those + // arguments might not have been resolved yet so we don't want to + // prematurely assume values for those arguments were not passed to + // this def. + // + // Nonetheless, it may be that some of this Record's values + // reference the record name. Indeed, the reason for having the + // record name be an Init is to provide this flexibility. The extra + // resolve steps after completely instantiating defs takes care of + // this. See TGParser::ParseDef and TGParser::ParseDefm. +} + +void Record::setName(const std::string &Name) { + setName(StringInit::get(Name)); } /// resolveReferencesTo - If anything in this record refers to RV, replace the Modified: llvm/trunk/utils/TableGen/Record.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/Record.h?rev=137232&r1=137231&r2=137232&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/Record.h (original) +++ llvm/trunk/utils/TableGen/Record.h Wed Aug 10 13:27:46 2011 @@ -1373,7 +1373,7 @@ // Unique record ID. unsigned ID; - std::string Name; + Init *Name; SMLoc Loc; std::vector TemplateArgs; std::vector Values; @@ -1384,11 +1384,13 @@ DefInit *TheInit; + void checkName(); + public: // Constructs a record. explicit Record(const std::string &N, SMLoc loc, RecordKeeper &records) : - ID(LastID++), Name(N), Loc(loc), TrackedRecords(records), TheInit(0) {} + ID(LastID++), Name(StringInit::get(N)), Loc(loc), TrackedRecords(records), TheInit(0) {} ~Record() {} @@ -1397,7 +1399,8 @@ unsigned getID() const { return ID; } - const std::string &getName() const { return Name; } + const std::string &getName() const; + void setName(Init *Name); // Also updates RecordKeeper. void setName(const std::string &Name); // Also updates RecordKeeper. SMLoc getLoc() const { return Loc; } Modified: llvm/trunk/utils/TableGen/TGParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/TGParser.cpp?rev=137232&r1=137231&r2=137232&view=diff ============================================================================== --- llvm/trunk/utils/TableGen/TGParser.cpp (original) +++ llvm/trunk/utils/TableGen/TGParser.cpp Wed Aug 10 13:27:46 2011 @@ -1690,6 +1690,9 @@ return true; if (CurMultiClass == 0) // Def's in multiclasses aren't really defs. + // See Record::setName(). This resolve step will see any new name + // for the def that might have been created when resolving + // inheritance, values and arguments above. CurRec->resolveReferences(); // If ObjectBody has template arguments, it's an error. @@ -2102,6 +2105,9 @@ if (!CurMultiClass) for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) + // See Record::setName(). This resolve step will see any new + // name for the def that might have been created when resolving + // inheritance, values and arguments above. NewRecDefs[i]->resolveReferences(); if (Lex.getCode() != tgtok::semi) From baldrick at free.fr Wed Aug 10 13:44:44 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 10 Aug 2011 18:44:44 -0000 Subject: [llvm-commits] [dragonegg] r137233 - /dragonegg/trunk/src/Trees.cpp Message-ID: <20110810184444.29EEF2A6C12C@llvm.org> Author: baldrick Date: Wed Aug 10 13:44:44 2011 New Revision: 137233 URL: http://llvm.org/viewvc/llvm-project?rev=137233&view=rev Log: Be more careful about when we generate nsw/nuw flags. Paying attention to -fstrict_overflow like this means that they will only be generated at -O2 and higher. Modified: dragonegg/trunk/src/Trees.cpp Modified: dragonegg/trunk/src/Trees.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Trees.cpp?rev=137233&r1=137232&r2=137233&view=diff ============================================================================== --- dragonegg/trunk/src/Trees.cpp (original) +++ dragonegg/trunk/src/Trees.cpp Wed Aug 10 13:44:44 2011 @@ -133,13 +133,13 @@ /// 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); + return TYPE_UNSIGNED(type) && TYPE_OVERFLOW_UNDEFINED(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); + return !TYPE_UNSIGNED(type) && TYPE_OVERFLOW_UNDEFINED(type); } /// getIntegerValue - Return the specified INTEGER_CST as an APInt. From clattner at apple.com Wed Aug 10 13:49:22 2011 From: clattner at apple.com (Chris Lattner) Date: Wed, 10 Aug 2011 11:49:22 -0700 Subject: [llvm-commits] [llvm] r137232 - in /llvm/trunk/utils/TableGen: Record.cpp Record.h TGParser.cpp In-Reply-To: <20110810182747.24D1D2A6C12D@llvm.org> References: <20110810182747.24D1D2A6C12D@llvm.org> Message-ID: On Aug 10, 2011, at 11:27 AM, David Greene wrote: > Author: greened > Date: Wed Aug 10 13:27:46 2011 > New Revision: 137232 > > URL: http://llvm.org/viewvc/llvm-project?rev=137232&view=rev > Log: > Make Record Name an Init > > Use an Init (ultimately a StringInit) to represent the Record name. > This allows the name to be composed by standard TableGen operators. > This will enable us to get rid of the ugly #NAME# hack processing and > naturally replace it with operators. It also increases flexibility > and power of the TableGen language by allowing record identifiers to > be computed dynamically. Hi David, This seems very strange. Where are you going with this? -Chris From baldrick at free.fr Wed Aug 10 13:59:52 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 10 Aug 2011 18:59:52 -0000 Subject: [llvm-commits] [dragonegg] r137235 - /dragonegg/trunk/src/Backend.cpp Message-ID: <20110810185952.DDE992A6C12C@llvm.org> Author: baldrick Date: Wed Aug 10 13:59:52 2011 New Revision: 137235 URL: http://llvm.org/viewvc/llvm-project?rev=137235&view=rev Log: Try to fix the dragonegg buildbots. Curiously, it worked fine here... Modified: dragonegg/trunk/src/Backend.cpp Modified: dragonegg/trunk/src/Backend.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Backend.cpp?rev=137235&r1=137234&r2=137235&view=diff ============================================================================== --- dragonegg/trunk/src/Backend.cpp (original) +++ dragonegg/trunk/src/Backend.cpp Wed Aug 10 13:59:52 2011 @@ -1668,8 +1668,9 @@ #if (GCC_MINOR > 5) varpool_can_remove_if_no_refs(vnode) #else - (DECL_COMDAT(decl) || (DECL_ARTIFICIAL(decl) && - !vnode->externally_visible)) + 0 // FIXME: Code below broke buildbots. +// (DECL_COMDAT(decl) || (DECL_ARTIFICIAL(decl) && +// !vnode->externally_visible)) #endif ) continue; From resistor at mac.com Wed Aug 10 14:01:10 2011 From: resistor at mac.com (Owen Anderson) Date: Wed, 10 Aug 2011 19:01:10 -0000 Subject: [llvm-commits] [llvm] r137236 - in /llvm/trunk: lib/Target/ARM/ARMInstrFormats.td lib/Target/ARM/Disassembler/ARMDisassembler.cpp test/MC/Disassembler/ARM/thumb-tests.txt Message-ID: <20110810190110.E90662A6C12C@llvm.org> Author: resistor Date: Wed Aug 10 14:01:10 2011 New Revision: 137236 URL: http://llvm.org/viewvc/llvm-project?rev=137236&view=rev Log: Add initial support for decoding NEON instructions in Thumb2 mode. Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Modified: llvm/trunk/lib/Target/ARM/ARMInstrFormats.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrFormats.td?rev=137236&r1=137235&r2=137236&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrFormats.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrFormats.td Wed Aug 10 14:01:10 2011 @@ -1608,7 +1608,7 @@ let AsmString = !strconcat(opc, "${p}", ".", dt, "\t", asm); let Pattern = pattern; list Predicates = [HasNEON]; - let DecoderNamespace = "NEON"; + let DecoderNamespace = "NEONData"; } // Same as NeonI except it does not have a "data type" specifier. @@ -1621,7 +1621,7 @@ let AsmString = !strconcat(opc, "${p}", "\t", asm); let Pattern = pattern; list Predicates = [HasNEON]; - let DecoderNamespace = "NEON"; + let DecoderNamespace = "NEONData"; } class NLdSt op21_20, bits<4> op11_8, bits<4> op7_4, @@ -1636,6 +1636,7 @@ let Inst{7-4} = op7_4; let PostEncoderMethod = "NEONThumb2LoadStorePostEncoder"; + let DecoderNamespace = "NEONLoadStore"; bits<5> Vd; bits<6> Rn; @@ -1911,6 +1912,7 @@ list Predicates = [HasNEON]; let PostEncoderMethod = "NEONThumb2DupPostEncoder"; + let DecoderNamespace = "NEONDup"; bits<5> V; bits<4> R; 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=137236&r1=137235&r2=137236&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp (original) +++ llvm/trunk/lib/Target/ARM/Disassembler/ARMDisassembler.cpp Wed Aug 10 14:01:10 2011 @@ -249,12 +249,32 @@ } MI.clear(); - result = decodeNEONInstruction32(MI, insn, Address, this); + result = decodeNEONDataInstruction32(MI, insn, Address, this); if (result) { + Size = 4; // Add a fake predicate operand, because we share these instruction // definitions with Thumb2 where these instructions are predicable. if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false; + return true; + } + + MI.clear(); + result = decodeNEONLoadStoreInstruction32(MI, insn, Address, this); + if (result) { Size = 4; + // Add a fake predicate operand, because we share these instruction + // definitions with Thumb2 where these instructions are predicable. + if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false; + return true; + } + + MI.clear(); + result = decodeNEONDupInstruction32(MI, insn, Address, this); + if (result) { + Size = 4; + // Add a fake predicate operand, because we share these instruction + // definitions with Thumb2 where these instructions are predicable. + if (!DecodePredicateOperand(MI, 0xE, Address, this)) return false; return true; } @@ -434,6 +454,14 @@ } MI.clear(); + result = decodeCommonInstruction32(MI, insn32, Address, this); + if (result) { + Size = 4; + AddThumbPredicate(MI); + return true; + } + + MI.clear(); result = decodeVFPInstruction32(MI, insn32, Address, this); if (result) { Size = 4; @@ -442,7 +470,29 @@ } MI.clear(); - result = decodeCommonInstruction32(MI, insn32, Address, this); + if (fieldFromInstruction32(insn32, 24, 4) == 0xF) { + uint32_t NEONDataInsn = insn32; + NEONDataInsn &= 0xF0FFFFFF; // Clear bits 27-24 + NEONDataInsn |= (NEONDataInsn & 0x10000000) >> 4; // Move bit 28 to bit 24 + NEONDataInsn |= 0x12000000; // Set bits 28 and 25 + result = decodeNEONDataInstruction32(MI, NEONDataInsn, Address, this); + if (result) { + Size = 4; + AddThumbPredicate(MI); + return true; + } + } + + MI.clear(); + result = decodeNEONLoadStoreInstruction32(MI, insn32, Address, this); + if (result) { + Size = 4; + AddThumbPredicate(MI); + return true; + } + + MI.clear(); + result = decodeNEONDupInstruction32(MI, insn32, Address, this); if (result) { Size = 4; AddThumbPredicate(MI); 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=137236&r1=137235&r2=137236&view=diff ============================================================================== --- llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt (original) +++ llvm/trunk/test/MC/Disassembler/ARM/thumb-tests.txt Wed Aug 10 14:01:10 2011 @@ -265,3 +265,6 @@ # CHECK: bne #24 0x0c 0xd1 + +# CHECK: vadd.f32 q0, q1, q2 +0x02 0xef 0x44 0x0d From dpatel at apple.com Wed Aug 10 14:04:07 2011 From: dpatel at apple.com (Devang Patel) Date: Wed, 10 Aug 2011 19:04:07 -0000 Subject: [llvm-commits] [llvm] r137237 - in /llvm/trunk: include/llvm/CodeGen/LexicalScopes.h lib/CodeGen/CMakeLists.txt lib/CodeGen/LexicalScopes.cpp Message-ID: <20110810190407.296D52A6C12C@llvm.org> Author: dpatel Date: Wed Aug 10 14:04:06 2011 New Revision: 137237 URL: http://llvm.org/viewvc/llvm-project?rev=137237&view=rev Log: Provide utility to extract and use lexical scoping information from machine instructions. Added: llvm/trunk/include/llvm/CodeGen/LexicalScopes.h llvm/trunk/lib/CodeGen/LexicalScopes.cpp Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt Added: llvm/trunk/include/llvm/CodeGen/LexicalScopes.h URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/LexicalScopes.h?rev=137237&view=auto ============================================================================== --- llvm/trunk/include/llvm/CodeGen/LexicalScopes.h (added) +++ llvm/trunk/include/llvm/CodeGen/LexicalScopes.h Wed Aug 10 14:04:06 2011 @@ -0,0 +1,247 @@ +//===- LexicalScopes.cpp - Collecting lexical scope info -*- C++ -*--------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements LexicalScopes analysis. +// +// This pass collects lexical scope information and maps machine instructions +// to respective lexical scopes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LEXICALSCOPES_H +#define LLVM_CODEGEN_LEXICALSCOPES_H + +#include "llvm/Metadata.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DebugLoc.h" +#include "llvm/Support/ValueHandle.h" +#include +namespace llvm { + +class MachineInstr; +class MachineBasicBlock; +class MachineFunction; +class LexicalScope; + +//===----------------------------------------------------------------------===// +/// InsnRange - This is used to track range of instructions with identical +/// lexical scope. +/// +typedef std::pair InsnRange; + +//===----------------------------------------------------------------------===// +/// LexicalScopes - This class provides interface to collect and use lexical +/// scoping information from machine instruction. +/// +class LexicalScopes { +public: + LexicalScopes() : MF(NULL), CurrentFnLexicalScope(NULL) { } + ~LexicalScopes(); + + /// initialize - Scan machine function and constuct lexical scope nest. + virtual void initialize(const MachineFunction &); + + /// releaseMemory - release memory. + virtual void releaseMemory(); + + /// empty - Return true if there is any lexical scope information available. + bool empty() { return CurrentFnLexicalScope == NULL; } + + /// isCurrentFunctionScope - Return true if given lexical scope represents + /// current function. + bool isCurrentFunctionScope(const LexicalScope *LS) { + return LS == CurrentFnLexicalScope; + } + + /// getCurrentFunctionScope - Return lexical scope for the current function. + LexicalScope *getCurrentFunctionScope() const { return CurrentFnLexicalScope;} + + /// getMachineBasicBlocks - Populate given set using machine basic blocks which + /// have machine instructions that belong to lexical scope identified by + /// DebugLoc. + void getMachineBasicBlocks(DebugLoc DL, + SmallPtrSet &MBBs); + + /// dominates - Return true if DebugLoc's lexical scope dominates at least one + /// machine instruction's lexical scope in a given machine basic block. + bool dominates(DebugLoc DL, MachineBasicBlock *MBB); + + /// findLexicalScope - Find lexical scope, either regular or inlined, for the + /// given DebugLoc. Return NULL if not found. + LexicalScope *findLexicalScope(DebugLoc DL); + + /// getAbstractScopesList - Return a reference to list of abstract scopes. + SmallVector &getAbstractScopesList() { + return AbstractScopesList; + } + + /// findAbstractScope - Find an abstract scope or return NULL. + LexicalScope *findAbstractScope(const MDNode *N) { + return AbstractScopeMap.lookup(N); + } + + /// findInlinedScope - Find an inlined scope for the given DebugLoc or return + /// NULL. + LexicalScope *findInlinedScope(DebugLoc DL) { + return InlinedLexicalScopeMap.lookup(DL); + } + + /// findLexicalScope - Find regular lexical scope or return NULL. + LexicalScope *findLexicalScope(const MDNode *N) { + return LexicalScopeMap.lookup(N); + } + + /// dump - Print data structures to dbgs(). + void dump(); + +private: + + /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If + /// not available then create new lexical scope. + LexicalScope *getOrCreateLexicalScope(DebugLoc DL); + + /// getOrCreateRegularScope - Find or create a regular lexical scope. + LexicalScope *getOrCreateRegularScope(MDNode *Scope); + + /// getOrCreateInlinedScope - Find or create an inlined lexical scope. + LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt); + + /// getOrCreateAbstractScope - Find or create an abstract lexical scope. + LexicalScope *getOrCreateAbstractScope(const MDNode *N); + + /// extractLexicalScopes - Extract instruction ranges for each lexical scopes + /// for the given machine function. + void extractLexicalScopes(SmallVectorImpl &MIRanges, + DenseMap &M); + void constructScopeNest(LexicalScope *Scope); + void assignInstructionRanges(SmallVectorImpl &MIRanges, + DenseMap &M); + +private: + const MachineFunction *MF; + + /// LexicalScopeMap - Tracks the scopes in the current function. Owns the + /// contained LexicalScope*s. + DenseMap LexicalScopeMap; + + /// InlinedLexicalScopeMap - Tracks inlined function scopes in current function. + DenseMap InlinedLexicalScopeMap; + + /// AbstractScopeMap - These scopes are not included LexicalScopeMap. + /// AbstractScopes owns its LexicalScope*s. + DenseMap AbstractScopeMap; + + /// AbstractScopesList - Tracks abstract scopes constructed while processing + /// a function. + SmallVectorAbstractScopesList; + + /// CurrentFnLexicalScope - Top level scope for the current function. + /// + LexicalScope *CurrentFnLexicalScope; +}; + +//===----------------------------------------------------------------------===// +/// LexicalScope - This class is used to track scope information. +/// +class LexicalScope { + +public: + LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) + : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), + LastInsn(0), FirstInsn(0), DFSIn(0), DFSOut(0), IndentLevel(0) { + if (Parent) + Parent->addChild(this); + } + + virtual ~LexicalScope() {} + + // Accessors. + LexicalScope *getParent() const { return Parent; } + const MDNode *getDesc() const { return Desc; } + const MDNode *getInlinedAt() const { return InlinedAtLocation; } + const MDNode *getScopeNode() const { return Desc; } + bool isAbstractScope() const { return AbstractScope; } + SmallVector &getChildren() { return Children; } + SmallVector &getRanges() { return Ranges; } + + /// addChild - Add a child scope. + void addChild(LexicalScope *S) { Children.push_back(S); } + + /// openInsnRange - This scope covers instruction range starting from MI. + void openInsnRange(const MachineInstr *MI) { + if (!FirstInsn) + FirstInsn = MI; + + if (Parent) + Parent->openInsnRange(MI); + } + + /// extendInsnRange - Extend the current instruction range covered by + /// this scope. + void extendInsnRange(const MachineInstr *MI) { + assert (FirstInsn && "MI Range is not open!"); + LastInsn = MI; + if (Parent) + Parent->extendInsnRange(MI); + } + + /// closeInsnRange - Create a range based on FirstInsn and LastInsn collected + /// until now. This is used when a new scope is encountered while walking + /// machine instructions. + void closeInsnRange(LexicalScope *NewScope = NULL) { + assert (LastInsn && "Last insn missing!"); + Ranges.push_back(InsnRange(FirstInsn, LastInsn)); + FirstInsn = NULL; + LastInsn = NULL; + // If Parent dominates NewScope then do not close Parent's instruction + // range. + if (Parent && (!NewScope || !Parent->dominates(NewScope))) + Parent->closeInsnRange(NewScope); + } + + /// dominates - Return true if current scope dominsates given lexical scope. + bool dominates(const LexicalScope *S) { + if (S == this) + return true; + if (DFSIn < S->getDFSIn() && DFSOut > S->getDFSOut()) + return true; + return false; + } + + // Depth First Search support to walk and manipulate LexicalScope hierarchy. + unsigned getDFSOut() const { return DFSOut; } + void setDFSOut(unsigned O) { DFSOut = O; } + unsigned getDFSIn() const { return DFSIn; } + void setDFSIn(unsigned I) { DFSIn = I; } + + /// dump - print lexical scope. + void dump() const; + +private: + LexicalScope *Parent; // Parent to this scope. + AssertingVH Desc; // Debug info descriptor. + AssertingVH InlinedAtLocation; // Location at which this + // scope is inlined. + bool AbstractScope; // Abstract Scope + SmallVector Children; // Scopes defined in scope. + // Contents not owned. + SmallVector Ranges; + + const MachineInstr *LastInsn; // Last instruction of this scope. + const MachineInstr *FirstInsn; // First instruction of this scope. + unsigned DFSIn, DFSOut; // In & Out Depth use to determine + // scope nesting. + mutable unsigned IndentLevel; // Private state for dump() +}; + +} // end llvm namespace + +#endif Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=137237&r1=137236&r2=137237&view=diff ============================================================================== --- llvm/trunk/lib/CodeGen/CMakeLists.txt (original) +++ llvm/trunk/lib/CodeGen/CMakeLists.txt Wed Aug 10 14:04:06 2011 @@ -23,6 +23,7 @@ IntrinsicLowering.cpp LLVMTargetMachine.cpp LatencyPriorityQueue.cpp + LexicalScopes.cpp LiveDebugVariables.cpp LiveInterval.cpp LiveIntervalAnalysis.cpp Added: llvm/trunk/lib/CodeGen/LexicalScopes.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LexicalScopes.cpp?rev=137237&view=auto ============================================================================== --- llvm/trunk/lib/CodeGen/LexicalScopes.cpp (added) +++ llvm/trunk/lib/CodeGen/LexicalScopes.cpp Wed Aug 10 14:04:06 2011 @@ -0,0 +1,305 @@ +//===- LexicalScopes.cpp - Collecting lexical scope info ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements LexicalScopes analysis. +// +// This pass collects lexical scope information and maps machine instructions +// to respective lexical scopes. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "lexicalscopes" +#include "llvm/CodeGen/LexicalScopes.h" +#include "llvm/Function.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +LexicalScopes::~LexicalScopes() { + releaseMemory(); +} + +/// releaseMemory - release memory. +void LexicalScopes::releaseMemory() { + MF = NULL; + CurrentFnLexicalScope = NULL; + DeleteContainerSeconds(LexicalScopeMap); + DeleteContainerSeconds(AbstractScopeMap); + InlinedLexicalScopeMap.clear(); + AbstractScopesList.clear(); +} + +/// initialize - Scan machine function and constuct lexical scope nest. +void LexicalScopes::initialize(const MachineFunction &Fn) { + releaseMemory(); + MF = &Fn; + SmallVector MIRanges; + DenseMap MI2ScopeMap; + extractLexicalScopes(MIRanges, MI2ScopeMap); + if (CurrentFnLexicalScope) { + constructScopeNest(CurrentFnLexicalScope); + assignInstructionRanges(MIRanges, MI2ScopeMap); + } +} + +/// extractLexicalScopes - Extract instruction ranges for each lexical scopes +/// for the given machine function. +void LexicalScopes:: +extractLexicalScopes(SmallVectorImpl &MIRanges, + DenseMap &MI2ScopeMap) { + + // Scan each instruction and create scopes. First build working set of scopes. + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E; ++I) { + const MachineInstr *RangeBeginMI = NULL; + const MachineInstr *PrevMI = NULL; + DebugLoc PrevDL; + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MInsn = II; + + // Check if instruction has valid location information. + const DebugLoc MIDL = MInsn->getDebugLoc(); + if (MIDL.isUnknown()) { + PrevMI = MInsn; + continue; + } + + // If scope has not changed then skip this instruction. + if (MIDL == PrevDL) { + PrevMI = MInsn; + continue; + } + + // Ignore DBG_VALUE. It does not contribute to any instruction in output. + if (MInsn->isDebugValue()) + continue; + + if (RangeBeginMI) { + // If we have already seen a beginning of an instruction range and + // current instruction scope does not match scope of first instruction + // in this range then create a new instruction range. + InsnRange R(RangeBeginMI, PrevMI); + MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); + MIRanges.push_back(R); + } + + // This is a beginning of a new instruction range. + RangeBeginMI = MInsn; + + // Reset previous markers. + PrevMI = MInsn; + PrevDL = MIDL; + } + + // Create last instruction range. + if (RangeBeginMI && PrevMI && !PrevDL.isUnknown()) { + InsnRange R(RangeBeginMI, PrevMI); + MIRanges.push_back(R); + MI2ScopeMap[RangeBeginMI] = getOrCreateLexicalScope(PrevDL); + } + } +} + +/// findLexicalScope - Find lexical scope, either regular or inlined, for the +/// given DebugLoc. Return NULL if not found. +LexicalScope *LexicalScopes::findLexicalScope(DebugLoc DL) { + MDNode *Scope = NULL; + MDNode *IA = NULL; + DL.getScopeAndInlinedAt(Scope, IA, MF->getFunction()->getContext()); + if (!Scope) return NULL; + if (IA) + return InlinedLexicalScopeMap.lookup(DebugLoc::getFromDILocation(IA)); + return LexicalScopeMap.lookup(DL.getScope(Scope->getContext())); +} + +/// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If +/// not available then create new lexical scope. +LexicalScope *LexicalScopes::getOrCreateLexicalScope(DebugLoc DL) { + MDNode *Scope = NULL; + MDNode *InlinedAt = NULL; + DL.getScopeAndInlinedAt(Scope, InlinedAt, MF->getFunction()->getContext()); + if (InlinedAt) { + // Create an abstract scope for inlined function. + getOrCreateAbstractScope(Scope); + // Create an inlined scope for inlined function. + return getOrCreateInlinedScope(Scope, InlinedAt); + } + + return getOrCreateRegularScope(Scope); +} + +/// getOrCreateRegularScope - Find or create a regular lexical scope. +LexicalScope *LexicalScopes::getOrCreateRegularScope(MDNode *Scope) { + LexicalScope *WScope = LexicalScopeMap.lookup(Scope); + if (WScope) + return WScope; + + LexicalScope *Parent = NULL; + if (DIDescriptor(Scope).isLexicalBlock()) + Parent = getOrCreateLexicalScope(DebugLoc::getFromDILexicalBlock(Scope)); + WScope = new LexicalScope(Parent, DIDescriptor(Scope), NULL, false); + LexicalScopeMap.insert(std::make_pair(Scope, WScope)); + if (!Parent && DIDescriptor(Scope).isSubprogram() + && DISubprogram(Scope).describes(MF->getFunction())) + CurrentFnLexicalScope = WScope; + + return WScope; +} + +/// getOrCreateInlinedScope - Find or create an inlined lexical scope. +LexicalScope *LexicalScopes::getOrCreateInlinedScope(MDNode *Scope, + MDNode *InlinedAt) { + LexicalScope *InlinedScope = LexicalScopeMap.lookup(InlinedAt); + if (InlinedScope) + return InlinedScope; + + DebugLoc InlinedLoc = DebugLoc::getFromDILocation(InlinedAt); + InlinedScope = new LexicalScope(getOrCreateLexicalScope(InlinedLoc), + DIDescriptor(Scope), InlinedAt, false); + InlinedLexicalScopeMap[InlinedLoc] = InlinedScope; + LexicalScopeMap[InlinedAt] = InlinedScope; + return InlinedScope; +} + +/// getOrCreateAbstractScope - Find or create an abstract lexical scope. +LexicalScope *LexicalScopes::getOrCreateAbstractScope(const MDNode *N) { + assert(N && "Invalid Scope encoding!"); + + LexicalScope *AScope = AbstractScopeMap.lookup(N); + if (AScope) + return AScope; + + LexicalScope *Parent = NULL; + DIDescriptor Scope(N); + if (Scope.isLexicalBlock()) { + DILexicalBlock DB(N); + DIDescriptor ParentDesc = DB.getContext(); + Parent = getOrCreateAbstractScope(ParentDesc); + } + AScope = new LexicalScope(Parent, DIDescriptor(N), NULL, true); + AbstractScopeMap[N] = AScope; + if (DIDescriptor(N).isSubprogram()) + AbstractScopesList.push_back(AScope); + return AScope; +} + +/// constructScopeNest +void LexicalScopes::constructScopeNest(LexicalScope *Scope) { + assert (Scope && "Unable to calculate scop edominance graph!"); + SmallVector WorkStack; + WorkStack.push_back(Scope); + unsigned Counter = 0; + while (!WorkStack.empty()) { + LexicalScope *WS = WorkStack.back(); + const SmallVector &Children = WS->getChildren(); + bool visitedChildren = false; + for (SmallVector::const_iterator SI = Children.begin(), + SE = Children.end(); SI != SE; ++SI) { + LexicalScope *ChildScope = *SI; + if (!ChildScope->getDFSOut()) { + WorkStack.push_back(ChildScope); + visitedChildren = true; + ChildScope->setDFSIn(++Counter); + break; + } + } + if (!visitedChildren) { + WorkStack.pop_back(); + WS->setDFSOut(++Counter); + } + } +} + +/// assignInstructionRanges - Find ranges of instructions covered by each lexical +/// scope. +void LexicalScopes:: +assignInstructionRanges(SmallVectorImpl &MIRanges, + DenseMap &MI2ScopeMap) { + + LexicalScope *PrevLexicalScope = NULL; + for (SmallVectorImpl::const_iterator RI = MIRanges.begin(), + RE = MIRanges.end(); RI != RE; ++RI) { + const InsnRange &R = *RI; + LexicalScope *S = MI2ScopeMap.lookup(R.first); + assert (S && "Lost LexicalScope for a machine instruction!"); + if (PrevLexicalScope && !PrevLexicalScope->dominates(S)) + PrevLexicalScope->closeInsnRange(S); + S->openInsnRange(R.first); + S->extendInsnRange(R.second); + PrevLexicalScope = S; + } + + if (PrevLexicalScope) + PrevLexicalScope->closeInsnRange(); +} + +/// getMachineBasicBlocks - Populate given set using machine basic blocks which +/// have machine instructions that belong to lexical scope identified by +/// DebugLoc. +void LexicalScopes:: +getMachineBasicBlocks(DebugLoc DL, SmallPtrSet &MBBs) { + MBBs.clear(); + LexicalScope *Scope = getOrCreateLexicalScope(DL); + if (!Scope) + return; + + SmallVector &InsnRanges = Scope->getRanges(); + for (SmallVector::iterator I = InsnRanges.begin(), + E = InsnRanges.end(); I != E; ++I) { + InsnRange &R = *I; + MBBs.insert(R.first->getParent()); + } +} + +/// dominates - Return true if DebugLoc's lexical scope dominates at least one +/// machine instruction's lexical scope in a given machine basic block. +bool LexicalScopes::dominates(DebugLoc DL, MachineBasicBlock *MBB) { + LexicalScope *Scope = getOrCreateLexicalScope(DL); + if (!Scope) + return false; + bool Result = false; + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + DebugLoc IDL = I->getDebugLoc(); + if (IDL.isUnknown()) + continue; + if (LexicalScope *IScope = getOrCreateLexicalScope(IDL)) + if (Scope->dominates(IScope)) + return true; + } + return Result; +} + +/// dump - Print data structures. +void LexicalScope::dump() const { +#ifndef NDEBUG + raw_ostream &err = dbgs(); + err.indent(IndentLevel); + err << "DFSIn: " << DFSIn << " DFSOut: " << DFSOut << "\n"; + const MDNode *N = Desc; + N->dump(); + if (AbstractScope) + err << "Abstract Scope\n"; + + IndentLevel += 2; + if (!Children.empty()) + err << "Children ...\n"; + for (unsigned i = 0, e = Children.size(); i != e; ++i) + if (Children[i] != this) + Children[i]->dump(); + + IndentLevel -= 2; +#endif +} + From nadav.rotem at intel.com Wed Aug 10 14:30:14 2011 From: nadav.rotem at intel.com (Nadav Rotem) Date: Wed, 10 Aug 2011 19:30:14 -0000 Subject: [llvm-commits] [llvm] r137238 - in /llvm/trunk: lib/Target/X86/X86ISelLowering.cpp test/CodeGen/X86/opt-shuff-tstore.ll Message-ID: <20110810193014.6F6702A6C12C@llvm.org> Author: nadav Date: Wed Aug 10 14:30:14 2011 New Revision: 137238 URL: http://llvm.org/viewvc/llvm-project?rev=137238&view=rev Log: When performing a truncating store, it is sometimes possible to rearrange the data in-register prior to saving to memory. When we reorder the data in memory we prevent the need to save multiple scalars to memory, making a single regular store. Added: llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=137238&r1=137237&r2=137238&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed Aug 10 14:30:14 2011 @@ -12574,14 +12574,91 @@ /// PerformSTORECombine - Do target-specific dag combines on STORE nodes. static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG, const X86Subtarget *Subtarget) { + StoreSDNode *St = cast(N); + EVT VT = St->getValue().getValueType(); + EVT StVT = St->getMemoryVT(); + DebugLoc dl = St->getDebugLoc(); + + // Optimize trunc store (of multiple scalars) to shuffle and store. + // First, pack all of the elements in one place. Next, store to memory + // in fewer chunks. + if (St->isTruncatingStore() && VT.isVector()) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + unsigned NumElems = VT.getVectorNumElements(); + assert(StVT != VT && "Cannot truncate to the same type"); + unsigned FromSz = VT.getVectorElementType().getSizeInBits(); + unsigned ToSz = StVT.getVectorElementType().getSizeInBits(); + + // From, To sizes and ElemCount must be pow of two + if (!isPowerOf2_32(NumElems * FromSz * ToSz)) return SDValue(); + // We are going to use the original vector elt for storing. + // accumulated smaller vector elements must be a multiple of bigger size. + if (0 != (NumElems * ToSz) % FromSz) return SDValue(); + unsigned SizeRatio = FromSz / ToSz; + + assert(SizeRatio * NumElems * ToSz == VT.getSizeInBits()); + + // Create a type on which we perform the shuffle + EVT WideVecVT = EVT::getVectorVT(*DAG.getContext(), + StVT.getScalarType(), NumElems*SizeRatio); + + assert(WideVecVT.getSizeInBits() == VT.getSizeInBits()); + + SDValue WideVec = DAG.getNode(ISD::BITCAST, dl, WideVecVT, St->getValue()); + SmallVector ShuffleVec(NumElems * SizeRatio, -1); + for (unsigned i = 0; i < NumElems; i++ ) ShuffleVec[i] = i * SizeRatio; + + // Can't shuffle using an illegal type + if (!TLI.isTypeLegal(WideVecVT)) return SDValue(); + + SDValue Shuff = DAG.getVectorShuffle(WideVecVT, dl, WideVec, + DAG.getUNDEF(WideVec.getValueType()), + ShuffleVec.data()); + // At this point all of the data is stored at the bottom of the + // register. We now need to save it to mem. + + // Find the largest store unit + MVT StoreType = MVT::i8; + for (unsigned tp = MVT::FIRST_INTEGER_VALUETYPE; + tp < MVT::LAST_INTEGER_VALUETYPE; ++tp) { + MVT Tp = (MVT::SimpleValueType)tp; + if (TLI.isTypeLegal(Tp) && StoreType.getSizeInBits() < NumElems * ToSz) + StoreType = Tp; + } + + // Bitcast the original vector into a vector of store-size units + EVT StoreVecVT = EVT::getVectorVT(*DAG.getContext(), + StoreType, VT.getSizeInBits()/EVT(StoreType).getSizeInBits()); + assert(StoreVecVT.getSizeInBits() == VT.getSizeInBits()); + SDValue ShuffWide = DAG.getNode(ISD::BITCAST, dl, StoreVecVT, Shuff); + SmallVector Chains; + SDValue Increment = DAG.getConstant(StoreType.getSizeInBits()/8, + TLI.getPointerTy()); + SDValue Ptr = St->getBasePtr(); + + // Perform one or more big stores into memory. + for (unsigned i = 0; i < (ToSz*NumElems)/StoreType.getSizeInBits() ; i++) { + SDValue SubVec = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, + StoreType, ShuffWide, + DAG.getIntPtrConstant(i)); + SDValue Ch = DAG.getStore(St->getChain(), dl, SubVec, Ptr, + St->getPointerInfo(), St->isVolatile(), + St->isNonTemporal(), St->getAlignment()); + Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr, Increment); + Chains.push_back(Ch); + } + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, &Chains[0], + Chains.size()); + } + + // Turn load->store of MMX types into GPR load/stores. This avoids clobbering // the FP state in cases where an emms may be missing. // A preferable solution to the general problem is to figure out the right // places to insert EMMS. This qualifies as a quick hack. // Similarly, turn load->store of i64 into double load/stores in 32-bit mode. - StoreSDNode *St = cast(N); - EVT VT = St->getValue().getValueType(); if (VT.getSizeInBits() != 64) return SDValue(); Added: llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll?rev=137238&view=auto ============================================================================== --- llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll (added) +++ llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll Wed Aug 10 14:30:14 2011 @@ -0,0 +1,39 @@ +; RUN: llc -mcpu=corei7 < %s -o - -promote-elements -mattr=+sse2,+sse41 | FileCheck %s + +; CHECK: func_4_8 +; A single memory write +; CHECK: movd +; CHECK-NEXT: ret +define void @func_4_8(<4 x i8> %param, <4 x i8>* %p) { + %r = add <4 x i8> %param, + store <4 x i8> %r, <4 x i8>* %p + ret void +} + +; CHECK: func_4_16 +; CHECK: movq +; CHECK-NEXT: ret +define void @func_4_16(<4 x i16> %param, <4 x i16>* %p) { + %r = add <4 x i16> %param, + store <4 x i16> %r, <4 x i16>* %p + ret void +} + +; CHECK: func_8_8 +; CHECK: movq +; CHECK-NEXT: ret +define void @func_8_8(<8 x i8> %param, <8 x i8>* %p) { + %r = add <8 x i8> %param, + store <8 x i8> %r, <8 x i8>* %p + ret void +} + +; CHECK: func_2_32 +; CHECK: movq +; CHECK-NEXT: ret +define void @func_2_32(<2 x i32> %param, <2 x i32>* %p) { + %r = add <2 x i32> %param, + store <2 x i32> %r, <2 x i32>* %p + ret void +} + From pranavb at codeaurora.org Wed Aug 10 14:37:56 2011 From: pranavb at codeaurora.org (Pranav Bhandarkar) Date: Wed, 10 Aug 2011 14:37:56 -0500 Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner. In-Reply-To: References: <000d01cc575e$7c2c1d70$74845850$@org> Message-ID: <000001cc5795$02b32420$08196c60$@org> Hi Nick, >>Thanks for working on this! Firstly, I have a high-level question: why can't (X +nsw (C1 +nsw C2) always become (X +nsw C3)? Your patch spends a lot of time verifying that >>overflow couldn't occur, but you're given an assumption a priori that it can't because the nsw flag is present. The reason is that 127 (C1) + 2 (C2) = 129 (C3) is not strictly true always. For instance, when the type is i8, then C3 is -127. Then we cannot guarantee the nsw flag for the values of x that we could before this combination (e.g x=-10). Adding the 'nsw' flag in this would mean that the semantics are not preserved in the strictest sense of the term. Does this address your question? >>Sure it can overflow the unsigned wrap point (crossing between -1 to 0) but when merging two adds or two subs, does that ever matter? I do not think unsigned wrap matters. Thanks for your comments, I will incorporate your suggestions on the patch. Do let me know your thoughts on the reasoning above. Pranav Qualcomm Innovation Center, Inc is a member of Code Aurora Forum. From baldrick at free.fr Wed Aug 10 14:43:19 2011 From: baldrick at free.fr (Duncan Sands) Date: Wed, 10 Aug 2011 19:43:19 -0000 Subject: [llvm-commits] [dragonegg] r137239 - /dragonegg/trunk/src/Backend.cpp Message-ID: <20110810194319.1CE9D2A6C12C@llvm.org> Author: baldrick Date: Wed Aug 10 14:43:18 2011 New Revision: 137239 URL: http://llvm.org/viewvc/llvm-project?rev=137239&view=rev Log: It looks like the linkage type tweaking of commit 137215 caused the buildbot failures, not the tighter logic for choosing what we output. So revert the linkage part, and restore the output choice logic. Modified: dragonegg/trunk/src/Backend.cpp Modified: dragonegg/trunk/src/Backend.cpp URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Backend.cpp?rev=137239&r1=137238&r2=137239&view=diff ============================================================================== --- dragonegg/trunk/src/Backend.cpp (original) +++ dragonegg/trunk/src/Backend.cpp Wed Aug 10 14:43:18 2011 @@ -869,17 +869,17 @@ Linkage = GlobalValue::LinkerPrivateLinkage; } else if (!TREE_PUBLIC(decl)) { Linkage = GlobalValue::InternalLinkage; - } else if (DECL_COMDAT(decl)) { - Linkage = GlobalValue::getLinkOnceLinkage(flag_odr); - } else if (DECL_ONE_ONLY(decl)) { - Linkage = GlobalValue::getWeakLinkage(flag_odr); } 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(); } @@ -1668,9 +1668,8 @@ #if (GCC_MINOR > 5) varpool_can_remove_if_no_refs(vnode) #else - 0 // FIXME: Code below broke buildbots. -// (DECL_COMDAT(decl) || (DECL_ARTIFICIAL(decl) && -// !vnode->externally_visible)) + (DECL_COMDAT(decl) || (DECL_ARTIFICIAL(decl) && + !vnode->externally_visible)) #endif ) continue; From greened at obbligato.org Wed Aug 10 14:48:43 2011 From: greened at obbligato.org (David A. Greene) Date: Wed, 10 Aug 2011 14:48:43 -0500 Subject: [llvm-commits] [llvm] r137232 - in /llvm/trunk/utils/TableGen: Record.cpp Record.h TGParser.cpp In-Reply-To: (Chris Lattner's message of "Wed, 10 Aug 2011 11:49:22 -0700") References: <20110810182747.24D1D2A6C12D@llvm.org> Message-ID: Chris Lattner writes: >> Use an Init (ultimately a StringInit) to represent the Record name. >> This allows the name to be composed by standard TableGen operators. >> This will enable us to get rid of the ugly #NAME# hack processing and >> naturally replace it with operators. It also increases flexibility >> and power of the TableGen language by allowing record identifiers to >> be computed dynamically. > > Hi David, > > This seems very strange. Where are you going with this? There are two things this can help address. The first is changing the way #NAME# currently works. That was something I added back a year or so ago to support AVX. It's clunky and requires special processing in TGParser. This change and some related ones I have coming can be used to replace #NAME# with strconcat operators. Then the processing falls out natually from how operators work. The second is additional flexibility that result from allowing Record names to be computed via operators. It then becomes easy to add instruction mnemonic prefixes, suffixes, etc. programmatically, which allows the x86 SIMD .td file to be compressed dramatically. This is along the lines of the cleanup work we talked about last week. It's aimed to address what's currently in trunk, not based on any future ISAs, though it will help tremendously when those come along as well. Currently I don't have plans to replace #NAME# in any existing .td files. What I'd like to do is add the basic TableGen support to allow me to introduce some of the factoring/abstraction mechanism I've used in our tree to simplify (in my view) how x86 SIMD instructions are specified. But the examples won't make any sense without the corresponding TableGen support so I'm working to incorporate that first. With those code examples I think we can have a more productive conversation about what we have at Cray and have better understanding overall. In other words, it's easier to talk about code than some abstract idea. :) Make sense? -Dave From nadav.rotem at intel.com Wed Aug 10 14:49:19 2011 From: nadav.rotem at intel.com (Nadav Rotem) Date: Wed, 10 Aug 2011 19:49:19 -0000 Subject: [llvm-commits] [llvm] r137241 - /llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll Message-ID: <20110810194919.AE9602A6C12C@llvm.org> Author: nadav Date: Wed Aug 10 14:49:19 2011 New Revision: 137241 URL: http://llvm.org/viewvc/llvm-project?rev=137241&view=rev Log: Fix the test. Add cpu target. Modified: llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll Modified: llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll?rev=137241&r1=137240&r2=137241&view=diff ============================================================================== --- llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll (original) +++ llvm/trunk/test/CodeGen/X86/opt-shuff-tstore.ll Wed Aug 10 14:49:19 2011 @@ -1,4 +1,4 @@ -; RUN: llc -mcpu=corei7 < %s -o - -promote-elements -mattr=+sse2,+sse41 | FileCheck %s +; RUN: llc -mcpu=corei7 -march=x86-64 < %s -o - -promote-elements -mattr=+sse2,+sse41 | FileCheck %s ; CHECK: func_4_8 ; A single memory write From nlewycky at google.com Wed Aug 10 14:57:17 2011 From: nlewycky at google.com (Nick Lewycky) Date: Wed, 10 Aug 2011 12:57:17 -0700 Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner. In-Reply-To: <000001cc5795$02b32420$08196c60$@org> References: <000d01cc575e$7c2c1d70$74845850$@org> <000001cc5795$02b32420$08196c60$@org> Message-ID: On 10 August 2011 12:37, Pranav Bhandarkar wrote: > Hi Nick, > > >>Thanks for working on this! Firstly, I have a high-level question: why > can't (X +nsw (C1 +nsw C2) always become (X +nsw C3)? Your patch spends a > lot of time verifying that >>overflow couldn't occur, but you're given an > assumption a priori that it can't because the nsw flag is present. > > The reason is that 127 (C1) + 2 (C2) = 129 (C3) is not strictly true > always. > For instance, when the type is i8, then C3 is -127. 127 + 2 = 129 remains true with i8 values, because i8 -127 = i8 129. They have the same bit pattern. Can you pick values for X, C1 and C2 which still satisfy the +nsw relationship between each other that can't be converted into X +nsw C3 where C3 = C1+C2 (no nsw requirement)? 127 and 2 don't work as counter-examples because that triggers undefined behaviour (it violates the 'nsw' bit present on the add). Nick Then we cannot guarantee > the nsw flag for the values of x that we could before this combination (e.g > x=-10). Adding the 'nsw' flag in this would mean that the semantics are not > preserved in the strictest sense of the term. Does this address your > question? > >>Sure it can overflow the unsigned wrap point (crossing between -1 to 0) > but when merging two adds or two subs, does that ever matter? > > I do not think unsigned wrap matters. > > Thanks for your comments, I will incorporate your suggestions on the patch. > Do let me know your thoughts on the reasoning above. > > Pranav > > Qualcomm Innovation Center, Inc is a member of Code Aurora Forum. > > -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/40ac2528/attachment.html From eli.friedman at gmail.com Wed Aug 10 15:07:44 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 10 Aug 2011 13:07:44 -0700 Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner. In-Reply-To: References: <000d01cc575e$7c2c1d70$74845850$@org> <000001cc5795$02b32420$08196c60$@org> Message-ID: On Wed, Aug 10, 2011 at 12:57 PM, Nick Lewycky wrote: > On 10 August 2011 12:37, Pranav Bhandarkar wrote: >> >> Hi Nick, >> >> >>Thanks for working on this! Firstly, I have a high-level question: why >> can't (X +nsw (C1 +nsw C2) always become (X +nsw C3)? Your patch spends a >> lot of time verifying that >>overflow couldn't occur, but you're given an >> assumption a priori that it can't because the nsw flag is present. >> >> The reason is that 127 (C1) + 2 (C2) = 129 (C3) is not strictly true >> always. >> For instance, when the type is i8, then C3 is -127. > > 127 + 2 = 129 remains true with i8 values, because i8 -127 = i8 129. They > have the same bit pattern. > Can you pick values for X, C1 and C2 which still satisfy the +nsw > relationship between each other that can't be converted into X +nsw C3 where > C3 = C1+C2 (no nsw requirement)? 127 and 2 don't work as counter-examples > because that triggers undefined behaviour (it violates the 'nsw' bit present > on the add). X = -128, C1 = 127, C1 = 2? -Eli From nlewycky at google.com Wed Aug 10 15:11:47 2011 From: nlewycky at google.com (Nick Lewycky) Date: Wed, 10 Aug 2011 13:11:47 -0700 Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner. In-Reply-To: References: <000d01cc575e$7c2c1d70$74845850$@org> <000001cc5795$02b32420$08196c60$@org> Message-ID: On 10 August 2011 13:07, Eli Friedman wrote: > On Wed, Aug 10, 2011 at 12:57 PM, Nick Lewycky > wrote: > > On 10 August 2011 12:37, Pranav Bhandarkar > wrote: > >> > >> Hi Nick, > >> > >> >>Thanks for working on this! Firstly, I have a high-level question: why > >> can't (X +nsw (C1 +nsw C2) always become (X +nsw C3)? Your patch spends > a > >> lot of time verifying that >>overflow couldn't occur, but you're given > an > >> assumption a priori that it can't because the nsw flag is present. > >> > >> The reason is that 127 (C1) + 2 (C2) = 129 (C3) is not strictly true > >> always. > >> For instance, when the type is i8, then C3 is -127. > > > > 127 + 2 = 129 remains true with i8 values, because i8 -127 = i8 129. They > > have the same bit pattern. > > Can you pick values for X, C1 and C2 which still satisfy the +nsw > > relationship between each other that can't be converted into X +nsw C3 > where > > C3 = C1+C2 (no nsw requirement)? 127 and 2 don't work as counter-examples > > because that triggers undefined behaviour (it violates the 'nsw' bit > present > > on the add). > > X = -128, C1 = 127, C1 = 2? > I assume C2 = 2 and all i8 values. That doesn't work because the expression was "(X +nsw (C1 +nsw C2)" and 127 +nsw 2 invokes undefined behaviour, crossing from 127 to -128/128 to reach -127/129. In fact nsw-adding anything positive to 127 is invalid, so you'd have to be sure to pick a negative C2 given a C1 of 127. Nick -------------- next part -------------- An HTML attachment was scrubbed... URL: http://lists.cs.uiuc.edu/pipermail/llvm-commits/attachments/20110810/6b6f1043/attachment.html From pranavb at codeaurora.org Wed Aug 10 15:15:05 2011 From: pranavb at codeaurora.org (Pranav Bhandarkar) Date: Wed, 10 Aug 2011 15:15:05 -0500 Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner. In-Reply-To: References: <000d01cc575e$7c2c1d70$74845850$@org> <000001cc5795$02b32420$08196c60$@org> Message-ID: <000401cc579a$31b07610$95116230$@org> Hi Nick / Eli >> X = -128, C1 = 127, C1 = 2? Thanks Eli. Nick, I had something like this in mind too. In fact, this is what I meant when I said "e.g. x = -10" in my last email. Pranav Qualcomm Innovation Center, Inc is a member of Code Aurora Forum. From eli.friedman at gmail.com Wed Aug 10 15:17:14 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 10 Aug 2011 13:17:14 -0700 Subject: [llvm-commits] [llvm] r137145 - /llvm/trunk/docs/Atomics.html In-Reply-To: References: <20110809210711.371622A6C12E@llvm.org> Message-ID: On Wed, Aug 10, 2011 at 10:05 AM, Jeffrey Yasskin wrote: > On Tue, Aug 9, 2011 at 2:07 PM, Eli Friedman wrote: >> + >> +

      >> + ?Atomic orderings >> +

      >> + >> + >> +
      >> + >> +

      In order to achieve a balance between performance and necessary guarantees, >> + ? there are six levels of atomicity. They are listed in order of strength; > > Do you want to mention that we've intentionally skipped > memory_order_consume for now? I'm adding a note to the discussion of Acquire. >> + ? each level includes all the guarantees of the previous level except for >> + ? Acquire/Release.

      >> + >> +

      Unordered is the lowest level of atomicity. It essentially guarantees that >> + ? races produce somewhat sane results instead of having undefined behavior. >> + ? This is intended to match the Java memory model for shared variables. It >> + ? cannot be used for synchronization, but is useful for Java and other >> + ? "safe" languages which need to guarantee that the generated code never >> + ? exhibits undefined behavior. ?Note that this guarantee is cheap on common >> + ? platforms for loads of a native width, but can be expensive or unavailable >> + ? for wider loads, like a 64-bit load on ARM. (A frontend for a "safe" >> + ? language would normally split a 64-bit load on ARM into two 32-bit >> + ? unordered loads.) In terms of the optimizer, this prohibits any >> + ? transformation that transforms a single load into multiple loads, >> + ? transforms a store into multiple stores, narrows a store, or stores a >> + ? value which would not be stored otherwise. ?Some examples of unsafe >> + ? optimizations are narrowing an assignment into a bitfield, rematerializing >> + ? a load, and turning loads and stores into a memcpy call. Reordering >> + ? unordered operations is safe, though, and optimizers should take >> + ? advantage of that because unordered operations are common in >> + ? languages that need them.

      >> + >> +

      Monotonic is the weakest level of atomicity that can be used in >> + ? synchronization primitives, although it does not provide any general >> + ? synchronization. It essentially guarantees that if you take all the >> + ? operations affecting a specific address, a consistent ordering exists. >> + ? This corresponds to the C++0x/C1x memory_order_relaxed; see >> + ? those standards for the exact definition. ?If you are writing a frontend, do >> + ? not use the low-level synchronization primitives unless you are compiling >> + ? a language which requires it or are sure a given pattern is correct. In >> + ? terms of the optimizer, this can be treated as a read+write on the relevant >> + ? memory location (and alias analysis will take advantage of that). ?In >> + ? addition, it is legal to reorder non-atomic and Unordered loads around >> + ? Monotonic loads. CSE/DSE and a few other optimizations are allowed, but > > It's also legal to reorder monotonic operations around each other as > long as you can prove they don't alias. (Think 'load a; load b; load > a" -> Normally it'd be fine to collapse the two ?'load a's with no > aliasing check, but with monotonic atomics, you can only do that if > a!=b.) I though that was implied by "can be treated as a read+write on the relevant memory location". >> + ? Monotonic operations are unlikely to be used in ways which would make >> + ? those optimizations useful.

      >> + >> +

      Acquire provides a barrier of the sort necessary to acquire a lock to access >> + ? other memory with normal loads and stores. ?This corresponds to the >> + ? C++0x/C1x memory_order_acquire. ?This is a low-level >> + ? synchronization primitive. In general, optimizers should treat this like >> + ? a nothrow call.

      >> + >> +

      Release is similar to Acquire, but with a barrier of the sort necessary to >> + ? release a lock.This corresponds to the C++0x/C1x >> + ? memory_order_release.

      > > Did you want to say, "In general, optimizers should treat this like a > nothrow call." for Release too? Of course, optimizers might be able to > do better by knowing it's a release, but doing that would probably > take a lot more infrastructure work. Done. >> + >> +

      AcquireRelease (acq_rel in IR) provides both an Acquire and a Release barrier. >> + ? This corresponds to the C++0x/C1x memory_order_acq_rel. In general, >> + ? optimizers should treat this like a nothrow call.

      >> + >> +

      SequentiallyConsistent (seq_cst in IR) provides Acquire and/or >> + ? Release semantics, and in addition guarantees a total ordering exists with >> + ? all other SequentiallyConsistent operations. This corresponds to the >> + ? C++0x/C1x memory_order_seq_cst, and Java volatile. ?The intent >> + ? of this ordering level is to provide a programming model which is relatively >> + ? easy to understand. In general, optimizers should treat this like a >> + ? nothrow call.

      >> + >> +
      >> + >> + >> +

      >> + ?Other atomic instructions >> +

      >> + >> + >> +
      >> + >> +

      cmpxchg and atomicrmw are essentially like an >> + ? atomic load followed by an atomic store (where the store is conditional for >> + ? cmpxchg), but no other memory operation operation can happen > > duplicate "operation" > >> + ? between the load and store.

      > > Do you want to mention that we've intentionally skipped "weak" > cmpxchgs and cmpxchgs with different success and failure ordering > constraints? Yes; added a note. >> + >> +

      >> + ?Atomics and IR optimization >> +

      >> + >> + >> +
      >> + >> +

      Predicates for optimizer writers to query: >> +

        >> + ?
      • isSimple(): A load or store which is not volatile or atomic. ?This is >> + ? ? ?what, for example, memcpyopt would check for operations it might >> + ? ? ?transform. >> + ?
      • isUnordered(): A load or store which is not volatile and at most >> + ? ? ?Unordered. This would be checked, for example, by LICM before hoisting >> + ? ? ?an operation. >> + ?
      • mayReadFromMemory()/mayWriteToMemory(): Existing predicate, but note >> + ? ? ?that they returns true for any operation which is volatile or at least > > s/returns/return/ Done. -Eli From eli.friedman at gmail.com Wed Aug 10 15:17:43 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 10 Aug 2011 20:17:43 -0000 Subject: [llvm-commits] [llvm] r137243 - /llvm/trunk/docs/Atomics.html Message-ID: <20110810201743.C1E8B2A6C12C@llvm.org> Author: efriedma Date: Wed Aug 10 15:17:43 2011 New Revision: 137243 URL: http://llvm.org/viewvc/llvm-project?rev=137243&view=rev Log: Changes per Jeffrey's comments. Modified: llvm/trunk/docs/Atomics.html Modified: llvm/trunk/docs/Atomics.html URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/Atomics.html?rev=137243&r1=137242&r2=137243&view=diff ============================================================================== --- llvm/trunk/docs/Atomics.html (original) +++ llvm/trunk/docs/Atomics.html Wed Aug 10 15:17:43 2011 @@ -138,14 +138,16 @@ those optimizations useful.

        Acquire provides a barrier of the sort necessary to acquire a lock to access - other memory with normal loads and stores. This corresponds to the - C++0x/C1x memory_order_acquire. This is a low-level + other memory with normal loads and stores. This corresponds to the + C++0x/C1x memory_order_acquire. It should also be used for + C++0x/C1x memory_order_consume. This is a low-level synchronization primitive. In general, optimizers should treat this like a nothrow call.

        Release is similar to Acquire, but with a barrier of the sort necessary to - release a lock.This corresponds to the C++0x/C1x - memory_order_release.

        + release a lock. This corresponds to the C++0x/C1x + memory_order_release. In general, optimizers should treat this + like a nothrow call.

        AcquireRelease (acq_rel in IR) provides both an Acquire and a Release barrier. This corresponds to the C++0x/C1x memory_order_acq_rel. In general, @@ -171,8 +173,9 @@

        cmpxchg and atomicrmw are essentially like an atomic load followed by an atomic store (where the store is conditional for - cmpxchg), but no other memory operation operation can happen - between the load and store.

        + cmpxchg), but no other memory operation can happen between + the load and store. Note that our cmpxchg does not have quite as many + options for making cmpxchg weaker as the C++0x version.

        A fence provides Acquire and/or Release ordering which is not part of another operation; it is normally used along with Monotonic memory @@ -203,7 +206,7 @@ Unordered. This would be checked, for example, by LICM before hoisting an operation.

      • mayReadFromMemory()/mayWriteToMemory(): Existing predicate, but note - that they returns true for any operation which is volatile or at least + that they return true for any operation which is volatile or at least Monotonic.
      • Alias analysis: Note that AA will return ModRef for anything Acquire or Release, and for the address accessed by any Monotonic operation. From eli.friedman at gmail.com Wed Aug 10 15:19:52 2011 From: eli.friedman at gmail.com (Eli Friedman) Date: Wed, 10 Aug 2011 13:19:52 -0700 Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner. In-Reply-To: References: <000d01cc575e$7c2c1d70$74845850$@org> <000001cc5795$02b32420$08196c60$@org> Message-ID: On Wed, Aug 10, 2011 at 1:11 PM, Nick Lewycky wrote: > On 10 August 2011 13:07, Eli Friedman wrote: >> >> On Wed, Aug 10, 2011 at 12:57 PM, Nick Lewycky >> wrote: >> > On 10 August 2011 12:37, Pranav Bhandarkar >> > wrote: >> >> >> >> Hi Nick, >> >> >> >> >>Thanks for working on this! Firstly, I have a high-level question: >> >> >> why >> >> can't (X +nsw (C1 +nsw C2) always become (X +nsw C3)? Your patch spends >> >> a >> >> lot of time verifying that >>overflow couldn't occur, but you're given >> >> an >> >> assumption a priori that it can't because the nsw flag is present. >> >> >> >> The reason is that 127 (C1) + 2 (C2) = 129 (C3) is not strictly true >> >> always. >> >> For instance, when the type is i8, then C3 is -127. >> > >> > 127 + 2 = 129 remains true with i8 values, because i8 -127 = i8 129. >> > They >> > have the same bit pattern. >> > Can you pick values for X, C1 and C2 which still satisfy the +nsw >> > relationship between each other that can't be converted into X +nsw C3 >> > where >> > C3 = C1+C2 (no nsw requirement)? 127 and 2 don't work as >> > counter-examples >> > because that triggers undefined behaviour (it violates the 'nsw' bit >> > present >> > on the add). >> >> X = -128, C1 = 127, C1 = 2? > > I assume C2 = 2 and all i8 values. That doesn't work because the expression > was "(X +nsw (C1 +nsw C2)" and 127 +nsw 2 invokes undefined behaviour, > crossing from 127 to -128/128 to reach -127/129. In fact nsw-adding anything > positive to 127 is invalid, so you'd have to be sure to pick a negative C2 > given a C1 of 127. The original expression is ((X +nsw C1) +nsw C2). -Eli From grosbach at apple.com Wed Aug 10 15:29:20 2011 From: grosbach at apple.com (Jim Grosbach) Date: Wed, 10 Aug 2011 20:29:20 -0000 Subject: [llvm-commits] [llvm] r137244 - in /llvm/trunk: lib/Target/ARM/ARMInstrInfo.td lib/Target/ARM/AsmParser/ARMAsmParser.cpp test/MC/ARM/arm-memory-instructions.s test/MC/ARM/diagnostics.s Message-ID: <20110810202920.30A742A6C12C@llvm.org> Author: grosbach Date: Wed Aug 10 15:29:19 2011 New Revision: 137244 URL: http://llvm.org/viewvc/llvm-project?rev=137244&view=rev Log: ARM LDRD(immediate) assembly parsing and encoding support. Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp llvm/trunk/test/MC/ARM/arm-memory-instructions.s llvm/trunk/test/MC/ARM/diagnostics.s Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=137244&r1=137243&r2=137244&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original) +++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Wed Aug 10 15:29:19 2011 @@ -710,20 +710,26 @@ // addrmode3 := reg +/- reg // addrmode3 := reg +/- imm8 // -//def AddrMode3AsmOperand : AsmOperandClass { let Name = "AddrMode3"; } +// FIXME: split into imm vs. reg versions. +def AddrMode3AsmOperand : AsmOperandClass { let Name = "AddrMode3"; } def addrmode3 : Operand, ComplexPattern { let EncoderMethod = "getAddrMode3OpValue"; let PrintMethod = "printAddrMode3Operand"; + let ParserMatchClass = AddrMode3AsmOperand; let MIOperandInfo = (ops GPR:$base, GPR:$offsreg, i32imm:$offsimm); } +// FIXME: split into imm vs. reg versions. +// FIXME: parser method to handle +/- register. +def AM3OffsetAsmOperand : AsmOperandClass { let Name = "AM3Offset"; } def am3offset : Operand, ComplexPattern { let EncoderMethod = "getAddrMode3OffsetOpValue"; let DecoderMethod = "DecodeAddrMode3Offset"; let PrintMethod = "printAddrMode3OffsetOperand"; + let ParserMatchClass = AM3OffsetAsmOperand; let MIOperandInfo = (ops GPR, i32imm); } @@ -2030,20 +2036,22 @@ let Inst{11-8} = addr{7-4}; // imm7_4/zero let Inst{3-0} = addr{3-0}; // imm3_0/Rm let DecoderMethod = "DecodeAddrMode3Instruction"; + let AsmMatchConverter = "cvtLdrdPre"; } def LDRD_POST: AI3ldstidx<0b1101, 0, 1, 0, (outs GPR:$Rt, GPR:$Rt2, GPR:$Rn_wb), - (ins GPR:$Rn, am3offset:$offset), IndexModePost, - LdMiscFrm, IIC_iLoad_d_ru, - "ldrd", "\t$Rt, $Rt2, [$Rn], $offset", - "$Rn = $Rn_wb", []> { + (ins addr_offset_none:$addr, am3offset:$offset), + IndexModePost, LdMiscFrm, IIC_iLoad_d_ru, + "ldrd", "\t$Rt, $Rt2, $addr, $offset", + "$addr.base = $Rn_wb", []> { bits<10> offset; - bits<4> Rn; + bits<4> addr; let Inst{23} = offset{8}; // U bit let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{11-8} = offset{7-4}; // imm7_4/zero let Inst{3-0} = offset{3-0}; // imm3_0/Rm let DecoderMethod = "DecodeAddrMode3Instruction"; +// let AsmMatchConverter = "cvtLdrdPost"; } } // hasExtraDefRegAllocReq = 1 } // mayLoad = 1, neverHasSideEffects = 1 Modified: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp?rev=137244&r1=137243&r2=137244&view=diff ============================================================================== --- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp (original) +++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp Wed Aug 10 15:29:19 2011 @@ -128,6 +128,8 @@ const SmallVectorImpl &); bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode, const SmallVectorImpl &); + bool cvtLdrdPre(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &); bool validateInstruction(MCInst &Inst, const SmallVectorImpl &Ops); @@ -534,6 +536,29 @@ int64_t Val = CE->getValue(); return Val > -4096 && Val < 4096; } + bool isAddrMode3() const { + if (Kind != Memory) + return false; + // No shifts are legal for AM3. + if (Mem.ShiftType != ARM_AM::no_shift) return false; + // Check for register offset. + if (Mem.OffsetRegNum) return true; + // Immediate offset in range [-255, 255]. + if (!Mem.OffsetImm) return true; + int64_t Val = Mem.OffsetImm->getValue(); + return Val > -256 && Val < 256; + } + bool isAM3Offset() const { + if (Kind != Immediate && Kind != PostIndexRegister) + return false; + if (Kind == PostIndexRegister) + return PostIdxReg.ShiftTy == ARM_AM::no_shift; + // Immediate offset in range [-255, 255]. + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Val = CE->getValue(); + return Val > -256 && Val < 256; + } bool isAddrMode5() const { if (Kind != Memory) return false; @@ -814,6 +839,46 @@ Inst.addOperand(MCOperand::CreateImm(Val)); } + void addAddrMode3Operands(MCInst &Inst, unsigned N) const { + assert(N == 3 && "Invalid number of operands!"); + int32_t Val = Mem.OffsetImm ? Mem.OffsetImm->getValue() : 0; + if (!Mem.OffsetRegNum) { + ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; + // Special case for #-0 + if (Val == INT32_MIN) Val = 0; + if (Val < 0) Val = -Val; + Val = ARM_AM::getAM3Opc(AddSub, Val); + } else { + // For register offset, we encode the shift type and negation flag + // here. + Val = ARM_AM::getAM3Opc(Mem.isNegative ? ARM_AM::sub : ARM_AM::add, 0); + } + Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum)); + Inst.addOperand(MCOperand::CreateImm(Val)); + } + + void addAM3OffsetOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + if (Kind == PostIndexRegister) { + int32_t Val = + ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0); + Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum)); + Inst.addOperand(MCOperand::CreateImm(Val)); + } + + // Constant offset. + const MCConstantExpr *CE = static_cast(getImm()); + int32_t Val = CE->getValue(); + ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add; + // Special case for #-0 + if (Val == INT32_MIN) Val = 0; + if (Val < 0) Val = -Val; + Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift); + Inst.addOperand(MCOperand::CreateReg(0)); + Inst.addOperand(MCOperand::CreateImm(Val)); + } + void addAddrMode5Operands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); // The lower two bits are always zero and as such are not encoded. @@ -2046,6 +2111,24 @@ return true; } +/// cvtLdrdPre - Convert parsed operands to MCInst. +/// Needed here because the Asm Gen Matcher can't handle properly tied operands +/// when they refer multiple MIOperands inside a single one. +bool ARMAsmParser:: +cvtLdrdPre(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &Operands) { + // Rt, Rt2 + ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); + ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1); + // Create a writeback register dummy placeholder. + Inst.addOperand(MCOperand::CreateImm(0)); + // addr + ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3); + // pred + ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); + return true; +} + /// Parse an ARM memory expression, return false if successful else return true /// or an error. The first token must be a '[' when called. bool ARMAsmParser:: @@ -2645,6 +2728,9 @@ validateInstruction(MCInst &Inst, const SmallVectorImpl &Operands) { switch (Inst.getOpcode()) { + case ARM::LDRD: + case ARM::LDRD_PRE: + case ARM::LDRD_POST: case ARM::LDREXD: { // Rt2 must be Rt + 1. unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg()); @@ -2654,6 +2740,9 @@ "destination operands must be sequential"); return false; } + case ARM::STRgD: + case ARM::STRgD_PRE: + case ARM::STRgD_POST: case ARM::STREXD: { // Rt2 must be Rt + 1. unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg()); Modified: llvm/trunk/test/MC/ARM/arm-memory-instructions.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/arm-memory-instructions.s?rev=137244&r1=137243&r2=137244&view=diff ============================================================================== --- llvm/trunk/test/MC/ARM/arm-memory-instructions.s (original) +++ llvm/trunk/test/MC/ARM/arm-memory-instructions.s Wed Aug 10 15:29:19 2011 @@ -105,3 +105,17 @@ @ CHECK: ldrbt r2, [r8], #-8 @ encoding: [0x08,0x20,0x78,0xe4] @ CHECK: ldrbt r8, [r7], r6 @ encoding: [0x06,0x80,0xf7,0xe6] @ CHECK: ldrbt r1, [r2], -r6, lsl #12 @ encoding: [0x06,0x16,0x72,0xe6] + + + at ------------------------------------------------------------------------------ +@ LDRD (immediate) + at ------------------------------------------------------------------------------ + ldrd r3, r4, [r5] + ldrd r7, r8, [r2, #15] + ldrd r1, r2, [r9, #32]! + ldrd r6, r7, [r1], #8 + +@ CHECK: ldrd r3, r4, [r5] @ encoding: [0xd0,0x30,0xc5,0xe1] +@ CHECK: ldrd r7, r8, [r2, #15] @ encoding: [0xdf,0x70,0xc2,0xe1] +@ CHECK: ldrd r1, r2, [r9, #32]! @ encoding: [0xd0,0x12,0xe9,0xe1] +@ CHECK: ldrd r6, r7, [r1], #8 @ encoding: [0xd8,0x60,0xc1,0xe0] Modified: llvm/trunk/test/MC/ARM/diagnostics.s URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ARM/diagnostics.s?rev=137244&r1=137243&r2=137244&view=diff ============================================================================== --- llvm/trunk/test/MC/ARM/diagnostics.s (original) +++ llvm/trunk/test/MC/ARM/diagnostics.s Wed Aug 10 15:29:19 2011 @@ -283,3 +283,17 @@ @ CHECK-ERRORS: error: bitfield width must be in range [1,32-lsb] @ CHECK-ERRORS: ubfxgt r4, r5, #16, #17 @ CHECK-ERRORS: ^ + + @ Out of order Rt/Rt2 operands for ldrd + ldrd r4, r3, [r8] + ldrd r4, r3, [r8, #8]! + ldrd r4, r3, [r8], #8 +@ CHECK-ERRORS: error: destination operands must be sequential +@ CHECK-ERRORS: ldrd r4, r3, [r8] +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: destination operands must be sequential +@ CHECK-ERRORS: ldrd r4, r3, [r8, #8]! +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: destination operands must be sequential +@ CHECK-ERRORS: ldrd r4, r3, [r8], #8 +@ CHECK-ERRORS: ^ From nlewycky at google.com Wed Aug 10 15:43:58 2011 From: nlewycky at google.com (Nick Lewycky) Date: Wed, 10 Aug 2011 13:43:58 -0700 Subject: [llvm-commits] PATCH: Preserving the 'nsw' flag in the instruction combiner. In-Reply-To: References: <000d01cc575e$7c2c1d70$74845850$@org> <000001cc5795$02b32420$08196c60$@org> Message-ID: On 10 August 2011 13:19, Eli Friedman wrote: > On Wed, Aug 10, 2011 at 1:11 PM, Nick Lewycky wrote: > > On 10 August 2011 13:07, Eli Friedman wrote: > >> > >> On Wed, Aug 10, 2011 at 12:57 PM, Nick Lewycky > >> wrote: > >> > On 10 August 2011 12:37, Pranav Bhandarkar > >> > wrote: > >> >> > >> >> Hi Nick, > >> >> > >> >> >>Thanks for working on this! Firstly, I have a high-level question: > >> >> >> why > >> >> can't (X +nsw (C1 +nsw C2) always become (X +nsw C3)? Your patch > spends > >> >> a > >> >> lot of time verifying that >>overflow couldn't occur, but you're > given > >> >> an > >> >> assumption a priori that it can't because the nsw flag is present. > >> >> > >> >> The reason is that 127 (C1) + 2 (C2) = 129 (C3) is not strictly true > >> >> always. > >> >> For instance, when the type is i8, then C3 is -127. > >> > > >> > 127 + 2 = 129 remains true with i8 values, because i8 -127 = i8 129. > >> > They > >> > have the same bit pattern. > >> > Can you pick values for X, C1 and C2 which still satisfy the +nsw > >> > relationship between each other that can't be converted into X +nsw C3 > >> > where > >> > C3 = C1+C2 (no nsw requirement)? 127 and 2 don't work as > >> > counter-examples > >> > because that triggers undefined behaviour (it violates the 'nsw' bit > >> > present > >> > on the add). > >> > >> X = -128, C1 = 127, C1 = 2? > > > > I assume C2 = 2 and all i8 values. That doesn't work because the > expression > > was "(X +nsw (C1 +nsw C2)" and 127 +nsw 2 invokes undefined behaviour, > > crossing from 127 to -128/128 to reach -127/129. In fact nsw-adding > anything > > positive to 127 is invalid, so you'd have to be sure to pick a negative > C2 > > given a C1 of 127. > > The original expression is ((X +nsw C1) +nsw C2). > Doh! Than
    TimeMander HallSide Room #1Side Room #2
    TimeMander HallSide Room #1Side Room #2
    @@ -145,7 +145,7 @@ Side session
    18:15