Skip to content

Commit 18a4fdc

Browse files
committed
[X86,SimplifyCFG] Support conditional faulting load or store only
This is to fix a bug when a target only support conditional faulting load, see test case hoist_store_without_cstore. Add option disable-cload-cstore to emulate single load/store case.
1 parent 215c47e commit 18a4fdc

File tree

2 files changed

+772
-175
lines changed

2 files changed

+772
-175
lines changed

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ static cl::opt<unsigned> HoistLoadsStoresWithCondFaultingThreshold(
132132
"to speculatively execute to eliminate conditional branch "
133133
"(default = 6)"));
134134

135+
static cl::opt<unsigned> DisableCloadCstore(
136+
"disable-cload-cstore", cl::Hidden, cl::init(0),
137+
cl::desc("Control to disable cond-faulting-load(1)/cond-faulting-store(2)"
138+
"/all(3)"));
139+
135140
static cl::opt<unsigned>
136141
HoistCommonSkipLimit("simplifycfg-hoist-common-skip-limit", cl::Hidden,
137142
cl::init(20),
@@ -1682,22 +1687,22 @@ static bool areIdenticalUpToCommutativity(const Instruction *I1,
16821687
static void hoistConditionalLoadsStores(
16831688
BranchInst *BI,
16841689
SmallVectorImpl<Instruction *> &SpeculatedConditionalLoadsStores,
1685-
std::optional<bool> Invert) {
1690+
std::optional<bool> Invert, Instruction *Sel) {
16861691
auto &Context = BI->getParent()->getContext();
16871692
auto *VCondTy = FixedVectorType::get(Type::getInt1Ty(Context), 1);
16881693
auto *Cond = BI->getOperand(0);
16891694
// Construct the condition if needed.
16901695
BasicBlock *BB = BI->getParent();
1691-
IRBuilder<> Builder(
1692-
Invert.has_value() ? SpeculatedConditionalLoadsStores.back() : BI);
16931696
Value *Mask = nullptr;
16941697
Value *MaskFalse = nullptr;
16951698
Value *MaskTrue = nullptr;
16961699
if (Invert.has_value()) {
1700+
IRBuilder<> Builder(Sel ? Sel : SpeculatedConditionalLoadsStores.back());
16971701
Mask = Builder.CreateBitCast(
16981702
*Invert ? Builder.CreateXor(Cond, ConstantInt::getTrue(Context)) : Cond,
16991703
VCondTy);
17001704
} else {
1705+
IRBuilder<> Builder(BI);
17011706
MaskFalse = Builder.CreateBitCast(
17021707
Builder.CreateXor(Cond, ConstantInt::getTrue(Context)), VCondTy);
17031708
MaskTrue = Builder.CreateBitCast(Cond, VCondTy);
@@ -1723,13 +1728,20 @@ static void hoistConditionalLoadsStores(
17231728
PHINode *PN = nullptr;
17241729
Value *PassThru = nullptr;
17251730
if (Invert.has_value())
1726-
for (User *U : I->users())
1731+
for (User *U : I->users()) {
17271732
if ((PN = dyn_cast<PHINode>(U))) {
17281733
PassThru = Builder.CreateBitCast(
17291734
PeekThroughBitcasts(PN->getIncomingValueForBlock(BB)),
17301735
FixedVectorType::get(Ty, 1));
1731-
break;
1736+
} else if (auto *Ins = cast<Instruction>(U);
1737+
Sel && Ins->getParent() == BB) {
1738+
// This happens when store or/and a speculative instruction between
1739+
// load and store were hoisted to the BB. Make sure the masked load
1740+
// inserted before its use.
1741+
// We assume there's one of such use.
1742+
Builder.SetInsertPoint(Ins);
17321743
}
1744+
}
17331745
MaskedLoadStore = Builder.CreateMaskedLoad(
17341746
FixedVectorType::get(Ty, 1), Op0, LI->getAlign(), Mask, PassThru);
17351747
Value *NewLoadStore = Builder.CreateBitCast(MaskedLoadStore, Ty);
@@ -1769,10 +1781,10 @@ static bool isSafeCheapLoadStore(const Instruction *I,
17691781
const TargetTransformInfo &TTI) {
17701782
// Not handle volatile or atomic.
17711783
if (auto *L = dyn_cast<LoadInst>(I)) {
1772-
if (!L->isSimple())
1784+
if (!L->isSimple() || (DisableCloadCstore & 1))
17731785
return false;
17741786
} else if (auto *S = dyn_cast<StoreInst>(I)) {
1775-
if (!S->isSimple())
1787+
if (!S->isSimple() || (DisableCloadCstore & 2))
17761788
return false;
17771789
} else
17781790
return false;
@@ -3308,6 +3320,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
33083320
// If we get here, we can hoist the instruction and if-convert.
33093321
LLVM_DEBUG(dbgs() << "SPECULATIVELY EXECUTING BB" << *ThenBB << "\n";);
33103322

3323+
Instruction *Sel = nullptr;
33113324
// Insert a select of the value of the speculated store.
33123325
if (SpeculatedStoreValue) {
33133326
IRBuilder<NoFolder> Builder(BI);
@@ -3318,6 +3331,7 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
33183331
std::swap(TrueV, FalseV);
33193332
Value *S = Builder.CreateSelect(
33203333
BrCond, TrueV, FalseV, "spec.store.select", BI);
3334+
Sel = cast<Instruction>(S);
33213335
SpeculatedStore->setOperand(0, S);
33223336
SpeculatedStore->applyMergedLocation(BI->getDebugLoc(),
33233337
SpeculatedStore->getDebugLoc());
@@ -3390,7 +3404,8 @@ bool SimplifyCFGOpt::speculativelyExecuteBB(BranchInst *BI,
33903404
std::prev(ThenBB->end()));
33913405

33923406
if (!SpeculatedConditionalLoadsStores.empty())
3393-
hoistConditionalLoadsStores(BI, SpeculatedConditionalLoadsStores, Invert);
3407+
hoistConditionalLoadsStores(BI, SpeculatedConditionalLoadsStores, Invert,
3408+
Sel);
33943409

33953410
// Insert selects and rewrite the PHI operands.
33963411
IRBuilder<NoFolder> Builder(BI);
@@ -8042,7 +8057,7 @@ bool SimplifyCFGOpt::simplifyCondBranch(BranchInst *BI, IRBuilder<> &Builder) {
80428057

80438058
if (CanSpeculateConditionalLoadsStores()) {
80448059
hoistConditionalLoadsStores(BI, SpeculatedConditionalLoadsStores,
8045-
std::nullopt);
8060+
std::nullopt, nullptr);
80468061
return requestResimplify();
80478062
}
80488063
}

0 commit comments

Comments
 (0)