Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 42 additions & 9 deletions llvm/lib/Target/Sparc/SparcISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
Expand Down Expand Up @@ -1704,8 +1705,10 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FP16_TO_FP, MVT::f128, Expand);
setOperationAction(ISD::FP_TO_FP16, MVT::f128, Expand);

setOperationAction(ISD::BITCAST, MVT::f32, Expand);
setOperationAction(ISD::BITCAST, MVT::i32, Expand);
setOperationAction(ISD::BITCAST, MVT::f32,
Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::BITCAST, MVT::i32,
Subtarget->isVIS3() ? Legal : Expand);

// Sparc has no select or setcc: expand to SELECT_CC.
setOperationAction(ISD::SELECT, MVT::i32, Expand);
Expand Down Expand Up @@ -1737,9 +1740,16 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SUBC, MVT::i32, Legal);
setOperationAction(ISD::SUBE, MVT::i32, Legal);

if (Subtarget->isVIS3()) {
setOperationAction(ISD::ADDC, MVT::i64, Legal);
setOperationAction(ISD::ADDE, MVT::i64, Legal);
}

if (Subtarget->is64Bit()) {
setOperationAction(ISD::BITCAST, MVT::f64, Expand);
setOperationAction(ISD::BITCAST, MVT::i64, Expand);
setOperationAction(ISD::BITCAST, MVT::f64,
Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::BITCAST, MVT::i64,
Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::SELECT, MVT::i64, Expand);
setOperationAction(ISD::SETCC, MVT::i64, Expand);
setOperationAction(ISD::BR_CC, MVT::i64, Custom);
Expand All @@ -1748,7 +1758,8 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::CTPOP, MVT::i64,
Subtarget->usePopc() ? Legal : Expand);
setOperationAction(ISD::CTTZ , MVT::i64, Expand);
setOperationAction(ISD::CTLZ , MVT::i64, Expand);
setOperationAction(ISD::CTLZ, MVT::i64,
Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
setOperationAction(ISD::ROTL , MVT::i64, Expand);
setOperationAction(ISD::ROTR , MVT::i64, Expand);
Expand Down Expand Up @@ -1809,8 +1820,10 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FSINCOS, MVT::f32, Expand);
setOperationAction(ISD::FREM , MVT::f32, Expand);
setOperationAction(ISD::FMA , MVT::f32, Expand);
setOperationAction(ISD::CTTZ , MVT::i32, Expand);
setOperationAction(ISD::CTLZ , MVT::i32, Expand);
setOperationAction(ISD::CTTZ, MVT::i32,
Subtarget->isVIS3() ? Promote : Expand);
setOperationAction(ISD::CTLZ, MVT::i32,
Subtarget->isVIS3() ? Promote : Expand);
setOperationAction(ISD::ROTL , MVT::i32, Expand);
setOperationAction(ISD::ROTR , MVT::i32, Expand);
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
Expand Down Expand Up @@ -1849,8 +1862,10 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
if (Subtarget->is64Bit()) {
setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand);
setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand);
setOperationAction(ISD::MULHU, MVT::i64, Expand);
setOperationAction(ISD::MULHS, MVT::i64, Expand);
setOperationAction(ISD::MULHU, MVT::i64,
Subtarget->isVIS3() ? Legal : Expand);
setOperationAction(ISD::MULHS, MVT::i64,
Subtarget->isVIS3() ? Legal : Expand);

setOperationAction(ISD::SHL_PARTS, MVT::i64, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
Expand Down Expand Up @@ -1981,6 +1996,13 @@ SparcTargetLowering::SparcTargetLowering(const TargetMachine &TM,
if (Subtarget->hasLeonCycleCounter())
setOperationAction(ISD::READCYCLECOUNTER, MVT::i64, Custom);

if (Subtarget->isVIS3()) {
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Promote);
setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Legal);
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Promote);
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
}

setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);

setMinFunctionAlignment(Align(4));
Expand Down Expand Up @@ -3560,6 +3582,17 @@ bool SparcTargetLowering::useLoadStackGuardNode(const Module &M) const {
return true;
}

bool SparcTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const {
if (VT != MVT::f32 && VT != MVT::f64)
return false;
if (Imm.isZero())
return Subtarget->isVIS();
if (Imm.isExactlyValue(+0.5) || Imm.isExactlyValue(-0.5))
return Subtarget->isVIS3();
return false;
}

