mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-06 17:24:34 +00:00
Reapply fixed r241790: Fix shift legalization and lowering for big constants.
Summary: If shift amount is a constant value > 64 bit it is handled incorrectly during type legalization and X86 lowering. This patch the type of shift amount argument in function DAGTypeLegalizer::ExpandShiftByConstant from unsigned to APInt. Reviewers: nadav, majnemer, sanjoy, RKSimon Subscribers: RKSimon, llvm-commits Differential Revision: http://reviews.llvm.org/D10767 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241806 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -1358,9 +1358,9 @@ std::pair <SDValue, SDValue> DAGTypeLegalizer::ExpandAtomic(SDNode *Node) {
|
|||||||
return ExpandChainLibCall(LC, Node, false);
|
return ExpandChainLibCall(LC, Node, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ExpandShiftByConstant - N is a shift by a value that needs to be expanded,
|
/// N is a shift by a value that needs to be expanded,
|
||||||
/// and the shift amount is a constant 'Amt'. Expand the operation.
|
/// and the shift amount is a constant 'Amt'. Expand the operation.
|
||||||
void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
|
void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, const APInt &Amt,
|
||||||
SDValue &Lo, SDValue &Hi) {
|
SDValue &Lo, SDValue &Hi) {
|
||||||
SDLoc DL(N);
|
SDLoc DL(N);
|
||||||
// Expand the incoming operand to be shifted, so that we have its parts
|
// Expand the incoming operand to be shifted, so that we have its parts
|
||||||
@ -1381,9 +1381,9 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
|
|||||||
EVT ShTy = N->getOperand(1).getValueType();
|
EVT ShTy = N->getOperand(1).getValueType();
|
||||||
|
|
||||||
if (N->getOpcode() == ISD::SHL) {
|
if (N->getOpcode() == ISD::SHL) {
|
||||||
if (Amt > VTBits) {
|
if (Amt.ugt(VTBits)) {
|
||||||
Lo = Hi = DAG.getConstant(0, DL, NVT);
|
Lo = Hi = DAG.getConstant(0, DL, NVT);
|
||||||
} else if (Amt > NVTBits) {
|
} else if (Amt.ugt(NVTBits)) {
|
||||||
Lo = DAG.getConstant(0, DL, NVT);
|
Lo = DAG.getConstant(0, DL, NVT);
|
||||||
Hi = DAG.getNode(ISD::SHL, DL,
|
Hi = DAG.getNode(ISD::SHL, DL,
|
||||||
NVT, InL, DAG.getConstant(Amt - NVTBits, DL, ShTy));
|
NVT, InL, DAG.getConstant(Amt - NVTBits, DL, ShTy));
|
||||||
@ -1405,16 +1405,15 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
|
|||||||
DAG.getNode(ISD::SHL, DL, NVT, InH,
|
DAG.getNode(ISD::SHL, DL, NVT, InH,
|
||||||
DAG.getConstant(Amt, DL, ShTy)),
|
DAG.getConstant(Amt, DL, ShTy)),
|
||||||
DAG.getNode(ISD::SRL, DL, NVT, InL,
|
DAG.getNode(ISD::SRL, DL, NVT, InL,
|
||||||
DAG.getConstant(NVTBits - Amt, DL, ShTy)));
|
DAG.getConstant(-Amt + NVTBits, DL, ShTy)));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (N->getOpcode() == ISD::SRL) {
|
if (N->getOpcode() == ISD::SRL) {
|
||||||
if (Amt > VTBits) {
|
if (Amt.ugt(VTBits)) {
|
||||||
Lo = DAG.getConstant(0, DL, NVT);
|
Lo = Hi = DAG.getConstant(0, DL, NVT);
|
||||||
Hi = DAG.getConstant(0, DL, NVT);
|
} else if (Amt.ugt(NVTBits)) {
|
||||||
} else if (Amt > NVTBits) {
|
|
||||||
Lo = DAG.getNode(ISD::SRL, DL,
|
Lo = DAG.getNode(ISD::SRL, DL,
|
||||||
NVT, InH, DAG.getConstant(Amt - NVTBits, DL, ShTy));
|
NVT, InH, DAG.getConstant(Amt - NVTBits, DL, ShTy));
|
||||||
Hi = DAG.getConstant(0, DL, NVT);
|
Hi = DAG.getConstant(0, DL, NVT);
|
||||||
@ -1426,19 +1425,19 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
|
|||||||
DAG.getNode(ISD::SRL, DL, NVT, InL,
|
DAG.getNode(ISD::SRL, DL, NVT, InL,
|
||||||
DAG.getConstant(Amt, DL, ShTy)),
|
DAG.getConstant(Amt, DL, ShTy)),
|
||||||
DAG.getNode(ISD::SHL, DL, NVT, InH,
|
DAG.getNode(ISD::SHL, DL, NVT, InH,
|
||||||
DAG.getConstant(NVTBits - Amt, DL, ShTy)));
|
DAG.getConstant(-Amt + NVTBits, DL, ShTy)));
|
||||||
Hi = DAG.getNode(ISD::SRL, DL, NVT, InH, DAG.getConstant(Amt, DL, ShTy));
|
Hi = DAG.getNode(ISD::SRL, DL, NVT, InH, DAG.getConstant(Amt, DL, ShTy));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
|
assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
|
||||||
if (Amt > VTBits) {
|
if (Amt.ugt(VTBits)) {
|
||||||
Hi = Lo = DAG.getNode(ISD::SRA, DL, NVT, InH,
|
Hi = Lo = DAG.getNode(ISD::SRA, DL, NVT, InH,
|
||||||
DAG.getConstant(NVTBits - 1, DL, ShTy));
|
DAG.getConstant(NVTBits - 1, DL, ShTy));
|
||||||
} else if (Amt > NVTBits) {
|
} else if (Amt.ugt(NVTBits)) {
|
||||||
Lo = DAG.getNode(ISD::SRA, DL, NVT, InH,
|
Lo = DAG.getNode(ISD::SRA, DL, NVT, InH,
|
||||||
DAG.getConstant(Amt-NVTBits, DL, ShTy));
|
DAG.getConstant(Amt - NVTBits, DL, ShTy));
|
||||||
Hi = DAG.getNode(ISD::SRA, DL, NVT, InH,
|
Hi = DAG.getNode(ISD::SRA, DL, NVT, InH,
|
||||||
DAG.getConstant(NVTBits - 1, DL, ShTy));
|
DAG.getConstant(NVTBits - 1, DL, ShTy));
|
||||||
} else if (Amt == NVTBits) {
|
} else if (Amt == NVTBits) {
|
||||||
@ -1450,7 +1449,7 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
|
|||||||
DAG.getNode(ISD::SRL, DL, NVT, InL,
|
DAG.getNode(ISD::SRL, DL, NVT, InL,
|
||||||
DAG.getConstant(Amt, DL, ShTy)),
|
DAG.getConstant(Amt, DL, ShTy)),
|
||||||
DAG.getNode(ISD::SHL, DL, NVT, InH,
|
DAG.getNode(ISD::SHL, DL, NVT, InH,
|
||||||
DAG.getConstant(NVTBits - Amt, DL, ShTy)));
|
DAG.getConstant(-Amt + NVTBits, DL, ShTy)));
|
||||||
Hi = DAG.getNode(ISD::SRA, DL, NVT, InH, DAG.getConstant(Amt, DL, ShTy));
|
Hi = DAG.getNode(ISD::SRA, DL, NVT, InH, DAG.getConstant(Amt, DL, ShTy));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2178,7 +2177,7 @@ void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N,
|
|||||||
// If we can emit an efficient shift operation, do so now. Check to see if
|
// If we can emit an efficient shift operation, do so now. Check to see if
|
||||||
// the RHS is a constant.
|
// the RHS is a constant.
|
||||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
|
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
|
||||||
return ExpandShiftByConstant(N, CN->getZExtValue(), Lo, Hi);
|
return ExpandShiftByConstant(N, CN->getAPIntValue(), Lo, Hi);
|
||||||
|
|
||||||
// If we can determine that the high bit of the shift is zero or one, even if
|
// If we can determine that the high bit of the shift is zero or one, even if
|
||||||
// the low bits are variable, emit this shift in an optimized form.
|
// the low bits are variable, emit this shift in an optimized form.
|
||||||
|
@ -167,7 +167,7 @@ private:
|
|||||||
SDValue GetVectorElementPointer(SDValue VecPtr, EVT EltVT, SDValue Index);
|
SDValue GetVectorElementPointer(SDValue VecPtr, EVT EltVT, SDValue Index);
|
||||||
SDValue JoinIntegers(SDValue Lo, SDValue Hi);
|
SDValue JoinIntegers(SDValue Lo, SDValue Hi);
|
||||||
SDValue LibCallify(RTLIB::Libcall LC, SDNode *N, bool isSigned);
|
SDValue LibCallify(RTLIB::Libcall LC, SDNode *N, bool isSigned);
|
||||||
|
|
||||||
std::pair<SDValue, SDValue> ExpandChainLibCall(RTLIB::Libcall LC,
|
std::pair<SDValue, SDValue> ExpandChainLibCall(RTLIB::Libcall LC,
|
||||||
SDNode *Node, bool isSigned);
|
SDNode *Node, bool isSigned);
|
||||||
std::pair<SDValue, SDValue> ExpandAtomic(SDNode *Node);
|
std::pair<SDValue, SDValue> ExpandAtomic(SDNode *Node);
|
||||||
@ -347,7 +347,7 @@ private:
|
|||||||
|
|
||||||
void ExpandIntRes_ATOMIC_LOAD (SDNode *N, SDValue &Lo, SDValue &Hi);
|
void ExpandIntRes_ATOMIC_LOAD (SDNode *N, SDValue &Lo, SDValue &Hi);
|
||||||
|
|
||||||
void ExpandShiftByConstant(SDNode *N, unsigned Amt,
|
void ExpandShiftByConstant(SDNode *N, const APInt &Amt,
|
||||||
SDValue &Lo, SDValue &Hi);
|
SDValue &Lo, SDValue &Hi);
|
||||||
bool ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi);
|
bool ExpandShiftWithKnownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi);
|
||||||
bool ExpandShiftWithUnknownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi);
|
bool ExpandShiftWithUnknownAmountBit(SDNode *N, SDValue &Lo, SDValue &Hi);
|
||||||
|
@ -23167,7 +23167,7 @@ static SDValue PerformSHLCombine(SDNode *N, SelectionDAG &DAG) {
|
|||||||
// We shift all of the values by one. In many cases we do not have
|
// We shift all of the values by one. In many cases we do not have
|
||||||
// hardware support for this operation. This is better expressed as an ADD
|
// hardware support for this operation. This is better expressed as an ADD
|
||||||
// of two values.
|
// of two values.
|
||||||
if (N1SplatC->getZExtValue() == 1)
|
if (N1SplatC->getAPIntValue() == 1)
|
||||||
return DAG.getNode(ISD::ADD, SDLoc(N), VT, N0, N0);
|
return DAG.getNode(ISD::ADD, SDLoc(N), VT, N0, N0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
44
test/CodeGen/X86/legalize-shl-vec.ll
Normal file
44
test/CodeGen/X86/legalize-shl-vec.ll
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
; RUN: llc < %s -march=x86-64 | FileCheck %s
|
||||||
|
|
||||||
|
define <2 x i256> @test_shl(<2 x i256> %In) {
|
||||||
|
%Amt = insertelement <2 x i256> undef, i256 -1, i32 0
|
||||||
|
%Out = shl <2 x i256> %In, %Amt
|
||||||
|
ret <2 x i256> %Out
|
||||||
|
|
||||||
|
; CHECK-LABEL: test_shl
|
||||||
|
; CHECK: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK: retq
|
||||||
|
}
|
||||||
|
|
||||||
|
define <2 x i256> @test_srl(<2 x i256> %In) {
|
||||||
|
%Amt = insertelement <2 x i256> undef, i256 -1, i32 0
|
||||||
|
%Out = lshr <2 x i256> %In, %Amt
|
||||||
|
ret <2 x i256> %Out
|
||||||
|
|
||||||
|
; CHECK-LABEL: test_srl
|
||||||
|
; CHECK: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK-NEXT: movq $0
|
||||||
|
; CHECK: retq
|
||||||
|
}
|
||||||
|
|
||||||
|
define <2 x i256> @test_sra(<2 x i256> %In) {
|
||||||
|
%Amt = insertelement <2 x i256> undef, i256 -1, i32 0
|
||||||
|
%Out = ashr <2 x i256> %In, %Amt
|
||||||
|
ret <2 x i256> %Out
|
||||||
|
|
||||||
|
; CHECK-LABEL: test_sra
|
||||||
|
; CHECK: sarq $63
|
||||||
|
}
|
Reference in New Issue
Block a user