mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
Remove extra truncs/exts around i32 bit operations on PPC64
This generalizes the code to eliminate extra truncs/exts around i1 bit operations to also do the same on PPC64 for i32 bit operations. This eliminates a fairly prevalent code wart: int foo(int a) { return a == 5 ? 7 : 8; } On PPC64, because of the extension implied by the ABI, this would generate: cmplwi 0, 3, 5 li 12, 8 li 4, 7 isel 3, 4, 12, 2 rldicl 3, 3, 0, 32 blr where the 'rldicl 3, 3, 0, 32', the extension, is completely unnecessary. At least for the single-BB case (which is all that the DAG combine mechanism can handle), this unnecessary extension is no longer generated. llvm-svn: 202600
This commit is contained in:
parent
44a4d4b894
commit
4937443651
@ -563,10 +563,11 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
|
|||||||
setTargetDAGCombine(ISD::BSWAP);
|
setTargetDAGCombine(ISD::BSWAP);
|
||||||
setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
|
setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
|
||||||
|
|
||||||
if (Subtarget->useCRBits()) {
|
|
||||||
setTargetDAGCombine(ISD::SIGN_EXTEND);
|
setTargetDAGCombine(ISD::SIGN_EXTEND);
|
||||||
setTargetDAGCombine(ISD::ZERO_EXTEND);
|
setTargetDAGCombine(ISD::ZERO_EXTEND);
|
||||||
setTargetDAGCombine(ISD::ANY_EXTEND);
|
setTargetDAGCombine(ISD::ANY_EXTEND);
|
||||||
|
|
||||||
|
if (Subtarget->useCRBits()) {
|
||||||
setTargetDAGCombine(ISD::TRUNCATE);
|
setTargetDAGCombine(ISD::TRUNCATE);
|
||||||
setTargetDAGCombine(ISD::SETCC);
|
setTargetDAGCombine(ISD::SETCC);
|
||||||
setTargetDAGCombine(ISD::SELECT_CC);
|
setTargetDAGCombine(ISD::SELECT_CC);
|
||||||
@ -7294,6 +7295,20 @@ SDValue PPCTargetLowering::DAGCombineTruncBoolExt(SDNode *N,
|
|||||||
SDNode *User = *UI;
|
SDNode *User = *UI;
|
||||||
if (User != N && !Visited.count(User))
|
if (User != N && !Visited.count(User))
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
|
// Make sure that we're not going to promote the non-output-value
|
||||||
|
// operand(s) or SELECT or SELECT_CC.
|
||||||
|
// FIXME: Although we could sometimes handle this, and it does occur in
|
||||||
|
// practice that one of the condition inputs to the select is also one of
|
||||||
|
// the outputs, we currently can't deal with this.
|
||||||
|
if (User->getOpcode() == ISD::SELECT) {
|
||||||
|
if (User->getOperand(0) == Inputs[i])
|
||||||
|
return SDValue();
|
||||||
|
} else if (User->getOpcode() == ISD::SELECT_CC) {
|
||||||
|
if (User->getOperand(0) == Inputs[i] ||
|
||||||
|
User->getOperand(1) == Inputs[i])
|
||||||
|
return SDValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7304,6 +7319,20 @@ SDValue PPCTargetLowering::DAGCombineTruncBoolExt(SDNode *N,
|
|||||||
SDNode *User = *UI;
|
SDNode *User = *UI;
|
||||||
if (User != N && !Visited.count(User))
|
if (User != N && !Visited.count(User))
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
|
// Make sure that we're not going to promote the non-output-value
|
||||||
|
// operand(s) or SELECT or SELECT_CC.
|
||||||
|
// FIXME: Although we could sometimes handle this, and it does occur in
|
||||||
|
// practice that one of the condition inputs to the select is also one of
|
||||||
|
// the outputs, we currently can't deal with this.
|
||||||
|
if (User->getOpcode() == ISD::SELECT) {
|
||||||
|
if (User->getOperand(0) == PromOps[i])
|
||||||
|
return SDValue();
|
||||||
|
} else if (User->getOpcode() == ISD::SELECT_CC) {
|
||||||
|
if (User->getOperand(0) == PromOps[i] ||
|
||||||
|
User->getOperand(1) == PromOps[i])
|
||||||
|
return SDValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7391,8 +7420,6 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N,
|
|||||||
SelectionDAG &DAG = DCI.DAG;
|
SelectionDAG &DAG = DCI.DAG;
|
||||||
SDLoc dl(N);
|
SDLoc dl(N);
|
||||||
|
|
||||||
assert(PPCSubTarget.useCRBits() &&
|
|
||||||
"Expecting to be tracking CR bits");
|
|
||||||
// If we're tracking CR bits, we need to be careful that we don't have:
|
// If we're tracking CR bits, we need to be careful that we don't have:
|
||||||
// zext(binary-ops(trunc(x), trunc(y)))
|
// zext(binary-ops(trunc(x), trunc(y)))
|
||||||
// or
|
// or
|
||||||
@ -7402,11 +7429,19 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N,
|
|||||||
// bits are set as required by the final extension, we still may need to do
|
// bits are set as required by the final extension, we still may need to do
|
||||||
// some masking to get the proper behavior.
|
// some masking to get the proper behavior.
|
||||||
|
|
||||||
|
// This same functionality is important on PPC64 when dealing with
|
||||||
|
// 32-to-64-bit extensions; these occur often when 32-bit values are used as
|
||||||
|
// the return values of functions. Because it is so similar, it is handled
|
||||||
|
// here as well.
|
||||||
|
|
||||||
if (N->getValueType(0) != MVT::i32 &&
|
if (N->getValueType(0) != MVT::i32 &&
|
||||||
N->getValueType(0) != MVT::i64)
|
N->getValueType(0) != MVT::i64)
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
if (N->getOperand(0).getValueType() != MVT::i1)
|
if (!((N->getOperand(0).getValueType() == MVT::i1 &&
|
||||||
|
PPCSubTarget.useCRBits()) ||
|
||||||
|
(N->getOperand(0).getValueType() == MVT::i32 &&
|
||||||
|
PPCSubTarget.isPPC64())))
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
if (N->getOperand(0).getOpcode() != ISD::AND &&
|
if (N->getOperand(0).getOpcode() != ISD::AND &&
|
||||||
@ -7468,6 +7503,20 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N,
|
|||||||
SDNode *User = *UI;
|
SDNode *User = *UI;
|
||||||
if (User != N && !Visited.count(User))
|
if (User != N && !Visited.count(User))
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
|
// Make sure that we're not going to promote the non-output-value
|
||||||
|
// operand(s) or SELECT or SELECT_CC.
|
||||||
|
// FIXME: Although we could sometimes handle this, and it does occur in
|
||||||
|
// practice that one of the condition inputs to the select is also one of
|
||||||
|
// the outputs, we currently can't deal with this.
|
||||||
|
if (User->getOpcode() == ISD::SELECT) {
|
||||||
|
if (User->getOperand(0) == Inputs[i])
|
||||||
|
return SDValue();
|
||||||
|
} else if (User->getOpcode() == ISD::SELECT_CC) {
|
||||||
|
if (User->getOperand(0) == Inputs[i] ||
|
||||||
|
User->getOperand(1) == Inputs[i])
|
||||||
|
return SDValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7478,9 +7527,24 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N,
|
|||||||
SDNode *User = *UI;
|
SDNode *User = *UI;
|
||||||
if (User != N && !Visited.count(User))
|
if (User != N && !Visited.count(User))
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
|
// Make sure that we're not going to promote the non-output-value
|
||||||
|
// operand(s) or SELECT or SELECT_CC.
|
||||||
|
// FIXME: Although we could sometimes handle this, and it does occur in
|
||||||
|
// practice that one of the condition inputs to the select is also one of
|
||||||
|
// the outputs, we currently can't deal with this.
|
||||||
|
if (User->getOpcode() == ISD::SELECT) {
|
||||||
|
if (User->getOperand(0) == PromOps[i])
|
||||||
|
return SDValue();
|
||||||
|
} else if (User->getOpcode() == ISD::SELECT_CC) {
|
||||||
|
if (User->getOperand(0) == PromOps[i] ||
|
||||||
|
User->getOperand(1) == PromOps[i])
|
||||||
|
return SDValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned PromBits = N->getOperand(0).getValueSizeInBits();
|
||||||
bool ReallyNeedsExt = false;
|
bool ReallyNeedsExt = false;
|
||||||
if (N->getOpcode() != ISD::ANY_EXTEND) {
|
if (N->getOpcode() != ISD::ANY_EXTEND) {
|
||||||
// If all of the inputs are not already sign/zero extended, then
|
// If all of the inputs are not already sign/zero extended, then
|
||||||
@ -7491,12 +7555,15 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N,
|
|||||||
|
|
||||||
unsigned OpBits =
|
unsigned OpBits =
|
||||||
Inputs[i].getOperand(0).getValueSizeInBits();
|
Inputs[i].getOperand(0).getValueSizeInBits();
|
||||||
|
assert(PromBits < OpBits && "Truncation not to a smaller bit count?");
|
||||||
|
|
||||||
if ((N->getOpcode() == ISD::ZERO_EXTEND &&
|
if ((N->getOpcode() == ISD::ZERO_EXTEND &&
|
||||||
!DAG.MaskedValueIsZero(Inputs[i].getOperand(0),
|
!DAG.MaskedValueIsZero(Inputs[i].getOperand(0),
|
||||||
APInt::getHighBitsSet(OpBits,
|
APInt::getHighBitsSet(OpBits,
|
||||||
OpBits-1))) ||
|
OpBits-PromBits))) ||
|
||||||
(N->getOpcode() == ISD::SIGN_EXTEND &&
|
(N->getOpcode() == ISD::SIGN_EXTEND &&
|
||||||
DAG.ComputeNumSignBits(Inputs[i].getOperand(0)) != OpBits)) {
|
DAG.ComputeNumSignBits(Inputs[i].getOperand(0)) <
|
||||||
|
(OpBits-(PromBits-1)))) {
|
||||||
ReallyNeedsExt = true;
|
ReallyNeedsExt = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -7580,16 +7647,19 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N,
|
|||||||
if (!ReallyNeedsExt)
|
if (!ReallyNeedsExt)
|
||||||
return N->getOperand(0);
|
return N->getOperand(0);
|
||||||
|
|
||||||
// To zero extend, just mask off everything except for the first bit.
|
// To zero extend, just mask off everything except for the first bit (in the
|
||||||
|
// i1 case).
|
||||||
if (N->getOpcode() == ISD::ZERO_EXTEND)
|
if (N->getOpcode() == ISD::ZERO_EXTEND)
|
||||||
return DAG.getNode(ISD::AND, dl, N->getValueType(0), N->getOperand(0),
|
return DAG.getNode(ISD::AND, dl, N->getValueType(0), N->getOperand(0),
|
||||||
DAG.getConstant(1, N->getValueType(0)));
|
DAG.getConstant(APInt::getLowBitsSet(
|
||||||
|
N->getValueSizeInBits(0), PromBits),
|
||||||
|
N->getValueType(0)));
|
||||||
|
|
||||||
assert(N->getOpcode() == ISD::SIGN_EXTEND &&
|
assert(N->getOpcode() == ISD::SIGN_EXTEND &&
|
||||||
"Invalid extension type");
|
"Invalid extension type");
|
||||||
EVT ShiftAmountTy = getShiftAmountTy(N->getValueType(0));
|
EVT ShiftAmountTy = getShiftAmountTy(N->getValueType(0));
|
||||||
SDValue ShiftCst =
|
SDValue ShiftCst =
|
||||||
DAG.getConstant(N->getValueSizeInBits(0)-1, ShiftAmountTy);
|
DAG.getConstant(N->getValueSizeInBits(0)-PromBits, ShiftAmountTy);
|
||||||
return DAG.getNode(ISD::SRA, dl, N->getValueType(0),
|
return DAG.getNode(ISD::SRA, dl, N->getValueType(0),
|
||||||
DAG.getNode(ISD::SHL, dl, N->getValueType(0),
|
DAG.getNode(ISD::SHL, dl, N->getValueType(0),
|
||||||
N->getOperand(0), ShiftCst), ShiftCst);
|
N->getOperand(0), ShiftCst), ShiftCst);
|
||||||
|
@ -124,11 +124,39 @@ entry:
|
|||||||
|
|
||||||
; CHECK-LABEL: @test7
|
; CHECK-LABEL: @test7
|
||||||
; CHECK: andi. {{[0-9]+}}, 3, 1
|
; CHECK: andi. {{[0-9]+}}, 3, 1
|
||||||
; CHECK: isel [[REG1:[0-9]+]], 4, 5, 1
|
; CHECK: isel 3, 4, 5, 1
|
||||||
; CHECK: extsw 3, [[REG1]]
|
|
||||||
; CHECK: blr
|
; CHECK: blr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define signext i32 @exttest7(i32 signext %a) #0 {
|
||||||
|
entry:
|
||||||
|
%cmp = icmp eq i32 %a, 5
|
||||||
|
%cond = select i1 %cmp, i32 7, i32 8
|
||||||
|
ret i32 %cond
|
||||||
|
|
||||||
|
; CHECK-LABEL: @exttest7
|
||||||
|
; CHECK-DAG: cmplwi {{[0-9]+}}, 3, 5
|
||||||
|
; CHECK-DAG: li [[REG1:[0-9]+]], 8
|
||||||
|
; CHECK-DAG: li [[REG2:[0-9]+]], 7
|
||||||
|
; CHECK: isel 3, [[REG2]], [[REG1]],
|
||||||
|
; CHECK-NOT: rldicl
|
||||||
|
; CHECK: blr
|
||||||
|
}
|
||||||
|
|
||||||
|
define zeroext i32 @exttest8() #0 {
|
||||||
|
entry:
|
||||||
|
%v0 = load i64* undef, align 8
|
||||||
|
%sub = sub i64 80, %v0
|
||||||
|
%div = lshr i64 %sub, 1
|
||||||
|
%conv13 = trunc i64 %div to i32
|
||||||
|
%cmp14 = icmp ugt i32 %conv13, 80
|
||||||
|
%.conv13 = select i1 %cmp14, i32 0, i32 %conv13
|
||||||
|
ret i32 %.conv13
|
||||||
|
; CHECK-LABEL: @exttest8
|
||||||
|
; This is a don't-crash test: %conv13 is both one of the possible select output
|
||||||
|
; values and also an input to the conditional feeding it.
|
||||||
|
}
|
||||||
|
|
||||||
; Function Attrs: nounwind readnone
|
; Function Attrs: nounwind readnone
|
||||||
define float @test8(i1 zeroext %v2, float %v1, float %v3) #0 {
|
define float @test8(i1 zeroext %v2, float %v1, float %v3) #0 {
|
||||||
entry:
|
entry:
|
||||||
|
Loading…
Reference in New Issue
Block a user