Skip to content

Commit ca32190

Browse files
author
Jingyue Wu
committedMay 14, 2015
[ValueTracking] refactor: extract method haveNoCommonBitsSet
Summary: Extract method haveNoCommonBitsSet so that we don't have to duplicate this logic in InstCombine and SeparateConstOffsetFromGEP. This patch also makes SeparateConstOffsetFromGEP more precise by passing DominatorTree to computeKnownBits. Test Plan: value-tracking-domtree.ll that tests ValueTracking indeed leverages dominating conditions Reviewers: broune, meheff, majnemer Reviewed By: majnemer Subscribers: jholewinski, llvm-commits Differential Revision: http://reviews.llvm.org/D9734 llvm-svn: 237407
1 parent e9bcddd commit ca32190

File tree

5 files changed

+100
-71
lines changed

5 files changed

+100
-71
lines changed
 

‎llvm/include/llvm/Analysis/ValueTracking.h

+5
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ namespace llvm {
4747
/// \p KnownZero the set of bits that are known to be zero
4848
void computeKnownBitsFromRangeMetadata(const MDNode &Ranges,
4949
APInt &KnownZero);
50+
/// Returns true if LHS and RHS have no common bits set.
51+
bool haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL,
52+
AssumptionCache *AC = nullptr,
53+
const Instruction *CxtI = nullptr,
54+
const DominatorTree *DT = nullptr);
5055

5156
/// ComputeSignBit - Determine whether the sign bit is known to be zero or
5257
/// one. Convenience wrapper around computeKnownBits.

‎llvm/lib/Analysis/ValueTracking.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,21 @@ void llvm::computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne,
138138
Query(AC, safeCxtI(V, CxtI), DT));
139139
}
140140

141+
bool llvm::haveNoCommonBitsSet(Value *LHS, Value *RHS, const DataLayout &DL,
142+
AssumptionCache *AC, const Instruction *CxtI,
143+
const DominatorTree *DT) {
144+
assert(LHS->getType() == RHS->getType() &&
145+
"LHS and RHS should have the same type");
146+
assert(LHS->getType()->isIntOrIntVectorTy() &&
147+
"LHS and RHS should be integers");
148+
IntegerType *IT = cast<IntegerType>(LHS->getType()->getScalarType());
149+
APInt LHSKnownZero(IT->getBitWidth(), 0), LHSKnownOne(IT->getBitWidth(), 0);
150+
APInt RHSKnownZero(IT->getBitWidth(), 0), RHSKnownOne(IT->getBitWidth(), 0);
151+
computeKnownBits(LHS, LHSKnownZero, LHSKnownOne, DL, 0, AC, CxtI, DT);
152+
computeKnownBits(RHS, RHSKnownZero, RHSKnownOne, DL, 0, AC, CxtI, DT);
153+
return (LHSKnownZero | RHSKnownZero).isAllOnesValue();
154+
}
155+
141156
static void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne,
142157
const DataLayout &DL, unsigned Depth,
143158
const Query &Q);

‎llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

+2-14
Original file line numberDiff line numberDiff line change
@@ -1160,20 +1160,8 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
11601160
return ReplaceInstUsesWith(I, V);
11611161

11621162
// A+B --> A|B iff A and B have no bits set in common.
1163-
if (IntegerType *IT = dyn_cast<IntegerType>(I.getType())) {
1164-
APInt LHSKnownOne(IT->getBitWidth(), 0);
1165-
APInt LHSKnownZero(IT->getBitWidth(), 0);
1166-
computeKnownBits(LHS, LHSKnownZero, LHSKnownOne, 0, &I);
1167-
if (LHSKnownZero != 0) {
1168-
APInt RHSKnownOne(IT->getBitWidth(), 0);
1169-
APInt RHSKnownZero(IT->getBitWidth(), 0);
1170-
computeKnownBits(RHS, RHSKnownZero, RHSKnownOne, 0, &I);
1171-
1172-
// No bits in common -> bitwise or.
1173-
if ((LHSKnownZero|RHSKnownZero).isAllOnesValue())
1174-
return BinaryOperator::CreateOr(LHS, RHS);
1175-
}
1176-
}
1163+
if (haveNoCommonBitsSet(LHS, RHS, DL, AC, &I, DT))
1164+
return BinaryOperator::CreateOr(LHS, RHS);
11771165

