[PATCH v2] [PowerPC] Add Hardware Transaction Memory builtins support

Hal Finkel hfinkel at anl.gov
Thu Mar 5 18:48:39 PST 2015


----- Original Message -----
> From: "Bill Schmidt" <wschmidt at linux.vnet.ibm.com>
> To: "Adhemerval Zanella" <azanella at linux.vnet.ibm.com>
> Cc: llvm-commits at cs.uiuc.edu, "Hal Finkel" <hfinkel at anl.gov>
> Sent: Thursday, March 5, 2015 3:54:50 PM
> Subject: Re: [PATCH v2] [PowerPC] Add Hardware Transaction Memory builtins support
> 
> Hi Adhemerval,
> 
> I have only a few inline comments, but I feel this needs Hal's review
> for some of the changes you've made, so adding him.  Also, in the
> future
> could you please use the Phabricator review process?  This is new
> since
> you were last working on LLVM, and is much more convenient for
> everyone.

Hi, welcome back. I agree with Bill, it would be much easier to review these on Phabricator. Could you please upload them there; see: http://llvm.org/docs/Phabricator.html#requesting-a-review-via-the-web-interface for instructions.

Thanks again,
Hal

> 
> On Thu, 2015-03-05 at 17:30 -0300, Adhemerval Zanella wrote:
> > On 05-03-2015 15:17, Adhemerval Zanella wrote:
> > > This patch adds Hardware Transaction Memory (HTM) support
> > > supported by
> > > ISA 2.07 (POWER8).
> > >
> > > The HTM instructions follows the RC ones and the transaction
> > > initiation
> > > result is set on RC0 (with exception of tcheck).  Currently
> > > approach is
> > > to create a register copy from CR0 to GPR and comapring.
> > >  Although this
> > > is suboptimal, since the branch could be taken directly by
> > > comparing
> > > the CR0 value, it generates code correctly on both test and
> > > branch and
> > > just return value.  A possible future optimization could be
> > > elimitate
> > > the MFCR instruction to branch directly.
> > >
> > > The HTM usage requires a recently newer kernel with PPC HTM
> > > enabled.
> > > Tested on powerpc64 and powerpc64le.
> > >
> > > This is send along a clang patch to enabled the builtins and
> > > option
> > > switch.
> > >
> > > [1]
> > > https://gcc.gnu.org/onlinedocs/gcc/PowerPC-Hardware-Transactional-Memory-Built-in-Functions.html
> > >
> > > --
> > >
> > > Changes from previous version:
> > >
> > > - Fixed grammatical error raised by Will Schmidt
> > > - Change __builtin_tcheck signature to no accept any arguments.
> > >  The CR fiels
> > >   will be selected by the backend and the result will be adjusted
> > >   accordingly.
> > > - Added PowerPC HTM High Level Inline Functions header
> > > (htmxlintrin.h).
> > >
> > > ---
> > >
> > > _______________________________________________
> > > llvm-commits mailing list
> > > llvm-commits at cs.uiuc.edu
> > > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> > >
> > And the patch below:
> > 
> > ---
> >  include/llvm/IR/IntrinsicsPowerPC.td               |  59 +++++++
> >  lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp      |   1 +
> >  .../PowerPC/Disassembler/PPCDisassembler.cpp       |   6 +
> >  lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp  |   7 +
> >  lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h    |   1 +
> >  lib/Target/PowerPC/PPC.td                          |   4 +-
> >  lib/Target/PowerPC/PPCISelLowering.cpp             |   6 +
> >  lib/Target/PowerPC/PPCInstr64Bit.td                |   6 +
> >  lib/Target/PowerPC/PPCInstrFormats.td              |  54 +++++++
> >  lib/Target/PowerPC/PPCInstrHTM.td                  | 172
> >  +++++++++++++++++++++
> >  lib/Target/PowerPC/PPCInstrInfo.cpp                |  53 +++++++
> >  lib/Target/PowerPC/PPCInstrInfo.td                 |  15 +-
> >  lib/Target/PowerPC/PPCRegisterInfo.cpp             |  31 ----
> >  lib/Target/PowerPC/PPCRegisterInfo.h               |  33 ++++
> >  lib/Target/PowerPC/PPCRegisterInfo.td              |   2 +
> >  lib/Target/PowerPC/PPCSubtarget.cpp                |   1 +
> >  lib/Target/PowerPC/PPCSubtarget.h                  |   2 +
> >  test/CodeGen/PowerPC/htm.ll                        | 125
> >  +++++++++++++++
> >  test/MC/PowerPC/htm.s                              |  53 +++++++
> >  19 files changed, 598 insertions(+), 33 deletions(-)
> >  create mode 100644 lib/Target/PowerPC/PPCInstrHTM.td
> >  create mode 100644 test/CodeGen/PowerPC/htm.ll
> >  create mode 100644 test/MC/PowerPC/htm.s
> > 
> > diff --git a/include/llvm/IR/IntrinsicsPowerPC.td
> > b/include/llvm/IR/IntrinsicsPowerPC.td
> > index bb03e05..2b182ae 100644
> > --- a/include/llvm/IR/IntrinsicsPowerPC.td
> > +++ b/include/llvm/IR/IntrinsicsPowerPC.td
> > @@ -802,3 +802,62 @@ let TargetPrefix = "ppc" in {  // All
> > intrinsics start with "llvm.ppc.".
> >                            [llvm_v4f64_ty], [llvm_i32_ty],
> >                            [IntrNoMem]>;
> >  }
> > 
> > +//===----------------------------------------------------------------------===//
> > +// PowerPC HTM Intrinsic Definitions.
> > +
> > +let TargetPrefix = "ppc" in {  // All intrinsics start with
> > "llvm.ppc.".
> > +
> > +def int_ppc_tbegin :
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
> > +def int_ppc_tend :
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
> > +
> > +def int_ppc_tabort : GCCBuiltin<"__builtin_tabort">,
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
> > +def int_ppc_tabortwc :
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty,
> > llvm_i32_ty], []>;
> > +def int_ppc_tabortwci :
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty,
> > llvm_i32_ty], []>;
> > +def int_ppc_tabortdc :
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty,
> > llvm_i32_ty], []>;
> > +def int_ppc_tabortdci :
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty,
> > llvm_i32_ty], []>;
> > +
> > +def int_ppc_tcheck : GCCBuiltin<"__builtin_tcheck">,
> > +      Intrinsic<[llvm_i32_ty], [], []>;
> > +def int_ppc_treclaim : GCCBuiltin<"__builtin_treclaim">,
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
> > +def int_ppc_trechkpt : GCCBuiltin<"__builtin_trechkpt">,
> > +      Intrinsic<[llvm_i32_ty], [], []>;
> > +def int_ppc_tsr :
> > +      Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
> > +
> > +def int_ppc_get_texasr : GCCBuiltin<"__builtin_get_texasr">,
> > +      Intrinsic<[llvm_i64_ty], [], []>;
> > +def int_ppc_get_texasru : GCCBuiltin<"__builtin_get_texasru">,
> > +      Intrinsic<[llvm_i64_ty], [], []>;
> > +def int_ppc_get_tfhar : GCCBuiltin<"__builtin_get_tfhar">,
> > +      Intrinsic<[llvm_i64_ty], [], []>;
> > +def int_ppc_get_tfiar : GCCBuiltin<"__builtin_get_tfiar">,
> > +      Intrinsic<[llvm_i64_ty], [], []>;
> > +
> > +def int_ppc_set_texasr : GCCBuiltin<"__builtin_set_texasr">,
> > +      Intrinsic<[], [llvm_i64_ty], []>;
> > +def int_ppc_set_texasru : GCCBuiltin<"__builtin_set_texasru">,
> > +      Intrinsic<[], [llvm_i64_ty], []>;
> > +def int_ppc_set_tfhar : GCCBuiltin<"__builtin_set_tfhar">,
> > +      Intrinsic<[], [llvm_i64_ty], []>;
> > +def int_ppc_set_tfiar : GCCBuiltin<"__builtin_set_tfiar">,
> > +      Intrinsic<[], [llvm_i64_ty], []>;
> > +
> > +// Extended mnemonics
> > +def int_ppc_tendall : GCCBuiltin<"__builtin_tendall">,
> > +      Intrinsic<[llvm_i32_ty], [], []>;
> > +def int_ppc_tresume : GCCBuiltin<"__builtin_tresume">,
> > +      Intrinsic<[llvm_i32_ty], [], []>;
> > +def int_ppc_tsuspend : GCCBuiltin<"__builtin_tsuspend">,
> > +      Intrinsic<[llvm_i32_ty], [], []>;
> > +
> > +def int_ppc_ttest : GCCBuiltin<"__builtin_ttest">,
> > +      Intrinsic<[llvm_i64_ty], [], []>;
> > +}
> > diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
> > b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
> > index c164f32..2349052 100644
> > --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
> > +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
> > @@ -427,6 +427,7 @@ public:
> >    bool isImm() const override { return Kind == Immediate || Kind
> >    == Expression; }
> >    bool isU1Imm() const { return Kind == Immediate &&
> >    isUInt<1>(getImm()); }
> >    bool isU2Imm() const { return Kind == Immediate &&
> >    isUInt<2>(getImm()); }
> > +  bool isU3Imm() const { return Kind == Immediate &&
> > isUInt<3>(getImm()); }
> >    bool isU4Imm() const { return Kind == Immediate &&
> >    isUInt<4>(getImm()); }
> >    bool isU5Imm() const { return Kind == Immediate &&
> >    isUInt<5>(getImm()); }
> >    bool isS5Imm() const { return Kind == Immediate &&
> >    isInt<5>(getImm()); }
> > diff --git a/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
> > b/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
> > index 0ed0723..a9f5fc7 100644
> > --- a/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
> > +++ b/lib/Target/PowerPC/Disassembler/PPCDisassembler.cpp
> > @@ -189,6 +189,12 @@ static DecodeStatus
> > DecodeCRRCRegisterClass(MCInst &Inst, uint64_t RegNo,
> >    return decodeRegisterClass(Inst, RegNo, CRRegs);
> >  }
> > 
> > +static DecodeStatus DecodeCRRC0RegisterClass(MCInst &Inst,
> > uint64_t RegNo,
> > +                                            uint64_t Address,
> > +                                            const void *Decoder) {
> > +  return decodeRegisterClass(Inst, RegNo, CRRegs);
> > +}
> > +
> >  static DecodeStatus DecodeCRBITRCRegisterClass(MCInst &Inst,
> >  uint64_t RegNo,
> >                                              uint64_t Address,
> >                                              const void *Decoder) {
> > diff --git a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
> > b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
> > index 5d1aa1a..311a4f2 100644
> > --- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
> > +++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
> > @@ -228,6 +228,13 @@ void PPCInstPrinter::printU2ImmOperand(const
> > MCInst *MI, unsigned OpNo,
> >    O << (unsigned int)Value;
> >  }
> > 
> > +void PPCInstPrinter::printU3ImmOperand(const MCInst *MI, unsigned
> > OpNo,
> > +                                       raw_ostream &O) {
> > +  unsigned int Value = MI->getOperand(OpNo).getImm();
> > +  assert(Value <= 8 && "Invalid u3imm argument!");
> > +  O << (unsigned int)Value;
> > +}
> > +
> >  void PPCInstPrinter::printU4ImmOperand(const MCInst *MI, unsigned
> >  OpNo,
> >                                         raw_ostream &O) {
> >    unsigned int Value = MI->getOperand(OpNo).getImm();
> > diff --git a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h
> > b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h
> > index 22934b8..8718743 100644
> > --- a/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h
> > +++ b/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h
> > @@ -45,6 +45,7 @@ public:
> > 
> >    void printU1ImmOperand(const MCInst *MI, unsigned OpNo,
> >    raw_ostream &O);
> >    void printU2ImmOperand(const MCInst *MI, unsigned OpNo,
> >    raw_ostream &O);
> > +  void printU3ImmOperand(const MCInst *MI, unsigned OpNo,
> > raw_ostream &O);
> >    void printU4ImmOperand(const MCInst *MI, unsigned OpNo,
> >    raw_ostream &O);
> >    void printS5ImmOperand(const MCInst *MI, unsigned OpNo,
> >    raw_ostream &O);
> >    void printU5ImmOperand(const MCInst *MI, unsigned OpNo,
> >    raw_ostream &O);
> > diff --git a/lib/Target/PowerPC/PPC.td b/lib/Target/PowerPC/PPC.td
> > index dc2a0d5..ce238c6 100644
> > --- a/lib/Target/PowerPC/PPC.td
> > +++ b/lib/Target/PowerPC/PPC.td
> > @@ -118,6 +118,8 @@ def FeatureP8Crypto :
> > SubtargetFeature<"crypto", "HasP8Crypto", "true",
> >  def FeatureP8Vector  : SubtargetFeature<"power8-vector",
> >  "HasP8Vector", "true",
> >                                          "Enable POWER8 vector
> >                                          instructions",
> >                                          [FeatureVSX,
> >                                          FeatureP8Altivec]>;
> > +def FeatureHTM : SubtargetFeature<"htm", "HasHTM", "true",
> > +                                  "Enable Hardware Transaction
> > Memory instructions">;
> > 
> >  def FeatureInvariantFunctionDescriptors :
> >    SubtargetFeature<"invariant-function-descriptors",
> > @@ -259,7 +261,7 @@ def ProcessorFeatures {
> >          [DirectivePwr8, FeatureAltivec, FeatureP8Altivec,
> >          FeatureVSX,
> >          FeatureP8Vector, FeatureMFOCRF, FeatureFCPSGN,
> >          FeatureFSqrt,
> >          FeatureFRE, FeatureFRES, FeatureFRSQRTE, FeatureFRSQRTES,
> > -        FeatureRecipPrec, FeatureSTFIWX, FeatureLFIWAX,
> > +        FeatureRecipPrec, FeatureSTFIWX, FeatureLFIWAX,
> > FeatureHTM,
> >          FeatureFPRND, FeatureFPCVT, FeatureISEL,
> >          FeaturePOPCNTD, FeatureCMPB, FeatureLDBRX,
> >          FeatureP8Crypto,
> >          Feature64Bit /*, Feature64BitRegs */, FeatureICBT,
> > diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp
> > b/lib/Target/PowerPC/PPCISelLowering.cpp
> > index 70770a9..c7ae48d 100644
> > --- a/lib/Target/PowerPC/PPCISelLowering.cpp
> > +++ b/lib/Target/PowerPC/PPCISelLowering.cpp
> > @@ -8723,6 +8723,12 @@
> > PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
> >      BuildMI(*BB, MI, dl, TII->get(TargetOpcode::COPY),
> >              MI->getOperand(0).getReg())
> >        .addReg(isEQ ? PPC::CR0EQ : PPC::CR0GT);
> > +  } else if (MI->getOpcode() == PPC::TCHECK_RET) {
> > +    DebugLoc Dl = MI->getDebugLoc();
> > +    MachineRegisterInfo &RegInfo = F->getRegInfo();
> > +    unsigned CRReg =
> > RegInfo.createVirtualRegister(&PPC::CRRCRegClass);
> > +    BuildMI(*BB, MI, Dl, TII->get(PPC::TCHECK), CRReg);
> > +    return BB;
> >    } else {
> >      llvm_unreachable("Unexpected instr type to insert");
> >    }
> > diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td
> > b/lib/Target/PowerPC/PPCInstr64Bit.td
> > index 69c0d7d..2605ae7 100644
> > --- a/lib/Target/PowerPC/PPCInstr64Bit.td
> > +++ b/lib/Target/PowerPC/PPCInstr64Bit.td
> > @@ -325,6 +325,12 @@ let hasSideEffects = 1, isBarrier = 1,
> > usesCustomInserter = 1 in {
> >                            Requires<[In64BitMode]>;
> >  }
> > 
> > +def MFSPR8 : XFXForm_1<31, 339, (outs g8rc:$RT), (ins
> > i32imm:$SPR),
> > +                       "mfspr $RT, $SPR", IIC_SprMFSPR>;
> > +def MTSPR8 : XFXForm_1<31, 467, (outs), (ins i32imm:$SPR,
> > g8rc:$RT),
> > +                       "mtspr $SPR, $RT", IIC_SprMTSPR>;
> > +
> > +
> >  //===----------------------------------------------------------------------===//
> >  // 64-bit SPR manipulation instrs.
> > 
> > diff --git a/lib/Target/PowerPC/PPCInstrFormats.td
> > b/lib/Target/PowerPC/PPCInstrFormats.td
> > index 2d3e43c..b7a7a1f 100644
> > --- a/lib/Target/PowerPC/PPCInstrFormats.td
> > +++ b/lib/Target/PowerPC/PPCInstrFormats.td
> > @@ -693,6 +693,60 @@ class XForm_16b<bits<6> opcode, bits<10> xo,
> > dag OOL, dag IOL, string asmstr,
> >    let A = 0;
> >  }
> > 
> > +class XForm_htm0<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
> > +                 string asmstr, InstrItinClass itin, list<dag>
> > pattern>
> > +  : I<opcode, OOL, IOL, asmstr, itin> {
> > +  bit R;
> > +
> > +  bit RC = 1;
> > +
> > +  let Inst{6-9}   = 0;
> > +  let Inst{10}    = R;
> > +  let Inst{11-20} = 0;
> > +  let Inst{21-30} = xo;
> > +  let Inst{31}    = RC;
> > +}
> > +
> > +class XForm_htm1<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
> > +                 string asmstr, InstrItinClass itin, list<dag>
> > pattern>
> > +  : I<opcode, OOL, IOL, asmstr, itin> {
> > +  bit A;
> > +
> > +  bit RC = 1;
> > +
> > +  let Inst{6}     = A;
> > +  let Inst{7-20}  = 0;
> > +  let Inst{21-30} = xo;
> > +  let Inst{31}    = RC;
> > +}
> > +
> > +class XForm_htm2<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
> > string asmstr,
> > +              InstrItinClass itin, list<dag> pattern>
> > +  : I<opcode, OOL, IOL, asmstr, itin> {
> > +  bit L;
> > +
> > +  bit RC = 0;    // set by isDOT
> > +
> > +  let Inst{7-9}   = 0;
> > +  let Inst{10}    = L;
> > +  let Inst{11-20} = 0;
> > +  let Inst{21-30} = xo;
> > +  let Inst{31}    = RC;
> > +}
> > +
> > +class XForm_htm3<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
> > string asmstr,
> > +              InstrItinClass itin, list<dag> pattern>
> > +  : I<opcode, OOL, IOL, asmstr, itin> {
> > +  bits<3> BF;
> > +
> > +  bit RC = 0;
> > +
> > +  let Inst{6-8}   = BF;
> > +  let Inst{9-20}  = 0;
> > +  let Inst{21-30} = xo;
> > +  let Inst{31}    = RC;
> > +}
> > +
> >  // XX*-Form (VSX)
> >  class XX1Form<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
> >  string asmstr,
> >                InstrItinClass itin, list<dag> pattern>
> > diff --git a/lib/Target/PowerPC/PPCInstrHTM.td
> > b/lib/Target/PowerPC/PPCInstrHTM.td
> > new file mode 100644
> > index 0000000..20e6a62
> > --- /dev/null
> > +++ b/lib/Target/PowerPC/PPCInstrHTM.td
> > @@ -0,0 +1,172 @@
> > +//===-- PPCInstrHTM.td - The PowerPC Hardware Transactional Memory
> >  -*-===//
> > +//
> > +//                     The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open
> > Source
> > +// License. See LICENSE.TXT for details.
> > +//
> > +//===----------------------------------------------------------------------===//
> > +//
> > +// This file describes the Hardware Transactional Memory extension
> > to the
> > +// PowerPC instruction set.
> > +//
> > +//===----------------------------------------------------------------------===//
> > +
> > +
> > +
> > +def HasHTM : Predicate<"PPCSubTarget->hasHTM()">;
> > +
> > +def HTM_get_imm : SDNodeXForm<imm, [{
> > +  return getI32Imm (N->getZExtValue());
> > +}]>;
> > +
> > +let hasSideEffects = 1, usesCustomInserter = 1  in {
> > +def TCHECK_RET : Pseudo<(outs crrc:$out), (ins), "#TCHECK_RET",
> > []>;
> > +}
> > +
> > +
> > +let Predicates = [HasHTM] in {
> > +
> > +def TBEGIN : XForm_htm0 <31, 654,
> > +                         (outs crrc0:$ret), (ins u1imm:$R),
> > "tbegin. $R", IIC_SprMTSPR, []>;
> > +
> > +def TEND : XForm_htm1 <31, 686,
> > +                       (outs crrc0:$ret), (ins u1imm:$A), "tend.
> > $A", IIC_SprMTSPR, []>;
> > +
> > +def TABORT : XForm_base_r3xo <31, 910,
> > +                              (outs crrc0:$ret), (ins gprc:$A),
> > "tabort. $A", IIC_SprMTSPR,
> > +                              []>, isDOT {
> > +  let RST = 0;
> > +  let B = 0;
> > +}
> > +
> > +def TABORTWC : XForm_base_r3xo <31, 782,
> > +                                (outs crrc0:$ret), (ins
> > u5imm:$RTS, gprc:$A, gprc:$B),
> > +                                "tabortwc. $RTS, $A, $B",
> > IIC_SprMTSPR, []>,
> > +                                isDOT;
> > +
> > +def TABORTWCI : XForm_base_r3xo <31, 846,
> > +                                 (outs crrc0:$ret), (ins
> > u5imm:$RTS, gprc:$A, u5imm:$B),
> > +                                 "tabortwci. $RTS, $A, $B",
> > IIC_SprMTSPR, []>,
> > +                                 isDOT;
> > +
> > +def TABORTDC : XForm_base_r3xo <31, 814,
> > +                                (outs crrc0:$ret), (ins
> > u5imm:$RTS, gprc:$A, gprc:$B),
> > +                                "tabortdc. $RTS, $A, $B",
> > IIC_SprMTSPR, []>,
> > +                                isDOT;
> > +
> > +def TABORTDCI : XForm_base_r3xo <31, 878,
> > +                                 (outs crrc0:$ret), (ins
> > u5imm:$RTS, gprc:$A, u5imm:$B),
> > +                                 "tabortdci. $RTS, $A, $B",
> > IIC_SprMTSPR, []>,
> > +                                 isDOT;
> > +
> > +def TSR : XForm_htm2 <31, 750,
> > +                      (outs crrc0:$ret), (ins u1imm:$L), "tsr.
> > $L", IIC_SprMTSPR, []>,
> > +                      isDOT;
> > +
> > +def TCHECK : XForm_htm3 <31, 718,
> > +                        (outs), (ins crrc:$BF), "tcheck $BF",
> > IIC_SprMTSPR, []>;
> > +
> > +
> > +def TRECLAIM : XForm_base_r3xo <31, 942,
> > +                                (outs crrc:$ret), (ins gprc:$A),
> > "treclaim. $A",
> > +                                IIC_SprMTSPR, []>,
> > +                                isDOT {
> > +  let RST = 0;
> > +  let B = 0;
> > +}
> > +
> > +def TRECHKPT : XForm_base_r3xo <31, 1006,
> > +                                (outs crrc:$ret), (ins),
> > "trechkpt.", IIC_SprMTSPR, []>,
> > +                                isDOT {
> > +  let RST = 0;
> > +  let A = 0;
> > +  let B = 0;
> > +}
> > +
> > +// Builtins
> > +
> > +// All HTM instructions, with the exception of tcheck, set CR0
> > with the
> > +// value of the MSR Transaction State (TS) bits that exist before
> > the
> > +// instruction is executed.  For tbegin., the EQ bit in CR0 can be
> > used
> > +// to determine whether the transaction was successfully started
> > (0) or
> > +// failed (1).  We use an XORI pattern to 'flip' the bit to match
> > the
> > +// tbegin builtin API which defines a return value of 1 as
> > success.
> > +
> > +def : Pat<(int_ppc_tbegin i32:$R),
> > +           (XORI
> > +             (EXTRACT_SUBREG (
> > +               TBEGIN (HTM_get_imm imm:$R)), sub_eq),
> > +            1)>;
> > +
> > +def : Pat<(int_ppc_tend i32:$R),
> > +          (TEND (HTM_get_imm imm:$R))>;
> > +
> > +
> > +def : Pat<(int_ppc_tabort i32:$R),
> > +          (TABORT $R)>;
> > +
> > +def : Pat<(int_ppc_tabortwc i32:$TO, i32:$RA, i32:$RB),
> > +          (TABORTWC (HTM_get_imm imm:$TO), $RA, $RB)>;
> > +
> > +def : Pat<(int_ppc_tabortwci i32:$TO, i32:$RA, i32:$SI),
> > +          (TABORTWCI (HTM_get_imm imm:$TO), $RA, (HTM_get_imm
> > imm:$SI))>;
> > +
> > +def : Pat<(int_ppc_tabortdc i32:$TO, i32:$RA, i32:$RB),
> > +          (TABORTDC (HTM_get_imm imm:$TO), $RA, $RB)>;
> > +
> > +def : Pat<(int_ppc_tabortdci i32:$TO, i32:$RA, i32:$SI),
> > +          (TABORTDCI (HTM_get_imm imm:$TO), $RA, (HTM_get_imm
> > imm:$SI))>;
> > +
> > +def : Pat<(int_ppc_tcheck),
> > +          (TCHECK_RET)>;
> > +
> > +def : Pat<(int_ppc_treclaim i32:$RA),
> > +          (TRECLAIM $RA)>;
> > +
> > +def : Pat<(int_ppc_trechkpt),
> > +          (TRECHKPT)>;
> > +
> > +def : Pat<(int_ppc_tsr i32:$L),
> > +          (TSR (HTM_get_imm imm:$L))>;
> > +
> > +def : Pat<(int_ppc_get_texasr),
> > +          (MFSPR8 130)>;
> > +
> > +def : Pat<(int_ppc_get_texasru),
> > +          (MFSPR8 131)>;
> > +
> > +def : Pat<(int_ppc_get_tfhar),
> > +          (MFSPR8 128)>;
> > +
> > +def : Pat<(int_ppc_get_tfiar),
> > +          (MFSPR8 129)>;
> > +
> > +
> > +def : Pat<(int_ppc_set_texasr i64:$V),
> > +          (MTSPR8 130, $V)>;
> > +
> > +def : Pat<(int_ppc_set_texasru i64:$V),
> > +          (MTSPR8 131, $V)>;
> > +
> > +def : Pat<(int_ppc_set_tfhar i64:$V),
> > +          (MTSPR8 128, $V)>;
> > +
> > +def : Pat<(int_ppc_set_tfiar i64:$V),
> > +          (MTSPR8 129, $V)>;
> > +
> > +
> > +// Extended mnemonics
> > +def : Pat<(int_ppc_tendall),
> > +          (TEND 1)>;
> > +
> > +def : Pat<(int_ppc_tresume),
> > +          (TSR 1)>;
> > +
> > +def : Pat<(int_ppc_tsuspend),
> > +          (TSR 0)>;
> > +
> > +def : Pat<(i64 (int_ppc_ttest)),
> > +          (RLDICL (i64 (COPY (TABORTWCI 0, ZERO, 0))), 36, 28)>;
> > +
> > +} // [HasHTM]
> > diff --git a/lib/Target/PowerPC/PPCInstrInfo.cpp
> > b/lib/Target/PowerPC/PPCInstrInfo.cpp
> > index fe9474a..d68ca0c 100644
> > --- a/lib/Target/PowerPC/PPCInstrInfo.cpp
> > +++ b/lib/Target/PowerPC/PPCInstrInfo.cpp
> > @@ -697,6 +697,33 @@ void
> > PPCInstrInfo::insertSelect(MachineBasicBlock &MBB,
> >      .addReg(Cond[1].getReg(), 0, SubIdx);
> >  }
> > 
> > +static unsigned getCRBitValue(unsigned CRBit) {
> > +  unsigned Ret = 4;
> > +  if (CRBit == PPC::CR0LT || CRBit == PPC::CR1LT ||
> > +      CRBit == PPC::CR2LT || CRBit == PPC::CR3LT ||
> > +      CRBit == PPC::CR4LT || CRBit == PPC::CR5LT ||
> > +      CRBit == PPC::CR6LT || CRBit == PPC::CR7LT)
> > +    Ret = 3;
> > +  if (CRBit == PPC::CR0GT || CRBit == PPC::CR1GT ||
> > +      CRBit == PPC::CR2GT || CRBit == PPC::CR3GT ||
> > +      CRBit == PPC::CR4GT || CRBit == PPC::CR5GT ||
> > +      CRBit == PPC::CR6GT || CRBit == PPC::CR7GT)
> > +    Ret = 2;
> > +  if (CRBit == PPC::CR0EQ || CRBit == PPC::CR1EQ ||
> > +      CRBit == PPC::CR2EQ || CRBit == PPC::CR3EQ ||
> > +      CRBit == PPC::CR4EQ || CRBit == PPC::CR5EQ ||
> > +      CRBit == PPC::CR6EQ || CRBit == PPC::CR7EQ)
> > +    Ret = 1;
> > +  if (CRBit == PPC::CR0UN || CRBit == PPC::CR1UN ||
> > +      CRBit == PPC::CR2UN || CRBit == PPC::CR3UN ||
> > +      CRBit == PPC::CR4UN || CRBit == PPC::CR5UN ||
> > +      CRBit == PPC::CR6UN || CRBit == PPC::CR7UN)
> > +    Ret = 0;
> > +
> > +  assert(Ret != 4 && "Invalid CR bit register");
> > +  return Ret;
> > +}
> > +
> >  void PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
> >                                 MachineBasicBlock::iterator I,
> >                                 DebugLoc DL,
> >                                 unsigned DestReg, unsigned SrcReg,
> > @@ -742,6 +769,32 @@ void
> > PPCInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
> >      SrcReg = SuperReg;
> >    }
> > 
> > +  // Different class register copy
> > +  if (PPC::CRBITRCRegClass.contains(SrcReg) &&
> > +      PPC::GPRCRegClass.contains(DestReg)) {
> > +    unsigned CRReg = getCRFromCRBit(SrcReg);
> > +    BuildMI(MBB, I, DL, get(PPC::MFOCRF), DestReg)
> > +       .addReg(CRReg), getKillRegState(KillSrc);
> > +    // Rotate the CR bit in the CR fields to be the least
> > significant bit and
> > +    // then mask with 0x1 (MB = ME = 31).
> > +    BuildMI(MBB, I, DL, get(PPC::RLWINM), DestReg)
> > +       .addReg(DestReg, RegState::Kill)
> > +       .addImm(TRI->getEncodingValue(CRReg) * 4 + (4 -
> > getCRBitValue(SrcReg)))
> > +       .addImm(31)
> > +       .addImm(31);
> > +    return;
> > +  } else if (PPC::CRRCRegClass.contains(SrcReg) &&
> > +      PPC::G8RCRegClass.contains(DestReg)) {
> > +    BuildMI(MBB, I, DL, get(PPC::MFOCRF8), DestReg)
> > +       .addReg(SrcReg), getKillRegState(KillSrc);
> > +    return;
> > +  } else if (PPC::CRRCRegClass.contains(SrcReg) &&
> > +      PPC::GPRCRegClass.contains(DestReg)) {
> > +    BuildMI(MBB, I, DL, get(PPC::MFOCRF), DestReg)
> > +       .addReg(SrcReg), getKillRegState(KillSrc);
> > +    return;
> > +   }
> > +
> >    unsigned Opc;
> >    if (PPC::GPRCRegClass.contains(DestReg, SrcReg))
> >      Opc = PPC::OR;
> > diff --git a/lib/Target/PowerPC/PPCInstrInfo.td
> > b/lib/Target/PowerPC/PPCInstrInfo.td
> > index fe436ca..a1a649c 100644
> > --- a/lib/Target/PowerPC/PPCInstrInfo.td
> > +++ b/lib/Target/PowerPC/PPCInstrInfo.td
> > @@ -445,13 +445,16 @@ def PPCRegCRRCAsmOperand : AsmOperandClass {
> >  def crrc : RegisterOperand<CRRC> {
> >    let ParserMatchClass = PPCRegCRRCAsmOperand;
> >  }
> > +def crrc0 : RegisterOperand<CRRC0> {
> > +  let ParserMatchClass = PPCRegCRRCAsmOperand;
> > +}
> > 
> >  def PPCU1ImmAsmOperand : AsmOperandClass {
> >    let Name = "U1Imm"; let PredicateMethod = "isU1Imm";
> >    let RenderMethod = "addImmOperands";
> >  }
> >  def u1imm   : Operand<i32> {
> > -  let PrintMethod = "printU1ImmOperand";
> > +  let PrintMethod = "printU2ImmOperand";
> >    let ParserMatchClass = PPCU1ImmAsmOperand;
> 
> Um, is this just here to see if I'm awake?  Why did you change the
> PrintMethod in this non-intuitive way? ;)
> 
> >  }
> > 
> > @@ -464,6 +467,15 @@ def u2imm   : Operand<i32> {
> >    let ParserMatchClass = PPCU2ImmAsmOperand;
> >  }
> > 
> > +def PPCU3ImmAsmOperand : AsmOperandClass {
> > +  let Name = "U3Imm"; let PredicateMethod = "isU3Imm";
> > +  let RenderMethod = "addImmOperands";
> > +}
> > +def u3imm   : Operand<i32> {
> > +  let PrintMethod = "printU3ImmOperand";
> > +  let ParserMatchClass = PPCU3ImmAsmOperand;
> > +}
> > +
> >  def PPCU4ImmAsmOperand : AsmOperandClass {
> >    let Name = "U4Imm"; let PredicateMethod = "isU4Imm";
> >    let RenderMethod = "addImmOperands";
> > @@ -2692,6 +2704,7 @@ include "PPCInstrSPE.td"
> >  include "PPCInstr64Bit.td"
> >  include "PPCInstrVSX.td"
> >  include "PPCInstrQPX.td"
> > +include "PPCInstrHTM.td"
> > 
> >  def crnot : OutPatFrag<(ops node:$in),
> >                         (CRNOR $in, $in)>;
> > diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp
> > b/lib/Target/PowerPC/PPCRegisterInfo.cpp
> > index c9a9684..7a6d089 100644
> > --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp
> > +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp
> > @@ -522,37 +522,6 @@ void
> > PPCRegisterInfo::lowerCRRestore(MachineBasicBlock::iterator II,
> >    MBB.erase(II);
> >  }
> > 
> > -static unsigned getCRFromCRBit(unsigned SrcReg) {
> > -  unsigned Reg = 0;
> > -  if (SrcReg == PPC::CR0LT || SrcReg == PPC::CR0GT ||
> > -      SrcReg == PPC::CR0EQ || SrcReg == PPC::CR0UN)
> > -    Reg = PPC::CR0;
> > -  else if (SrcReg == PPC::CR1LT || SrcReg == PPC::CR1GT ||
> > -           SrcReg == PPC::CR1EQ || SrcReg == PPC::CR1UN)
> > -    Reg = PPC::CR1;
> > -  else if (SrcReg == PPC::CR2LT || SrcReg == PPC::CR2GT ||
> > -           SrcReg == PPC::CR2EQ || SrcReg == PPC::CR2UN)
> > -    Reg = PPC::CR2;
> > -  else if (SrcReg == PPC::CR3LT || SrcReg == PPC::CR3GT ||
> > -           SrcReg == PPC::CR3EQ || SrcReg == PPC::CR3UN)
> > -    Reg = PPC::CR3;
> > -  else if (SrcReg == PPC::CR4LT || SrcReg == PPC::CR4GT ||
> > -           SrcReg == PPC::CR4EQ || SrcReg == PPC::CR4UN)
> > -    Reg = PPC::CR4;
> > -  else if (SrcReg == PPC::CR5LT || SrcReg == PPC::CR5GT ||
> > -           SrcReg == PPC::CR5EQ || SrcReg == PPC::CR5UN)
> > -    Reg = PPC::CR5;
> > -  else if (SrcReg == PPC::CR6LT || SrcReg == PPC::CR6GT ||
> > -           SrcReg == PPC::CR6EQ || SrcReg == PPC::CR6UN)
> > -    Reg = PPC::CR6;
> > -  else if (SrcReg == PPC::CR7LT || SrcReg == PPC::CR7GT ||
> > -           SrcReg == PPC::CR7EQ || SrcReg == PPC::CR7UN)
> > -    Reg = PPC::CR7;
> > -
> > -  assert(Reg != 0 && "Invalid CR bit register");
> > -  return Reg;
> > -}
> > -
> >  void
> >  PPCRegisterInfo::lowerCRBitSpilling(MachineBasicBlock::iterator
> >  II,
> >                                           unsigned FrameIndex)
> >                                           const {
> >    // Get the instruction.
> > diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h
> > b/lib/Target/PowerPC/PPCRegisterInfo.h
> > index 4c2ef90..7f840f0 100644
> > --- a/lib/Target/PowerPC/PPCRegisterInfo.h
> > +++ b/lib/Target/PowerPC/PPCRegisterInfo.h
> > @@ -26,6 +26,39 @@ class PPCSubtarget;
> >  class TargetInstrInfo;
> >  class Type;
> > 
> > +
> > +inline static unsigned getCRFromCRBit(unsigned SrcReg) {
> > +  unsigned Reg = 0;
> > +  if (SrcReg == PPC::CR0LT || SrcReg == PPC::CR0GT ||
> > +      SrcReg == PPC::CR0EQ || SrcReg == PPC::CR0UN)
> > +    Reg = PPC::CR0;
> > +  else if (SrcReg == PPC::CR1LT || SrcReg == PPC::CR1GT ||
> > +           SrcReg == PPC::CR1EQ || SrcReg == PPC::CR1UN)
> > +    Reg = PPC::CR1;
> > +  else if (SrcReg == PPC::CR2LT || SrcReg == PPC::CR2GT ||
> > +           SrcReg == PPC::CR2EQ || SrcReg == PPC::CR2UN)
> > +    Reg = PPC::CR2;
> > +  else if (SrcReg == PPC::CR3LT || SrcReg == PPC::CR3GT ||
> > +           SrcReg == PPC::CR3EQ || SrcReg == PPC::CR3UN)
> > +    Reg = PPC::CR3;
> > +  else if (SrcReg == PPC::CR4LT || SrcReg == PPC::CR4GT ||
> > +           SrcReg == PPC::CR4EQ || SrcReg == PPC::CR4UN)
> > +    Reg = PPC::CR4;
> > +  else if (SrcReg == PPC::CR5LT || SrcReg == PPC::CR5GT ||
> > +           SrcReg == PPC::CR5EQ || SrcReg == PPC::CR5UN)
> > +    Reg = PPC::CR5;
> > +  else if (SrcReg == PPC::CR6LT || SrcReg == PPC::CR6GT ||
> > +           SrcReg == PPC::CR6EQ || SrcReg == PPC::CR6UN)
> > +    Reg = PPC::CR6;
> > +  else if (SrcReg == PPC::CR7LT || SrcReg == PPC::CR7GT ||
> > +           SrcReg == PPC::CR7EQ || SrcReg == PPC::CR7UN)
> > +    Reg = PPC::CR7;
> > +
> > +  assert(Reg != 0 && "Invalid CR bit register");
> > +  return Reg;
> > +}
> > +
> > +
> >  class PPCRegisterInfo : public PPCGenRegisterInfo {
> >    DenseMap<unsigned, unsigned> ImmToIdxMap;
> >    const PPCSubtarget &Subtarget;
> > diff --git a/lib/Target/PowerPC/PPCRegisterInfo.td
> > b/lib/Target/PowerPC/PPCRegisterInfo.td
> > index 9a7df96..6ca68ed 100644
> > --- a/lib/Target/PowerPC/PPCRegisterInfo.td
> > +++ b/lib/Target/PowerPC/PPCRegisterInfo.td
> > @@ -341,6 +341,8 @@ def CRBITRC : RegisterClass<"PPC", [i1], 32,
> >  def CRRC : RegisterClass<"PPC", [i32], 32, (add CR0, CR1, CR5,
> >  CR6,
> >                                                  CR7, CR2, CR3,
> >                                                  CR4)>;
> > 
> > +def CRRC0 : RegisterClass<"PPC", [i32], 32, (add CR0)>;
> > +
> >  // The CTR registers are not allocatable because they're used by
> >  the
> >  // decrement-and-branch instructions, and thus need to stay live
> >  across
> >  // multiple basic blocks.
> > diff --git a/lib/Target/PowerPC/PPCSubtarget.cpp
> > b/lib/Target/PowerPC/PPCSubtarget.cpp
> > index 02b721b..b261765 100644
> > --- a/lib/Target/PowerPC/PPCSubtarget.cpp
> > +++ b/lib/Target/PowerPC/PPCSubtarget.cpp
> > @@ -96,6 +96,7 @@ void PPCSubtarget::initializeEnvironment() {
> >    HasICBT = false;
> >    HasInvariantFunctionDescriptors = false;
> >    IsQPXStackUnaligned = false;
> > +  HasHTM = false;
> >  }
> > 
> >  void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef
> >  FS) {
> > diff --git a/lib/Target/PowerPC/PPCSubtarget.h
> > b/lib/Target/PowerPC/PPCSubtarget.h
> > index a74b5fb..f5ca015 100644
> > --- a/lib/Target/PowerPC/PPCSubtarget.h
> > +++ b/lib/Target/PowerPC/PPCSubtarget.h
> > @@ -114,6 +114,7 @@ protected:
> >    bool IsLittleEndian;
> >    bool HasICBT;
> >    bool HasInvariantFunctionDescriptors;
> > +  bool HasHTM;
> > 
> >    /// When targeting QPX running a stock PPC64 Linux kernel where
> >    the stack
> >    /// alignment has not been changed, we need to keep the 16-byte
> >    alignment
> > @@ -236,6 +237,7 @@ public:
> >    bool hasInvariantFunctionDescriptors() const {
> >      return HasInvariantFunctionDescriptors;
> >    }
> > +  bool hasHTM () const { return HasHTM; }
> > 
> >    bool isQPXStackUnaligned() const { return IsQPXStackUnaligned; }
> >    unsigned getPlatformStackAlignment() const {
> > diff --git a/test/CodeGen/PowerPC/htm.ll
> > b/test/CodeGen/PowerPC/htm.ll
> > new file mode 100644
> > index 0000000..60ea51b
> > --- /dev/null
> > +++ b/test/CodeGen/PowerPC/htm.ll
> > @@ -0,0 +1,125 @@
> > +; RUN: llc -mcpu=pwr8 -mattr=+htm < %s | FileCheck %s
> > +target datalayout = "E-m:e-i64:64-n32:64"
> > +target triple = "powerpc64-unknown-linux-gnu"
> > +
> > +define zeroext i32 @test1() {
> > +entry:
> > +  %0 = tail call i32 @llvm.ppc.tbegin(i32 0)
> > +  ret i32 %0
> > +
> > +; CHECK-LABEL: @test1
> > +; CHECK: tbegin. 0
> > +; CHECK: mfocrf  [[REGISTER:[0-9]+]], 128
> > +; CHECK: rlwinm  [[REGISTER]], [[REGISTER]], 3, 31, 31
> > +; CHECK: xori    [[REGISTER]], [[REGISTER]], 1
> > +}
> 
> This is overspecified and fragile.  It isn't necessarily the case
> that
> the same register will be assigned in all these cases.  There could
> be
> up to three different ones, so please rewrite accordingly.
> 
> > +
> > +declare i32 @llvm.ppc.tbegin(i32) #1
> > +
> > +
> > +define zeroext i32 @test2() {
> > +entry:
> > +  %0 = tail call i32 @llvm.ppc.tend(i32 0)
> > +  ret i32 %0
> > +; CHECK-LABEL: @test2
> > +; CHECK: tend. 0
> > +; CHECK: mfocrf  [[REGISTER:[0-9]+]], 128
> 
> You aren't reusing [[REGISTER]] anywhere, so please change this to
> {{[0-9]+}}.
> 
> > +}
> > +
> > +declare i32 @llvm.ppc.tend(i32)
> > +
> > +
> > +define void @test3() {
> > +entry:
> > +  %0 = tail call i32 @llvm.ppc.tabort(i32 0)
> > +  %1 = tail call i32 @llvm.ppc.tabortdc(i32 0, i32 1, i32 2)
> > +  %2 = tail call i32 @llvm.ppc.tabortdci(i32 0, i32 1, i32 2)
> > +  %3 = tail call i32 @llvm.ppc.tabortwc(i32 0, i32 1, i32 2)
> > +  %4 = tail call i32 @llvm.ppc.tabortwci(i32 0, i32 1, i32 2)
> > +  ret void
> > +; CHECK-LABEL: @test3
> > +; CHECK: tabort.    [[REG1:[0-9]+]]
> > +; CHECK: tabortdc.  0, [[REG2:[0-9]+]], [[REG3:[0-9]+]]
> > +; CHECK: tabortdci. 0, [[REG2]], 2
> > +; CHECK: tabortwc.  0, [[REG2]], [[REG3]]
> > +; CHECK: tabortwci. 0, [[REG2]], 2
> > +}
> 
> I can't tell for sure, but this looks too fragile as well -- are all
> of
> those REG2 instances really guaranteed to be the same register?  I
> believe you should just use {{[0-9]+}} for all of these.
> 
> Thanks,
> Bill
> 
> > +
> > +declare i32 @llvm.ppc.tabort(i32)
> > +declare i32 @llvm.ppc.tabortdc(i32, i32, i32)
> > +declare i32 @llvm.ppc.tabortdci(i32, i32, i32)
> > +declare i32 @llvm.ppc.tabortwc(i32, i32, i32)
> > +declare i32 @llvm.ppc.tabortwci(i32, i32, i32)
> > +
> > +
> > +define void @test4() {
> > +entry:
> > +  %0 = tail call i32 @llvm.ppc.tendall()
> > +  %1 = tail call i32 @llvm.ppc.tresume()
> > +  %2 = tail call i32 @llvm.ppc.tsuspend()
> > +  ret void
> > +; CHECK-LABEL: @test4
> > +; CHECK: tend. 1
> > +; CHECK: tsr.  1
> > +; CHECK: tsr.  0
> > +}
> > +
> > +declare i32 @llvm.ppc.tendall()
> > +declare i32 @llvm.ppc.tresume()
> > +declare i32 @llvm.ppc.tsuspend()
> > +
> > +
> > +define void @test5(i64 %v) {
> > +entry:
> > +  tail call void @llvm.ppc.set.texasr(i64 %v)
> > +  tail call void @llvm.ppc.set.texasru(i64 %v)
> > +  tail call void @llvm.ppc.set.tfhar(i64 %v)
> > +  tail call void @llvm.ppc.set.tfiar(i64 %v)
> > +  ret void
> > +; CHECK-LABEL: @test5
> > +; CHECK: mtspr 130, [[REG1:[0-9]+]]
> > +; CHECK: mtspr 131, [[REG2:[0-9]+]]
> > +; CHECK: mtspr 128, [[REG3:[0-9]+]]
> > +; CHECK: mtspr 129, [[REG4:[0-9]+]]
> > +}
> > +
> > +define i64 @test6() {
> > +entry:
> > +  %0 = tail call i64 @llvm.ppc.get.texasr()
> > +  ret i64 %0
> > +; CHECK-LABEL: @test6
> > +; CHECK: mfspr [[REG1:[0-9]+]], 130
> > +}
> > +
> > +define i64 @test7() {
> > +entry:
> > +  %0 = tail call i64 @llvm.ppc.get.texasru()
> > +  ret i64 %0
> > +; CHECK-LABEL: @test7
> > +; CHECK: mfspr [[REG1:[0-9]+]], 131
> > +}
> > +
> > +define i64 @test8() {
> > +entry:
> > +  %0 = tail call i64 @llvm.ppc.get.tfhar()
> > +  ret i64 %0
> > +; CHECK-LABEL: @test8
> > +; CHECK: mfspr [[REG1:[0-9]+]], 128
> > +}
> > +
> > +define i64 @test9() {
> > +entry:
> > +  %0 = tail call i64 @llvm.ppc.get.tfiar()
> > +  ret i64 %0
> > +; CHECK-LABEL: @test9
> > +; CHECK: mfspr [[REG1:[0-9]+]], 129
> > +}
> > +
> > +declare void @llvm.ppc.set.texasr(i64)
> > +declare void @llvm.ppc.set.texasru(i64)
> > +declare void @llvm.ppc.set.tfhar(i64)
> > +declare void @llvm.ppc.set.tfiar(i64)
> > +declare i64 @llvm.ppc.get.texasr()
> > +declare i64 @llvm.ppc.get.texasru()
> > +declare i64 @llvm.ppc.get.tfhar()
> > +declare i64 @llvm.ppc.get.tfiar()
> > diff --git a/test/MC/PowerPC/htm.s b/test/MC/PowerPC/htm.s
> > new file mode 100644
> > index 0000000..f99ff3c
> > --- /dev/null
> > +++ b/test/MC/PowerPC/htm.s
> > @@ -0,0 +1,53 @@
> > +# RUN: llvm-mc -triple powerpc64-unknown-linux-gnu --show-encoding
> > %s | FileCheck -check-prefix=CHECK-BE %s
> > +# RUN: llvm-mc -triple powerpc64le-unknown-linux-gnu
> > --show-encoding %s | FileCheck -check-prefix=CHECK-LE %s
> > +
> > +# CHECK-BE: tbegin. 0                      # encoding:
> > [0x7c,0x00,0x05,0x1d]
> > +# CHECK-LE: tbegin. 0                      # encoding:
> > [0x1d,0x05,0x00,0x7c]
> > +            tbegin. 0
> > +# CHECK-BE: tbegin. 1                      # encoding:
> > [0x7c,0x20,0x05,0x1d]
> > +# CHECK-LE: tbegin. 1                      # encoding:
> > [0x1d,0x05,0x20,0x7c]
> > +            tbegin. 1
> > +
> > +# CHECK-BE: tend. 0                        # encoding:
> > [0x7c,0x00,0x05,0x5d]
> > +# CHECK-LE: tend. 0                        # encoding:
> > [0x5d,0x05,0x00,0x7c]
> > +            tend. 0
> > +# CHECK-BE: tend. 1                        # encoding:
> > [0x7e,0x00,0x05,0x5d]
> > +# CHECK-LE: tend. 1                        # encoding:
> > [0x5d,0x05,0x00,0x7e]
> > +            tend. 1
> > +
> > +# CHECK-BE: tabort. 9                      # encoding:
> > [0x7c,0x09,0x07,0x1d]
> > +# CHECK-LE: tabort. 9                      # encoding:
> > [0x1d,0x07,0x09,0x7c]
> > +            tabort. 9
> > +# CHECK-BE: tabortdc. 0, 9, 9              # encoding:
> > [0x7c,0x09,0x4e,0x5d]
> > +# CHECK-LE: tabortdc. 0, 9, 9              # encoding:
> > [0x5d,0x4e,0x09,0x7c]
> > +            tabortdc. 0, 9, 9
> > +# CHECK-BE: tabortdci. 0, 9, 0             # encoding:
> > [0x7c,0x09,0x06,0xdd]
> > +# CHECK-LE: tabortdci. 0, 9, 0             # encoding:
> > [0xdd,0x06,0x09,0x7c]
> > +            tabortdci. 0, 9, 0
> > +# CHECK-BE: tabortwc. 0, 9, 9              # encoding:
> > [0x7c,0x09,0x4e,0x1d]
> > +# CHECK-LE: tabortwc. 0, 9, 9              # encoding:
> > [0x1d,0x4e,0x09,0x7c]
> > +            tabortwc. 0, 9, 9
> > +# CHECK-BE: tabortwci. 0, 9, 0             # encoding:
> > [0x7c,0x09,0x06,0x9d]
> > +# CHECK-LE: tabortwci. 0, 9, 0             # encoding:
> > [0x9d,0x06,0x09,0x7c]
> > +            tabortwci. 0, 9, 0
> > +
> > +# CHECK-BE: tsr. 0                         # encoding:
> > [0x7c,0x00,0x05,0xdd]
> > +# CHECK-LE: tsr. 0                         # encoding:
> > [0xdd,0x05,0x00,0x7c]
> > +            tsr. 0
> > +# CHECK-BE: tsr. 1                         # encoding:
> > [0x7c,0x20,0x05,0xdd]
> > +# CHECK-LE: tsr. 1                         # encoding:
> > [0xdd,0x05,0x20,0x7c]
> > +            tsr. 1
> > +
> > +# CHECK-BE: tcheck 0                       # encoding:
> > [0x7c,0x00,0x05,0x9c]
> > +# CHECK-LE: tcheck 0                       # encoding:
> > [0x9c,0x05,0x00,0x7c]
> > +            tcheck 0
> > +# CHECK-BE: tcheck 3                       # encoding:
> > [0x7d,0x80,0x05,0x9c]
> > +# CHECK-LE: tcheck 3                       # encoding:
> > [0x9c,0x05,0x80,0x7d]
> > +            tcheck 3
> > +
> > +# CHECK-BE: treclaim. 9                    # encoding:
> > [0x7c,0x09,0x07,0x5d]
> > +# CHECK-LE: treclaim. 9                    # encoding:
> > [0x5d,0x07,0x09,0x7c]
> > +            treclaim. 9
> > +# CHECK-BE: trechkpt.                      # encoding:
> > [0x7c,0x00,0x07,0xdd]
> > +# CHECK-LE: trechkpt.                      # encoding:
> > [0xdd,0x07,0x00,0x7c]
> > +            trechkpt.
> > 
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> > 
> 
> 
> 

-- 
Hal Finkel
Assistant Computational Scientist
Leadership Computing Facility
Argonne National Laboratory



More information about the llvm-commits mailing list