53 changes: 53 additions & 0 deletions llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,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,
Expand Down Expand Up @@ -741,6 +768,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;
Expand Down
13 changes: 13 additions & 0 deletions llvm/lib/Target/PowerPC/PPCInstrInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ 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";
Expand All @@ -451,6 +454,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";
Expand Down Expand Up @@ -2708,6 +2720,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)>;
Expand Down
31 changes: 0 additions & 31 deletions llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,37 +524,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.
Expand Down
33 changes: 33 additions & 0 deletions llvm/lib/Target/PowerPC/PPCRegisterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,39 @@
#include "PPCGenRegisterInfo.inc"

namespace llvm {

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 PPCTargetMachine &TM;
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/PowerPC/PPCRegisterInfo.td
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/PowerPC/PPCSubtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ void PPCSubtarget::initializeEnvironment() {
HasInvariantFunctionDescriptors = false;
HasPartwordAtomics = false;
IsQPXStackUnaligned = false;
HasHTM = false;
}

void PPCSubtarget::initSubtargetFeatures(StringRef CPU, StringRef FS) {
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/PowerPC/PPCSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class PPCSubtarget : public PPCGenSubtargetInfo {
bool HasICBT;
bool HasInvariantFunctionDescriptors;
bool HasPartwordAtomics;
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
Expand Down Expand Up @@ -246,6 +247,7 @@ class PPCSubtarget : public PPCGenSubtargetInfo {

return 16;
}
bool hasHTM() const { return HasHTM; }

const Triple &getTargetTriple() const { return TargetTriple; }

Expand Down
125 changes: 125 additions & 0 deletions llvm/test/CodeGen/PowerPC/htm.ll
Original file line number Diff line number Diff line change
@@ -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 [[REGISTER1:[0-9]+]], 128
; CHECK: rlwinm [[REGISTER2:[0-9]+]], [[REGISTER1]], 3, 31, 31
; CHECK: xori {{[0-9]+}}, [[REGISTER2]], 1
}

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 {{[0-9]+}}, 128
}

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. {{[0-9]+}}
; CHECK: tabortdc. 0, {{[0-9]+}}, {{[0-9]+}}
; CHECK: tabortdci. 0, {{[0-9]+}}, 2
; CHECK: tabortwc. 0, {{[0-9]+}}, {{[0-9]+}}
; CHECK: tabortwci. 0, {{[0-9]+}}, 2
}

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()
53 changes: 53 additions & 0 deletions llvm/test/MC/PowerPC/htm.s
Original file line number Diff line number Diff line change
@@ -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.