[llvm] r347424 - [DAGCombiner] refactor select-of-FP-constants transform
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 21 12:54:47 PST 2018
Author: spatel
Date: Wed Nov 21 12:54:47 2018
New Revision: 347424
URL: http://llvm.org/viewvc/llvm-project?rev=347424&view=rev
Log:
[DAGCombiner] refactor select-of-FP-constants transform
This transform needs to be limited.
We are converting to a constant pool load very early, and we
are turning loads that are independent of the select condition
(and therefore speculatable) into a dependent non-speculatable
load.
We may also be transferring a condition code from an FP register
to integer to create that dependent load.
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=347424&r1=347423&r2=347424&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed Nov 21 12:54:47 2018
@@ -416,6 +416,9 @@ namespace {
SDValue SimplifySelectCC(const SDLoc &DL, SDValue N0, SDValue N1,
SDValue N2, SDValue N3, ISD::CondCode CC,
bool NotExtCompare = false);
+ SDValue convertSelectOfFPConstantsToLoadOffset(
+ const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2, SDValue N3,
+ ISD::CondCode CC);
SDValue foldSelectCCToShiftAnd(const SDLoc &DL, SDValue N0, SDValue N1,
SDValue N2, SDValue N3, ISD::CondCode CC);
SDValue foldLogicOfSetCCs(bool IsAnd, SDValue N0, SDValue N1,
@@ -18166,6 +18169,60 @@ SDValue DAGCombiner::foldSelectCCToShift
return DAG.getNode(ISD::AND, DL, AType, Shift, N2);
}
+/// Turn "(a cond b) ? 1.0f : 2.0f" into "load (tmp + ((a cond b) ? 0 : 4)"
+/// where "tmp" is a constant pool entry containing an array with 1.0 and 2.0
+/// in it. This may be a win when the constant is not otherwise available
+/// because it replaces two constant pool loads with one.
+SDValue DAGCombiner::convertSelectOfFPConstantsToLoadOffset(
+ const SDLoc &DL, SDValue N0, SDValue N1, SDValue N2, SDValue N3,
+ ISD::CondCode CC) {
+ // If we are before legalize types, we want the other legalization to happen
+ // first (for example, to avoid messing with soft float).
+ auto *TV = dyn_cast<ConstantFPSDNode>(N2);
+ auto *FV = dyn_cast<ConstantFPSDNode>(N3);
+ EVT VT = N2.getValueType();
+ if (!TV || !FV || !TLI.isTypeLegal(VT))
+ return SDValue();
+
+ // If a constant can be materialized without loads, this does not make sense.
+ if (TLI.getOperationAction(ISD::ConstantFP, VT) == TargetLowering::Legal ||
+ TLI.isFPImmLegal(TV->getValueAPF(), TV->getValueType(0)) ||
+ TLI.isFPImmLegal(FV->getValueAPF(), FV->getValueType(0)))
+ return SDValue();
+
+ // If both constants have multiple uses, then we won't need to do an extra
+ // load. The values are likely around in registers for other users.
+ if (!TV->hasOneUse() && !FV->hasOneUse())
+ return SDValue();
+
+ Constant *Elts[] = { const_cast<ConstantFP*>(FV->getConstantFPValue()),
+ const_cast<ConstantFP*>(TV->getConstantFPValue()) };
+ Type *FPTy = Elts[0]->getType();
+ const DataLayout &TD = DAG.getDataLayout();
+
+ // Create a ConstantArray of the two constants.
+ Constant *CA = ConstantArray::get(ArrayType::get(FPTy, 2), Elts);
+ SDValue CPIdx = DAG.getConstantPool(CA, TLI.getPointerTy(DAG.getDataLayout()),
+ TD.getPrefTypeAlignment(FPTy));
+ unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
+
+ // Get offsets to the 0 and 1 elements of the array, so we can select between
+ // them.
+ SDValue Zero = DAG.getIntPtrConstant(0, DL);
+ unsigned EltSize = (unsigned)TD.getTypeAllocSize(Elts[0]->getType());
+ SDValue One = DAG.getIntPtrConstant(EltSize, SDLoc(FV));
+ SDValue Cond =
+ DAG.getSetCC(DL, getSetCCResultType(N0.getValueType()), N0, N1, CC);
+ AddToWorklist(Cond.getNode());
+ SDValue CstOffset = DAG.getSelect(DL, Zero.getValueType(), Cond, One, Zero);
+ AddToWorklist(CstOffset.getNode());
+ CPIdx = DAG.getNode(ISD::ADD, DL, CPIdx.getValueType(), CPIdx, CstOffset);
+ AddToWorklist(CPIdx.getNode());
+ return DAG.getLoad(TV->getValueType(0), DL, DAG.getEntryNode(), CPIdx,
+ MachinePointerInfo::getConstantPool(
+ DAG.getMachineFunction()), Alignment);
+}
+
/// Simplify an expression of the form (N0 cond N1) ? N2 : N3
/// where 'cond' is the comparison specified by CC.
SDValue DAGCombiner::SimplifySelectCC(const SDLoc &DL, SDValue N0, SDValue N1,
@@ -18191,59 +18248,9 @@ SDValue DAGCombiner::SimplifySelectCC(co
return !SCCC->isNullValue() ? N2 : N3;
}
- // Turn "(a cond b) ? 1.0f : 2.0f" into "load (tmp + ((a cond b) ? 0 : 4)"
- // where "tmp" is a constant pool entry containing an array with 1.0 and 2.0
- // in it. This is a win when the constant is not otherwise available because
- // it replaces two constant pool loads with one. We only do this if the FP
- // type is known to be legal, because if it isn't, then we are before legalize
- // types an we want the other legalization to happen first (e.g. to avoid
- // messing with soft float) and if the ConstantFP is not legal, because if
- // it is legal, we may not need to store the FP constant in a constant pool.
- if (auto *TV = dyn_cast<ConstantFPSDNode>(N2))
- if (auto *FV = dyn_cast<ConstantFPSDNode>(N3)) {
- if (TLI.isTypeLegal(VT) &&
- (TLI.getOperationAction(ISD::ConstantFP, VT) !=
- TargetLowering::Legal &&
- !TLI.isFPImmLegal(TV->getValueAPF(), TV->getValueType(0)) &&
- !TLI.isFPImmLegal(FV->getValueAPF(), FV->getValueType(0))) &&
- // If both constants have multiple uses, then we won't need to do an
- // extra load, they are likely around in registers for other users.
- (TV->hasOneUse() || FV->hasOneUse())) {
- Constant *Elts[] = {
- const_cast<ConstantFP*>(FV->getConstantFPValue()),
- const_cast<ConstantFP*>(TV->getConstantFPValue())
- };
- Type *FPTy = Elts[0]->getType();
- const DataLayout &TD = DAG.getDataLayout();
-
- // Create a ConstantArray of the two constants.
- Constant *CA = ConstantArray::get(ArrayType::get(FPTy, 2), Elts);
- SDValue CPIdx =
- DAG.getConstantPool(CA, TLI.getPointerTy(DAG.getDataLayout()),
- TD.getPrefTypeAlignment(FPTy));
- unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
-
- // Get the offsets to the 0 and 1 element of the array so that we can
- // select between them.
- SDValue Zero = DAG.getIntPtrConstant(0, DL);
- unsigned EltSize = (unsigned)TD.getTypeAllocSize(Elts[0]->getType());
- SDValue One = DAG.getIntPtrConstant(EltSize, SDLoc(FV));
-
- SDValue Cond = DAG.getSetCC(DL, getSetCCResultType(CmpOpVT), N0, N1,
- CC);
- AddToWorklist(Cond.getNode());
- SDValue CstOffset = DAG.getSelect(DL, Zero.getValueType(),
- Cond, One, Zero);
- AddToWorklist(CstOffset.getNode());
- CPIdx = DAG.getNode(ISD::ADD, DL, CPIdx.getValueType(), CPIdx,
- CstOffset);
- AddToWorklist(CPIdx.getNode());
- return DAG.getLoad(
- TV->getValueType(0), DL, DAG.getEntryNode(), CPIdx,
- MachinePointerInfo::getConstantPool(DAG.getMachineFunction()),
- Alignment);
- }
- }
+ if (SDValue V =
+ convertSelectOfFPConstantsToLoadOffset(DL, N0, N1, N2, N3, CC))
+ return V;
if (SDValue V = foldSelectCCToShiftAnd(DL, N0, N1, N2, N3, CC))
return V;
More information about the llvm-commits
mailing list