// Override to disable global variable loading on Linux.
void SparcTargetLowering::insertSSPDeclarations(Module &M) const {
if (!Subtarget->isTargetLinux())
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/Sparc/SparcISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,9 @@ namespace llvm {
return VT != MVT::f128;
}

bool isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const override;

bool shouldInsertFencesForAtomic(const Instruction *I) const override {
// FIXME: We insert fences for each atomics and generate
// sub-optimal code for PSO/TSO. (Approximately nobody uses any
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/Sparc/SparcInstr64Bit.td
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,11 @@ def : Pat<(and i64:$lhs, (not i64:$rhs)), (ANDNrr $lhs, $rhs)>;
def : Pat<(or i64:$lhs, (not i64:$rhs)), (ORNrr $lhs, $rhs)>;
def : Pat<(not (xor i64:$lhs, i64:$rhs)), (XNORrr $lhs, $rhs)>;

def : Pat<(addc i64:$lhs, i64:$rhs), (ADDCCrr $lhs, $rhs)>, Requires<[HasVIS3]>;
def : Pat<(add i64:$lhs, i64:$rhs), (ADDrr $lhs, $rhs)>;
def : Pat<(sub i64:$lhs, i64:$rhs), (SUBrr $lhs, $rhs)>;

def : Pat<(addc i64:$lhs, (i64 simm13:$rhs)), (ADDCCri $lhs, imm:$rhs)>, Requires<[HasVIS3]>;
def : Pat<(add i64:$lhs, (i64 simm13:$rhs)), (ADDri $lhs, imm:$rhs)>;
def : Pat<(sub i64:$lhs, (i64 simm13:$rhs)), (SUBri $lhs, imm:$rhs)>;

Expand Down
87 changes: 79 additions & 8 deletions llvm/lib/Target/Sparc/SparcInstrVIS.td
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ class VISInst2<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
!strconcat(OpcStr, " $rs2, $rd")>;

// For VIS Instructions with only rd operand.
let Constraints = "$rd = $f", rs1 = 0, rs2 = 0 in
let rs1 = 0, rs2 = 0 in
class VISInstD<bits<9> opfval, string OpcStr, RegisterClass RC = DFPRegs>
: VISInstFormat<opfval,
(outs RC:$rd), (ins RC:$f),
(outs RC:$rd), (ins),
!strconcat(OpcStr, " $rd")>;

// VIS 1 Instructions
Expand Down Expand Up @@ -259,14 +259,14 @@ def LZCNT : VISInstFormat<0b000010111, (outs I64Regs:$rd),
(ins I64Regs:$rs2), "lzcnt $rs2, $rd">;

let rs1 = 0 in {
def MOVSTOSW : VISInstFormat<0b100010011, (outs I64Regs:$rd),
(ins DFPRegs:$rs2), "movstosw $rs2, $rd">;
def MOVSTOUW : VISInstFormat<0b100010001, (outs I64Regs:$rd),
(ins DFPRegs:$rs2), "movstouw $rs2, $rd">;
def MOVSTOSW : VISInstFormat<0b100010011, (outs IntRegs:$rd),
(ins FPRegs:$rs2), "movstosw $rs2, $rd">;
def MOVSTOUW : VISInstFormat<0b100010001, (outs IntRegs:$rd),
(ins FPRegs:$rs2), "movstouw $rs2, $rd">;
def MOVDTOX : VISInstFormat<0b100010000, (outs I64Regs:$rd),
(ins DFPRegs:$rs2), "movdtox $rs2, $rd">;
def MOVWTOS : VISInstFormat<0b100011001, (outs DFPRegs:$rd),
(ins I64Regs:$rs2), "movwtos $rs2, $rd">;
def MOVWTOS : VISInstFormat<0b100011001, (outs FPRegs:$rd),
(ins IntRegs:$rs2), "movwtos $rs2, $rd">;
def MOVXTOD : VISInstFormat<0b100011000, (outs DFPRegs:$rd),
(ins I64Regs:$rs2), "movxtod $rs2, $rd">;
}
Expand All @@ -277,3 +277,74 @@ def UMULXHI : VISInst<0b000010110, "umulxhi", I64Regs>;
def XMULX : VISInst<0b100010101, "xmulx", I64Regs>;
def XMULXHI : VISInst<0b100010110, "xmulxhi", I64Regs>;
} // Predicates = [IsVIS3]

// FP immediate patterns.
def fpimm0 : FPImmLeaf<fAny, [{return Imm.isExactlyValue(+0.0);}]>;
def fpnegimm0 : FPImmLeaf<fAny, [{return Imm.isExactlyValue(-0.0);}]>;
def fpimmhalf : FPImmLeaf<fAny, [{return Imm.isExactlyValue(+0.5);}]>;
def fpnegimmhalf : FPImmLeaf<fAny, [{return Imm.isExactlyValue(-0.5);}]>;

// VIS instruction patterns.
let Predicates = [HasVIS] in {
// Zero immediate.
def : Pat<(f64 fpimm0), (FZERO)>;
def : Pat<(f32 fpimm0), (FZEROS)>;
def : Pat<(f64 fpnegimm0), (FNEGD (FZERO))>;
def : Pat<(f32 fpnegimm0), (FNEGS (FZEROS))>;
} // Predicates = [HasVIS]

// VIS3 instruction patterns.
let Predicates = [HasVIS3] in {
// +/-0.5 immediate.
// This is needed to enable halving instructions.
// FIXME generalize this to arbitrary immediates.
// SET/MOVWTOS or SETX/MOVXTOD pair should let us materialize FP constants
// faster than constant pool loading.
def : Pat<(f32 fpimmhalf), (MOVWTOS (SETHIi 0x0FC000))>;
def : Pat<(f32 fpnegimmhalf), (MOVWTOS (SETHIi 0x2FC000))>;
def : Pat<(f64 fpimmhalf), (MOVXTOD (SLLXri (SETHIi 0x0FF800), 32))>;
def : Pat<(f64 fpnegimmhalf), (MOVXTOD (SLLXri (SETHIi 0x2FF800), 32))>;

def : Pat<(i64 (adde i64:$lhs, i64:$rhs)), (ADDXCCC $lhs, $rhs)>;

def : Pat<(i64 (mulhu i64:$lhs, i64:$rhs)), (UMULXHI $lhs, $rhs)>;
// Signed "MULXHI".
// Based on the formula presented in OSA2011 §7.140, but with bitops to select
// the values to be added.
// TODO: This expansion should probably be moved to DAG legalization phase.
def : Pat<(i64 (mulhs i64:$lhs, i64:$rhs)),
(SUBrr (UMULXHI $lhs, $rhs),
(ADDrr (ANDrr (SRAXri $lhs, 63), $rhs),
(ANDrr (SRAXri $rhs, 63), $lhs)))>;

def : Pat<(i64 (ctlz i64:$src)), (LZCNT $src)>;
def : Pat<(i64 (ctlz_zero_undef i64:$src)), (LZCNT $src)>;

def : Pat<(i32 (bitconvert f32:$src)), (MOVSTOUW $src)>;
def : Pat<(i64 (zanyext (i32 (bitconvert f32:$src)))), (MOVSTOUW $src)>;
def : Pat<(i64 (sext (i32 (bitconvert f32:$src)))), (MOVSTOSW $src)>;
def : Pat<(f32 (bitconvert i32:$src)), (MOVWTOS $src)>;
def : Pat<(i64 (bitconvert f64:$src)), (MOVDTOX $src)>;
def : Pat<(f64 (bitconvert i64:$src)), (MOVXTOD $src)>;

// OP-then-neg FP operations.
def : Pat<(f32 (fneg (fadd f32:$rs1, f32:$rs2))), (FNADDS $rs1, $rs2)>;
def : Pat<(f64 (fneg (fadd f64:$rs1, f64:$rs2))), (FNADDD $rs1, $rs2)>;
def : Pat<(f32 (fneg (fmul f32:$rs1, f32:$rs2))), (FNMULS $rs1, $rs2)>;
def : Pat<(f32 (fmul (fneg f32:$rs1), f32:$rs2)), (FNMULS $rs1, $rs2)>;
def : Pat<(f32 (fmul f32:$rs1, (fneg f32:$rs2))), (FNMULS $rs1, $rs2)>;
def : Pat<(f64 (fneg (fmul f64:$rs1, f64:$rs2))), (FNMULD $rs1, $rs2)>;
def : Pat<(f64 (fmul (fneg f64:$rs1), f64:$rs2)), (FNMULD $rs1, $rs2)>;
def : Pat<(f64 (fmul f64:$rs1, (fneg f64:$rs2))), (FNMULD $rs1, $rs2)>;
def : Pat<(f64 (fneg (fmul (fpextend f32:$rs1), (fpextend f32:$rs2)))), (FNSMULD $rs1, $rs2)>;
def : Pat<(f64 (fmul (fneg (fpextend f32:$rs1)), (fpextend f32:$rs2))), (FNSMULD $rs1, $rs2)>;
def : Pat<(f64 (fmul (fpextend f32:$rs1), (fneg (fpextend f32:$rs2)))), (FNSMULD $rs1, $rs2)>;

// Op-then-halve FP operations.
def : Pat<(f32 (fmul (fadd f32:$rs1, f32:$rs2), fpimmhalf)), (FHADDS $rs1, $rs2)>;
def : Pat<(f64 (fmul (fadd f64:$rs1, f64:$rs2), fpimmhalf)), (FHADDD $rs1, $rs2)>;
def : Pat<(f32 (fmul (fsub f32:$rs1, f32:$rs2), fpimmhalf)), (FHSUBS $rs1, $rs2)>;
def : Pat<(f64 (fmul (fsub f64:$rs1, f64:$rs2), fpimmhalf)), (FHSUBD $rs1, $rs2)>;
def : Pat<(f32 (fmul (fadd f32:$rs1, f32:$rs2), fpnegimmhalf)), (FNHADDS $rs1, $rs2)>;
def : Pat<(f64 (fmul (fadd f64:$rs1, f64:$rs2), fpnegimmhalf)), (FNHADDD $rs1, $rs2)>;
} // Predicates = [HasVIS3]
Loading
Loading