mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-25 17:20:48 +00:00
Compile:
uint %test(uint %X) { %Y = call uint %llvm.ctpop.i32(uint %X) ret uint %Y } to: test: save -96, %o6, %o6 sll %i0, 0, %l0 popc %l0, %i0 restore %g0, %g0, %g0 retl nop instead of to 40 logical ops. Note the shift-by-zero that clears the top part of the 64-bit V9 register. Testcase here: CodeGen/SparcV8/ctpop.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@25814 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -33,21 +33,20 @@ using namespace llvm;
|
|||||||
namespace V8ISD {
|
namespace V8ISD {
|
||||||
enum {
|
enum {
|
||||||
FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END,
|
FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END,
|
||||||
CMPICC, // Compare two GPR operands, set icc.
|
CMPICC, // Compare two GPR operands, set icc.
|
||||||
CMPFCC, // Compare two FP operands, set fcc.
|
CMPFCC, // Compare two FP operands, set fcc.
|
||||||
BRICC, // Branch to dest on icc condition
|
BRICC, // Branch to dest on icc condition
|
||||||
BRFCC, // Branch to dest on fcc condition
|
BRFCC, // Branch to dest on fcc condition
|
||||||
|
SELECT_ICC, // Select between two values using the current ICC flags.
|
||||||
|
SELECT_FCC, // Select between two values using the current FCC flags.
|
||||||
|
|
||||||
Hi, Lo, // Hi/Lo operations, typically on a global address.
|
Hi, Lo, // Hi/Lo operations, typically on a global address.
|
||||||
|
|
||||||
FTOI, // FP to Int within a FP register.
|
FTOI, // FP to Int within a FP register.
|
||||||
ITOF, // Int to FP within a FP register.
|
ITOF, // Int to FP within a FP register.
|
||||||
|
|
||||||
SELECT_ICC, // Select between two values using the current ICC flags.
|
CALL, // A V8 call instruction.
|
||||||
SELECT_FCC, // Select between two values using the current FCC flags.
|
RET_FLAG, // Return with a flag operand.
|
||||||
|
|
||||||
CALL, // A V8 call instruction.
|
|
||||||
RET_FLAG, // Return with a flag operand.
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,10 +172,14 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
|
|||||||
setOperationAction(ISD::VAEND , MVT::Other, Expand);
|
setOperationAction(ISD::VAEND , MVT::Other, Expand);
|
||||||
setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
|
setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
|
||||||
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
|
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
|
||||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
|
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
|
||||||
|
|
||||||
setStackPointerRegisterToSaveRestore(V8::O6);
|
setStackPointerRegisterToSaveRestore(V8::O6);
|
||||||
|
|
||||||
|
if (TM.getSubtarget<SparcV8Subtarget>().isV9()) {
|
||||||
|
setOperationAction(ISD::CTPOP, MVT::i32, Legal);
|
||||||
|
}
|
||||||
|
|
||||||
computeRegisterProperties();
|
computeRegisterProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,12 +190,12 @@ const char *SparcV8TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case V8ISD::CMPFCC: return "V8ISD::CMPFCC";
|
case V8ISD::CMPFCC: return "V8ISD::CMPFCC";
|
||||||
case V8ISD::BRICC: return "V8ISD::BRICC";
|
case V8ISD::BRICC: return "V8ISD::BRICC";
|
||||||
case V8ISD::BRFCC: return "V8ISD::BRFCC";
|
case V8ISD::BRFCC: return "V8ISD::BRFCC";
|
||||||
|
case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC";
|
||||||
|
case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC";
|
||||||
case V8ISD::Hi: return "V8ISD::Hi";
|
case V8ISD::Hi: return "V8ISD::Hi";
|
||||||
case V8ISD::Lo: return "V8ISD::Lo";
|
case V8ISD::Lo: return "V8ISD::Lo";
|
||||||
case V8ISD::FTOI: return "V8ISD::FTOI";
|
case V8ISD::FTOI: return "V8ISD::FTOI";
|
||||||
case V8ISD::ITOF: return "V8ISD::ITOF";
|
case V8ISD::ITOF: return "V8ISD::ITOF";
|
||||||
case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC";
|
|
||||||
case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC";
|
|
||||||
case V8ISD::CALL: return "V8ISD::CALL";
|
case V8ISD::CALL: return "V8ISD::CALL";
|
||||||
case V8ISD::RET_FLAG: return "V8ISD::RET_FLAG";
|
case V8ISD::RET_FLAG: return "V8ISD::RET_FLAG";
|
||||||
}
|
}
|
||||||
|
@@ -764,6 +764,14 @@ let Predicates = [HasV9] in {
|
|||||||
[(set DFPRegs:$dst, (fabs DFPRegs:$src))]>;
|
[(set DFPRegs:$dst, (fabs DFPRegs:$src))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear
|
||||||
|
// the top 32-bits before using it. To do this clearing, we use a SLLri X,0.
|
||||||
|
def POPCrr : F3_1<2, 0b101110,
|
||||||
|
(ops IntRegs:$dst, IntRegs:$src),
|
||||||
|
"popc $src, $dst", []>, Requires<[HasV9]>;
|
||||||
|
def : Pat<(ctpop IntRegs:$src),
|
||||||
|
(POPCrr (SLLri IntRegs:$src, 0))>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Non-Instruction Patterns
|
// Non-Instruction Patterns
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@@ -33,21 +33,20 @@ using namespace llvm;
|
|||||||
namespace V8ISD {
|
namespace V8ISD {
|
||||||
enum {
|
enum {
|
||||||
FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END,
|
FIRST_NUMBER = ISD::BUILTIN_OP_END+V8::INSTRUCTION_LIST_END,
|
||||||
CMPICC, // Compare two GPR operands, set icc.
|
CMPICC, // Compare two GPR operands, set icc.
|
||||||
CMPFCC, // Compare two FP operands, set fcc.
|
CMPFCC, // Compare two FP operands, set fcc.
|
||||||
BRICC, // Branch to dest on icc condition
|
BRICC, // Branch to dest on icc condition
|
||||||
BRFCC, // Branch to dest on fcc condition
|
BRFCC, // Branch to dest on fcc condition
|
||||||
|
SELECT_ICC, // Select between two values using the current ICC flags.
|
||||||
|
SELECT_FCC, // Select between two values using the current FCC flags.
|
||||||
|
|
||||||
Hi, Lo, // Hi/Lo operations, typically on a global address.
|
Hi, Lo, // Hi/Lo operations, typically on a global address.
|
||||||
|
|
||||||
FTOI, // FP to Int within a FP register.
|
FTOI, // FP to Int within a FP register.
|
||||||
ITOF, // Int to FP within a FP register.
|
ITOF, // Int to FP within a FP register.
|
||||||
|
|
||||||
SELECT_ICC, // Select between two values using the current ICC flags.
|
CALL, // A V8 call instruction.
|
||||||
SELECT_FCC, // Select between two values using the current FCC flags.
|
RET_FLAG, // Return with a flag operand.
|
||||||
|
|
||||||
CALL, // A V8 call instruction.
|
|
||||||
RET_FLAG, // Return with a flag operand.
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,10 +172,14 @@ SparcV8TargetLowering::SparcV8TargetLowering(TargetMachine &TM)
|
|||||||
setOperationAction(ISD::VAEND , MVT::Other, Expand);
|
setOperationAction(ISD::VAEND , MVT::Other, Expand);
|
||||||
setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
|
setOperationAction(ISD::STACKSAVE , MVT::Other, Expand);
|
||||||
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
|
setOperationAction(ISD::STACKRESTORE , MVT::Other, Expand);
|
||||||
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
|
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32 , Expand);
|
||||||
|
|
||||||
setStackPointerRegisterToSaveRestore(V8::O6);
|
setStackPointerRegisterToSaveRestore(V8::O6);
|
||||||
|
|
||||||
|
if (TM.getSubtarget<SparcV8Subtarget>().isV9()) {
|
||||||
|
setOperationAction(ISD::CTPOP, MVT::i32, Legal);
|
||||||
|
}
|
||||||
|
|
||||||
computeRegisterProperties();
|
computeRegisterProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,12 +190,12 @@ const char *SparcV8TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||||||
case V8ISD::CMPFCC: return "V8ISD::CMPFCC";
|
case V8ISD::CMPFCC: return "V8ISD::CMPFCC";
|
||||||
case V8ISD::BRICC: return "V8ISD::BRICC";
|
case V8ISD::BRICC: return "V8ISD::BRICC";
|
||||||
case V8ISD::BRFCC: return "V8ISD::BRFCC";
|
case V8ISD::BRFCC: return "V8ISD::BRFCC";
|
||||||
|
case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC";
|
||||||
|
case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC";
|
||||||
case V8ISD::Hi: return "V8ISD::Hi";
|
case V8ISD::Hi: return "V8ISD::Hi";
|
||||||
case V8ISD::Lo: return "V8ISD::Lo";
|
case V8ISD::Lo: return "V8ISD::Lo";
|
||||||
case V8ISD::FTOI: return "V8ISD::FTOI";
|
case V8ISD::FTOI: return "V8ISD::FTOI";
|
||||||
case V8ISD::ITOF: return "V8ISD::ITOF";
|
case V8ISD::ITOF: return "V8ISD::ITOF";
|
||||||
case V8ISD::SELECT_ICC: return "V8ISD::SELECT_ICC";
|
|
||||||
case V8ISD::SELECT_FCC: return "V8ISD::SELECT_FCC";
|
|
||||||
case V8ISD::CALL: return "V8ISD::CALL";
|
case V8ISD::CALL: return "V8ISD::CALL";
|
||||||
case V8ISD::RET_FLAG: return "V8ISD::RET_FLAG";
|
case V8ISD::RET_FLAG: return "V8ISD::RET_FLAG";
|
||||||
}
|
}
|
||||||
|
@@ -764,6 +764,14 @@ let Predicates = [HasV9] in {
|
|||||||
[(set DFPRegs:$dst, (fabs DFPRegs:$src))]>;
|
[(set DFPRegs:$dst, (fabs DFPRegs:$src))]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// POPCrr - This does a ctpop of a 64-bit register. As such, we have to clear
|
||||||
|
// the top 32-bits before using it. To do this clearing, we use a SLLri X,0.
|
||||||
|
def POPCrr : F3_1<2, 0b101110,
|
||||||
|
(ops IntRegs:$dst, IntRegs:$src),
|
||||||
|
"popc $src, $dst", []>, Requires<[HasV9]>;
|
||||||
|
def : Pat<(ctpop IntRegs:$src),
|
||||||
|
(POPCrr (SLLri IntRegs:$src, 0))>;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Non-Instruction Patterns
|
// Non-Instruction Patterns
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
Reference in New Issue
Block a user