forked from OSchip/llvm-project
parent
490075a7dd
commit
f4e76cf44d
|
@ -1097,6 +1097,48 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
|
||||||
DebugLoc dl = N->getDebugLoc();
|
DebugLoc dl = N->getDebugLoc();
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default: break;
|
default: break;
|
||||||
|
case XCoreISD::LADD: {
|
||||||
|
SDValue N0 = N->getOperand(0);
|
||||||
|
SDValue N1 = N->getOperand(1);
|
||||||
|
SDValue N2 = N->getOperand(2);
|
||||||
|
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
|
||||||
|
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
|
||||||
|
EVT VT = N0.getValueType();
|
||||||
|
|
||||||
|
// fold (ladd 0, 0, x) -> 0, x & 1
|
||||||
|
if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
|
||||||
|
SDValue Carry = DAG.getConstant(0, VT);
|
||||||
|
SDValue Result = DAG.getNode(ISD::AND, dl, VT, N2,
|
||||||
|
DAG.getConstant(1, VT));
|
||||||
|
SDValue Ops [] = { Carry, Result };
|
||||||
|
return DAG.getMergeValues(Ops, 2, dl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case XCoreISD::LSUB: {
|
||||||
|
SDValue N0 = N->getOperand(0);
|
||||||
|
SDValue N1 = N->getOperand(1);
|
||||||
|
SDValue N2 = N->getOperand(2);
|
||||||
|
ConstantSDNode *N0C = dyn_cast<ConstantSDNode>(N0);
|
||||||
|
ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
|
||||||
|
EVT VT = N0.getValueType();
|
||||||
|
|
||||||
|
// fold (lsub 0, 0, x) -> x, -x iff x has only the low bit set
|
||||||
|
if (N0C && N0C->isNullValue() && N1C && N1C->isNullValue()) {
|
||||||
|
APInt KnownZero, KnownOne;
|
||||||
|
APInt Mask = APInt::getHighBitsSet(VT.getSizeInBits(),
|
||||||
|
VT.getSizeInBits() - 1);
|
||||||
|
DAG.ComputeMaskedBits(N2, Mask, KnownZero, KnownOne);
|
||||||
|
if (KnownZero == Mask) {
|
||||||
|
SDValue Borrow = N2;
|
||||||
|
SDValue Result = DAG.getNode(ISD::SUB, dl, VT,
|
||||||
|
DAG.getConstant(0, VT), N2);
|
||||||
|
SDValue Ops [] = { Borrow, Result };
|
||||||
|
return DAG.getMergeValues(Ops, 2, dl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ISD::STORE: {
|
case ISD::STORE: {
|
||||||
// Replace unaligned store of unaligned load with memmove.
|
// Replace unaligned store of unaligned load with memmove.
|
||||||
StoreSDNode *ST = cast<StoreSDNode>(N);
|
StoreSDNode *ST = cast<StoreSDNode>(N);
|
||||||
|
@ -1137,6 +1179,27 @@ SDValue XCoreTargetLowering::PerformDAGCombine(SDNode *N,
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XCoreTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op,
|
||||||
|
const APInt &Mask,
|
||||||
|
APInt &KnownZero,
|
||||||
|
APInt &KnownOne,
|
||||||
|
const SelectionDAG &DAG,
|
||||||
|
unsigned Depth) const {
|
||||||
|
KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0);
|
||||||
|
switch (Op.getOpcode()) {
|
||||||
|
default: break;
|
||||||
|
case XCoreISD::LADD:
|
||||||
|
case XCoreISD::LSUB:
|
||||||
|
if (Op.getResNo() == 0) {
|
||||||
|
// Top bits of carry / borrow are clear.
|
||||||
|
KnownZero = APInt::getHighBitsSet(Mask.getBitWidth(),
|
||||||
|
Mask.getBitWidth() - 1);
|
||||||
|
KnownZero &= Mask;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Addressing mode description hooks
|
// Addressing mode description hooks
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -144,6 +144,13 @@ namespace llvm {
|
||||||
|
|
||||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
|
||||||
|
virtual void computeMaskedBitsForTargetNode(const SDValue Op,
|
||||||
|
const APInt &Mask,
|
||||||
|
APInt &KnownZero,
|
||||||
|
APInt &KnownOne,
|
||||||
|
const SelectionDAG &DAG,
|
||||||
|
unsigned Depth = 0) const;
|
||||||
|
|
||||||
virtual SDValue
|
virtual SDValue
|
||||||
LowerFormalArguments(SDValue Chain,
|
LowerFormalArguments(SDValue Chain,
|
||||||
CallingConv::ID CallConv,
|
CallingConv::ID CallConv,
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
; RUN: llvm-as < %s | llc -march=xcore | FileCheck %s
|
||||||
|
|
||||||
|
; Only needs one ladd
|
||||||
|
define i64 @f1(i32 %x, i32 %y) nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = zext i32 %x to i64 ; <i64> [#uses=1]
|
||||||
|
%1 = zext i32 %y to i64 ; <i64> [#uses=1]
|
||||||
|
%2 = add i64 %1, %0 ; <i64> [#uses=1]
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
; CHECK: f1:
|
||||||
|
; CHECK: ldc r2, 0
|
||||||
|
; CHECK-NEXT: ladd r1, r0, r1, r0, r2
|
||||||
|
; CHECK-NEXT: retsp 0
|
||||||
|
|
||||||
|
; Only needs one lsub and one neg
|
||||||
|
define i64 @f2(i32 %x, i32 %y) nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = zext i32 %x to i64 ; <i64> [#uses=1]
|
||||||
|
%1 = zext i32 %y to i64 ; <i64> [#uses=1]
|
||||||
|
%2 = sub i64 %1, %0 ; <i64> [#uses=1]
|
||||||
|
ret i64 %2
|
||||||
|
}
|
||||||
|
; CHECK: f2:
|
||||||
|
; CHECK: ldc r2, 0
|
||||||
|
; CHECK-NEXT: lsub r1, r0, r1, r0, r2
|
||||||
|
; CHECK-NEXT: neg r1, r1
|
||||||
|
; CHECK-NEXT: retsp 0
|
Loading…
Reference in New Issue