Skip to content

Commit

Permalink
[VE] Add lvm/svm intrinsic instructions
Browse files Browse the repository at this point in the history
Add lvm/svm intrinsic instructions and a regression test.  Change
RegisterInfo to specify that VM0/VMP0 are constant and reserved
registers.  This modifies a vst regression test, so update it.
Also add pseudo instructions for VM512 register classes
and mechanism to expand them after register allocation.

Reviewed By: simoll

Differential Revision: https://reviews.llvm.org/D91541
  • Loading branch information
kaz7 committed Nov 16, 2020
1 parent c7cbf32 commit 38621c4
Show file tree
Hide file tree
Showing 7 changed files with 219 additions and 49 deletions.
4 changes: 4 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsVEVL.gen.td
Expand Up @@ -84,3 +84,7 @@ let TargetPrefix = "ve" in def int_ve_vl_lsv_vvss : GCCBuiltin<"__builtin_ve_vl_
let TargetPrefix = "ve" in def int_ve_vl_lvsl_svs : GCCBuiltin<"__builtin_ve_vl_lvsl_svs">, Intrinsic<[LLVMType<i64>], [LLVMType<v256f64>, LLVMType<i32>], [IntrNoMem]>;
let TargetPrefix = "ve" in def int_ve_vl_lvsd_svs : GCCBuiltin<"__builtin_ve_vl_lvsd_svs">, Intrinsic<[LLVMType<f64>], [LLVMType<v256f64>, LLVMType<i32>], [IntrNoMem]>;
let TargetPrefix = "ve" in def int_ve_vl_lvss_svs : GCCBuiltin<"__builtin_ve_vl_lvss_svs">, Intrinsic<[LLVMType<f32>], [LLVMType<v256f64>, LLVMType<i32>], [IntrNoMem]>;
let TargetPrefix = "ve" in def int_ve_vl_lvm_mmss : GCCBuiltin<"__builtin_ve_vl_lvm_mmss">, Intrinsic<[LLVMType<v256i1>], [LLVMType<v256i1>, LLVMType<i64>, LLVMType<i64>], [IntrNoMem]>;
let TargetPrefix = "ve" in def int_ve_vl_lvm_MMss : GCCBuiltin<"__builtin_ve_vl_lvm_MMss">, Intrinsic<[LLVMType<v512i1>], [LLVMType<v512i1>, LLVMType<i64>, LLVMType<i64>], [IntrNoMem]>;
let TargetPrefix = "ve" in def int_ve_vl_svm_sms : GCCBuiltin<"__builtin_ve_vl_svm_sms">, Intrinsic<[LLVMType<i64>], [LLVMType<v256i1>, LLVMType<i64>], [IntrNoMem]>;
let TargetPrefix = "ve" in def int_ve_vl_svm_sMs : GCCBuiltin<"__builtin_ve_vl_svm_sMs">, Intrinsic<[LLVMType<i64>], [LLVMType<v512i1>, LLVMType<i64>], [IntrNoMem]>;
84 changes: 84 additions & 0 deletions llvm/lib/Target/VE/VEInstrInfo.cpp
Expand Up @@ -717,6 +717,12 @@ Register VEInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
return GlobalBaseReg;
}

static Register getVM512Upper(Register reg) {
return (reg - VE::VMP0) * 2 + VE::VM0;
}

static Register getVM512Lower(Register reg) { return getVM512Upper(reg) + 1; }

