mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-14 15:28:20 +00:00
Add support for lowering 128-bit shifts on ppc64.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48029 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -233,6 +233,10 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
|
|||||||
addRegisterClass(MVT::i64, PPC::G8RCRegisterClass);
|
addRegisterClass(MVT::i64, PPC::G8RCRegisterClass);
|
||||||
// BUILD_PAIR can't be handled natively, and should be expanded to shl/or
|
// BUILD_PAIR can't be handled natively, and should be expanded to shl/or
|
||||||
setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
|
setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);
|
||||||
|
// 64-bit PowerPC wants to expand i128 shifts itself.
|
||||||
|
setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom);
|
||||||
|
setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom);
|
||||||
|
setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom);
|
||||||
} else {
|
} else {
|
||||||
// 32-bit PowerPC wants to expand i64 shifts itself.
|
// 32-bit PowerPC wants to expand i64 shifts itself.
|
||||||
setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
|
setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
|
||||||
@@ -2416,77 +2420,89 @@ SDOperand PPCTargetLowering::LowerFLT_ROUNDS_(SDOperand Op, SelectionDAG &DAG) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDOperand PPCTargetLowering::LowerSHL_PARTS(SDOperand Op, SelectionDAG &DAG) {
|
SDOperand PPCTargetLowering::LowerSHL_PARTS(SDOperand Op, SelectionDAG &DAG) {
|
||||||
assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
|
MVT::ValueType VT = Op.getValueType();
|
||||||
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!");
|
unsigned BitWidth = MVT::getSizeInBits(VT);
|
||||||
|
assert(Op.getNumOperands() == 3 &&
|
||||||
|
VT == Op.getOperand(1).getValueType() &&
|
||||||
|
"Unexpected SHL!");
|
||||||
|
|
||||||
// Expand into a bunch of logical ops. Note that these ops
|
// Expand into a bunch of logical ops. Note that these ops
|
||||||
// depend on the PPC behavior for oversized shift amounts.
|
// depend on the PPC behavior for oversized shift amounts.
|
||||||
SDOperand Lo = Op.getOperand(0);
|
SDOperand Lo = Op.getOperand(0);
|
||||||
SDOperand Hi = Op.getOperand(1);
|
SDOperand Hi = Op.getOperand(1);
|
||||||
SDOperand Amt = Op.getOperand(2);
|
SDOperand Amt = Op.getOperand(2);
|
||||||
|
MVT::ValueType AmtVT = Amt.getValueType();
|
||||||
|
|
||||||
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
|
||||||
DAG.getConstant(32, MVT::i32), Amt);
|
DAG.getConstant(BitWidth, AmtVT), Amt);
|
||||||
SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Amt);
|
SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, VT, Hi, Amt);
|
||||||
SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Tmp1);
|
SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, VT, Lo, Tmp1);
|
||||||
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
|
||||||
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
|
||||||
DAG.getConstant(-32U, MVT::i32));
|
DAG.getConstant(-BitWidth, AmtVT));
|
||||||
SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Tmp5);
|
SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, VT, Lo, Tmp5);
|
||||||
SDOperand OutHi = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
|
SDOperand OutHi = DAG.getNode(ISD::OR, VT, Tmp4, Tmp6);
|
||||||
SDOperand OutLo = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Amt);
|
SDOperand OutLo = DAG.getNode(PPCISD::SHL, VT, Lo, Amt);
|
||||||
SDOperand OutOps[] = { OutLo, OutHi };
|
SDOperand OutOps[] = { OutLo, OutHi };
|
||||||
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
|
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
|
||||||
OutOps, 2);
|
OutOps, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDOperand PPCTargetLowering::LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) {
|
SDOperand PPCTargetLowering::LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) {
|
||||||
assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
|
MVT::ValueType VT = Op.getValueType();
|
||||||
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRL!");
|
unsigned BitWidth = MVT::getSizeInBits(VT);
|
||||||
|
assert(Op.getNumOperands() == 3 &&
|
||||||
|
VT == Op.getOperand(1).getValueType() &&
|
||||||
|
"Unexpected SRL!");
|
||||||
|
|
||||||
// Otherwise, expand into a bunch of logical ops. Note that these ops
|
// Expand into a bunch of logical ops. Note that these ops
|
||||||
// depend on the PPC behavior for oversized shift amounts.
|
// depend on the PPC behavior for oversized shift amounts.
|
||||||
SDOperand Lo = Op.getOperand(0);
|
SDOperand Lo = Op.getOperand(0);
|
||||||
SDOperand Hi = Op.getOperand(1);
|
SDOperand Hi = Op.getOperand(1);
|
||||||
SDOperand Amt = Op.getOperand(2);
|
SDOperand Amt = Op.getOperand(2);
|
||||||
|
MVT::ValueType AmtVT = Amt.getValueType();
|
||||||
|
|
||||||
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
|
||||||
DAG.getConstant(32, MVT::i32), Amt);
|
DAG.getConstant(BitWidth, AmtVT), Amt);
|
||||||
SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
|
SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, VT, Lo, Amt);
|
||||||
SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
|
SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, VT, Hi, Tmp1);
|
||||||
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
|
||||||
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
|
||||||
DAG.getConstant(-32U, MVT::i32));
|
DAG.getConstant(-BitWidth, AmtVT));
|
||||||
SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Tmp5);
|
SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, VT, Hi, Tmp5);
|
||||||
SDOperand OutLo = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6);
|
SDOperand OutLo = DAG.getNode(ISD::OR, VT, Tmp4, Tmp6);
|
||||||
SDOperand OutHi = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Amt);
|
SDOperand OutHi = DAG.getNode(PPCISD::SRL, VT, Hi, Amt);
|
||||||
SDOperand OutOps[] = { OutLo, OutHi };
|
SDOperand OutOps[] = { OutLo, OutHi };
|
||||||
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
|
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
|
||||||
OutOps, 2);
|
OutOps, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDOperand PPCTargetLowering::LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) {
|
SDOperand PPCTargetLowering::LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) {
|
||||||
assert(Op.getNumOperands() == 3 && Op.getValueType() == MVT::i32 &&
|
MVT::ValueType VT = Op.getValueType();
|
||||||
Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRA!");
|
unsigned BitWidth = MVT::getSizeInBits(VT);
|
||||||
|
assert(Op.getNumOperands() == 3 &&
|
||||||
|
VT == Op.getOperand(1).getValueType() &&
|
||||||
|
"Unexpected SRA!");
|
||||||
|
|
||||||
// Otherwise, expand into a bunch of logical ops, followed by a select_cc.
|
// Expand into a bunch of logical ops, followed by a select_cc.
|
||||||
SDOperand Lo = Op.getOperand(0);
|
SDOperand Lo = Op.getOperand(0);
|
||||||
SDOperand Hi = Op.getOperand(1);
|
SDOperand Hi = Op.getOperand(1);
|
||||||
SDOperand Amt = Op.getOperand(2);
|
SDOperand Amt = Op.getOperand(2);
|
||||||
|
MVT::ValueType AmtVT = Amt.getValueType();
|
||||||
|
|
||||||
SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32,
|
SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT,
|
||||||
DAG.getConstant(32, MVT::i32), Amt);
|
DAG.getConstant(BitWidth, AmtVT), Amt);
|
||||||
SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt);
|
SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, VT, Lo, Amt);
|
||||||
SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1);
|
SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, VT, Hi, Tmp1);
|
||||||
SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3);
|
SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3);
|
||||||
SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt,
|
SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt,
|
||||||
DAG.getConstant(-32U, MVT::i32));
|
DAG.getConstant(-BitWidth, AmtVT));
|
||||||
SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Tmp5);
|
SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, VT, Hi, Tmp5);
|
||||||
SDOperand OutHi = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Amt);
|
SDOperand OutHi = DAG.getNode(PPCISD::SRA, VT, Hi, Amt);
|
||||||
SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, MVT::i32),
|
SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, AmtVT),
|
||||||
Tmp4, Tmp6, ISD::SETLE);
|
Tmp4, Tmp6, ISD::SETLE);
|
||||||
SDOperand OutOps[] = { OutLo, OutHi };
|
SDOperand OutOps[] = { OutLo, OutHi };
|
||||||
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(MVT::i32, MVT::i32),
|
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT),
|
||||||
OutOps, 2);
|
OutOps, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
test/CodeGen/PowerPC/shift128.ll
Normal file
14
test/CodeGen/PowerPC/shift128.ll
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
; RUN: llvm-as < %s | llc -march=ppc64 | grep sld | count 5
|
||||||
|
|
||||||
|
define i128 @foo_lshr(i128 %x, i128 %y) {
|
||||||
|
%r = lshr i128 %x, %y
|
||||||
|
ret i128 %r
|
||||||
|
}
|
||||||
|
define i128 @foo_ashr(i128 %x, i128 %y) {
|
||||||
|
%r = ashr i128 %x, %y
|
||||||
|
ret i128 %r
|
||||||
|
}
|
||||||
|
define i128 @foo_shl(i128 %x, i128 %y) {
|
||||||
|
%r = shl i128 %x, %y
|
||||||
|
ret i128 %r
|
||||||
|
}
|
Reference in New Issue
Block a user