11781166
if (Constant *CRHS = dyn_cast<Constant>(RHS)) {
11791167
Value *X;

‎llvm/lib/Transforms/Scalar/SeparateConstOffsetFromGEP.cpp

+45-57
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
#include "llvm/Analysis/ValueTracking.h"
161161
#include "llvm/IR/Constants.h"
162162
#include "llvm/IR/DataLayout.h"
163+
#include "llvm/IR/Dominators.h"
163164
#include "llvm/IR/Instructions.h"
164165
#include "llvm/IR/LLVMContext.h"
165166
#include "llvm/IR/Module.h"
@@ -202,23 +203,26 @@ namespace {
202203
/// 5); nor can we transform (3 * (a + 5)) to (3 * a + 5), however in this case,
203204
/// -instcombine probably already optimized (3 * (a + 5)) to (3 * a + 15).
204205
class ConstantOffsetExtractor {
205-
public:
206+
public:
206207
/// Extracts a constant offset from the given GEP index. It returns the
207208
/// new index representing the remainder (equal to the original index minus
208209
/// the constant offset), or nullptr if we cannot extract a constant offset.
209210
/// \p Idx The given GEP index
210211
/// \p GEP The given GEP
211212
/// \p UserChainTail Outputs the tail of UserChain so that we can
212213
/// garbage-collect unused instructions in UserChain.
213-
static Value *Extract(Value *Idx, GetElementPtrInst *GEP,
214-
User *&UserChainTail);
214+
static Value *Extract(Value *Idx, GetElementPtrInst *GEP,
215+
User *&UserChainTail, const DominatorTree *DT);
215216
/// Looks for a constant offset from the given GEP index without extracting
216217
/// it. It returns the numeric value of the extracted constant offset (0 if
217218
/// failed). The meaning of the arguments are the same as Extract.
218-
static int64_t Find(Value *Idx, GetElementPtrInst *GEP);
219+
static int64_t Find(Value *Idx, GetElementPtrInst *GEP,
220+
const DominatorTree *DT);
219221

220-
private:
221-
ConstantOffsetExtractor(Instruction *InsertionPt) : IP(InsertionPt) {}
222+
private:
223+
ConstantOffsetExtractor(Instruction *InsertionPt, const DominatorTree *DT)
224+
: IP(InsertionPt), DL(InsertionPt->getModule()->getDataLayout()), DT(DT) {
225+
}
222226
/// Searches the expression that computes V for a non-zero constant C s.t.
223227
/// V can be reassociated into the form V' + C. If the searching is
224228
/// successful, returns C and update UserChain as a def-use chain from C to V;
@@ -276,13 +280,6 @@ class ConstantOffsetExtractor {
276280
/// returns "sext i32 (zext i16 V to i32) to i64".
277281
Value *applyExts(Value *V);
278282

279-
/// Returns true if LHS and RHS have no bits in common, i.e., for every n
280-
/// the n-th bit of either LHS, or RHS is 0.
281-
bool NoCommonBits(Value *LHS, Value *RHS) const;
282-
/// Computes which bits are known to be one or zero.
283-
/// \p KnownOne Mask of all bits that are known to be one.
284-
/// \p KnownZero Mask of all bits that are known to be zero.
285-
void ComputeKnownBits(Value *V, APInt &KnownOne, APInt &KnownZero) const;
286283
/// A helper function that returns whether we can trace into the operands
287284
/// of binary operator BO for a constant offset.
288285
///
@@ -304,28 +301,35 @@ class ConstantOffsetExtractor {
304301
/// sext/zext instructions along UserChain.
305302
SmallVector<CastInst *, 16> ExtInsts;
306303
Instruction *IP; /// Insertion position of cloned instructions.
304+
const DataLayout &DL;
305+
const DominatorTree *DT;
307306
};
308307

309308
/// \brief A pass that tries to split every GEP in the function into a variadic
310309
/// base and a constant offset. It is a FunctionPass because searching for the
311310
/// constant offset may inspect other basic blocks.
312311
class SeparateConstOffsetFromGEP : public FunctionPass {
313-
public:
312+
public:
314313
static char ID;
315314
SeparateConstOffsetFromGEP(const TargetMachine *TM = nullptr,
316315
bool LowerGEP = false)
317-
: FunctionPass(ID), TM(TM), LowerGEP(LowerGEP) {
316+
: FunctionPass(ID), DL(nullptr), DT(nullptr), TM(TM), LowerGEP(LowerGEP) {
318317
initializeSeparateConstOffsetFromGEPPass(*PassRegistry::getPassRegistry());
319318
}
320319

321320
void getAnalysisUsage(AnalysisUsage &AU) const override {
321+
AU.addRequired<DominatorTreeWrapperPass>();
322322
AU.addRequired<TargetTransformInfoWrapperPass>();
323323
AU.setPreservesCFG();
324324
}
325325

326+
bool doInitialization(Module &M) override {
327+
DL = &M.getDataLayout();
328+
return false;
329+
}
326330
bool runOnFunction(Function &F) override;
327331

328-
private:
332+
private:
329333
/// Tries to split the given GEP into a variadic base and a constant offset,
330334
/// and returns true if the splitting succeeds.
331335
bool splitGEP(GetElementPtrInst *GEP);
@@ -372,6 +376,8 @@ class SeparateConstOffsetFromGEP : public FunctionPass {
372376
/// Verify F is free of dead code.
373377
void verifyNoDeadCode(Function &F);
374378

379+
const DataLayout *DL;
380+
const DominatorTree *DT;
375381
const TargetMachine *TM;
376382
/// Whether to lower a GEP with multiple indices into arithmetic operations or
377383
/// multiple GEPs with a single index.
@@ -384,6 +390,7 @@ INITIALIZE_PASS_BEGIN(
384390
SeparateConstOffsetFromGEP, "separate-const-offset-from-gep",
385391
"Split GEPs to a variadic base and a constant offset for better CSE", false,
386392
false)
393+
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
387394
INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
388395
INITIALIZE_PASS_END(
389396
SeparateConstOffsetFromGEP, "separate-const-offset-from-gep",
@@ -412,7 +419,8 @@ bool ConstantOffsetExtractor::CanTraceInto(bool SignExtended,
412419
Value *LHS = BO->getOperand(0), *RHS = BO->getOperand(1);
413420
// Do not trace into "or" unless it is equivalent to "add". If LHS and RHS
414421
// don't have common bits, (LHS | RHS) is equivalent to (LHS + RHS).
415-
if (BO->getOpcode() == Instruction::Or && !NoCommonBits(LHS, RHS))
422+
if (BO->getOpcode() == Instruction::Or &&
423+
!haveNoCommonBitsSet(LHS, RHS, DL, nullptr, BO, DT))
416424
return false;
417425

418426
// In addition, tracing into BO requires that its surrounding s/zext (if
@@ -497,9 +505,8 @@ APInt ConstantOffsetExtractor::find(Value *V, bool SignExtended,
497505
ConstantOffset = CI->getValue();
498506
} else if (BinaryOperator *BO = dyn_cast<BinaryOperator>(V)) {
499507
// Trace into subexpressions for more hoisting opportunities.
500-
if (CanTraceInto(SignExtended, ZeroExtended, BO, NonNegative)) {
508+
if (CanTraceInto(SignExtended, ZeroExtended, BO, NonNegative))
501509
ConstantOffset = findInEitherOperand(BO, SignExtended, ZeroExtended);
502-
}
503510
} else if (isa<SExtInst>(V)) {
504511
ConstantOffset = find(U->getOperand(0), /* SignExtended */ true,
505512
ZeroExtended, NonNegative).sext(BitWidth);
@@ -642,8 +649,9 @@ Value *ConstantOffsetExtractor::removeConstOffset(unsigned ChainIndex) {
642649
}
643650

644651
Value *ConstantOffsetExtractor::Extract(Value *Idx, GetElementPtrInst *GEP,
645-
User *&UserChainTail) {
646-
ConstantOffsetExtractor Extractor(GEP);
652+
User *&UserChainTail,
653+
const DominatorTree *DT) {
654+
ConstantOffsetExtractor Extractor(GEP, DT);
647655
// Find a non-zero constant offset first.
648656
APInt ConstantOffset =
649657
Extractor.find(Idx, /* SignExtended */ false, /* ZeroExtended */ false,
@@ -658,37 +666,19 @@ Value *ConstantOffsetExtractor::Extract(Value *Idx, GetElementPtrInst *GEP,
658666
return IdxWithoutConstOffset;
659667
}
660668

661-
int64_t ConstantOffsetExtractor::Find(Value *Idx, GetElementPtrInst *GEP) {
669+
int64_t ConstantOffsetExtractor::Find(Value *Idx, GetElementPtrInst *GEP,
670+
const DominatorTree *DT) {
662671
// If Idx is an index of an inbound GEP, Idx is guaranteed to be non-negative.
663-
return ConstantOffsetExtractor(GEP)
672+
return ConstantOffsetExtractor(GEP, DT)
664673
.find(Idx, /* SignExtended */ false, /* ZeroExtended */ false,
665674
GEP->isInBounds())
666675
.getSExtValue();
667676
}
668677

669-
void ConstantOffsetExtractor::ComputeKnownBits(Value *V, APInt &KnownOne,
670-
APInt &KnownZero) const {
671-
IntegerType *IT = cast<IntegerType>(V->getType());
672-
KnownOne = APInt(IT->getBitWidth(), 0);
673-
KnownZero = APInt(IT->getBitWidth(), 0);
674-
const DataLayout &DL = IP->getModule()->getDataLayout();
675-
llvm::computeKnownBits(V, KnownZero, KnownOne, DL, 0);
676-
}
677-
678-
bool ConstantOffsetExtractor::NoCommonBits(Value *LHS, Value *RHS) const {
679-
assert(LHS->getType() == RHS->getType() &&
680-
"LHS and RHS should have the same type");
681-
APInt LHSKnownOne, LHSKnownZero, RHSKnownOne, RHSKnownZero;
682-
ComputeKnownBits(LHS, LHSKnownOne, LHSKnownZero);
683-
ComputeKnownBits(RHS, RHSKnownOne, RHSKnownZero);
684-
return (LHSKnownZero | RHSKnownZero).isAllOnesValue();
685-
}
686-
687678
bool SeparateConstOffsetFromGEP::canonicalizeArrayIndicesToPointerSize(
688679
GetElementPtrInst *GEP) {
689680
bool Changed = false;
690-
const DataLayout &DL = GEP->getModule()->getDataLayout();
691-
Type *IntPtrTy = DL.getIntPtrType(GEP->getType());
681+
Type *IntPtrTy = DL->getIntPtrType(GEP->getType());
692682
gep_type_iterator GTI = gep_type_begin(*GEP);
693683
for (User::op_iterator I = GEP->op_begin() + 1, E = GEP->op_end();
694684
I != E; ++I, ++GTI) {
@@ -709,19 +699,18 @@ SeparateConstOffsetFromGEP::accumulateByteOffset(GetElementPtrInst *GEP,
709699
NeedsExtraction = false;
710700
int64_t AccumulativeByteOffset = 0;
711701
gep_type_iterator GTI = gep_type_begin(*GEP);
712-
const DataLayout &DL = GEP->getModule()->getDataLayout();
713702
for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I, ++GTI) {
714703
if (isa<SequentialType>(*GTI)) {
715704
// Tries to extract a constant offset from this GEP index.
716705
int64_t ConstantOffset =
717-
ConstantOffsetExtractor::Find(GEP->getOperand(I), GEP);
706+
ConstantOffsetExtractor::Find(GEP->getOperand(I), GEP, DT);
718707
if (ConstantOffset != 0) {
719708
NeedsExtraction = true;
720709
// A GEP may have multiple indices. We accumulate the extracted
721710
// constant offset to a byte offset, and later offset the remainder of
722711
// the original GEP with this byte offset.
723712
AccumulativeByteOffset +=
724-
ConstantOffset * DL.getTypeAllocSize(GTI.getIndexedType());
713+
ConstantOffset * DL->getTypeAllocSize(GTI.getIndexedType());
725714
}
726715
} else if (LowerGEP) {
727716
StructType *StTy = cast<StructType>(*GTI);
@@ -730,7 +719,7 @@ SeparateConstOffsetFromGEP::accumulateByteOffset(GetElementPtrInst *GEP,
730719
if (Field != 0) {
731720
NeedsExtraction = true;
732721
AccumulativeByteOffset +=
733-
DL.getStructLayout(StTy)->getElementOffset(Field);
722+
DL->getStructLayout(StTy)->getElementOffset(Field);
734723
}
735724
}
736725
}
@@ -740,8 +729,7 @@ SeparateConstOffsetFromGEP::accumulateByteOffset(GetElementPtrInst *GEP,
740729
void SeparateConstOffsetFromGEP::lowerToSingleIndexGEPs(
741730
GetElementPtrInst *Variadic, int64_t AccumulativeByteOffset) {
742731
IRBuilder<> Builder(Variadic);
743-
const DataLayout &DL = Variadic->getModule()->getDataLayout();
744-
Type *IntPtrTy = DL.getIntPtrType(Variadic->getType());
732+
Type *IntPtrTy = DL->getIntPtrType(Variadic->getType());
745733

746734
Type *I8PtrTy =
747735
Builder.getInt8PtrTy(Variadic->getType()->getPointerAddressSpace());
@@ -761,7 +749,7 @@ void SeparateConstOffsetFromGEP::lowerToSingleIndexGEPs(
761749
continue;
762750

763751
APInt ElementSize = APInt(IntPtrTy->getIntegerBitWidth(),
764-
DL.getTypeAllocSize(GTI.getIndexedType()));
752+
DL->getTypeAllocSize(GTI.getIndexedType()));
765753
// Scale the index by element size.
766754
if (ElementSize != 1) {
767755
if (ElementSize.isPowerOf2()) {
@@ -794,8 +782,7 @@ void
794782
SeparateConstOffsetFromGEP::lowerToArithmetics(GetElementPtrInst *Variadic,
795783
int64_t AccumulativeByteOffset) {
796784
IRBuilder<> Builder(Variadic);
797-
const DataLayout &DL = Variadic->getModule()->getDataLayout();
798-
Type *IntPtrTy = DL.getIntPtrType(Variadic->getType());
785+
Type *IntPtrTy = DL->getIntPtrType(Variadic->getType());
799786

800787
Value *ResultPtr = Builder.CreatePtrToInt(Variadic->getOperand(0), IntPtrTy);
801788
gep_type_iterator GTI = gep_type_begin(*Variadic);
@@ -811,7 +798,7 @@ SeparateConstOffsetFromGEP::lowerToArithmetics(GetElementPtrInst *Variadic,
811798
continue;
812799

813800
APInt ElementSize = APInt(IntPtrTy->getIntegerBitWidth(),
814-
DL.getTypeAllocSize(GTI.getIndexedType()));
801+
DL->getTypeAllocSize(GTI.getIndexedType()));
815802
// Scale the index by element size.
816803
if (ElementSize != 1) {
817804
if (ElementSize.isPowerOf2()) {
@@ -887,7 +874,7 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
887874
Value *OldIdx = GEP->getOperand(I);
888875
User *UserChainTail;
889876
Value *NewIdx =
890-
ConstantOffsetExtractor::Extract(OldIdx, GEP, UserChainTail);
877+
ConstantOffsetExtractor::Extract(OldIdx, GEP, UserChainTail, DT);
891878
if (NewIdx != nullptr) {
892879
// Switches to the index with the constant offset removed.
893880
GEP->setOperand(I, NewIdx);
@@ -969,10 +956,9 @@ bool SeparateConstOffsetFromGEP::splitGEP(GetElementPtrInst *GEP) {
969956
// Per ANSI C standard, signed / unsigned = unsigned and signed % unsigned =
970957
// unsigned.. Therefore, we cast ElementTypeSizeOfGEP to signed because it is
971958
// used with unsigned integers later.
972-
const DataLayout &DL = GEP->getModule()->getDataLayout();
973959
int64_t ElementTypeSizeOfGEP = static_cast<int64_t>(
974-
DL.getTypeAllocSize(GEP->getType()->getElementType()));
975-
Type *IntPtrTy = DL.getIntPtrType(GEP->getType());
960+
DL->getTypeAllocSize(GEP->getType()->getElementType()));
961+
Type *IntPtrTy = DL->getIntPtrType(GEP->getType());
976962
if (AccumulativeByteOffset % ElementTypeSizeOfGEP == 0) {
977963
// Very likely. As long as %gep is natually aligned, the byte offset we
978964
// extracted should be a multiple of sizeof(*%gep).
@@ -1019,6 +1005,8 @@ bool SeparateConstOffsetFromGEP::runOnFunction(Function &F) {
10191005
if (DisableSeparateConstOffsetFromGEP)
10201006
return false;
10211007

1008+
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1009+
10221010
bool Changed = false;
10231011
for (Function::iterator B = F.begin(), BE = F.end(); B != BE; ++B) {
10241012
for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
; RUN: opt < %s -separate-const-offset-from-gep -value-tracking-dom-conditions -reassociate-geps-verify-no-dead-code -S | FileCheck %s
2+
3+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4+
target triple = "nvptx64-unknown-unknown"
5+
6+
; if (i == 4)
7+
; p = &input[i | 3];
8+
;
9+
; =>
10+
;
11+
; if (i == 4) {
12+
; base = &input[i];
13+
; p = &base[3];
14+
; }
15+
;
16+
; We should treat (i | 3) as (i + 3) because i is guaranteed to be 4, which
17+
; does not share any set bits with 3.
18+
define float* @guarded_or(float* %input, i64 %i) {
19+
; CHECK-LABEL: @guarded_or(
20+
entry:
21+
%is4 = icmp eq i64 %i, 4
22+
br i1 %is4, label %then, label %exit
23+
24+
then:
25+
%or = or i64 %i, 3
26+
%p = getelementptr inbounds float, float* %input, i64 %or
27+
; CHECK: [[base:[^ ]+]] = getelementptr float, float* %input, i64 %i
28+
; CHECK: getelementptr float, float* [[base]], i64 3
29+
ret float* %p
30+
31+
exit:
32+
ret float* null
33+
}

0 commit comments

Comments
 (0)
Please sign in to comment.