bool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
switch (MI.getOpcode()) {
case VE::EXTEND_STACK: {
Expand All @@ -729,6 +735,84 @@ bool VEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
case VE::GETSTACKTOP: {
return expandGetStackTopPseudo(MI);
}

case VE::LVMyir:
case VE::LVMyim:
case VE::LVMyir_y:
case VE::LVMyim_y: {
Register VMXu = getVM512Upper(MI.getOperand(0).getReg());
Register VMXl = getVM512Lower(MI.getOperand(0).getReg());
int64_t Imm = MI.getOperand(1).getImm();
bool IsSrcReg =
MI.getOpcode() == VE::LVMyir || MI.getOpcode() == VE::LVMyir_y;
Register Src = IsSrcReg ? MI.getOperand(2).getReg() : VE::NoRegister;
int64_t MImm = IsSrcReg ? 0 : MI.getOperand(2).getImm();
bool KillSrc = IsSrcReg ? MI.getOperand(2).isKill() : false;
Register VMX = VMXl;
if (Imm >= 4) {
VMX = VMXu;
Imm -= 4;
}
MachineBasicBlock *MBB = MI.getParent();
DebugLoc DL = MI.getDebugLoc();
switch (MI.getOpcode()) {
case VE::LVMyir:
BuildMI(*MBB, MI, DL, get(VE::LVMir))
.addDef(VMX)
.addImm(Imm)
.addReg(Src, getKillRegState(KillSrc));
break;
case VE::LVMyim:
BuildMI(*MBB, MI, DL, get(VE::LVMim))
.addDef(VMX)
.addImm(Imm)
.addImm(MImm);
break;
case VE::LVMyir_y:
assert(MI.getOperand(0).getReg() == MI.getOperand(3).getReg() &&
"LVMyir_y has different register in 3rd operand");
BuildMI(*MBB, MI, DL, get(VE::LVMir_m))
.addDef(VMX)
.addImm(Imm)
.addReg(Src, getKillRegState(KillSrc))
.addReg(VMX);
break;
case VE::LVMyim_y:
assert(MI.getOperand(0).getReg() == MI.getOperand(3).getReg() &&
"LVMyim_y has different register in 3rd operand");
BuildMI(*MBB, MI, DL, get(VE::LVMim_m))
.addDef(VMX)
.addImm(Imm)
.addImm(MImm)
.addReg(VMX);
break;
}
MI.eraseFromParent();
return true;
}
case VE::SVMyi: {
Register Dest = MI.getOperand(0).getReg();
Register VMZu = getVM512Upper(MI.getOperand(1).getReg());
Register VMZl = getVM512Lower(MI.getOperand(1).getReg());
bool KillSrc = MI.getOperand(1).isKill();
int64_t Imm = MI.getOperand(2).getImm();
Register VMZ = VMZl;
if (Imm >= 4) {
VMZ = VMZu;
Imm -= 4;
}
MachineBasicBlock *MBB = MI.getParent();
DebugLoc DL = MI.getDebugLoc();
MachineInstrBuilder MIB =
BuildMI(*MBB, MI, DL, get(VE::SVMmi), Dest).addReg(VMZ).addImm(Imm);
MachineInstr *Inst = MIB.getInstr();
MI.eraseFromParent();
if (KillSrc) {
const TargetRegisterInfo *TRI = &getRegisterInfo();
Inst->addRegisterKilled(MI.getOperand(1).getReg(), TRI, true);
}
return true;
}
}
return false;
}
Expand Down
4 changes: 4 additions & 0 deletions llvm/lib/Target/VE/VEInstrIntrinsicVL.gen.td
Expand Up @@ -162,3 +162,7 @@ def : Pat<(int_ve_vl_pfchv_ssl i64:$sy, i64:$sz, i32:$vl), (PFCHVrrl i64:$sy, i6
def : Pat<(int_ve_vl_pfchv_ssl simm7:$I, i64:$sz, i32:$vl), (PFCHVirl (LO7 $I), i64:$sz, i32:$vl)>;
def : Pat<(int_ve_vl_pfchvnc_ssl i64:$sy, i64:$sz, i32:$vl), (PFCHVNCrrl i64:$sy, i64:$sz, i32:$vl)>;
def : Pat<(int_ve_vl_pfchvnc_ssl simm7:$I, i64:$sz, i32:$vl), (PFCHVNCirl (LO7 $I), i64:$sz, i32:$vl)>;
def : Pat<(int_ve_vl_lvm_mmss v256i1:$ptm, uimm6:$N, i64:$sz), (LVMir_m (ULO7 $N), i64:$sz, v256i1:$ptm)>;
def : Pat<(int_ve_vl_lvm_MMss v512i1:$ptm, uimm6:$N, i64:$sz), (LVMyir_y (ULO7 $N), i64:$sz, v512i1:$ptm)>;
def : Pat<(int_ve_vl_svm_sms v256i1:$vmz, uimm6:$N), (SVMmi v256i1:$vmz, (ULO7 $N))>;
def : Pat<(int_ve_vl_svm_sMs v512i1:$vmz, uimm6:$N), (SVMyi v512i1:$vmz, (ULO7 $N))>;
20 changes: 20 additions & 0 deletions llvm/lib/Target/VE/VEInstrVec.td
Expand Up @@ -2,6 +2,26 @@
// Vector Instructions
//===----------------------------------------------------------------------===//

// Pseudo instructions for VM512 modifications
//
// Specifies hasSideEffects = 0 to disable UnmodeledSideEffects.

let hasSideEffects = 0 in {
let Constraints = "$vx = $vd", DisableEncoding = "$vd" in {
def LVMyir_y : Pseudo<(outs VM512:$vx), (ins uimm3:$sy, I64:$sz, VM512:$vd),
"# pseudo LVM $vx, $sy, $sz, $vd">;
def LVMyim_y : Pseudo<(outs VM512:$vx),
(ins uimm3:$sy, mimm:$sz, VM512:$vd),
"# pseudo LVM $vx, $sy, $sz, $vd">;
}
def LVMyir : Pseudo<(outs VM512:$vx), (ins uimm3:$sy, I64:$sz),
"# pseudo LVM $vx, $sy, $sz">;
def LVMyim : Pseudo<(outs VM512:$vx), (ins uimm3:$sy, mimm:$sz),
"# pseudo LVM $vx, $sy, $sz">;
def SVMyi : Pseudo<(outs I64:$sx), (ins VM512:$vz, uimm3:$sy),
"# pseudo SVM $sx, $vz, $sy">;
}

//===----------------------------------------------------------------------===//
// Instructions
//
Expand Down
14 changes: 13 additions & 1 deletion llvm/lib/Target/VE/VERegisterInfo.cpp
Expand Up @@ -86,10 +86,22 @@ BitVector VERegisterInfo::getReservedRegs(const MachineFunction &MF) const {
++ItAlias)
Reserved.set(*ItAlias);

// Reserve constant registers.
Reserved.set(VE::VM0);
Reserved.set(VE::VMP0);

return Reserved;
}

bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const { return false; }
bool VERegisterInfo::isConstantPhysReg(MCRegister PhysReg) const {
switch (PhysReg) {
case VE::VM0:
case VE::VMP0:
return true;
default:
return false;
}
}

const TargetRegisterClass *
VERegisterInfo::getPointerRegClass(const MachineFunction &MF,
Expand Down
46 changes: 46 additions & 0 deletions llvm/test/CodeGen/VE/VELIntrinsics/lvm.ll
@@ -0,0 +1,46 @@
; RUN: llc < %s -mtriple=ve -mattr=+vpu | FileCheck %s

;;; Test load/save vector mask intrinsic instructions
;;;
;;; Note:
;;; We test LVMir_m, LVMyir_y, SVMmi, and SVMyi instructions.

; Function Attrs: nounwind readnone
define i64 @lvm_mmss(i8* nocapture readnone %0, i64 %1) {
; CHECK-LABEL: lvm_mmss:
; CHECK: # %bb.0:
; CHECK-NEXT: lvm %vm1, 3, %s1
; CHECK-NEXT: svm %s0, %vm1, 3
; CHECK-NEXT: b.l.t (, %s10)
%3 = tail call <256 x i1> @llvm.ve.vl.lvm.mmss(<256 x i1> undef, i64 3, i64 %1)
%4 = tail call i64 @llvm.ve.vl.svm.sms(<256 x i1> %3, i64 3)
ret i64 %4
}

; Function Attrs: nounwind readnone
declare <256 x i1> @llvm.ve.vl.lvm.mmss(<256 x i1>, i64, i64)

; Function Attrs: nounwind readnone
declare i64 @llvm.ve.vl.svm.sms(<256 x i1>, i64)

; Function Attrs: nounwind readnone
define i64 @lvml_MMss(i8* nocapture readnone %0, i64 %1) {
; CHECK-LABEL: lvml_MMss:
; CHECK: # %bb.0:
; CHECK-NEXT: lvm %vm2, 1, %s1
; CHECK-NEXT: svm %s0, %vm3, 3
; CHECK-NEXT: svm %s1, %vm2, 2
; CHECK-NEXT: adds.l %s0, %s1, %s0
; CHECK-NEXT: b.l.t (, %s10)
%3 = tail call <512 x i1> @llvm.ve.vl.lvm.MMss(<512 x i1> undef, i64 5, i64 %1)
%4 = tail call i64 @llvm.ve.vl.svm.sMs(<512 x i1> %3, i64 3)
%5 = tail call i64 @llvm.ve.vl.svm.sMs(<512 x i1> %3, i64 6)
%6 = add i64 %5, %4
ret i64 %6
}

; Function Attrs: nounwind readnone
declare <512 x i1> @llvm.ve.vl.lvm.MMss(<512 x i1>, i64, i64)

; Function Attrs: nounwind readnone
declare i64 @llvm.ve.vl.svm.sMs(<512 x i1>, i64)

0 comments on commit 38621c4

Please sign in to comment.