1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[VE] Support f128

Support f128 using VE instructions.  Update regression tests.
I've noticed there is no load or store i128 test, so I add them too.

Reviewed By: simoll

Differential Revision: https://reviews.llvm.org/D86035
This commit is contained in:
Kazushi (Jam) Marukawa 2020-06-27 19:08:09 +09:00
parent 1eb4fcbf00
commit efd49fca73
19 changed files with 703 additions and 81 deletions

View File

@ -14,6 +14,9 @@
// Aurora VE
//===----------------------------------------------------------------------===//
def CC_VE_C_Stack: CallingConv<[
// F128 are assigned to the stack in 16-byte aligned units
CCIfType<[f128], CCAssignToStackWithShadow<16, 16, [SX7]>>,
// All of the rest are assigned to the stack in 8-byte aligned units.
CCAssignToStack<0, 8>
]>;
@ -36,6 +39,14 @@ def CC_VE : CallingConv<[
CCIfType<[i64, f64],
CCAssignToReg<[SX0, SX1, SX2, SX3, SX4, SX5, SX6, SX7]>>,
// long double --> pair of generic 64 bit registers
//
// NOTE: If Q1 is allocated while SX1 is free, llvm tries to allocate SX1 for
// following operands, this masks SX1 to avoid such behavior.
CCIfType<[f128],
CCAssignToRegWithShadow<[Q0, Q1, Q2, Q3],
[SX0, SX1, SX3, SX5]>>,
// Alternatively, they are assigned to the stack in 8-byte aligned units.
CCDelegateTo<CC_VE_C_Stack>
]>;
@ -53,6 +64,9 @@ def CC_VE2 : CallingConv<[
// +------+------+
CCIfType<[f32], CCBitConvertToType<i64>>,
// F128 are assigned to the stack in 16-byte aligned units
CCIfType<[f128], CCAssignToStack<16, 16>>,
CCAssignToStack<0, 8>
]>;
@ -71,6 +85,11 @@ def RetCC_VE : CallingConv<[
// --> generic 64 bit registers
CCIfType<[i64, f64],
CCAssignToReg<[SX0, SX1, SX2, SX3, SX4, SX5, SX6, SX7]>>,
// long double --> pair of generic 64 bit registers
CCIfType<[f128],
CCAssignToRegWithShadow<[Q0, Q1, Q2, Q3],
[SX0, SX1, SX3, SX5]>>,
]>;
// Callee-saved registers

View File

