Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit 5307076

Browse files
committed
[InstCombine] re-commit r218721 icmp-select-icmp optimization
Takes care of the assert that caused build fails. Rather than asserting the code checks now that the definition and use are in the same block, and does not attempt to optimize when that is not the case. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219175 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 844eeb3 commit 5307076

File tree

4 files changed

+152
-9
lines changed

4 files changed

+152
-9
lines changed

lib/Transforms/InstCombine/InstCombine.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "llvm/Analysis/AssumptionTracker.h"
1515
#include "llvm/Analysis/TargetFolder.h"
1616
#include "llvm/Analysis/ValueTracking.h"
17+
#include "llvm/IR/Dominators.h"
1718
#include "llvm/IR/IRBuilder.h"
1819
#include "llvm/IR/InstVisitor.h"
1920
#include "llvm/IR/IntrinsicInst.h"
@@ -97,8 +98,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner
9798
public InstVisitor<InstCombiner, Instruction *> {
9899
AssumptionTracker *AT;
99100
const DataLayout *DL;
100-
TargetLibraryInfo *TLI;
101101
DominatorTree *DT; // not required
102+
TargetLibraryInfo *TLI;
102103
bool MadeIRChange;
103104
LibCallSimplifier *Simplifier;
104105
bool MinimizeSize;
@@ -113,7 +114,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner
113114
BuilderTy *Builder;
114115

115116
static char ID; // Pass identification, replacement for typeid
116-
InstCombiner() : FunctionPass(ID), DL(nullptr), Builder(nullptr) {
117+
InstCombiner()
118+
: FunctionPass(ID), DL(nullptr), DT(nullptr), Builder(nullptr) {
117119
MinimizeSize = false;
118120
initializeInstCombinerPass(*PassRegistry::getPassRegistry());
119121
}
@@ -242,6 +244,11 @@ class LLVM_LIBRARY_VISIBILITY InstCombiner
242244

243245
// visitInstruction - Specify what to return for unhandled instructions...
244246
Instruction *visitInstruction(Instruction &I) { return nullptr; }
247+
bool dominatesAllUses(const Instruction *DI, const Instruction *UI,
248+
const BasicBlock *DB) const;
249+
bool replacedSelectWithOperand(SelectInst *SI, const ICmpInst *Icmp,
250+
const ConstantInt *CI1,
251+
const ConstantInt *CI2);
245252

246253
private:
247254
bool ShouldChangeType(Type *From, Type *To) const;

lib/Transforms/InstCombine/InstCombineCompares.cpp

+138-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/IR/IntrinsicInst.h"
2222
#include "llvm/IR/PatternMatch.h"
2323
#include "llvm/Target/TargetLibraryInfo.h"
24+
2425
using namespace llvm;
2526
using namespace PatternMatch;
2627

@@ -2429,6 +2430,128 @@ static bool swapMayExposeCSEOpportunities(const Value * Op0,
24292430
return GlobalSwapBenefits > 0;
24302431
}
24312432

2433+
/// \brief Check that one use is in the same block as the definition and all
2434+
/// other uses are in blocks dominated by a given block
2435+
///
2436+
/// \param DI Definition
2437+
/// \param UI Use
2438+
/// \param DB Block that must dominate all uses of \p DI outside
2439+
/// the parent block
2440+
/// \return true when \p UI is the only use of \p DI in the parent block
2441+
/// and all other uses of \p DI are in blocks dominated by \p DB.
2442+
///
2443+
bool InstCombiner::dominatesAllUses(const Instruction *DI,
2444+
const Instruction *UI,
2445+
const BasicBlock *DB) const {
2446+
assert(DI && UI && "Instruction not defined\n");
2447+
if (DI->getParent() != UI->getParent())
2448+
return false;
2449+
// DominatorTree available?
2450+
if (!DT)
2451+
return false;
2452+
for (const User *U : DI->users()) {
2453+
auto *Usr = cast<Instruction>(U);
2454+
if (Usr != UI && !DT->dominates(DB, Usr->getParent()))
2455+
return false;
2456+
}
2457+
return true;
2458+
}
2459+
2460+
///
2461+
/// true when the instruction sequence within a block is select-cmp-br.
2462+
///
2463+
static bool isChainSelectCmpBranch(const SelectInst *SI) {
2464+
const BasicBlock *BB = SI->getParent();
2465+
if (!BB)
2466+
return false;
2467+
auto *BI = dyn_cast_or_null<BranchInst>(BB->getTerminator());
2468+
if (!BI || BI->getNumSuccessors() != 2)
2469+
return false;
2470+
auto *IC = dyn_cast<ICmpInst>(BI->getCondition());
2471+
if (!IC || (IC->getOperand(0) != SI && IC->getOperand(1) != SI))
2472+
return false;
2473+
return true;
2474+
}
2475+
2476+
///
2477+
/// \brief True when a select result is replaced by one of its operands
2478+
/// in select-icmp sequence. This will eventually result in the elimination
2479+
/// of the select.
2480+
///
2481+
/// \param SI Select instruction
2482+
/// \param Icmp Compare instruction
2483+
/// \param CI1 'true' when first select operand is equal to RHSC of Icmp
2484+
/// \param CI2 'true' when second select operand is equal to RHSC of Icmp
2485+
///
2486+
/// Notes:
2487+
/// - The replacement is global and requires dominator information
2488+
/// - The caller is responsible for the actual replacement
2489+
///
2490+
/// Example:
2491+
///
2492+
/// entry:
2493+
/// %4 = select i1 %3, %C* %0, %C* null
2494+
/// %5 = icmp eq %C* %4, null
2495+
/// br i1 %5, label %9, label %7
2496+
/// ...
2497+
/// ; <label>:7 ; preds = %entry
2498+
/// %8 = getelementptr inbounds %C* %4, i64 0, i32 0
2499+
/// ...
2500+
///
2501+
/// can be transformed to
2502+
///
2503+
/// %5 = icmp eq %C* %0, null
2504+
/// %6 = select i1 %3, i1 %5, i1 true
2505+
/// br i1 %6, label %9, label %7
2506+
/// ...
2507+
/// ; <label>:7 ; preds = %entry
2508+
/// %8 = getelementptr inbounds %C* %0, i64 0, i32 0 // replace by %0!
2509+
///
2510+
/// Similar when the first operand of the select is a constant or/and
2511+
/// the compare is for not equal rather than equal.
2512+
///
2513+
/// FIXME: Currently the function considers equal compares only. It should be
2514+
/// possbile to extend it to not equal compares also.
2515+
///
2516+
bool InstCombiner::replacedSelectWithOperand(SelectInst *SI,
2517+
const ICmpInst *Icmp,
2518+
const ConstantInt *CI1,
2519+
const ConstantInt *CI2) {
2520+
if (isChainSelectCmpBranch(SI) && Icmp->isEquality()) {
2521+
// Code sequence is select - icmp.[eq|ne] - br
2522+
unsigned ReplaceWithOpd = 0;
2523+
if (CI1 && !CI1->isZero())
2524+
// The first constant operand of the select and the RHS of
2525+
// the compare match, so try to substitute
2526+
// the select results with its second operand
2527+
// Example:
2528+
// %4 = select i1 %3, %C* null, %C* %0
2529+
// %5 = icmp eq %C* %4, null
2530+
// ==> could replace select with second operand
2531+
ReplaceWithOpd = 2;
2532+
else if (CI2 && !CI2->isZero())
2533+
// Similar when the second operand of the select is a constant
2534+
// Example:
2535+
// %4 = select i1 %3, %C* %0, %C* null
2536+
// %5 = icmp eq %C* %4, null
2537+
// ==> could replace select with first operand
2538+
ReplaceWithOpd = 1;
2539+
if (ReplaceWithOpd) {
2540+
// Replace select with operand on else path for EQ compares.
2541+
// Replace select with operand on then path for NE compares.
2542+
BasicBlock *Succ =
2543+
Icmp->getPredicate() == ICmpInst::ICMP_EQ
2544+
? SI->getParent()->getTerminator()->getSuccessor(1)
2545+
: SI->getParent()->getTerminator()->getSuccessor(0);
2546+
if (InstCombiner::dominatesAllUses(SI, Icmp, Succ)) {
2547+
SI->replaceAllUsesWith(SI->getOperand(ReplaceWithOpd));
2548+
return true;
2549+
}
2550+
}
2551+
}
2552+
return false;
2553+
}
2554+
24322555
Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
24332556
bool Changed = false;
24342557
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
@@ -2885,8 +3008,21 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
28853008
// fold to a constant (in which case the icmp is replaced with a select
28863009
// which will usually simplify) or this is the only user of the
28873010
// select (in which case we are trading a select+icmp for a simpler
2888-
// select+icmp).
2889-
if ((Op1 && Op2) || (LHSI->hasOneUse() && (Op1 || Op2))) {
3011+
// select+icmp) or all uses of the select can be replaced based on
3012+
// dominance information ("Global cases").
3013+
bool Transform = false;
3014+
if (Op1 && Op2)
3015+
Transform = true;
3016+
else if (Op1 || Op2) {
3017+
if (LHSI->hasOneUse())
3018+
Transform = true;
3019+
else
3020+
// Global cases
3021+
Transform = replacedSelectWithOperand(
3022+
cast<SelectInst>(LHSI), &I, dyn_cast_or_null<ConstantInt>(Op1),
3023+
dyn_cast_or_null<ConstantInt>(Op2));
3024+
}
3025+
if (Transform) {
28903026
if (!Op1)
28913027
Op1 = Builder->CreateICmp(I.getPredicate(), LHSI->getOperand(1),
28923028
RHSC, I.getName());

lib/Transforms/InstCombine/InstructionCombining.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,16 @@ INITIALIZE_PASS_BEGIN(InstCombiner, "instcombine",
9090
"Combine redundant instructions", false, false)
9191
INITIALIZE_PASS_DEPENDENCY(AssumptionTracker)
9292
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
93+
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
9394
INITIALIZE_PASS_END(InstCombiner, "instcombine",
9495
"Combine redundant instructions", false, false)
9596

9697
void InstCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
9798
AU.setPreservesCFG();
9899
AU.addRequired<AssumptionTracker>();
99100
AU.addRequired<TargetLibraryInfo>();
101+
AU.addRequired<DominatorTreeWrapperPass>();
102+
AU.addPreserved<DominatorTreeWrapperPass>();
100103
}
101104

102105

@@ -2933,12 +2936,9 @@ bool InstCombiner::runOnFunction(Function &F) {
29332936
AT = &getAnalysis<AssumptionTracker>();
29342937
DataLayoutPass *DLP = getAnalysisIfAvailable<DataLayoutPass>();
29352938
DL = DLP ? &DLP->getDataLayout() : nullptr;
2939+
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
29362940
TLI = &getAnalysis<TargetLibraryInfo>();
29372941

2938-
DominatorTreeWrapperPass *DTWP =
2939-
getAnalysisIfAvailable<DominatorTreeWrapperPass>();
2940-
DT = DTWP ? &DTWP->getDomTree() : nullptr;
2941-
29422942
// Minimizing size?
29432943
MinimizeSize = F.getAttributes().hasAttribute(AttributeSet::FunctionIndex,
29442944
Attribute::MinSize);

test/Transforms/InstCombine/pr12338.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
define void @entry() nounwind {
44
entry:
5+
; CHECK: br label %for.cond
56
br label %for.cond
67

78
for.cond:
89
%local = phi <1 x i32> [ <i32 0>, %entry ], [ %phi2, %cond.end47 ]
9-
; CHECK: sub <1 x i32> <i32 92>, %local
1010
%phi3 = sub <1 x i32> zeroinitializer, %local
1111
br label %cond.end
1212

0 commit comments

Comments
 (0)