@@ -1025,6 +1025,8 @@ void SelectionDAGBuilder::clear() {
1025
1025
UnusedArgNodeMap.clear ();
1026
1026
PendingLoads.clear ();
1027
1027
PendingExports.clear ();
1028
+ PendingConstrainedFP.clear ();
1029
+ PendingConstrainedFPStrict.clear ();
1028
1030
CurInst = nullptr ;
1029
1031
HasTailCall = false ;
1030
1032
SDNodeOrder = LowestSDNodeOrder;
@@ -1035,7 +1037,7 @@ void SelectionDAGBuilder::clearDanglingDebugInfo() {
1035
1037
DanglingDebugInfoMap.clear ();
1036
1038
}
1037
1039
1038
- SDValue SelectionDAGBuilder::getRoot () {
1040
+ SDValue SelectionDAGBuilder::getMemoryRoot () {
1039
1041
if (PendingLoads.empty ())
1040
1042
return DAG.getRoot ();
1041
1043
@@ -1053,9 +1055,31 @@ SDValue SelectionDAGBuilder::getRoot() {
1053
1055
return Root;
1054
1056
}
1055
1057
1058
+ SDValue SelectionDAGBuilder::getRoot () {
1059
+ // Chain up all pending constrained intrinsics together with all
1060
+ // pending loads, by simply appending them to PendingLoads and
1061
+ // then calling getMemoryRoot().
1062
+ PendingLoads.reserve (PendingLoads.size () +
1063
+ PendingConstrainedFP.size () +
1064
+ PendingConstrainedFPStrict.size ());
1065
+ PendingLoads.append (PendingConstrainedFP.begin (),
1066
+ PendingConstrainedFP.end ());
1067
+ PendingLoads.append (PendingConstrainedFPStrict.begin (),
1068
+ PendingConstrainedFPStrict.end ());
1069
+ PendingConstrainedFP.clear ();
1070
+ PendingConstrainedFPStrict.clear ();
1071
+ return getMemoryRoot ();
1072
+ }
1073
+
1056
1074
SDValue SelectionDAGBuilder::getControlRoot () {
1057
1075
SDValue Root = DAG.getRoot ();
1058
1076
1077
+ // We need to emit pending fpexcept.strict constrained intrinsics,
1078
+ // so append them to the PendingExports list.
1079
+ PendingExports.append (PendingConstrainedFPStrict.begin (),
1080
+ PendingConstrainedFPStrict.end ());
1081
+ PendingConstrainedFPStrict.clear ();
1082
+
1059
1083
if (PendingExports.empty ())
1060
1084
return Root;
1061
1085
@@ -4060,9 +4084,11 @@ void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
4060
4084
4061
4085
SDValue Root;
4062
4086
bool ConstantMemory = false ;
4063
- if (isVolatile || NumValues > MaxParallelChains )
4087
+ if (isVolatile)
4064
4088
// Serialize volatile loads with other side effects.
4065
4089
Root = getRoot ();
4090
+ else if (NumValues > MaxParallelChains)
4091
+ Root = getMemoryRoot ();
4066
4092
else if (AA &&
4067
4093
AA->pointsToConstantMemory (MemoryLocation (
4068
4094
SV,
@@ -4237,7 +4263,7 @@ void SelectionDAGBuilder::visitStore(const StoreInst &I) {
4237
4263
SDValue Src = getValue (SrcV);
4238
4264
SDValue Ptr = getValue (PtrV);
4239
4265
4240
- SDValue Root = getRoot ();
4266
+ SDValue Root = I. isVolatile () ? getRoot () : getMemoryRoot ();
4241
4267
SmallVector<SDValue, 4 > Chains (std::min (MaxParallelChains, NumValues));
4242
4268
SDLoc dl = getCurSDLoc ();
4243
4269
unsigned Alignment = I.getAlignment ();
@@ -4329,7 +4355,7 @@ void SelectionDAGBuilder::visitMaskedStore(const CallInst &I,
4329
4355
VT.getStoreSize ().getKnownMinSize (),
4330
4356
Alignment, AAInfo);
4331
4357
SDValue StoreNode =
4332
- DAG.getMaskedStore (getRoot (), sdl, Src0, Ptr, Offset, Mask, VT, MMO,
4358
+ DAG.getMaskedStore (getMemoryRoot (), sdl, Src0, Ptr, Offset, Mask, VT, MMO,
4333
4359
ISD::UNINDEXED, false /* Truncating */ , IsCompressing);
4334
4360
DAG.setRoot (StoreNode);
4335
4361
setValue (&I, StoreNode);
@@ -4463,7 +4489,7 @@ void SelectionDAGBuilder::visitMaskedScatter(const CallInst &I) {
4463
4489
IndexType = ISD::SIGNED_SCALED;
4464
4490
Scale = DAG.getTargetConstant (1 , sdl, TLI.getPointerTy (DAG.getDataLayout ()));
4465
4491
}
4466
- SDValue Ops[] = { getRoot (), Src0, Mask, Base, Index, Scale };
4492
+ SDValue Ops[] = { getMemoryRoot (), Src0, Mask, Base, Index, Scale };
4467
4493
SDValue Scatter = DAG.getMaskedScatter (DAG.getVTList (MVT::Other), VT, sdl,
4468
4494
Ops, MMO, IndexType);
4469
4495
DAG.setRoot (Scatter);
@@ -5850,7 +5876,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
5850
5876
bool isTC = I.isTailCall () && isInTailCallPosition (&I, DAG.getTarget ());
5851
5877
// FIXME: Support passing different dest/src alignments to the memcpy DAG
5852
5878
// node.
5853
- SDValue MC = DAG.getMemcpy (getRoot (), sdl, Op1, Op2, Op3, Align, isVol,
5879
+ SDValue Root = isVol ? getRoot () : getMemoryRoot ();
5880
+ SDValue MC = DAG.getMemcpy (Root, sdl, Op1, Op2, Op3, Align, isVol,
5854
5881
false , isTC,
5855
5882
MachinePointerInfo (I.getArgOperand (0 )),
5856
5883
MachinePointerInfo (I.getArgOperand (1 )));
@@ -5866,7 +5893,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
5866
5893
unsigned Align = std::max<unsigned >(MSI.getDestAlignment (), 1 );
5867
5894
bool isVol = MSI.isVolatile ();
5868
5895
bool isTC = I.isTailCall () && isInTailCallPosition (&I, DAG.getTarget ());
5869
- SDValue MS = DAG.getMemset (getRoot (), sdl, Op1, Op2, Op3, Align, isVol,
5896
+ SDValue Root = isVol ? getRoot () : getMemoryRoot ();
5897
+ SDValue MS = DAG.getMemset (Root, sdl, Op1, Op2, Op3, Align, isVol,
5870
5898
isTC, MachinePointerInfo (I.getArgOperand (0 )));
5871
5899
updateDAGForMaybeTailCall (MS);
5872
5900
return ;
@@ -5884,7 +5912,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
5884
5912
bool isTC = I.isTailCall () && isInTailCallPosition (&I, DAG.getTarget ());
5885
5913
// FIXME: Support passing different dest/src alignments to the memmove DAG
5886
5914
// node.
5887
- SDValue MM = DAG.getMemmove (getRoot (), sdl, Op1, Op2, Op3, Align, isVol,
5915
+ SDValue Root = isVol ? getRoot () : getMemoryRoot ();
5916
+ SDValue MM = DAG.getMemmove (Root, sdl, Op1, Op2, Op3, Align, isVol,
5888
5917
isTC, MachinePointerInfo (I.getArgOperand (0 )),
5889
5918
MachinePointerInfo (I.getArgOperand (1 )));
5890
5919
updateDAGForMaybeTailCall (MM);
@@ -7039,9 +7068,29 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
7039
7068
SDValue Result = DAG.getNode (Opcode, sdl, VTs, Opers);
7040
7069
7041
7070
assert (Result.getNode ()->getNumValues () == 2 );
7042
- // See above -- chain is handled like for loads here.
7071
+
7072
+ // Push node to the appropriate list so that future instructions can be
7073
+ // chained up correctly.
7043
7074
SDValue OutChain = Result.getValue (1 );
7044
- PendingLoads.push_back (OutChain);
7075
+ switch (FPI.getExceptionBehavior ().getValue ()) {
7076
+ case fp::ExceptionBehavior::ebIgnore:
7077
+ // The only reason why ebIgnore nodes still need to be chained is that
7078
+ // they might depend on the current rounding mode, and therefore must
7079
+ // not be moved across instruction that may change that mode.
7080
+ LLVM_FALLTHROUGH;
7081
+ case fp::ExceptionBehavior::ebMayTrap:
7082
+ // These must not be moved across calls or instructions that may change
7083
+ // floating-point exception masks.
7084
+ PendingConstrainedFP.push_back (OutChain);
7085
+ break ;
7086
+ case fp::ExceptionBehavior::ebStrict:
7087
+ // These must not be moved across calls or instructions that may change
7088
+ // floating-point exception masks or read floating-point exception flags.
7089
+ // In addition, they cannot be optimized out even if unused.
7090
+ PendingConstrainedFPStrict.push_back (OutChain);
7091
+ break ;
7092
+ }
7093
+
7045
7094
SDValue FPResult = Result.getValue (0 );
7046
7095
setValue (&FPI, FPResult);
7047
7096
}
@@ -7424,7 +7473,8 @@ bool SelectionDAGBuilder::visitMemPCpyCall(const CallInst &I) {
7424
7473
// In the mempcpy context we need to pass in a false value for isTailCall
7425
7474
// because the return pointer needs to be adjusted by the size of
7426
7475
// the copied memory.
7427
- SDValue MC = DAG.getMemcpy (getRoot (), sdl, Dst, Src, Size, Align, isVol,
7476
+ SDValue Root = isVol ? getRoot () : getMemoryRoot ();
7477
+ SDValue MC = DAG.getMemcpy (Root, sdl, Dst, Src, Size, Align, isVol,
7428
7478
false , /* isTailCall=*/ false ,
7429
7479
MachinePointerInfo (I.getArgOperand (0 )),
7430
7480
MachinePointerInfo (I.getArgOperand (1 )));
0 commit comments