@ -554,6 +554,15 @@ SDValue VETargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
return Chain;
}
bool VETargetLowering::isOffsetFoldingLegal(
const GlobalAddressSDNode *GA) const {
// VE uses 64 bit addressing, so we need multiple instructions to generate
// an address. Folding address with offset increases the number of
// instructions, so that we disable it here. Offsets will be folded in
// the DAG combine later if it worth to do so.
return false;
}
/// isFPImmLegal - Returns true if the target can instruction select the
/// specified FP immediate natively. If false, the legalizer will
/// materialize the FP immediate as a load from a constant pool.
@ -623,6 +632,7 @@ VETargetLowering::VETargetLowering(const TargetMachine &TM,
addRegisterClass(MVT::i64, &VE::I64RegClass);
addRegisterClass(MVT::f32, &VE::F32RegClass);
addRegisterClass(MVT::f64, &VE::I64RegClass);
addRegisterClass(MVT::f128, &VE::F128RegClass);
/// Load & Store {
for (MVT FPVT : MVT::fp_valuetypes()) {
@ -649,6 +659,7 @@ VETargetLowering::VETargetLowering(const TargetMachine &TM,
setOperationAction(ISD::BlockAddress, PtrVT, Custom);
setOperationAction(ISD::GlobalAddress, PtrVT, Custom);
setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom);
setOperationAction(ISD::ConstantPool, PtrVT, Custom);
/// VAARG handling {
setOperationAction(ISD::VASTART, MVT::Other, Custom);
@ -719,6 +730,21 @@ VETargetLowering::VETargetLowering(const TargetMachine &TM,
}
/// } Conversion
/// Floating-point Ops {
// VE doesn't have fdiv of f128.
setOperationAction(ISD::FDIV, MVT::f128, Expand);
// VE doesn't have load/store of f128, so use custom-lowering.
setOperationAction(ISD::LOAD, MVT::f128, Custom);
setOperationAction(ISD::STORE, MVT::f128, Custom);
for (MVT FPVT : {MVT::f32, MVT::f64}) {
// f32 and f64 uses ConstantFP. f128 uses ConstantPool.
setOperationAction(ISD::ConstantFP, FPVT, Legal);
}
/// } Floating-point Ops
setStackPointerRegisterToSaveRestore(VE::SX11);
// We have target-specific dag combine patterns for the following nodes:
@ -769,6 +795,10 @@ SDValue VETargetLowering::withTargetFlags(SDValue Op, unsigned TF,
return DAG.getTargetBlockAddress(BA->getBlockAddress(), Op.getValueType(),
0, TF);
if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op))
return DAG.getTargetConstantPool(CP->getConstVal(), CP->getValueType(0),
CP->getAlign(), CP->getOffset(), TF);
if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op))
return DAG.getTargetExternalSymbol(ES->getSymbol(), ES->getValueType(0),
TF);
@ -853,6 +883,11 @@ SDValue VETargetLowering::LowerBlockAddress(SDValue Op,
return makeAddress(Op, DAG);
}
SDValue VETargetLowering::lowerConstantPool(SDValue Op,
SelectionDAG &DAG) const {
return makeAddress(Op, DAG);
}
SDValue
VETargetLowering::LowerToTLSGeneralDynamicModel(SDValue Op,
SelectionDAG &DAG) const {
@ -903,6 +938,118 @@ SDValue VETargetLowering::LowerGlobalTLSAddress(SDValue Op,
return LowerToTLSGeneralDynamicModel(Op, DAG);
}
// Lower a f128 load into two f64 loads.
static SDValue lowerLoadF128(SDValue Op, SelectionDAG &DAG) {
SDLoc DL(Op);
LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode());
assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type");
unsigned Alignment = LdNode->getAlign().value();
if (Alignment > 8)
Alignment = 8;
SDValue Lo64 =
DAG.getLoad(MVT::f64, DL, LdNode->getChain(), LdNode->getBasePtr(),
LdNode->getPointerInfo(), Alignment,
LdNode->isVolatile() ? MachineMemOperand::MOVolatile
: MachineMemOperand::MONone);
EVT AddrVT = LdNode->getBasePtr().getValueType();
SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, LdNode->getBasePtr(),
DAG.getConstant(8, DL, AddrVT));
SDValue Hi64 =
DAG.getLoad(MVT::f64, DL, LdNode->getChain(), HiPtr,
LdNode->getPointerInfo(), Alignment,
LdNode->isVolatile() ? MachineMemOperand::MOVolatile
: MachineMemOperand::MONone);
SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32);
SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32);
// VE stores Hi64 to 8(addr) and Lo64 to 0(addr)
SDNode *InFP128 =
DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::f128);
InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128,
SDValue(InFP128, 0), Hi64, SubRegEven);
InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128,
SDValue(InFP128, 0), Lo64, SubRegOdd);
SDValue OutChains[2] = {SDValue(Lo64.getNode(), 1),
SDValue(Hi64.getNode(), 1)};
SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
SDValue Ops[2] = {SDValue(InFP128, 0), OutChain};
return DAG.getMergeValues(Ops, DL);
}
SDValue VETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode());
SDValue BasePtr = LdNode->getBasePtr();
if (isa<FrameIndexSDNode>(BasePtr.getNode())) {
// Do not expand store instruction with frame index here because of
// dependency problems. We expand it later in eliminateFrameIndex().
return Op;
}
EVT MemVT = LdNode->getMemoryVT();
if (MemVT == MVT::f128)
return lowerLoadF128(Op, DAG);
return Op;
}
// Lower a f128 store into two f64 stores.
static SDValue lowerStoreF128(SDValue Op, SelectionDAG &DAG) {
SDLoc DL(Op);
StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode());
assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type");
SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32);
SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32);
SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64,
StNode->getValue(), SubRegEven);
SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64,
StNode->getValue(), SubRegOdd);
unsigned Alignment = StNode->getAlign().value();
if (Alignment > 8)
Alignment = 8;
// VE stores Hi64 to 8(addr) and Lo64 to 0(addr)
SDValue OutChains[2];
OutChains[0] =
DAG.getStore(StNode->getChain(), DL, SDValue(Lo64, 0),
StNode->getBasePtr(), MachinePointerInfo(), Alignment,
StNode->isVolatile() ? MachineMemOperand::MOVolatile
: MachineMemOperand::MONone);
EVT AddrVT = StNode->getBasePtr().getValueType();
SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, StNode->getBasePtr(),
DAG.getConstant(8, DL, AddrVT));
OutChains[1] =
DAG.getStore(StNode->getChain(), DL, SDValue(Hi64, 0), HiPtr,
MachinePointerInfo(), Alignment,
StNode->isVolatile() ? MachineMemOperand::MOVolatile
: MachineMemOperand::MONone);
return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
}
SDValue VETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
StoreSDNode *StNode = cast<StoreSDNode>(Op.getNode());
assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type");
SDValue BasePtr = StNode->getBasePtr();
if (isa<FrameIndexSDNode>(BasePtr.getNode())) {
// Do not expand store instruction with frame index here because of
// dependency problems. We expand it later in eliminateFrameIndex().
return Op;
}
EVT MemVT = StNode->getMemoryVT();
if (MemVT == MVT::f128)
return lowerStoreF128(Op, DAG);
// Otherwise, ask llvm to expand it.
return SDValue();
}
SDValue VETargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>();
@ -935,7 +1082,19 @@ SDValue VETargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG) const {
SDValue Chain = VAList.getValue(1);
SDValue NextPtr;
if (VT == MVT::f32) {
if (VT == MVT::f128) {
// VE f128 values must be stored with 16 bytes alignment. We doesn't
// know the actual alignment of VAList, so we take alignment of it
// dyanmically.
int Align = 16;
VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList,
DAG.getConstant(Align - 1, DL, PtrVT));
VAList = DAG.getNode(ISD::AND, DL, PtrVT, VAList,
DAG.getConstant(-Align, DL, PtrVT));
// Increment the pointer, VAList, by 16 to the next vaarg.
NextPtr =
DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(16, DL));
} else if (VT == MVT::f32) {
// float --> need special handling like below.
// 0 4
// +------+------+
@ -1034,12 +1193,18 @@ SDValue VETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
llvm_unreachable("Should not custom lower this!");
case ISD::BlockAddress:
return LowerBlockAddress(Op, DAG);
case ISD::ConstantPool:
return lowerConstantPool(Op, DAG);
case ISD::DYNAMIC_STACKALLOC:
return lowerDYNAMIC_STACKALLOC(Op, DAG);
case ISD::GlobalAddress:
return LowerGlobalAddress(Op, DAG);
case ISD::GlobalTLSAddress:
return LowerGlobalTLSAddress(Op, DAG);
case ISD::LOAD:
return lowerLOAD(Op, DAG);
case ISD::STORE:
return lowerSTORE(Op, DAG);
case ISD::VASTART:
return LowerVASTART(Op, DAG);
case ISD::VAARG:

View File

@ -80,8 +80,11 @@ public:
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerVAARG(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerToTLSGeneralDynamicModel(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
/// } Custom Lower
@ -97,6 +100,7 @@ public:
SelectionDAG &DAG) const;
SDValue makeAddress(SDValue Op, SelectionDAG &DAG) const;
bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
bool isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const override;
/// Returns true if the target allows unaligned memory accesses of the

View File

@ -315,6 +315,34 @@ static bool IsAliasOfSX(Register Reg) {
VE::F32RegClass.contains(Reg);
}
static void copyPhysSubRegs(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I, const DebugLoc &DL,
MCRegister DestReg, MCRegister SrcReg, bool KillSrc,
const MCInstrDesc &MCID, unsigned int NumSubRegs,
const unsigned *SubRegIdx,
const TargetRegisterInfo *TRI) {
MachineInstr *MovMI = nullptr;
for (unsigned Idx = 0; Idx != NumSubRegs; ++Idx) {
Register SubDest = TRI->getSubReg(DestReg, SubRegIdx[Idx]);
Register SubSrc = TRI->getSubReg(SrcReg, SubRegIdx[Idx]);
assert(SubDest && SubSrc && "Bad sub-register");
if (MCID.getOpcode() == VE::ORri) {
// generate "ORri, dest, src, 0" instruction.
MachineInstrBuilder MIB =
BuildMI(MBB, I, DL, MCID, SubDest).addReg(SubSrc).addImm(0);
MovMI = MIB.getInstr();
} else {
llvm_unreachable("Unexpected reg-to-reg copy instruction");
}
}
// Add implicit super-register defs and kills to the last MovMI.
MovMI->addRegisterDefined(DestReg, TRI);
if (KillSrc)
MovMI->addRegisterKilled(SrcReg, TRI, true);
}
void VEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I, const DebugLoc &DL,
MCRegister DestReg, MCRegister SrcReg,
@ -324,6 +352,12 @@ void VEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
BuildMI(MBB, I, DL, get(VE::ORri), DestReg)
.addReg(SrcReg, getKillRegState(KillSrc))
.addImm(0);
} else if (VE::F128RegClass.contains(DestReg, SrcReg)) {
// Use two instructions.
const unsigned SubRegIdx[] = {VE::sub_even, VE::sub_odd};
unsigned int NumSubRegs = 2;
copyPhysSubRegs(MBB, I, DL, DestReg, SrcReg, KillSrc, get(VE::ORri),
NumSubRegs, SubRegIdx, &getRegisterInfo());
} else {
const TargetRegisterInfo *TRI = &getRegisterInfo();
dbgs() << "Impossible reg-to-reg copy from " << printReg(SrcReg, TRI)
@ -341,7 +375,8 @@ unsigned VEInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
if (MI.getOpcode() == VE::LDrii || // I64
MI.getOpcode() == VE::LDLSXrii || // I32
MI.getOpcode() == VE::LDUrii // F32
MI.getOpcode() == VE::LDUrii || // F32
MI.getOpcode() == VE::LDQrii // F128 (pseudo)
) {
if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
MI.getOperand(2).getImm() == 0 && MI.getOperand(3).isImm() &&
@ -362,7 +397,8 @@ unsigned VEInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
if (MI.getOpcode() == VE::STrii || // I64
MI.getOpcode() == VE::STLrii || // I32
MI.getOpcode() == VE::STUrii // F32
MI.getOpcode() == VE::STUrii || // F32
MI.getOpcode() == VE::STQrii // F128 (pseudo)
) {
if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&
MI.getOperand(1).getImm() == 0 && MI.getOperand(2).isImm() &&
@ -411,6 +447,13 @@ void VEInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
.addImm(0)
.addReg(SrcReg, getKillRegState(isKill))
.addMemOperand(MMO);
} else if (VE::F128RegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(VE::STQrii))
.addFrameIndex(FI)
.addImm(0)
.addImm(0)
.addReg(SrcReg, getKillRegState(isKill))
.addMemOperand(MMO);
} else
report_fatal_error("Can't store this register to stack slot");
}
@ -448,6 +491,12 @@ void VEInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
.addImm(0)
.addImm(0)
.addMemOperand(MMO);
} else if (VE::F128RegClass.hasSubClassEq(RC)) {
BuildMI(MBB, I, DL, get(VE::LDQrii), DestReg)
.addFrameIndex(FI)
.addImm(0)
.addImm(0)
.addMemOperand(MMO);
} else
report_fatal_error("Can't load this register from stack slot");
}

