From 92b38a9d1c2c8dcd1055de5dc1458ec24baee4da Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Sat, 1 Mar 2014 21:36:57 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202600 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelLowering.cpp | 94 +++++++++++++++++++++++++++++----- test/CodeGen/PowerPC/crbits.ll | 32 +++++++++++- 2 files changed, 112 insertions(+), 14 deletions(-) diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index f56f0cf84cc..7dc47be0d51 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -563,10 +563,11 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) setTargetDAGCombine(ISD::BSWAP); setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN); + setTargetDAGCombine(ISD::SIGN_EXTEND); + setTargetDAGCombine(ISD::ZERO_EXTEND); + setTargetDAGCombine(ISD::ANY_EXTEND); + if (Subtarget->useCRBits()) { - setTargetDAGCombine(ISD::SIGN_EXTEND); - setTargetDAGCombine(ISD::ZERO_EXTEND); - setTargetDAGCombine(ISD::ANY_EXTEND); setTargetDAGCombine(ISD::TRUNCATE); setTargetDAGCombine(ISD::SETCC); setTargetDAGCombine(ISD::SELECT_CC); @@ -7294,6 +7295,20 @@ SDValue PPCTargetLowering::DAGCombineTruncBoolExt(SDNode *N, SDNode *User = *UI; if (User != N && !Visited.count(User)) 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; if (User != N && !Visited.count(User)) 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; 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: // zext(binary-ops(trunc(x), trunc(y))) // 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 // 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 && N->getValueType(0) != MVT::i64) 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(); if (N->getOperand(0).getOpcode() != ISD::AND && @@ -7468,6 +7503,20 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N, SDNode *User = *UI; if (User != N && !Visited.count(User)) 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; if (User != N && !Visited.count(User)) 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; if (N->getOpcode() != ISD::ANY_EXTEND) { // If all of the inputs are not already sign/zero extended, then @@ -7491,12 +7555,15 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N, unsigned OpBits = Inputs[i].getOperand(0).getValueSizeInBits(); + assert(PromBits < OpBits && "Truncation not to a smaller bit count?"); + if ((N->getOpcode() == ISD::ZERO_EXTEND && !DAG.MaskedValueIsZero(Inputs[i].getOperand(0), - APInt::getHighBitsSet(OpBits, - OpBits-1))) || + APInt::getHighBitsSet(OpBits, + OpBits-PromBits))) || (N->getOpcode() == ISD::SIGN_EXTEND && - DAG.ComputeNumSignBits(Inputs[i].getOperand(0)) != OpBits)) { + DAG.ComputeNumSignBits(Inputs[i].getOperand(0)) < + (OpBits-(PromBits-1)))) { ReallyNeedsExt = true; break; } @@ -7580,16 +7647,19 @@ SDValue PPCTargetLowering::DAGCombineExtBoolTrunc(SDNode *N, if (!ReallyNeedsExt) 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) 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 && "Invalid extension type"); EVT ShiftAmountTy = getShiftAmountTy(N->getValueType(0)); 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), DAG.getNode(ISD::SHL, dl, N->getValueType(0), N->getOperand(0), ShiftCst), ShiftCst); diff --git a/test/CodeGen/PowerPC/crbits.ll b/test/CodeGen/PowerPC/crbits.ll index 7021102e523..06e90019db7 100644 --- a/test/CodeGen/PowerPC/crbits.ll +++ b/test/CodeGen/PowerPC/crbits.ll @@ -124,11 +124,39 @@ entry: ; CHECK-LABEL: @test7 ; CHECK: andi. {{[0-9]+}}, 3, 1 -; CHECK: isel [[REG1:[0-9]+]], 4, 5, 1 -; CHECK: extsw 3, [[REG1]] +; CHECK: isel 3, 4, 5, 1 ; 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 define float @test8(i1 zeroext %v2, float %v1, float %v3) #0 { entry: -- 2.11.0