@@ -120,11 +120,13 @@ static cl::opt<bool>
120
120
HoistCommon (" simplifycfg-hoist-common" , cl::Hidden, cl::init(true ),
121
121
cl::desc(" Hoist common instructions up to the parent block" ));
122
122
123
- static cl::opt<bool > HoistLoadsStoresWithCondFaulting (
124
- " simplifycfg-hoist-loads-stores-with-cond-faulting" , cl::Hidden,
125
- cl::init (true ),
126
- cl::desc(" Hoist loads/stores if the target supports "
127
- " conditional faulting" ));
123
+ static cl::opt<bool > HoistLoadsWithCondFaulting (
124
+ " simplifycfg-hoist-loads-with-cond-faulting" , cl::Hidden, cl::init(true ),
125
+ cl::desc(" Hoist loads if the target supports conditional faulting" ));
126
+
127
+ static cl::opt<bool > HoistStoresWithCondFaulting (
128
+ " simplifycfg-hoist-stores-with-cond-faulting" , cl::Hidden, cl::init(true ),
129
+ cl::desc(" Hoist stores if the target supports conditional faulting" ));
128
130
129
131
static cl::opt<unsigned > HoistLoadsStoresWithCondFaultingThreshold (
130
132
" hoist-loads-stores-with-cond-faulting-threshold" , cl::Hidden, cl::init(6 ),
@@ -1682,22 +1684,22 @@ static bool areIdenticalUpToCommutativity(const Instruction *I1,
1682
1684
static void hoistConditionalLoadsStores (
1683
1685
BranchInst *BI,
1684
1686
SmallVectorImpl<Instruction *> &SpeculatedConditionalLoadsStores,
1685
- std::optional<bool > Invert) {
1687
+ std::optional<bool > Invert, Instruction *Sel ) {
1686
1688
auto &Context = BI->getParent ()->getContext ();
1687
1689
auto *VCondTy = FixedVectorType::get (Type::getInt1Ty (Context), 1 );
1688
1690
auto *Cond = BI->getOperand (0 );
1689
1691
// Construct the condition if needed.
1690
1692
BasicBlock *BB = BI->getParent ();
1691
- IRBuilder<> Builder (
1692
- Invert.has_value () ? SpeculatedConditionalLoadsStores.back () : BI);
1693
1693
Value *Mask = nullptr ;
1694
1694
Value *MaskFalse = nullptr ;
1695
1695
Value *MaskTrue = nullptr ;
1696
1696
if (Invert.has_value ()) {
1697
+ IRBuilder<> Builder (Sel ? Sel : SpeculatedConditionalLoadsStores.back ());
1697
1698
Mask = Builder.CreateBitCast (
1698
1699
*Invert ? Builder.CreateXor (Cond, ConstantInt::getTrue (Context)) : Cond,
1699
1700
VCondTy);
1700
1701
} else {
1702
+ IRBuilder<> Builder (BI);
1701
1703
MaskFalse = Builder.CreateBitCast (
1702
1704
Builder.CreateXor (Cond, ConstantInt::getTrue (Context)), VCondTy);
1703
1705
MaskTrue = Builder.CreateBitCast (Cond, VCondTy);
@@ -1723,13 +1725,20 @@ static void hoistConditionalLoadsStores(
1723
1725
PHINode *PN = nullptr ;
1724
1726
Value *PassThru = nullptr ;
1725
1727
if (Invert.has_value ())
1726
- for (User *U : I->users ())
1728
+ for (User *U : I->users ()) {
1727
1729
if ((PN = dyn_cast<PHINode>(U))) {
1728
1730
PassThru = Builder.CreateBitCast (
1729
1731
PeekThroughBitcasts (PN->getIncomingValueForBlock (BB)),
1730
1732
FixedVectorType::get (Ty, 1 ));
1731
- break ;
1733
+ } else if (auto *Ins = cast<Instruction>(U);
1734
+ Sel && Ins->getParent () == BB) {
1735
+ // This happens when store or/and a speculative instruction between
1736
+ // load and store were hoisted to the BB. Make sure the masked load
1737
+ // inserted before its use.
1738
+ // We assume there's one of such use.
1739
+ Builder.SetInsertPoint (Ins);
1732
1740
}
1741
+ }
1733
1742
MaskedLoadStore = Builder.CreateMaskedLoad (
1734
1743
FixedVectorType::get (Ty, 1 ), Op0, LI->getAlign (), Mask, PassThru);
1735
1744
Value *NewLoadStore = Builder.CreateBitCast (MaskedLoadStore, Ty);
@@ -1770,10 +1779,10 @@ static bool isSafeCheapLoadStore(const Instruction *I,
1770
1779
// Not handle volatile or atomic.
1771
1780
bool IsStore = false ;
1772
1781
if (auto *L = dyn_cast<LoadInst>(I)) {
1773
- if (!L->isSimple ())
1782
+ if (!L->isSimple () || !HoistLoadsWithCondFaulting )
1774
1783
return false ;
1775
1784
} else if (auto *S = dyn_cast<StoreInst>(I)) {
1776
- if (!S->isSimple ())
1785
+ if (!S->isSimple () || !HoistStoresWithCondFaulting )
1777
1786
return false ;
1778
1787
IsStore = true ;
1779
1788
} else
@@ -3214,8 +3223,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
3214
3223
SmallVector<Instruction *, 4 > SpeculatedDbgIntrinsics;
3215
3224
3216
3225
unsigned SpeculatedInstructions = 0 ;
3217
- bool HoistLoadsStores = HoistLoadsStoresWithCondFaulting &&
3218
- Options.HoistLoadsStoresWithCondFaulting ;
3226
+ bool HoistLoadsStores = Options.HoistLoadsStoresWithCondFaulting ;
3219
3227
SmallVector<Instruction *, 2 > SpeculatedConditionalLoadsStores;
3220
3228
Value *SpeculatedStoreValue = nullptr ;
3221
3229
StoreInst *SpeculatedStore = nullptr ;
@@ -3310,6 +3318,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
3310
3318
// If we get here, we can hoist the instruction and if-convert.
3311
3319
LLVM_DEBUG (dbgs () << " SPECULATIVELY EXECUTING BB" << *ThenBB << " \n " ;);
3312
3320
3321
+ Instruction *Sel = nullptr ;
3313
3322
// Insert a select of the value of the speculated store.
3314
3323
if (SpeculatedStoreValue) {
3315
3324
IRBuilder<NoFolder> Builder (BI);
@@ -3320,6 +3329,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
3320
3329
std::swap (TrueV, FalseV);
3321
3330
Value *S = Builder.CreateSelect (
3322
3331
BrCond, TrueV, FalseV, " spec.store.select" , BI);
3332
+ Sel = cast<Instruction>(S);
3323
3333
SpeculatedStore->setOperand (0 , S);
3324
3334
SpeculatedStore->applyMergedLocation (BI->getDebugLoc (),
3325
3335
SpeculatedStore->getDebugLoc ());
@@ -3392,7 +3402,8 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
3392
3402
std::prev (ThenBB->end ()));
3393
3403
3394
3404
if (!SpeculatedConditionalLoadsStores.empty ())
3395
- hoistConditionalLoadsStores (BI, SpeculatedConditionalLoadsStores, Invert);
3405
+ hoistConditionalLoadsStores (BI, SpeculatedConditionalLoadsStores, Invert,
3406
+ Sel);
3396
3407
3397
3408
// Insert selects and rewrite the PHI operands.
3398
3409
IRBuilder<NoFolder> Builder (BI);
@@ -8020,8 +8031,7 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
8020
8031
hoistCommonCodeFromSuccessors (BI, !Options.HoistCommonInsts ))
8021
8032
return requestResimplify ();
8022
8033
8023
- if (BI && HoistLoadsStoresWithCondFaulting &&
8024
- Options.HoistLoadsStoresWithCondFaulting &&
8034
+ if (BI && Options.HoistLoadsStoresWithCondFaulting &&
8025
8035
isProfitableToSpeculate (BI, std::nullopt, TTI)) {
8026
8036
SmallVector<Instruction *, 2 > SpeculatedConditionalLoadsStores;
8027
8037
auto CanSpeculateConditionalLoadsStores = [&]() {
@@ -8044,7 +8054,7 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
8044
8054
8045
8055
if (CanSpeculateConditionalLoadsStores ()) {
8046
8056
hoistConditionalLoadsStores (BI, SpeculatedConditionalLoadsStores,
8047
- std::nullopt);
8057
+ std::nullopt, nullptr );
8048
8058
return requestResimplify ();
8049
8059
}
8050
8060
}
0 commit comments