View File

@ -986,6 +986,13 @@ defm LD1BSX : LOADm<"ld1b.sx", 0x05, I32, i32, sextloadi8>;
let cx = 1, DecoderMethod = "DecodeLoadI32" in
defm LD1BZX : LOADm<"ld1b.zx", 0x05, I32, i32, zextloadi8>;
// LDQ pseudo instructions
let mayLoad = 1, hasSideEffects = 0 in {
def LDQrii : Pseudo<(outs F128:$dest), (ins MEMrii:$addr),
"# pseudo ldq $dest, $addr",
[(set f128:$dest, (load ADDRrii:$addr))]>;
}
// Multiclass for store instructions.
let mayStore = 1 in
multiclass STOREm<string opcStr, bits<8> opc, RegisterClass RC, ValueType Ty,
@ -1031,6 +1038,13 @@ defm ST2B : STOREm<"st2b", 0x14, I32, i32, truncstorei16>;
let DecoderMethod = "DecodeStoreI32" in
defm ST1B : STOREm<"st1b", 0x15, I32, i32, truncstorei8>;
// STQ pseudo instructions
let mayStore = 1, hasSideEffects = 0 in {
def STQrii : Pseudo<(outs), (ins MEMrii:$addr, F128:$sx),
"# pseudo stq $sx, $addr",
[(store f128:$sx, ADDRrii:$addr)]>;
}
// Section 8.2.12 - DLDS
let DecoderMethod = "DecodeLoadI64" in
defm DLD : LOADm<"dld", 0x09, I64, i64, load>;
@ -1307,13 +1321,13 @@ let cw = 1, cx = 1 in
defm FMINS : RRFm<"fmin.s", 0x3E, F32, f32, fminnum, simm7fp, mimmfp32>;
// Section 8.7.7 - FAQ (Floating Add Quadruple)
defm FADDQ : RRFm<"fadd.q", 0x6C, F128, f128>;
defm FADDQ : RRFm<"fadd.q", 0x6C, F128, f128, fadd>;
// Section 8.7.8 - FSQ (Floating Subtract Quadruple)
defm FSUBQ : RRFm<"fsub.q", 0x7C, F128, f128>;
defm FSUBQ : RRFm<"fsub.q", 0x7C, F128, f128, fsub>;
// Section 8.7.9 - FMQ (Floating Subtract Quadruple)
defm FMULQ : RRFm<"fmul.q", 0x6D, F128, f128>;
defm FMULQ : RRFm<"fmul.q", 0x6D, F128, f128, fmul>;
// Section 8.7.10 - FCQ (Floating Compare Quadruple)
defm FCMPQ : RRNCbm<"fcmp.q", 0x7D, I64, f64, F128, f128, null_frag, simm7fp,
@ -1631,6 +1645,14 @@ defm : TRUNC64m<truncstorei8, ST1Brri, ST1Brii, ST1Bzri, ST1Bzii>;
defm : TRUNC64m<truncstorei16, ST2Brri, ST2Brii, ST2Bzri, ST2Bzii>;
defm : TRUNC64m<truncstorei32, STLrri, STLrii, STLzri, ST1Bzii>;
// Address calculation and its optimization
def : Pat<(VEhi tconstpool:$in), (LEASLzii 0, 0, tconstpool:$in)>;
def : Pat<(VElo tconstpool:$in),
(ANDrm (LEAzii 0, 0, tconstpool:$in), !add(32, 64))>;
def : Pat<(add (VEhi tconstpool:$in1), (VElo tconstpool:$in2)),
(LEASLrii (ANDrm (LEAzii 0, 0, tconstpool:$in2), !add(32, 64)), 0,
(tconstpool:$in1))>;
// Address calculation and its optimization
def : Pat<(VEhi tglobaladdr:$in), (LEASLzii 0, 0, tglobaladdr:$in)>;
def : Pat<(VElo tglobaladdr:$in),

View File

@ -51,6 +51,8 @@ static MCOperand LowerOperand(const MachineInstr *MI, const MachineOperand &MO,
break;
return MCOperand::createReg(MO.getReg());
case MachineOperand::MO_ConstantPoolIndex:
return LowerSymbolOperand(MI, MO, AP.GetCPISymbol(MO.getIndex()), AP);
case MachineOperand::MO_ExternalSymbol:
return LowerSymbolOperand(
MI, MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP);

View File

@ -120,6 +120,38 @@ void VERegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
Offset += MI.getOperand(FIOperandNum + 2).getImm();
if (MI.getOpcode() == VE::STQrii) {
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
Register SrcReg = MI.getOperand(3).getReg();
Register SrcHiReg = getSubReg(SrcReg, VE::sub_even);
Register SrcLoReg = getSubReg(SrcReg, VE::sub_odd);
// VE stores HiReg to 8(addr) and LoReg to 0(addr)
MachineInstr *StMI = BuildMI(*MI.getParent(), II, dl, TII.get(VE::STrii))
.addReg(FrameReg)
.addImm(0)
.addImm(0)
.addReg(SrcLoReg);
replaceFI(MF, II, *StMI, dl, 0, Offset, FrameReg);
MI.setDesc(TII.get(VE::STrii));
MI.getOperand(3).setReg(SrcHiReg);
Offset += 8;
} else if (MI.getOpcode() == VE::LDQrii) {
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
Register DestReg = MI.getOperand(0).getReg();
Register DestHiReg = getSubReg(DestReg, VE::sub_even);
Register DestLoReg = getSubReg(DestReg, VE::sub_odd);
// VE loads HiReg from 8(addr) and LoReg from 0(addr)
MachineInstr *StMI =
BuildMI(*MI.getParent(), II, dl, TII.get(VE::LDrii), DestLoReg)
.addReg(FrameReg)
.addImm(0)
.addImm(0);
replaceFI(MF, II, *StMI, dl, 1, Offset, FrameReg);
MI.setDesc(TII.get(VE::LDrii));
MI.getOperand(0).setReg(DestHiReg);
Offset += 8;
}
replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FrameReg);
}

View File

@ -1,5 +1,11 @@
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
declare i32 @sample_add(i32, i32)
declare i32 @stack_callee_int(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)
declare i32 @stack_callee_int_szext(i1 signext, i8 zeroext, i32, i32, i32, i32, i32, i32, i16 zeroext, i8 signext)
declare float @stack_callee_float(float, float, float, float, float, float, float, float, float, float)
declare void @test(i64)
define i32 @sample_call() {
; CHECK-LABEL: sample_call:
; CHECK: .LBB{{[0-9]+}}_2:
@ -14,8 +20,6 @@ define i32 @sample_call() {
ret i32 %r
}
declare i32 @sample_add(i32, i32)
define i32 @stack_call_int() {
; CHECK-LABEL: stack_call_int:
; CHECK: .LBB{{[0-9]+}}_2:
@ -40,8 +44,6 @@ define i32 @stack_call_int() {
ret i32 %r
}
declare i32 @stack_callee_int(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32)
define i32 @stack_call_int_szext() {
; CHECK-LABEL: stack_call_int_szext:
; CHECK: .LBB{{[0-9]+}}_2:
@ -65,8 +67,6 @@ define i32 @stack_call_int_szext() {
ret i32 %r
}
declare i32 @stack_callee_int_szext(i1 signext, i8 zeroext, i32, i32, i32, i32, i32, i32, i16 zeroext, i8 signext)
define float @stack_call_float() {
; CHECK-LABEL: stack_call_float:
; CHECK: .LBB{{[0-9]+}}_2:
@ -91,8 +91,6 @@ define float @stack_call_float() {
ret float %r
}
declare float @stack_callee_float(float, float, float, float, float, float, float, float, float, float)
define float @stack_call_float2(float %p0) {
; CHECK-LABEL: stack_call_float2:
; CHECK: .LBB{{[0-9]+}}_2:

View File

@ -18,6 +18,15 @@ define double @func2(double %a, double %b) {
ret double %r
}
define fp128 @func3(fp128 %a, fp128 %b) {
; CHECK-LABEL: func3:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: fadd.q %s0, %s0, %s2
; CHECK-NEXT: or %s11, 0, %s9
%r = fadd fp128 %a, %b
ret fp128 %r
}
define float @func4(float %a) {
; CHECK-LABEL: func4:
; CHECK: .LBB{{[0-9]+}}_2:
@ -38,6 +47,20 @@ define double @func5(double %a) {
ret double %r
}
define fp128 @func6(fp128 %a) {
; CHECK-LABEL: func6:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s4, 8(, %s2)
; CHECK-NEXT: ld %s5, (, %s2)
; CHECK-NEXT: fadd.q %s0, %s0, %s4
; CHECK-NEXT: or %s11, 0, %s9
%r = fadd fp128 %a, 0xL00000000000000004001400000000000
ret fp128 %r
}
define float @func7(float %a) {
; CHECK-LABEL: func7:
; CHECK: .LBB{{[0-9]+}}_2:
@ -60,6 +83,20 @@ define double @func8(double %a) {
ret double %r
}
define fp128 @func9(fp128 %a) {
; CHECK-LABEL: func9:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s4, 8(, %s2)
; CHECK-NEXT: ld %s5, (, %s2)
; CHECK-NEXT: fadd.q %s0, %s0, %s4
; CHECK-NEXT: or %s11, 0, %s9
%r = fadd fp128 %a, 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF
ret fp128 %r
}
define float @fadds_imm(float %a) {
; CHECK-LABEL: fadds_imm:
; CHECK: .LBB{{[0-9]+}}_2:
@ -77,3 +114,17 @@ define double @faddd_imm(double %a) {
%r = fadd double %a, -2.e+00
ret double %r
}
define fp128 @faddq_imm(fp128 %a) {
; CHECK-LABEL: faddq_imm:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s4, 8(, %s2)
; CHECK-NEXT: ld %s5, (, %s2)
; CHECK-NEXT: fadd.q %s0, %s0, %s4
; CHECK-NEXT: or %s11, 0, %s9
%r = fadd fp128 %a, 0xLA0000000000000000000000000000000
ret fp128 %r
}

View File

@ -18,6 +18,18 @@ define double @func2(double %a, double %b) {
ret double %r
}
define fp128 @func3(fp128 %a, fp128 %b) {
; CHECK-LABEL: func3:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s4, __divtf3@lo
; CHECK-NEXT: and %s4, %s4, (32)0
; CHECK-NEXT: lea.sl %s12, __divtf3@hi(, %s4)
; CHECK-NEXT: bsic %s10, (, %s12)
; CHECK-NEXT: or %s11, 0, %s9
%r = fdiv fp128 %a, %b
ret fp128 %r
}
define float @func4(float %a) {
; CHECK-LABEL: func4:
; CHECK: .LBB{{[0-9]+}}_2:
@ -38,6 +50,23 @@ define double @func5(double %a) {
ret double %r
}
define fp128 @func6(fp128 %a) {
; CHECK-LABEL: func6:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s4, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s2, 8(, %s4)
; CHECK-NEXT: ld %s3, (, %s4)
; CHECK-NEXT: lea %s4, __divtf3@lo
; CHECK-NEXT: and %s4, %s4, (32)0
; CHECK-NEXT: lea.sl %s12, __divtf3@hi(, %s4)
; CHECK-NEXT: bsic %s10, (, %s12)
; CHECK-NEXT: or %s11, 0, %s9
%r = fdiv fp128 %a, 0xL00000000000000004001400000000000
ret fp128 %r
}
define float @func7(float %a) {
; CHECK-LABEL: func7:
; CHECK: .LBB{{[0-9]+}}_2:
@ -59,3 +88,21 @@ define double @func8(double %a) {
%r = fdiv double %a, 0x7FEFFFFFFFFFFFFF
ret double %r
}
; Function Attrs: norecurse nounwind readnone
define fp128 @func9(fp128 %a) {
; CHECK-LABEL: func9:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s4, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s2, 8(, %s4)
; CHECK-NEXT: ld %s3, (, %s4)
; CHECK-NEXT: lea %s4, __divtf3@lo
; CHECK-NEXT: and %s4, %s4, (32)0
; CHECK-NEXT: lea.sl %s12, __divtf3@hi(, %s4)
; CHECK-NEXT: bsic %s10, (, %s12)
; CHECK-NEXT: or %s11, 0, %s9
%r = fdiv fp128 %a, 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF
ret fp128 %r
}

View File

@ -18,6 +18,15 @@ define double @func2(double %a, double %b) {
ret double %r
}
define fp128 @func3(fp128 %a, fp128 %b) {
; CHECK-LABEL: func3:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: fmul.q %s0, %s0, %s2
; CHECK-NEXT: or %s11, 0, %s9
%r = fmul fp128 %a, %b
ret fp128 %r
}
define float @func4(float %a) {
; CHECK-LABEL: func4:
; CHECK: .LBB{{[0-9]+}}_2:
@ -38,6 +47,20 @@ define double @func5(double %a) {
ret double %r
}
define fp128 @func6(fp128 %a) {
; CHECK-LABEL: func6:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s4, 8(, %s2)
; CHECK-NEXT: ld %s5, (, %s2)
; CHECK-NEXT: fmul.q %s0, %s0, %s4
; CHECK-NEXT: or %s11, 0, %s9
%r = fmul fp128 %a, 0xL00000000000000004001400000000000
ret fp128 %r
}
define float @func7(float %a) {
; CHECK-LABEL: func7:
; CHECK: .LBB{{[0-9]+}}_2:
@ -60,6 +83,20 @@ define double @func8(double %a) {
ret double %r
}
define fp128 @func9(fp128 %a) {
; CHECK-LABEL: func9:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s4, 8(, %s2)
; CHECK-NEXT: ld %s5, (, %s2)
; CHECK-NEXT: fmul.q %s0, %s0, %s4
; CHECK-NEXT: or %s11, 0, %s9
%r = fmul fp128 %a, 0xLFFFFFFFFFFFFFFFF7FFEFFFFFFFFFFFF
ret fp128 %r
}
define float @fmuls_ir(float %a) {
; CHECK-LABEL: fmuls_ir:
; CHECK: .LBB{{[0-9]+}}_2:
@ -95,4 +132,3 @@ define float @fmuls_ri3(float %a) {
%r = fmul float %a, 1.175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875E-38
ret float %r
}

View File

@ -18,6 +18,15 @@ define double @func2(double %a, double %b) {
ret double %r
}
define fp128 @func3(fp128 %a, fp128 %b) {
; CHECK-LABEL: func3:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: fsub.q %s0, %s0, %s2
; CHECK-NEXT: or %s11, 0, %s9
%r = fsub fp128 %a, %b
ret fp128 %r
}
define float @func4(float %a) {
; CHECK-LABEL: func4:
; CHECK: .LBB{{[0-9]+}}_2:
@ -38,6 +47,20 @@ define double @func5(double %a) {
ret double %r
}
define fp128 @func6(fp128 %a) {
; CHECK-LABEL: func6:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s4, 8(, %s2)
; CHECK-NEXT: ld %s5, (, %s2)
; CHECK-NEXT: fadd.q %s0, %s0, %s4
; CHECK-NEXT: or %s11, 0, %s9
%r = fadd fp128 %a, 0xL0000000000000000C001400000000000
ret fp128 %r
}
define float @func7(float %a) {
; CHECK-LABEL: func7:
; CHECK: .LBB{{[0-9]+}}_2:
@ -60,6 +83,20 @@ define double @func8(double %a) {
ret double %r
}
define fp128 @func9(fp128 %a) {
; CHECK-LABEL: func9:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, .LCPI{{[0-9]+}}_0@hi(, %s2)
; CHECK-NEXT: ld %s4, 8(, %s2)
; CHECK-NEXT: ld %s5, (, %s2)
; CHECK-NEXT: fadd.q %s0, %s0, %s4
; CHECK-NEXT: or %s11, 0, %s9
%r = fadd fp128 %a, 0xLFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFF
ret fp128 %r
}
define float @fsubs_ir(float %a) {
; CHECK-LABEL: fsubs_ir:
; CHECK: .LBB{{[0-9]+}}_2:

View File

@ -1,5 +1,18 @@
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
; Function Attrs: norecurse nounwind readonly
define fp128 @loadf128(fp128* nocapture readonly %0) {
; CHECK-LABEL: loadf128:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: ld %s2, 8(, %s0)
; CHECK-NEXT: ld %s3, (, %s0)
; CHECK-NEXT: or %s0, 0, %s2
; CHECK-NEXT: or %s1, 0, %s3
; CHECK-NEXT: or %s11, 0, %s9
%2 = load fp128, fp128* %0, align 16
ret fp128 %2
}
; Function Attrs: norecurse nounwind readonly
define double @loadf64(double* nocapture readonly %0) {
; CHECK-LABEL: loadf64:
@ -20,6 +33,18 @@ define float @loadf32(float* nocapture readonly %0) {
ret float %2
}
; Function Attrs: norecurse nounwind readonly
define i128 @loadi128(i128* nocapture readonly %0) {
; CHECK-LABEL: loadi128:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: ld %s2, (, %s0)
; CHECK-NEXT: ld %s1, 8(, %s0)
; CHECK-NEXT: or %s0, 0, %s2
; CHECK-NEXT: or %s11, 0, %s9
%2 = load i128, i128* %0, align 16
ret i128 %2
}
; Function Attrs: norecurse nounwind readonly
define i64 @loadi64(i64* nocapture readonly %0) {
; CHECK-LABEL: loadi64:
@ -126,6 +151,18 @@ define i64 @loadi8zext(i8* nocapture readonly %0) {
ret i64 %3
}
; Function Attrs: norecurse nounwind readonly
define fp128 @loadf128stk() {
; CHECK-LABEL: loadf128stk:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: ld %s1, 176(, %s11)
; CHECK-NEXT: ld %s0, 184(, %s11)
; CHECK-NEXT: or %s11, 0, %s9
%addr = alloca fp128, align 16
%1 = load fp128, fp128* %addr, align 16
ret fp128 %1
}
; Function Attrs: norecurse nounwind readonly
define double @loadf64stk() {
; CHECK-LABEL: loadf64stk:
@ -148,6 +185,18 @@ define float @loadf32stk() {
ret float %1
}
; Function Attrs: norecurse nounwind readonly
define i128 @loadi128stk() {
; CHECK-LABEL: loadi128stk:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: ld %s0, 176(, %s11)
; CHECK-NEXT: ld %s1, 184(, %s11)
; CHECK-NEXT: or %s11, 0, %s9
%addr = alloca i128, align 16
%1 = load i128, i128* %addr, align 16
ret i128 %1
}
; Function Attrs: norecurse nounwind readonly
define i64 @loadi64stk() {
; CHECK-LABEL: loadi64stk:

View File

@ -4,8 +4,24 @@
@vi16 = common dso_local local_unnamed_addr global i16 0, align 2
@vi32 = common dso_local local_unnamed_addr global i32 0, align 4
@vi64 = common dso_local local_unnamed_addr global i64 0, align 8
@vi128 = common dso_local local_unnamed_addr global i128 0, align 16
@vf32 = common dso_local local_unnamed_addr global float 0.000000e+00, align 4
@vf64 = common dso_local local_unnamed_addr global double 0.000000e+00, align 8
@vf128 = common dso_local local_unnamed_addr global fp128 0xL00000000000000000000000000000000, align 16
; Function Attrs: norecurse nounwind readonly
define fp128 @loadf128com() {
; CHECK-LABEL: loadf128com:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, vf128@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s2, vf128@hi(, %s0)
; CHECK-NEXT: ld %s0, 8(, %s2)
; CHECK-NEXT: ld %s1, (, %s2)
; CHECK-NEXT: or %s11, 0, %s9
%1 = load fp128, fp128* @vf128, align 16
ret fp128 %1
}
; Function Attrs: norecurse nounwind readonly
define double @loadf64com() {
@ -33,6 +49,20 @@ define float @loadf32com() {
ret float %1
}
; Function Attrs: norecurse nounwind readonly
define i128 @loadi128com() {
; CHECK-LABEL: loadi128com:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, vi128@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s1, vi128@hi(, %s0)
; CHECK-NEXT: ld %s0, (, %s1)
; CHECK-NEXT: ld %s1, 8(, %s1)
; CHECK-NEXT: or %s11, 0, %s9
%1 = load i128, i128* @vi128, align 16
ret i128 %1
}
; Function Attrs: norecurse nounwind readonly
define i64 @loadi64com() {
; CHECK-LABEL: loadi64com:

View File

@ -13,10 +13,10 @@
define signext i8 @loadi8s() {
; CHECK-LABEL: loadi8s:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi8+2@lo
; CHECK-NEXT: lea %s0, bufi8@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi8+2@hi(, %s0)
; CHECK-NEXT: ld1b.sx %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, bufi8@hi(, %s0)
; CHECK-NEXT: ld1b.sx %s0, 2(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i8, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @bufi8, i64 0, i64 2), align 1
@ -27,10 +27,10 @@ entry:
define signext i16 @loadi16s() {
; CHECK-LABEL: loadi16s:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi16+4@lo
; CHECK-NEXT: lea %s0, bufi16@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi16+4@hi(, %s0)
; CHECK-NEXT: ld2b.sx %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, bufi16@hi(, %s0)
; CHECK-NEXT: ld2b.sx %s0, 4(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i16, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @bufi16, i64 0, i64 2), align 2
@ -41,10 +41,10 @@ entry:
define signext i32 @loadi32s() {
; CHECK-LABEL: loadi32s:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi32+8@lo
; CHECK-NEXT: lea %s0, bufi32@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi32+8@hi(, %s0)
; CHECK-NEXT: ldl.sx %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, bufi32@hi(, %s0)
; CHECK-NEXT: ldl.sx %s0, 8(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @bufi32, i64 0, i64 2), align 4
@ -55,10 +55,10 @@ entry:
define i64 @loadi64s() {
; CHECK-LABEL: loadi64s:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi64+16@lo
; CHECK-NEXT: lea %s0, bufi64@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi64+16@hi(, %s0)
; CHECK-NEXT: ld %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, bufi64@hi(, %s0)
; CHECK-NEXT: ld %s0, 16(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @bufi64, i64 0, i64 2), align 8
@ -69,14 +69,11 @@ entry:
define i128 @loadi128s() {
; CHECK-LABEL: loadi128s:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi128+32@lo
; CHECK-NEXT: lea %s0, bufi128@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi128+32@hi(, %s0)
; CHECK-NEXT: ld %s0, (, %s0)
; CHECK-NEXT: lea %s1, bufi128+40@lo
; CHECK-NEXT: and %s1, %s1, (32)0
; CHECK-NEXT: lea.sl %s1, bufi128+40@hi(, %s1)
; CHECK-NEXT: ld %s1, (, %s1)
; CHECK-NEXT: lea.sl %s1, bufi128@hi(, %s0)
; CHECK-NEXT: ld %s0, 32(, %s1)
; CHECK-NEXT: ld %s1, 40(, %s1)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i128, i128* getelementptr inbounds ([3 x i128], [3 x i128]* @bufi128, i64 0, i64 2), align 16
@ -87,10 +84,10 @@ entry:
define zeroext i8 @loadi8z() {
; CHECK-LABEL: loadi8z:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi8+2@lo
; CHECK-NEXT: lea %s0, bufi8@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi8+2@hi(, %s0)
; CHECK-NEXT: ld1b.zx %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, bufi8@hi(, %s0)
; CHECK-NEXT: ld1b.zx %s0, 2(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i8, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @bufi8, i64 0, i64 2), align 1
@ -101,10 +98,10 @@ entry:
define zeroext i16 @loadi16z() {
; CHECK-LABEL: loadi16z:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi16+4@lo
; CHECK-NEXT: lea %s0, bufi16@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi16+4@hi(, %s0)
; CHECK-NEXT: ld2b.zx %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, bufi16@hi(, %s0)
; CHECK-NEXT: ld2b.zx %s0, 4(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i16, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @bufi16, i64 0, i64 2), align 2
@ -115,10 +112,10 @@ entry:
define zeroext i32 @loadi32z() {
; CHECK-LABEL: loadi32z:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi32+8@lo
; CHECK-NEXT: lea %s0, bufi32@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi32+8@hi(, %s0)
; CHECK-NEXT: ldl.zx %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, bufi32@hi(, %s0)
; CHECK-NEXT: ldl.zx %s0, 8(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i32, i32* getelementptr inbounds ([3 x i32], [3 x i32]* @bufi32, i64 0, i64 2), align 4
@ -129,10 +126,10 @@ entry:
define i64 @loadi64z() {
; CHECK-LABEL: loadi64z:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi64+16@lo
; CHECK-NEXT: lea %s0, bufi64@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi64+16@hi(, %s0)
; CHECK-NEXT: ld %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, bufi64@hi(, %s0)
; CHECK-NEXT: ld %s0, 16(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i64, i64* getelementptr inbounds ([3 x i64], [3 x i64]* @bufi64, i64 0, i64 2), align 8
@ -143,14 +140,11 @@ entry:
define i128 @loadi128z() {
; CHECK-LABEL: loadi128z:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, bufi128+32@lo
; CHECK-NEXT: lea %s0, bufi128@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, bufi128+32@hi(, %s0)
; CHECK-NEXT: ld %s0, (, %s0)
; CHECK-NEXT: lea %s1, bufi128+40@lo
; CHECK-NEXT: and %s1, %s1, (32)0
; CHECK-NEXT: lea.sl %s1, bufi128+40@hi(, %s1)
; CHECK-NEXT: ld %s1, (, %s1)
; CHECK-NEXT: lea.sl %s1, bufi128@hi(, %s0)
; CHECK-NEXT: ld %s0, 32(, %s1)
; CHECK-NEXT: ld %s1, 40(, %s1)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load i128, i128* getelementptr inbounds ([3 x i128], [3 x i128]* @bufi128, i64 0, i64 2), align 16
@ -161,10 +155,10 @@ entry:
define float @loadf32() {
; CHECK-LABEL: loadf32:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, buff32+8@lo
; CHECK-NEXT: lea %s0, buff32@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, buff32+8@hi(, %s0)
; CHECK-NEXT: ldu %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, buff32@hi(, %s0)
; CHECK-NEXT: ldu %s0, 8(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load float, float* getelementptr inbounds ([3 x float], [3 x float]* @buff32, i64 0, i64 2), align 4
@ -175,10 +169,10 @@ entry:
define double @loadf64() {
; CHECK-LABEL: loadf64:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, buff64+16@lo
; CHECK-NEXT: lea %s0, buff64@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, buff64+16@hi(, %s0)
; CHECK-NEXT: ld %s0, (, %s0)
; CHECK-NEXT: lea.sl %s0, buff64@hi(, %s0)
; CHECK-NEXT: ld %s0, 16(, %s0)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load double, double* getelementptr inbounds ([3 x double], [3 x double]* @buff64, i64 0, i64 2), align 8
@ -189,14 +183,11 @@ entry:
define fp128 @loadf128() {
; CHECK-LABEL: loadf128:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s0, buff128+32@lo
; CHECK-NEXT: lea %s0, buff128@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, buff128+32@hi(, %s0)
; CHECK-NEXT: ld %s0, (, %s0)
; CHECK-NEXT: lea %s1, buff128+40@lo
; CHECK-NEXT: and %s1, %s1, (32)0
; CHECK-NEXT: lea.sl %s1, buff128+40@hi(, %s1)
; CHECK-NEXT: ld %s1, (, %s1)
; CHECK-NEXT: lea.sl %s2, buff128@hi(, %s0)
; CHECK-NEXT: ld %s0, 40(, %s2)
; CHECK-NEXT: ld %s1, 32(, %s2)
; CHECK-NEXT: or %s11, 0, %s9
entry:
%0 = load fp128, fp128* getelementptr inbounds ([3 x fp128], [3 x fp128]* @buff128, i64 0, i64 2), align 16

View File

@ -1,5 +1,16 @@
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
; Function Attrs: norecurse nounwind readonly
define void @storef128(fp128* nocapture %0, fp128 %1) {
; CHECK-LABEL: storef128:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: st %s2, 8(, %s0)
; CHECK-NEXT: st %s3, (, %s0)
; CHECK-NEXT: or %s11, 0, %s9
store fp128 %1, fp128* %0, align 16
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storef64(double* nocapture %0, double %1) {
; CHECK-LABEL: storef64:
@ -20,6 +31,17 @@ define void @storef32(float* nocapture %0, float %1) {
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storei128(i128* nocapture %0, i128 %1) {
; CHECK-LABEL: storei128:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: st %s2, 8(, %s0)
; CHECK-NEXT: st %s1, (, %s0)
; CHECK-NEXT: or %s11, 0, %s9
store i128 %1, i128* %0, align 16
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storei64(i64* nocapture %0, i64 %1) {
; CHECK-LABEL: storei64:
@ -93,6 +115,18 @@ define void @storei8tr(i8* nocapture %0, i64 %1) {
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storef128stk(fp128 %0) {
; CHECK-LABEL: storef128stk:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: st %s1, 176(, %s11)
; CHECK-NEXT: st %s0, 184(, %s11)
; CHECK-NEXT: or %s11, 0, %s9
%addr = alloca fp128, align 16
store fp128 %0, fp128* %addr, align 16
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storef64stk(double %0) {
; CHECK-LABEL: storef64stk:
@ -115,6 +149,18 @@ define void @storef32stk(float %0) {
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storei128stk(i128 %0) {
; CHECK-LABEL: storei128stk:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: st %s1, 184(, %s11)
; CHECK-NEXT: st %s0, 176(, %s11)
; CHECK-NEXT: or %s11, 0, %s9
%addr = alloca i128, align 16
store i128 %0, i128* %addr, align 16
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storei64stk(i64 %0) {
; CHECK-LABEL: storei64stk:

View File

@ -4,8 +4,24 @@
@vi16 = common dso_local local_unnamed_addr global i16 0, align 2
@vi32 = common dso_local local_unnamed_addr global i32 0, align 4
@vi64 = common dso_local local_unnamed_addr global i64 0, align 8
@vi128 = common dso_local local_unnamed_addr global i128 0, align 16
@vf32 = common dso_local local_unnamed_addr global float 0.000000e+00, align 4
@vf64 = common dso_local local_unnamed_addr global double 0.000000e+00, align 8
@vf128 = common dso_local local_unnamed_addr global fp128 0xL00000000000000000000000000000000, align 16
; Function Attrs: norecurse nounwind readonly
define void @storef128com(fp128 %0) {
; CHECK-LABEL: storef128com:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, vf128@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, vf128@hi(, %s2)
; CHECK-NEXT: st %s0, 8(, %s2)
; CHECK-NEXT: st %s1, (, %s2)
; CHECK-NEXT: or %s11, 0, %s9
store fp128 %0, fp128* @vf128, align 16
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storef64com(double %0) {
@ -33,6 +49,20 @@ define void @storef32com(float %0) {
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storei128com(i128 %0) {
; CHECK-LABEL: storei128com:
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: lea %s2, vi128@lo
; CHECK-NEXT: and %s2, %s2, (32)0
; CHECK-NEXT: lea.sl %s2, vi128@hi(, %s2)
; CHECK-NEXT: st %s1, 8(, %s2)
; CHECK-NEXT: st %s0, (, %s2)
; CHECK-NEXT: or %s11, 0, %s9
store i128 %0, i128* @vi128, align 16
ret void
}
; Function Attrs: norecurse nounwind readonly
define void @storei64com(i64 %0) {
; CHECK-LABEL: storei64com:
@ -84,4 +114,3 @@ define void @storei8com(i8 %0) {
store i8 %0, i8* @vi8, align 1
ret void
}

View File

@ -10,19 +10,26 @@
@.str.7 = private unnamed_addr constant [6 x i8] c"h=%p\0A\00", align 1
@.str.8 = private unnamed_addr constant [7 x i8] c"i=%ld\0A\00", align 1
@.str.9 = private unnamed_addr constant [7 x i8] c"j=%lf\0A\00", align 1
@.str.10 = private unnamed_addr constant [7 x i8] c"j=%Lf\0A\00", align 1
define i32 @func_vainout(i32, ...) {
; CHECK-LABEL: func_vainout:
; CHECK: ldl.sx %s1, 184(, %s9)
; CHECK: ld2b.sx %s18, 192(, %s9)
; CHECK: ld1b.sx %s19, 200(, %s9)
; CHECK: ldl.sx %s20, 208(, %s9)
; CHECK: ld2b.zx %s21, 216(, %s9)
; CHECK: ld1b.zx %s22, 224(, %s9)
; CHECK: ldu %s23, 236(, %s9)
; CHECK: ld %s24, 240(, %s9)
; CHECK: ld %s25, 248(, %s9)
; CHECK: ld %s26, 256(, %s9)
; CHECK: ld2b.sx %s19, 192(, %s9)
; CHECK: ld1b.sx %s22, 200(, %s9)
; CHECK: ldl.sx %s23, 208(, %s9)
; CHECK: ld2b.zx %s24, 216(, %s9)
; CHECK: ld1b.zx %s25, 224(, %s9)
; CHECK: ldu %s26, 236(, %s9)
; CHECK: ld %s27, 240(, %s9)
; CHECK: ld %s28, 248(, %s9)
; CHECK: ld %s29, 256(, %s9)
; CHECK: lea %s0, 279(, %s9)
; CHECK: and %s0, -16, %s0
; CHECK: lea %s2, 16(, %s0)
; CHECK: ld %s20, 8(, %s0)
; CHECK: ld %s21, (, %s0)
; CHECK: ld %s18, 16(, %s0)
%a = alloca i8*, align 8
%a8 = bitcast i8** %a to i8*
@ -38,6 +45,8 @@ define i32 @func_vainout(i32, ...) {
%p7 = va_arg i8** %a, i8*
%p8 = va_arg i8** %a, i64
%p9 = va_arg i8** %a, double
%p10 = va_arg i8** %a, fp128
%p11 = va_arg i8** %a, double
call void @llvm.va_end(i8* nonnull %a8)
call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %a8)
%pf0 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i64 0, i64 0), i32 %p0)
@ -54,6 +63,8 @@ define i32 @func_vainout(i32, ...) {
%pf7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.7, i64 0, i64 0), i8* %p7)
%pf8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.8, i64 0, i64 0), i64 %p8)
%pf9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.9, i64 0, i64 0), double %p9)
%pf10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.10, i64 0, i64 0), fp128 %p10)
%pf11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.9, i64 0, i64 0), double %p11)
ret i32 0
}
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)

View File

@ -7,9 +7,6 @@ define i32 @caller() {
; CHECK: .LBB{{[0-9]+}}_2:
; CHECK-NEXT: st %s18, 48(, %s9) # 8-byte Folded Spill
; CHECK-NEXT: or %s18, 0, (0)1
; CHECK-NEXT: st %s18, 280(, %s11)
; CHECK-NEXT: or %s0, 11, (0)1
; CHECK-NEXT: st %s0, 272(, %s11)
; CHECK-NEXT: st %s18, 264(, %s11)
; CHECK-NEXT: or %s0, 10, (0)1
; CHECK-NEXT: st %s0, 256(, %s11)
@ -28,18 +25,25 @@ define i32 @caller() {
; CHECK-NEXT: st %s2, 192(, %s11)
; CHECK-NEXT: or %s1, 1, (0)1
; CHECK-NEXT: st %s1, 184(, %s11)
; CHECK-NEXT: lea %s0, .LCPI{{[0-9]+}}_0@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s0, .LCPI{{[0-9]+}}_0@hi(, %s0)
; CHECK-NEXT: ld %s34, 8(, %s0)
; CHECK-NEXT: ld %s35, (, %s0)
; CHECK-NEXT: st %s18, 176(, %s11)
; CHECK-NEXT: lea.sl %s6, 1086324736
; CHECK-NEXT: st %s6, 224(, %s11)
; CHECK-NEXT: st %s34, 280(, %s11)
; CHECK-NEXT: lea %s0, func@lo
; CHECK-NEXT: and %s0, %s0, (32)0
; CHECK-NEXT: lea.sl %s12, func@hi(, %s0)
; CHECK-NEXT: st %s6, 224(, %s11)
; CHECK-NEXT: st %s35, 272(, %s11)
; CHECK-NEXT: or %s0, 0, %s18
; CHECK-NEXT: or %s7, 0, %s18
; CHECK-NEXT: bsic %s10, (, %s12)
; CHECK-NEXT: or %s0, 0, %s18
; CHECK-NEXT: ld %s18, 48(, %s9) # 8-byte Folded Reload
; CHECK-NEXT: or %s11, 0, %s9
call i32 (i32, ...) @func(i32 0, i16 1, i8 2, i32 3, i16 4, i8 5, float 6.0, i8* null, i64 8, double 9.0, i128 10, i128 11)
call i32 (i32, ...) @func(i32 0, i16 1, i8 2, i32 3, i16 4, i8 5, float 6.0, i8* null, i64 8, double 9.0, i128 10, fp128 0xLA000000000000000)
ret i32 0
}